@data-client/core 0.15.0 → 0.15.3

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 CHANGED
@@ -1,5 +1,15 @@
1
1
  # @data-client/core
2
2
 
3
+ ## 0.15.3
4
+
5
+ ### Patch Changes
6
+
7
+ - [#3691](https://github.com/reactive/data-client/pull/3691) [`bf3ac79`](https://github.com/reactive/data-client/commit/bf3ac7966dc615b1dc6cc6c6d600148fdca4e354) Thanks [@ntucker](https://github.com/ntucker)! - Fix CommonJS compatibility for `/mock` subpath exports.
8
+
9
+ Jest and other CommonJS consumers can now import from `@data-client/react/mock` and `@data-client/core/mock` without ESM parsing errors.
10
+
11
+ - [`ed4ec6d`](https://github.com/reactive/data-client/commit/ed4ec6dc516ac9e3977de7ec9018bff962626133) Thanks [@ntucker](https://github.com/ntucker)! - Fix image links in package README
12
+
3
13
  ## 0.15.0
4
14
 
5
15
  ### Minor Changes
package/README.md CHANGED
@@ -1,7 +1,7 @@
1
1
  <h1>
2
2
  <div align="center">
3
3
  <a href="https://dataclient.io" target="_blank" rel="noopener">
4
- <img alt="Reactive Data Client" src="./data_client_logo_and_text.svg?sanitize=true">
4
+ <img alt="Reactive Data Client" src="https://raw.githubusercontent.com/reactive/data-client/master/packages/core/data_client_logo_and_text.svg?sanitize=true">
5
5
  </a>
6
6
  </div>
7
7
  </h1>
package/dist/mock.js ADDED
@@ -0,0 +1,1242 @@
1
+ 'use strict';
2
+
3
+ var normalizr = require('@data-client/normalizr');
4
+
5
+ function expireReducer(state, action) {
6
+ const meta = {
7
+ ...state.meta
8
+ };
9
+ Object.keys(meta).forEach(key => {
10
+ if (action.testKey(key)) {
11
+ meta[key] = {
12
+ ...meta[key],
13
+ // 1 instead of 0 so we can do 'falsy' checks to see if it is set
14
+ expiresAt: 1
15
+ };
16
+ }
17
+ });
18
+ return {
19
+ ...state,
20
+ meta
21
+ };
22
+ }
23
+
24
+ function createMeta(expiryLength, fetchedAt) {
25
+ const now = Date.now();
26
+ return {
27
+ fetchedAt: fetchedAt != null ? fetchedAt : now,
28
+ date: now,
29
+ expiresAt: now + expiryLength
30
+ };
31
+ }
32
+
33
+ const FETCH = 'rdc/fetch';
34
+ const SET = 'rdc/set';
35
+ const SET_RESPONSE = 'rdc/setresponse';
36
+ const OPTIMISTIC = 'rdc/optimistic';
37
+ const RESET = 'rdc/reset';
38
+ const SUBSCRIBE = 'rdc/subscribe';
39
+ const UNSUBSCRIBE = 'rdc/unsubscribe';
40
+ const INVALIDATE = 'rdc/invalidate';
41
+ const INVALIDATEALL = 'rdc/invalidateall';
42
+ const EXPIREALL = 'rdc/expireall';
43
+ const GC = 'rdc/gc';
44
+ const FETCH_TYPE = FETCH;
45
+
46
+ function createOptimistic(endpoint, args, fetchedAt) {
47
+ var _endpoint$dataExpiryL, _endpoint$dataExpiryL2;
48
+ /* istanbul ignore next */
49
+ if (process.env.NODE_ENV === 'development' && ((_endpoint$dataExpiryL = endpoint.dataExpiryLength) != null ? _endpoint$dataExpiryL : 0) < 0) {
50
+ throw new Error('Negative expiry length are not allowed.');
51
+ }
52
+ return {
53
+ type: OPTIMISTIC,
54
+ key: endpoint.key(...args),
55
+ args,
56
+ endpoint,
57
+ meta: createMeta((_endpoint$dataExpiryL2 = endpoint.dataExpiryLength) != null ? _endpoint$dataExpiryL2 : 60000, fetchedAt)
58
+ };
59
+ }
60
+
61
+ function fetchReducer(state, action) {
62
+ if (action.endpoint.getOptimisticResponse && action.endpoint.sideEffect) {
63
+ const setAction = createOptimistic(action.endpoint, action.args, action.meta.fetchedAt);
64
+ return {
65
+ ...state,
66
+ optimistic: [...state.optimistic, setAction]
67
+ };
68
+ }
69
+ return state;
70
+ }
71
+
72
+ function invalidateReducer(state, action) {
73
+ const endpoints = {
74
+ ...state.endpoints
75
+ };
76
+ const meta = {
77
+ ...state.meta
78
+ };
79
+ const invalidateKey = key => {
80
+ delete endpoints[key];
81
+ const itemMeta = {
82
+ ...meta[key],
83
+ expiresAt: 0,
84
+ invalidated: true
85
+ };
86
+ delete itemMeta.error;
87
+ meta[key] = itemMeta;
88
+ };
89
+ if (action.type === INVALIDATE) {
90
+ invalidateKey(action.key);
91
+ } else {
92
+ Object.keys(endpoints).forEach(key => {
93
+ if (action.testKey(key)) {
94
+ invalidateKey(key);
95
+ }
96
+ });
97
+ }
98
+ return {
99
+ ...state,
100
+ endpoints,
101
+ meta
102
+ };
103
+ }
104
+
105
+ function setReducer(state, action, controller) {
106
+ let value;
107
+ if (typeof action.value === 'function') {
108
+ const previousValue = controller.get(action.schema, ...action.args, state);
109
+ if (previousValue === undefined) return state;
110
+ value = action.value(previousValue);
111
+ } else {
112
+ value = action.value;
113
+ }
114
+ try {
115
+ const {
116
+ entities,
117
+ indexes,
118
+ entitiesMeta
119
+ } = normalizr.normalize(action.schema, value, action.args, state, action.meta);
120
+ return {
121
+ entities,
122
+ endpoints: state.endpoints,
123
+ indexes,
124
+ meta: state.meta,
125
+ entitiesMeta,
126
+ optimistic: state.optimistic,
127
+ lastReset: state.lastReset
128
+ };
129
+ // reducer must update the state, so in case of processing errors we simply compute the endpoints inline
130
+ } catch (error) {
131
+ // this is not always bubbled up, so let's double sure this doesn't fail silently
132
+ /* istanbul ignore else */
133
+ if (process.env.NODE_ENV !== 'production') {
134
+ console.error(error);
135
+ }
136
+ return state;
137
+ }
138
+ }
139
+
140
+ class AbortOptimistic extends Error {}
141
+
142
+ function setResponseReducer(state, action, controller) {
143
+ if (action.error) {
144
+ return reduceError(state, action, action.response);
145
+ }
146
+ try {
147
+ var _state$meta$action$ke;
148
+ let response;
149
+ // for true set's response is contained in action
150
+ if (action.type === OPTIMISTIC) {
151
+ // this should never happen
152
+ /* istanbul ignore if */
153
+ if (!action.endpoint.getOptimisticResponse) return state;
154
+ try {
155
+ // compute optimistic response based on current state
156
+ response = action.endpoint.getOptimisticResponse.call(action.endpoint, controller.snapshot(state, action.meta.fetchedAt), ...action.args);
157
+ } catch (e) {
158
+ // AbortOptimistic means 'do nothing', otherwise we count the exception as endpoint failure
159
+ if (e.constructor === AbortOptimistic) {
160
+ return state;
161
+ }
162
+ throw e;
163
+ }
164
+ } else {
165
+ response = action.response;
166
+ }
167
+ const {
168
+ result,
169
+ entities,
170
+ indexes,
171
+ entitiesMeta
172
+ } = normalizr.normalize(action.endpoint.schema, response, action.args, state, action.meta);
173
+ const endpoints = {
174
+ ...state.endpoints,
175
+ [action.key]: result
176
+ };
177
+ try {
178
+ if (action.endpoint.update) {
179
+ const updaters = action.endpoint.update(result, ...action.args);
180
+ Object.keys(updaters).forEach(key => {
181
+ endpoints[key] = updaters[key](endpoints[key]);
182
+ });
183
+ }
184
+ // no reason to completely fail because of user-code error
185
+ // integrity of this state update is still guaranteed
186
+ } catch (error) {
187
+ console.error(`The following error occured during Endpoint.update() for ${action.key}`);
188
+ console.error(error);
189
+ }
190
+ return {
191
+ entities,
192
+ endpoints,
193
+ indexes,
194
+ meta: {
195
+ ...state.meta,
196
+ [action.key]: {
197
+ date: action.meta.date,
198
+ fetchedAt: action.meta.fetchedAt,
199
+ expiresAt: action.meta.expiresAt,
200
+ prevExpiresAt: (_state$meta$action$ke = state.meta[action.key]) == null ? void 0 : _state$meta$action$ke.expiresAt
201
+ }
202
+ },
203
+ entitiesMeta,
204
+ optimistic: filterOptimistic(state, action),
205
+ lastReset: state.lastReset
206
+ };
207
+ // reducer must update the state, so in case of processing errors we simply compute the endpoints inline
208
+ } catch (error) {
209
+ if (typeof error === 'object') {
210
+ error.message = `Error processing ${action.key}\n\nFull Schema: ${JSON.stringify(action.endpoint.schema, undefined, 2)}\n\nError:\n${error.message}`;
211
+ if ('response' in action) error.response = action.response;
212
+ error.status = 400;
213
+ }
214
+
215
+ // this is not always bubbled up, so let's double sure this doesn't fail silently
216
+ /* istanbul ignore else */
217
+ if (process.env.NODE_ENV !== 'production') {
218
+ console.error(error);
219
+ }
220
+ return reduceError(state, action, error);
221
+ }
222
+ }
223
+ function reduceError(state, action, error) {
224
+ if (error.name === 'AbortError') {
225
+ // In case we abort simply undo the optimistic update and act like no fetch even occured
226
+ // We still want those watching promises from fetch directly to observed the abort, but we don't want to
227
+ // Trigger errors in this case. This means theoretically improperly built aborts useSuspense() could suspend forever.
228
+ return {
229
+ ...state,
230
+ optimistic: filterOptimistic(state, action)
231
+ };
232
+ }
233
+ return {
234
+ ...state,
235
+ meta: {
236
+ ...state.meta,
237
+ [action.key]: {
238
+ date: action.meta.date,
239
+ fetchedAt: action.meta.fetchedAt,
240
+ expiresAt: action.meta.expiresAt,
241
+ error,
242
+ errorPolicy: action.endpoint.errorPolicy == null ? void 0 : action.endpoint.errorPolicy(error)
243
+ }
244
+ },
245
+ optimistic: filterOptimistic(state, action)
246
+ };
247
+ }
248
+ /** Filter all requests with same serialization that did not start after the resolving request */
249
+ function filterOptimistic(state, resolvingAction) {
250
+ return state.optimistic.filter(optimisticAction => optimisticAction.key !== resolvingAction.key || (optimisticAction.type === OPTIMISTIC ? optimisticAction.meta.fetchedAt !== resolvingAction.meta.fetchedAt : optimisticAction.meta.date > resolvingAction.meta.date));
251
+ }
252
+
253
+ function createReducer(controller) {
254
+ return function reducer(state, action) {
255
+ if (!state) state = initialState$1;
256
+ switch (action.type) {
257
+ case GC:
258
+ // inline deletes are fine as these should have 0 refcounts
259
+ action.entities.forEach(({
260
+ key,
261
+ pk
262
+ }) => {
263
+ var _entities$key, _entitiesMeta$key;
264
+ (_entities$key = state.entities[key]) == null || delete _entities$key[pk];
265
+ (_entitiesMeta$key = state.entitiesMeta[key]) == null || delete _entitiesMeta$key[pk];
266
+ });
267
+ action.endpoints.forEach(fetchKey => {
268
+ delete state.endpoints[fetchKey];
269
+ delete state.meta[fetchKey];
270
+ });
271
+ return state;
272
+ case FETCH:
273
+ return fetchReducer(state, action);
274
+ case OPTIMISTIC:
275
+ // eslint-disable-next-line no-fallthrough
276
+ case SET_RESPONSE:
277
+ return setResponseReducer(state, action, controller);
278
+ case SET:
279
+ return setReducer(state, action, controller);
280
+ case INVALIDATEALL:
281
+ case INVALIDATE:
282
+ return invalidateReducer(state, action);
283
+ case EXPIREALL:
284
+ return expireReducer(state, action);
285
+ case RESET:
286
+ return {
287
+ ...initialState$1,
288
+ lastReset: action.date
289
+ };
290
+ default:
291
+ // A reducer must always return a valid state.
292
+ // Alternatively you can throw an error if an invalid action is dispatched.
293
+ return state;
294
+ }
295
+ };
296
+ }
297
+ const initialState$1 = {
298
+ entities: {},
299
+ endpoints: {},
300
+ indexes: {},
301
+ meta: {},
302
+ entitiesMeta: {},
303
+ optimistic: [],
304
+ lastReset: 0
305
+ };
306
+
307
+ var __INTERNAL__ = /*#__PURE__*/Object.freeze({
308
+ __proto__: null,
309
+ INVALID: normalizr.INVALID,
310
+ MemoCache: normalizr.MemoCache,
311
+ initialState: initialState$1
312
+ });
313
+
314
+ function createSubscription(endpoint, {
315
+ args
316
+ }) {
317
+ return {
318
+ type: SUBSCRIBE,
319
+ key: endpoint.key(...args),
320
+ args,
321
+ endpoint
322
+ };
323
+ }
324
+ function createUnsubscription(endpoint, {
325
+ args
326
+ }) {
327
+ return {
328
+ type: UNSUBSCRIBE,
329
+ key: endpoint.key(...args),
330
+ args,
331
+ endpoint
332
+ };
333
+ }
334
+
335
+ const ensurePojo =
336
+ // FormData doesn't exist in node
337
+ /* istanbul ignore else we don't run coverage when we test node*/
338
+ typeof FormData !== 'undefined' ? body => body instanceof FormData ? Object.fromEntries(body.entries()) : body : /* istanbul ignore next */body => body;
339
+
340
+ function createSetResponse(endpoint, {
341
+ args,
342
+ fetchedAt,
343
+ response,
344
+ error = false
345
+ }) {
346
+ var _endpoint$errorExpiry, _endpoint$dataExpiryL;
347
+ const expiryLength = error ? (_endpoint$errorExpiry = endpoint.errorExpiryLength) != null ? _endpoint$errorExpiry : 1000 : (_endpoint$dataExpiryL = endpoint.dataExpiryLength) != null ? _endpoint$dataExpiryL : 60000;
348
+ /* istanbul ignore next */
349
+ if (process.env.NODE_ENV === 'development' && expiryLength < 0) {
350
+ throw new Error('Negative expiry length are not allowed.');
351
+ }
352
+ return {
353
+ type: SET_RESPONSE,
354
+ key: endpoint.key(...args),
355
+ response,
356
+ args: args.map(ensurePojo),
357
+ endpoint,
358
+ meta: createMeta(expiryLength, fetchedAt),
359
+ error
360
+ };
361
+ }
362
+
363
+ function createSet(schema, {
364
+ args,
365
+ fetchedAt,
366
+ value
367
+ }) {
368
+ return {
369
+ type: SET,
370
+ value,
371
+ args: args.map(ensurePojo),
372
+ schema,
373
+ meta: createMeta(60000, fetchedAt)
374
+ };
375
+ }
376
+
377
+ function createReset() {
378
+ return {
379
+ type: RESET,
380
+ date: Date.now()
381
+ };
382
+ }
383
+
384
+ function createInvalidateAll(testKey) {
385
+ return {
386
+ type: INVALIDATEALL,
387
+ testKey
388
+ };
389
+ }
390
+
391
+ function createInvalidate(endpoint, {
392
+ args
393
+ }) {
394
+ return {
395
+ type: INVALIDATE,
396
+ key: endpoint.key(...args)
397
+ };
398
+ }
399
+
400
+ /**
401
+ * Requesting a fetch to begin
402
+ */
403
+ function createFetch(endpoint, {
404
+ args
405
+ }) {
406
+ let resolve = 0;
407
+ let reject = 0;
408
+ const promise = new Promise((a, b) => {
409
+ [resolve, reject] = [a, b];
410
+ });
411
+ const meta = {
412
+ fetchedAt: Date.now(),
413
+ resolve,
414
+ reject,
415
+ promise
416
+ };
417
+ return {
418
+ type: FETCH,
419
+ key: endpoint.key(...args),
420
+ args,
421
+ endpoint,
422
+ meta
423
+ };
424
+ }
425
+
426
+ function createExpireAll(testKey) {
427
+ return {
428
+ type: EXPIREALL,
429
+ testKey
430
+ };
431
+ }
432
+
433
+ class ImmortalGCPolicy {
434
+ // eslint-disable-next-line @typescript-eslint/no-empty-function
435
+ init() {}
436
+ // eslint-disable-next-line @typescript-eslint/no-empty-function
437
+ cleanup() {}
438
+ createCountRef() {
439
+ return () => () => undefined;
440
+ }
441
+ }
442
+
443
+ function selectMeta(state, fetchKey) {
444
+ return state.meta[fetchKey];
445
+ }
446
+
447
+ const unsetDispatch = action => {
448
+ throw new Error(`Dispatching while constructing your middleware is not allowed. ` + `Other middleware would not be applied to this dispatch.`);
449
+ };
450
+ const unsetState = () => {
451
+ // This is only the value until it is set by the DataProvider
452
+ /* istanbul ignore next */
453
+ return initialState$1;
454
+ };
455
+
456
+ /**
457
+ * Imperative control of Reactive Data Client store
458
+ * @see https://dataclient.io/docs/api/Controller
459
+ */
460
+ class Controller {
461
+ /**
462
+ * Dispatches an action to Reactive Data Client reducer.
463
+ *
464
+ * @see https://dataclient.io/docs/api/Controller#dispatch
465
+ */
466
+
467
+ /**
468
+ * Gets the latest state snapshot that is fully committed.
469
+ *
470
+ * This can be useful for imperative use-cases like event handlers.
471
+ * This should *not* be used to render; instead useSuspense() or useCache()
472
+ * @see https://dataclient.io/docs/api/Controller#getState
473
+ */
474
+
475
+ /**
476
+ * Singleton to maintain referential equality between calls
477
+ */
478
+
479
+ /**
480
+ * Handles garbage collection
481
+ */
482
+
483
+ constructor({
484
+ dispatch = unsetDispatch,
485
+ getState = unsetState,
486
+ memo = new normalizr.MemoCache(),
487
+ gcPolicy = new ImmortalGCPolicy()
488
+ } = {}) {
489
+ this._dispatch = dispatch;
490
+ this.getState = getState;
491
+ this.memo = memo;
492
+ this.gcPolicy = gcPolicy;
493
+ }
494
+
495
+ // TODO: drop when drop support for destructuring (0.14 and below)
496
+ set dispatch(dispatch) {
497
+ /* istanbul ignore next */
498
+ this._dispatch = dispatch;
499
+ }
500
+
501
+ // TODO: drop when drop support for destructuring (0.14 and below)
502
+ get dispatch() {
503
+ return this._dispatch;
504
+ }
505
+ bindMiddleware({
506
+ dispatch,
507
+ getState
508
+ }) {
509
+ this._dispatch = dispatch;
510
+ this.getState = getState;
511
+ }
512
+
513
+ /*************** Action Dispatchers ***************/
514
+
515
+ /**
516
+ * Fetches the endpoint with given args, updating the Reactive Data Client cache with the response or error upon completion.
517
+ * @see https://dataclient.io/docs/api/Controller#fetch
518
+ */
519
+ fetch = (endpoint, ...args) => {
520
+ const action = createFetch(endpoint, {
521
+ args
522
+ });
523
+ this.dispatch(action);
524
+ if (endpoint.schema) {
525
+ return action.meta.promise.then(input => normalizr.denormalize(endpoint.schema, input, {}, args));
526
+ }
527
+ return action.meta.promise;
528
+ };
529
+
530
+ /**
531
+ * Fetches only if endpoint is considered 'stale'; otherwise returns undefined
532
+ * @see https://dataclient.io/docs/api/Controller#fetchIfStale
533
+ */
534
+ fetchIfStale = (endpoint, ...args) => {
535
+ const {
536
+ data,
537
+ expiresAt,
538
+ expiryStatus
539
+ } = this.getResponseMeta(endpoint, ...args, this.getState());
540
+ if (expiryStatus !== normalizr.ExpiryStatus.Invalid && Date.now() <= expiresAt) return data;
541
+ return this.fetch(endpoint, ...args);
542
+ };
543
+
544
+ /**
545
+ * Forces refetching and suspense on useSuspense with the same Endpoint and parameters.
546
+ * @see https://dataclient.io/docs/api/Controller#invalidate
547
+ */
548
+ invalidate = (endpoint, ...args) => args[0] !== null ? this.dispatch(createInvalidate(endpoint, {
549
+ args: args
550
+ })) : Promise.resolve();
551
+
552
+ /**
553
+ * Forces refetching and suspense on useSuspense on all matching endpoint result keys.
554
+ * @see https://dataclient.io/docs/api/Controller#invalidateAll
555
+ * @returns Promise that resolves when invalidation is commited.
556
+ */
557
+ invalidateAll = options => this.dispatch(createInvalidateAll(key => options.testKey(key)));
558
+
559
+ /**
560
+ * Sets all matching endpoint result keys to be STALE.
561
+ * @see https://dataclient.io/docs/api/Controller#expireAll
562
+ * @returns Promise that resolves when expiry is commited. *NOT* fetch promise
563
+ */
564
+ expireAll = options => this.dispatch(createExpireAll(key => options.testKey(key)));
565
+
566
+ /**
567
+ * Resets the entire Reactive Data Client cache. All inflight requests will not resolve.
568
+ * @see https://dataclient.io/docs/api/Controller#resetEntireStore
569
+ */
570
+ resetEntireStore = () => this.dispatch(createReset());
571
+
572
+ /**
573
+ * Sets value for the Queryable and args.
574
+ * @see https://dataclient.io/docs/api/Controller#set
575
+ */
576
+
577
+ set(schema, ...rest) {
578
+ const value = rest[rest.length - 1];
579
+ const action = createSet(schema, {
580
+ args: rest.slice(0, rest.length - 1),
581
+ value
582
+ });
583
+ // TODO: reject with error if this fails in reducer
584
+ return this.dispatch(action);
585
+ }
586
+
587
+ /**
588
+ * Sets response for the Endpoint and args.
589
+ * @see https://dataclient.io/docs/api/Controller#setResponse
590
+ */
591
+ setResponse = (endpoint, ...rest) => {
592
+ const response = rest[rest.length - 1];
593
+ const action = createSetResponse(endpoint, {
594
+ args: rest.slice(0, rest.length - 1),
595
+ response
596
+ });
597
+ return this.dispatch(action);
598
+ };
599
+
600
+ /**
601
+ * Sets an error response for the Endpoint and args.
602
+ * @see https://dataclient.io/docs/api/Controller#setError
603
+ */
604
+ setError = (endpoint, ...rest) => {
605
+ const response = rest[rest.length - 1];
606
+ const action = createSetResponse(endpoint, {
607
+ args: rest.slice(0, rest.length - 1),
608
+ response,
609
+ error: true
610
+ });
611
+ return this.dispatch(action);
612
+ };
613
+
614
+ /**
615
+ * Resolves an inflight fetch.
616
+ * @see https://dataclient.io/docs/api/Controller#resolve
617
+ */
618
+ resolve = (endpoint, meta) => {
619
+ return this.dispatch(createSetResponse(endpoint, meta));
620
+ };
621
+
622
+ /**
623
+ * Marks a new subscription to a given Endpoint.
624
+ * @see https://dataclient.io/docs/api/Controller#subscribe
625
+ */
626
+ subscribe = (endpoint, ...args) => args[0] !== null ? this.dispatch(createSubscription(endpoint, {
627
+ args: args
628
+ })) : Promise.resolve();
629
+
630
+ /**
631
+ * Marks completion of subscription to a given Endpoint.
632
+ * @see https://dataclient.io/docs/api/Controller#unsubscribe
633
+ */
634
+ unsubscribe = (endpoint, ...args) => args[0] !== null ? this.dispatch(createUnsubscription(endpoint, {
635
+ args: args
636
+ })) : Promise.resolve();
637
+
638
+ /*************** More ***************/
639
+
640
+ /* TODO:
641
+ abort = <E extends EndpointInterface>(
642
+ endpoint: E,
643
+ ...args: readonly [...Parameters<E>]
644
+ ): Promise<void>
645
+ */
646
+
647
+ /**
648
+ * Gets a snapshot (https://dataclient.io/docs/api/Snapshot)
649
+ * @see https://dataclient.io/docs/api/Controller#snapshot
650
+ */
651
+ snapshot = (state, fetchedAt) => {
652
+ return new Snapshot(this, state, fetchedAt);
653
+ };
654
+
655
+ /**
656
+ * Gets the error, if any, for a given endpoint. Returns undefined for no errors.
657
+ * @see https://dataclient.io/docs/api/Controller#getError
658
+ */
659
+
660
+ getError(endpoint, ...rest) {
661
+ if (rest[0] === null) return;
662
+ const state = rest[rest.length - 1];
663
+ // this is typescript generics breaking
664
+ const args = rest.slice(0, rest.length - 1);
665
+ const key = endpoint.key(...args);
666
+ const meta = selectMeta(state, key);
667
+ const error = state.endpoints[key];
668
+ if (error !== undefined && (meta == null ? void 0 : meta.errorPolicy) === 'soft') return;
669
+ return meta == null ? void 0 : meta.error;
670
+ }
671
+
672
+ /**
673
+ * Gets the (globally referentially stable) response for a given endpoint/args pair from state given.
674
+ * @see https://dataclient.io/docs/api/Controller#getResponse
675
+ */
676
+
677
+ getResponse(endpoint, ...rest) {
678
+ // TODO: breaking: only return data
679
+ return this.getResponseMeta(endpoint, ...rest);
680
+ }
681
+
682
+ /**
683
+ * Gets the (globally referentially stable) response for a given endpoint/args pair from state given.
684
+ * @see https://dataclient.io/docs/api/Controller#getResponseMeta
685
+ */
686
+
687
+ getResponseMeta(endpoint, ...rest) {
688
+ const state = rest[rest.length - 1];
689
+ // this is typescript generics breaking
690
+ const args = rest.slice(0, rest.length - 1)
691
+ // handle FormData
692
+ .map(ensurePojo);
693
+ const isActive = args.length !== 1 || args[0] !== null;
694
+ const key = isActive ? endpoint.key(...args) : '';
695
+ const cacheEndpoints = isActive ? state.endpoints[key] : undefined;
696
+ const schema = endpoint.schema;
697
+ const meta = selectMeta(state, key);
698
+ let expiresAt = meta == null ? void 0 : meta.expiresAt;
699
+ // if we have no endpoint entry, and our endpoint has a schema - try querying the store
700
+ const shouldQuery = cacheEndpoints === undefined && schema !== undefined;
701
+ const input = shouldQuery ?
702
+ // nothing in endpoints cache, so try querying if we have a schema to do so
703
+ this.memo.buildQueryKey(schema, args, state, key) : cacheEndpoints;
704
+ if (!isActive) {
705
+ // when not active simply return the query input without denormalizing
706
+ return {
707
+ data: input,
708
+ expiryStatus: normalizr.ExpiryStatus.Valid,
709
+ expiresAt: Infinity,
710
+ countRef: () => () => undefined
711
+ };
712
+ }
713
+ let isInvalid = false;
714
+ if (shouldQuery) {
715
+ isInvalid = !normalizr.validateQueryKey(input);
716
+ // endpoint without entities
717
+ } else if (!schema || !schemaHasEntity(schema)) {
718
+ return {
719
+ data: cacheEndpoints,
720
+ expiryStatus: this.getExpiryStatus(!cacheEndpoints, !!endpoint.invalidIfStale, meta),
721
+ expiresAt: expiresAt || 0,
722
+ countRef: this.gcPolicy.createCountRef({
723
+ key
724
+ })
725
+ };
726
+ }
727
+ const {
728
+ data,
729
+ paths
730
+ } = this.memo.denormalize(schema, input, state.entities, args);
731
+ if (!expiresAt) {
732
+ // note: isInvalid can only be true if shouldQuery is true
733
+ if (isInvalid) expiresAt = 1;
734
+ // fallback to entity expiry time
735
+ else expiresAt = entityExpiresAt(paths, state.entitiesMeta);
736
+ }
737
+ return {
738
+ data,
739
+ expiryStatus: this.getExpiryStatus(typeof data === 'symbol', !!endpoint.invalidIfStale || isInvalid, meta),
740
+ expiresAt,
741
+ countRef: this.gcPolicy.createCountRef({
742
+ key,
743
+ paths
744
+ })
745
+ };
746
+ }
747
+
748
+ /**
749
+ * Queries the store for a Querable schema
750
+ * @see https://dataclient.io/docs/api/Controller#get
751
+ */
752
+ get(schema, ...rest) {
753
+ const state = rest[rest.length - 1];
754
+ // this is typescript generics breaking
755
+ const args = rest.slice(0, rest.length - 1).map(ensurePojo);
756
+ const {
757
+ data
758
+ } = this.memo.query(schema, args, state);
759
+ return typeof data === 'symbol' ? undefined : data;
760
+ }
761
+
762
+ /**
763
+ * Queries the store for a Querable schema; providing related metadata
764
+ * @see https://dataclient.io/docs/api/Controller#getQueryMeta
765
+ */
766
+ getQueryMeta(schema, ...rest) {
767
+ const state = rest[rest.length - 1];
768
+ // this is typescript generics breaking
769
+ const args = rest.slice(0, rest.length - 1).map(ensurePojo);
770
+ const {
771
+ data,
772
+ paths
773
+ } = this.memo.query(schema, args, state);
774
+ return {
775
+ data: typeof data === 'symbol' ? undefined : data,
776
+ countRef: this.gcPolicy.createCountRef({
777
+ paths
778
+ })
779
+ };
780
+ }
781
+ getExpiryStatus(invalidData, invalidIfStale, meta = {}) {
782
+ // https://dataclient.io/docs/concepts/expiry-policy#expiry-status
783
+ // we don't track the difference between stale or fresh because that is tied to triggering
784
+ // conditions
785
+ return meta.invalidated || invalidData && !meta.error ? normalizr.ExpiryStatus.Invalid : invalidData || invalidIfStale ? normalizr.ExpiryStatus.InvalidIfStale : normalizr.ExpiryStatus.Valid;
786
+ }
787
+ }
788
+
789
+ // benchmark: https://www.measurethat.net/Benchmarks/Show/24691/0/min-reducer-vs-imperative-with-paths
790
+ // earliest expiry dictates age
791
+ function entityExpiresAt(paths, entitiesMeta) {
792
+ let expiresAt = Infinity;
793
+ for (const {
794
+ key,
795
+ pk
796
+ } of paths) {
797
+ var _entitiesMeta$key;
798
+ const entityExpiry = (_entitiesMeta$key = entitiesMeta[key]) == null || (_entitiesMeta$key = _entitiesMeta$key[pk]) == null ? void 0 : _entitiesMeta$key.expiresAt;
799
+ // expiresAt will always resolve to false with any comparison
800
+ if (entityExpiry < expiresAt) expiresAt = entityExpiry;
801
+ }
802
+ return expiresAt;
803
+ }
804
+
805
+ /** Determine whether the schema has any entities.
806
+ *
807
+ * Without entities, denormalization is not needed, and results should not be queried.
808
+ */
809
+ function schemaHasEntity(schema) {
810
+ if (normalizr.isEntity(schema)) return true;
811
+ if (Array.isArray(schema)) return schema.length !== 0 && schemaHasEntity(schema[0]);
812
+ if (schema && (typeof schema === 'object' || typeof schema === 'function')) {
813
+ const nestedSchema = 'schema' in schema ? schema.schema : schema;
814
+ if (typeof nestedSchema === 'function') {
815
+ return schemaHasEntity(nestedSchema);
816
+ }
817
+ return Object.values(nestedSchema).some(x => schemaHasEntity(x));
818
+ }
819
+ return false;
820
+ }
821
+ class Snapshot {
822
+ static abort = new AbortOptimistic();
823
+ state;
824
+ controller;
825
+ fetchedAt;
826
+ abort = Snapshot.abort;
827
+ constructor(controller, state, fetchedAt = 0) {
828
+ this.state = state;
829
+ this.controller = controller;
830
+ this.fetchedAt = fetchedAt;
831
+ }
832
+
833
+ /*************** Data Access ***************/
834
+ /** @see https://dataclient.io/docs/api/Snapshot#getResponse */
835
+
836
+ getResponse(endpoint, ...args) {
837
+ return this.controller.getResponse(endpoint, ...args, this.state);
838
+ }
839
+
840
+ /** @see https://dataclient.io/docs/api/Snapshot#getResponseMeta */
841
+
842
+ getResponseMeta(endpoint, ...args) {
843
+ return this.controller.getResponseMeta(endpoint, ...args, this.state);
844
+ }
845
+
846
+ /** @see https://dataclient.io/docs/api/Snapshot#getError */
847
+
848
+ getError(endpoint, ...args) {
849
+ return this.controller.getError(endpoint, ...args, this.state);
850
+ }
851
+
852
+ /**
853
+ * Retrieved memoized value for any Querable schema
854
+ * @see https://dataclient.io/docs/api/Snapshot#get
855
+ */
856
+ get(schema, ...args) {
857
+ return this.controller.get(schema, ...args, this.state);
858
+ }
859
+
860
+ /**
861
+ * Queries the store for a Querable schema; providing related metadata
862
+ * @see https://dataclient.io/docs/api/Snapshot#getQueryMeta
863
+ */
864
+ getQueryMeta(schema, ...args) {
865
+ return this.controller.getQueryMeta(schema, ...args, this.state);
866
+ }
867
+ }
868
+
869
+ var _DevToolsManager;
870
+ let DEFAULT_CONFIG = {};
871
+ if (process.env.NODE_ENV !== 'production') {
872
+ var _globalThis$document;
873
+ const extraEndpointKeys = ['dataExpiryLength', 'errorExpiryLength', 'errorPolicy', 'invalidIfStale', 'pollFrequency', 'getOptimisticResponse', 'update'];
874
+ function serializeEndpoint(endpoint) {
875
+ var _toJSON, _endpoint$schema;
876
+ const serial = {
877
+ name: endpoint.name,
878
+ schema: (_toJSON = (_endpoint$schema = endpoint.schema) == null || _endpoint$schema.toJSON == null ? void 0 : _endpoint$schema.toJSON()) != null ? _toJSON : endpoint.schema,
879
+ sideEffect: endpoint.sideEffect
880
+ };
881
+ extraEndpointKeys.forEach(key => {
882
+ if (key in endpoint) serial[key] = endpoint[key];
883
+ });
884
+ return serial;
885
+ }
886
+ const HASINTL = typeof Intl !== 'undefined';
887
+ DEFAULT_CONFIG = {
888
+ name: `Data Client: ${(_globalThis$document = globalThis.document) == null ? void 0 : _globalThis$document.title}`,
889
+ autoPause: true,
890
+ features: {
891
+ pause: true,
892
+ // start/pause recording of dispatched actions
893
+ lock: true,
894
+ // lock/unlock dispatching actions and side effects
895
+ persist: false,
896
+ // persist states on page reloading
897
+ export: true,
898
+ // export history of actions in a file
899
+ import: 'custom',
900
+ // import history of actions from a file
901
+ jump: true,
902
+ // jump back and forth (time travelling)
903
+ skip: true,
904
+ // skip (cancel) actions
905
+ reorder: true,
906
+ // drag and drop actions in the history list
907
+ dispatch: false,
908
+ // dispatch custom actions or action creators
909
+ test: false // generate tests for the selected actions
910
+ },
911
+ actionSanitizer: action => {
912
+ if (!('endpoint' in action)) return action;
913
+ return {
914
+ ...action,
915
+ endpoint: serializeEndpoint(action.endpoint)
916
+ };
917
+ },
918
+ serialize: {
919
+ options: undefined,
920
+ /* istanbul ignore next */
921
+ replacer: HASINTL ? (key, value) => {
922
+ if (typeof value === 'number' && typeof key === 'string' && isFinite(value) && (key === 'date' || key.endsWith('At'))) {
923
+ return Intl.DateTimeFormat('en-US', {
924
+ hour: 'numeric',
925
+ minute: 'numeric',
926
+ second: 'numeric',
927
+ fractionalSecondDigits: 3
928
+ }).format(value);
929
+ }
930
+ return value;
931
+ } : undefined
932
+ }
933
+ };
934
+ }
935
+
936
+ /** Integrates with https://github.com/reduxjs/redux-devtools
937
+ *
938
+ * Options: https://github.com/reduxjs/redux-devtools/blob/main/extension/docs/API/Arguments.md
939
+ *
940
+ * @see https://dataclient.io/docs/api/DevToolsManager
941
+ */
942
+ class DevToolsManager {
943
+ constructor(config, skipLogging) {
944
+ this.started = false;
945
+ this.actions = [];
946
+ this.maxBufferLength = 100;
947
+ /* istanbul ignore next */
948
+ this.devTools = typeof window !== 'undefined' && window.__REDUX_DEVTOOLS_EXTENSION__ && window.__REDUX_DEVTOOLS_EXTENSION__.connect({
949
+ ...DEFAULT_CONFIG,
950
+ ...config
951
+ });
952
+ // we cut it in half so we should double so we don't lose
953
+ if (config != null && config.maxAge) this.maxBufferLength = config.maxAge * 2;
954
+ if (skipLogging) this.skipLogging = skipLogging;
955
+ }
956
+ handleAction(action, state) {
957
+ if (this.started) {
958
+ this.devTools.send(action, state);
959
+ } else {
960
+ // avoid this getting too big in case this is long running
961
+ // we cut in half so we aren't constantly reallocating
962
+ if (this.actions.length > this.maxBufferLength) this.actions = this.actions.slice(this.maxBufferLength / 2);
963
+ // queue actions
964
+ this.actions.push([action, state]);
965
+ }
966
+ }
967
+
968
+ /** Called when initial state is ready */
969
+ init(state) {
970
+ if (process.env.NODE_ENV !== 'production' && this.devTools) {
971
+ this.devTools.init(state);
972
+ this.devTools.subscribe(msg => {
973
+ switch (msg.type) {
974
+ case 'START':
975
+ this.started = true;
976
+ if (this.actions.length) {
977
+ this.actions.forEach(([action, state]) => {
978
+ this.handleAction(action, state);
979
+ });
980
+ this.actions = [];
981
+ }
982
+ break;
983
+ case 'STOP':
984
+ this.started = false;
985
+ break;
986
+ case 'DISPATCH':
987
+ if (msg.payload.type === 'RESET') {
988
+ this.controller.resetEntireStore();
989
+ }
990
+ break;
991
+ }
992
+ });
993
+ }
994
+ }
995
+
996
+ /** Ensures all subscriptions are cleaned up. */
997
+ cleanup() {}
998
+ }
999
+ _DevToolsManager = DevToolsManager;
1000
+ (() => {
1001
+ /* istanbul ignore if */
1002
+ /* istanbul ignore next */
1003
+ if (process.env.NODE_ENV !== 'production') {
1004
+ _DevToolsManager.prototype.middleware = function (controller) {
1005
+ if (!this.devTools) return next => action => next(action);
1006
+ this.controller = controller;
1007
+ const reducer = createReducer(controller);
1008
+ let state = controller.getState();
1009
+ return next => action => {
1010
+ var _this$skipLogging;
1011
+ const shouldSkip = (_this$skipLogging = this.skipLogging) == null ? void 0 : _this$skipLogging.call(this, action);
1012
+ const ret = next(action);
1013
+ if (this.started) {
1014
+ // we track state changes here since getState() will only update after a batch commit
1015
+ state = reducer(state, action);
1016
+ } else {
1017
+ state = controller.getState();
1018
+ }
1019
+ ret.then(() => {
1020
+ if (shouldSkip) return;
1021
+ this.handleAction(action, state.optimistic.reduce(reducer, state));
1022
+ });
1023
+ return ret;
1024
+ };
1025
+ };
1026
+ } else {
1027
+ _DevToolsManager.prototype.middleware = () => next => action => next(action);
1028
+ }
1029
+ })();
1030
+
1031
+ async function collapseFixture(fixture, args, interceptorData) {
1032
+ let error = 'error' in fixture ? fixture.error : false;
1033
+ let response = fixture.response;
1034
+ if (typeof fixture.response === 'function') {
1035
+ try {
1036
+ response = await fixture.response.apply(interceptorData, args);
1037
+ // dispatch goes through user-code that can sometimes fail.
1038
+ // let's ensure we always handle errors
1039
+ } catch (e) {
1040
+ response = e;
1041
+ error = true;
1042
+ }
1043
+ }
1044
+ return {
1045
+ response,
1046
+ error
1047
+ };
1048
+ }
1049
+
1050
+ function createFixtureMap(fixtures = []) {
1051
+ const map = new Map();
1052
+ const computed = [];
1053
+ for (const fixture of fixtures) {
1054
+ if ('args' in fixture) {
1055
+ if (typeof fixture.response !== 'function') {
1056
+ const key = fixture.endpoint.key(...fixture.args);
1057
+ map.set(key, fixture);
1058
+ } else {
1059
+ // this has to be a typo. probably needs to remove args
1060
+ console.warn(`Fixture found with function response, and explicit args. Interceptors should not specify args.
1061
+ ${fixture.endpoint.name}: ${JSON.stringify(fixture.args)}
1062
+
1063
+ Treating as Interceptor`);
1064
+ computed.push(fixture);
1065
+ }
1066
+ } else {
1067
+ computed.push(fixture);
1068
+ }
1069
+ }
1070
+ return [map, computed];
1071
+ }
1072
+
1073
+ function MockController(Base, {
1074
+ fixtures = [],
1075
+ getInitialInterceptorData = () => ({})
1076
+ }) {
1077
+ const [fixtureMap, interceptors] = createFixtureMap(fixtures);
1078
+
1079
+ // eslint-disable-next-line @typescript-eslint/ban-ts-comment
1080
+ // @ts-ignore
1081
+ return class MockedController extends Base {
1082
+ // legacy compatibility (re-declaration)
1083
+ // TODO: drop when drop support for destructuring (0.14 and below)
1084
+
1085
+ fixtureMap = fixtureMap;
1086
+ interceptors = interceptors;
1087
+ interceptorData = getInitialInterceptorData();
1088
+ constructor(...args) {
1089
+ super(...args);
1090
+
1091
+ // legacy compatibility
1092
+ // TODO: drop when drop support for destructuring (0.14 and below)
1093
+ if (!this._dispatch) {
1094
+ this._dispatch = args[0].dispatch;
1095
+ }
1096
+ }
1097
+
1098
+ // legacy compatibility - we need this to work with 0.14 and below as they do not have this setter
1099
+ // TODO: drop when drop support for destructuring (0.14 and below)
1100
+ // eslint-disable-next-line @typescript-eslint/ban-ts-comment
1101
+ // @ts-ignore
1102
+ set dispatch(dispatch) {
1103
+ this._dispatch = dispatch;
1104
+ }
1105
+ get dispatch() {
1106
+ return action => {
1107
+ var _actionTypes$FETCH;
1108
+ // support legacy that has _TYPE suffix
1109
+ if (action.type === ((_actionTypes$FETCH = FETCH) != null ? _actionTypes$FETCH : FETCH_TYPE)) {
1110
+ // eslint-disable-next-line prefer-const
1111
+ let {
1112
+ key,
1113
+ args
1114
+ } = action;
1115
+ let fixture;
1116
+ if (this.fixtureMap.has(key)) {
1117
+ fixture = this.fixtureMap.get(key);
1118
+ if (!args) args = fixture.args;
1119
+ // exact matches take priority; now test ComputedFixture
1120
+ } else {
1121
+ for (const cfix of this.interceptors) {
1122
+ if (cfix.endpoint.testKey(key)) {
1123
+ fixture = cfix;
1124
+ break;
1125
+ }
1126
+ }
1127
+ }
1128
+ // we have a match
1129
+ if (fixture !== undefined) {
1130
+ var _fixture$delay;
1131
+ const replacedAction = {
1132
+ ...action
1133
+ };
1134
+ const delayMs = typeof fixture.delay === 'function' ? fixture.delay(...args) : (_fixture$delay = fixture.delay) != null ? _fixture$delay : 0;
1135
+ if ('fetchResponse' in fixture) {
1136
+ const {
1137
+ fetchResponse
1138
+ } = fixture;
1139
+ fixture = {
1140
+ endpoint: fixture.endpoint,
1141
+ response(...args) {
1142
+ const endpoint = action.endpoint.extend({
1143
+ fetchResponse: (input, init) => {
1144
+ const ret = fetchResponse.call(this, input, init);
1145
+ return Promise.resolve(new Response(JSON.stringify(ret), {
1146
+ status: 200,
1147
+ headers: new Headers({
1148
+ 'Content-Type': 'application/json'
1149
+ })
1150
+ }));
1151
+ }
1152
+ });
1153
+ return endpoint(...args);
1154
+ }
1155
+ };
1156
+ }
1157
+ const fetch = async () => {
1158
+ if (!fixture) {
1159
+ throw new Error('No fixture found');
1160
+ }
1161
+ // delayCollapse determines when the fixture function is 'collapsed' (aka 'run')
1162
+ // collapsed: https://en.wikipedia.org/wiki/Copenhagen_interpretation
1163
+ if (fixture.delayCollapse) {
1164
+ await new Promise(resolve => setTimeout(resolve, delayMs));
1165
+ }
1166
+ const result = await collapseFixture(fixture, args, this.interceptorData);
1167
+ if (!fixture.delayCollapse && delayMs) {
1168
+ await new Promise(resolve => setTimeout(resolve, delayMs));
1169
+ }
1170
+ if (result.error) {
1171
+ throw result.response;
1172
+ }
1173
+ return result.response;
1174
+ };
1175
+ if (typeof replacedAction.endpoint.extend === 'function') {
1176
+ replacedAction.endpoint = replacedAction.endpoint.extend({
1177
+ fetch
1178
+ });
1179
+ } else {
1180
+ // TODO: full testing of this
1181
+ replacedAction.endpoint = fetch;
1182
+ replacedAction.endpoint.__proto__ = action.endpoint;
1183
+ }
1184
+
1185
+ // TODO: make super.dispatch (once we drop support for destructuring)
1186
+ return this._dispatch(replacedAction);
1187
+ }
1188
+ }
1189
+ // TODO: make super.dispatch (once we drop support for destructuring)
1190
+ return this._dispatch(action);
1191
+ };
1192
+ }
1193
+ };
1194
+ }
1195
+
1196
+ const {
1197
+ initialState
1198
+ } = __INTERNAL__;
1199
+ function mockInitialState(fixtures = []) {
1200
+ const actions = [];
1201
+ const dispatch = action => {
1202
+ actions.push(action);
1203
+ return Promise.resolve();
1204
+ };
1205
+ const controller = new Controller({
1206
+ dispatch
1207
+ });
1208
+ const reducer = createReducer(controller);
1209
+ fixtures.forEach(fixture => {
1210
+ dispatchFixture(fixture, fixture.args, controller);
1211
+ });
1212
+ return actions.reduce(reducer, initialState);
1213
+ }
1214
+ function dispatchFixture(fixture, args, controller, fetchedAt) {
1215
+ // eslint-disable-next-line prefer-const
1216
+ let {
1217
+ endpoint
1218
+ } = fixture;
1219
+ const {
1220
+ response,
1221
+ error
1222
+ } = fixture;
1223
+ if (controller.resolve) {
1224
+ controller.resolve(endpoint, {
1225
+ args,
1226
+ response,
1227
+ error,
1228
+ fetchedAt: Date.now()
1229
+ });
1230
+ } else {
1231
+ if (error === true) {
1232
+ controller.setError(endpoint, ...args, response);
1233
+ } else {
1234
+ controller.setResponse(endpoint, ...args, response);
1235
+ }
1236
+ }
1237
+ }
1238
+
1239
+ exports.MockController = MockController;
1240
+ exports.collapseFixture = collapseFixture;
1241
+ exports.createFixtureMap = createFixtureMap;
1242
+ exports.mockInitialState = mockInitialState;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@data-client/core",
3
- "version": "0.15.0",
3
+ "version": "0.15.3",
4
4
  "description": "Async State Management without the Management. REST, GraphQL, SSE, Websockets, Fetch",
5
5
  "sideEffects": false,
6
6
  "main": "dist/index.js",
@@ -56,6 +56,7 @@
56
56
  },
57
57
  "./mock": {
58
58
  "types": "./lib/mock/index.d.ts",
59
+ "require": "./dist/mock.js",
59
60
  "default": "./lib/mock/index.js"
60
61
  },
61
62
  "./package.json": "./package.json"
@@ -72,9 +73,7 @@
72
73
  "node.mjs",
73
74
  "legacy",
74
75
  "LICENSE",
75
- "README.md",
76
- "./typescript.svg",
77
- "./data_client_logo_and_text.svg"
76
+ "README.md"
78
77
  ],
