Skip to content
← Back to Community
FnCache - Snippet Package Manager
Profile icon
seanlnge

This was my submission for Repl.it's Code Jam #10. It was made over the course of 19 straight hours of work, 12 of which were overnight, so I'm not having such a great morning lol


FnCache

Snippet Package Manager by SpicySpices

The node package manager is a great tool, it allows for entire scripts of code to be ran in a single line of code. It is a great tool to use in any Node.js project. Although NPM's power is unmatched, it is much too excessive for minute usage.

Take an example, imagine a user is trying to create a 3 dimensional rendering engine. There are many things to calculate, rotation matrices, 3d points to ordered pairs on a screen - the point is that there are many functions that need to be created for a simple creation. The user would also like these functions to be written with utmost precision and speed. A solution for all of these problems would be FnCache.


What is FnCache

FnCache is an NPM package and website that can provide any function in the FnCache library. It has the purpose of being an easy way to retrieve small functions without the trouble of going through the process of installing NPM packages. It is basically the node package manager, but for smaller functions and with more ease.

To call a function using FnCache, simply type fn.<name of function>(parameters). Need to check if a number is prime using the quickest known algorithm? fn.isPrime(22679) BOOM, someone made a function for that. Need to send a GET request to your server? fn.getRequest(url) BOOM, a function for that.

Any function that can be written is a function that can be created in FnCache. No matter whether it is asynchronous, returns a value, or takes 10 minutes to resolve, any function can be added to FnCache, even ones containing other functions.


Installation

Now knowing what FnCache is, how do we implement it? It is a simple process, but first it is necessary to download the NPM package for FnCache
npm i @spicyspices/fncache
We can then add a require or import statement into the code

const fn = require('@spicyspices/fncache');

After that, we need to use await on a starter FnCache function, with the first parameter being the node file that is running, and the other being the variable that FnCache is saved to.

await fn('index.js', 'fn');

With that done, we can use any function in the FnCache library.

console.log(fn.add(5483, 3395)); // Logs '8878'

Usage

Getting a function is as simple as typing fn. and then whatever function you desire to use. For instance, if you were to have a dice roller, you could enter let diceRoll = fn.randomInt(1, 6);, and then variable diceRoll would become a random integer from 1 to 6. There are many functions and they are all catalogued on this website

Creating a function is also very simple. There are 2 ways to do so, either by using the website directly, or manually doing it by using code. The website is very straight-forward, so I will not explain that, but the code is a bit different. To create a function, everything will need to be setup to start. Next you will need to write fn.set() this will take 3 required parameters and a callback. These parameters are desired function name, current function, and description. The callback will need an error and data parameters. After following these, it should look something like this:

function divBy2(x){ return x % 2 == 0; } fn.set('isEven', divBy2, "Check if given argument is even", (err, data) => { if(err) throw err; console.log(data); })

How it Works

FnCache is an online service, meaning it has a server. This server stores information such as the code, the parameters, and the number of downloads, to view on the website, and to send to users. Obviously, the client is not going to be able to store the tens of thousands of possible functions, that would be many megabytes of data, and this is where the Cache in FnCache comes in. The package @spicyspices/fncache will first start by scanning the main Node.js file to look for possible fn functions that might be called; this is in the await fn('index.js', 'fn'); method. After collecting the possible functions, it will send a request to the server to get the code for those functions. It will store these into another file and format the functions plus the module.exports = {} to allow Node.js to recognize them as a script. The package will then use require(''); on the file, and copy the functions into the global fn object. For speed however, only during the caching process, the package will use eval() to set the functions into the fn object, and synchronously format the file while the rest of the code is running. During any other times that the code might be ran, the package will use the other file with the cached functions for ease and speed.


Test Programs

Random String Generator

const fn = require('@spicyspices/fncache'); async function main(){ await fn('index.js', 'fn'); let str = ''; for(let i = 0; i < 8; i++){ let random = fn.randomInt(65, 122); str += fn.intToChar(random); } console.log(str); } main();

Creating a Sleep Function

const fn = require('@spicyspices/fncache'); async function main(){ await fn('index.js', 'fn'); fn.set('sleep', sleep, 'An asynchronous function that only finishes once a timespan (ms) has passed', (err, data) => { if(err) throw err; console.log(data); }); } function sleep(ms){ return new Promise(resolve => setTimeout(resolve, ms)); } main();

Simulating a Roll of Dice

const fn = require('@spicyspices/fncache'); async function main(){ await fn('index.js', 'fn'); let sides = 20; let amount = 4; let rolls = []; for(let i = 0; i < amount; i++){ rolls.push(fn.randomInt(1, 20)); } console.log(rolls); } main();

Links:

Official Website
Server Code
Github Repository
NPM Package Registry
Test Program with FnCache

Thanks for checking this out :)

