Gathering detailed insights and metrics for megamap
Gathering detailed insights and metrics for megamap
Gathering detailed insights and metrics for megamap
Gathering detailed insights and metrics for megamap
Extended JavaScript Map with caching, loading, expiry features... and more
npm install megamap
Typescript
Module System
Node Version
NPM Version
TypeScript (65.44%)
Vue (28.33%)
JavaScript (5.35%)
HTML (0.8%)
CSS (0.08%)
Total Downloads
0
Last Day
0
Last Week
0
Last Month
0
Last Year
0
3 Stars
157 Commits
2 Watchers
4 Branches
1 Contributors
Updated on Dec 25, 2024
Latest Version
1.3.4
Package Id
megamap@1.3.4
Unpacked Size
61.43 kB
Size
12.67 kB
File Count
20
NPM Version
10.8.2
Node Version
20.18.0
Published on
Nov 12, 2024
Cumulative downloads
Total Downloads
Last Day
0%
NaN
Compared to previous day
Last Week
0%
NaN
Compared to previous week
Last Month
0%
NaN
Compared to previous month
Last Year
0%
NaN
Compared to previous year
1
5
1
A TypeScript-first map implementation that handles loading, caching, searching, filtering, and reactivity.
MegaMap is a TypeScript library designed for advanced key-value mapping. It extends the native JavaScript Record
object
and integrates additional features such as caching, loadability, and automatic expiry of entries. MegaMap is built upon
two foundational classes, LoadableMap
and CachedLoadableMap
, each offering distinct capabilities. This library is
ideal for sophisticated mapping solutions where enhanced control over data storage and retrieval is needed.
Ideally, this library is meant to be used in conjunction with a data store (e.g. a database, API, etc.), and/or state management solution, such as pinia.
I've started creating a demo on usage of the library, you can find the source at megamap-demo
There's a live demo at megamap-demo.pages.dev
1import { MegaMap, ReactiveMegaMap } from 'megamap' 2 3// Basic loading and caching 4const posts = new MegaMap({ 5 loadOne: (id) => fetch(`/api/posts/${id}`).then(r => r.json()), 6 loadAll: () => fetch('/api/posts').then(r => r.json()), 7 expiryInterval: 5000, // Cache expires after 5 seconds 8}) 9 10// Load and cache automatically 11await posts.get('123') // Fetches from API 12await posts.get('123') // Returns from cache 13await posts.get('123') // After 5s, fetches fresh data 14 15// Enable search functionality 16const searchablePosts = new MegaMap({ 17 ...postsConfig, 18 searchableFields: ['title', 'content', 'tags'] 19}) 20 21// Fuzzy search across all loaded items 22const results = searchablePosts.searchItems('typescript') 23 24// Maintain filtered sublists automatically 25const organizedPosts = new MegaMap({ 26 ...postsConfig, 27 subListFilters: { 28 published: post => post.status === 'published', 29 draft: post => post.status === 'draft', 30 recent: post => isWithinLast7Days(post.date) 31 } 32}) 33 34// Access filtered lists 35console.log(organizedPosts.subLists.published) // Array of published posts 36console.log(organizedPosts.subLists.draft) // Array of drafts 37console.log(organizedPosts.subLists.recent) // Recent posts 38 39// Make it reactive (Vue.js) 40const reactivePosts = new ReactiveMegaMap({ 41 loadOne: (id) => fetch(`/api/posts/${id}`).then(r => r.json()), 42 loadAll: () => fetch('/api/posts').then(r => r.json()), 43 subListFilters: { 44 published: post => post.status === 'published', 45 draft: post => post.status === 'draft' 46 } 47}) 48 49// Now it's Vue reactive - changes trigger component updates 50reactivePosts.set('123', { title: 'Updated' })
1<!-- PostManager.vue --> 2<template> 3 <div class="space-y-4"> 4 <!-- Search --> 5 <input v-model="search" placeholder="Search posts..." /> 6 7 <!-- Posts Lists --> 8 <div class="grid grid-cols-2 gap-4"> 9 <div> 10 <h2>Published ({{ postsMap.subLists.published.length }})</h2> 11 <div v-for="post in postsMap.subLists.published" :key="post.id"> 12 {{ post.title }} 13 </div> 14 </div> 15 <div> 16 <h2>Drafts ({{ postsMap.subLists.draft.length }})</h2> 17 <div v-for="post in postsMap.subLists.draft" :key="post.id"> 18 {{ post.title }} 19 </div> 20 </div> 21 </div> 22 </div> 23</template> 24 25<script setup lang="ts"> 26import { ref, onMounted } from 'vue' 27import { ReactiveMegaMap } from 'megamap' 28 29interface Post { 30 id: string 31 title: string 32 status: 'draft' | 'published' 33} 34 35const search = ref('') 36const postsMap = new ReactiveMegaMap<string, Post>({ 37 loadOne: (id) => fetch(`/api/posts/${id}`).then(r => r.json()), 38 loadAll: () => fetch('/api/posts').then(r => r.json()), 39 searchableFields: ['title'], 40 subListFilters: { 41 published: post => post.status === 'published', 42 draft: post => post.status === 'draft' 43 } 44}) 45 46onMounted(() => postsMap.getAll()) 47 48// Update a post - UI automatically updates 49const publishPost = (id: string) => { 50 postsMap.set(id, { ...postsMap.value[id], status: 'published' }) 51} 52</script>
This example shows:
TL;DR:
MegaMap provides a suite of TypeScript classes for advanced key-value mapping, each offering unique capabilities:
LoadableMap: This class extends basic map functionality with dynamic loading capabilities. Key features include:
loadOne
).loadAll
).keyProperty
) for complex data types.onUpdated
).CachedLoadableMap: Building on LoadableMap, this class adds caching features with automatic expiry. It includes:
expiryInterval
).MegaMap: This is a comprehensive class combining loading, caching, and advanced manipulation. It includes:
secondaryMaps
) for additional organizational capabilities.filter
).ReactiveMegaMap: A specialized version of MegaMap designed for reactive frameworks like Vue.js. It offers:
1npm install megamap
In the examples below we are implementing things outside of state management, and in a vue template directly. This is not recommended for production use, but is done here for the sake of simplicity. We are also using some fake data loader functions, check those out here.
We'll also set up some named queries, these are basically stored functions that can be called on the MegaMap instance, allowing you to easily retrieve data from the map without having to write the same code over and over again.
The format is meant to be clean and simple, so that you can easily read and understand what the query is doing.
1 const namedQueries = { 2 byAuthor: async (authorId) => { 3 return fetch(`/api/posts/by-author/${authorId}`).then(res => res.json()) 4 }, 5 byTag: async (tag) => { 6 return fetch(`/api/posts/by-tag/${tag}`).then(res => res.json()) 7 }, 8}
...and some filters that will be used in the subListFilters
option to populate the subLists
property of our MegaMap:
1const subListFilters = { 2 active: (item: any) => item.status === "active", 3 draft: (item: any) => item.status === "draft", 4 inactive: (item: any) => item.status === "inactive", 5}
We'll refer to these functions in the examples below.
MegaMap
/ReactiveMegaMap
ClassesCurrently, these two classes are almost identical. The only difference is that ReactiveMegaMap
uses Vue reactive
properties, which enables reactivity for the sub-lists inside components/templates.
For MegaMap
:
1import { MegaMap } from "megamap" 2 3// create a new MegaMap 4const allPosts = new MegaMap({ 5 loadOne: fakeRecordLoad, // see above 6 loadAll: fakeMultipleRecordLoad, // see above, 7 subListFilters, // see above 8 namedQueries, // see above 9}) 10 11// another MegaMap that will be populated with user's "posts" 12const myPosts = MegaMap({ 13 loadOne: fakeRecordLoad, // see above 14 loadAll: fakeMultipleRecordLoad, // see above, 15 subListFilters, // see above 16 secondaryMaps: [allPosts] // see below 17 18}) 19 20// simulate a record load every second 21setInterval(async () => { 22 await megaMap.get(`key${Math.floor(Math.random() * 1000) + 1}`) 23}, 1000) 24
The MegaMap
class has a secondaryMaps
option that allows you to specify other MegaMaps that new items should be
added to. This is useful for creating multiple views of the same data, for example, a "My Posts" view and an "All Posts"
This way, when a new item is loaded into myPosts
, it will also be added to allPosts
.
and for ReactiveMegaMap
in Vue:
1<template> 2 <fieldset> 3 <legend>ACTIVE</legend> 4 <div> 5 <div v-for="item in megaMap.subLists.active" :key="item._id"> 6 {{ item.data }} 7 </div> 8 </div> 9 </fieldset> 10</template> 11<script setup> 12 13 import {ReactiveMegaMap} from "megamap" 14 15 const megaMap = new ReactiveMegaMap({ 16 loadOne: fakeRecordLoad, // see above 17 loadAll: fakeMultipleRecordLoad, // see above, 18 subListFilters, // see above 19 namedQueries, // see above 20 }) 21 22 // using the predefined named queries 23 const authorPosts = ref(await megaMap.query.byAuthor("00001")) 24 const taggedPosts = ref(await megaMap.query.byTag("fake")) 25 26 // simulate a record load every second 27 setInterval(async () => { 28 await megaMap.get(`key${Math.floor(Math.random() * 1008) + 1}`) 29 }, 1000) 30 31</script>
You can also utilize the following classes independently of MegaMap:
LoadableMap
ClassThis class extends the native JavaScript Record
object with dynamic loading capabilities. It does not include any of the
advanced features of CachedLoadableMap
or MegaMap
, but is useful for loading data into maps instead of handling this
manually.
1import { LoadableMap } from "megamap" 2 3const loadableMap = new LoadableMap<string, TFakePost>({ 4 loadOne: fakeRecordLoad, // see above 5 loadAll: fakeMultipleRecordLoad, // see above, 6 keyProperty: "_id", // default is "_id" 7 onUpdated: (updatedItem) => { 8 console.log(`Updated item: ${updatedItem.id}`) 9 } 10})
CachedLoadableMap
ClassAdds caching and expiry features to LoadableMap
, will automatically expire cached items after the specified interval,
so that they will be reloaded on the next access.
This class is useful for caching data that is accessed often, but not expected to change frequently, but may need to be refreshed.
1import { CachedLoadableMap } from 'megamap'; 2 3const cachedMap = new CachedLoadableMap<string, DataType>({ 4 loadOne: fakeRecordLoad, // see above 5 loadAll: fakeMultipleRecordLoad, // see above, 6 keyProperty: "_id", // default is "_id" 7 expiryInterval: 1000 * 60 * 60 * 24, // 24 hours 8 onUpdated: (updatedItem) => { 9 console.log(`Updated item: ${updatedItem.id}`) 10 } 11});
Contributions to MegaMap are welcome. Please feel free to submit pull requests or suggest features.
This project is licensed under the MIT License.
No vulnerabilities found.
No security vulnerabilities found.