79
78
  "scripts": {
80
79
  "build:lib": "NODE_ENV=production BROWSERSLIST_ENV='2020' POLYFILL_TARGETS='chrome>88,safari>14' yarn g:babel --out-dir lib",
@@ -140,7 +139,7 @@
140
139
  },
141
140
  "devDependencies": {
142
141
  "@anansi/browserslist-config": "^1.4.2",
143
- "@data-client/endpoint": "0.15.0",
142
+ "@data-client/endpoint": "0.15.2",
144
143
  "@types/jest": "30.0.0",
145
144
  "@types/node": "^24.0.0",
146
145
  "rollup-plugins": "1.0.0"
@@ -1,64 +0,0 @@
1
- <?xml version="1.0" encoding="utf-8"?>
2
- <!-- Generator: Adobe Illustrator 23.0.3, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
3
- <svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
4
- viewBox="69 220 1136 205" height="100" xml:space="preserve">
5
- <style type="text/css">
6
- .st0{fill:current;}
7
- .st1{fill:#3E96DB;}
8
- </style>
9
- <g>
10
- <g>
11
- <g>
12
- <path class="st0" d="M448.61,325.58l5.27,10.28h-11.52l-5.27-10.28l-5.51-10.78l-0.25-0.49c-1.81-2.96-5.02-4.94-8.72-4.94
13
- h-10.28v26.49h-10.28v-57.59h36.37c4.28,0,8.15,1.73,10.94,4.53c2.8,2.88,4.53,6.75,4.53,11.02c0,6.25-3.7,11.68-9.05,14.15
14
- c-1.4,0.66-2.88,1.07-4.44,1.23L448.61,325.58z M438.41,299.09c0.74,0,1.48-0.16,2.14-0.49c1.89-0.82,3.13-2.72,3.13-4.77
15
- c0-1.89-0.99-3.21-1.56-3.78c-0.66-0.66-1.89-1.48-3.7-1.48h-26.08v10.61L438.41,299.09z"/>
16
- <path class="st0" d="M518.13,293.74v5.35h37.02v10.28h-37.02v10.86c0,2.88,2.39,5.27,5.27,5.27h42.04v10.28H523.4
17
- c-8.56,0-15.47-6.99-15.47-15.55v-26.49c0-8.56,6.91-15.55,15.47-15.55h42.04v10.28H523.4
18
- C520.52,288.48,518.13,290.86,518.13,293.74z"/>
19
- <path class="st0" d="M674.79,335.78h-11.52L658,325.5l-12.59-24.68l-12.59,24.68l-5.27,10.28h-11.52l5.27-10.28l24.11-47.31
20
- l24.11,47.31L674.79,335.78z"/>
21
- <path class="st0" d="M727.61,306.99c0,10.2,8.31,18.51,18.51,18.51h28.8v10.28h-28.8c-15.88,0-28.8-12.92-28.8-28.8
22
- s12.92-28.8,28.8-28.8h28.8v10.28h-28.8C735.92,288.48,727.61,296.79,727.61,306.99z"/>
23
- <path class="st0" d="M886.32,278.27v10.28h-23.61v47.31h-10.28v-47.31h-23.61v-10.28H886.32z"/>
24
- <path class="st0" d="M940.3,335.78v-57.59h10.28v57.59H940.3z"/>
25
- <path class="st0" d="M1059.85,278.19l-5.27,10.28l-24.11,47.31l-24.11-47.31l-5.27-10.28h11.52l5.27,10.28l12.59,24.68
26
- l12.59-24.68l5.27-10.28H1059.85z"/>
27
- <path class="st0" d="M1117.19,293.74v5.35h37.02v10.28h-37.02v10.86c0,2.88,2.39,5.27,5.27,5.27h42.04v10.28h-42.04
28
- c-8.56,0-15.47-6.99-15.47-15.55v-26.49c0-8.56,6.91-15.55,15.47-15.55h42.04v10.28h-42.04
29
- C1119.58,288.48,1117.19,290.86,1117.19,293.74z"/>
30
- </g>
31
- <g>
32
- <path class="st0" d="M562.83,376.16h9.02c6.88,0,11.55,4.34,11.55,10.7c0,6.36-4.68,10.7-11.55,10.7h-9.02V376.16z M571.67,394.9
33
- c5.29,0,8.68-3.24,8.68-8.04c0-4.8-3.39-8.04-8.68-8.04h-5.78v16.08H571.67z"/>
34
- <path class="st0" d="M625.16,392.21h-11.37l-2.35,5.35h-3.15l9.69-21.4H621l9.72,21.4h-3.21L625.16,392.21z M624.09,389.76
35
- l-4.62-10.48l-4.62,10.48H624.09z"/>
36
- <path class="st0" d="M660.83,378.82h-7.34v-2.66h17.7v2.66h-7.34v18.74h-3.03V378.82z"/>
37
- <path class="st0" d="M710.84,392.21h-11.37l-2.35,5.35h-3.15l9.69-21.4h3.03l9.72,21.4h-3.21L710.84,392.21z M709.77,389.76
38
- l-4.62-10.48l-4.62,10.48H709.77z"/>
39
- <path class="st0" d="M773.57,386.86c0-6.33,4.83-10.94,11.34-10.94c3.3,0,6.17,1.13,8.13,3.33l-1.99,1.93
40
- c-1.65-1.74-3.67-2.54-6.02-2.54c-4.83,0-8.41,3.48-8.41,8.22c0,4.74,3.58,8.22,8.41,8.22c2.35,0,4.37-0.83,6.02-2.57l1.99,1.93
41
- c-1.96,2.2-4.83,3.36-8.16,3.36C778.4,397.8,773.57,393.19,773.57,386.86z"/>
42
- <path class="st0" d="M821.16,376.16h3.06v18.74h11.59v2.66h-14.64V376.16z"/>
43
- <path class="st0" d="M863.07,376.16h3.06v21.4h-3.06V376.16z"/>
44
- <path class="st0" d="M911.82,394.9v2.66h-15.53v-21.4h15.1v2.66h-12.04v6.57h10.73v2.6h-10.73v6.91H911.82z"/>
45
- <path class="st0" d="M958.93,376.16v21.4h-2.51l-12.84-15.96v15.96h-3.06v-21.4h2.51l12.84,15.96v-15.96H958.93z"/>
46
- <path class="st0" d="M993.35,378.82h-7.34v-2.66h17.7v2.66h-7.34v18.74h-3.03V378.82z"/>
47
- </g>
48
- </g>
49
- <g>
50
- <path class="st1" d="M275.11,347.41c-21.84,54.68-67.33,87.9-101.61,74.21c-1.86-0.74-3.65-1.61-5.36-2.59
51
- c31.37,7.82,68.88-18.56,86.22-61.96c18.43-46.13,7.09-94.02-25.32-106.97c-19.2-7.67-41.49-1.36-60.3,14.65
52
- c23.82-34.07,57.23-51.76,83.86-41.13C286.87,237.31,296.95,292.74,275.11,347.41z"/>
53
- <path class="st1" d="M215.54,391.87c-67.76-21.72-114.76-64.06-104.98-94.57c0.53-1.66,1.22-3.24,2.06-4.76
54
- c-3.46,28.09,34.11,62.97,87.9,80.22c57.17,18.33,111.01,9.8,120.25-19.05c5.48-17.09-5.92-37.48-28-55.07
55
- c44.07,22.77,70.76,53.62,63.16,77.33C346.16,406.48,283.3,413.6,215.54,391.87z"/>
56
- <path class="st1" d="M161.63,326.13c37.03-27.02,76.92-35.4,89.08-18.72c0.66,0.91,1.22,1.86,1.7,2.88
57
- c-13.31-12.47-45.72-6.16-75.13,15.29c-31.25,22.79-47.25,54.05-35.75,69.82c6.81,9.34,21.75,11.15,39.29,6.34
58
- c-28.58,14.29-54.78,16.46-64.23,3.51C104.44,388.57,124.6,353.15,161.63,326.13z"/>
59
- <circle class="st1" cx="212.69" cy="340.87" r="11.83"/>
60
- <circle class="st1" cx="143.77" cy="298.83" r="11.83"/>
61
- <circle class="st1" cx="318.02" cy="274.77" r="11.83"/>
62
- </g>
63
- </g>
64
- </svg>
package/typescript.svg DELETED
@@ -1,8 +0,0 @@
1
- <?xml version="1.0" encoding="UTF-8"?>
2
- <svg width="21px" height="21px" viewBox="0 0 256 256" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" preserveAspectRatio="xMidYMid">
3
- <g>
4
- <polygon fill="#007ACC" transform="translate(128.000000, 128.000000) scale(1, -1) translate(-128.000000, -128.000000) " points="0 128 0 0 128 0 256 0 256 128 256 256 128 256 0 256"></polygon>
5
- <path d="M146.658132,223.436863 L146.739401,212.953054 L130.079084,212.953054 L113.418767,212.953054 L113.418767,165.613371 L113.418767,118.273689 L101.63464,118.273689 L89.8505126,118.273689 L89.8505126,165.613371 L89.8505126,212.953054 L73.1901951,212.953054 L56.5298776,212.953054 L56.5298776,223.233689 C56.5298776,228.922577 56.6517824,233.676863 56.8143221,233.798768 C56.9362269,233.961308 77.2130522,234.042577 101.797179,234.001943 L146.536227,233.880038 L146.658132,223.436863 Z" fill="#FFFFFF" transform="translate(101.634640, 176.142993) rotate(-180.000000) translate(-101.634640, -176.142993) "></path>
6
- <path d="M206.566631,234.272145 C213.068219,232.646748 218.025679,229.761668 222.57679,225.048018 C224.933616,222.528653 228.428219,217.936907 228.712663,216.839764 C228.793933,216.514684 217.659965,209.037859 210.914568,204.852462 C210.670758,204.689922 209.69552,205.74643 208.598377,207.371827 C205.306949,212.166748 201.852981,214.239129 196.570441,214.604843 C188.809171,215.133097 183.811076,211.069605 183.851711,204.283573 C183.851711,202.292462 184.136155,201.114049 184.948854,199.488653 C186.65552,195.953414 189.825044,193.840399 199.7806,189.533097 C218.106949,181.649922 225.949489,176.448653 230.825679,169.053097 C236.270758,160.804208 237.489806,147.638494 233.792028,137.845478 C229.728536,127.199129 219.651076,119.966113 205.469489,117.568653 C201.080917,116.796589 190.678377,116.918494 185.964727,117.771827 C175.684092,119.600399 165.931711,124.679764 159.917743,131.343891 C157.560917,133.944526 152.969171,140.730557 153.253616,141.218176 C153.37552,141.380716 154.432028,142.030875 155.610441,142.721668 C156.748219,143.371827 161.05552,145.850557 165.119012,148.207383 L172.473933,152.474049 L174.01806,150.198494 C176.171711,146.907065 180.885362,142.396589 183.729806,140.893097 C191.897425,136.585795 203.112663,137.195319 208.639012,142.15278 C210.995838,144.30643 211.971076,146.541351 211.971076,149.83278 C211.971076,152.799129 211.605362,154.099446 210.061235,156.334367 C208.070123,159.178811 204.006631,161.576272 192.466314,166.574367 C179.259965,172.263256 173.571076,175.798494 168.369806,181.406113 C165.362822,184.656907 162.518377,189.858176 161.339965,194.206113 C160.364727,197.822621 160.120917,206.884208 160.892981,210.541351 C163.61552,223.300716 173.245996,232.199764 187.143139,234.841034 C191.653616,235.694367 202.137425,235.369287 206.566631,234.272145 Z" fill="#FFFFFF" transform="translate(194.578507, 176.190240) scale(1, -1) translate(-194.578507, -176.190240) "></path>
7
- </g>
8
- </svg>