@magnetarjs/core
Advanced tools
Comparing version 0.0.22 to 0.1.0
@@ -425,3 +425,6 @@ 'use strict'; | ||
if (actionName === 'fetch') { | ||
if (payload && payload.ifUnfetched === true) { | ||
const optimisticFetch = !payload || | ||
!Object.hasOwnProperty.call(payload || {}, 'force') || | ||
(payload === null || payload === void 0 ? void 0 : payload.force) === false; | ||
if (optimisticFetch) { | ||
const localStoreName = moduleConfig.localStoreName || globalConfig.localStoreName; | ||
@@ -428,0 +431,0 @@ // the local store successfully returned a fetch response based on already fetched data |
@@ -421,3 +421,6 @@ import { merge, mergeAndConcat } from 'merge-anything'; | ||
if (actionName === 'fetch') { | ||
if (payload && payload.ifUnfetched === true) { | ||
const optimisticFetch = !payload || | ||
!Object.hasOwnProperty.call(payload || {}, 'force') || | ||
(payload === null || payload === void 0 ? void 0 : payload.force) === false; | ||
if (optimisticFetch) { | ||
const localStoreName = moduleConfig.localStoreName || globalConfig.localStoreName; | ||
@@ -424,0 +427,0 @@ // the local store successfully returned a fetch response based on already fetched data |
@@ -30,6 +30,20 @@ import { O } from 'ts-toolbelt'; | ||
* Fetches document(s) and adds the data to your local store's state. | ||
* Fetch is optimistic by default — if it can find the doc's data in your local state, it will return that and prevent any remote fetches. | ||
* You can force a re-fetch by passing `{ force: true }` | ||
* @returns the document(s) data that was fetched. If you need to access other metadata that was retrieved during fetching, you can use `modifyReadResponse.added`. | ||
* @example | ||
* const bulbasaur = magnetar.collection('pokedex').doc('001') | ||
* bulbasaur.fetch() // does nothing if already fetched once | ||
* @example | ||
* const bulbasaur = magnetar.collection('pokedex').doc('001') | ||
* bulbasaur.fetch({ force: true }) // makes API call to remote store | ||
* @example | ||
* const pokedex = magnetar.collection('pokedex') | ||
* pokedex.fetch() // does nothing if already fetched once | ||
* @example | ||
* const pokedex = magnetar.collection('pokedex') | ||
* pokedex.fetch({ force: true }) // makes API call to remote store | ||
*/ | ||
export declare type MagnetarFetchAction<DocDataType extends Record<string, any> = Record<string, any>, calledFrom extends 'collection' | 'doc' = 'collection' | 'doc'> = (payload?: { | ||
ifUnfetched?: boolean; | ||
force?: boolean; | ||
} | Record<string, any> | void, actionConfig?: ActionConfig) => Promise<calledFrom extends 'collection' ? Map<string, DocDataType> : DocDataType>; | ||
@@ -36,0 +50,0 @@ /** |
@@ -6,9 +6,9 @@ export declare type StoreName = string; | ||
/** | ||
* In case the doc was pulled from cache with `fetch({ ifUnfetched: true })` then `exists` will be `'unknown'` | ||
* In case the doc was returned optimisticly (from the local store data) then `exists` will be `'unknown'` | ||
*/ | ||
exists: boolean | 'unknown'; | ||
/** | ||
* In case the doc was pulled from cache with `fetch({ ifUnfetched: true })` then `metadata` will be absent | ||
* In case the doc was returned optimisticly (from the local store data) then `metadata` will be absent | ||
*/ | ||
metadata?: Record<string, any>; | ||
}; |
@@ -77,3 +77,3 @@ import { O } from 'ts-toolbelt'; | ||
payload: { | ||
ifUnfetched?: boolean; | ||
force?: boolean; | ||
} | Record<string, any> | void; | ||
@@ -80,0 +80,0 @@ }>; |
{ | ||
"name": "@magnetarjs/core", | ||
"version": "0.0.22", | ||
"version": "0.1.0", | ||
"sideEffects": false, | ||
@@ -26,3 +26,3 @@ "description": "Magnetar core library.", | ||
"devDependencies": { | ||
"@magnetarjs/test-utils": "^0.0.12", | ||
"@magnetarjs/test-utils": "^0.1.0", | ||
"ava": "^3.15.0" | ||
@@ -71,3 +71,3 @@ }, | ||
}, | ||
"gitHead": "6f7e1b9b3440de3408be14439a31a9a4967377fd" | ||
"gitHead": "d5d2a2b58bdf4d7950f2532f0ad0580730fde5bd" | ||
} |
@@ -168,3 +168,7 @@ /* eslint-disable no-inner-declarations */ | ||
if (actionName === 'fetch') { | ||
if (payload && payload.ifUnfetched === true) { | ||
const optimisticFetch = | ||
!payload || | ||
!Object.hasOwnProperty.call(payload || {}, 'force') || | ||
payload?.force === false | ||
if (optimisticFetch) { | ||
const localStoreName = moduleConfig.localStoreName || globalConfig.localStoreName | ||
@@ -171,0 +175,0 @@ // the local store successfully returned a fetch response based on already fetched data |
@@ -40,3 +40,17 @@ import { O } from 'ts-toolbelt' | ||
* Fetches document(s) and adds the data to your local store's state. | ||
* Fetch is optimistic by default — if it can find the doc's data in your local state, it will return that and prevent any remote fetches. | ||
* You can force a re-fetch by passing `{ force: true }` | ||
* @returns the document(s) data that was fetched. If you need to access other metadata that was retrieved during fetching, you can use `modifyReadResponse.added`. | ||
* @example | ||
* const bulbasaur = magnetar.collection('pokedex').doc('001') | ||
* bulbasaur.fetch() // does nothing if already fetched once | ||
* @example | ||
* const bulbasaur = magnetar.collection('pokedex').doc('001') | ||
* bulbasaur.fetch({ force: true }) // makes API call to remote store | ||
* @example | ||
* const pokedex = magnetar.collection('pokedex') | ||
* pokedex.fetch() // does nothing if already fetched once | ||
* @example | ||
* const pokedex = magnetar.collection('pokedex') | ||
* pokedex.fetch({ force: true }) // makes API call to remote store | ||
*/ | ||
@@ -47,3 +61,3 @@ export type MagnetarFetchAction< | ||
> = ( | ||
payload?: { ifUnfetched?: boolean } | Record<string, any> | void, | ||
payload?: { force?: boolean } | Record<string, any> | void, | ||
actionConfig?: ActionConfig | ||
@@ -50,0 +64,0 @@ ) => Promise<calledFrom extends 'collection' ? Map<string, DocDataType> : DocDataType> |
@@ -7,9 +7,9 @@ export type StoreName = string | ||
/** | ||
* In case the doc was pulled from cache with `fetch({ ifUnfetched: true })` then `exists` will be `'unknown'` | ||
* In case the doc was returned optimisticly (from the local store data) then `exists` will be `'unknown'` | ||
*/ | ||
exists: boolean | 'unknown' | ||
/** | ||
* In case the doc was pulled from cache with `fetch({ ifUnfetched: true })` then `metadata` will be absent | ||
* In case the doc was returned optimisticly (from the local store data) then `metadata` will be absent | ||
*/ | ||
metadata?: Record<string, any> | ||
} |
@@ -97,3 +97,3 @@ import { O } from 'ts-toolbelt' | ||
*/ | ||
payload: { ifUnfetched?: boolean } | Record<string, any> | void | ||
payload: { force?: boolean } | Record<string, any> | void | ||
} | ||
@@ -136,17 +136,16 @@ > | ||
export type PluginDeletePropActionPayload< | ||
SpecificPluginModuleConfig = PluginModuleConfig | ||
> = O.Patch< | ||
PluginActionPayloadBase<SpecificPluginModuleConfig>, | ||
{ | ||
/** | ||
* Whatever payload was passed to the action that was triggered | ||
*/ | ||
payload: string | string[] | ||
/** | ||
* docId must be provided | ||
*/ | ||
docId: string | ||
} | ||
> | ||
export type PluginDeletePropActionPayload<SpecificPluginModuleConfig = PluginModuleConfig> = | ||
O.Patch< | ||
PluginActionPayloadBase<SpecificPluginModuleConfig>, | ||
{ | ||
/** | ||
* Whatever payload was passed to the action that was triggered | ||
*/ | ||
payload: string | string[] | ||
/** | ||
* docId must be provided | ||
*/ | ||
docId: string | ||
} | ||
> | ||
/** | ||
@@ -153,0 +152,0 @@ * Should handle 'deleteProp' for docs. (use `getCollectionPathDocIdEntry(modulePath)` helper) |
@@ -13,3 +13,3 @@ import test from 'ava' | ||
try { | ||
await pokedexModule.fetch() | ||
await pokedexModule.fetch({ force: true }) | ||
} catch (error) { | ||
@@ -28,3 +28,3 @@ t.fail(error) | ||
try { | ||
await trainerModule.fetch() | ||
await trainerModule.fetch({ force: true }) | ||
} catch (error) { | ||
@@ -40,3 +40,3 @@ t.fail(error) | ||
const queryModuleRef = pokedexModule.where('name', '==', 'Flareon') | ||
await queryModuleRef.fetch() | ||
await queryModuleRef.fetch({ force: true }) | ||
const actual = [...queryModuleRef.data.values()] | ||
@@ -54,3 +54,3 @@ const expected = [pokedex(136)] | ||
const queryModuleRef = pokedexModule.where('name', '!=', 'Bulbasaur').limit(1) | ||
await queryModuleRef.fetch() | ||
await queryModuleRef.fetch({ force: true }) | ||
const actual = [...queryModuleRef.data.values()] | ||
@@ -68,3 +68,3 @@ const expected = [pokedex(2)] | ||
const queryModuleRef = pokedexModule.where('base.HP', '==', 10) | ||
await queryModuleRef.fetch() | ||
await queryModuleRef.fetch({ force: true }) | ||
const actual = [...queryModuleRef.data.values()] | ||
@@ -82,3 +82,3 @@ const expected = [pokedex(50)] | ||
const queryModuleRef = pokedexModule.where('base.HP', '<', 11) | ||
await queryModuleRef.fetch() | ||
await queryModuleRef.fetch({ force: true }) | ||
const actual = [...queryModuleRef.data.values()] | ||
@@ -96,3 +96,3 @@ const expected = [pokedex(50)] | ||
const queryModuleRef = pokedexModule.where('base.HP', '<=', 10) | ||
await queryModuleRef.fetch() | ||
await queryModuleRef.fetch({ force: true }) | ||
const actual = [...queryModuleRef.data.values()] | ||
@@ -110,3 +110,3 @@ const expected = [pokedex(50)] | ||
const queryModuleRef = pokedexModule.where('base.HP', '>', 249) | ||
await queryModuleRef.fetch() | ||
await queryModuleRef.fetch({ force: true }) | ||
const actual = [...queryModuleRef.data.values()] | ||
@@ -124,3 +124,3 @@ const expected = [pokedex(113)] | ||
const queryModuleRef = pokedexModule.where('base.HP', '>=', 250) | ||
await queryModuleRef.fetch() | ||
await queryModuleRef.fetch({ force: true }) | ||
const actual = [...queryModuleRef.data.values()] | ||
@@ -138,3 +138,3 @@ const expected = [pokedex(113)] | ||
const queryModuleRef = pokedexModule.where('type', 'array-contains', 'Steel') | ||
await queryModuleRef.fetch() | ||
await queryModuleRef.fetch({ force: true }) | ||
const actual = [...queryModuleRef.data.values()] | ||
@@ -152,3 +152,3 @@ const expected = [pokedex(81), pokedex(82)] | ||
const queryModuleRef = pokedexModule.where('name', 'in', ['Vaporeon', 'Jolteon', 'Flareon']) | ||
await queryModuleRef.fetch() | ||
await queryModuleRef.fetch({ force: true }) | ||
const actual = [...queryModuleRef.data.values()] | ||
@@ -168,3 +168,3 @@ const expected = [pokedex(134), pokedex(135), pokedex(136)] | ||
.where('name', 'not-in', [pokedex(81).name, pokedex(82).name, pokedex(91).name]) | ||
await queryModuleRef.fetch() | ||
await queryModuleRef.fetch({ force: true }) | ||
const actual = [...queryModuleRef.data.values()] | ||
@@ -182,3 +182,3 @@ const expected = [pokedex(87), pokedex(124), pokedex(131), pokedex(144)] | ||
const queryModuleRef = pokedexModule.where('type', 'array-contains-any', ['Steel', 'Ice']) | ||
await queryModuleRef.fetch() | ||
await queryModuleRef.fetch({ force: true }) | ||
const actual = [...queryModuleRef.data.values()] | ||
@@ -206,3 +206,3 @@ const expected = [ | ||
.where('base.Speed', '>=', 100) | ||
await queryModuleRef.fetch() | ||
await queryModuleRef.fetch({ force: true }) | ||
const actual = [...queryModuleRef.data.values()] | ||
@@ -223,3 +223,3 @@ const expected = [pokedex(6), pokedex(38), pokedex(78)] | ||
.orderBy('name', 'desc') | ||
await queryModuleRef.fetch() | ||
await queryModuleRef.fetch({ force: true }) | ||
// Rapidash 78 | ||
@@ -240,3 +240,3 @@ // Ninetales 38 | ||
const queryModuleRef = pokedexModule.limit(10) | ||
await queryModuleRef.fetch() | ||
await queryModuleRef.fetch({ force: true }) | ||
const actual = [...queryModuleRef.data.values()] | ||
@@ -243,0 +243,0 @@ const expected = [ |
@@ -111,3 +111,3 @@ import test from 'ava' | ||
try { | ||
const result = await pokedexModule.fetch() | ||
const result = await pokedexModule.fetch({ force: true }) | ||
t.deepEqual(result.get('1'), pokedex(1)) | ||
@@ -128,3 +128,3 @@ t.deepEqual(result.get('136'), pokedex(136)) | ||
try { | ||
const result = await trainerModule.fetch() | ||
const result = await trainerModule.fetch({ force: true }) | ||
t.deepEqual(result, { name: 'Luca', age: 10, dream: 'job' }) | ||
@@ -143,3 +143,3 @@ } catch (error) { | ||
const queryModuleRef = pokedexModuleWithQuery | ||
await queryModuleRef.fetch() | ||
await queryModuleRef.fetch({ force: true }) | ||
t.deepEqual([...queryModuleRef.data.values()], [pokedex(136)]) | ||
@@ -146,0 +146,0 @@ } catch (error) { |
@@ -135,6 +135,6 @@ import test from 'ava' | ||
const { pokedexModule } = createMagnetarInstance() | ||
const getPayload = { shouldFail: 'local' } | ||
const fetchPayload = { shouldFail: 'local', force: true } | ||
t.deepEqual(pokedexModule.data.get('1'), pokedex(1)) | ||
try { | ||
await pokedexModule.fetch(getPayload, { | ||
await pokedexModule.fetch(fetchPayload, { | ||
onError: 'stop', | ||
@@ -144,3 +144,3 @@ on: { | ||
if (storeName === 'local') { | ||
t.deepEqual(payload, getPayload) | ||
t.deepEqual(payload, fetchPayload) | ||
} | ||
@@ -154,3 +154,3 @@ }, | ||
} catch (error) { | ||
t.deepEqual(error, { message: 'failed', payload: getPayload }) | ||
t.deepEqual(error, { message: 'failed', payload: fetchPayload }) | ||
} | ||
@@ -162,7 +162,7 @@ t.deepEqual(pokedexModule.data.get('1'), pokedex(1)) | ||
const { pokedexModule } = createMagnetarInstance() | ||
const getPayload = { shouldFail: 'remote' } | ||
const fetchPayload = { shouldFail: 'remote', force: true } | ||
t.deepEqual(pokedexModule.data.get('1'), pokedex(1)) | ||
let result: any | ||
try { | ||
result = await pokedexModule.fetch(getPayload, { | ||
result = await pokedexModule.fetch(fetchPayload, { | ||
onError: 'stop', | ||
@@ -173,3 +173,3 @@ on: { | ||
if (storeName === 'remote') { | ||
t.deepEqual(payload, getPayload) | ||
t.deepEqual(payload, fetchPayload) | ||
} | ||
@@ -180,3 +180,3 @@ }, | ||
} catch (error) { | ||
t.deepEqual(error, { message: 'failed', payload: getPayload }) | ||
t.deepEqual(error, { message: 'failed', payload: fetchPayload }) | ||
} | ||
@@ -189,6 +189,6 @@ t.deepEqual(result, undefined) | ||
const { pokedexModule } = createMagnetarInstance() | ||
const getPayload = { shouldFail: 'local' } | ||
const fetchPayload = { shouldFail: 'local', force: true } | ||
t.deepEqual(pokedexModule.data.get('1'), pokedex(1)) | ||
try { | ||
const result = await pokedexModule.fetch(getPayload, { | ||
const result = await pokedexModule.fetch(fetchPayload, { | ||
onError: 'continue', | ||
@@ -198,3 +198,3 @@ on: { | ||
if (storeName === 'local') { | ||
t.deepEqual(payload, getPayload) | ||
t.deepEqual(payload, fetchPayload) | ||
} | ||
@@ -205,3 +205,3 @@ if (storeName === 'remote') t.fail() | ||
if (storeName === 'remote') { | ||
t.deepEqual(payload, getPayload) | ||
t.deepEqual(payload, fetchPayload) | ||
// even though the local store failed, we got the result of the remote store | ||
@@ -208,0 +208,0 @@ t.deepEqual((result as FetchResponse).docs.length, 151) |
@@ -11,3 +11,3 @@ import test from 'ava' | ||
// try { | ||
// const result = await pokedexModule.fetch() | ||
// const result = await pokedexModule.fetch({ force: true }) | ||
// t.deepEqual(result.get('1'), pokedex(1)) | ||
@@ -35,3 +35,3 @@ // t.deepEqual(result.get('136'), pokedex(136)) | ||
// fetch twice at the same time | ||
await Promise.all([trainerModule.fetch(), trainerModule.fetch()]) | ||
await Promise.all([trainerModule.fetch({ force: true }), trainerModule.fetch({ force: true })]) | ||
} catch (error) { | ||
@@ -46,3 +46,3 @@ t.fail(error) | ||
// fetch twice again the same time | ||
await Promise.all([trainerModule.fetch(), trainerModule.fetch()]) | ||
await Promise.all([trainerModule.fetch({ force: true }), trainerModule.fetch({ force: true })]) | ||
} catch (error) { | ||
@@ -58,3 +58,3 @@ t.fail(error) | ||
test('read: fetch (document) - ifUnfetched', async (t) => { | ||
test('read: fetch (document) - optimistic fetch by default', async (t) => { | ||
// get resolves once all stores have given a response with data | ||
@@ -75,6 +75,3 @@ const storeNames: string[] = [] | ||
// fetch twice at the same time | ||
await Promise.all([ | ||
trainerModule.fetch({ ifUnfetched: true }), | ||
trainerModule.fetch({ ifUnfetched: true }), | ||
]) | ||
await Promise.all([trainerModule.fetch({ force: true }), trainerModule.fetch({ force: true })]) | ||
} catch (error) { | ||
@@ -89,6 +86,3 @@ t.fail(error) | ||
// fetch twice again the same time | ||
await Promise.all([ | ||
trainerModule.fetch({ ifUnfetched: true }), | ||
trainerModule.fetch({ ifUnfetched: true }), | ||
]) | ||
await Promise.all([trainerModule.fetch(), trainerModule.fetch()]) | ||
} catch (error) { | ||
@@ -95,0 +89,0 @@ t.fail(error) |
@@ -19,11 +19,14 @@ import test from 'ava' | ||
let payloadInSuccessEvent: any | ||
const result = await magnetar.collection('pokedex').fetch(undefined, { | ||
on: { | ||
success: ({ payload }) => { | ||
payloadInSuccessEvent = payload | ||
const result = await magnetar.collection('pokedex').fetch( | ||
{ force: true }, | ||
{ | ||
on: { | ||
success: ({ payload }) => { | ||
payloadInSuccessEvent = payload | ||
}, | ||
}, | ||
}, | ||
}) | ||
} | ||
) | ||
// the remote result SHOULD HAVE the applied defaults | ||
t.deepEqual(payloadInSuccessEvent, { auth: 'Bearer 123123' }) | ||
t.deepEqual(payloadInSuccessEvent, { auth: 'Bearer 123123', force: true }) | ||
t.deepEqual(result.get('136'), { ...pokedex(136), seen: true }) | ||
@@ -105,11 +108,14 @@ } catch (error) { | ||
let payloadInSuccessEvent: any | ||
const result = await pokedexModule.fetch(undefined, { | ||
on: { | ||
success: ({ payload }) => { | ||
payloadInSuccessEvent = payload | ||
const result = await pokedexModule.fetch( | ||
{ force: true }, | ||
{ | ||
on: { | ||
success: ({ payload }) => { | ||
payloadInSuccessEvent = payload | ||
}, | ||
}, | ||
}, | ||
}) | ||
} | ||
) | ||
// the remote result SHOULD HAVE the applied defaults | ||
t.deepEqual(payloadInSuccessEvent, { auth: 'Bearer 123123' }) | ||
t.deepEqual(payloadInSuccessEvent, { auth: 'Bearer 123123', force: true }) | ||
t.deepEqual(result.get('136'), { ...pokedex(136), seen: true }) | ||
@@ -186,3 +192,3 @@ } catch (error) { | ||
const result = await pokedexModule.fetch( | ||
{}, | ||
{ force: true }, | ||
{ | ||
@@ -201,3 +207,3 @@ modifyPayloadOn: { read: addToken }, | ||
t.deepEqual(result.get('136'), { ...pokedex(136), seen: true }) | ||
t.deepEqual(payloadInSuccessEvent, { auth: 'Bearer 123123' }) | ||
t.deepEqual(payloadInSuccessEvent, { auth: 'Bearer 123123', force: true }) | ||
} catch (error) { | ||
@@ -204,0 +210,0 @@ t.fail(error) |
265865
5975