Huge News!Announcing our $40M Series B led by Abstract Ventures.Learn More
Socket
Sign inDemoInstall
Socket

@magnetarjs/core

Package Overview
Dependencies
Maintainers
1
Versions
152
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

@magnetarjs/core - npm Package Compare versions

Comparing version 0.0.19 to 0.0.20

dist/types/Collection.d.ts

284

dist/index.cjs.js

@@ -325,3 +325,3 @@ 'use strict';

function handleActionPerStore([collectionPath, _docId], moduleConfig, globalConfig, actionName, actionType, docFn, // actions executed on a "doc" will always return `doc()`
function handleActionPerStore([collectionPath, _docId], moduleConfig, globalConfig, actionName, actionType, fetchPromises, docFn, // actions executed on a "doc" will always return `doc()`
collectionFn // actions executed on a "collection" will return `collection()` or `doc()`

@@ -331,114 +331,137 @@ ) {

return function (payload, actionConfig = {}) {
return __awaiter(this, void 0, void 0, function* () {
let docId = _docId;
let modulePath = [collectionPath, docId].filter(Boolean).join('/');
// get all the config needed to perform this action
const onError = actionConfig.onError || moduleConfig.onError || globalConfig.onError;
const modifyPayloadFnsMap = getModifyPayloadFnsMap(globalConfig.modifyPayloadOn, moduleConfig.modifyPayloadOn, actionConfig.modifyPayloadOn);
const modifyReadResponseMap = getModifyReadResponseFnsMap(globalConfig.modifyReadResponseOn, moduleConfig.modifyReadResponseOn, actionConfig.modifyReadResponseOn);
const eventNameFnsMap = getEventNameFnsMap(globalConfig.on, moduleConfig.on, actionConfig.on);
const storesToExecute = actionConfig.executionOrder ||
(moduleConfig.executionOrder || {})[actionName] ||
(moduleConfig.executionOrder || {})[actionType] ||
(globalConfig.executionOrder || {})[actionName] ||
(globalConfig.executionOrder || {})[actionType] ||
[];
throwIfNoFnsToExecute(storesToExecute);
// update the payload
for (const modifyFn of modifyPayloadFnsMap[actionName]) {
payload = modifyFn(payload, docId);
}
let stopExecution = false;
/**
* The abort mechanism for the entire store chain. When executed in handleAction() it won't go to the next store in executionOrder.
*/
function stopExecutionAfterAction(trueOrRevert = true) {
stopExecution = trueOrRevert;
}
/**
* each each time a store returns a `FetchResponse` then all `doOnFetchFns` need to be executed
*/
const doOnFetchFns = modifyReadResponseMap.added;
// handle and await each action in sequence
let resultFromPlugin;
for (const [i, storeName] of storesToExecute.entries()) {
// a previous iteration stopped the execution:
if (stopExecution === true)
break;
// find the action on the plugin
const pluginAction = globalConfig.stores[storeName].actions[actionName];
const pluginModuleConfig = getPluginModuleConfig(moduleConfig, storeName);
// the plugin action
resultFromPlugin = !pluginAction
? resultFromPlugin
: yield handleAction({
collectionPath,
docId,
modulePath,
pluginModuleConfig,
pluginAction,
payload,
eventNameFnsMap,
onError,
actionName,
stopExecutionAfterAction,
storeName,
});
// handle reverting. stopExecution might have been modified by `handleAction`
if (stopExecution === 'revert') {
const storesToRevert = storesToExecute.slice(0, i);
storesToRevert.reverse();
for (const storeToRevert of storesToRevert) {
const pluginRevertAction = globalConfig.stores[storeToRevert].revert;
const pluginModuleConfig = getPluginModuleConfig(moduleConfig, storeToRevert);
yield pluginRevertAction({
payload,
const fetchPromiseKey = JSON.stringify(payload);
const foundFetchPromise = fetchPromises.get(fetchPromiseKey);
if (actionName === 'fetch' && isWhat.isPromise(foundFetchPromise))
return foundFetchPromise;
// eslint-disable-next-line no-async-promise-executor
const actionPromise = new Promise((resolve, reject) => __awaiter(this, void 0, void 0, function* () {
try {
let docId = _docId;
let modulePath = [collectionPath, docId].filter(Boolean).join('/');
// get all the config needed to perform this action
const onError = actionConfig.onError || moduleConfig.onError || globalConfig.onError;
const modifyPayloadFnsMap = getModifyPayloadFnsMap(globalConfig.modifyPayloadOn, moduleConfig.modifyPayloadOn, actionConfig.modifyPayloadOn);
const modifyReadResponseMap = getModifyReadResponseFnsMap(globalConfig.modifyReadResponseOn, moduleConfig.modifyReadResponseOn, actionConfig.modifyReadResponseOn);
const eventNameFnsMap = getEventNameFnsMap(globalConfig.on, moduleConfig.on, actionConfig.on);
const storesToExecute = actionConfig.executionOrder ||
(moduleConfig.executionOrder || {})[actionName] ||
(moduleConfig.executionOrder || {})[actionType] ||
(globalConfig.executionOrder || {})[actionName] ||
(globalConfig.executionOrder || {})[actionType] ||
[];
throwIfNoFnsToExecute(storesToExecute);
// update the payload
for (const modifyFn of modifyPayloadFnsMap[actionName]) {
payload = modifyFn(payload, docId);
}
let stopExecution = false;
/**
* The abort mechanism for the entire store chain. When executed in handleAction() it won't go to the next store in executionOrder.
*/
function stopExecutionAfterAction(trueOrRevert = true) {
stopExecution = trueOrRevert;
}
/**
* each each time a store returns a `FetchResponse` then all `doOnFetchFns` need to be executed
*/
const doOnFetchFns = modifyReadResponseMap.added;
// handle and await each action in sequence
let resultFromPlugin;
for (const [i, storeName] of storesToExecute.entries()) {
// a previous iteration stopped the execution:
if (stopExecution === true)
break;
// find the action on the plugin
const pluginAction = globalConfig.stores[storeName].actions[actionName];
const pluginModuleConfig = getPluginModuleConfig(moduleConfig, storeName);
// the plugin action
resultFromPlugin = !pluginAction
? resultFromPlugin
: yield handleAction({
collectionPath,
docId,
modulePath,
pluginModuleConfig,
pluginAction,
payload,
eventNameFnsMap,
onError,
actionName,
error: resultFromPlugin, // in this case the result is the error
stopExecutionAfterAction,
storeName,
});
// revert eventFns, handle and await each eventFn in sequence
for (const fn of eventNameFnsMap.revert) {
yield fn({ payload, result: resultFromPlugin, actionName, storeName, collectionPath, docId, path: modulePath, pluginModuleConfig }); // prettier-ignore
// handle reverting. stopExecution might have been modified by `handleAction`
if (stopExecution === 'revert') {
const storesToRevert = storesToExecute.slice(0, i);
storesToRevert.reverse();
for (const storeToRevert of storesToRevert) {
const pluginRevertAction = globalConfig.stores[storeToRevert].revert;
const pluginModuleConfig = getPluginModuleConfig(moduleConfig, storeToRevert);
yield pluginRevertAction({
payload,
collectionPath,
docId,
pluginModuleConfig,
actionName,
error: resultFromPlugin, // in this case the result is the error
});
// revert eventFns, handle and await each eventFn in sequence
for (const fn of eventNameFnsMap.revert) {
yield fn({ payload, result: resultFromPlugin, actionName, storeName, collectionPath, docId, path: modulePath, pluginModuleConfig }); // prettier-ignore
}
}
// now we must throw the error
throw resultFromPlugin;
}
// now we must throw the error
throw resultFromPlugin;
}
// special handling for 'insert' (resultFromPlugin will always be `string`)
if (actionName === 'insert' && isWhat.isFullString(resultFromPlugin)) {
// update the modulePath if a doc with random ID was inserted in a collection
// if this is the case the result will be a string - the randomly genererated ID
if (!docId) {
docId = resultFromPlugin;
modulePath = [collectionPath, docId].filter(Boolean).join('/');
// special handling for 'insert' (resultFromPlugin will always be `string`)
if (actionName === 'insert' && isWhat.isFullString(resultFromPlugin)) {
// update the modulePath if a doc with random ID was inserted in a collection
// if this is the case the result will be a string - the randomly genererated ID
if (!docId) {
docId = resultFromPlugin;
modulePath = [collectionPath, docId].filter(Boolean).join('/');
}
}
}
// special handling for 'fetch' (resultFromPlugin will always be `FetchResponse | OnAddedFn`)
if (actionName === 'fetch') {
if (isDoOnFetch(resultFromPlugin)) {
doOnFetchFns.push(resultFromPlugin);
}
if (isFetchResponse(resultFromPlugin)) {
for (const docRetrieved of resultFromPlugin.docs) {
executeOnFns(doOnFetchFns, docRetrieved.data, [docRetrieved]);
// special handling for 'fetch' (resultFromPlugin will always be `FetchResponse | OnAddedFn`)
if (actionName === 'fetch') {
if (isDoOnFetch(resultFromPlugin)) {
doOnFetchFns.push(resultFromPlugin);
}
if (isFetchResponse(resultFromPlugin)) {
for (const docRetrieved of resultFromPlugin.docs) {
executeOnFns(doOnFetchFns, docRetrieved.data, [docRetrieved]);
}
}
}
}
// anything that's executed from a "collection" module:
// 'insert' always returns a DocInstance, unless the "abort" action was called, then the modulePath might still be a collection:
if (actionName === 'insert' && docId) {
// we do not pass the `moduleConfig`, because it's the moduleConfig of the "collection" in this case
resolve(docFn(modulePath));
return;
}
// anything that's executed from a "doc" module:
if (docId || !collectionFn) {
resolve(docFn(modulePath, moduleConfig));
if (actionName === 'fetch')
fetchPromises.delete(fetchPromiseKey);
return;
}
// all other actions triggered on collections ('fetch' is the only possibility left)
// should return the collection:
resolve(collectionFn(modulePath, moduleConfig));
if (actionName === 'fetch')
fetchPromises.delete(fetchPromiseKey);
}
// anything that's executed from a "collection" module:
// 'insert' always returns a DocInstance, unless the "abort" action was called, then the modulePath might still be a collection:
if (actionName === 'insert' && docId) {
// we do not pass the `moduleConfig`, because it's the moduleConfig of the "collection" in this case
return docFn(modulePath);
catch (error) {
reject(error);
if (actionName === 'fetch')
fetchPromises.delete(fetchPromiseKey);
}
// anything that's executed from a "doc" module:
if (docId || !collectionFn)
return docFn(modulePath, moduleConfig);
// all other actions triggered on collections ('fetch' is the only possibility left)
// should return the collection:
return collectionFn(modulePath, moduleConfig);
});
}));
if (actionName === 'fetch') {
fetchPromises.set(fetchPromiseKey, actionPromise);
}
return actionPromise;
};

@@ -488,7 +511,7 @@ }

function handleStreamPerStore([collectionPath, docId], moduleConfig, globalConfig, actionType, streams) {
function handleStreamPerStore([collectionPath, docId], moduleConfig, globalConfig, actionType, streamPromiseInfo) {
// returns the action the dev can call with myModule.insert() etc.
return function (payload, actionConfig = {}) {
return __awaiter(this, void 0, void 0, function* () {
const { openStreams, openStreamPromises, findStreamPromise } = streams;
const { openStreams, openStreamPromises, findStreamPromise } = streamPromiseInfo;
const foundStreamPromise = findStreamPromise(payload);

@@ -584,4 +607,5 @@ if (isWhat.isPromise(foundStreamPromise))

function createCollectionWithContext([collectionPath, docId], moduleConfig, globalConfig, docFn, collectionFn, streams) {
const { openStreams, findStream, openStreamPromises, findStreamPromise } = streams;
function createCollectionWithContext([collectionPath, docId], moduleConfig, globalConfig, docFn, collectionFn, streamAndFetchPromises) {
const { openStreams, findStream, openStreamPromises, findStreamPromise, fetchPromises } = streamAndFetchPromises; // prettier-ignore
const streamPromiseInfo = { openStreams, findStream, openStreamPromises, findStreamPromise };
const id = collectionPath.split('/').slice(-1)[0];

@@ -592,6 +616,6 @@ const path = collectionPath;

};
const insert = handleActionPerStore([collectionPath, docId], moduleConfig, globalConfig, 'insert', actionNameTypeMap.insert, docFn, collectionFn); //prettier-ignore
const _delete = handleActionPerStore([collectionPath, docId], moduleConfig, globalConfig, 'delete', actionNameTypeMap.delete, docFn, collectionFn); //prettier-ignore
const fetch = handleActionPerStore([collectionPath, docId], moduleConfig, globalConfig, 'fetch', actionNameTypeMap.fetch, docFn, collectionFn); //prettier-ignore
const stream = handleStreamPerStore([collectionPath, docId], moduleConfig, globalConfig, actionNameTypeMap.stream, streams); // prettier-ignore
const insert = handleActionPerStore([collectionPath, docId], moduleConfig, globalConfig, 'insert', actionNameTypeMap.insert, fetchPromises, docFn, collectionFn); //prettier-ignore
const _delete = handleActionPerStore([collectionPath, docId], moduleConfig, globalConfig, 'delete', actionNameTypeMap.delete, fetchPromises, docFn, collectionFn); //prettier-ignore
const fetch = handleActionPerStore([collectionPath, docId], moduleConfig, globalConfig, 'fetch', actionNameTypeMap.fetch, fetchPromises, docFn, collectionFn); //prettier-ignore
const stream = handleStreamPerStore([collectionPath, docId], moduleConfig, globalConfig, actionNameTypeMap.stream, streamPromiseInfo); // prettier-ignore
const actions = { stream, fetch, insert, delete: _delete };

@@ -628,4 +652,5 @@ // Every store will have its 'setupModule' function executed

function createDocWithContext([collectionPath, docId], moduleConfig, globalConfig, docFn, collectionFn, streams) {
const { openStreams, findStream, openStreamPromises, findStreamPromise } = streams;
function createDocWithContext([collectionPath, docId], moduleConfig, globalConfig, docFn, collectionFn, streamAndFetchPromises) {
const { openStreams, findStream, openStreamPromises, findStreamPromise, fetchPromises } = streamAndFetchPromises; // prettier-ignore
const streamPromiseInfo = { openStreams, findStream, openStreamPromises, findStreamPromise };
const id = docId;

@@ -637,10 +662,10 @@ const path = [collectionPath, docId].join('/');

const actions = {
insert: handleActionPerStore([collectionPath, docId], moduleConfig, globalConfig, 'insert', actionNameTypeMap.insert, docFn),
merge: handleActionPerStore([collectionPath, docId], moduleConfig, globalConfig, 'merge', actionNameTypeMap.merge, docFn),
assign: handleActionPerStore([collectionPath, docId], moduleConfig, globalConfig, 'assign', actionNameTypeMap.assign, docFn),
replace: handleActionPerStore([collectionPath, docId], moduleConfig, globalConfig, 'replace', actionNameTypeMap.replace, docFn),
deleteProp: handleActionPerStore([collectionPath, docId], moduleConfig, globalConfig, 'deleteProp', actionNameTypeMap.deleteProp, docFn),
delete: handleActionPerStore([collectionPath, docId], moduleConfig, globalConfig, 'delete', actionNameTypeMap.delete, docFn),
fetch: handleActionPerStore([collectionPath, docId], moduleConfig, globalConfig, 'fetch', actionNameTypeMap.fetch, docFn),
stream: handleStreamPerStore([collectionPath, docId], moduleConfig, globalConfig, actionNameTypeMap.stream, streams), // prettier-ignore
insert: handleActionPerStore([collectionPath, docId], moduleConfig, globalConfig, 'insert', actionNameTypeMap.insert, fetchPromises, docFn),
merge: handleActionPerStore([collectionPath, docId], moduleConfig, globalConfig, 'merge', actionNameTypeMap.merge, fetchPromises, docFn),
assign: handleActionPerStore([collectionPath, docId], moduleConfig, globalConfig, 'assign', actionNameTypeMap.assign, fetchPromises, docFn),
replace: handleActionPerStore([collectionPath, docId], moduleConfig, globalConfig, 'replace', actionNameTypeMap.replace, fetchPromises, docFn),
deleteProp: handleActionPerStore([collectionPath, docId], moduleConfig, globalConfig, 'deleteProp', actionNameTypeMap.deleteProp, fetchPromises, docFn),
delete: handleActionPerStore([collectionPath, docId], moduleConfig, globalConfig, 'delete', actionNameTypeMap.delete, fetchPromises, docFn),
fetch: handleActionPerStore([collectionPath, docId], moduleConfig, globalConfig, 'fetch', actionNameTypeMap.fetch, fetchPromises, docFn),
stream: handleStreamPerStore([collectionPath, docId], moduleConfig, globalConfig, actionNameTypeMap.stream, streamPromiseInfo), // prettier-ignore
};

@@ -706,2 +731,6 @@ // Every store will have its 'setupModule' function executed

const streamPromiseMap = new Map(); // apply type upon get/set
/**
* the global storage for fetch promises
*/
const fetchPromiseMap = new Map(); // apply type upon get/set
function getModuleInstance(modulePath, moduleConfig = {}, moduleType, docFn, collectionFn) {

@@ -717,3 +746,3 @@ throwIfInvalidModulePath(modulePath, moduleType);

// else create and cache a new instance
// first create the streamCloseFnMap and streamPromiseMap for this module
// create the streamCloseFnMap and streamPromiseMap for this module
if (!streamCloseFnMap.has(modulePath)) {

@@ -725,11 +754,24 @@ streamCloseFnMap.set(modulePath, new Map());

}
// create the fetchPromiseMap for this module
if (!fetchPromiseMap.has(modulePath)) {
fetchPromiseMap.set(modulePath, new Map());
}
// grab the open stream utils
const openStreams = streamCloseFnMap.get(modulePath);
const findStream = (streamPayload) => findMapValueForKey(openStreams, streamPayload);
// grab the fetch promise utils
const fetchPromises = fetchPromiseMap.get(modulePath);
const openStreamPromises = streamPromiseMap.get(modulePath);
const findStreamPromise = (streamPayload) => findMapValueForKey(openStreamPromises, streamPayload);
const streams = { openStreams, findStream, openStreamPromises, findStreamPromise };
const streamAndFetchPromises = {
openStreams,
findStream,
openStreamPromises,
findStreamPromise,
fetchPromises,
};
// then create the module instance
const createInstanceWithContext = moduleType === 'doc' ? createDocWithContext : createCollectionWithContext;
// @ts-ignore
const moduleInstance = createInstanceWithContext([collectionPath, docId], moduleConfig, globalConfig, docFn, collectionFn, streams);
const moduleInstance = createInstanceWithContext([collectionPath, docId], moduleConfig, globalConfig, docFn, collectionFn, streamAndFetchPromises);
moduleMap.set(moduleIdentifier, moduleInstance);

@@ -736,0 +778,0 @@ return moduleInstance;

@@ -321,3 +321,3 @@ import { merge, mergeAndConcat } from 'merge-anything';

function handleActionPerStore([collectionPath, _docId], moduleConfig, globalConfig, actionName, actionType, docFn, // actions executed on a "doc" will always return `doc()`
function handleActionPerStore([collectionPath, _docId], moduleConfig, globalConfig, actionName, actionType, fetchPromises, docFn, // actions executed on a "doc" will always return `doc()`
collectionFn // actions executed on a "collection" will return `collection()` or `doc()`

@@ -327,114 +327,137 @@ ) {

return function (payload, actionConfig = {}) {
return __awaiter(this, void 0, void 0, function* () {
let docId = _docId;
let modulePath = [collectionPath, docId].filter(Boolean).join('/');
// get all the config needed to perform this action
const onError = actionConfig.onError || moduleConfig.onError || globalConfig.onError;
const modifyPayloadFnsMap = getModifyPayloadFnsMap(globalConfig.modifyPayloadOn, moduleConfig.modifyPayloadOn, actionConfig.modifyPayloadOn);
const modifyReadResponseMap = getModifyReadResponseFnsMap(globalConfig.modifyReadResponseOn, moduleConfig.modifyReadResponseOn, actionConfig.modifyReadResponseOn);
const eventNameFnsMap = getEventNameFnsMap(globalConfig.on, moduleConfig.on, actionConfig.on);
const storesToExecute = actionConfig.executionOrder ||
(moduleConfig.executionOrder || {})[actionName] ||
(moduleConfig.executionOrder || {})[actionType] ||
(globalConfig.executionOrder || {})[actionName] ||
(globalConfig.executionOrder || {})[actionType] ||
[];
throwIfNoFnsToExecute(storesToExecute);
// update the payload
for (const modifyFn of modifyPayloadFnsMap[actionName]) {
payload = modifyFn(payload, docId);
}
let stopExecution = false;
/**
* The abort mechanism for the entire store chain. When executed in handleAction() it won't go to the next store in executionOrder.
*/
function stopExecutionAfterAction(trueOrRevert = true) {
stopExecution = trueOrRevert;
}
/**
* each each time a store returns a `FetchResponse` then all `doOnFetchFns` need to be executed
*/
const doOnFetchFns = modifyReadResponseMap.added;
// handle and await each action in sequence
let resultFromPlugin;
for (const [i, storeName] of storesToExecute.entries()) {
// a previous iteration stopped the execution:
if (stopExecution === true)
break;
// find the action on the plugin
const pluginAction = globalConfig.stores[storeName].actions[actionName];
const pluginModuleConfig = getPluginModuleConfig(moduleConfig, storeName);
// the plugin action
resultFromPlugin = !pluginAction
? resultFromPlugin
: yield handleAction({
collectionPath,
docId,
modulePath,
pluginModuleConfig,
pluginAction,
payload,
eventNameFnsMap,
onError,
actionName,
stopExecutionAfterAction,
storeName,
});
// handle reverting. stopExecution might have been modified by `handleAction`
if (stopExecution === 'revert') {
const storesToRevert = storesToExecute.slice(0, i);
storesToRevert.reverse();
for (const storeToRevert of storesToRevert) {
const pluginRevertAction = globalConfig.stores[storeToRevert].revert;
const pluginModuleConfig = getPluginModuleConfig(moduleConfig, storeToRevert);
yield pluginRevertAction({
payload,
const fetchPromiseKey = JSON.stringify(payload);
const foundFetchPromise = fetchPromises.get(fetchPromiseKey);
if (actionName === 'fetch' && isPromise(foundFetchPromise))
return foundFetchPromise;
// eslint-disable-next-line no-async-promise-executor
const actionPromise = new Promise((resolve, reject) => __awaiter(this, void 0, void 0, function* () {
try {
let docId = _docId;
let modulePath = [collectionPath, docId].filter(Boolean).join('/');
// get all the config needed to perform this action
const onError = actionConfig.onError || moduleConfig.onError || globalConfig.onError;
const modifyPayloadFnsMap = getModifyPayloadFnsMap(globalConfig.modifyPayloadOn, moduleConfig.modifyPayloadOn, actionConfig.modifyPayloadOn);
const modifyReadResponseMap = getModifyReadResponseFnsMap(globalConfig.modifyReadResponseOn, moduleConfig.modifyReadResponseOn, actionConfig.modifyReadResponseOn);
const eventNameFnsMap = getEventNameFnsMap(globalConfig.on, moduleConfig.on, actionConfig.on);
const storesToExecute = actionConfig.executionOrder ||
(moduleConfig.executionOrder || {})[actionName] ||
(moduleConfig.executionOrder || {})[actionType] ||
(globalConfig.executionOrder || {})[actionName] ||
(globalConfig.executionOrder || {})[actionType] ||
[];
throwIfNoFnsToExecute(storesToExecute);
// update the payload
for (const modifyFn of modifyPayloadFnsMap[actionName]) {
payload = modifyFn(payload, docId);
}
let stopExecution = false;
/**
* The abort mechanism for the entire store chain. When executed in handleAction() it won't go to the next store in executionOrder.
*/
function stopExecutionAfterAction(trueOrRevert = true) {
stopExecution = trueOrRevert;
}
/**
* each each time a store returns a `FetchResponse` then all `doOnFetchFns` need to be executed
*/
const doOnFetchFns = modifyReadResponseMap.added;
// handle and await each action in sequence
let resultFromPlugin;
for (const [i, storeName] of storesToExecute.entries()) {
// a previous iteration stopped the execution:
if (stopExecution === true)
break;
// find the action on the plugin
const pluginAction = globalConfig.stores[storeName].actions[actionName];
const pluginModuleConfig = getPluginModuleConfig(moduleConfig, storeName);
// the plugin action
resultFromPlugin = !pluginAction
? resultFromPlugin
: yield handleAction({
collectionPath,
docId,
modulePath,
pluginModuleConfig,
pluginAction,
payload,
eventNameFnsMap,
onError,
actionName,
error: resultFromPlugin, // in this case the result is the error
stopExecutionAfterAction,
storeName,
});
// revert eventFns, handle and await each eventFn in sequence
for (const fn of eventNameFnsMap.revert) {
yield fn({ payload, result: resultFromPlugin, actionName, storeName, collectionPath, docId, path: modulePath, pluginModuleConfig }); // prettier-ignore
// handle reverting. stopExecution might have been modified by `handleAction`
if (stopExecution === 'revert') {
const storesToRevert = storesToExecute.slice(0, i);
storesToRevert.reverse();
for (const storeToRevert of storesToRevert) {
const pluginRevertAction = globalConfig.stores[storeToRevert].revert;
const pluginModuleConfig = getPluginModuleConfig(moduleConfig, storeToRevert);
yield pluginRevertAction({
payload,
collectionPath,
docId,
pluginModuleConfig,
actionName,
error: resultFromPlugin, // in this case the result is the error
});
// revert eventFns, handle and await each eventFn in sequence
for (const fn of eventNameFnsMap.revert) {
yield fn({ payload, result: resultFromPlugin, actionName, storeName, collectionPath, docId, path: modulePath, pluginModuleConfig }); // prettier-ignore
}
}
// now we must throw the error
throw resultFromPlugin;
}
// now we must throw the error
throw resultFromPlugin;
}
// special handling for 'insert' (resultFromPlugin will always be `string`)
if (actionName === 'insert' && isFullString(resultFromPlugin)) {
// update the modulePath if a doc with random ID was inserted in a collection
// if this is the case the result will be a string - the randomly genererated ID
if (!docId) {
docId = resultFromPlugin;
modulePath = [collectionPath, docId].filter(Boolean).join('/');
// special handling for 'insert' (resultFromPlugin will always be `string`)
if (actionName === 'insert' && isFullString(resultFromPlugin)) {
// update the modulePath if a doc with random ID was inserted in a collection
// if this is the case the result will be a string - the randomly genererated ID
if (!docId) {
docId = resultFromPlugin;
modulePath = [collectionPath, docId].filter(Boolean).join('/');
}
}
}
// special handling for 'fetch' (resultFromPlugin will always be `FetchResponse | OnAddedFn`)
if (actionName === 'fetch') {
if (isDoOnFetch(resultFromPlugin)) {
doOnFetchFns.push(resultFromPlugin);
}
if (isFetchResponse(resultFromPlugin)) {
for (const docRetrieved of resultFromPlugin.docs) {
executeOnFns(doOnFetchFns, docRetrieved.data, [docRetrieved]);
// special handling for 'fetch' (resultFromPlugin will always be `FetchResponse | OnAddedFn`)
if (actionName === 'fetch') {
if (isDoOnFetch(resultFromPlugin)) {
doOnFetchFns.push(resultFromPlugin);
}
if (isFetchResponse(resultFromPlugin)) {
for (const docRetrieved of resultFromPlugin.docs) {
executeOnFns(doOnFetchFns, docRetrieved.data, [docRetrieved]);
}
}
}
}
// anything that's executed from a "collection" module:
// 'insert' always returns a DocInstance, unless the "abort" action was called, then the modulePath might still be a collection:
if (actionName === 'insert' && docId) {
// we do not pass the `moduleConfig`, because it's the moduleConfig of the "collection" in this case
resolve(docFn(modulePath));
return;
}
// anything that's executed from a "doc" module:
if (docId || !collectionFn) {
resolve(docFn(modulePath, moduleConfig));
if (actionName === 'fetch')
fetchPromises.delete(fetchPromiseKey);
return;
}
// all other actions triggered on collections ('fetch' is the only possibility left)
// should return the collection:
resolve(collectionFn(modulePath, moduleConfig));
if (actionName === 'fetch')
fetchPromises.delete(fetchPromiseKey);
}
// anything that's executed from a "collection" module:
// 'insert' always returns a DocInstance, unless the "abort" action was called, then the modulePath might still be a collection:
if (actionName === 'insert' && docId) {
// we do not pass the `moduleConfig`, because it's the moduleConfig of the "collection" in this case
return docFn(modulePath);
catch (error) {
reject(error);
if (actionName === 'fetch')
fetchPromises.delete(fetchPromiseKey);
}
// anything that's executed from a "doc" module:
if (docId || !collectionFn)
return docFn(modulePath, moduleConfig);
// all other actions triggered on collections ('fetch' is the only possibility left)
// should return the collection:
return collectionFn(modulePath, moduleConfig);
});
}));
if (actionName === 'fetch') {
fetchPromises.set(fetchPromiseKey, actionPromise);
}
return actionPromise;
};

@@ -484,7 +507,7 @@ }

function handleStreamPerStore([collectionPath, docId], moduleConfig, globalConfig, actionType, streams) {
function handleStreamPerStore([collectionPath, docId], moduleConfig, globalConfig, actionType, streamPromiseInfo) {
// returns the action the dev can call with myModule.insert() etc.
return function (payload, actionConfig = {}) {
return __awaiter(this, void 0, void 0, function* () {
const { openStreams, openStreamPromises, findStreamPromise } = streams;
const { openStreams, openStreamPromises, findStreamPromise } = streamPromiseInfo;
const foundStreamPromise = findStreamPromise(payload);

@@ -580,4 +603,5 @@ if (isPromise(foundStreamPromise))

function createCollectionWithContext([collectionPath, docId], moduleConfig, globalConfig, docFn, collectionFn, streams) {
const { openStreams, findStream, openStreamPromises, findStreamPromise } = streams;
function createCollectionWithContext([collectionPath, docId], moduleConfig, globalConfig, docFn, collectionFn, streamAndFetchPromises) {
const { openStreams, findStream, openStreamPromises, findStreamPromise, fetchPromises } = streamAndFetchPromises; // prettier-ignore
const streamPromiseInfo = { openStreams, findStream, openStreamPromises, findStreamPromise };
const id = collectionPath.split('/').slice(-1)[0];

@@ -588,6 +612,6 @@ const path = collectionPath;

};
const insert = handleActionPerStore([collectionPath, docId], moduleConfig, globalConfig, 'insert', actionNameTypeMap.insert, docFn, collectionFn); //prettier-ignore
const _delete = handleActionPerStore([collectionPath, docId], moduleConfig, globalConfig, 'delete', actionNameTypeMap.delete, docFn, collectionFn); //prettier-ignore
const fetch = handleActionPerStore([collectionPath, docId], moduleConfig, globalConfig, 'fetch', actionNameTypeMap.fetch, docFn, collectionFn); //prettier-ignore
const stream = handleStreamPerStore([collectionPath, docId], moduleConfig, globalConfig, actionNameTypeMap.stream, streams); // prettier-ignore
const insert = handleActionPerStore([collectionPath, docId], moduleConfig, globalConfig, 'insert', actionNameTypeMap.insert, fetchPromises, docFn, collectionFn); //prettier-ignore
const _delete = handleActionPerStore([collectionPath, docId], moduleConfig, globalConfig, 'delete', actionNameTypeMap.delete, fetchPromises, docFn, collectionFn); //prettier-ignore
const fetch = handleActionPerStore([collectionPath, docId], moduleConfig, globalConfig, 'fetch', actionNameTypeMap.fetch, fetchPromises, docFn, collectionFn); //prettier-ignore
const stream = handleStreamPerStore([collectionPath, docId], moduleConfig, globalConfig, actionNameTypeMap.stream, streamPromiseInfo); // prettier-ignore
const actions = { stream, fetch, insert, delete: _delete };

@@ -624,4 +648,5 @@ // Every store will have its 'setupModule' function executed

function createDocWithContext([collectionPath, docId], moduleConfig, globalConfig, docFn, collectionFn, streams) {
const { openStreams, findStream, openStreamPromises, findStreamPromise } = streams;
function createDocWithContext([collectionPath, docId], moduleConfig, globalConfig, docFn, collectionFn, streamAndFetchPromises) {
const { openStreams, findStream, openStreamPromises, findStreamPromise, fetchPromises } = streamAndFetchPromises; // prettier-ignore
const streamPromiseInfo = { openStreams, findStream, openStreamPromises, findStreamPromise };
const id = docId;

@@ -633,10 +658,10 @@ const path = [collectionPath, docId].join('/');

const actions = {
insert: handleActionPerStore([collectionPath, docId], moduleConfig, globalConfig, 'insert', actionNameTypeMap.insert, docFn),
merge: handleActionPerStore([collectionPath, docId], moduleConfig, globalConfig, 'merge', actionNameTypeMap.merge, docFn),
assign: handleActionPerStore([collectionPath, docId], moduleConfig, globalConfig, 'assign', actionNameTypeMap.assign, docFn),
replace: handleActionPerStore([collectionPath, docId], moduleConfig, globalConfig, 'replace', actionNameTypeMap.replace, docFn),
deleteProp: handleActionPerStore([collectionPath, docId], moduleConfig, globalConfig, 'deleteProp', actionNameTypeMap.deleteProp, docFn),
delete: handleActionPerStore([collectionPath, docId], moduleConfig, globalConfig, 'delete', actionNameTypeMap.delete, docFn),
fetch: handleActionPerStore([collectionPath, docId], moduleConfig, globalConfig, 'fetch', actionNameTypeMap.fetch, docFn),
stream: handleStreamPerStore([collectionPath, docId], moduleConfig, globalConfig, actionNameTypeMap.stream, streams), // prettier-ignore
insert: handleActionPerStore([collectionPath, docId], moduleConfig, globalConfig, 'insert', actionNameTypeMap.insert, fetchPromises, docFn),
merge: handleActionPerStore([collectionPath, docId], moduleConfig, globalConfig, 'merge', actionNameTypeMap.merge, fetchPromises, docFn),
assign: handleActionPerStore([collectionPath, docId], moduleConfig, globalConfig, 'assign', actionNameTypeMap.assign, fetchPromises, docFn),
replace: handleActionPerStore([collectionPath, docId], moduleConfig, globalConfig, 'replace', actionNameTypeMap.replace, fetchPromises, docFn),
deleteProp: handleActionPerStore([collectionPath, docId], moduleConfig, globalConfig, 'deleteProp', actionNameTypeMap.deleteProp, fetchPromises, docFn),
delete: handleActionPerStore([collectionPath, docId], moduleConfig, globalConfig, 'delete', actionNameTypeMap.delete, fetchPromises, docFn),
fetch: handleActionPerStore([collectionPath, docId], moduleConfig, globalConfig, 'fetch', actionNameTypeMap.fetch, fetchPromises, docFn),
stream: handleStreamPerStore([collectionPath, docId], moduleConfig, globalConfig, actionNameTypeMap.stream, streamPromiseInfo), // prettier-ignore
};

@@ -702,2 +727,6 @@ // Every store will have its 'setupModule' function executed

const streamPromiseMap = new Map(); // apply type upon get/set
/**
* the global storage for fetch promises
*/
const fetchPromiseMap = new Map(); // apply type upon get/set
function getModuleInstance(modulePath, moduleConfig = {}, moduleType, docFn, collectionFn) {

@@ -713,3 +742,3 @@ throwIfInvalidModulePath(modulePath, moduleType);

// else create and cache a new instance
// first create the streamCloseFnMap and streamPromiseMap for this module
// create the streamCloseFnMap and streamPromiseMap for this module
if (!streamCloseFnMap.has(modulePath)) {

@@ -721,11 +750,24 @@ streamCloseFnMap.set(modulePath, new Map());

}
// create the fetchPromiseMap for this module
if (!fetchPromiseMap.has(modulePath)) {
fetchPromiseMap.set(modulePath, new Map());
}
// grab the open stream utils
const openStreams = streamCloseFnMap.get(modulePath);
const findStream = (streamPayload) => findMapValueForKey(openStreams, streamPayload);
// grab the fetch promise utils
const fetchPromises = fetchPromiseMap.get(modulePath);
const openStreamPromises = streamPromiseMap.get(modulePath);
const findStreamPromise = (streamPayload) => findMapValueForKey(openStreamPromises, streamPayload);
const streams = { openStreams, findStream, openStreamPromises, findStreamPromise };
const streamAndFetchPromises = {
openStreams,
findStream,
openStreamPromises,
findStreamPromise,
fetchPromises,
};
// then create the module instance
const createInstanceWithContext = moduleType === 'doc' ? createDocWithContext : createCollectionWithContext;
// @ts-ignore
const moduleInstance = createInstanceWithContext([collectionPath, docId], moduleConfig, globalConfig, docFn, collectionFn, streams);
const moduleInstance = createInstanceWithContext([collectionPath, docId], moduleConfig, globalConfig, docFn, collectionFn, streamAndFetchPromises);
moduleMap.set(moduleIdentifier, moduleInstance);

@@ -732,0 +774,0 @@ return moduleInstance;

{
"name": "@magnetarjs/core",
"version": "0.0.19",
"version": "0.0.20",
"sideEffects": false,

@@ -8,3 +8,3 @@ "description": "Magnetar core library.",

"module": "dist/index.esm.js",
"types": "types/index.d.ts",
"types": "dist/types/index.d.ts",
"scripts": {

@@ -15,3 +15,3 @@ "build": "npm run rollup",

"test--only": "ava --match='*only:*'",
"rollup": "rimraf dist && rimraf types && rollup -c build.js"
"rollup": "rimraf dist && rollup -c build.js"
},

@@ -28,3 +28,3 @@ "author": "Luca Ban - Mesqueeb",

"devDependencies": {
"@magnetarjs/test-utils": "^0.0.10",
"@magnetarjs/test-utils": "^0.0.11",
"ava": "^3.15.0"

@@ -73,3 +73,3 @@ },

},
"gitHead": "0894958dbdebbe4ec1adeb418d4d76050bd5c51d"
"gitHead": "ad27bdb9bb5fba289ffdb3abe4c94e1b94072160"
}

@@ -13,2 +13,3 @@ import { O } from 'ts-toolbelt'

MagnetarDeleteAction,
FetchPromises,
} from './types/actions'

@@ -67,3 +68,3 @@ import { actionNameTypeMap } from './types/actionsInternal'

collectionFn: CollectionFn<DocDataType>,
streams: {
streamAndFetchPromises: {
openStreams: OpenStreams

@@ -73,5 +74,7 @@ findStream: FindStream

findStreamPromise: FindStreamPromise
fetchPromises: FetchPromises
}
): CollectionInstance<DocDataType> {
const { openStreams, findStream, openStreamPromises, findStreamPromise } = streams
const { openStreams, findStream, openStreamPromises, findStreamPromise, fetchPromises } = streamAndFetchPromises // prettier-ignore
const streamPromiseInfo = { openStreams, findStream, openStreamPromises, findStreamPromise }
const id = collectionPath.split('/').slice(-1)[0]

@@ -84,6 +87,6 @@ const path = collectionPath

const insert = handleActionPerStore([collectionPath, docId], moduleConfig, globalConfig, 'insert', actionNameTypeMap.insert, docFn, collectionFn) as MagnetarInsertAction<DocDataType> //prettier-ignore
const _delete = handleActionPerStore([collectionPath, docId], moduleConfig, globalConfig, 'delete', actionNameTypeMap.delete, docFn, collectionFn) as MagnetarDeleteAction<DocDataType> //prettier-ignore
const fetch = handleActionPerStore([collectionPath, docId], moduleConfig, globalConfig, 'fetch', actionNameTypeMap.fetch, docFn, collectionFn) as MagnetarFetchAction<DocDataType, 'collection'> //prettier-ignore
const stream = handleStreamPerStore([collectionPath, docId], moduleConfig, globalConfig, actionNameTypeMap.stream, streams) // prettier-ignore
const insert = handleActionPerStore([collectionPath, docId], moduleConfig, globalConfig, 'insert', actionNameTypeMap.insert, fetchPromises, docFn, collectionFn) as MagnetarInsertAction<DocDataType> //prettier-ignore
const _delete = handleActionPerStore([collectionPath, docId], moduleConfig, globalConfig, 'delete', actionNameTypeMap.delete, fetchPromises, docFn, collectionFn) as MagnetarDeleteAction<DocDataType> //prettier-ignore
const fetch = handleActionPerStore([collectionPath, docId], moduleConfig, globalConfig, 'fetch', actionNameTypeMap.fetch, fetchPromises, docFn, collectionFn) as MagnetarFetchAction<DocDataType, 'collection'> //prettier-ignore
const stream = handleStreamPerStore([collectionPath, docId], moduleConfig, globalConfig, actionNameTypeMap.stream, streamPromiseInfo) // prettier-ignore

@@ -90,0 +93,0 @@ const actions = { stream, fetch, insert, delete: _delete }

@@ -13,2 +13,3 @@ import { O } from 'ts-toolbelt'

FindStreamPromise,
FetchPromises,
} from './types/actions'

@@ -26,3 +27,3 @@ import { actionNameTypeMap } from './types/actionsInternal'

*/
data: DocDataType
data: DocDataType | undefined
/**

@@ -70,3 +71,3 @@ * `collection` is available on every document for chaining

collectionFn: CollectionFn,
streams: {
streamAndFetchPromises: {
openStreams: OpenStreams

@@ -76,5 +77,7 @@ findStream: FindStream

findStreamPromise: FindStreamPromise
fetchPromises: FetchPromises
}
): DocInstance<DocDataType> {
const { openStreams, findStream, openStreamPromises, findStreamPromise } = streams
const { openStreams, findStream, openStreamPromises, findStreamPromise, fetchPromises } = streamAndFetchPromises // prettier-ignore
const streamPromiseInfo = { openStreams, findStream, openStreamPromises, findStreamPromise }
const id = docId

@@ -88,10 +91,10 @@ const path = [collectionPath, docId].join('/')

const actions = {
insert: (handleActionPerStore([collectionPath, docId], moduleConfig, globalConfig, 'insert', actionNameTypeMap.insert, docFn) as MagnetarInsertAction<DocDataType>), // prettier-ignore
merge: (handleActionPerStore([collectionPath, docId], moduleConfig, globalConfig, 'merge', actionNameTypeMap.merge, docFn) as MagnetarWriteAction<DocDataType>), // prettier-ignore
assign: (handleActionPerStore([collectionPath, docId], moduleConfig, globalConfig, 'assign', actionNameTypeMap.assign, docFn) as MagnetarWriteAction<DocDataType>), // prettier-ignore
replace: (handleActionPerStore([collectionPath, docId], moduleConfig, globalConfig, 'replace', actionNameTypeMap.replace, docFn) as MagnetarWriteAction<DocDataType>), // prettier-ignore
deleteProp: (handleActionPerStore([collectionPath, docId], moduleConfig, globalConfig, 'deleteProp', actionNameTypeMap.deleteProp, docFn) as MagnetarDeletePropAction<DocDataType>), // prettier-ignore
delete: (handleActionPerStore([collectionPath, docId], moduleConfig, globalConfig, 'delete', actionNameTypeMap.delete, docFn) as MagnetarDeleteAction<DocDataType>), // prettier-ignore
fetch: (handleActionPerStore([collectionPath, docId], moduleConfig, globalConfig, 'fetch', actionNameTypeMap.fetch, docFn) as MagnetarFetchAction<DocDataType, 'doc'>), // prettier-ignore
stream: handleStreamPerStore([collectionPath, docId], moduleConfig, globalConfig, actionNameTypeMap.stream, streams), // prettier-ignore
insert: (handleActionPerStore([collectionPath, docId], moduleConfig, globalConfig, 'insert', actionNameTypeMap.insert, fetchPromises, docFn) as MagnetarInsertAction<DocDataType>), // prettier-ignore
merge: (handleActionPerStore([collectionPath, docId], moduleConfig, globalConfig, 'merge', actionNameTypeMap.merge, fetchPromises, docFn) as MagnetarWriteAction<DocDataType>), // prettier-ignore
assign: (handleActionPerStore([collectionPath, docId], moduleConfig, globalConfig, 'assign', actionNameTypeMap.assign, fetchPromises, docFn) as MagnetarWriteAction<DocDataType>), // prettier-ignore
replace: (handleActionPerStore([collectionPath, docId], moduleConfig, globalConfig, 'replace', actionNameTypeMap.replace, fetchPromises, docFn) as MagnetarWriteAction<DocDataType>), // prettier-ignore
deleteProp: (handleActionPerStore([collectionPath, docId], moduleConfig, globalConfig, 'deleteProp', actionNameTypeMap.deleteProp, fetchPromises, docFn) as MagnetarDeletePropAction<DocDataType>), // prettier-ignore
delete: (handleActionPerStore([collectionPath, docId], moduleConfig, globalConfig, 'delete', actionNameTypeMap.delete, fetchPromises, docFn) as MagnetarDeleteAction<DocDataType>), // prettier-ignore
fetch: (handleActionPerStore([collectionPath, docId], moduleConfig, globalConfig, 'fetch', actionNameTypeMap.fetch, fetchPromises, docFn) as MagnetarFetchAction<DocDataType, 'doc'>), // prettier-ignore
stream: handleStreamPerStore([collectionPath, docId], moduleConfig, globalConfig, actionNameTypeMap.stream, streamPromiseInfo), // prettier-ignore
}

@@ -98,0 +101,0 @@

@@ -6,3 +6,9 @@ import { O } from 'ts-toolbelt'

import { createDocWithContext, DocInstance } from './Doc'
import { OpenStreams, OpenStreamPromises, FindStream, FindStreamPromise } from './types/actions'
import {
OpenStreams,
OpenStreamPromises,
FindStream,
FindStreamPromise,
FetchPromises,
} from './types/actions'
import { throwIfInvalidModulePath } from './helpers/throwFns'

@@ -76,2 +82,6 @@ import { getCollectionPathDocIdEntry } from './helpers/pathHelpers'

const streamPromiseMap: Map<string, OpenStreamPromises> = new Map() // apply type upon get/set
/**
* the global storage for fetch promises
*/
const fetchPromiseMap: Map<string, FetchPromises> = new Map() // apply type upon get/set

@@ -93,3 +103,4 @@ function getModuleInstance(

// else create and cache a new instance
// first create the streamCloseFnMap and streamPromiseMap for this module
// create the streamCloseFnMap and streamPromiseMap for this module
if (!streamCloseFnMap.has(modulePath)) {

@@ -101,9 +112,25 @@ streamCloseFnMap.set(modulePath, new Map())

}
// create the fetchPromiseMap for this module
if (!fetchPromiseMap.has(modulePath)) {
fetchPromiseMap.set(modulePath, new Map())
}
// grab the open stream utils
const openStreams = streamCloseFnMap.get(modulePath) as OpenStreams
const findStream: FindStream = (streamPayload: any) =>
findMapValueForKey(openStreams, streamPayload)
// grab the fetch promise utils
const fetchPromises = fetchPromiseMap.get(modulePath) as FetchPromises
const openStreamPromises = streamPromiseMap.get(modulePath) as OpenStreamPromises
const findStreamPromise: FindStreamPromise = (streamPayload: any) =>
findMapValueForKey(openStreamPromises, streamPayload)
const streams = { openStreams, findStream, openStreamPromises, findStreamPromise }
const streamAndFetchPromises = {
openStreams,
findStream,
openStreamPromises,
findStreamPromise,
fetchPromises,
}
// then create the module instance

@@ -119,3 +146,3 @@ const createInstanceWithContext =

collectionFn,
streams
streamAndFetchPromises
)

@@ -122,0 +149,0 @@ moduleMap.set(moduleIdentifier, moduleInstance)

@@ -0,3 +1,4 @@

/* eslint-disable no-inner-declarations */
import { O } from 'ts-toolbelt'
import { isFullString } from 'is-what'
import { isFullString, isPromise } from 'is-what'
import { handleAction } from './handleAction'

@@ -13,2 +14,3 @@ import { getEventNameFnsMap } from '../types/events'

ActionName,
FetchPromises,
} from '../types/actions'

@@ -33,2 +35,3 @@ import { ActionType, ActionTernary } from '../types/actionsInternal'

actionType: ActionType,
fetchPromises: FetchPromises,
docFn: DocFn, // actions executed on a "doc" will always return `doc()`

@@ -44,2 +47,3 @@ collectionFn?: CollectionFn // actions executed on a "collection" will return `collection()` or `doc()`

actionType: ActionType,
fetchPromises: FetchPromises,
docFn: DocFn, // actions executed on a "doc" will always return `doc()`

@@ -54,134 +58,162 @@ collectionFn?: CollectionFn // actions executed on a "collection" will return `collection()` or `doc()`

// returns the action the dev can call with myModule.insert() etc.
return async function (
return function (
payload?: any,
actionConfig: ActionConfig = {}
): Promise<DocInstance | CollectionInstance> {
let docId = _docId
let modulePath = [collectionPath, docId].filter(Boolean).join('/')
// get all the config needed to perform this action
const onError = actionConfig.onError || moduleConfig.onError || globalConfig.onError
const modifyPayloadFnsMap = getModifyPayloadFnsMap(
globalConfig.modifyPayloadOn,
moduleConfig.modifyPayloadOn,
actionConfig.modifyPayloadOn
)
const modifyReadResponseMap = getModifyReadResponseFnsMap(
globalConfig.modifyReadResponseOn,
moduleConfig.modifyReadResponseOn,
actionConfig.modifyReadResponseOn
)
const eventNameFnsMap = getEventNameFnsMap(globalConfig.on, moduleConfig.on, actionConfig.on)
const storesToExecute: string[] =
actionConfig.executionOrder ||
(moduleConfig.executionOrder || {})[actionName] ||
(moduleConfig.executionOrder || {})[actionType] ||
(globalConfig.executionOrder || {})[actionName] ||
(globalConfig.executionOrder || {})[actionType] ||
[]
throwIfNoFnsToExecute(storesToExecute)
// update the payload
for (const modifyFn of modifyPayloadFnsMap[actionName]) {
payload = modifyFn(payload, docId)
}
const fetchPromiseKey = JSON.stringify(payload)
const foundFetchPromise = fetchPromises.get(fetchPromiseKey)
if (actionName === 'fetch' && isPromise(foundFetchPromise)) return foundFetchPromise
// create the abort mechanism
type StopExecution = boolean | 'revert'
let stopExecution = false as StopExecution
/**
* The abort mechanism for the entire store chain. When executed in handleAction() it won't go to the next store in executionOrder.
*/
function stopExecutionAfterAction(trueOrRevert: StopExecution = true): void {
stopExecution = trueOrRevert
}
// eslint-disable-next-line no-async-promise-executor
const actionPromise = new Promise<DocInstance | CollectionInstance>(async (resolve, reject) => {
try {
let docId = _docId
let modulePath = [collectionPath, docId].filter(Boolean).join('/')
// get all the config needed to perform this action
const onError = actionConfig.onError || moduleConfig.onError || globalConfig.onError
const modifyPayloadFnsMap = getModifyPayloadFnsMap(
globalConfig.modifyPayloadOn,
moduleConfig.modifyPayloadOn,
actionConfig.modifyPayloadOn
)
const modifyReadResponseMap = getModifyReadResponseFnsMap(
globalConfig.modifyReadResponseOn,
moduleConfig.modifyReadResponseOn,
actionConfig.modifyReadResponseOn
)
const eventNameFnsMap = getEventNameFnsMap(
globalConfig.on,
moduleConfig.on,
actionConfig.on
)
const storesToExecute: string[] =
actionConfig.executionOrder ||
(moduleConfig.executionOrder || {})[actionName] ||
(moduleConfig.executionOrder || {})[actionType] ||
(globalConfig.executionOrder || {})[actionName] ||
(globalConfig.executionOrder || {})[actionType] ||
[]
throwIfNoFnsToExecute(storesToExecute)
// update the payload
for (const modifyFn of modifyPayloadFnsMap[actionName]) {
payload = modifyFn(payload, docId)
}
/**
* each each time a store returns a `FetchResponse` then all `doOnFetchFns` need to be executed
*/
const doOnFetchFns: DoOnFetch[] = modifyReadResponseMap.added
// create the abort mechanism
type StopExecution = boolean | 'revert'
let stopExecution = false as StopExecution
/**
* The abort mechanism for the entire store chain. When executed in handleAction() it won't go to the next store in executionOrder.
*/
function stopExecutionAfterAction(trueOrRevert: StopExecution = true): void {
stopExecution = trueOrRevert
}
// handle and await each action in sequence
let resultFromPlugin: void | string | FetchResponse | OnAddedFn | any
for (const [i, storeName] of storesToExecute.entries()) {
// a previous iteration stopped the execution:
if (stopExecution === true) break
// find the action on the plugin
const pluginAction = globalConfig.stores[storeName].actions[actionName]
const pluginModuleConfig = getPluginModuleConfig(moduleConfig, storeName)
// the plugin action
resultFromPlugin = !pluginAction
? resultFromPlugin
: await handleAction({
collectionPath,
docId,
modulePath,
pluginModuleConfig,
pluginAction,
payload, // should always use the payload as passed originally for clarity
eventNameFnsMap,
onError,
actionName,
stopExecutionAfterAction,
storeName,
})
// handle reverting. stopExecution might have been modified by `handleAction`
if (stopExecution === 'revert') {
const storesToRevert = storesToExecute.slice(0, i)
storesToRevert.reverse()
for (const storeToRevert of storesToRevert) {
const pluginRevertAction = globalConfig.stores[storeToRevert].revert
const pluginModuleConfig = getPluginModuleConfig(moduleConfig, storeToRevert)
await pluginRevertAction({
payload,
collectionPath,
docId,
pluginModuleConfig,
actionName,
error: resultFromPlugin, // in this case the result is the error
})
// revert eventFns, handle and await each eventFn in sequence
for (const fn of eventNameFnsMap.revert) {
await fn({ payload, result: resultFromPlugin, actionName, storeName, collectionPath, docId, path: modulePath, pluginModuleConfig }) // prettier-ignore
/**
* each each time a store returns a `FetchResponse` then all `doOnFetchFns` need to be executed
*/
const doOnFetchFns: DoOnFetch[] = modifyReadResponseMap.added
// handle and await each action in sequence
let resultFromPlugin: void | string | FetchResponse | OnAddedFn | any
for (const [i, storeName] of storesToExecute.entries()) {
// a previous iteration stopped the execution:
if (stopExecution === true) break
// find the action on the plugin
const pluginAction = globalConfig.stores[storeName].actions[actionName]
const pluginModuleConfig = getPluginModuleConfig(moduleConfig, storeName)
// the plugin action
resultFromPlugin = !pluginAction
? resultFromPlugin
: await handleAction({
collectionPath,
docId,
modulePath,
pluginModuleConfig,
pluginAction,
payload, // should always use the payload as passed originally for clarity
eventNameFnsMap,
onError,
actionName,
stopExecutionAfterAction,
storeName,
})
// handle reverting. stopExecution might have been modified by `handleAction`
if (stopExecution === 'revert') {
const storesToRevert = storesToExecute.slice(0, i)
storesToRevert.reverse()
for (const storeToRevert of storesToRevert) {
const pluginRevertAction = globalConfig.stores[storeToRevert].revert
const pluginModuleConfig = getPluginModuleConfig(moduleConfig, storeToRevert)
await pluginRevertAction({
payload,
collectionPath,
docId,
pluginModuleConfig,
actionName,
error: resultFromPlugin, // in this case the result is the error
})
// revert eventFns, handle and await each eventFn in sequence
for (const fn of eventNameFnsMap.revert) {
await fn({ payload, result: resultFromPlugin, actionName, storeName, collectionPath, docId, path: modulePath, pluginModuleConfig }) // prettier-ignore
}
}
// now we must throw the error
throw resultFromPlugin
}
// special handling for 'insert' (resultFromPlugin will always be `string`)
if (actionName === 'insert' && isFullString(resultFromPlugin)) {
// update the modulePath if a doc with random ID was inserted in a collection
// if this is the case the result will be a string - the randomly genererated ID
if (!docId) {
docId = resultFromPlugin
modulePath = [collectionPath, docId].filter(Boolean).join('/')
}
}
// special handling for 'fetch' (resultFromPlugin will always be `FetchResponse | OnAddedFn`)
if (actionName === 'fetch') {
if (isDoOnFetch(resultFromPlugin)) {
doOnFetchFns.push(resultFromPlugin)
}
if (isFetchResponse(resultFromPlugin)) {
for (const docRetrieved of resultFromPlugin.docs) {
executeOnFns(doOnFetchFns, docRetrieved.data, [docRetrieved])
}
}
}
}
// now we must throw the error
throw resultFromPlugin
}
// special handling for 'insert' (resultFromPlugin will always be `string`)
if (actionName === 'insert' && isFullString(resultFromPlugin)) {
// update the modulePath if a doc with random ID was inserted in a collection
// if this is the case the result will be a string - the randomly genererated ID
if (!docId) {
docId = resultFromPlugin
modulePath = [collectionPath, docId].filter(Boolean).join('/')
// anything that's executed from a "collection" module:
// 'insert' always returns a DocInstance, unless the "abort" action was called, then the modulePath might still be a collection:
if (actionName === 'insert' && docId) {
// we do not pass the `moduleConfig`, because it's the moduleConfig of the "collection" in this case
resolve(docFn(modulePath))
return
}
}
// special handling for 'fetch' (resultFromPlugin will always be `FetchResponse | OnAddedFn`)
if (actionName === 'fetch') {
if (isDoOnFetch(resultFromPlugin)) {
doOnFetchFns.push(resultFromPlugin)
// anything that's executed from a "doc" module:
if (docId || !collectionFn) {
resolve(docFn(modulePath, moduleConfig))
if (actionName === 'fetch') fetchPromises.delete(fetchPromiseKey)
return
}
if (isFetchResponse(resultFromPlugin)) {
for (const docRetrieved of resultFromPlugin.docs) {
executeOnFns(doOnFetchFns, docRetrieved.data, [docRetrieved])
}
}
// all other actions triggered on collections ('fetch' is the only possibility left)
// should return the collection:
resolve(collectionFn(modulePath, moduleConfig))
if (actionName === 'fetch') fetchPromises.delete(fetchPromiseKey)
} catch (error) {
reject(error)
if (actionName === 'fetch') fetchPromises.delete(fetchPromiseKey)
}
}
})
// anything that's executed from a "collection" module:
// 'insert' always returns a DocInstance, unless the "abort" action was called, then the modulePath might still be a collection:
if (actionName === 'insert' && docId) {
// we do not pass the `moduleConfig`, because it's the moduleConfig of the "collection" in this case
return docFn(modulePath)
if (actionName === 'fetch') {
fetchPromises.set(fetchPromiseKey, actionPromise)
}
// anything that's executed from a "doc" module:
if (docId || !collectionFn) return docFn(modulePath, moduleConfig)
// all other actions triggered on collections ('fetch' is the only possibility left)
// should return the collection:
return collectionFn(modulePath, moduleConfig)
return actionPromise
}
}

@@ -27,3 +27,3 @@ import { O } from 'ts-toolbelt'

actionType: ActionType,
streams: {
streamPromiseInfo: {
openStreams: OpenStreams

@@ -37,3 +37,3 @@ findStream: FindStream

return async function (payload?: any, actionConfig: ActionConfig = {}): Promise<void> {
const { openStreams, openStreamPromises, findStreamPromise } = streams
const { openStreams, openStreamPromises, findStreamPromise } = streamPromiseInfo
const foundStreamPromise = findStreamPromise(payload)

@@ -40,0 +40,0 @@ if (isPromise(foundStreamPromise)) return foundStreamPromise

@@ -104,1 +104,6 @@ import { O } from 'ts-toolbelt'

export type FindStreamPromise = (streamPayload?: any) => Promise<void> | undefined
/**
* All fetch promises with the payload passed to `fetch(payload)` as key (JSON.stringify) and the "fetch promise" as value. In case `fetch()` had no payload, use `undefined`
*/
export type FetchPromises = Map<string, Promise<any>>
export type StoreName = string
export type DocMetadata = {
data: Record<string, any>
data: Record<string, any> | undefined
id: string

@@ -6,0 +6,0 @@ /**

@@ -44,3 +44,3 @@ import test from 'ava'

const prop = 'age'
t.deepEqual(trainerModule.data.age, 10)
t.deepEqual(trainerModule.data?.age, 10)

@@ -51,3 +51,2 @@ // create references on beforehand

const magnetarCollectionData = magnetar.collection('app-data').data // prettier-ignore
console.log(`magnetarCollectionData → `, magnetarCollectionData)

@@ -62,7 +61,7 @@ try {

// check data of references created on beforehand
t.deepEqual(magnetarDoc.data[prop], undefined)
t.deepEqual(magnetarCollectionDoc.data[prop], undefined)
t.deepEqual(magnetarDoc.data?.[prop], undefined)
t.deepEqual(magnetarCollectionDoc.data?.[prop], undefined)
t.deepEqual(magnetarCollectionData.get('trainer')?.[prop], undefined)
// check data of references executed on
t.deepEqual(trainerModule.data[prop], undefined)
t.deepEqual(trainerModule.data?.[prop], undefined)
})

@@ -110,3 +109,3 @@

test('read: get (collection)', async (t) => {
test('read: fetch (collection)', async (t) => {
// 'fetch' resolves once all stores have given a response with data

@@ -128,3 +127,3 @@ const { pokedexModule } = createMagnetarInstance()

test('read: get (document)', async (t) => {
test('read: fetch (document)', async (t) => {
// get resolves once all stores have given a response with data

@@ -131,0 +130,0 @@ const { trainerModule } = createMagnetarInstance()

@@ -5,3 +5,3 @@ {

"declaration": true,
"declarationDir": "./types/",
"declarationDir": "./dist/types/",
// This must be specified if "paths" is set

@@ -8,0 +8,0 @@ "baseUrl": "."

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc