UNPKG

@magnetarjs/core

Version:
132 lines (131 loc) 5.51 kB
import { MODULE_IDENTIFIER_SPLIT, getPathFilterIdentifier, getPathWhereOrderByIdentifier, } from '@magnetarjs/types'; import { mapGetOrSet } from 'getorset-anything'; import { isString } from 'is-what'; import { createCollectionWithContext } from './Collection.js'; import { createDocWithContext } from './Doc.js'; import { defaultsGlobalConfig } from './helpers/configHelpers.js'; import { getCollectionPathDocIdEntry } from './helpers/pathHelpers.js'; import { throwIfInvalidModulePath } from './helpers/throwFns.js'; /** * Creates a magnetar instance. * @see {@link GlobalConfig} * @see {@link MagnetarInstance} */ export function Magnetar(magnetarConfig) { /** * the passed GlobalConfig is merged onto defaults */ const globalConfig = defaultsGlobalConfig(magnetarConfig); /** * All collections visited so far, kept to be able to clear all data */ const collectionNames = new Set(); /** * the global storage for WriteLock objects * @see {@link WriteLock} */ const writeLockMap = new Map(); // apply type upon get/set /** * the global storage for closeStream functions */ const closeStreamFnMap = new Map(); // apply type upon get/set /** * the global storage for open stream promises */ const streamingPromiseMap = new Map(); // apply type upon get/set /** * the global storage for fetch promises */ const fetchPromiseMap = new Map(); // apply type upon get/set /** * the global storage for FetchMetaDataCollection */ const fetchMetaMap = new Map(); // apply type upon get/set async function clearAllData(options) { for (const collectionName of collectionNames) { if (options?.exclude?.includes(collectionName)) continue; collection(collectionName).data?.clear(); } } /** _ to prevent name clash */ async function _closeAllStreams(options) { for (const collectionName of collectionNames) { if (options?.exclude?.includes(collectionName)) continue; collection(collectionName).closeAllStreams(); } } function getModuleInstance(modulePath, moduleConfig = {}, moduleType, docFn, collectionFn) { throwIfInvalidModulePath(modulePath, moduleType); const [collectionPath, docId] = getCollectionPathDocIdEntry(modulePath); collectionNames.add(collectionPath); const pathFilterIdentifier = getPathFilterIdentifier(modulePath, moduleConfig); // grab (and set) the FetchPromises for this module const fetchPromises = mapGetOrSet(fetchPromiseMap, pathFilterIdentifier, () => ({ fetch: new Map(), fetchCount: new Map(), fetchSum: new Map(), fetchAverage: new Map(), })); // Create the FetchMeta helpers for this module const pathWhereOrderByIdentifier = getPathWhereOrderByIdentifier(modulePath, moduleConfig); const fetchMeta = { get: () => fetchMetaMap.get(pathWhereOrderByIdentifier) || { reachedEnd: false, cursor: undefined }, set: (payload) => fetchMetaMap.set(pathWhereOrderByIdentifier, payload), }; // grab the stream related functions function cacheStream(closeStreamFn, streamingPromise) { closeStreamFnMap.set(pathFilterIdentifier, closeStreamFn); streamingPromiseMap.set(pathFilterIdentifier, streamingPromise); } function streaming() { return streamingPromiseMap.get(pathFilterIdentifier) || null; } function closeStream() { const closeStreamFn = closeStreamFnMap.get(pathFilterIdentifier); if (closeStreamFn) { closeStreamFn(); setTimeout(() => { streamingPromiseMap.delete(pathFilterIdentifier); closeStreamFnMap.delete(pathFilterIdentifier); }); } } function closeAllStreams() { for (const [identifier, closeStreamFn] of closeStreamFnMap) { const openStreamPath = identifier.split(MODULE_IDENTIFIER_SPLIT)[0]; if (openStreamPath === modulePath || openStreamPath?.startsWith(modulePath + '/')) { closeStreamFn(); } } } const streamAndFetchPromises = { writeLockMap, fetchPromises, cacheStream, streaming, closeStream, closeAllStreams, }; // then create the module instance if (moduleType === 'doc' && isString(docId)) { return createDocWithContext([collectionPath, docId], moduleConfig, globalConfig, docFn, collectionFn, streamAndFetchPromises); } return createCollectionWithContext(collectionPath, moduleConfig, globalConfig, docFn, collectionFn, streamAndFetchPromises, fetchMeta); } function collection(modulePath, moduleConfig = {}) { return getModuleInstance(modulePath, moduleConfig, 'collection', doc, collection); // prettier-ignore } function doc(modulePath, moduleConfig = {}) { return getModuleInstance(modulePath, moduleConfig, 'doc', doc, collection); // prettier-ignore } const instance = { globalConfig, collection: collection, doc: doc, clearAllData, closeAllStreams: _closeAllStreams, }; return instance; }