@khanacademy/wonder-blocks-data 14.1.2 → 14.1.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +16 -0
- package/dist/es/index.js +62 -832
- package/dist/index.js +53 -826
- package/package.json +4 -5
package/dist/index.js
CHANGED
|
@@ -4,10 +4,8 @@ Object.defineProperty(exports, '__esModule', { value: true });
|
|
|
4
4
|
|
|
5
5
|
var wonderBlocksCore = require('@khanacademy/wonder-blocks-core');
|
|
6
6
|
var wonderStuffCore = require('@khanacademy/wonder-stuff-core');
|
|
7
|
-
var _extends = require('@babel/runtime/helpers/extends');
|
|
8
7
|
var React = require('react');
|
|
9
|
-
|
|
10
|
-
function _interopDefaultLegacy (e) { return e && typeof e === 'object' && 'default' in e ? e : { 'default': e }; }
|
|
8
|
+
var jsxRuntime = require('react/jsx-runtime');
|
|
11
9
|
|
|
12
10
|
function _interopNamespace(e) {
|
|
13
11
|
if (e && e.__esModule) return e;
|
|
@@ -27,840 +25,69 @@ function _interopNamespace(e) {
|
|
|
27
25
|
return Object.freeze(n);
|
|
28
26
|
}
|
|
29
27
|
|
|
30
|
-
var _extends__default = /*#__PURE__*/_interopDefaultLegacy(_extends);
|
|
31
28
|
var React__namespace = /*#__PURE__*/_interopNamespace(React);
|
|
32
29
|
|
|
33
|
-
|
|
34
|
-
FetchPolicy["CacheBeforeNetwork"] = "CacheBeforeNetwork";
|
|
35
|
-
FetchPolicy["CacheAndNetwork"] = "CacheAndNetwork";
|
|
36
|
-
FetchPolicy["CacheOnly"] = "CacheOnly";
|
|
37
|
-
FetchPolicy["NetworkOnly"] = "NetworkOnly";
|
|
38
|
-
return FetchPolicy;
|
|
39
|
-
}({});
|
|
40
|
-
|
|
41
|
-
const DataErrors = Object.freeze({
|
|
42
|
-
Unknown: "Unknown",
|
|
43
|
-
Internal: "Internal",
|
|
44
|
-
InvalidInput: "InvalidInput",
|
|
45
|
-
Network: "Network",
|
|
46
|
-
NotAllowed: "NotAllowed",
|
|
47
|
-
Parse: "Parse",
|
|
48
|
-
Hydrated: "Hydrated"
|
|
49
|
-
});
|
|
50
|
-
class DataError extends wonderStuffCore.KindError {
|
|
51
|
-
constructor(message, kind, {
|
|
52
|
-
metadata,
|
|
53
|
-
cause
|
|
54
|
-
} = {}) {
|
|
55
|
-
super(message, kind, {
|
|
56
|
-
metadata,
|
|
57
|
-
cause,
|
|
58
|
-
name: "Data"
|
|
59
|
-
});
|
|
60
|
-
}
|
|
61
|
-
}
|
|
30
|
+
var FetchPolicy=/*#__PURE__*/function(FetchPolicy){FetchPolicy["CacheBeforeNetwork"]="CacheBeforeNetwork";FetchPolicy["CacheAndNetwork"]="CacheAndNetwork";FetchPolicy["CacheOnly"]="CacheOnly";FetchPolicy["NetworkOnly"]="NetworkOnly";return FetchPolicy}({});
|
|
62
31
|
|
|
63
|
-
class
|
|
64
|
-
constructor(initialCache = {}) {
|
|
65
|
-
this._cache = void 0;
|
|
66
|
-
this._cache = initialCache;
|
|
67
|
-
}
|
|
68
|
-
get inUse() {
|
|
69
|
-
return Object.keys(this._cache).length > 0;
|
|
70
|
-
}
|
|
71
|
-
set(scope, id, value) {
|
|
72
|
-
var _this$_cache$scope;
|
|
73
|
-
if (!id || typeof id !== "string") {
|
|
74
|
-
throw new DataError("id must be non-empty string", DataErrors.InvalidInput);
|
|
75
|
-
}
|
|
76
|
-
if (!scope || typeof scope !== "string") {
|
|
77
|
-
throw new DataError("scope must be non-empty string", DataErrors.InvalidInput);
|
|
78
|
-
}
|
|
79
|
-
if (typeof value === "function") {
|
|
80
|
-
throw new DataError("value must be a non-function value", DataErrors.InvalidInput);
|
|
81
|
-
}
|
|
82
|
-
this._cache[scope] = (_this$_cache$scope = this._cache[scope]) != null ? _this$_cache$scope : {};
|
|
83
|
-
this._cache[scope][id] = value;
|
|
84
|
-
}
|
|
85
|
-
get(scope, id) {
|
|
86
|
-
var _this$_cache$scope$id, _this$_cache$scope2;
|
|
87
|
-
return (_this$_cache$scope$id = (_this$_cache$scope2 = this._cache[scope]) == null ? void 0 : _this$_cache$scope2[id]) != null ? _this$_cache$scope$id : null;
|
|
88
|
-
}
|
|
89
|
-
purge(scope, id) {
|
|
90
|
-
var _this$_cache$scope3;
|
|
91
|
-
if (!((_this$_cache$scope3 = this._cache[scope]) != null && _this$_cache$scope3[id])) {
|
|
92
|
-
return;
|
|
93
|
-
}
|
|
94
|
-
delete this._cache[scope][id];
|
|
95
|
-
if (Object.keys(this._cache[scope]).length === 0) {
|
|
96
|
-
delete this._cache[scope];
|
|
97
|
-
}
|
|
98
|
-
}
|
|
99
|
-
purgeScope(scope, predicate) {
|
|
100
|
-
if (!this._cache[scope]) {
|
|
101
|
-
return;
|
|
102
|
-
}
|
|
103
|
-
if (predicate == null) {
|
|
104
|
-
delete this._cache[scope];
|
|
105
|
-
return;
|
|
106
|
-
}
|
|
107
|
-
for (const key of Object.keys(this._cache[scope])) {
|
|
108
|
-
if (predicate(key, this._cache[scope][key])) {
|
|
109
|
-
delete this._cache[scope][key];
|
|
110
|
-
}
|
|
111
|
-
}
|
|
112
|
-
if (Object.keys(this._cache[scope]).length === 0) {
|
|
113
|
-
delete this._cache[scope];
|
|
114
|
-
}
|
|
115
|
-
}
|
|
116
|
-
purgeAll(predicate) {
|
|
117
|
-
if (predicate == null) {
|
|
118
|
-
this._cache = {};
|
|
119
|
-
return;
|
|
120
|
-
}
|
|
121
|
-
for (const scope of Object.keys(this._cache)) {
|
|
122
|
-
this.purgeScope(scope, (id, value) => predicate(scope, id, value));
|
|
123
|
-
}
|
|
124
|
-
}
|
|
125
|
-
}
|
|
32
|
+
const DataErrors=Object.freeze({Unknown:"Unknown",Internal:"Internal",InvalidInput:"InvalidInput",Network:"Network",NotAllowed:"NotAllowed",Parse:"Parse",Hydrated:"Hydrated"});class DataError extends wonderStuffCore.KindError{constructor(message,kind,{metadata,cause}={}){super(message,kind,{metadata,cause,name:"Data"});}}
|
|
126
33
|
|
|
127
|
-
class
|
|
128
|
-
constructor(initialCache = {}) {
|
|
129
|
-
try {
|
|
130
|
-
super(wonderStuffCore.clone(initialCache));
|
|
131
|
-
} catch (e) {
|
|
132
|
-
throw new DataError(`An error occurred trying to initialize from a response cache snapshot: ${e}`, DataErrors.InvalidInput);
|
|
133
|
-
}
|
|
134
|
-
}
|
|
135
|
-
set(scope, id, value) {
|
|
136
|
-
super.set(scope, id, Object.freeze(wonderStuffCore.clone(value)));
|
|
137
|
-
}
|
|
138
|
-
clone() {
|
|
139
|
-
try {
|
|
140
|
-
return wonderStuffCore.clone(this._cache);
|
|
141
|
-
} catch (e) {
|
|
142
|
-
throw new DataError("An error occurred while trying to clone the cache", DataErrors.Internal, {
|
|
143
|
-
cause: e
|
|
144
|
-
});
|
|
145
|
-
}
|
|
146
|
-
}
|
|
147
|
-
}
|
|
34
|
+
class ScopedInMemoryCache{get inUse(){return Object.keys(this._cache).length>0}set(scope,id,value){if(!id||typeof id!=="string"){throw new DataError("id must be non-empty string",DataErrors.InvalidInput)}if(!scope||typeof scope!=="string"){throw new DataError("scope must be non-empty string",DataErrors.InvalidInput)}if(typeof value==="function"){throw new DataError("value must be a non-function value",DataErrors.InvalidInput)}this._cache[scope]=this._cache[scope]??{};this._cache[scope][id]=value;}get(scope,id){return this._cache[scope]?.[id]??null}purge(scope,id){if(!this._cache[scope]?.[id]){return}delete this._cache[scope][id];if(Object.keys(this._cache[scope]).length===0){delete this._cache[scope];}}purgeScope(scope,predicate){if(!this._cache[scope]){return}if(predicate==null){delete this._cache[scope];return}for(const key of Object.keys(this._cache[scope])){if(predicate(key,this._cache[scope][key])){delete this._cache[scope][key];}}if(Object.keys(this._cache[scope]).length===0){delete this._cache[scope];}}purgeAll(predicate){if(predicate==null){this._cache={};return}for(const scope of Object.keys(this._cache)){this.purgeScope(scope,(id,value)=>predicate(scope,id,value));}}constructor(initialCache={}){this._cache=initialCache;}}
|
|
148
35
|
|
|
149
|
-
|
|
150
|
-
let _default$2;
|
|
151
|
-
class SsrCache {
|
|
152
|
-
static get Default() {
|
|
153
|
-
if (!_default$2) {
|
|
154
|
-
_default$2 = new SsrCache();
|
|
155
|
-
}
|
|
156
|
-
return _default$2;
|
|
157
|
-
}
|
|
158
|
-
constructor(hydrationCache = null, ssrOnlyCache = null) {
|
|
159
|
-
this._hydrationCache = void 0;
|
|
160
|
-
this._ssrOnlyCache = void 0;
|
|
161
|
-
this.initialize = source => {
|
|
162
|
-
if (this._hydrationCache.inUse) {
|
|
163
|
-
throw new Error("Cannot initialize data response cache more than once");
|
|
164
|
-
}
|
|
165
|
-
this._hydrationCache = new SerializableInMemoryCache({
|
|
166
|
-
[DefaultScope$2]: source
|
|
167
|
-
});
|
|
168
|
-
};
|
|
169
|
-
this.cacheData = (id, data, hydrate) => this._setCachedResponse(id, {
|
|
170
|
-
data
|
|
171
|
-
}, hydrate);
|
|
172
|
-
this.cacheError = (id, error, hydrate) => {
|
|
173
|
-
const errorMessage = typeof error === "string" ? error : error.message;
|
|
174
|
-
return this._setCachedResponse(id, {
|
|
175
|
-
error: errorMessage
|
|
176
|
-
}, hydrate);
|
|
177
|
-
};
|
|
178
|
-
this.getEntry = id => {
|
|
179
|
-
const ssrEntry = wonderBlocksCore.Server.isServerSide() ? this._ssrOnlyCache.get(DefaultScope$2, id) : null;
|
|
180
|
-
const internalEntry = ssrEntry != null ? ssrEntry : this._hydrationCache.get(DefaultScope$2, id);
|
|
181
|
-
if (!wonderBlocksCore.Server.isServerSide() && internalEntry != null) {
|
|
182
|
-
this._hydrationCache.purge(DefaultScope$2, id);
|
|
183
|
-
}
|
|
184
|
-
return internalEntry;
|
|
185
|
-
};
|
|
186
|
-
this.purgeData = predicate => {
|
|
187
|
-
const realPredicate = predicate ? (_, key, cachedEntry) => predicate(key, cachedEntry) : undefined;
|
|
188
|
-
this._hydrationCache.purgeAll(realPredicate);
|
|
189
|
-
this._ssrOnlyCache.purgeAll(realPredicate);
|
|
190
|
-
};
|
|
191
|
-
this.cloneHydratableData = () => {
|
|
192
|
-
var _ref;
|
|
193
|
-
const cache = this._hydrationCache.clone();
|
|
194
|
-
return (_ref = cache[DefaultScope$2]) != null ? _ref : {};
|
|
195
|
-
};
|
|
196
|
-
this._ssrOnlyCache = ssrOnlyCache || new SerializableInMemoryCache();
|
|
197
|
-
this._hydrationCache = hydrationCache || new SerializableInMemoryCache();
|
|
198
|
-
}
|
|
199
|
-
_setCachedResponse(id, entry, hydrate) {
|
|
200
|
-
const frozenEntry = Object.freeze(entry);
|
|
201
|
-
if (wonderBlocksCore.Server.isServerSide()) {
|
|
202
|
-
if (hydrate) {
|
|
203
|
-
this._hydrationCache.set(DefaultScope$2, id, frozenEntry);
|
|
204
|
-
} else {
|
|
205
|
-
this._ssrOnlyCache.set(DefaultScope$2, id, frozenEntry);
|
|
206
|
-
}
|
|
207
|
-
}
|
|
208
|
-
return frozenEntry;
|
|
209
|
-
}
|
|
210
|
-
}
|
|
36
|
+
class SerializableInMemoryCache extends ScopedInMemoryCache{set(scope,id,value){super.set(scope,id,Object.freeze(wonderStuffCore.clone(value)));}clone(){try{return wonderStuffCore.clone(this._cache)}catch(e){throw new DataError("An error occurred while trying to clone the cache",DataErrors.Internal,{cause:e})}}constructor(initialCache={}){try{super(wonderStuffCore.clone(initialCache));}catch(e){throw new DataError(`An error occurred trying to initialize from a response cache snapshot: ${e}`,DataErrors.InvalidInput)}}}
|
|
211
37
|
|
|
212
|
-
const
|
|
213
|
-
const purgeHydrationCache = predicate => SsrCache.Default.purgeData(predicate);
|
|
214
|
-
|
|
215
|
-
let _default$1;
|
|
216
|
-
class RequestFulfillment {
|
|
217
|
-
constructor() {
|
|
218
|
-
this._requests = {};
|
|
219
|
-
this.fulfill = (id, {
|
|
220
|
-
handler,
|
|
221
|
-
hydrate: _hydrate = true
|
|
222
|
-
}) => {
|
|
223
|
-
const inflight = this._requests[id];
|
|
224
|
-
if (inflight) {
|
|
225
|
-
return inflight;
|
|
226
|
-
}
|
|
227
|
-
const request = handler().then(data => ({
|
|
228
|
-
status: "success",
|
|
229
|
-
data
|
|
230
|
-
})).catch(error => {
|
|
231
|
-
const actualError = typeof error === "string" ? new DataError("Request failed", DataErrors.Unknown, {
|
|
232
|
-
metadata: {
|
|
233
|
-
unexpectedError: error
|
|
234
|
-
}
|
|
235
|
-
}) : error;
|
|
236
|
-
if (actualError.name === "AbortError") {
|
|
237
|
-
return {
|
|
238
|
-
status: "aborted"
|
|
239
|
-
};
|
|
240
|
-
}
|
|
241
|
-
return {
|
|
242
|
-
status: "error",
|
|
243
|
-
error: actualError
|
|
244
|
-
};
|
|
245
|
-
}).finally(() => {
|
|
246
|
-
delete this._requests[id];
|
|
247
|
-
});
|
|
248
|
-
this._requests[id] = request;
|
|
249
|
-
return request;
|
|
250
|
-
};
|
|
251
|
-
this.abort = id => {
|
|
252
|
-
delete this._requests[id];
|
|
253
|
-
};
|
|
254
|
-
this.abortAll = () => {
|
|
255
|
-
Object.keys(this._requests).forEach(id => this.abort(id));
|
|
256
|
-
};
|
|
257
|
-
}
|
|
258
|
-
static get Default() {
|
|
259
|
-
if (!_default$1) {
|
|
260
|
-
_default$1 = new RequestFulfillment();
|
|
261
|
-
}
|
|
262
|
-
return _default$1;
|
|
263
|
-
}
|
|
264
|
-
}
|
|
38
|
+
const DefaultScope$2="default";let _default$2;class SsrCache{static get Default(){if(!_default$2){_default$2=new SsrCache;}return _default$2}_setCachedResponse(id,entry,hydrate){const frozenEntry=Object.freeze(entry);if(wonderBlocksCore.Server.isServerSide()){if(hydrate){this._hydrationCache.set(DefaultScope$2,id,frozenEntry);}else {this._ssrOnlyCache.set(DefaultScope$2,id,frozenEntry);}}return frozenEntry}constructor(hydrationCache=null,ssrOnlyCache=null){this.initialize=source=>{if(this._hydrationCache.inUse){throw new Error("Cannot initialize data response cache more than once")}this._hydrationCache=new SerializableInMemoryCache({[DefaultScope$2]:source});};this.cacheData=(id,data,hydrate)=>this._setCachedResponse(id,{data},hydrate);this.cacheError=(id,error,hydrate)=>{const errorMessage=typeof error==="string"?error:error.message;return this._setCachedResponse(id,{error:errorMessage},hydrate)};this.getEntry=id=>{const ssrEntry=wonderBlocksCore.Server.isServerSide()?this._ssrOnlyCache.get(DefaultScope$2,id):null;const internalEntry=ssrEntry??this._hydrationCache.get(DefaultScope$2,id);if(!wonderBlocksCore.Server.isServerSide()&&internalEntry!=null){this._hydrationCache.purge(DefaultScope$2,id);}return internalEntry};this.purgeData=predicate=>{const realPredicate=predicate?(_,key,cachedEntry)=>predicate(key,cachedEntry):undefined;this._hydrationCache.purgeAll(realPredicate);this._ssrOnlyCache.purgeAll(realPredicate);};this.cloneHydratableData=()=>{const cache=this._hydrationCache.clone();return cache[DefaultScope$2]??{}};this._ssrOnlyCache=ssrOnlyCache||new SerializableInMemoryCache;this._hydrationCache=hydrationCache||new SerializableInMemoryCache;}}
|
|
265
39
|
|
|
266
|
-
const
|
|
267
|
-
TrackerContext.displayName = "TrackerContext";
|
|
268
|
-
let _default;
|
|
269
|
-
class RequestTracker {
|
|
270
|
-
static get Default() {
|
|
271
|
-
if (!_default) {
|
|
272
|
-
_default = new RequestTracker();
|
|
273
|
-
}
|
|
274
|
-
return _default;
|
|
275
|
-
}
|
|
276
|
-
constructor(responseCache) {
|
|
277
|
-
this._trackedRequests = {};
|
|
278
|
-
this._responseCache = void 0;
|
|
279
|
-
this._requestFulfillment = void 0;
|
|
280
|
-
this.trackDataRequest = (id, handler, hydrate) => {
|
|
281
|
-
if (this._trackedRequests[id] == null) {
|
|
282
|
-
this._trackedRequests[id] = {
|
|
283
|
-
handler,
|
|
284
|
-
hydrate
|
|
285
|
-
};
|
|
286
|
-
}
|
|
287
|
-
};
|
|
288
|
-
this.reset = () => {
|
|
289
|
-
this._trackedRequests = {};
|
|
290
|
-
};
|
|
291
|
-
this.fulfillTrackedRequests = () => {
|
|
292
|
-
const promises = [];
|
|
293
|
-
const {
|
|
294
|
-
cacheData,
|
|
295
|
-
cacheError
|
|
296
|
-
} = this._responseCache;
|
|
297
|
-
for (const requestKey of Object.keys(this._trackedRequests)) {
|
|
298
|
-
const options = this._trackedRequests[requestKey];
|
|
299
|
-
try {
|
|
300
|
-
promises.push(this._requestFulfillment.fulfill(requestKey, _extends__default["default"]({}, options)).then(result => {
|
|
301
|
-
switch (result.status) {
|
|
302
|
-
case "success":
|
|
303
|
-
cacheData(requestKey, result.data, options.hydrate);
|
|
304
|
-
break;
|
|
305
|
-
case "error":
|
|
306
|
-
cacheError(requestKey, result.error, options.hydrate);
|
|
307
|
-
break;
|
|
308
|
-
}
|
|
309
|
-
return;
|
|
310
|
-
}));
|
|
311
|
-
} catch (e) {
|
|
312
|
-
promises.push(Promise.resolve(cacheError(requestKey, e, options.hydrate)));
|
|
313
|
-
}
|
|
314
|
-
}
|
|
315
|
-
this.reset();
|
|
316
|
-
return Promise.all(promises).then(() => this._responseCache.cloneHydratableData());
|
|
317
|
-
};
|
|
318
|
-
this._responseCache = responseCache || SsrCache.Default;
|
|
319
|
-
this._requestFulfillment = new RequestFulfillment();
|
|
320
|
-
}
|
|
321
|
-
get hasUnfulfilledRequests() {
|
|
322
|
-
return Object.keys(this._trackedRequests).length > 0;
|
|
323
|
-
}
|
|
324
|
-
}
|
|
40
|
+
const initializeHydrationCache=source=>SsrCache.Default.initialize(source);const purgeHydrationCache=predicate=>SsrCache.Default.purgeData(predicate);
|
|
325
41
|
|
|
326
|
-
const
|
|
327
|
-
if (wonderBlocksCore.Server.isServerSide()) {
|
|
328
|
-
return null;
|
|
329
|
-
}
|
|
330
|
-
if (process.env.NODE_ENV === "production") {
|
|
331
|
-
return new DataError("No CSR tracking", DataErrors.NotAllowed);
|
|
332
|
-
} else {
|
|
333
|
-
return new DataError("Data requests are not tracked for fulfillment when when client-side", DataErrors.NotAllowed);
|
|
334
|
-
}
|
|
335
|
-
};
|
|
336
|
-
const fetchTrackedRequests = () => {
|
|
337
|
-
const ssrCheck = SSRCheck();
|
|
338
|
-
if (ssrCheck != null) {
|
|
339
|
-
return Promise.reject(ssrCheck);
|
|
340
|
-
}
|
|
341
|
-
return RequestTracker.Default.fulfillTrackedRequests();
|
|
342
|
-
};
|
|
343
|
-
const hasTrackedRequestsToBeFetched = () => {
|
|
344
|
-
const ssrCheck = SSRCheck();
|
|
345
|
-
if (ssrCheck != null) {
|
|
346
|
-
throw ssrCheck;
|
|
347
|
-
}
|
|
348
|
-
return RequestTracker.Default.hasUnfulfilledRequests;
|
|
349
|
-
};
|
|
350
|
-
const abortInflightRequests = () => {
|
|
351
|
-
RequestFulfillment.Default.abortAll();
|
|
352
|
-
};
|
|
353
|
-
|
|
354
|
-
const cache$1 = new ScopedInMemoryCache();
|
|
355
|
-
const SharedCache = cache$1;
|
|
356
|
-
const useSharedCache = (id, scope, initialValue) => {
|
|
357
|
-
if (!id || typeof id !== "string") {
|
|
358
|
-
throw new DataError("id must be a non-empty string", DataErrors.InvalidInput);
|
|
359
|
-
}
|
|
360
|
-
if (!scope || typeof scope !== "string") {
|
|
361
|
-
throw new DataError("scope must be a non-empty string", DataErrors.InvalidInput);
|
|
362
|
-
}
|
|
363
|
-
const cacheValue = React__namespace.useCallback(value => value == null ? cache$1.purge(scope, id) : cache$1.set(scope, id, value), [id, scope]);
|
|
364
|
-
let currentValue = cache$1.get(scope, id);
|
|
365
|
-
if (currentValue == null && initialValue !== undefined) {
|
|
366
|
-
const value = typeof initialValue === "function" ? initialValue() : initialValue;
|
|
367
|
-
if (value != null) {
|
|
368
|
-
cacheValue(value);
|
|
369
|
-
currentValue = value;
|
|
370
|
-
}
|
|
371
|
-
}
|
|
372
|
-
return [currentValue, cacheValue];
|
|
373
|
-
};
|
|
374
|
-
|
|
375
|
-
const purgeCaches = () => {
|
|
376
|
-
SharedCache.purgeAll();
|
|
377
|
-
purgeHydrationCache();
|
|
378
|
-
};
|
|
379
|
-
|
|
380
|
-
class TrackData extends React__namespace.Component {
|
|
381
|
-
render() {
|
|
382
|
-
if (!wonderBlocksCore.Server.isServerSide()) {
|
|
383
|
-
throw new Error("This component is not for use during client-side rendering");
|
|
384
|
-
}
|
|
385
|
-
return React__namespace.createElement(TrackerContext.Provider, {
|
|
386
|
-
value: RequestTracker.Default.trackDataRequest
|
|
387
|
-
}, this.props.children);
|
|
388
|
-
}
|
|
389
|
-
}
|
|
42
|
+
let _default$1;class RequestFulfillment{static get Default(){if(!_default$1){_default$1=new RequestFulfillment;}return _default$1}constructor(){this._requests={};this.fulfill=(id,{handler,hydrate=true})=>{const inflight=this._requests[id];if(inflight){return inflight}const request=handler().then(data=>({status:"success",data})).catch(error=>{const actualError=typeof error==="string"?new DataError("Request failed",DataErrors.Unknown,{metadata:{unexpectedError:error}}):error;if(actualError.name==="AbortError"){return {status:"aborted"}}return {status:"error",error:actualError}}).finally(()=>{delete this._requests[id];});this._requests[id]=request;return request};this.abort=id=>{delete this._requests[id];};this.abortAll=()=>{Object.keys(this._requests).forEach(id=>this.abort(id));};}}
|
|
390
43
|
|
|
391
|
-
const
|
|
392
|
-
status: "loading"
|
|
393
|
-
});
|
|
394
|
-
const noDataStatus = Object.freeze({
|
|
395
|
-
status: "no-data"
|
|
396
|
-
});
|
|
397
|
-
const abortedStatus = Object.freeze({
|
|
398
|
-
status: "aborted"
|
|
399
|
-
});
|
|
400
|
-
const Status = Object.freeze({
|
|
401
|
-
loading: () => loadingStatus,
|
|
402
|
-
noData: () => noDataStatus,
|
|
403
|
-
aborted: () => abortedStatus,
|
|
404
|
-
success: data => ({
|
|
405
|
-
status: "success",
|
|
406
|
-
data
|
|
407
|
-
}),
|
|
408
|
-
error: error => ({
|
|
409
|
-
status: "error",
|
|
410
|
-
error
|
|
411
|
-
})
|
|
412
|
-
});
|
|
413
|
-
|
|
414
|
-
const resultFromCachedResponse = cacheEntry => {
|
|
415
|
-
if (cacheEntry == null) {
|
|
416
|
-
return null;
|
|
417
|
-
}
|
|
418
|
-
const {
|
|
419
|
-
data,
|
|
420
|
-
error
|
|
421
|
-
} = cacheEntry;
|
|
422
|
-
if (error != null) {
|
|
423
|
-
return Status.error(new DataError(error, DataErrors.Hydrated));
|
|
424
|
-
}
|
|
425
|
-
if (data != null) {
|
|
426
|
-
return Status.success(data);
|
|
427
|
-
}
|
|
428
|
-
return Status.aborted();
|
|
429
|
-
};
|
|
430
|
-
|
|
431
|
-
const InterceptContext = React__namespace.createContext([]);
|
|
432
|
-
InterceptContext.displayName = "InterceptContext";
|
|
433
|
-
|
|
434
|
-
const useRequestInterception = (requestId, handler) => {
|
|
435
|
-
const interceptors = React__namespace.useContext(InterceptContext);
|
|
436
|
-
const interceptedHandler = React__namespace.useCallback(() => {
|
|
437
|
-
const interceptResponse = interceptors.reduceRight((prev, interceptor) => {
|
|
438
|
-
if (prev != null) {
|
|
439
|
-
return prev;
|
|
440
|
-
}
|
|
441
|
-
return interceptor(requestId);
|
|
442
|
-
}, null);
|
|
443
|
-
return interceptResponse != null ? interceptResponse : handler();
|
|
444
|
-
}, [handler, interceptors, requestId]);
|
|
445
|
-
return interceptedHandler;
|
|
446
|
-
};
|
|
447
|
-
|
|
448
|
-
const useServerEffect = (requestId, handler, options = {}) => {
|
|
449
|
-
const {
|
|
450
|
-
hydrate = true,
|
|
451
|
-
skip = false
|
|
452
|
-
} = options;
|
|
453
|
-
const interceptedHandler = useRequestInterception(requestId, handler);
|
|
454
|
-
const cachedResult = SsrCache.Default.getEntry(requestId);
|
|
455
|
-
const maybeTrack = React.useContext(TrackerContext);
|
|
456
|
-
if (!skip && cachedResult == null && wonderBlocksCore.Server.isServerSide()) {
|
|
457
|
-
maybeTrack == null || maybeTrack(requestId, interceptedHandler, hydrate);
|
|
458
|
-
}
|
|
459
|
-
return cachedResult == null ? null : resultFromCachedResponse(cachedResult);
|
|
460
|
-
};
|
|
461
|
-
|
|
462
|
-
const DefaultScope$1 = "useCachedEffect";
|
|
463
|
-
const useCachedEffect = (requestId, handler, options = {}) => {
|
|
464
|
-
var _ref;
|
|
465
|
-
const {
|
|
466
|
-
fetchPolicy = FetchPolicy.CacheBeforeNetwork,
|
|
467
|
-
skip: hardSkip = false,
|
|
468
|
-
retainResultOnChange = false,
|
|
469
|
-
onResultChanged,
|
|
470
|
-
scope = DefaultScope$1
|
|
471
|
-
} = options;
|
|
472
|
-
const interceptedHandler = useRequestInterception(requestId, handler);
|
|
473
|
-
const [mostRecentResult, setMostRecentResult] = useSharedCache(requestId, scope);
|
|
474
|
-
const forceUpdate = wonderBlocksCore.useForceUpdate();
|
|
475
|
-
const networkResultRef = React__namespace.useRef();
|
|
476
|
-
const currentRequestRef = React__namespace.useRef();
|
|
477
|
-
const fetchRequest = React__namespace.useMemo(() => {
|
|
478
|
-
var _currentRequestRef$cu;
|
|
479
|
-
(_currentRequestRef$cu = currentRequestRef.current) == null || _currentRequestRef$cu.cancel();
|
|
480
|
-
currentRequestRef.current = null;
|
|
481
|
-
networkResultRef.current = null;
|
|
482
|
-
const fetchFn = () => {
|
|
483
|
-
var _currentRequestRef$cu2, _currentRequestRef$cu3;
|
|
484
|
-
if (fetchPolicy === FetchPolicy.CacheOnly) {
|
|
485
|
-
throw new DataError("Cannot fetch with CacheOnly policy", DataErrors.NotAllowed);
|
|
486
|
-
}
|
|
487
|
-
const request = RequestFulfillment.Default.fulfill(`${requestId}|${scope}`, {
|
|
488
|
-
handler: interceptedHandler
|
|
489
|
-
});
|
|
490
|
-
if (request === ((_currentRequestRef$cu2 = currentRequestRef.current) == null ? void 0 : _currentRequestRef$cu2.request)) {
|
|
491
|
-
return;
|
|
492
|
-
}
|
|
493
|
-
networkResultRef.current = null;
|
|
494
|
-
(_currentRequestRef$cu3 = currentRequestRef.current) == null || _currentRequestRef$cu3.cancel();
|
|
495
|
-
let cancel = false;
|
|
496
|
-
request.then(result => {
|
|
497
|
-
currentRequestRef.current = null;
|
|
498
|
-
if (cancel) {
|
|
499
|
-
return;
|
|
500
|
-
}
|
|
501
|
-
setMostRecentResult(result);
|
|
502
|
-
networkResultRef.current = result;
|
|
503
|
-
if (onResultChanged != null) {
|
|
504
|
-
onResultChanged(result);
|
|
505
|
-
} else {
|
|
506
|
-
forceUpdate();
|
|
507
|
-
}
|
|
508
|
-
return;
|
|
509
|
-
});
|
|
510
|
-
currentRequestRef.current = {
|
|
511
|
-
requestId,
|
|
512
|
-
request,
|
|
513
|
-
cancel() {
|
|
514
|
-
cancel = true;
|
|
515
|
-
RequestFulfillment.Default.abort(requestId);
|
|
516
|
-
}
|
|
517
|
-
};
|
|
518
|
-
};
|
|
519
|
-
return fetchFn;
|
|
520
|
-
}, [requestId, onResultChanged, forceUpdate, setMostRecentResult, fetchPolicy]);
|
|
521
|
-
const shouldFetch = React__namespace.useMemo(() => {
|
|
522
|
-
if (hardSkip) {
|
|
523
|
-
return false;
|
|
524
|
-
}
|
|
525
|
-
switch (fetchPolicy) {
|
|
526
|
-
case FetchPolicy.CacheOnly:
|
|
527
|
-
return false;
|
|
528
|
-
case FetchPolicy.CacheBeforeNetwork:
|
|
529
|
-
return mostRecentResult == null;
|
|
530
|
-
case FetchPolicy.CacheAndNetwork:
|
|
531
|
-
case FetchPolicy.NetworkOnly:
|
|
532
|
-
return networkResultRef.current == null;
|
|
533
|
-
}
|
|
534
|
-
}, [mostRecentResult, fetchPolicy, hardSkip]);
|
|
535
|
-
React__namespace.useEffect(() => {
|
|
536
|
-
if (!shouldFetch) {
|
|
537
|
-
return;
|
|
538
|
-
}
|
|
539
|
-
fetchRequest();
|
|
540
|
-
return () => {
|
|
541
|
-
var _currentRequestRef$cu4;
|
|
542
|
-
(_currentRequestRef$cu4 = currentRequestRef.current) == null || _currentRequestRef$cu4.cancel();
|
|
543
|
-
currentRequestRef.current = null;
|
|
544
|
-
};
|
|
545
|
-
}, [shouldFetch, fetchRequest]);
|
|
546
|
-
const lastResultAgnosticOfIdRef = React__namespace.useRef(Status.noData());
|
|
547
|
-
const loadingResult = retainResultOnChange ? lastResultAgnosticOfIdRef.current : shouldFetch ? Status.loading() : Status.noData();
|
|
548
|
-
const result = (_ref = fetchPolicy === FetchPolicy.NetworkOnly ? networkResultRef.current : mostRecentResult) != null ? _ref : loadingResult;
|
|
549
|
-
lastResultAgnosticOfIdRef.current = result;
|
|
550
|
-
return [result, fetchRequest];
|
|
551
|
-
};
|
|
552
|
-
|
|
553
|
-
let WhenClientSide = function (WhenClientSide) {
|
|
554
|
-
WhenClientSide["DoNotHydrate"] = "DoNotHydrate";
|
|
555
|
-
WhenClientSide["ExecuteWhenNoResult"] = "ExecuteWhenNoResult";
|
|
556
|
-
WhenClientSide["ExecuteWhenNoSuccessResult"] = "ExecuteWhenNoSuccessResult";
|
|
557
|
-
WhenClientSide["AlwaysExecute"] = "AlwaysExecute";
|
|
558
|
-
return WhenClientSide;
|
|
559
|
-
}({});
|
|
560
|
-
const DefaultScope = "useHydratableEffect";
|
|
561
|
-
const useHydratableEffect = (requestId, handler, options = {}) => {
|
|
562
|
-
const {
|
|
563
|
-
clientBehavior = WhenClientSide.ExecuteWhenNoSuccessResult,
|
|
564
|
-
skip = false,
|
|
565
|
-
retainResultOnChange = false,
|
|
566
|
-
onResultChanged,
|
|
567
|
-
scope = DefaultScope
|
|
568
|
-
} = options;
|
|
569
|
-
const serverResult = useServerEffect(requestId, handler, {
|
|
570
|
-
hydrate: clientBehavior !== WhenClientSide.DoNotHydrate,
|
|
571
|
-
skip
|
|
572
|
-
});
|
|
573
|
-
const getDefaultCacheValue = React__namespace.useCallback(() => {
|
|
574
|
-
switch (clientBehavior) {
|
|
575
|
-
case WhenClientSide.DoNotHydrate:
|
|
576
|
-
case WhenClientSide.AlwaysExecute:
|
|
577
|
-
return null;
|
|
578
|
-
case WhenClientSide.ExecuteWhenNoResult:
|
|
579
|
-
return serverResult;
|
|
580
|
-
case WhenClientSide.ExecuteWhenNoSuccessResult:
|
|
581
|
-
if ((serverResult == null ? void 0 : serverResult.status) === "success") {
|
|
582
|
-
return serverResult;
|
|
583
|
-
}
|
|
584
|
-
return null;
|
|
585
|
-
}
|
|
586
|
-
}, [serverResult]);
|
|
587
|
-
useSharedCache(requestId, scope, getDefaultCacheValue);
|
|
588
|
-
const [clientResult] = useCachedEffect(requestId, handler, {
|
|
589
|
-
skip,
|
|
590
|
-
onResultChanged,
|
|
591
|
-
retainResultOnChange,
|
|
592
|
-
scope,
|
|
593
|
-
fetchPolicy: FetchPolicy.CacheBeforeNetwork
|
|
594
|
-
});
|
|
595
|
-
return serverResult != null ? serverResult : clientResult;
|
|
596
|
-
};
|
|
597
|
-
|
|
598
|
-
const Data = ({
|
|
599
|
-
requestId,
|
|
600
|
-
handler,
|
|
601
|
-
children,
|
|
602
|
-
retainResultOnChange: _retainResultOnChange = false,
|
|
603
|
-
clientBehavior: _clientBehavior = WhenClientSide.ExecuteWhenNoSuccessResult
|
|
604
|
-
}) => {
|
|
605
|
-
const result = useHydratableEffect(requestId, handler, {
|
|
606
|
-
retainResultOnChange: _retainResultOnChange,
|
|
607
|
-
clientBehavior: _clientBehavior
|
|
608
|
-
});
|
|
609
|
-
return children(result);
|
|
610
|
-
};
|
|
611
|
-
|
|
612
|
-
const InterceptRequests = ({
|
|
613
|
-
interceptor,
|
|
614
|
-
children
|
|
615
|
-
}) => {
|
|
616
|
-
const interceptors = React__namespace.useContext(InterceptContext);
|
|
617
|
-
const updatedInterceptors = React__namespace.useMemo(() => [...interceptors, interceptor], [interceptors, interceptor]);
|
|
618
|
-
return React__namespace.createElement(InterceptContext.Provider, {
|
|
619
|
-
value: updatedInterceptors
|
|
620
|
-
}, children);
|
|
621
|
-
};
|
|
622
|
-
|
|
623
|
-
const toString = value => {
|
|
624
|
-
var _JSON$stringify;
|
|
625
|
-
if (typeof value === "string") {
|
|
626
|
-
return value;
|
|
627
|
-
}
|
|
628
|
-
if (typeof value === "object" && value != null) {
|
|
629
|
-
if (value instanceof Date) {
|
|
630
|
-
return value.toISOString();
|
|
631
|
-
} else if (typeof value.toString === "function") {
|
|
632
|
-
return value.toString();
|
|
633
|
-
}
|
|
634
|
-
}
|
|
635
|
-
return (_JSON$stringify = JSON.stringify(value)) != null ? _JSON$stringify : "";
|
|
636
|
-
};
|
|
637
|
-
const toStringifiedVariables = (acc, key, value) => {
|
|
638
|
-
if (typeof value === "object" && value !== null) {
|
|
639
|
-
const subValues = wonderStuffCore.entries(value);
|
|
640
|
-
if (subValues.length !== 0) {
|
|
641
|
-
return subValues.reduce((innerAcc, [i, v]) => {
|
|
642
|
-
const subKey = `${key}.${i}`;
|
|
643
|
-
return toStringifiedVariables(innerAcc, subKey, v);
|
|
644
|
-
}, acc);
|
|
645
|
-
}
|
|
646
|
-
}
|
|
647
|
-
acc[key] = toString(value);
|
|
648
|
-
return acc;
|
|
649
|
-
};
|
|
650
|
-
const getGqlRequestId = (operation, variables, context) => {
|
|
651
|
-
const parts = [];
|
|
652
|
-
const sortableContext = new URLSearchParams(context);
|
|
653
|
-
sortableContext.sort();
|
|
654
|
-
parts.push(sortableContext.toString());
|
|
655
|
-
parts.push(operation.id);
|
|
656
|
-
if (variables != null) {
|
|
657
|
-
const stringifiedVariables = Object.keys(variables).reduce((acc, key) => {
|
|
658
|
-
const value = variables[key];
|
|
659
|
-
return toStringifiedVariables(acc, key, value);
|
|
660
|
-
}, {});
|
|
661
|
-
const sortableVariables = new URLSearchParams(stringifiedVariables);
|
|
662
|
-
sortableVariables.sort();
|
|
663
|
-
parts.push(sortableVariables.toString());
|
|
664
|
-
}
|
|
665
|
-
return parts.join("|");
|
|
666
|
-
};
|
|
667
|
-
|
|
668
|
-
const GqlErrors = Object.freeze({
|
|
669
|
-
Internal: "Internal",
|
|
670
|
-
BadResponse: "BadResponse",
|
|
671
|
-
ErrorResult: "ErrorResult"
|
|
672
|
-
});
|
|
673
|
-
class GqlError extends wonderStuffCore.KindError {
|
|
674
|
-
constructor(message, kind, {
|
|
675
|
-
metadata,
|
|
676
|
-
cause
|
|
677
|
-
} = {}) {
|
|
678
|
-
super(message, kind, {
|
|
679
|
-
metadata,
|
|
680
|
-
cause,
|
|
681
|
-
name: "Gql"
|
|
682
|
-
});
|
|
683
|
-
}
|
|
684
|
-
}
|
|
44
|
+
const TrackerContext=React__namespace.createContext(null);TrackerContext.displayName="TrackerContext";let _default;class RequestTracker{static get Default(){if(!_default){_default=new RequestTracker;}return _default}get hasUnfulfilledRequests(){return Object.keys(this._trackedRequests).length>0}constructor(responseCache){this._trackedRequests={};this.trackDataRequest=(id,handler,hydrate)=>{if(this._trackedRequests[id]==null){this._trackedRequests[id]={handler,hydrate};}};this.reset=()=>{this._trackedRequests={};};this.fulfillTrackedRequests=()=>{const promises=[];const{cacheData,cacheError}=this._responseCache;for(const requestKey of Object.keys(this._trackedRequests)){const options=this._trackedRequests[requestKey];try{promises.push(this._requestFulfillment.fulfill(requestKey,{...options}).then(result=>{switch(result.status){case"success":cacheData(requestKey,result.data,options.hydrate);break;case"error":cacheError(requestKey,result.error,options.hydrate);break}return}));}catch(e){promises.push(Promise.resolve(cacheError(requestKey,e,options.hydrate)));}}this.reset();return Promise.all(promises).then(()=>this._responseCache.cloneHydratableData())};this._responseCache=responseCache||SsrCache.Default;this._requestFulfillment=new RequestFulfillment;}}
|
|
685
45
|
|
|
686
|
-
const
|
|
687
|
-
const bodyText = await response.text();
|
|
688
|
-
let result;
|
|
689
|
-
try {
|
|
690
|
-
result = JSON.parse(bodyText);
|
|
691
|
-
} catch (e) {
|
|
692
|
-
throw new DataError("Failed to parse response", DataErrors.Parse, {
|
|
693
|
-
metadata: {
|
|
694
|
-
statusCode: response.status,
|
|
695
|
-
bodyText
|
|
696
|
-
},
|
|
697
|
-
cause: e
|
|
698
|
-
});
|
|
699
|
-
}
|
|
700
|
-
if (response.status >= 300) {
|
|
701
|
-
throw new DataError("Response unsuccessful", DataErrors.Network, {
|
|
702
|
-
metadata: {
|
|
703
|
-
statusCode: response.status,
|
|
704
|
-
result
|
|
705
|
-
}
|
|
706
|
-
});
|
|
707
|
-
}
|
|
708
|
-
if (!Object.prototype.hasOwnProperty.call(result, "data") && !Object.prototype.hasOwnProperty.call(result, "errors")) {
|
|
709
|
-
throw new GqlError("Server response missing", GqlErrors.BadResponse, {
|
|
710
|
-
metadata: {
|
|
711
|
-
statusCode: response.status,
|
|
712
|
-
result
|
|
713
|
-
}
|
|
714
|
-
});
|
|
715
|
-
}
|
|
716
|
-
if (result.errors != null && Array.isArray(result.errors) && result.errors.length > 0) {
|
|
717
|
-
throw new GqlError("GraphQL errors", GqlErrors.ErrorResult, {
|
|
718
|
-
metadata: {
|
|
719
|
-
statusCode: response.status,
|
|
720
|
-
result
|
|
721
|
-
}
|
|
722
|
-
});
|
|
723
|
-
}
|
|
724
|
-
return result.data;
|
|
725
|
-
};
|
|
726
|
-
|
|
727
|
-
const DocumentTypes = Object.freeze({
|
|
728
|
-
query: "query",
|
|
729
|
-
mutation: "mutation"
|
|
730
|
-
});
|
|
731
|
-
const cache = new Map();
|
|
732
|
-
function graphQLDocumentNodeParser(document) {
|
|
733
|
-
var _definition$name;
|
|
734
|
-
const cached = cache.get(document);
|
|
735
|
-
if (cached) {
|
|
736
|
-
return cached;
|
|
737
|
-
}
|
|
738
|
-
if (!(document != null && document.kind)) {
|
|
739
|
-
if (process.env.NODE_ENV === "production") {
|
|
740
|
-
throw new DataError("Bad DocumentNode", DataErrors.InvalidInput);
|
|
741
|
-
} else {
|
|
742
|
-
throw new DataError(`Argument of ${JSON.stringify(document)} passed to parser was not a valid GraphQL ` + `DocumentNode. You may need to use 'graphql-tag' or another method ` + `to convert your operation into a document`, DataErrors.InvalidInput);
|
|
743
|
-
}
|
|
744
|
-
}
|
|
745
|
-
const fragments = document.definitions.filter(x => x.kind === "FragmentDefinition");
|
|
746
|
-
const queries = document.definitions.filter(x => x.kind === "OperationDefinition" && x.operation === "query");
|
|
747
|
-
const mutations = document.definitions.filter(x => x.kind === "OperationDefinition" && x.operation === "mutation");
|
|
748
|
-
const subscriptions = document.definitions.filter(x => x.kind === "OperationDefinition" && x.operation === "subscription");
|
|
749
|
-
if (fragments.length && !queries.length && !mutations.length) {
|
|
750
|
-
if (process.env.NODE_ENV === "production") {
|
|
751
|
-
throw new DataError("Fragment only", DataErrors.InvalidInput);
|
|
752
|
-
} else {
|
|
753
|
-
throw new DataError(`Passing only a fragment to 'graphql' is not supported. ` + `You must include a query or mutation as well`, DataErrors.InvalidInput);
|
|
754
|
-
}
|
|
755
|
-
}
|
|
756
|
-
if (subscriptions.length) {
|
|
757
|
-
if (process.env.NODE_ENV === "production") {
|
|
758
|
-
throw new DataError("No subscriptions", DataErrors.InvalidInput);
|
|
759
|
-
} else {
|
|
760
|
-
throw new DataError(`We do not support subscriptions. ` + `${JSON.stringify(document)} had ${subscriptions.length} subscriptions`, DataErrors.InvalidInput);
|
|
761
|
-
}
|
|
762
|
-
}
|
|
763
|
-
if (queries.length + mutations.length > 1) {
|
|
764
|
-
if (process.env.NODE_ENV === "production") {
|
|
765
|
-
throw new DataError("Too many ops", DataErrors.InvalidInput);
|
|
766
|
-
} else {
|
|
767
|
-
throw new DataError(`We only support one query or mutation per component. ` + `${JSON.stringify(document)} had ${queries.length} queries and ` + `${mutations.length} mutations. `, DataErrors.InvalidInput);
|
|
768
|
-
}
|
|
769
|
-
}
|
|
770
|
-
const type = queries.length ? DocumentTypes.query : DocumentTypes.mutation;
|
|
771
|
-
const definitions = queries.length ? queries : mutations;
|
|
772
|
-
const definition = definitions[0];
|
|
773
|
-
const variables = definition.variableDefinitions || [];
|
|
774
|
-
const name = ((_definition$name = definition.name) == null ? void 0 : _definition$name.kind) === "Name" ? definition.name.value : "data";
|
|
775
|
-
const payload = {
|
|
776
|
-
name,
|
|
777
|
-
type,
|
|
778
|
-
variables
|
|
779
|
-
};
|
|
780
|
-
cache.set(document, payload);
|
|
781
|
-
return payload;
|
|
782
|
-
}
|
|
46
|
+
const SSRCheck=()=>{if(wonderBlocksCore.Server.isServerSide()){return null}if(process.env.NODE_ENV==="production"){return new DataError("No CSR tracking",DataErrors.NotAllowed)}else {return new DataError("Data requests are not tracked for fulfillment when when client-side",DataErrors.NotAllowed)}};const fetchTrackedRequests=()=>{const ssrCheck=SSRCheck();if(ssrCheck!=null){return Promise.reject(ssrCheck)}return RequestTracker.Default.fulfillTrackedRequests()};const hasTrackedRequestsToBeFetched=()=>{const ssrCheck=SSRCheck();if(ssrCheck!=null){throw ssrCheck}return RequestTracker.Default.hasUnfulfilledRequests};const abortInflightRequests=()=>{RequestFulfillment.Default.abortAll();};
|
|
783
47
|
|
|
784
|
-
const
|
|
785
|
-
|
|
786
|
-
|
|
787
|
-
|
|
788
|
-
|
|
789
|
-
|
|
790
|
-
|
|
791
|
-
|
|
792
|
-
|
|
793
|
-
|
|
794
|
-
|
|
795
|
-
|
|
796
|
-
const
|
|
797
|
-
|
|
798
|
-
|
|
799
|
-
|
|
800
|
-
}) => {
|
|
801
|
-
|
|
802
|
-
|
|
803
|
-
|
|
804
|
-
|
|
805
|
-
|
|
806
|
-
|
|
807
|
-
|
|
808
|
-
};
|
|
809
|
-
|
|
810
|
-
const
|
|
811
|
-
|
|
812
|
-
|
|
813
|
-
|
|
814
|
-
|
|
815
|
-
|
|
816
|
-
|
|
817
|
-
|
|
818
|
-
|
|
819
|
-
|
|
820
|
-
|
|
821
|
-
|
|
822
|
-
|
|
823
|
-
|
|
824
|
-
|
|
825
|
-
|
|
826
|
-
|
|
827
|
-
}
|
|
828
|
-
const {
|
|
829
|
-
fetch,
|
|
830
|
-
defaultContext
|
|
831
|
-
} = gqlRouterContext;
|
|
832
|
-
const contextRef = React.useRef(defaultContext);
|
|
833
|
-
const mergedContext = mergeGqlContext(defaultContext, contextOverrides);
|
|
834
|
-
const refKeys = Object.keys(contextRef.current);
|
|
835
|
-
const mergedKeys = Object.keys(mergedContext);
|
|
836
|
-
const shouldWeUpdateRef = refKeys.length !== mergedKeys.length || mergedKeys.every(key => contextRef.current[key] !== mergedContext[key]);
|
|
837
|
-
if (shouldWeUpdateRef) {
|
|
838
|
-
contextRef.current = mergedContext;
|
|
839
|
-
}
|
|
840
|
-
const finalContext = contextRef.current;
|
|
841
|
-
const finalRouterContext = React.useMemo(() => ({
|
|
842
|
-
fetch,
|
|
843
|
-
defaultContext: finalContext
|
|
844
|
-
}), [fetch, finalContext]);
|
|
845
|
-
return finalRouterContext;
|
|
846
|
-
};
|
|
847
|
-
|
|
848
|
-
const useGql = (context = {}) => {
|
|
849
|
-
const gqlRouterContext = useGqlRouterContext(context);
|
|
850
|
-
const gqlFetch = React.useCallback((operation, options = Object.freeze({})) => {
|
|
851
|
-
const {
|
|
852
|
-
fetch,
|
|
853
|
-
defaultContext
|
|
854
|
-
} = gqlRouterContext;
|
|
855
|
-
const {
|
|
856
|
-
variables,
|
|
857
|
-
context = {}
|
|
858
|
-
} = options;
|
|
859
|
-
const finalContext = mergeGqlContext(defaultContext, context);
|
|
860
|
-
return fetch(operation, variables, finalContext).then(response => getGqlDataFromResponse(response));
|
|
861
|
-
}, [gqlRouterContext]);
|
|
862
|
-
return gqlFetch;
|
|
863
|
-
};
|
|
48
|
+
const cache$1=new ScopedInMemoryCache;const SharedCache=cache$1;const useSharedCache=(id,scope,initialValue)=>{if(!id||typeof id!=="string"){throw new DataError("id must be a non-empty string",DataErrors.InvalidInput)}if(!scope||typeof scope!=="string"){throw new DataError("scope must be a non-empty string",DataErrors.InvalidInput)}const cacheValue=React__namespace.useCallback(value=>value==null?cache$1.purge(scope,id):cache$1.set(scope,id,value),[id,scope]);let currentValue=cache$1.get(scope,id);if(currentValue==null&&initialValue!==undefined){const value=typeof initialValue==="function"?initialValue():initialValue;if(value!=null){cacheValue(value);currentValue=value;}}return [currentValue,cacheValue]};
|
|
49
|
+
|
|
50
|
+
const purgeCaches=()=>{SharedCache.purgeAll();purgeHydrationCache();};
|
|
51
|
+
|
|
52
|
+
class TrackData extends React__namespace.Component{render(){if(!wonderBlocksCore.Server.isServerSide()){throw new Error("This component is not for use during client-side rendering")}return jsxRuntime.jsx(TrackerContext.Provider,{value:RequestTracker.Default.trackDataRequest,children:this.props.children})}}
|
|
53
|
+
|
|
54
|
+
const loadingStatus=Object.freeze({status:"loading"});const noDataStatus=Object.freeze({status:"no-data"});const abortedStatus=Object.freeze({status:"aborted"});const Status=Object.freeze({loading:()=>loadingStatus,noData:()=>noDataStatus,aborted:()=>abortedStatus,success:data=>({status:"success",data}),error:error=>({status:"error",error})});
|
|
55
|
+
|
|
56
|
+
const resultFromCachedResponse=cacheEntry=>{if(cacheEntry==null){return null}const{data,error}=cacheEntry;if(error!=null){return Status.error(new DataError(error,DataErrors.Hydrated))}if(data!=null){return Status.success(data)}return Status.aborted()};
|
|
57
|
+
|
|
58
|
+
const InterceptContext=React__namespace.createContext([]);InterceptContext.displayName="InterceptContext";
|
|
59
|
+
|
|
60
|
+
const useRequestInterception=(requestId,handler)=>{const interceptors=React__namespace.useContext(InterceptContext);const interceptedHandler=React__namespace.useCallback(()=>{const interceptResponse=interceptors.reduceRight((prev,interceptor)=>{if(prev!=null){return prev}return interceptor(requestId)},null);return interceptResponse??handler()},[handler,interceptors,requestId]);return interceptedHandler};
|
|
61
|
+
|
|
62
|
+
const useServerEffect=(requestId,handler,options={})=>{const{hydrate=true,skip=false}=options;const interceptedHandler=useRequestInterception(requestId,handler);const cachedResult=SsrCache.Default.getEntry(requestId);const maybeTrack=React.useContext(TrackerContext);if(!skip&&cachedResult==null&&wonderBlocksCore.Server.isServerSide()){maybeTrack?.(requestId,interceptedHandler,hydrate);}return cachedResult==null?null:resultFromCachedResponse(cachedResult)};
|
|
63
|
+
|
|
64
|
+
const DefaultScope$1="useCachedEffect";const useCachedEffect=(requestId,handler,options={})=>{const{fetchPolicy=FetchPolicy.CacheBeforeNetwork,skip:hardSkip=false,retainResultOnChange=false,onResultChanged,scope=DefaultScope$1}=options;const interceptedHandler=useRequestInterception(requestId,handler);const[mostRecentResult,setMostRecentResult]=useSharedCache(requestId,scope);const forceUpdate=wonderBlocksCore.useForceUpdate();const networkResultRef=React__namespace.useRef();const currentRequestRef=React__namespace.useRef();const fetchRequest=React__namespace.useMemo(()=>{currentRequestRef.current?.cancel();currentRequestRef.current=null;networkResultRef.current=null;const fetchFn=()=>{if(fetchPolicy===FetchPolicy.CacheOnly){throw new DataError("Cannot fetch with CacheOnly policy",DataErrors.NotAllowed)}const request=RequestFulfillment.Default.fulfill(`${requestId}|${scope}`,{handler:interceptedHandler});if(request===currentRequestRef.current?.request){return}networkResultRef.current=null;currentRequestRef.current?.cancel();let cancel=false;request.then(result=>{currentRequestRef.current=null;if(cancel){return}setMostRecentResult(result);networkResultRef.current=result;if(onResultChanged!=null){onResultChanged(result);}else {forceUpdate();}return});currentRequestRef.current={requestId,request,cancel(){cancel=true;RequestFulfillment.Default.abort(requestId);}};};return fetchFn},[requestId,onResultChanged,forceUpdate,setMostRecentResult,fetchPolicy]);const shouldFetch=React__namespace.useMemo(()=>{if(hardSkip){return false}switch(fetchPolicy){case FetchPolicy.CacheOnly:return false;case FetchPolicy.CacheBeforeNetwork:return mostRecentResult==null;case FetchPolicy.CacheAndNetwork:case FetchPolicy.NetworkOnly:return networkResultRef.current==null}},[mostRecentResult,fetchPolicy,hardSkip]);React__namespace.useEffect(()=>{if(!shouldFetch){return}fetchRequest();return ()=>{currentRequestRef.current?.cancel();currentRequestRef.current=null;}},[shouldFetch,fetchRequest]);const lastResultAgnosticOfIdRef=React__namespace.useRef(Status.noData());const loadingResult=retainResultOnChange?lastResultAgnosticOfIdRef.current:shouldFetch?Status.loading():Status.noData();const result=(fetchPolicy===FetchPolicy.NetworkOnly?networkResultRef.current:mostRecentResult)??loadingResult;lastResultAgnosticOfIdRef.current=result;return [result,fetchRequest]};
|
|
65
|
+
|
|
66
|
+
var WhenClientSide=/*#__PURE__*/function(WhenClientSide){WhenClientSide["DoNotHydrate"]="DoNotHydrate";WhenClientSide["ExecuteWhenNoResult"]="ExecuteWhenNoResult";WhenClientSide["ExecuteWhenNoSuccessResult"]="ExecuteWhenNoSuccessResult";WhenClientSide["AlwaysExecute"]="AlwaysExecute";return WhenClientSide}({});const DefaultScope="useHydratableEffect";const useHydratableEffect=(requestId,handler,options={})=>{const{clientBehavior="ExecuteWhenNoSuccessResult",skip=false,retainResultOnChange=false,onResultChanged,scope=DefaultScope}=options;const serverResult=useServerEffect(requestId,handler,{hydrate:clientBehavior!=="DoNotHydrate",skip});const getDefaultCacheValue=React__namespace.useCallback(()=>{switch(clientBehavior){case"DoNotHydrate":case"AlwaysExecute":return null;case"ExecuteWhenNoResult":return serverResult;case"ExecuteWhenNoSuccessResult":if(serverResult?.status==="success"){return serverResult}return null}},[serverResult]);useSharedCache(requestId,scope,getDefaultCacheValue);const[clientResult]=useCachedEffect(requestId,handler,{skip,onResultChanged,retainResultOnChange,scope,fetchPolicy:FetchPolicy.CacheBeforeNetwork});return serverResult??clientResult};
|
|
67
|
+
|
|
68
|
+
const Data=({requestId,handler,children,retainResultOnChange=false,clientBehavior=WhenClientSide.ExecuteWhenNoSuccessResult})=>{const result=useHydratableEffect(requestId,handler,{retainResultOnChange,clientBehavior});return children(result)};
|
|
69
|
+
|
|
70
|
+
const InterceptRequests=({interceptor,children})=>{const interceptors=React__namespace.useContext(InterceptContext);const updatedInterceptors=React__namespace.useMemo(()=>[...interceptors,interceptor],[interceptors,interceptor]);return jsxRuntime.jsx(InterceptContext.Provider,{value:updatedInterceptors,children:children})};
|
|
71
|
+
|
|
72
|
+
const toString=value=>{if(typeof value==="string"){return value}if(typeof value==="object"&&value!=null){if(value instanceof Date){return value.toISOString()}else if(typeof value.toString==="function"){return value.toString()}}return JSON.stringify(value)??""};const toStringifiedVariables=(acc,key,value)=>{if(typeof value==="object"&&value!==null){const subValues=wonderStuffCore.entries(value);if(subValues.length!==0){return subValues.reduce((innerAcc,[i,v])=>{const subKey=`${key}.${i}`;return toStringifiedVariables(innerAcc,subKey,v)},acc)}}acc[key]=toString(value);return acc};const getGqlRequestId=(operation,variables,context)=>{const parts=[];const sortableContext=new URLSearchParams(context);sortableContext.sort();parts.push(sortableContext.toString());parts.push(operation.id);if(variables!=null){const stringifiedVariables=Object.keys(variables).reduce((acc,key)=>{const value=variables[key];return toStringifiedVariables(acc,key,value)},{});const sortableVariables=new URLSearchParams(stringifiedVariables);sortableVariables.sort();parts.push(sortableVariables.toString());}return parts.join("|")};
|
|
73
|
+
|
|
74
|
+
const GqlErrors=Object.freeze({Internal:"Internal",BadResponse:"BadResponse",ErrorResult:"ErrorResult"});class GqlError extends wonderStuffCore.KindError{constructor(message,kind,{metadata,cause}={}){super(message,kind,{metadata,cause,name:"Gql"});}}
|
|
75
|
+
|
|
76
|
+
const getGqlDataFromResponse=async response=>{const bodyText=await response.text();let result;try{result=JSON.parse(bodyText);}catch(e){throw new DataError("Failed to parse response",DataErrors.Parse,{metadata:{statusCode:response.status,bodyText},cause:e})}if(response.status>=300){throw new DataError("Response unsuccessful",DataErrors.Network,{metadata:{statusCode:response.status,result}})}if(!Object.prototype.hasOwnProperty.call(result,"data")&&!Object.prototype.hasOwnProperty.call(result,"errors")){throw new GqlError("Server response missing",GqlErrors.BadResponse,{metadata:{statusCode:response.status,result}})}if(result.errors!=null&&Array.isArray(result.errors)&&result.errors.length>0){throw new GqlError("GraphQL errors",GqlErrors.ErrorResult,{metadata:{statusCode:response.status,result}})}return result.data};
|
|
77
|
+
|
|
78
|
+
const DocumentTypes=Object.freeze({query:"query",mutation:"mutation"});const cache=new Map;function graphQLDocumentNodeParser(document){const cached=cache.get(document);if(cached){return cached}if(!document?.kind){if(process.env.NODE_ENV==="production"){throw new DataError("Bad DocumentNode",DataErrors.InvalidInput)}else {throw new DataError(`Argument of ${JSON.stringify(document)} passed to parser was not a valid GraphQL `+`DocumentNode. You may need to use 'graphql-tag' or another method `+`to convert your operation into a document`,DataErrors.InvalidInput)}}const fragments=document.definitions.filter(x=>x.kind==="FragmentDefinition");const queries=document.definitions.filter(x=>x.kind==="OperationDefinition"&&x.operation==="query");const mutations=document.definitions.filter(x=>x.kind==="OperationDefinition"&&x.operation==="mutation");const subscriptions=document.definitions.filter(x=>x.kind==="OperationDefinition"&&x.operation==="subscription");if(fragments.length&&!queries.length&&!mutations.length){if(process.env.NODE_ENV==="production"){throw new DataError("Fragment only",DataErrors.InvalidInput)}else {throw new DataError(`Passing only a fragment to 'graphql' is not supported. `+`You must include a query or mutation as well`,DataErrors.InvalidInput)}}if(subscriptions.length){if(process.env.NODE_ENV==="production"){throw new DataError("No subscriptions",DataErrors.InvalidInput)}else {throw new DataError(`We do not support subscriptions. `+`${JSON.stringify(document)} had ${subscriptions.length} subscriptions`,DataErrors.InvalidInput)}}if(queries.length+mutations.length>1){if(process.env.NODE_ENV==="production"){throw new DataError("Too many ops",DataErrors.InvalidInput)}else {throw new DataError(`We only support one query or mutation per component. `+`${JSON.stringify(document)} had ${queries.length} queries and `+`${mutations.length} mutations. `,DataErrors.InvalidInput)}}const type=queries.length?DocumentTypes.query:DocumentTypes.mutation;const definitions=queries.length?queries:mutations;const definition=definitions[0];const variables=definition.variableDefinitions||[];const name=definition.name?.kind==="Name"?definition.name.value:"data";const payload={name,type,variables};cache.set(document,payload);return payload}
|
|
79
|
+
|
|
80
|
+
const toGqlOperation=documentNode=>{const definition=graphQLDocumentNodeParser(documentNode);const wbDataOperation={id:definition.name,type:definition.type};return wbDataOperation};
|
|
81
|
+
|
|
82
|
+
const GqlRouterContext=React__namespace.createContext(null);GqlRouterContext.displayName="GqlRouterContext";
|
|
83
|
+
|
|
84
|
+
const GqlRouter=({defaultContext:thisDefaultContext,fetch:thisFetch,children})=>{const configuration=React__namespace.useMemo(()=>({fetch:thisFetch,defaultContext:thisDefaultContext}),[thisDefaultContext,thisFetch]);return jsxRuntime.jsx(GqlRouterContext.Provider,{value:configuration,children:children})};
|
|
85
|
+
|
|
86
|
+
const mergeGqlContext=(defaultContext,overrides)=>{return Object.keys(overrides).reduce((acc,key)=>{if(overrides[key]!==undefined){if(overrides[key]===null){delete acc[key];}else {acc[key]=overrides[key];}}return acc},{...defaultContext})};
|
|
87
|
+
|
|
88
|
+
const useGqlRouterContext=(contextOverrides={})=>{const gqlRouterContext=React.useContext(GqlRouterContext);if(gqlRouterContext==null){throw new GqlError("No GqlRouter",GqlErrors.Internal)}const{fetch,defaultContext}=gqlRouterContext;const contextRef=React.useRef(defaultContext);const mergedContext=mergeGqlContext(defaultContext,contextOverrides);const refKeys=Object.keys(contextRef.current);const mergedKeys=Object.keys(mergedContext);const shouldWeUpdateRef=refKeys.length!==mergedKeys.length||mergedKeys.every(key=>contextRef.current[key]!==mergedContext[key]);if(shouldWeUpdateRef){contextRef.current=mergedContext;}const finalContext=contextRef.current;const finalRouterContext=React.useMemo(()=>({fetch,defaultContext:finalContext}),[fetch,finalContext]);return finalRouterContext};
|
|
89
|
+
|
|
90
|
+
const useGql=(context={})=>{const gqlRouterContext=useGqlRouterContext(context);const gqlFetch=React.useCallback((operation,options=Object.freeze({}))=>{const{fetch,defaultContext}=gqlRouterContext;const{variables,context={}}=options;const finalContext=mergeGqlContext(defaultContext,context);return fetch(operation,variables,finalContext).then(response=>getGqlDataFromResponse(response))},[gqlRouterContext]);return gqlFetch};
|
|
864
91
|
|
|
865
92
|
exports.Data = Data;
|
|
866
93
|
exports.DataError = DataError;
|