Voters
Profile icon
LKgroup
Profile icon
badst
Profile icon
Kookiez
Profile icon
darknew
Profile icon
elipie
Profile icon
EpicGamer007
Profile icon
DynamicSquid
Profile icon
programmeruser
Profile icon
TsunamiOrSumth
Profile icon
RayhanADev
Comments
hotnewtop
Profile icon
fuzzyastrocat

That's nice. How does the performance of calling a FnCache function compare to calling the function directly?

Best of luck with the jam too! :D

Profile icon
seanlnge

@fuzzyastrocat thanks you as well :D

An FnCache function runs the exact same code, therefore not reducing performance, however the one thing that takes time is retrieving and caching all of the functions, because it has to send a request to the server, which takes several milliseconds. This only has to happen once though as the functions are already saved.

Profile icon
fuzzyastrocat

@SpicedSpices That caching was what I was wondering about. Once again, nicely done!

Profile icon
fuzzyastrocat

@SpicedSpices Oh forgot to ask — will the caching take more time as more functions are added to the database, or does it only retrieve the functions used in the program?

Profile icon
seanlnge

@fuzzyastrocat ah ok, thanks and you as well!

Profile icon
seanlnge

@fuzzyastrocat the way it works is by scanning over the index.js file, and finding all the potential functions that might be used, and retrieving those, so no it should stay the same amount of time with more functions in the database

Profile icon
fuzzyastrocat

@SpicedSpices Great! Sorry for all the questions, but I'm interested: how does it scan to see which functions are used? Example: let string = "add"; if(1 < 2) { string = "sub"; } fn[string](1, 2);

Profile icon
seanlnge

@fuzzyastrocat that is something it cannot do, but after some thought about it, you wouldn't be able to do that with normal functions, so I don't mind that bug feature that much

Profile icon
fuzzyastrocat

@SpicedSpices You would be able to do that with normal functions (I do it often in my projects)...

function fun_a(x){ console.log("fun_a got: " + x); } function fun_b(x){ console.log("fun_b got: " + x); } const fn = { a: fun_a, b: fun_b }; let string = "a"; if(1 < 2) { string = "b"; } fn[string](1);
Profile icon
seanlnge

@fuzzyastrocat ah i see what you mean, but what im thinking is visualizing fn.add as its own function. I guess you are right though that could add a layer of complexity to running the functions

Profile icon
fuzzyastrocat

@SpicedSpices Hmm ok. fn.add isn't its own function though, the key add in the object fn points to some function (namely, the adding one).

Profile icon
seanlnge

@fuzzyastrocat yeah i get that, im just saying that for the sake of simplicity, treating it as one function would make it easier to work with

Profile icon
fuzzyastrocat

@SpicedSpices I'm not sure what you mean by "as one function", but I think I get what you're saying otherwise. (Though not easier to work with, easier to implement :D)

Profile icon
DynamicSquid

Looking spicey!

Profile icon
HahaYes

@DynamicSquid yes, quite spicy

Profile icon
RayhanADev

Oh sick CSS, it gets a bit wack on smaller displays but good work! Best of luck!

Profile icon
firefish

@SpicedSpices I found them alll.

function sub(a, b){ return a - b; } function randomFloat(min, max){ return Math.random()*(max-min)+min; } function mul(a, b){ return a * b; } function isEven(a){ return a % 2 == 0; } function div(a, b){ return a / b; } function permutate(n, r){ let nf = n; let nrf = n - r; for(let i=2; i<n; i++) nf *= i; for(let i=2; i<n-r; i++) nrf *= i; return nf/nrf; } function intToChar(int){ return String.fromCharCode(int); } function randomInt(min, max){ return Math.floor(Math.random()*(max-min+1)+min); } function isPrime(n){ if(n % 2 == 0 || n % 3 == 0) return false; for(let i=6; i<Math.floor(Math.sqrt(n)); i += 6){ if(n % (i + 1) == 0) return false; if(n % (i - 1) == 0) return false; } return true; } async function getRequest(url, json) { const fetch = require('node-fetch'); let response = await fetch(url); if(json) return response.json(); return response; } function factorial(n){ let val = n; for(let i=2; i<n; i++){ val *= i; } return val; } function sleep(ms){ return new Promise(resolve => setTimeout(resolve, ms)); } function p(statement){ console.log(statement); } function add(a, b){ return a + b; } function gcf(x, y){ return x == 0 ? y : gcf(y%x, x); } module.exports = {sub, randomFloat, mul, isEven, div, permutate, intToChar, randomInt, isPrime, getRequest, factorial, sleep, p, add, gcf}
Profile icon
seanlnge

@firefish lol why did you download all of them

Profile icon
firefish

@SpicedSpices was just a bit bored...

Profile icon
seanlnge
Profile icon
TsunamiOrSumth

existential crisis deepens
good job and good luck tho!

Profile icon
realTronsi

what's the point of fn.add() and fn.intToChar(int) etc.

Profile icon
seanlnge

@realTronsi those are just test functions that I added to make sure everything worked

Profile icon
realTronsi