
Research
Shai-Hulud Descends to Hades: Miasma Worm Campaign Spreads with New PyPI Wave
Socket found 37 malicious PyPI wheels that abuse Python startup hooks to launch a Bun-powered credential stealer tied to Mini Shai-Hulud/Miasma.
@mountainpass/server-agnostic-functions-core
Advanced tools
Provides an interface for writing server-agnostic (serverless) functions.
Provides an interface for writing server-agnostic (serverless) functions.
The name "serverless functions" is a misnomer - there's always a server involved. The intention of the term is to demonstrate that the developer is shielded from the operational concerns - however there are still many facets that make serverless implementations difficult to maintain:
Vendor Lock In
Libraries
Routing
Testing
Every service provider has reinvented it's own serverless function interfaces which means vendor lockin - we strive to be provider agnostic.
This library provides an AgnosticRouter class (and HttpRequest, HttpResponse interfaces), so that functions can be built using a standard (HTTP) interface, and then wrapped in it's respective runtime Wrapper.
Due to the simplified interface and the inbuilt Routing layer, we can reliably unit test our Router in isolation, with the confidence that the hosted service will behave consistently at runtime.
Here is an example AgnosticRouter implementation. e.g.
import { AgnosticRouter } from '@mountainpass/server-agnostic-functions-core'
const router = new AgnosticRouter()
router.get('/users/{userId}', (req, res) => {
res.json({message: 'success', user: req.params.userId })
})
router.get('/services/getUsersByQueryId', (req, res) => {
res.json({message: 'success', user: req.query.userId })
})
Then to host it, wrap it in your service provider's wrapper. Below is an example using ExpressWrapper. e.g.
import { ExpressWrapper } from '@mountainpass/server-agnostic-functions-express'
import express from 'express'
const app = express()
app.use(new ExpressWrapper().wrap(diagnosticRouter()))
app.listen(3000, () => console.log('listening on port 3000'))
More provider examples are available below.
Supported provider wrappers and their example usages:
| Status | Package | Provides a wrapper for... | Usage Example |
|---|---|---|---|
| ✅ | @mountainpass/server-agnostic-functions-aws | AWS Lambda Functions | Link |
| ✅ | @mountainpass/server-agnostic-functions-cloudflare | Cloudflare Workers | Link |
| ✅ | @mountainpass/server-agnostic-functions-express | Express NodeJs Web Application Framework | Link |
| ❓ | Your Provider? |
The router provides helper functions for all http methods. e.g.
router.get('/mypath', ...)
router.post('/mypath', ...)
router.put('/mypath', ...)
router.delete('/mypath', ...)
router.patch('/mypath', ...)
router.head('/mypath', ...)
router.options('/mypath', ...)
router.connect('/mypath', ...)
router.trace('/mypath', ...)
Have multiple routers? The core library allows you to join two routers together.
Use the following code to add router2's middleware and routes, into the original router. These calls can be chained.
router
.join(router2)
.join(router3)
The following example demonstrates the use of paths and path parameters. e.g.
// simple paths
router.get('/', ...)
router.get('/some/path', ...)
// path parameters
router.get('/user/{userId}/order/{orderId}', (req, res) => {
res.json({ user: req.params.userId, order: req.params.orderId })
})
// regular expressions and named groups
router.get(/^\/some\/path$/, ...)
router.get('/some/path/.*', ...)
router.get('/user/(?<userId>[^/?]+)/order/(?<orderId>[^/?]+)', (req, res) => {
res.json({ user: req.params.userId, order: req.params.orderId })
})
There is a use function for providing middleware on incoming requests. You may end the response flow at any point, by invoking the res.json(), res.send(), or res.end() functions. e.g.
// apply a global response header
router.use(async (req: HttpRequest, res: HttpResponse) => {
res.headers['access-control-allow-origin'] = ['*']
})
// reject unauthorised requests
router.use(async (req: HttpRequest, res: HttpResponse) => {
if (!isAuthorised(req)) {
res.status(401)
res.send('Unauthorised')
}
})
An inmemory, temporal, lazy loading cache (InMemoryCacher) is provided, for caching data.
Alternatively you can use the HttpResponseCacher, a higher level abstraction which handles the http response for you (and supports ETag and Cache-Control headers).
import {
AgnosticRouter,
FetchResponseQueryablePromise,
hashString,
HttpRequest,
HttpResponse,
HttpResponseCacher
} from '@mountainpass/server-agnostic-functions-core';
import mongoose from 'mongoose';
import Users from './db/Users.model';
// responsible for fetching data from the database and caching it, based on a key
const dataFetcher = new HttpResponseCacher(async (key: string, prevData: FetchResponseQueryablePromise<string> | undefined) => {
await mongoose.connect(process.env.MONGO_URL)
const tmp = await Users.find({ userId: key })
const data = JSON.stringify(tmp)
const hash = hashString(data)
// returns two objects the data and the hash
return { data, hash }
}, { maxAgeMs: 30000, maxItems: 10 })
export const router = new AgnosticRouter()
// fetches data from the cache based on the userId key
router.get('/users/{userId}', async (req: HttpRequest, res: HttpResponse) => {
return dataFetcher.fetchAndServe(req, res, req.params.userId)
}
We don't currently support serving files from the filesystem for two reasons:
However, I can definitely see the value in being able to provide this functionality.
I'd love to hear if anyone has any ideas on how to solve this. e.g.
.js file, and then unzip and serve content from in memory. (https://www.npmjs.com/package/jszip)fs operations can opt in.Most serverless functions do not support maintaining websockets or streaming content. As such, we have not included support for these services.
Some serverless environments are not NodeJS environments. As such, efforts have been made to exclude all NodeJS native libraries and global variables usage from the core module.
Don't see your provider? Have a go at writing your own, it's actually very easy! Start with the AwsWrapper as an example.
Once it's ready, please submit a PR back to the repo, so the entire community can benefit!
The wrapper should be as lightweight and efficient as possible. Avoid adding unneccessary libraries or code.
AgnosticRouter can take Type arguments, for the underlying Request and Response types. These are then provided via the underlying property, on the HttpRequest and HttpResponse handler parameters.AgnosticRouter does not (currently) support nesting child AgnosticRouters.FAQs
Provides an interface for writing server-agnostic (serverless) functions.
The npm package @mountainpass/server-agnostic-functions-core receives a total of 3 weekly downloads. As such, @mountainpass/server-agnostic-functions-core popularity was classified as not popular.
We found that @mountainpass/server-agnostic-functions-core demonstrated a not healthy version release cadence and project activity because the last version was released a year ago. It has 2 open source maintainers collaborating on the project.
Did you know?

Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.

Research
Socket found 37 malicious PyPI wheels that abuse Python startup hooks to launch a Bun-powered credential stealer tied to Mini Shai-Hulud/Miasma.

Security News
RubyGems and Bundler 4.0.13 introduced an opt-in cooldown feature that delays newly published gems during dependency resolution.

Security News
pnpm 11.5 now recognizes npm staged publish approvals in release metadata, preventing those releases from being mistaken for lower-trust package publishes.