diff --git a/CHANGELOG.md b/CHANGELOG.md index 47d07196..ed5a5956 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,6 +7,40 @@ - Magnetar is now ESM only. This means you need to use `import` instead of `require`. - Magnetar now requires Node v18+. - `@magnetarjs/plugin-vue2` was removed. +- `local` store plugin now needs to be called `cache` + +Before: + +```js +import { CreatePlugin as PluginVue3 } from '@magnetarjs/plugin-vue3' + +const local = PluginVue3({ generateRandomId }) +const remote = ... + +export const magnetar = Magnetar({ + localStoreName: 'local', + stores: { local, remote }, + executionOrder: { + read: ['local', 'remote'], + write: ['local', 'remote'], + // ... +``` + +After: + +```js +import { CreatePlugin as PluginVue3 } from '@magnetarjs/plugin-vue3' + +const cache = PluginVue3({ generateRandomId }) +const remote = ... + +export const magnetar = Magnetar({ + stores: { cache, remote }, + executionOrder: { + read: ['cache', 'remote'], + write: ['cache', 'remote'], + // ... +``` ## v0.4.0 @@ -30,7 +64,7 @@ firebase.initializeApp({ // initialise PluginFirestore import { CreatePlugin as PluginFirestore } from '@magnetarjs/plugin-firestore' -const remote = PluginFirestore.CreatePlugin({ firebaseInstance: firebase }) +const remote = PluginFirestore({ firebaseInstance: firebase }) ``` After: @@ -48,7 +82,7 @@ const db = getFirestore(firebaseApp) // initialise PluginFirestore import { CreatePlugin as PluginFirestore } from '@magnetarjs/plugin-firestore' -const remote = PluginFirestore.CreatePlugin({ db }) +const remote = PluginFirestore({ db }) ``` ## v0.3.0 diff --git a/README.md b/README.md index 06199c6e..b14deb4d 100644 --- a/README.md +++ b/README.md @@ -2,7 +2,7 @@ # Magnetar 🌟 -A framework-agnostic syncing solution that auto-connects any DB/API with your local data store and has optimistic-UI built in. +A framework-agnostic syncing solution that auto-connects any DB/API with your local cache data store and has optimistic-UI built in. ```sh npm i magnetar diff --git a/docs/docs-main/about/index.md b/docs/docs-main/about/index.md index 1897c507..b5e9c474 100644 --- a/docs/docs-main/about/index.md +++ b/docs/docs-main/about/index.md @@ -4,15 +4,15 @@ - Magnetar is a **_state management_** library.
A library that brings a simple syntax for reading and writing data and allows you to easily work with this data in your app like a global store. -- Magnetar has 2-way sync **_database integration_** for Google Firestore (and others coming). You do not need to learn to work with the database SDK.
β€” Whenever you modify data in your local store, Magnetar will update your database on the server.
β€” Whenever the server has changes, Magnetar will reflect those in your local store. +- Magnetar has 2-way sync **_database integration_** for Google Firestore (and others coming). You do not need to learn to work with the database SDK.
β€” Whenever you modify data in your local cache store, Magnetar will update your database on the server.
β€” Whenever the server has changes, Magnetar will reflect those in your local cache store. -- Magnetar's main focus is to be the **_local representation of your database_**. +- Magnetar's main focus is to be the **_cache as representation of your database_**. - Magnetar is framework-agnostic. It can be used with Vue/React/Angular/Vanilla JS projects. - Magnetar is modular. It works with plugins that provide capabilities so you can only include what you actually need. -- Magnetar has plugins for Vue 2 & Vue 3 that offer **_built-in reactivity_**.
Just like Vuex, displaying data in Vue just works as you would expect and is reactive on local/server changes. (Magnetar does not rely on Vuex) +- Magnetar has plugins for Vue 2 & Vue 3 that offer **_built-in reactivity_**.
Just like Vuex, displaying data in Vue just works as you would expect and is reactive on local cache/server changes. (Magnetar does not rely on Vuex) @@ -34,12 +34,12 @@ Here is a hypothetical example of a To Do list powered by Magnetar that uses the onCreated(() => { // fetch all documents from Firestore & continue to watch for any changes - // will keep local data up to date when changes on database occur + // will keep cached data up to date when changes on database occur todoItemsModule.stream() }) /** - * Displays the local data of your module (data comes in via the stream) + * Displays the cached data of your module (data comes in via the stream) */ const items = computed(() => { // in magnetar, the collection `.data` is a JS Map @@ -47,7 +47,7 @@ Here is a hypothetical example of a To Do list powered by Magnetar that uses the }) /** - * Adds a new item to the local data & makes API call to Firestore + * Adds a new item to the cached data & makes API call to Firestore * UI is reflected automatically */ function addItem(newData) { @@ -55,7 +55,7 @@ Here is a hypothetical example of a To Do list powered by Magnetar that uses the } /** - * Edits an item in the local data & makes API call to Firestore + * Edits an item in the cached data & makes API call to Firestore * UI is reflected automatically */ function editItem(id, newData) { @@ -63,7 +63,7 @@ Here is a hypothetical example of a To Do list powered by Magnetar that uses the } /** - * Deletes an item from the local data & makes API call to Firestore + * Deletes an item from the cached data & makes API call to Firestore * UI is reflected automatically */ function deleteItem(id) { diff --git a/docs/docs-main/concepts/index.md b/docs/docs-main/concepts/index.md index a9a90151..0acfb09c 100644 --- a/docs/docs-main/concepts/index.md +++ b/docs/docs-main/concepts/index.md @@ -6,21 +6,21 @@ The idea of Magnetar is that you only need to learn how to work with one syntax In most cases you use Magnetar with two store plugins installed: -- A "local" store plugin, for the data you need cached while using the app. (like Vuex or a simple global object) +- A "cache" store plugin, for the data you need cached while using the app. (like Vuex or a simple global object) - A "remote" store plugin, for the remote data stored. (like Firestore or any other database) -**When reading data:** the _remote_ store will fetch the data; the _local_ store will then add that data for you, so you can easily access and use it in your app. +**When reading data:** the _remote_ store will fetch the data; the _cache_ store will then add that data for you, so you can easily access and use it in your app. -**When writing data:** the _local_ store will save your changes in its cache; the _remote_ will then make an API call to your database. (you can also flip this around, so the local store is only updated after the remote one) +**When writing data:** the _cache_ store will save your changes in its cache; the _remote_ will then make an API call to your database. (you can also flip this around, so the local cache store is only updated after the remote one) ### List of Plugins Available store plugins - Firestore (remote) -- Simple Store (local) -- Vue 2 (local) -- Vue 3 (local) +- Simple Store (cache) +- Vue 2 (cache) +- Vue 3 (cache) Planned store plugins (TBD) @@ -75,6 +75,6 @@ const myDoc = magnetar.collection('some-collection').doc('some-doc') ### The Purpose of a Collection/Doc Path -Each collection and doc need to have a _path_ that points to that collection. The purpose of this path is to become the identifier where your local store will save your documents. +Each collection and doc need to have a _path_ that points to that collection. The purpose of this path is to become the identifier where your local cache store will save your documents. By default a _path_ is the same _path_ to the data in your remote store. Eg. a doc module with path `users/abc123` will represent the same document as in your database at that path. diff --git a/docs/docs-main/faq/index.md b/docs/docs-main/faq/index.md index 43e403c4..753eeef8 100644 --- a/docs/docs-main/faq/index.md +++ b/docs/docs-main/faq/index.md @@ -4,11 +4,11 @@ TLDR; Firestore SDK **charges you on every read**. Magnetar does cache management for free. -Firestore has its own implementation of locally cached data. However, every time you access that data it will also double check if the data is up to date with the server. This means that you are charged money every time you simply want to use your data locally. +Firestore has its own implementation of locally cached data. However, every time you access that data it will also double check if the data is up to date with the server. This means that you are charged money every time you simply want to use your cached data locally. When you think about this, most devs end up saving the data in some sort of object or in a state management library Vue data or Vuex/Redux. This means that you then have to add write logic to write the data back to the database either way. -Magnetar's goal is to replace all this logic you need to write yourself to read and write data, providing its own local store so you can more easily prevent Firebase from charging you when reading docs you already fetched. +Magnetar's goal is to replace all this logic you need to write yourself to read and write data, providing its own local cache store so you can more easily prevent Firebase from charging you when reading docs you already fetched. ## Why did you build Magnetar? @@ -26,13 +26,13 @@ I'm the creator of [Vuex Easy Firestore](https://mesqueeb.github.io/vuex-easy-fi -## Why the concept of local/remote store plugins? +## Why the concept of cache/remote store plugins? I wanted Magnetar to be compatible with a wide variety of use cases and projects. When it comes to remote stores, I wanted to be able to use Firestore but competitors like Fauna and Supabase also looked interesting. I didn't want to limit the future to just Firestore. -When it comes to local stores, there are different approaches again. A simple store that just works with a Map or Object is tricky to make reactive out of the box for Vue projects. Adding reactivity out of the box needed a different implementation for Vue 2 and Vue 3. Again, not to limit the future and prevent code bloat, using a similar plugin system for local stores was the way to go. +When it comes to local cache stores, there are different approaches again. A simple store that just works with a Map or Object is tricky to make reactive out of the box for Vue projects. Adding reactivity out of the box needed a different implementation for Vue 2 and Vue 3. Again, not to limit the future and prevent code bloat, using a similar plugin system for local cache stores was the way to go. Finally I also like the idea of having your own data caching options. I'm planning to also add store plugins that work with localStorage, indexedDB, etc. All of this meant that a store plugin system was the best choice! diff --git a/docs/docs-main/hooks-and-events/index.md b/docs/docs-main/hooks-and-events/index.md index 96e2daeb..99d96c12 100644 --- a/docs/docs-main/hooks-and-events/index.md +++ b/docs/docs-main/hooks-and-events/index.md @@ -121,7 +121,7 @@ pokedexModule.doc('abc').insert({ name: 'Unown', type: undefined }) ### Remove Certain Values -Some remote stores (eg. Firestore) do not allow the value `undefined`. In this case you can set up a hook that completely removes `undefined` before the data is sent to your local and remote stores. For this example we're going to use a tiny helper utility I wrote called [remove-anything](https://github.com/mesqueeb/remove-anything). +Some remote stores (eg. Firestore) do not allow the value `undefined`. In this case you can set up a hook that completely removes `undefined` before the data is sent to your cache and remote stores. For this example we're going to use a tiny helper utility I wrote called [remove-anything](https://github.com/mesqueeb/remove-anything). ```js import { removeProp } from 'remove-anything' @@ -172,7 +172,7 @@ The config you can pass for `modifyReadResponseOn` is an object with the followi - `modified` β€” triggered every time data is modified on your remote store (the server), during the method `stream` - `removed` β€” triggered every time data is removed from your remote store (the server) OR if a document satisfy the query filters of your module anymore, during the method `stream` -Your `modifyReadResponseOn`-function will receive a `payload` as param which is the _incoming data_ and **must** return that `payload` again. The main purpose is that you can modify the payload before it is added to your local store. +Your `modifyReadResponseOn`-function will receive a `payload` as param which is the _incoming data_ and **must** return that `payload` again. The main purpose is that you can modify the payload before it is added to your local cache store. Here we give some examples with common use cases. @@ -205,7 +205,7 @@ pokedexModule.stream() > documentation below is still WIP -> hint: returning `undefined` will discard the document change and do nothing with the local store +> hint: returning `undefined` will discard the document change and do nothing with the local cache store ### Accessing Metadata when Reading Data diff --git a/docs/docs-main/module-setup/index.md b/docs/docs-main/module-setup/index.md index f5f2e223..0b9d5996 100644 --- a/docs/docs-main/module-setup/index.md +++ b/docs/docs-main/module-setup/index.md @@ -52,7 +52,7 @@ It's also become clear that these modules might be better off each having their > Why do you need to define both `modifyPayloadOn.insert` and `modifyReadResponseOn.added` ? -- `modifyPayloadOn.insert` β€” is triggered every time you write data locally (which is then synced to the server with those default values) +- `modifyPayloadOn.insert` β€” is triggered every time you write data locally to cache (which is then synced to the server with those default values) - `modifyReadResponseOn.added` β€” is triggered every time data comes in from your remote store (the server) To learn more about these functions and other possibilities read [Hooks and Events](../hooks-and-events/). @@ -96,7 +96,7 @@ import { pokedexModule } from 'pokedexModule.js' // making a read request will retrieve docs with the fixed query enabled: await pokedexModule.fetch() - // accessing local data will also filter on just docs as per the fixed query: + // accessing cached data will also filter on just docs as per the fixed query: pokedexModule.data.values() })() ``` @@ -167,7 +167,7 @@ async function searchPokemon(type) { } ``` -As you can see in the example, using a query in Magnetar is very powerful because it will not only query your read requests to the remote store, but can also apply that same query when reading your local data. +As you can see in the example, using a query in Magnetar is very powerful because it will not only query your read requests to the remote store, but can also apply that same query when reading your cached data. You can find more information on reading data at [Read Data](../read-data/#query-data-filter-order-by-limit). diff --git a/docs/docs-main/plugins/index.md b/docs/docs-main/plugins/index.md index b63c50ea..484fbf9e 100644 --- a/docs/docs-main/plugins/index.md +++ b/docs/docs-main/plugins/index.md @@ -75,7 +75,7 @@ function generateRandomId() { // this function is used when you execute `insert` without specifying an ID } -const local = PluginVue3.CreatePlugin({ generateRandomId }) +const cache = PluginVue3.CreatePlugin({ generateRandomId }) ``` ## Simple Store @@ -95,5 +95,5 @@ function generateRandomId() { // this function is used when you execute `insert` without specifying an ID } -const local = PluginSimpleStore.CreatePlugin({ generateRandomId }) +const cache = PluginSimpleStore.CreatePlugin({ generateRandomId }) ``` diff --git a/docs/docs-main/read-data/index.md b/docs/docs-main/read-data/index.md index c3b531ab..932eda2d 100644 --- a/docs/docs-main/read-data/index.md +++ b/docs/docs-main/read-data/index.md @@ -7,23 +7,23 @@ There are two ways to retrieve data from your remote stores. Either of these met ## Fetch Data Once -When you get data by executing `fetch()`, the data will be fetched from a server by your "remote" store plugin and then added to your module's data by your "local" store plugin. +When you get data by executing `fetch()`, the data will be fetched from a server by your "remote" store plugin and then added to your module's data by your "cache" store plugin. For displaying fetched data in the DOM see the [Displaying data in the DOM](../setup/#displaying-data-in-the-dom). ### Fetch a Single Document -When you call `fetch()` on a document module, your remote store will go and fetch the document from your database and add it to your local store. +When you call `fetch()` on a document module, your remote store will go and fetch the document from your database and add it to your local cache store. ```javascript const bulbasaur = magnetar.doc('pokedex/001') -// bulbasaur's data is not yet in local data +// bulbasaur's data is not yet in cached data // bulbasaur.data β‰ˆ {} await bulbasaur.fetch() -// now it is available locally: +// now it is available: const data = bulbasaur.data // bulbasaur.data β‰ˆ { name: 'Bulbasaur' } @@ -144,9 +144,9 @@ magnetar.collection('pokedex').average // { base: { HP: 64.2 } } ## Stream Realtime Updates -When you set up a _**stream**_ for a document or collection, just like `fetch()`, your the data will be fetched from a server by your _remote_ store plugin and then added to your module's _local_ data. +When you set up a _**stream**_ for a document or collection, just like `fetch()`, your the data will be fetched from a server by your _remote_ store plugin and then added to your module's _cache_ data. -Afterwards, any changes to this document remotely will automatically be reflected in your module's _local_ data while the stream is open. +Afterwards, any changes to this document remotely will automatically be reflected in your module's _cache_ data while the stream is open. Please note: a streaming promise will never resolve as long as your stream is open! There is **no way** to know when or how many documents will be loaded in, as this depends on your remote store. @@ -265,10 +265,10 @@ There are founr methods to query more specific data in a collection: You can execute and chain these methods on collections to create a _queried module_ that is just like a regular module but with your query applied. -When you apply a query it affects both the remote and local stores: +When you apply a query it affects both the remote and cache stores: - If you make a `fetch()` call with a _queried module_, it will pass the queries to the remote store, which will make sure that your query is applied to the API call. -- If you access module data with a _queried module_, the local store will also make sure that your query is applied to whatever data it returns. +- If you access module data with a _queried module_, the local cache store will also make sure that your query is applied to whatever data it returns. ```js const pokedexModule = magnetar.collection('pokedex') @@ -312,7 +312,7 @@ magnetar ``` -For now read the Firestore documentation on [Simple and Compound Queries](https://firebase.google.com/docs/firestore/query-data/queries). The concept is inspired by Firestore, but with Magnetar _every_ local and remote store plugin implements the proper logic to work with these kind of queries! +For now read the Firestore documentation on [Simple and Compound Queries](https://firebase.google.com/docs/firestore/query-data/queries). The concept is inspired by Firestore, but with Magnetar _every_ cache and remote store plugin implements the proper logic to work with these kind of queries! More Magnetar specific information on this will come soon. diff --git a/docs/docs-main/setup/index.md b/docs/docs-main/setup/index.md index ccb4764e..00d61b6c 100644 --- a/docs/docs-main/setup/index.md +++ b/docs/docs-main/setup/index.md @@ -5,7 +5,7 @@ To instantiate Magnetar, you need to first instantiate the store plugins you will use: 1. instantiate a plugin for a _**remote**_ data store -2. instantiate a plugin for a _**local**_ data store +2. instantiate a plugin for a local _**cache**_ data store 3. _then_ instantiate the Magnetar instance with those plugins ### Example @@ -13,7 +13,7 @@ To instantiate Magnetar, you need to first instantiate the store plugins you wil This is a complete setup example which uses: - the **Firestore** plugin for remote data store -- the **Vue 3** plugin for local data store +- the **Vue 3** plugin for local cache data store > Please note: in reality it's cleaner to have **all imports at the top** @@ -42,21 +42,20 @@ function generateRandomId () { return doc(collection(db, 'random')).id } const remote = PluginFirestore.CreatePlugin({ db }) // --------------------------------------- -// 2. the plugin vue3 for local data store -// create the local store plugin instance & pass your `generateRandomId`: +// 2. the plugin vue3 for cache data store +// create the cache store plugin instance & pass your `generateRandomId`: // --------------------------------------- -const local = PluginVue3.CreatePlugin({ generateRandomId }) +const cache = PluginVue3.CreatePlugin({ generateRandomId }) // ----------------------------------------------------- // 3. instantiate the Magnetar instance with the store plugins // ----------------------------------------------------- export const magnetar = Magnetar({ - stores: { local, remote }, - localStoreName: 'local', + stores: { cache, remote }, executionOrder: { - read: ['local', 'remote'], - write: ['local', 'remote'], - delete: ['local', 'remote'], + read: ['cache', 'remote'], + write: ['cache', 'remote'], + delete: ['cache', 'remote'], }, on: { success: logger }, // disable this on production builds }) @@ -65,8 +64,7 @@ export const magnetar = Magnetar({ Some info on the main Magnetar instance props: -- `stores` βΈΊ an object with the store name as key and the store plugin instance as value -- `localStoreName` βΈΊ the name of the store that saves data locally +- `stores` βΈΊ an object with the store name as key and the store plugin instance as value, needs at least one plugin for the `cache` key, the other keys you can choose the name - `executionOrder` βΈΊ the execution order of your stores, this order is required for optimistic UI (but can be flipped) - `on` βΈΊ event listeners for anything that happens in Magnetar, see the [Events chapter](../hooks-and-events/) for more info @@ -100,7 +98,7 @@ export const trainerModule = magnetar.doc('app-data/trainer') Using your collection or document modules, you can access the `data`, `id` and several methods. -**Any data accessed is readonly!** To "mutate" the data, you **have** to use the provided methods. This is good because any kind of mutation is supposed to go through a function so it can be synced to your local & remote stores. +**Any data accessed is readonly!** To "mutate" the data, you **have** to use the provided methods. This is good because any kind of mutation is supposed to go through a function so it can be synced to your local cache & remote stores. Here we show some of the data and methods you can access on a module: @@ -121,8 +119,8 @@ pokedexModule.insert({ name: 'Squirtle' }) // inserts a new document pokedexModule.delete('001') // deletes a document // methods to read data -pokedexModule.fetch() // fetches documents from the remote store & adds them locally -pokedexModule.stream() // opens a database stream & adds incoming documents locally +pokedexModule.fetch() // fetches documents from the remote store & caches them locally +pokedexModule.stream() // opens a database stream & caches incoming documents locally ``` ### Document Modules @@ -147,8 +145,8 @@ pokemonModule.deleteProp('name') // deletes a property from the document pokemonModule.delete() // deletes the document // methods to read data -pokemonModule.fetch() // fetches the document from the remote store & adds it locally -pokemonModule.stream() // opens a database stream & keeps the document up to date locally +pokemonModule.fetch() // fetches the document from the remote store & caches it locally +pokemonModule.stream() // opens a database stream & keeps the cached document up to date locally ``` ## Displaying Data in the DOM @@ -160,7 +158,7 @@ Here we show to how make sure your DOM is updated reactively whenever this data ### Vue Example -In Vue you must make sure you use the Vue 2 or Vue 3 plugin as local store which will enable reactivity. +In Vue you must make sure you use the Vue 2 or Vue 3 plugin as local cache store which will enable reactivity. You can use a computed prop to show the data in your template like so: diff --git a/docs/docs-main/write-data/index.md b/docs/docs-main/write-data/index.md index 25850658..96186b0c 100644 --- a/docs/docs-main/write-data/index.md +++ b/docs/docs-main/write-data/index.md @@ -17,7 +17,7 @@ pokedexModule.insert({ name: 'squirtle' }) This is what happens: -Your document is passed to both your store plugins. The local store plugin is responsible caching this document, and your remote store plugin is responsible for making the API call to your database. +Your document is passed to both your store plugins. The local cache store plugin is responsible caching this document, and your remote store plugin is responsible for making the API call to your database. ### Access the New Document @@ -46,7 +46,7 @@ Since your remote store will make an API call, insert will always returns a prom > If the insert promise only resolves **after** the remote store API call, how is this Optimistic UI? -Awaiting an insert promise will never be _Optimistic_! However, when you insert a new document, your _local_ store is responsible for generating a new ID and saving the data in your module's cache. This part is done immediately and is therefore _Optimistic_! +Awaiting an insert promise will never be _Optimistic_! However, when you insert a new document, your _cache_ store is responsible for generating a new ID and saving the data in your module's cache. This part is done immediately and is therefore _Optimistic_! > How can I achieve Optimistic UI then? (How can I display changes immediately in the UI?) diff --git a/packages/core/package.json b/packages/core/package.json index a9d6cb77..51ef8411 100644 --- a/packages/core/package.json +++ b/packages/core/package.json @@ -47,6 +47,8 @@ "vue-store", "firestore", "data-store", + "data-cache", + "cache-store", "local-store", "remote-store", "global-store", diff --git a/packages/core/src/helpers/configHelpers.ts b/packages/core/src/helpers/configHelpers.ts index 3c5c6990..85863f06 100644 --- a/packages/core/src/helpers/configHelpers.ts +++ b/packages/core/src/helpers/configHelpers.ts @@ -2,9 +2,12 @@ import type { GlobalConfig } from '@magnetarjs/types' import { merge } from 'merge-anything' export function defaultsGlobalConfig(config: GlobalConfig): Required { - const defaults: Required = { - localStoreName: '', - stores: {}, + if (!('stores' in config)) { + throw new Error( + 'GlobalConfig must have a stores property with at least one plugin provided for the `cache` key', + ) + } + const defaults: Omit, 'stores'> = { executionOrder: { read: [], write: [], diff --git a/packages/core/src/helpers/executeOnFns.ts b/packages/core/src/helpers/executeOnFns.ts index 76303df2..e06d2708 100644 --- a/packages/core/src/helpers/executeOnFns.ts +++ b/packages/core/src/helpers/executeOnFns.ts @@ -11,18 +11,18 @@ import type { */ export function executeOnFns(params: { modifyReadResultFns: (OnAddedFn | OnModifiedFn | OnRemovedFn)[] - localStoreFns: (DoOnFetch | OnAddedFn | OnModifiedFn | OnRemovedFn)[] + cacheStoreFns: (DoOnFetch | OnAddedFn | OnModifiedFn | OnRemovedFn)[] payload: Payload docMetaData: DocMetadata }): Payload | undefined { - const { modifyReadResultFns, localStoreFns, payload, docMetaData } = params + const { modifyReadResultFns, cacheStoreFns, payload, docMetaData } = params let newPayload = payload for (const fn of modifyReadResultFns) { // we only want to execute these when there is a payload if (newPayload) newPayload = fn(newPayload as any, docMetaData) as any } - for (const fn of localStoreFns) { + for (const fn of cacheStoreFns) { // we only want to execute these always, regardless wether or not there's a payload newPayload = fn(newPayload as any, docMetaData) as any } diff --git a/packages/core/src/helpers/moduleHelpers.ts b/packages/core/src/helpers/moduleHelpers.ts index a8b651bc..d74c7a13 100644 --- a/packages/core/src/helpers/moduleHelpers.ts +++ b/packages/core/src/helpers/moduleHelpers.ts @@ -1,6 +1,5 @@ import type { GlobalConfig, ModuleConfig, PluginModuleConfig } from '@magnetarjs/types' import { isFunction, isPlainObject } from 'is-what' -import { throwIfNolocalStoreName } from './throwFns.js' /** * Extracts the PluginModuleConfig from the ModuleConfig @@ -41,37 +40,33 @@ export function executeSetupModulePerStore( } } -/** Executes the `getModuleData` function from the store specified as 'localStoreName' */ +/** Executes the `getModuleData` function from the store specified as 'cache' */ export function getDataFromDataStore(moduleConfig: ModuleConfig, globalConfig: GlobalConfig, collectionPath: string): Map // prettier-ignore -/** Executes the `getModuleData` function from the store specified as 'localStoreName' */ +/** Executes the `getModuleData` function from the store specified as 'cache' */ export function getDataFromDataStore(moduleConfig: ModuleConfig, globalConfig: GlobalConfig, collectionPath: string, docId: string): { [key: string]: any } // prettier-ignore -/** Executes the `getModuleData` function from the store specified as 'localStoreName' */ +/** Executes the `getModuleData` function from the store specified as 'cache' */ export function getDataFromDataStore( moduleConfig: ModuleConfig, globalConfig: GlobalConfig, collectionPath: string, docId?: string, ): { [key: string]: any } | Map { - const localStoreName = globalConfig.localStoreName - throwIfNolocalStoreName(localStoreName) - const getModuleData = globalConfig.stores[localStoreName]?.getModuleData + const getModuleData = globalConfig.stores['cache']?.getModuleData if (!getModuleData) { throw new Error('The data store did not provide a getModuleData function!') } - const pluginModuleConfig = getPluginModuleConfig(moduleConfig, localStoreName) + const pluginModuleConfig = getPluginModuleConfig(moduleConfig, 'cache') return getModuleData({ collectionPath, docId, pluginModuleConfig }) } -/** Executes the `getModuleData` function from the store specified as 'localStoreName' */ +/** Executes the `getModuleData` function from the store specified as 'cache' */ export function getExistsFromDataStore( globalConfig: GlobalConfig, collectionPath: string, docId: string, ): undefined | 'error' | boolean { - const localStoreName = globalConfig.localStoreName - throwIfNolocalStoreName(localStoreName) - const getModuleExists = globalConfig.stores[localStoreName]?.getModuleExists + const getModuleExists = globalConfig.stores['cache']?.getModuleExists if (!getModuleExists) { throw new Error('The data store did not provide a getModuleExists function!') } @@ -79,37 +74,33 @@ export function getExistsFromDataStore( return getModuleExists({ collectionPath, docId }) } -/** Executes the `getModuleCount` function from the store specified as 'localStoreName' */ +/** Executes the `getModuleCount` function from the store specified as 'cache' */ export function getCountFromDataStore( moduleConfig: ModuleConfig, globalConfig: GlobalConfig, collectionPath: string, ): number { - const localStoreName = globalConfig.localStoreName - throwIfNolocalStoreName(localStoreName) - const getModuleCount = globalConfig.stores[localStoreName]?.getModuleCount + const getModuleCount = globalConfig.stores['cache']?.getModuleCount if (!getModuleCount) { throw new Error('The data store did not provide a getModuleCount function!') } - const pluginModuleConfig = getPluginModuleConfig(moduleConfig, localStoreName) + const pluginModuleConfig = getPluginModuleConfig(moduleConfig, 'cache') return getModuleCount({ collectionPath, pluginModuleConfig }) } -/** Executes the `getModuleAggregate` function from the store specified as 'localStoreName' */ +/** Executes the `getModuleAggregate` function from the store specified as 'cache' */ export function getAggregateFromDataStore( kind: 'sum' | 'average', moduleConfig: ModuleConfig, globalConfig: GlobalConfig, collectionPath: string, ): { [key in string]: number | { [key in string]: unknown } } { - const localStoreName = globalConfig.localStoreName - throwIfNolocalStoreName(localStoreName) - const getModuleAggregate = globalConfig.stores[localStoreName]?.getModuleAggregate + const getModuleAggregate = globalConfig.stores['cache']?.getModuleAggregate if (!getModuleAggregate) { throw new Error('The data store did not provide a getModuleAggregate function!') } - const pluginModuleConfig = getPluginModuleConfig(moduleConfig, localStoreName) + const pluginModuleConfig = getPluginModuleConfig(moduleConfig, 'cache') return getModuleAggregate(kind, { collectionPath, pluginModuleConfig }) } diff --git a/packages/core/src/helpers/throwFns.ts b/packages/core/src/helpers/throwFns.ts index 7a58e010..40777d4e 100644 --- a/packages/core/src/helpers/throwFns.ts +++ b/packages/core/src/helpers/throwFns.ts @@ -1,6 +1,5 @@ import type { DoOnStreamFns, StreamResponse } from '@magnetarjs/types' import { isCollectionModule, isDocModule } from '@magnetarjs/utils' -import { isFullString } from 'is-what' export function logError(errorMessage: string): undefined { console.error('[@magnetarjs error]\n', errorMessage) @@ -13,7 +12,7 @@ export function logErrorAndThrow(errorMessage: string): undefined { export function throwOnIncompleteStreamResponses( streamInfoPerStore: { [storeName: string]: StreamResponse }, - doOnStreamFns: DoOnStreamFns + doOnStreamFns: DoOnStreamFns, ): undefined { const noStreamLogic = !Object.keys(streamInfoPerStore).length if (noStreamLogic) { @@ -36,15 +35,9 @@ export function throwIfNoFnsToExecute(storesToExecute: string[]): undefined { } } -export function throwIfNolocalStoreName(localStoreName: string): undefined { - if (isFullString(localStoreName)) return - const errorMessage = `No 'localStoreName' provided.` - logErrorAndThrow(errorMessage) -} - export function throwIfInvalidModulePath( modulePath: string, - moduleType: 'collection' | 'doc' + moduleType: 'collection' | 'doc', ): undefined { let errorMessage = '' if (moduleType === 'collection') { diff --git a/packages/core/src/moduleActions/handleFetchPerStore.ts b/packages/core/src/moduleActions/handleFetchPerStore.ts index e2165257..2d3dd24e 100644 --- a/packages/core/src/moduleActions/handleFetchPerStore.ts +++ b/packages/core/src/moduleActions/handleFetchPerStore.ts @@ -136,7 +136,7 @@ export function handleFetchPerStore( } /** - * each each time a store returns a `FetchResponse` then it must first go through all on added fns to potentially modify the retuned payload before writing locally + * each each time a store returns a `FetchResponse` then it must first go through all on added fns to potentially modify the retuned payload before writing to cache */ const doOnAddedFns: OnAddedFn[] = modifyReadResponseMap.added /** @@ -213,12 +213,12 @@ export function handleFetchPerStore( for (const docMetaData of docs) { const docResult = executeOnFns({ modifyReadResultFns: doOnAddedFns, - localStoreFns: doOnFetchFns, + cacheStoreFns: doOnFetchFns, payload: docMetaData.data, docMetaData, }) // after doing all `doOnAddedFns` (modifying the read result) - // and all `doOnFetchFns` (adding it to the local store) + // and all `doOnFetchFns` (adding it to the local cache store) // we still have a record, so must return it when resolving the fetch action if (docResult) collectionFetchResult.set(docMetaData.id, docResult) diff --git a/packages/core/src/moduleActions/handleStreamPerStore.ts b/packages/core/src/moduleActions/handleStreamPerStore.ts index 1bde8165..47b485cd 100644 --- a/packages/core/src/moduleActions/handleStreamPerStore.ts +++ b/packages/core/src/moduleActions/handleStreamPerStore.ts @@ -28,7 +28,7 @@ export function handleStreamPerStore( actionType: ActionType, streaming: () => Promise | null, cacheStream: (closeStreamFn: () => void, streamingPromise: Promise | null) => void, - writeLockMap: Map + writeLockMap: Map, ): MagnetarStreamAction { // returns the action the dev can call with myModule.insert() etc. return async function (payload?: any, actionConfig: ActionConfig = {}): Promise { @@ -41,12 +41,12 @@ export function handleStreamPerStore( const modifyPayloadFnsMap = getModifyPayloadFnsMap( globalConfig.modifyPayloadOn, moduleConfig.modifyPayloadOn, - actionConfig.modifyPayloadOn + actionConfig.modifyPayloadOn, ) const modifyReadResponseMap = getModifyReadResponseFnsMap( globalConfig.modifyReadResponseOn, moduleConfig.modifyReadResponseOn, - actionConfig.modifyReadResponseOn + actionConfig.modifyReadResponseOn, ) const storesToExecute: string[] = actionConfig.executionOrder || @@ -102,7 +102,7 @@ export function handleStreamPerStore( return executeOnFns({ modifyReadResultFns: modifyReadResponseFns.added, - localStoreFns: doOnStreamFns.added, + cacheStoreFns: doOnStreamFns.added, payload: result.payload, docMetaData: result.meta, }) @@ -123,7 +123,7 @@ export function handleStreamPerStore( return executeOnFns({ modifyReadResultFns: modifyReadResponseFns.added, - localStoreFns: doOnStreamFns.added, + cacheStoreFns: doOnStreamFns.added, payload: result.payload, docMetaData: result.meta, }) @@ -137,7 +137,7 @@ export function handleStreamPerStore( return executeOnFns({ modifyReadResultFns: modifyReadResponseFns.removed, - localStoreFns: doOnStreamFns.removed, + cacheStoreFns: doOnStreamFns.removed, payload: _payload, docMetaData: _meta, }) diff --git a/packages/core/src/moduleActions/handleWritePerStore.ts b/packages/core/src/moduleActions/handleWritePerStore.ts index 5a386a08..5927300b 100644 --- a/packages/core/src/moduleActions/handleWritePerStore.ts +++ b/packages/core/src/moduleActions/handleWritePerStore.ts @@ -43,7 +43,7 @@ export function handleWritePerStore( actionName: Extract< ActionName, 'insert' | 'merge' | 'assign' | 'replace' | 'deleteProp' | 'delete' - > + >, ): | MagnetarWriteAction | MagnetarInsertAction @@ -59,7 +59,7 @@ export function handleWritePerStore( return { promise: null, resolve: () => undefined, countdown: null } }) - // we need to create a promise we'll resolve later to prevent any incoming docs from being written to the local state during this time + // we need to create a promise we'll resolve later to prevent any incoming docs from being written to the cache store during this time if (writeLock.promise === null) { writeLock.promise = new Promise((resolve) => { writeLock.resolve = () => { @@ -90,12 +90,12 @@ export function handleWritePerStore( const modifyPayloadFnsMap = getModifyPayloadFnsMap( globalConfig.modifyPayloadOn, moduleConfig.modifyPayloadOn, - actionConfig.modifyPayloadOn + actionConfig.modifyPayloadOn, ) const eventNameFnsMap = getEventNameFnsMap( globalConfig.on, moduleConfig.on, - actionConfig.on + actionConfig.on, ) const storesToExecute: string[] = actionConfig.executionOrder || diff --git a/packages/core/test/external/delete.test.ts b/packages/core/test/external/delete.test.ts index 461bb4e3..6e04e2c9 100644 --- a/packages/core/test/external/delete.test.ts +++ b/packages/core/test/external/delete.test.ts @@ -29,12 +29,12 @@ test('delete (collection)', async () => { assert.deepEqual(pokedexModule.data.get('1'), undefined) }) -test('revert: delete (local β†’ remote)', async () => { +test('revert: delete (cache β†’ remote)', async () => { const { trainerModule } = createMagnetarInstance() assert.deepEqual(trainerModule.data, { age: 10, name: 'Luca' }) try { - await trainerModule.delete('remote', { onError: 'revert', executionOrder: ['local', 'remote'] }) // mocks error on delete for remote store mock + await trainerModule.delete('remote', { onError: 'revert', executionOrder: ['cache', 'remote'] }) // mocks error on delete for remote store mock } catch (error) { assert.isTrue(!!error) } @@ -43,12 +43,12 @@ test('revert: delete (local β†’ remote)', async () => { }) // todo: for this test to work we need to mock a data pool for the remote plugin mock -// test('revert: delete (remote β†’ local)', async t => { +// test('revert: delete (remote β†’ cache)', async t => { // const { trainerModule } = createMagnetarInstance() // assert.deepEqual(trainerModule.data, { age: 10, name: 'Luca' }) // try { -// await trainerModule.delete('local', { onError: 'revert', executionOrder: ['remote', 'local'] }) // mocks error on delete for remote store mock +// await trainerModule.delete('cache', { onError: 'revert', executionOrder: ['remote', 'cache'] }) // mocks error on delete for remote store mock // } catch (error) { // assert.isTrue(!!error) // } diff --git a/packages/core/test/helpers/createMagnetarInstance.ts b/packages/core/test/helpers/createMagnetarInstance.ts index 5b434e01..d333edff 100644 --- a/packages/core/test/helpers/createMagnetarInstance.ts +++ b/packages/core/test/helpers/createMagnetarInstance.ts @@ -35,21 +35,20 @@ export type TrainerModuleData = { export function createMagnetarInstance( magnetarGlobalConfig: Partial = {}, - startEmpty = false + startEmpty = false, ): { pokedexModule: CollectionInstance trainerModule: DocInstance magnetar: MagnetarInstance } { - const local = CreatePluginLocal({ storeName: 'local', generateRandomId }) + const cache = CreatePluginLocal({ storeName: 'cache', generateRandomId }) const remote = CreatePluginRemote({ storeName: 'remote' }) const magnetar = Magnetar({ - localStoreName: 'local', - stores: { local, remote }, + stores: { cache, remote }, executionOrder: { - read: ['local', 'remote'], - write: ['local', 'remote'], - delete: ['local', 'remote'], + read: ['cache', 'remote'], + write: ['cache', 'remote'], + delete: ['cache', 'remote'], }, ...magnetarGlobalConfig, }) @@ -57,7 +56,7 @@ export function createMagnetarInstance( ? magnetar.collection('pokedex') : magnetar.collection('pokedex', { configPerStore: { - local: { initialData: getInitialDataCollection() }, // path for the plugin + cache: { initialData: getInitialDataCollection() }, // path for the plugin remote: {}, // path for the plugin }, }) @@ -65,7 +64,7 @@ export function createMagnetarInstance( ? magnetar.doc('app-data/trainer') : magnetar.doc('app-data/trainer', { configPerStore: { - local: { initialData: getInitialDataDocument() }, // path for the plugin + cache: { initialData: getInitialDataDocument() }, // path for the plugin remote: {}, // path for the plugin }, }) diff --git a/packages/core/test/internal/errorHandling.test.ts b/packages/core/test/internal/errorHandling.test.ts index 7071f976..b171c945 100644 --- a/packages/core/test/internal/errorHandling.test.ts +++ b/packages/core/test/internal/errorHandling.test.ts @@ -7,14 +7,14 @@ test('write + onError: stop -- emits fail events & aborts execution by default', const { pokedexModule } = createMagnetarInstance() const insertPayload = { ...pokedexEntryDefaults({ name: 'this should fail' }), - shouldFail: 'local', + shouldFail: 'cache', } try { await pokedexModule.doc('testid').insert(insertPayload, { onError: 'stop', on: { error: ({ payload, storeName }) => { - if (storeName === 'local') { + if (storeName === 'cache') { assert.deepEqual(payload, insertPayload) } }, @@ -40,7 +40,7 @@ test('write + onError: stop -- fail in second store plugin does not prevent exec onError: 'stop', on: { error: ({ payload, storeName }) => { - if (storeName === 'local') assert.fail() + if (storeName === 'cache') assert.fail() if (storeName === 'remote') { assert.deepEqual(payload, insertPayload) } @@ -57,14 +57,14 @@ test('write + onError: continue', async () => { const { pokedexModule } = createMagnetarInstance() const insertPayload = { ...pokedexEntryDefaults({ name: 'this should fail' }), - shouldFail: 'local', + shouldFail: 'cache', } try { await pokedexModule.doc('testid').insert(insertPayload, { onError: 'continue', on: { error: ({ payload, storeName }) => { - if (storeName === 'local') { + if (storeName === 'cache') { assert.deepEqual(payload, insertPayload) } if (storeName === 'remote') assert.fail() @@ -93,7 +93,7 @@ test('write + onError: revert', async () => { onError: 'revert', on: { revert: ({ payload, result, actionName, storeName }) => { - if (storeName === 'local') { + if (storeName === 'cache') { assert.deepEqual(actionName, 'insert') } }, @@ -102,7 +102,7 @@ test('write + onError: revert', async () => { assert.deepEqual(pokedexModule.data.get('testid'), insertPayload) }, error: ({ payload, storeName }) => { - if (storeName === 'local') assert.fail() + if (storeName === 'cache') assert.fail() if (storeName === 'remote') { assert.deepEqual(payload, insertPayload) } @@ -119,19 +119,19 @@ test('write + onError: revert - will not go to next store', async () => { const { pokedexModule } = createMagnetarInstance() const insertPayload = { ...pokedexEntryDefaults({ name: 'this should fail' }), - shouldFail: 'local', + shouldFail: 'cache', } try { await pokedexModule.doc('testid').insert(insertPayload, { onError: 'revert', on: { error: ({ payload, storeName }) => { - if (storeName === 'local') { + if (storeName === 'cache') { assert.deepEqual(payload, insertPayload) } }, revert: ({ storeName }) => { - if (storeName === 'local') assert.fail() + if (storeName === 'cache') assert.fail() }, before: ({ payload, storeName }) => { if (storeName === 'remote') { @@ -148,14 +148,14 @@ test('write + onError: revert - will not go to next store', async () => { test('fetch + onError: stop -- emits fail events & aborts execution by default', async () => { const { pokedexModule } = createMagnetarInstance() - const fetchPayload = { shouldFail: 'local', force: true } + const fetchPayload = { shouldFail: 'cache', force: true } assert.deepEqual(pokedexModule.data.get('1'), pokedex(1)) try { await pokedexModule.fetch(fetchPayload, { onError: 'stop', on: { error: ({ payload, storeName }) => { - if (storeName === 'local') { + if (storeName === 'cache') { assert.deepEqual(payload, fetchPayload) } }, @@ -180,7 +180,7 @@ test('fetch + onError: stop -- fail in second store plugin does not prevent exec onError: 'stop', on: { error: ({ payload, storeName }) => { - if (storeName === 'local') assert.fail() + if (storeName === 'cache') assert.fail() if (storeName === 'remote') { assert.deepEqual(payload, fetchPayload) } @@ -196,14 +196,14 @@ test('fetch + onError: stop -- fail in second store plugin does not prevent exec test('fetch + onError: continue', async () => { const { pokedexModule } = createMagnetarInstance() - const fetchPayload = { shouldFail: 'local', force: true } + const fetchPayload = { shouldFail: 'cache', force: true } assert.deepEqual(pokedexModule.data.get('1'), pokedex(1)) try { const result = await pokedexModule.fetch(fetchPayload, { onError: 'continue', on: { error: ({ payload, storeName }) => { - if (storeName === 'local') { + if (storeName === 'cache') { assert.deepEqual(payload, fetchPayload) } if (storeName === 'remote') assert.fail() @@ -211,7 +211,7 @@ test('fetch + onError: continue', async () => { success: ({ payload, result, storeName }) => { if (storeName === 'remote') { assert.deepEqual(payload, fetchPayload) - // even though the local store failed, we got the result of the remote store + // even though the cache store failed, we got the result of the remote store assert.deepEqual((result as FetchResponse).docs.length, 151) } }, @@ -222,7 +222,7 @@ test('fetch + onError: continue', async () => { } catch (error) { assert.fail(JSON.stringify(error)) } - // the local store didn't succeed in applying its 'inserted' event, so its local data will be empty: + // the cache store didn't succeed in applying its 'inserted' event, so its cached data will be empty: assert.deepEqual(pokedexModule.data.get('1'), pokedex(1)) assert.deepEqual(pokedexModule.data.get('136'), undefined) }) diff --git a/packages/core/test/internal/events.test.ts b/packages/core/test/internal/events.test.ts index 70846bf8..fa3164ea 100644 --- a/packages/core/test/internal/events.test.ts +++ b/packages/core/test/internal/events.test.ts @@ -27,7 +27,7 @@ test('insert: emits before & success events', async () => { await pokedexModule.insert(insertPayload, { on: { before: ({ payload, storeName }) => { - if (storeName === 'local') { + if (storeName === 'cache') { assert.deepEqual(payload, insertPayload) ranAllEvents.push(1) } @@ -37,7 +37,7 @@ test('insert: emits before & success events', async () => { } }, success: ({ payload, storeName }) => { - if (storeName === 'local') { + if (storeName === 'cache') { assert.deepEqual(payload, insertPayload) ranAllEvents.push(1) } @@ -58,7 +58,7 @@ test('insert: can abort in before events', async () => { const result = await pokedexModule.insert(insertPayload, { on: { before: ({ payload, abort, storeName }) => { - if (storeName === 'local') { + if (storeName === 'cache') { abort() } if (storeName === 'remote') assert.fail() @@ -67,7 +67,7 @@ test('insert: can abort in before events', async () => { assert.fail() }, error: ({ storeName }) => { - if (storeName === 'local') assert.fail() + if (storeName === 'cache') assert.fail() }, }, }) @@ -85,13 +85,13 @@ test('insert: can abort in success events', async () => { const result = await pokedexModule.insert(insertPayload, { on: { before: ({ payload, storeName }) => { - if (storeName === 'local') { + if (storeName === 'cache') { ranAllEvents.push(1) } if (storeName === 'remote') assert.fail() }, success: ({ payload, abort, storeName }) => { - if (storeName === 'local') { + if (storeName === 'cache') { ranAllEvents.push(1) abort() } diff --git a/packages/core/test/internal/globalModuleAndActionConfig.test.ts b/packages/core/test/internal/globalModuleAndActionConfig.test.ts index 10d1d8c7..ced6a26a 100644 --- a/packages/core/test/internal/globalModuleAndActionConfig.test.ts +++ b/packages/core/test/internal/globalModuleAndActionConfig.test.ts @@ -6,25 +6,24 @@ import { createMagnetarInstance } from '../helpers/createMagnetarInstance.js' const CreatePluginLocal = PluginMockLocal.CreatePlugin test('emits global, module and action events', async () => { - const local = CreatePluginLocal({ storeName: 'local', generateRandomId }) + const cache = CreatePluginLocal({ storeName: 'cache', generateRandomId }) const ranAllEvents: any[] = [] const magnetar = Magnetar({ - localStoreName: 'local', - stores: { local }, + stores: { cache }, executionOrder: { - read: ['local'], - write: ['local'], + read: ['cache'], + write: ['cache'], }, on: { before: ({ payload, storeName }) => { - if (storeName === 'local') ranAllEvents.push(payload) + if (storeName === 'cache') ranAllEvents.push(payload) }, }, }) const usersModule = magnetar.collection('users', { on: { before: ({ payload, storeName }) => { - if (storeName === 'local') ranAllEvents.push(payload) + if (storeName === 'cache') ranAllEvents.push(payload) }, }, }) @@ -33,7 +32,7 @@ test('emits global, module and action events', async () => { const result = await usersModule.insert(insertPayload, { on: { before: ({ payload, storeName }) => { - if (storeName === 'local') ranAllEvents.push(payload) + if (storeName === 'cache') ranAllEvents.push(payload) }, }, }) @@ -42,13 +41,12 @@ test('emits global, module and action events', async () => { }) test('can modify payload in global, module and action settings', async () => { - const local = CreatePluginLocal({ storeName: 'local', generateRandomId }) + const cache = CreatePluginLocal({ storeName: 'cache', generateRandomId }) const magnetar = Magnetar({ - localStoreName: 'local', - stores: { local }, + stores: { cache }, executionOrder: { - read: ['local'], - write: ['local'], + read: ['cache'], + write: ['cache'], }, modifyPayloadOn: { insert: (payload) => { @@ -86,7 +84,7 @@ test('can overwrite execution order', async () => { await pokedexModule.insert(insertPayload) let ranAllEvents: string[] = [] await pokedexModule.doc('7').delete(undefined, { - executionOrder: ['local', 'remote'], + executionOrder: ['cache', 'remote'], on: { before: ({ payload, storeName }) => { ranAllEvents.push(storeName) @@ -96,11 +94,11 @@ test('can overwrite execution order', async () => { }, }, }) - assert.deepEqual(ranAllEvents, ['local', 'local', 'remote', 'remote']) + assert.deepEqual(ranAllEvents, ['cache', 'cache', 'remote', 'remote']) await pokedexModule.insert(insertPayload) ranAllEvents = [] await pokedexModule.doc('7').delete(undefined, { - executionOrder: ['remote', 'local'], + executionOrder: ['remote', 'cache'], on: { before: ({ payload, storeName }) => { ranAllEvents.push(storeName) @@ -110,5 +108,5 @@ test('can overwrite execution order', async () => { }, }, }) - assert.deepEqual(ranAllEvents, ['remote', 'remote', 'local', 'local']) + assert.deepEqual(ranAllEvents, ['remote', 'remote', 'cache', 'cache']) }) diff --git a/packages/core/test/internal/modifyPayloadAndReadResponse.test.ts b/packages/core/test/internal/modifyPayloadAndReadResponse.test.ts index c80a7cd4..c939fe8a 100644 --- a/packages/core/test/internal/modifyPayloadAndReadResponse.test.ts +++ b/packages/core/test/internal/modifyPayloadAndReadResponse.test.ts @@ -24,7 +24,7 @@ test('fetch: can mutate payload & read response (config in global magnetar insta payloadInSuccessEvent = payload }, }, - } + }, ) // the remote result SHOULD HAVE the applied defaults assert.deepEqual(payloadInSuccessEvent, { auth: 'Bearer 123123', force: true }) @@ -32,7 +32,7 @@ test('fetch: can mutate payload & read response (config in global magnetar insta } catch (error) { assert.fail(JSON.stringify(error)) } - // the local store SHOULD HAVE the applied defaults + // the cache store SHOULD HAVE the applied defaults assert.deepEqual(magnetar.collection('pokedex').data.get('136'), { ...pokedex(136), seen: true }) }) @@ -56,10 +56,10 @@ test('stream: can mutate payload & read response (config in global magnetar inst payloadInSuccessEvent = payload }, }, - } + }, ) await waitMs(600) - // the local store SHOULD HAVE the applied defaults + // the cache store SHOULD HAVE the applied defaults assert.deepEqual(payloadInSuccessEvent, { auth: 'Bearer 123123' }) assert.deepEqual(magnetar.collection('pokedex').data.get('2'), { ...pokedex(2), seen: true }) }) @@ -83,7 +83,7 @@ test('insert: can mutate payload (config in global magnetar instance)', async () } catch (error) { assert.fail(JSON.stringify(error)) } - // the local store SHOULD HAVE the applied defaults + // the cache store SHOULD HAVE the applied defaults assert.deepEqual(magnetar.collection('pokedex').data.get('7'), { ...pokedex(7), seen: true }) assert.deepEqual(magnetar.collection('pokedex').data.get('10'), { ...pokedex(10), seen: true }) assert.deepEqual(magnetar.collection('pokedex').data.get('25'), { ...pokedex(25), seen: true }) @@ -112,7 +112,7 @@ test('fetch: can mutate payload & read response (config in module)', async () => payloadInSuccessEvent = payload }, }, - } + }, ) // the remote result SHOULD HAVE the applied defaults assert.deepEqual(payloadInSuccessEvent, { auth: 'Bearer 123123', force: true }) @@ -120,7 +120,7 @@ test('fetch: can mutate payload & read response (config in module)', async () => } catch (error) { assert.fail(JSON.stringify(error)) } - // the local store SHOULD HAVE the applied defaults + // the cache store SHOULD HAVE the applied defaults assert.deepEqual(pokedexModule.data.get('136'), { ...pokedex(136), seen: true }) }) @@ -145,10 +145,10 @@ test('stream: can mutate payload & read response (config in module)', async () = payloadInSuccessEvent = payload }, }, - } + }, ) await waitMs(600) - // the local store SHOULD HAVE the applied defaults + // the cache store SHOULD HAVE the applied defaults assert.deepEqual(payloadInSuccessEvent, { auth: 'Bearer 123123' }) assert.deepEqual(pokedexModule.data.get('2'), { ...pokedex(2), seen: true }) }) @@ -170,7 +170,7 @@ test('insert: can mutate payload (config in module)', async () => { } catch (error) { assert.fail(JSON.stringify(error)) } - // the local store SHOULD HAVE the applied defaults + // the cache store SHOULD HAVE the applied defaults assert.deepEqual(pokedexModule.data.get('7'), { ...pokedex(7), seen: true }) }) @@ -196,7 +196,7 @@ test('fetch: can mutate payload & read response (config in action)', async () => payloadInSuccessEvent = payload }, }, - } + }, ) // the remote result SHOULD HAVE the applied defaults assert.deepEqual(result.get('1'), { ...pokedex(1), seen: true }) @@ -205,7 +205,7 @@ test('fetch: can mutate payload & read response (config in action)', async () => } catch (error) { assert.fail(JSON.stringify(error)) } - // the local store SHOULD HAVE the applied defaults + // the cache store SHOULD HAVE the applied defaults assert.deepEqual(pokedexModule.data.get('1'), { ...pokedex(1), seen: true }) assert.deepEqual(pokedexModule.data.get('136'), { ...pokedex(136), seen: true }) }) @@ -230,11 +230,11 @@ test('stream: can mutate payload & read response (config in action)', async () = payloadInSuccessEvent = payload }, }, - } + }, ) await waitMs(600) assert.deepEqual(payloadInSuccessEvent, { auth: 'Bearer 123123' }) - // the local store SHOULD HAVE the applied defaults + // the cache store SHOULD HAVE the applied defaults assert.deepEqual(pokedexModule.data.get('1'), { ...pokedex(1), seen: true }) assert.deepEqual(pokedexModule.data.get('2'), { ...pokedex(2), seen: true }) }) @@ -256,7 +256,7 @@ test('insert: can mutate payload (config in action)', async () => { } catch (error) { assert.fail(JSON.stringify(error)) } - // the local store SHOULD HAVE the applied defaults + // the cache store SHOULD HAVE the applied defaults assert.deepEqual(pokedexModule.data.get('1'), { ...pokedex(1) }) assert.deepEqual(pokedexModule.data.get('7'), { ...pokedex(7), seen: true }) }) @@ -281,8 +281,8 @@ test('insert: can mutate payload (config in module - action from doc)', async () } catch (error) { assert.fail(JSON.stringify(error)) } - // the local store result not from pokedexModule SHOULD NOT HAVE the applied defaults + // the cache store result not from pokedexModule SHOULD NOT HAVE the applied defaults assert.deepEqual(pokedexModule.data.get('7'), { ...pokedex(7), seen: true }) - // the local store SHOULD HAVE the applied defaults + // the cache store SHOULD HAVE the applied defaults assert.deepEqual(pokedexModule.data.get('10'), { ...pokedex(10) }) }) diff --git a/packages/core/test/internal/stream.test.ts b/packages/core/test/internal/stream.test.ts index e714f874..462e6023 100644 --- a/packages/core/test/internal/stream.test.ts +++ b/packages/core/test/internal/stream.test.ts @@ -76,7 +76,7 @@ test('stream (doc) but updating multiple times in between stream', async () => { // now the first change comes back from the server: await Promise.all([p3.resolve(), await p3.promise]) - // WE MUST MAKE SURE THAT `colour: 'blue'` is not undone in our local state!!! + // WE MUST MAKE SURE THAT `colour: 'blue'` is not undone in our cached state!!! assert.deepEqual(trainerModule.data, { name: 'Luca', age: 10, dream: 'job', colour: 'blue' }) // now the second change comes back from the server: diff --git a/packages/dev-vue3-firestore/src/magnetar.ts b/packages/dev-vue3-firestore/src/magnetar.ts index cd8a0b7f..7f22c947 100644 --- a/packages/dev-vue3-firestore/src/magnetar.ts +++ b/packages/dev-vue3-firestore/src/magnetar.ts @@ -1,5 +1,5 @@ // --------------------------------------- -// plugin vue3 for local data store +// plugin vue3 for cache data store // --------------------------------------- import { Magnetar } from '@magnetarjs/core' import { CreatePlugin as PluginFirestore } from '@magnetarjs/plugin-firestore' @@ -9,8 +9,8 @@ import { db } from './initFirebase.js' export const generateRandomId = (): string => doc(collection(db, 'random')).id -// create the local store plugin instance: -const local = PluginVue3({ generateRandomId }) +// create the cache store plugin instance: +const cache = PluginVue3({ generateRandomId }) const remote = PluginFirestore({ db }) @@ -18,11 +18,10 @@ const remote = PluginFirestore({ db }) // instantiate the Magnetar instance with the store plugins // ----------------------------------------------------- export const magnetar = Magnetar({ - stores: { local, remote }, - localStoreName: 'local', + stores: { cache, remote }, executionOrder: { - read: ['local', 'remote'], - write: ['local', 'remote'], - delete: ['local', 'remote'], + read: ['cache', 'remote'], + write: ['cache', 'remote'], + delete: ['cache', 'remote'], }, }) diff --git a/packages/magnetar/package.json b/packages/magnetar/package.json index 9525452b..bb06f497 100644 --- a/packages/magnetar/package.json +++ b/packages/magnetar/package.json @@ -47,6 +47,8 @@ "vue-store", "firestore", "data-store", + "data-cache", + "cache-store", "local-store", "remote-store", "global-store", diff --git a/packages/plugin-firestore-admin/package.json b/packages/plugin-firestore-admin/package.json index b2f684b0..8c66b451 100644 --- a/packages/plugin-firestore-admin/package.json +++ b/packages/plugin-firestore-admin/package.json @@ -62,6 +62,8 @@ "vue-store", "firestore", "data-store", + "data-cache", + "cache-store", "local-store", "remote-store", "global-store", diff --git a/packages/plugin-firestore-admin/test/external/mergeAssignReplace.test.ts b/packages/plugin-firestore-admin/test/external/mergeAssignReplace.test.ts index c8bb106c..5c8e0f45 100644 --- a/packages/plugin-firestore-admin/test/external/mergeAssignReplace.test.ts +++ b/packages/plugin-firestore-admin/test/external/mergeAssignReplace.test.ts @@ -86,7 +86,7 @@ import { firestoreDeepEqual } from '../helpers/firestoreDeepEqual.js' }) } { - // these tests are not really testing reverting the remote store, only the local store: + // these tests are not really testing reverting the remote store, only the cache store: const testName = 'revert: merge' test(testName, async () => { const { pokedexModule } = await createMagnetarInstance(testName, { @@ -108,7 +108,7 @@ import { firestoreDeepEqual } from '../helpers/firestoreDeepEqual.js' }) } { - // these tests are not really testing reverting the remote store, only the local store: + // these tests are not really testing reverting the remote store, only the cache store: const testName = 'revert: assign' test(testName, async () => { const { pokedexModule } = await createMagnetarInstance(testName, { @@ -130,7 +130,7 @@ import { firestoreDeepEqual } from '../helpers/firestoreDeepEqual.js' }) } { - // these tests are not really testing reverting the remote store, only the local store: + // these tests are not really testing reverting the remote store, only the cache store: const testName = 'revert: replace' test(testName, async () => { const { pokedexModule } = await createMagnetarInstance(testName, { diff --git a/packages/plugin-firestore-admin/test/helpers/createMagnetarInstance.ts b/packages/plugin-firestore-admin/test/helpers/createMagnetarInstance.ts index ff7497dd..05d71c08 100644 --- a/packages/plugin-firestore-admin/test/helpers/createMagnetarInstance.ts +++ b/packages/plugin-firestore-admin/test/helpers/createMagnetarInstance.ts @@ -36,7 +36,7 @@ export async function createMagnetarInstance( }: { insertDocs?: { [path: string]: { [key: string]: any } } remoteConfig?: { [key: string]: any } - } = {} + } = {}, ): Promise<{ pokedexModule: CollectionInstance trainerModule: DocInstance @@ -64,21 +64,20 @@ export async function createMagnetarInstance( await Promise.all(insertPromises) // create & prepare the modules - const local = CreatePluginLocal({ storeName: 'local', generateRandomId }) + const cache = CreatePluginLocal({ storeName: 'cache', generateRandomId }) const remote = CreatePluginRemote({ db }) const magnetar = Magnetar({ - localStoreName: 'local', - stores: { local, remote }, + stores: { cache, remote }, executionOrder: { - read: ['local', 'remote'], - write: ['local', 'remote'], - delete: ['local', 'remote'], + read: ['cache', 'remote'], + write: ['cache', 'remote'], + delete: ['cache', 'remote'], }, }) const pokedexModule = magnetar.collection('pokedex', { configPerStore: { - local: { initialData: initialEntriesPokedex }, + cache: { initialData: initialEntriesPokedex }, remote: { firestorePath: `magnetarTests/${testName}/pokedex`, ...remoteConfig }, }, }) @@ -101,7 +100,7 @@ export async function createMagnetarInstance( const trainerModule = magnetar.doc('app-data/trainer', { configPerStore: { - local: { initialData: getInitialDataDocument() }, + cache: { initialData: getInitialDataDocument() }, remote: { firestorePath: `magnetarTests/${testName}`, ...remoteConfig }, }, }) diff --git a/packages/plugin-firestore-admin/test/internal/revert.test.ts b/packages/plugin-firestore-admin/test/internal/revert.test.ts index 56ba1e2e..2365e0dc 100644 --- a/packages/plugin-firestore-admin/test/internal/revert.test.ts +++ b/packages/plugin-firestore-admin/test/internal/revert.test.ts @@ -4,10 +4,10 @@ import { createMagnetarInstance } from '../helpers/createMagnetarInstance.js' import { firestoreDeepEqual } from '../helpers/firestoreDeepEqual.js' { - const testName = 'revert: (remote β†’ local) insert (document)' + const testName = 'revert: (remote β†’ cache) insert (document)' test(testName, async () => { const { pokedexModule } = await createMagnetarInstance(testName) - const payload = { ...pokedex(7), shouldFail: 'local' } + const payload = { ...pokedex(7), shouldFail: 'cache' } assert.deepEqual(pokedexModule.doc('7').data, undefined) const squirtle = pokedexModule.doc('7') @@ -15,7 +15,7 @@ import { firestoreDeepEqual } from '../helpers/firestoreDeepEqual.js' try { await squirtle.insert(payload, { onError: 'revert', - executionOrder: ['remote', 'local'], + executionOrder: ['remote', 'cache'], on: { success: async ({ storeName }) => { if (storeName !== 'remote') return @@ -33,15 +33,15 @@ import { firestoreDeepEqual } from '../helpers/firestoreDeepEqual.js' }) } { - const testName = 'revert: (remote β†’ local) insert (collection) β†’ random ID' + const testName = 'revert: (remote β†’ cache) insert (collection) β†’ random ID' test(testName, async () => { const { pokedexModule } = await createMagnetarInstance(testName) - const payload = { ...pokedex(7), shouldFail: 'local' } + const payload = { ...pokedex(7), shouldFail: 'cache' } try { await pokedexModule.insert(payload, { onError: 'revert', - executionOrder: ['remote', 'local'], + executionOrder: ['remote', 'cache'], on: { success: async ({ storeName }) => { if (storeName !== 'remote') return @@ -62,9 +62,9 @@ import { firestoreDeepEqual } from '../helpers/firestoreDeepEqual.js' // Todo: currently not possible // see: https://github.com/cycraft/core/issues/2 // { -// const testName = 'revert: (remote β†’ local) delete (document)' +// const testName = 'revert: (remote β†’ cache) delete (document)' // test(testName, async t => { -// const payload = { ...pokedex(7), shouldFailDelete: 'local' } +// const payload = { ...pokedex(7), shouldFailDelete: 'cache' } // const { pokedexModule } = await createMagnetarInstance(testName) // assert.deepEqual(pokedexModule.doc('7').data, undefined) // await pokedexModule.insert(payload) @@ -75,7 +75,7 @@ import { firestoreDeepEqual } from '../helpers/firestoreDeepEqual.js' // .doc('7') // .delete(undefined, { // onError: 'revert', -// executionOrder: ['remote', 'local'], +// executionOrder: ['remote', 'cache'], // on: { // success: async ({ storeName }) => { // if (storeName !== 'remote') return @@ -99,7 +99,7 @@ import { firestoreDeepEqual } from '../helpers/firestoreDeepEqual.js' // } { - // this tests is _not really_ testing reverting the remote store, they test if the local store is reverted and if the remote store stays untouched on an error + // this tests is _not really_ testing reverting the remote store, they test if the cache store is reverted and if the remote store stays untouched on an error const testName = 'revert: merge (with extra checks)' test(testName, async () => { const { pokedexModule } = await createMagnetarInstance(testName, { @@ -114,7 +114,7 @@ import { firestoreDeepEqual } from '../helpers/firestoreDeepEqual.js' onError: 'revert', on: { success: ({ storeName }) => { - if (storeName !== 'local') return + if (storeName !== 'cache') return const expectedMidway = { id: 1, name: 'Bulbasaur', @@ -142,7 +142,7 @@ import { firestoreDeepEqual } from '../helpers/firestoreDeepEqual.js' }) } { - // this tests is _not really_ testing reverting the remote store, they test if the local store is reverted and if the remote store stays untouched on an error + // this tests is _not really_ testing reverting the remote store, they test if the cache store is reverted and if the remote store stays untouched on an error const testName = 'revert: assign (with extra checks)' test(testName, async () => { const { pokedexModule } = await createMagnetarInstance(testName, { @@ -157,7 +157,7 @@ import { firestoreDeepEqual } from '../helpers/firestoreDeepEqual.js' onError: 'revert', on: { success: ({ storeName }) => { - if (storeName !== 'local') return + if (storeName !== 'cache') return const expectedMidway = { id: 1, name: 'Bulbasaur', @@ -180,7 +180,7 @@ import { firestoreDeepEqual } from '../helpers/firestoreDeepEqual.js' }) } { - // this tests is _not really_ testing reverting the remote store, they test if the local store is reverted and if the remote store stays untouched on an error + // this tests is _not really_ testing reverting the remote store, they test if the cache store is reverted and if the remote store stays untouched on an error const testName = 'revert: replace (with extra checks)' test(testName, async () => { const { pokedexModule } = await createMagnetarInstance(testName, { @@ -195,7 +195,7 @@ import { firestoreDeepEqual } from '../helpers/firestoreDeepEqual.js' onError: 'revert', on: { success: ({ storeName }) => { - if (storeName !== 'local') return + if (storeName !== 'cache') return const expectedMidway = { base: { HP: undefined } } assert.deepEqual(pokedexModule.doc('1').data, expectedMidway as any) }, diff --git a/packages/plugin-firestore/package.json b/packages/plugin-firestore/package.json index b2401ea4..1ca4e37e 100644 --- a/packages/plugin-firestore/package.json +++ b/packages/plugin-firestore/package.json @@ -58,6 +58,8 @@ "vue-store", "firestore", "data-store", + "data-cache", + "cache-store", "local-store", "remote-store", "global-store", diff --git a/packages/plugin-firestore/test/external/mergeAssignReplace.test.ts b/packages/plugin-firestore/test/external/mergeAssignReplace.test.ts index c8bb106c..5c8e0f45 100644 --- a/packages/plugin-firestore/test/external/mergeAssignReplace.test.ts +++ b/packages/plugin-firestore/test/external/mergeAssignReplace.test.ts @@ -86,7 +86,7 @@ import { firestoreDeepEqual } from '../helpers/firestoreDeepEqual.js' }) } { - // these tests are not really testing reverting the remote store, only the local store: + // these tests are not really testing reverting the remote store, only the cache store: const testName = 'revert: merge' test(testName, async () => { const { pokedexModule } = await createMagnetarInstance(testName, { @@ -108,7 +108,7 @@ import { firestoreDeepEqual } from '../helpers/firestoreDeepEqual.js' }) } { - // these tests are not really testing reverting the remote store, only the local store: + // these tests are not really testing reverting the remote store, only the cache store: const testName = 'revert: assign' test(testName, async () => { const { pokedexModule } = await createMagnetarInstance(testName, { @@ -130,7 +130,7 @@ import { firestoreDeepEqual } from '../helpers/firestoreDeepEqual.js' }) } { - // these tests are not really testing reverting the remote store, only the local store: + // these tests are not really testing reverting the remote store, only the cache store: const testName = 'revert: replace' test(testName, async () => { const { pokedexModule } = await createMagnetarInstance(testName, { diff --git a/packages/plugin-firestore/test/helpers/createMagnetarInstance.ts b/packages/plugin-firestore/test/helpers/createMagnetarInstance.ts index f0cb7ada..22ee0322 100644 --- a/packages/plugin-firestore/test/helpers/createMagnetarInstance.ts +++ b/packages/plugin-firestore/test/helpers/createMagnetarInstance.ts @@ -37,7 +37,7 @@ export async function createMagnetarInstance( }: { insertDocs?: { [path: string]: { [key: string]: any } } remoteConfig?: { [key: string]: any } - } = {} + } = {}, ): Promise<{ pokedexModule: CollectionInstance trainerModule: DocInstance @@ -65,21 +65,20 @@ export async function createMagnetarInstance( await Promise.all(insertPromises) // create & prepare the modules - const local = CreatePluginLocal({ storeName: 'local', generateRandomId }) + const cache = CreatePluginLocal({ storeName: 'cache', generateRandomId }) const remote = CreatePluginRemote({ db }) const magnetar = Magnetar({ - localStoreName: 'local', - stores: { local, remote }, + stores: { cache, remote }, executionOrder: { - read: ['local', 'remote'], - write: ['local', 'remote'], - delete: ['local', 'remote'], + read: ['cache', 'remote'], + write: ['cache', 'remote'], + delete: ['cache', 'remote'], }, }) const pokedexModule = magnetar.collection('pokedex', { configPerStore: { - local: { initialData: initialEntriesPokedex }, + cache: { initialData: initialEntriesPokedex }, remote: { firestorePath: `magnetarTests/${testName}/pokedex`, ...remoteConfig }, }, }) @@ -102,7 +101,7 @@ export async function createMagnetarInstance( const trainerModule = magnetar.doc('app-data/trainer', { configPerStore: { - local: { initialData: getInitialDataDocument() }, + cache: { initialData: getInitialDataDocument() }, remote: { firestorePath: `magnetarTests/${testName}`, ...remoteConfig }, }, }) diff --git a/packages/plugin-firestore/test/internal/revert.test.ts b/packages/plugin-firestore/test/internal/revert.test.ts index 56ba1e2e..2365e0dc 100644 --- a/packages/plugin-firestore/test/internal/revert.test.ts +++ b/packages/plugin-firestore/test/internal/revert.test.ts @@ -4,10 +4,10 @@ import { createMagnetarInstance } from '../helpers/createMagnetarInstance.js' import { firestoreDeepEqual } from '../helpers/firestoreDeepEqual.js' { - const testName = 'revert: (remote β†’ local) insert (document)' + const testName = 'revert: (remote β†’ cache) insert (document)' test(testName, async () => { const { pokedexModule } = await createMagnetarInstance(testName) - const payload = { ...pokedex(7), shouldFail: 'local' } + const payload = { ...pokedex(7), shouldFail: 'cache' } assert.deepEqual(pokedexModule.doc('7').data, undefined) const squirtle = pokedexModule.doc('7') @@ -15,7 +15,7 @@ import { firestoreDeepEqual } from '../helpers/firestoreDeepEqual.js' try { await squirtle.insert(payload, { onError: 'revert', - executionOrder: ['remote', 'local'], + executionOrder: ['remote', 'cache'], on: { success: async ({ storeName }) => { if (storeName !== 'remote') return @@ -33,15 +33,15 @@ import { firestoreDeepEqual } from '../helpers/firestoreDeepEqual.js' }) } { - const testName = 'revert: (remote β†’ local) insert (collection) β†’ random ID' + const testName = 'revert: (remote β†’ cache) insert (collection) β†’ random ID' test(testName, async () => { const { pokedexModule } = await createMagnetarInstance(testName) - const payload = { ...pokedex(7), shouldFail: 'local' } + const payload = { ...pokedex(7), shouldFail: 'cache' } try { await pokedexModule.insert(payload, { onError: 'revert', - executionOrder: ['remote', 'local'], + executionOrder: ['remote', 'cache'], on: { success: async ({ storeName }) => { if (storeName !== 'remote') return @@ -62,9 +62,9 @@ import { firestoreDeepEqual } from '../helpers/firestoreDeepEqual.js' // Todo: currently not possible // see: https://github.com/cycraft/core/issues/2 // { -// const testName = 'revert: (remote β†’ local) delete (document)' +// const testName = 'revert: (remote β†’ cache) delete (document)' // test(testName, async t => { -// const payload = { ...pokedex(7), shouldFailDelete: 'local' } +// const payload = { ...pokedex(7), shouldFailDelete: 'cache' } // const { pokedexModule } = await createMagnetarInstance(testName) // assert.deepEqual(pokedexModule.doc('7').data, undefined) // await pokedexModule.insert(payload) @@ -75,7 +75,7 @@ import { firestoreDeepEqual } from '../helpers/firestoreDeepEqual.js' // .doc('7') // .delete(undefined, { // onError: 'revert', -// executionOrder: ['remote', 'local'], +// executionOrder: ['remote', 'cache'], // on: { // success: async ({ storeName }) => { // if (storeName !== 'remote') return @@ -99,7 +99,7 @@ import { firestoreDeepEqual } from '../helpers/firestoreDeepEqual.js' // } { - // this tests is _not really_ testing reverting the remote store, they test if the local store is reverted and if the remote store stays untouched on an error + // this tests is _not really_ testing reverting the remote store, they test if the cache store is reverted and if the remote store stays untouched on an error const testName = 'revert: merge (with extra checks)' test(testName, async () => { const { pokedexModule } = await createMagnetarInstance(testName, { @@ -114,7 +114,7 @@ import { firestoreDeepEqual } from '../helpers/firestoreDeepEqual.js' onError: 'revert', on: { success: ({ storeName }) => { - if (storeName !== 'local') return + if (storeName !== 'cache') return const expectedMidway = { id: 1, name: 'Bulbasaur', @@ -142,7 +142,7 @@ import { firestoreDeepEqual } from '../helpers/firestoreDeepEqual.js' }) } { - // this tests is _not really_ testing reverting the remote store, they test if the local store is reverted and if the remote store stays untouched on an error + // this tests is _not really_ testing reverting the remote store, they test if the cache store is reverted and if the remote store stays untouched on an error const testName = 'revert: assign (with extra checks)' test(testName, async () => { const { pokedexModule } = await createMagnetarInstance(testName, { @@ -157,7 +157,7 @@ import { firestoreDeepEqual } from '../helpers/firestoreDeepEqual.js' onError: 'revert', on: { success: ({ storeName }) => { - if (storeName !== 'local') return + if (storeName !== 'cache') return const expectedMidway = { id: 1, name: 'Bulbasaur', @@ -180,7 +180,7 @@ import { firestoreDeepEqual } from '../helpers/firestoreDeepEqual.js' }) } { - // this tests is _not really_ testing reverting the remote store, they test if the local store is reverted and if the remote store stays untouched on an error + // this tests is _not really_ testing reverting the remote store, they test if the cache store is reverted and if the remote store stays untouched on an error const testName = 'revert: replace (with extra checks)' test(testName, async () => { const { pokedexModule } = await createMagnetarInstance(testName, { @@ -195,7 +195,7 @@ import { firestoreDeepEqual } from '../helpers/firestoreDeepEqual.js' onError: 'revert', on: { success: ({ storeName }) => { - if (storeName !== 'local') return + if (storeName !== 'cache') return const expectedMidway = { base: { HP: undefined } } assert.deepEqual(pokedexModule.doc('1').data, expectedMidway as any) }, diff --git a/packages/plugin-simple-store/package.json b/packages/plugin-simple-store/package.json index 83d1ea0d..410858ed 100644 --- a/packages/plugin-simple-store/package.json +++ b/packages/plugin-simple-store/package.json @@ -51,6 +51,8 @@ "vue-store", "firestore", "data-store", + "data-cache", + "cache-store", "local-store", "remote-store", "global-store", diff --git a/packages/plugin-simple-store/src/CreatePlugin.ts b/packages/plugin-simple-store/src/CreatePlugin.ts index a1619412..baad3e09 100644 --- a/packages/plugin-simple-store/src/CreatePlugin.ts +++ b/packages/plugin-simple-store/src/CreatePlugin.ts @@ -42,7 +42,7 @@ export type MakeRestoreBackup = (collectionPath: string, docId: string) => void export const CreatePlugin: MagnetarPlugin = ( simpleStoreOptions: SimpleStoreOptions, ): PluginInstance => { - // this is the local state of the plugin, each plugin that acts as a "local Store Plugin" should have something similar + // this is the cache state of the plugin, each plugin that acts as a "cache Store Plugin" should have something similar // do not define the store plugin data on the top level! Be sure to define it inside the scope of the plugin function!! const data: { [collectionPath: string]: Map } = {} const exists: { [docPath: string]: undefined | 'error' | boolean } = {} @@ -84,7 +84,7 @@ export const CreatePlugin: MagnetarPlugin = ( } /** - * This must be provided by Store Plugins that have "local" data. It is triggered ONCE when the module (doc or collection) is instantiated. In any case, an empty Map for the collectionPath (to be derived from the modulePath) must be set up. + * This must be provided by Store Plugins that have "cache" data. It is triggered ONCE when the module (doc or collection) is instantiated. In any case, an empty Map for the collectionPath (to be derived from the modulePath) must be set up. */ const modulesAlreadySetup = new Set() const setupModule = ({ @@ -114,7 +114,7 @@ export const CreatePlugin: MagnetarPlugin = ( } /** - * This must be provided by Store Plugins that have "local" data. It is triggered EVERY TIME the module's data is accessed. The `modulePath` will be either that of a "collection" or a "doc". When it's a collection, it must return a Map with the ID as key and the doc data as value `Map`. When it's a "doc" it must return the doc data directly `DocDataType`. + * This must be provided by Store Plugins that have "cache" data. It is triggered EVERY TIME the module's data is accessed. The `modulePath` will be either that of a "collection" or a "doc". When it's a collection, it must return a Map with the ID as key and the doc data as value `Map`. When it's a "doc" it must return the doc data directly `DocDataType`. */ const getModuleData = ({ collectionPath, @@ -138,7 +138,7 @@ export const CreatePlugin: MagnetarPlugin = ( } /** - * This must be provided by Store Plugins that have "local" data. It should signify wether or not the document exists. Must return `undefined` when not sure (if the document was never fetched). It is triggered EVERY TIME the module's `.data` is accessed. + * This must be provided by Store Plugins that have "cache" data. It should signify wether or not the document exists. Must return `undefined` when not sure (if the document was never fetched). It is triggered EVERY TIME the module's `.data` is accessed. */ const getModuleExists = ({ collectionPath, @@ -148,7 +148,7 @@ export const CreatePlugin: MagnetarPlugin = ( } /** - * This must be provided by Store Plugins that have "local" data. It is triggered EVERY TIME the module's count is accessed. + * This must be provided by Store Plugins that have "cache" data. It is triggered EVERY TIME the module's count is accessed. */ const getModuleAggregate = ( kind: 'sum' | 'average', @@ -163,7 +163,7 @@ export const CreatePlugin: MagnetarPlugin = ( } /** - * This must be provided by Store Plugins that have "local" data. It is triggered EVERY TIME the module's count is accessed. + * This must be provided by Store Plugins that have "cache" data. It is triggered EVERY TIME the module's count is accessed. */ const getModuleCount = ({ collectionPath, diff --git a/packages/plugin-simple-store/src/actions/fetch.ts b/packages/plugin-simple-store/src/actions/fetch.ts index 007141b3..89b79a5e 100644 --- a/packages/plugin-simple-store/src/actions/fetch.ts +++ b/packages/plugin-simple-store/src/actions/fetch.ts @@ -14,7 +14,7 @@ import { insertActionFactory } from './insert.js' export function fetchActionFactory( data: { [collectionPath: string]: Map }, exists: { [docPath: string]: undefined | 'error' | boolean }, - simpleStoreOptions: SimpleStoreOptions + simpleStoreOptions: SimpleStoreOptions, ): PluginFetchAction { return function ({ payload, @@ -37,12 +37,12 @@ export function fetchActionFactory( startAfter, }) if (collectionData.size > 0) { - const localDocs: DocMetadata[] = [...collectionData.entries()].map(([_docId, data]) => ({ + const cachedDocs: DocMetadata[] = [...collectionData.entries()].map(([_docId, data]) => ({ data, exists: 'unknown', id: _docId, })) - const fetchResponse: FetchResponse = { docs: localDocs } + const fetchResponse: FetchResponse = { docs: cachedDocs } return fetchResponse // if size === 0 fall through to returning DoOnFetch down below } } @@ -52,13 +52,13 @@ export function fetchActionFactory( */ const itSureExists = exists[`${collectionPath}/${docId}`] === true if (docId && itSureExists) { - const localDoc = data[collectionPath]?.get(docId) + const cachedDoc = data[collectionPath]?.get(docId) // if already fetched - if (localDoc) { + if (cachedDoc) { const fetchResponse: FetchResponse = { docs: [ { - data: localDoc, + data: cachedDoc, exists: 'unknown', id: docId, }, @@ -67,7 +67,7 @@ export function fetchActionFactory( return fetchResponse } // if not yet fetched - if (!localDoc) { + if (!cachedDoc) { // fall through to returning DoOnFetch down below } } @@ -92,12 +92,12 @@ export function fetchActionFactory( exists[docPath] = meta.exists } - // abort updating local state if the payload is undefined + // abort updating local cache state if the payload is undefined if (_payload === undefined) return insertActionFactory( data, - simpleStoreOptions + simpleStoreOptions, )({ payload: _payload, collectionPath, diff --git a/packages/plugin-simple-store/src/actions/fetchAggregate.ts b/packages/plugin-simple-store/src/actions/fetchAggregate.ts index 7893ee72..9a5e4dc3 100644 --- a/packages/plugin-simple-store/src/actions/fetchAggregate.ts +++ b/packages/plugin-simple-store/src/actions/fetchAggregate.ts @@ -29,7 +29,7 @@ export function fetchAggregateActionFactory( const pathId = getPathWhereIdentifier(collectionPath, pluginModuleConfig) const doOnFetchSumAggregate: DoOnFetchAggregate = (count) => { - // abort updating local state if the payload was set to undefined + // abort updating local cache state if the payload was set to undefined if (count === undefined) return pathAggregateDic[pathId] = merge( diff --git a/packages/plugin-simple-store/src/actions/fetchCount.ts b/packages/plugin-simple-store/src/actions/fetchCount.ts index e8795b72..159a8a04 100644 --- a/packages/plugin-simple-store/src/actions/fetchCount.ts +++ b/packages/plugin-simple-store/src/actions/fetchCount.ts @@ -22,7 +22,7 @@ export function fetchCountActionFactory( const pathId = getPathWhereIdentifier(collectionPath, pluginModuleConfig) const doOnFetchAggregateAction: DoOnFetchAggregate = (count) => { - // abort updating local state if the payload was set to undefined + // abort updating local cache state if the payload was set to undefined if (count === undefined) return pathCountDic[pathId] = count diff --git a/packages/plugin-simple-store/src/actions/stream.ts b/packages/plugin-simple-store/src/actions/stream.ts index 201d371a..e7d4d7b1 100644 --- a/packages/plugin-simple-store/src/actions/stream.ts +++ b/packages/plugin-simple-store/src/actions/stream.ts @@ -11,7 +11,7 @@ import { insertActionFactory } from './insert.js' export function streamActionFactory( data: { [collectionPath: string]: Map }, - simpleStoreOptions: SimpleStoreOptions + simpleStoreOptions: SimpleStoreOptions, ): PluginStreamAction { return function ({ payload, @@ -27,13 +27,13 @@ export function streamActionFactory( // hover over the prop names below to see more info on when they are triggered: const doOnStream: DoOnStream = { added: (payload, meta) => { - // abort updating local state if the payload was set to undefined + // abort updating local cache state if the payload was set to undefined if (payload === undefined) return undefined const _docId = docId || `${meta.id}` insertActionFactory( data, - simpleStoreOptions + simpleStoreOptions, )({ payload, collectionPath, @@ -44,13 +44,13 @@ export function streamActionFactory( return undefined }, modified: (payload, meta) => { - // abort updating local state if the payload was set to undefined + // abort updating local cache state if the payload was set to undefined if (payload === undefined) return undefined const _docId = docId || `${meta.id}` insertActionFactory( data, - simpleStoreOptions + simpleStoreOptions, )({ payload, collectionPath, @@ -61,7 +61,7 @@ export function streamActionFactory( return undefined }, removed: (payload, meta) => { - // abort updating local state if the payload was set to undefined + // abort updating local cache state if the payload was set to undefined if (payload === undefined) return undefined const collectionPathDocIdToDelete: [string, string] = isFullString(docId) @@ -72,7 +72,7 @@ export function streamActionFactory( const [_cPath, _dId] = collectionPathDocIdToDelete deleteActionFactory( data, - simpleStoreOptions + simpleStoreOptions, )({ payload: undefined, collectionPath: _cPath, diff --git a/packages/plugin-simple-store/test/external/collectionGroup.test.ts b/packages/plugin-simple-store/test/external/collectionGroup.test.ts index 30ae89f5..90aba1cc 100644 --- a/packages/plugin-simple-store/test/external/collectionGroup.test.ts +++ b/packages/plugin-simple-store/test/external/collectionGroup.test.ts @@ -9,7 +9,7 @@ test('fetch (collectionGroup)', async () => { // } catch (error) { // assert.fail(JSON.stringify(error)) // } - // // the local store should have updated its data to the remote store (via the plugin's onNextStoresSuccess handler) + // // the cache store should have updated its data to the remote store (via the plugin's onNextStoresSuccess handler) // assert.deepEqual(trainerModule.data, { name: 'Luca', age: 10, dream: 'job' }) }) @@ -23,6 +23,6 @@ test('fetch (collectionGroup)', async () => { // } catch (error) { // assert.fail(JSON.stringify(error)) // } -// // the local store should have updated its data to the remote store (via the plugin's onNextStoresSuccess handler) +// // the cache store should have updated its data to the remote store (via the plugin's onNextStoresSuccess handler) // assert.deepEqual(trainerModule.data, { name: 'Luca', age: 10, dream: 'job' }) // }) diff --git a/packages/plugin-simple-store/test/external/fetch.test.ts b/packages/plugin-simple-store/test/external/fetch.test.ts index baf33e48..aa94338a 100644 --- a/packages/plugin-simple-store/test/external/fetch.test.ts +++ b/packages/plugin-simple-store/test/external/fetch.test.ts @@ -41,7 +41,7 @@ test('fetch (document) if unfetched', async () => { assert.fail(JSON.stringify(error)) } // even though we haven't _force_ fetched, the data is still fetched - // because even though the the local state was already there, we had never executed `fetch` or `stream` once in this session + // because even though the the cached state was already there, we had never executed `fetch` or `stream` once in this session assert.deepEqual(trainerModule.data, { name: 'Luca', age: 10, dream: 'job' }) }) diff --git a/packages/plugin-simple-store/test/helpers/createMagnetarInstance.ts b/packages/plugin-simple-store/test/helpers/createMagnetarInstance.ts index 2695be6c..9b3a1a47 100644 --- a/packages/plugin-simple-store/test/helpers/createMagnetarInstance.ts +++ b/packages/plugin-simple-store/test/helpers/createMagnetarInstance.ts @@ -27,26 +27,25 @@ export function createMagnetarInstance(): { trainerModule: DocInstance magnetar: MagnetarInstance } { - const local = CreatePluginLocal({ generateRandomId }) + const cache = CreatePluginLocal({ generateRandomId }) const remote = CreatePluginRemote({ storeName: 'remote' }) const magnetar = Magnetar({ - localStoreName: 'local', - stores: { local, remote }, + stores: { cache, remote }, executionOrder: { - read: ['local', 'remote'], - write: ['local', 'remote'], - delete: ['local', 'remote'], + read: ['cache', 'remote'], + write: ['cache', 'remote'], + delete: ['cache', 'remote'], }, }) const pokedexModule = magnetar.collection('pokedex', { configPerStore: { - local: { initialData: getInitialDataCollection() }, // path for the plugin + cache: { initialData: getInitialDataCollection() }, // path for the plugin remote: {}, // path for the plugin }, }) const trainerModule = magnetar.doc('app-data/trainer', { configPerStore: { - local: { initialData: getInitialDataDocument() }, // path for the plugin + cache: { initialData: getInitialDataDocument() }, // path for the plugin remote: {}, // path for the plugin }, }) diff --git a/packages/plugin-vue3/package.json b/packages/plugin-vue3/package.json index ec994063..4e13dc66 100644 --- a/packages/plugin-vue3/package.json +++ b/packages/plugin-vue3/package.json @@ -56,6 +56,8 @@ "vue-store", "firestore", "data-store", + "data-cache", + "cache-store", "local-store", "remote-store", "global-store", diff --git a/packages/plugin-vue3/src/CreatePlugin.ts b/packages/plugin-vue3/src/CreatePlugin.ts index 543609a5..3717f4a9 100644 --- a/packages/plugin-vue3/src/CreatePlugin.ts +++ b/packages/plugin-vue3/src/CreatePlugin.ts @@ -50,7 +50,7 @@ export type MakeRestoreBackup = (collectionPath: string, docId: string) => void export const CreatePlugin: MagnetarPlugin = ( vue3StoreOptions: Vue3StoreOptions, ): PluginInstance => { - // this is the local state of the plugin, each plugin that acts as a "local Store Plugin" should have something similar + // this is the local cache state of the plugin, each plugin that acts as a "cache Store Plugin" should have something similar // do not define the store plugin data on the top level! Be sure to define it inside the scope of the plugin function!! const data: { [collectionPath: string]: Map } = {} const exists: { [docPath: string]: undefined | 'error' | boolean } = reactive({}) @@ -93,7 +93,7 @@ export const CreatePlugin: MagnetarPlugin = ( } /** - * This must be provided by Store Plugins that have "local" data. It is triggered ONCE when the module (doc or collection) is instantiated. In any case, an empty Map for the collectionPath (to be derived from the modulePath) must be set up. + * This must be provided by Store Plugins that have "cache" data. It is triggered ONCE when the module (doc or collection) is instantiated. In any case, an empty Map for the collectionPath (to be derived from the modulePath) must be set up. */ const modulesAlreadySetup = new Set() const setupModule = ({ @@ -122,7 +122,7 @@ export const CreatePlugin: MagnetarPlugin = ( } /** - * This must be provided by Store Plugins that have "local" data. It is triggered EVERY TIME the module's data is accessed. The `modulePath` will be either that of a "collection" or a "doc". When it's a collection, it must return a Map with the ID as key and the doc data as value `Map`. When it's a "doc" it must return the doc data directly `DocDataType`. + * This must be provided by Store Plugins that have "cache" data. It is triggered EVERY TIME the module's data is accessed. The `modulePath` will be either that of a "collection" or a "doc". When it's a collection, it must return a Map with the ID as key and the doc data as value `Map`. When it's a "doc" it must return the doc data directly `DocDataType`. */ const getModuleData = ({ collectionPath, @@ -146,7 +146,7 @@ export const CreatePlugin: MagnetarPlugin = ( } /** - * This must be provided by Store Plugins that have "local" data. It should signify wether or not the document exists. Must return `undefined` when not sure (if the document was never fetched). It is triggered EVERY TIME the module's `.data` is accessed. + * This must be provided by Store Plugins that have "cache" data. It should signify wether or not the document exists. Must return `undefined` when not sure (if the document was never fetched). It is triggered EVERY TIME the module's `.data` is accessed. */ const getModuleExists = ({ collectionPath, @@ -156,7 +156,7 @@ export const CreatePlugin: MagnetarPlugin = ( } /** - * This must be provided by Store Plugins that have "local" data. It is triggered EVERY TIME the module's count is accessed. + * This must be provided by Store Plugins that have "cache" data. It is triggered EVERY TIME the module's count is accessed. */ const getModuleAggregate = ( kind: 'sum' | 'average', @@ -171,7 +171,7 @@ export const CreatePlugin: MagnetarPlugin = ( } /** - * This must be provided by Store Plugins that have "local" data. It is triggered EVERY TIME the module's count is accessed. + * This must be provided by Store Plugins that have "cache" data. It is triggered EVERY TIME the module's count is accessed. */ const getModuleCount = ({ collectionPath, diff --git a/packages/plugin-vue3/src/actions/fetch.ts b/packages/plugin-vue3/src/actions/fetch.ts index bc9c3882..335c1fda 100644 --- a/packages/plugin-vue3/src/actions/fetch.ts +++ b/packages/plugin-vue3/src/actions/fetch.ts @@ -37,12 +37,12 @@ export function fetchActionFactory( startAfter, }) if (collectionData.size > 0) { - const localDocs: DocMetadata[] = [...collectionData.entries()].map(([_docId, data]) => ({ + const cachedDocs: DocMetadata[] = [...collectionData.entries()].map(([_docId, data]) => ({ data, exists: 'unknown', id: _docId, })) - const fetchResponse: FetchResponse = { docs: localDocs } + const fetchResponse: FetchResponse = { docs: cachedDocs } return fetchResponse // if size === 0 fall through to returning DoOnFetch down below } } @@ -52,13 +52,13 @@ export function fetchActionFactory( */ const itSureExists = exists[`${collectionPath}/${docId}`] === true if (docId && itSureExists) { - const localDoc = data[collectionPath]?.get(docId) + const cachedDoc = data[collectionPath]?.get(docId) // if already fetched - if (localDoc) { + if (cachedDoc) { const fetchResponse: FetchResponse = { docs: [ { - data: localDoc, + data: cachedDoc, exists: 'unknown', id: docId, }, @@ -67,7 +67,7 @@ export function fetchActionFactory( return fetchResponse } // if not yet fetched - if (!localDoc) { + if (!cachedDoc) { // fall through to returning DoOnFetch down below } } @@ -92,7 +92,7 @@ export function fetchActionFactory( exists[docPath] = meta.exists } - // abort updating local state if the payload is undefined + // abort updating local cache state if the payload is undefined if (_payload === undefined) return insertActionFactory( diff --git a/packages/plugin-vue3/src/actions/fetchAggregate.ts b/packages/plugin-vue3/src/actions/fetchAggregate.ts index 2af1946c..a5986ae2 100644 --- a/packages/plugin-vue3/src/actions/fetchAggregate.ts +++ b/packages/plugin-vue3/src/actions/fetchAggregate.ts @@ -29,7 +29,7 @@ export function fetchAggregateActionFactory( const pathId = getPathWhereIdentifier(collectionPath, pluginModuleConfig) const doOnFetchSumAggregate: DoOnFetchAggregate = (count) => { - // abort updating local state if the payload was set to undefined + // abort updating local cache state if the payload was set to undefined if (count === undefined) return pathAggregateDic[pathId] = merge( diff --git a/packages/plugin-vue3/src/actions/fetchCount.ts b/packages/plugin-vue3/src/actions/fetchCount.ts index 1e742908..4bc02b1b 100644 --- a/packages/plugin-vue3/src/actions/fetchCount.ts +++ b/packages/plugin-vue3/src/actions/fetchCount.ts @@ -22,7 +22,7 @@ export function fetchCountActionFactory( const pathId = getPathWhereIdentifier(collectionPath, pluginModuleConfig) const doOnFetchAggregateAction: DoOnFetchAggregate = (count) => { - // abort updating local state if the payload was set to undefined + // abort updating local cache state if the payload was set to undefined if (count === undefined) return pathCountDic[pathId] = count diff --git a/packages/plugin-vue3/src/actions/stream.ts b/packages/plugin-vue3/src/actions/stream.ts index 5e27e02c..44e81009 100644 --- a/packages/plugin-vue3/src/actions/stream.ts +++ b/packages/plugin-vue3/src/actions/stream.ts @@ -27,7 +27,7 @@ export function streamActionFactory( // hover over the prop names below to see more info on when they are triggered: const doOnStream: DoOnStream = { added: (payload, meta) => { - // abort updating local state if the payload was set to undefined + // abort updating local cache state if the payload was set to undefined if (payload === undefined) return undefined const _docId = docId || `${meta.id}` @@ -44,7 +44,7 @@ export function streamActionFactory( return undefined }, modified: (payload, meta) => { - // abort updating local state if the payload was set to undefined + // abort updating local cache state if the payload was set to undefined if (payload === undefined) return undefined const _docId = docId || `${meta.id}` @@ -61,7 +61,7 @@ export function streamActionFactory( return undefined }, removed: (payload, meta) => { - // abort updating local state if the payload was set to undefined + // abort updating local cache state if the payload was set to undefined if (payload === undefined) return undefined const collectionPathDocIdToDelete: [string, string] = isFullString(docId) diff --git a/packages/plugin-vue3/test/external/collectionGroup.test.ts b/packages/plugin-vue3/test/external/collectionGroup.test.ts index 30ae89f5..90aba1cc 100644 --- a/packages/plugin-vue3/test/external/collectionGroup.test.ts +++ b/packages/plugin-vue3/test/external/collectionGroup.test.ts @@ -9,7 +9,7 @@ test('fetch (collectionGroup)', async () => { // } catch (error) { // assert.fail(JSON.stringify(error)) // } - // // the local store should have updated its data to the remote store (via the plugin's onNextStoresSuccess handler) + // // the cache store should have updated its data to the remote store (via the plugin's onNextStoresSuccess handler) // assert.deepEqual(trainerModule.data, { name: 'Luca', age: 10, dream: 'job' }) }) @@ -23,6 +23,6 @@ test('fetch (collectionGroup)', async () => { // } catch (error) { // assert.fail(JSON.stringify(error)) // } -// // the local store should have updated its data to the remote store (via the plugin's onNextStoresSuccess handler) +// // the cache store should have updated its data to the remote store (via the plugin's onNextStoresSuccess handler) // assert.deepEqual(trainerModule.data, { name: 'Luca', age: 10, dream: 'job' }) // }) diff --git a/packages/plugin-vue3/test/external/fetch.test.ts b/packages/plugin-vue3/test/external/fetch.test.ts index 08e7f283..0ef397bc 100644 --- a/packages/plugin-vue3/test/external/fetch.test.ts +++ b/packages/plugin-vue3/test/external/fetch.test.ts @@ -41,7 +41,7 @@ test('fetch (document) if unfetched', async () => { assert.fail(JSON.stringify(error)) } // even though we haven't _force_ fetched, the data is still fetched - // because even though the the local state was already there, we had never executed `fetch` or `stream` once in this session + // because even though the the cache state was already there, we had never executed `fetch` or `stream` once in this session assert.deepEqual(trainerModule.data, { name: 'Luca', age: 10, dream: 'job' }) }) diff --git a/packages/plugin-vue3/test/helpers/createMagnetarInstance.ts b/packages/plugin-vue3/test/helpers/createMagnetarInstance.ts index 2695be6c..9b3a1a47 100644 --- a/packages/plugin-vue3/test/helpers/createMagnetarInstance.ts +++ b/packages/plugin-vue3/test/helpers/createMagnetarInstance.ts @@ -27,26 +27,25 @@ export function createMagnetarInstance(): { trainerModule: DocInstance magnetar: MagnetarInstance } { - const local = CreatePluginLocal({ generateRandomId }) + const cache = CreatePluginLocal({ generateRandomId }) const remote = CreatePluginRemote({ storeName: 'remote' }) const magnetar = Magnetar({ - localStoreName: 'local', - stores: { local, remote }, + stores: { cache, remote }, executionOrder: { - read: ['local', 'remote'], - write: ['local', 'remote'], - delete: ['local', 'remote'], + read: ['cache', 'remote'], + write: ['cache', 'remote'], + delete: ['cache', 'remote'], }, }) const pokedexModule = magnetar.collection('pokedex', { configPerStore: { - local: { initialData: getInitialDataCollection() }, // path for the plugin + cache: { initialData: getInitialDataCollection() }, // path for the plugin remote: {}, // path for the plugin }, }) const trainerModule = magnetar.doc('app-data/trainer', { configPerStore: { - local: { initialData: getInitialDataDocument() }, // path for the plugin + cache: { initialData: getInitialDataDocument() }, // path for the plugin remote: {}, // path for the plugin }, }) diff --git a/packages/test-utils/src/PluginLocalMock/CreatePlugin.ts b/packages/test-utils/src/PluginLocalMock/CreatePlugin.ts index 2f9d76f8..687ccb71 100644 --- a/packages/test-utils/src/PluginLocalMock/CreatePlugin.ts +++ b/packages/test-utils/src/PluginLocalMock/CreatePlugin.ts @@ -43,7 +43,7 @@ export type MakeRestoreBackup = (collectionPath: string, docId: string) => void export const CreatePlugin: MagnetarPlugin = ( storePluginOptions: StorePluginOptions, ): PluginInstance => { - // this is the local state of the plugin, each plugin that acts as a "local Store Plugin" should have something similar + // this is the local cache state of the plugin, each plugin that acts as a "cache Store Plugin" should have something similar // do not define the store plugin data on the top level! Be sure to define it inside the scope of the plugin function!! const data: { [collectionPath: string]: Map } = {} const exists: { [docPath: string]: undefined | 'error' | boolean } = {} @@ -86,7 +86,7 @@ export const CreatePlugin: MagnetarPlugin = ( } /** - * This must be provided by Store Plugins that have "local" data. It is triggered ONCE when the module (doc or collection) is instantiated. In any case, an empty Map for the collectionPath (to be derived from the modulePath) must be set up. + * This must be provided by Store Plugins that have "cache" data. It is triggered ONCE when the module (doc or collection) is instantiated. In any case, an empty Map for the collectionPath (to be derived from the modulePath) must be set up. */ const modulesAlreadySetup = new Set() const setupModule = ({ @@ -115,7 +115,7 @@ export const CreatePlugin: MagnetarPlugin = ( } /** - * This must be provided by Store Plugins that have "local" data. It is triggered EVERY TIME the module's data is accessed. The `modulePath` will be either that of a "collection" or a "doc". When it's a collection, it must return a Map with the ID as key and the doc data as value `Map`. When it's a "doc" it must return the doc data directly `DocDataType`. + * This must be provided by Store Plugins that have "cache" data. It is triggered EVERY TIME the module's data is accessed. The `modulePath` will be either that of a "collection" or a "doc". When it's a collection, it must return a Map with the ID as key and the doc data as value `Map`. When it's a "doc" it must return the doc data directly `DocDataType`. */ const getModuleData = ({ collectionPath, @@ -139,7 +139,7 @@ export const CreatePlugin: MagnetarPlugin = ( } /** - * This must be provided by Store Plugins that have "local" data. It should signify wether or not the document exists. Must return `undefined` when not sure (if the document was never fetched). It is triggered EVERY TIME the module's `.data` is accessed. + * This must be provided by Store Plugins that have "cache" data. It should signify wether or not the document exists. Must return `undefined` when not sure (if the document was never fetched). It is triggered EVERY TIME the module's `.data` is accessed. */ const getModuleExists = ({ collectionPath, @@ -149,7 +149,7 @@ export const CreatePlugin: MagnetarPlugin = ( } /** - * This must be provided by Store Plugins that have "local" data. It is triggered EVERY TIME the module's count is accessed. + * This must be provided by Store Plugins that have "cache" data. It is triggered EVERY TIME the module's count is accessed. */ const getModuleAggregate = ( kind: 'sum' | 'average', @@ -164,7 +164,7 @@ export const CreatePlugin: MagnetarPlugin = ( } /** - * This must be provided by Store Plugins that have "local" data. It is triggered EVERY TIME the module's count is accessed. + * This must be provided by Store Plugins that have "cache" data. It is triggered EVERY TIME the module's count is accessed. */ const getModuleCount = ({ collectionPath, diff --git a/packages/test-utils/src/PluginLocalMock/actions/fetch.ts b/packages/test-utils/src/PluginLocalMock/actions/fetch.ts index d00f9850..34cf66cb 100644 --- a/packages/test-utils/src/PluginLocalMock/actions/fetch.ts +++ b/packages/test-utils/src/PluginLocalMock/actions/fetch.ts @@ -15,7 +15,7 @@ import { insertActionFactory } from './insert.js' export function fetchActionFactory( data: { [collectionPath: string]: Map }, exists: { [docPath: string]: undefined | 'error' | boolean }, - storePluginOptions: StorePluginOptions + storePluginOptions: StorePluginOptions, ): PluginFetchAction { return function ({ payload, @@ -41,12 +41,12 @@ export function fetchActionFactory( startAfter, }) if (collectionData.size > 0) { - const localDocs: DocMetadata[] = [...collectionData.entries()].map(([_docId, data]) => ({ + const cachedDocs: DocMetadata[] = [...collectionData.entries()].map(([_docId, data]) => ({ data, exists: 'unknown', id: _docId, })) - const fetchResponse: FetchResponse = { docs: localDocs } + const fetchResponse: FetchResponse = { docs: cachedDocs } return fetchResponse // if size === 0 fall through to returning DoOnFetch down below } } @@ -56,13 +56,13 @@ export function fetchActionFactory( */ const itSureExists = exists[`${collectionPath}/${docId}`] === true if (docId && itSureExists) { - const localDoc = data[collectionPath]?.get(docId) + const cachedDoc = data[collectionPath]?.get(docId) // if already fetched - if (localDoc) { + if (cachedDoc) { const fetchResponse: FetchResponse = { docs: [ { - data: localDoc, + data: cachedDoc, exists: 'unknown', id: docId, }, @@ -71,7 +71,7 @@ export function fetchActionFactory( return fetchResponse } // if not yet fetched - if (!localDoc) { + if (!cachedDoc) { // fall through to returning DoOnFetch down below } } @@ -97,12 +97,12 @@ export function fetchActionFactory( exists[docPath] = meta.exists } - // abort updating local state if the payload was set to undefined + // abort updating local cache state if the payload was set to undefined if (_payload === undefined) return insertActionFactory( data, - storePluginOptions + storePluginOptions, )({ payload: _payload, collectionPath, diff --git a/packages/test-utils/src/PluginLocalMock/actions/fetchAggregate.ts b/packages/test-utils/src/PluginLocalMock/actions/fetchAggregate.ts index a11e3e78..baf790f9 100644 --- a/packages/test-utils/src/PluginLocalMock/actions/fetchAggregate.ts +++ b/packages/test-utils/src/PluginLocalMock/actions/fetchAggregate.ts @@ -29,7 +29,7 @@ export function fetchAggregateActionFactory( const pathId = getPathWhereIdentifier(collectionPath, pluginModuleConfig) const doOnFetchSumAggregate: DoOnFetchAggregate = (count) => { - // abort updating local state if the payload was set to undefined + // abort updating local cache state if the payload was set to undefined if (count === undefined) return pathAggregateDic[pathId] = merge( diff --git a/packages/test-utils/src/PluginLocalMock/actions/fetchCount.ts b/packages/test-utils/src/PluginLocalMock/actions/fetchCount.ts index 35efdc0d..4b6f0564 100644 --- a/packages/test-utils/src/PluginLocalMock/actions/fetchCount.ts +++ b/packages/test-utils/src/PluginLocalMock/actions/fetchCount.ts @@ -25,7 +25,7 @@ export function fetchCountActionFactory( const pathId = getPathWhereIdentifier(collectionPath, pluginModuleConfig) const doOnFetchAggregateAction: DoOnFetchAggregate = (count) => { - // abort updating local state if the payload was set to undefined + // abort updating local cache state if the payload was set to undefined if (count === undefined) return pathCountDic[pathId] = count diff --git a/packages/test-utils/src/PluginLocalMock/actions/stream.ts b/packages/test-utils/src/PluginLocalMock/actions/stream.ts index ba793dbb..ad14d10d 100644 --- a/packages/test-utils/src/PluginLocalMock/actions/stream.ts +++ b/packages/test-utils/src/PluginLocalMock/actions/stream.ts @@ -12,7 +12,7 @@ import { insertActionFactory } from './insert.js' export function streamActionFactory( data: { [collectionPath: string]: Map }, - storePluginOptions: StorePluginOptions + storePluginOptions: StorePluginOptions, ): PluginStreamAction { return function ({ payload, @@ -32,12 +32,12 @@ export function streamActionFactory( // hover over the prop names below to see more info on when they are triggered: const doOnStream: DoOnStream = { added: (payload, meta) => { - // abort updating local state if the payload was set to undefined + // abort updating local cache state if the payload was set to undefined if (payload === undefined) return undefined insertActionFactory( data, - storePluginOptions + storePluginOptions, )({ payload, collectionPath, @@ -48,12 +48,12 @@ export function streamActionFactory( return undefined }, modified: (payload, meta) => { - // abort updating local state if the payload was set to undefined + // abort updating local cache state if the payload was set to undefined if (payload === undefined) return undefined insertActionFactory( data, - storePluginOptions + storePluginOptions, )({ payload, collectionPath, @@ -70,12 +70,12 @@ export function streamActionFactory( ? [collectionPath, payload] : [collectionPath, meta.id] const [_cPath, _dId] = collectionPathDocIdToDelete - // abort updating local state if the payload was set to undefined + // abort updating local cache state if the payload was set to undefined if (payload === undefined) return undefined deleteActionFactory( data, - storePluginOptions + storePluginOptions, )({ payload: undefined, collectionPath: _cPath, diff --git a/packages/types/package.json b/packages/types/package.json index 631ea385..3ef34037 100644 --- a/packages/types/package.json +++ b/packages/types/package.json @@ -43,6 +43,8 @@ "vue-store", "firestore", "data-store", + "data-cache", + "cache-store", "local-store", "remote-store", "global-store", diff --git a/packages/types/src/Collection.ts b/packages/types/src/Collection.ts index 3c86a503..7c196b34 100644 --- a/packages/types/src/Collection.ts +++ b/packages/types/src/Collection.ts @@ -29,11 +29,11 @@ export type CollectionInstance< */ count: number /** - * Holds the fetched "sum" of the fields on which you called `fetchSum()` so far. This only gets updated when `fetchSum` is called, it is not automatically updated when local `data` changes. + * Holds the fetched "sum" of the fields on which you called `fetchSum()` so far. This only gets updated when `fetchSum` is called, it is not automatically updated when local cached `data` changes. */ sum: PartialDeep> /** - * Holds the fetched "average" of the fields on which you called `fetchAverage()` so far. This only gets updated when `fetchAverage` is called, it is not automatically updated when local `data` changes. + * Holds the fetched "average" of the fields on which you called `fetchAverage()` so far. This only gets updated when `fetchAverage` is called, it is not automatically updated when local cached `data` changes. */ average: PartialDeep> /** diff --git a/packages/types/src/types/actions.ts b/packages/types/src/types/actions.ts index 4daffcea..e728e7b2 100644 --- a/packages/types/src/types/actions.ts +++ b/packages/types/src/types/actions.ts @@ -16,8 +16,8 @@ export type ActionName = 'fetch' | 'fetchCount' | 'fetchSum' | 'fetchAverage' | * You can pass options to this action specifically; * This is what the dev can provide as second param when executing any action in addition to the payload. * @example - * // first update the server and await that before updating the local store: - * { executionOrder: ['remote', 'local'] } + * // first update the server and await that before updating the local cache store: + * { executionOrder: ['remote', 'cache'] } * @example * // don't throw errors for this action, wherever it might fail * { onError: 'continue' } @@ -52,8 +52,8 @@ export type MagnetarStreamAction< ) => Promise /** - * 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. + * Fetches document(s) and adds the data to your local cache store's state. + * Fetch is optimistic by default β€” if it can find the doc's data in your local cache 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 @@ -82,7 +82,7 @@ export type MagnetarFetchAction< ) => Promise : DocDataType | undefined> /** - * Fetches a collection's document count and caches this count to your local store's state. + * Fetches a collection's document count and caches this count to your local cache store's state. * @returns the document count that was fetched. * @example * magnetar.collection('pokedex').count // 0 @@ -94,7 +94,7 @@ export type MagnetarFetchAction< export type MagnetarFetchCountAction = () => Promise /** - * Fetches a collection's document sum for a the passed fieldPath and caches this sum to your local store's state. + * Fetches a collection's document sum for a the passed fieldPath and caches this sum to your local cache store's state. * @returns the document sum that was fetched. * @example * magnetar.collection('pokedex').sum // {} @@ -108,7 +108,7 @@ export type MagnetarFetchSumAction< > = (fieldPath: OPathsWithOptional) => Promise /** - * Fetches a collection's document average for a the passed fieldPath and caches this average to your local store's state. + * Fetches a collection's document average for a the passed fieldPath and caches this average to your local cache store's state. * @returns the document average that was fetched. * @example * magnetar.collection('pokedex').average // 0 @@ -140,7 +140,7 @@ export type MagnetarInsertAction< ) => Promise> /** - * @returns the new document data after applying the changes to the local document (including any modifications from modifyPayloadOn) + * @returns the new document data after applying the changes to the cached document (including any modifications from modifyPayloadOn) */ export type MagnetarWriteAction< DocDataType extends { [key: string]: any } = { [key: string]: any }, @@ -154,7 +154,7 @@ export type MagnetarWriteAction< ) => Promise /** - * @returns the new document data after applying the changes to the local document (including any modifications from modifyPayloadOn) + * @returns the new document data after applying the changes to the cached document (including any modifications from modifyPayloadOn) */ export type MagnetarDeletePropAction< DocDataType extends { [key: string]: any } = { [key: string]: any }, diff --git a/packages/types/src/types/config.ts b/packages/types/src/types/config.ts index 71e82d12..b34610b7 100644 --- a/packages/types/src/types/config.ts +++ b/packages/types/src/types/config.ts @@ -25,11 +25,12 @@ export type ExecutionOrderConfig = { * The Magnetar global options. Can be overwritten on a per-module or per-action basis. */ export type GlobalConfig = { - /** - * the storeName of the plugin that will keep your local data cache for usage with your client. - */ - localStoreName: StoreName - stores: { [storeName: string]: PluginInstance } + stores: { + /** the cache store, this plugin is responsible for the data to be linked to your UI */ + cache: PluginInstance + /** any other stores you can choose the key name of */ + [storeName: string]: PluginInstance + } executionOrder?: ExecutionOrderConfig onError?: 'revert' | 'continue' | 'stop' modifyPayloadOn?: ModifyPayloadFnMap diff --git a/packages/types/src/types/core.ts b/packages/types/src/types/core.ts index ea75b80b..8edef4ec 100644 --- a/packages/types/src/types/core.ts +++ b/packages/types/src/types/core.ts @@ -4,11 +4,11 @@ export type DocMetadata = { data: { [key: string]: any } | undefined id: string /** - * In case the doc was returned optimisticly (from the local store data) then `exists` will be `'unknown'` + * In case the doc was returned optimisticly (from the local cache store data) then `exists` will be `'unknown'` */ exists: boolean | 'unknown' /** - * In case the doc was returned optimisticly (from the local store data) then `metadata` will be absent + * In case the doc was returned optimisticly (from the local cache store data) then `metadata` will be absent */ metadata?: { [key: string]: any } } diff --git a/packages/types/src/types/modifyReadResponse.ts b/packages/types/src/types/modifyReadResponse.ts index b4165232..e5d20991 100644 --- a/packages/types/src/types/modifyReadResponse.ts +++ b/packages/types/src/types/modifyReadResponse.ts @@ -26,7 +26,7 @@ export type OnRemovedFn = ( ) => { [key: string]: any } | string | undefined /** - * These functions will be executed everytime BEFORE documents are added/modified/deleted in your local data store. The function defined will receive the payload with changes from the server. You can then modify and return this payload. + * These functions will be executed everytime BEFORE documents are added/modified/deleted in your cache data store. The function defined will receive the payload with changes from the server. You can then modify and return this payload. */ export type ModifyReadResponseFnMap< DocDataType extends { [key: string]: any } = { [key: string]: any }, @@ -46,7 +46,7 @@ export type ModifyReadResponseFnMap< } /** - * These functions will be executed everytime BEFORE documents are added/modified/deleted in your local data store. The function defined will receive the payload with changes from the server. You can then modify and return this payload. + * These functions will be executed everytime BEFORE documents are added/modified/deleted in your cache data store. The function defined will receive the payload with changes from the server. You can then modify and return this payload. */ export type ModifyReadResponseFnsMap = { added: OnAddedFn[] diff --git a/packages/types/src/types/plugins.ts b/packages/types/src/types/plugins.ts index 3ea2a31e..3c28a46d 100644 --- a/packages/types/src/types/plugins.ts +++ b/packages/types/src/types/plugins.ts @@ -44,27 +44,27 @@ export type PluginInstance = { */ revert: PluginRevertAction /** - * This must be provided by Store Plugins that have "local" data. It is triggered ONCE when the module (doc or collection) is instantiated. In any case, an empty Map for the collectionPath (to be derived from the modulePath) must be set up. + * This must be provided by Store Plugins that have "cache" data. It is triggered ONCE when the module (doc or collection) is instantiated. In any case, an empty Map for the collectionPath (to be derived from the modulePath) must be set up. */ setupModule?: (pluginModuleSetupPayload: PluginModuleSetupPayload) => void /** - * This must be provided by Store Plugins that have "local" data. It is triggered EVERY TIME the module's `.data` is accessed. The `modulePath` will be either that of a "collection" or a "doc". When it's a collection, it must return a Map with the ID as key and the doc data as value `Map`. When it's a "doc" it must return the doc data directly `DocDataType`. + * This must be provided by Store Plugins that have "cache" data. It is triggered EVERY TIME the module's `.data` is accessed. The `modulePath` will be either that of a "collection" or a "doc". When it's a collection, it must return a Map with the ID as key and the doc data as value `Map`. When it's a "doc" it must return the doc data directly `DocDataType`. */ getModuleData?: ( pluginModuleSetupPayload: PluginModuleSetupPayload, ) => { [key: string]: any } | Map /** - * This must be provided by Store Plugins that have "local" data. It should signify wether or not the document exists. Must return `undefined` when not sure (if the document was never fetched). It is triggered EVERY TIME the module's `.data` is accessed. + * This must be provided by Store Plugins that have "cache" data. It should signify wether or not the document exists. Must return `undefined` when not sure (if the document was never fetched). It is triggered EVERY TIME the module's `.data` is accessed. */ getModuleExists?: ( pluginModuleSetupPayload: Pick, ) => undefined | 'error' | boolean /** - * This must be provided by Store Plugins that have "local" data. It is triggered EVERY TIME the module's `.count` is accessed. The `modulePath` will always be that of a "collection". It must return the fetched doc count, or fall back to `.data.size` in case it hasn't fetched the doc count yet. + * This must be provided by Store Plugins that have "cache" data. It is triggered EVERY TIME the module's `.count` is accessed. The `modulePath` will always be that of a "collection". It must return the fetched doc count, or fall back to `.data.size` in case it hasn't fetched the doc count yet. */ getModuleCount?: (pluginModuleSetupPayload: Omit) => number /** - * This must be provided by Store Plugins that have "local" data. It is triggered EVERY TIME the module's `.count` is accessed. The `modulePath` will always be that of a "collection". It must return the fetched doc sum/average for the fields requested so far + * This must be provided by Store Plugins that have "cache" data. It is triggered EVERY TIME the module's `.count` is accessed. The `modulePath` will always be that of a "collection". It must return the fetched doc sum/average for the fields requested so far */ getModuleAggregate?: ( kind: 'sum' | 'average', @@ -77,7 +77,7 @@ export type PluginInstance = { } /** - * Where, orderBy, limit clauses or extra config a dev might pass when instanciates a module as second param (under `configPerStore`). Eg. `collection('pokedex', { configPerStore: { local: pluginModuleConfig } })` + * Where, orderBy, limit clauses or extra config a dev might pass when instanciates a module as second param (under `configPerStore`). Eg. `collection('pokedex', { configPerStore: { cache: pluginModuleConfig } })` */ export type PluginModuleConfig = Clauses & { [key in string]: any } @@ -132,14 +132,14 @@ export type PluginStreamActionPayload /** - * Should handle 'stream' for collections & docs. (use `getCollectionPathDocIdEntry(modulePath)` helper, based on what it returns, you know if it's a collection or doc). Should return `StreamResponse` when acting as a "remote" Store Plugin, and `DoOnStream` when acting as "local" Store Plugin. + * Should handle 'stream' for collections & docs. (use `getCollectionPathDocIdEntry(modulePath)` helper, based on what it returns, you know if it's a collection or doc). Should return `StreamResponse` when acting as a "remote" Store Plugin, and `DoOnStream` when acting as "cache" Store Plugin. */ export type PluginStreamAction = ( payload: PluginStreamActionPayload, @@ -156,7 +156,7 @@ export type PluginFetchActionPayload /** - * Should handle 'fetch' for collections & docs. (use `getCollectionPathDocIdEntry(modulePath)` helper, based on what it returns, you know if it's a collection or doc). Should return `FetchResponse` when acting as a "remote" Store Plugin, and `DoOnFetch` when acting as "local" Store Plugin. + * Should handle 'fetch' for collections & docs. (use `getCollectionPathDocIdEntry(modulePath)` helper, based on what it returns, you know if it's a collection or doc). Should return `FetchResponse` when acting as a "remote" Store Plugin, and `DoOnFetch` when acting as "cache" Store Plugin. */ export type PluginFetchAction = ( payload: PluginFetchActionPayload, @@ -168,7 +168,7 @@ export type PluginFetchCountActionPayload = Omit< > /** - * Should handle 'fetchCount' for collections. Should return `FetchAggregateResponse` when acting as a "remote" Store Plugin, and `DoOnFetchAggregate` when acting as "local" Store Plugin. + * Should handle 'fetchCount' for collections. Should return `FetchAggregateResponse` when acting as a "remote" Store Plugin, and `DoOnFetchAggregate` when acting as "cache" Store Plugin. */ export type PluginFetchCountAction = ( payload: PluginFetchCountActionPayload, @@ -189,7 +189,7 @@ export type PluginFetchAggregateActionPayload = Omit< > /** - * Should handle 'fetchSum' 'fetchAverage' for collections. Should return `FetchAggregateResponse` when acting as a "remote" Store Plugin, and `DoOnFetchAggregate` when acting as "local" Store Plugin. + * Should handle 'fetchSum' 'fetchAverage' for collections. Should return `FetchAggregateResponse` when acting as a "remote" Store Plugin, and `DoOnFetchAggregate` when acting as "cache" Store Plugin. */ export type PluginFetchAggregateAction = ( payload: PluginFetchAggregateActionPayload, @@ -329,27 +329,27 @@ export type PluginActionTernary = TActionName ex export type StreamResponse = { streaming: Promise; stop: () => void } /** - * Plugin's response to a 'stream' action, when acting as a "local" Store Plugin. + * Plugin's response to a 'stream' action, when acting as a "cache" Store Plugin. */ export type DoOnStream = { /** * 'added' will/should be triggered per document on 3 occasions: on 'fetch' when a document is read; on 'stream' when initial documents are read; on 'stream' when there are consequent insertions of documents on the end-point. * - * As local store plugin this should be a function that covers the logic to save the payload to the local state. + * As local cache store plugin this should be a function that covers the logic to save the payload to the local cache state. * As remote store plugin this is what must be executed during the events. */ added?: OnAddedFn /** * 'modified' will/should be triggered per document on 1 occasion: on 'stream' when a document that was already read through that stream once before is modified on the end-point. * - * As local store plugin this should be a function that covers the logic to update the payload in the local state. + * As local cache store plugin this should be a function that covers the logic to update the payload in the local cache state. * As remote store plugin this is what must be executed during the events. */ modified?: OnModifiedFn /** * 'removed' will/should be triggered per document on 2 occasions: on 'stream' when a document is "deleted" on the end-point; when a document doesn't adhere to the "stream clauses" any more. * - * As local store plugin this should be a function that covers the logic to remove the payload from the local state. + * As local cache store plugin this should be a function that covers the logic to remove the payload from the local cache state. * As remote store plugin this is what must be executed during the events. */ removed?: OnRemovedFn @@ -366,7 +366,7 @@ export type DoOnStreamFns = { /** * MustExecuteOnRead: - * The functions for 'added', 'modified' and 'removed' **must** be executed by the plugin whenever the stream sees any of these changes. These are the functions that will pass the data to the other "local" Store Plugins. + * The functions for 'added', 'modified' and 'removed' **must** be executed by the plugin whenever the stream sees any of these changes. These are the functions that will pass the data to the other "cache" Store Plugins. */ export type MustExecuteOnRead = Required @@ -386,7 +386,7 @@ export type FetchResponse = { } /** - * Plugin's response to a 'fetch' action, when acting as a "local" Store Plugin. + * Plugin's response to a 'fetch' action, when acting as a "cache" Store Plugin. */ export type DoOnFetch = ( docData: { [key: string]: unknown } | undefined, @@ -398,6 +398,6 @@ export type DoOnFetch = ( */ export type FetchAggregateResponse = number /** - * The local store should provide a function that will store the fetchCount when it comes in from the remote store. + * The local cache store should provide a function that will store the fetchCount when it comes in from the remote store. */ export type DoOnFetchAggregate = (payload: FetchAggregateResponse) => undefined diff --git a/packages/ui/package.json b/packages/ui/package.json index 2e902fb8..e1066900 100644 --- a/packages/ui/package.json +++ b/packages/ui/package.json @@ -61,6 +61,8 @@ "vue-store", "firestore", "data-store", + "data-cache", + "cache-store", "local-store", "remote-store", "global-store", diff --git a/packages/ui/src/utils/computedAsync.ts b/packages/ui/src/utils/computedAsync.ts index 2b80757c..0fe10381 100644 --- a/packages/ui/src/utils/computedAsync.ts +++ b/packages/ui/src/utils/computedAsync.ts @@ -4,16 +4,16 @@ import { computed, ComputedRef, Ref } from 'vue' /** * A version of `computedAsync` from `@vueuse/core` that enforces to * return a `ComputedRef` from the async function in order to prevent - * a bug where magnetar's local state mutations doesn't trigger a refresh. + * a bug where magnetar's local cache state mutations doesn't trigger a refresh. */ export function computedAsync( fn: () => Promise>, initialState: T, - isEvaluating?: Ref + isEvaluating?: Ref, ): ComputedRef { const initialVal = Symbol('initial') const vueUseComputed = vueUseComputedAsync(fn, initialVal as any, isEvaluating) return computed(() => - vueUseComputed.value === initialVal ? initialState : vueUseComputed.value.value + vueUseComputed.value === initialVal ? initialState : vueUseComputed.value.value, ) } diff --git a/packages/ui/testApp/magnetar.ts b/packages/ui/testApp/magnetar.ts index 86d3671b..4eebe1ac 100644 --- a/packages/ui/testApp/magnetar.ts +++ b/packages/ui/testApp/magnetar.ts @@ -1,5 +1,5 @@ // --------------------------------------- -// plugin vue3 for local data store +// plugin vue3 for cache data store // --------------------------------------- import { Magnetar } from '@magnetarjs/core' import { CreatePlugin as PluginFirestore } from '@magnetarjs/plugin-firestore' @@ -9,8 +9,8 @@ import { db } from './initFirebase.js' export const generateRandomId = (): string => doc(collection(db, 'random')).id -// create the local store plugin instance: -const local = PluginVue3({ generateRandomId }) +// create the cache store plugin instance: +const cache = PluginVue3({ generateRandomId }) const remote = PluginFirestore({ db, debug: true }) @@ -18,11 +18,10 @@ const remote = PluginFirestore({ db, debug: true }) // instantiate the Magnetar instance with the store plugins // ----------------------------------------------------- export const magnetar = Magnetar({ - stores: { local, remote }, - localStoreName: 'local', + stores: { cache, remote }, executionOrder: { - read: ['local', 'remote'], - write: ['local', 'remote'], - delete: ['local', 'remote'], + read: ['cache', 'remote'], + write: ['cache', 'remote'], + delete: ['cache', 'remote'], }, }) diff --git a/packages/utils-firestore/package.json b/packages/utils-firestore/package.json index 5ac0d616..e9c13f04 100644 --- a/packages/utils-firestore/package.json +++ b/packages/utils-firestore/package.json @@ -54,6 +54,8 @@ "vue-store", "firestore", "data-store", + "data-cache", + "cache-store", "local-store", "remote-store", "global-store", diff --git a/packages/utils-firestore/src/types.ts b/packages/utils-firestore/src/types.ts index 306bd5f0..1cf2cec3 100644 --- a/packages/utils-firestore/src/types.ts +++ b/packages/utils-firestore/src/types.ts @@ -36,8 +36,7 @@ export type FirestorePluginOptions