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

sveltekit-rate-limiter

Package Overview
Dependencies
Maintainers
1
Versions
26
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

sveltekit-rate-limiter - npm Package Compare versions

Comparing version 0.3.1 to 0.3.2

17

dist/server/index.d.ts

@@ -5,3 +5,2 @@ import type { RequestEvent } from '@sveltejs/kit';

export interface RateLimiterStore {
check: (hash: string, unit: RateUnit) => Promise<number>;
add: (hash: string, unit: RateUnit) => Promise<number>;

@@ -11,3 +10,3 @@ clear: () => Promise<void>;

export interface RateLimiterPlugin {
hash: (event: RequestEvent) => Promise<string | boolean>;
hash: (event: RequestEvent) => Promise<string | boolean | null>;
get rate(): Rate;

@@ -33,8 +32,8 @@ }

}
export type RateLimiterOptions = {
plugins?: RateLimiterPlugin[];
store?: RateLimiterStore;
maxItems?: number;
onLimited?: (event: RequestEvent, reason: 'rate' | 'rejected') => Promise<void | boolean> | void | boolean;
rates?: {
export type RateLimiterOptions = Partial<{
plugins: RateLimiterPlugin[];
store: RateLimiterStore;
maxItems: number;
onLimited: (event: RequestEvent, reason: 'rate' | 'rejected') => Promise<void | boolean> | void | boolean;
rates: {
IP?: Rate;

@@ -44,3 +43,3 @@ IPUA?: Rate;

};
};
}>;
export declare class RateLimiter {

@@ -47,0 +46,0 @@ private readonly store;

@@ -19,16 +19,13 @@ import crypto from 'crypto';

}
set(hash, rate, unit) {
this.cache.set(hash, rate, { ttl: RateLimiter.TTLTime(unit) });
return rate;
}
async clear() {
return this.cache.clear();
}
async check(hash) {
return this.cache.get(hash) ?? 0;
}
async add(hash, unit) {
const currentRate = await this.check(hash);
const currentRate = this.cache.get(hash) ?? 0;
return this.set(hash, currentRate + 1, unit);
}
set(hash, rate, unit) {
this.cache.set(hash, rate, { ttl: RateLimiter.TTLTime(unit) });
return rate;
}
}

@@ -158,2 +155,5 @@ ///// Plugins /////////////////////////////////////////////////////////////////

}
else if (id === null) {
continue;
}
if (!id) {

@@ -176,3 +176,3 @@ throw new Error('Empty hash returned from rate limiter ' + plugin.constructor.name);

constructor(options = {}) {
this.plugins = options.plugins ?? [];
this.plugins = [...(options.plugins ?? [])];
this.onLimited = options.onLimited;

@@ -179,0 +179,0 @@ if (options.rates?.IP)

{
"name": "sveltekit-rate-limiter",
"version": "0.3.1",
"version": "0.3.2",
"author": "Andreas Söderlund <ciscoheat@gmail.com> (https://blog.encodeart.dev)",

@@ -5,0 +5,0 @@ "description": "A modular rate limiter for SvelteKit. Use in password resets, account registration, etc.",

@@ -5,8 +5,12 @@ # sveltekit-rate-limiter

Uses an in-memory cache, but can be swapped for something else. Same for limiters, which are plugins. See the [source file](https://github.com/ciscoheat/sveltekit-rate-limiter/blob/main/src/lib/rateLimiter.ts) for interfaces.
Uses an in-memory cache ([@isaacs/ttlcache](https://www.npmjs.com/package/@isaacs/ttlcache)), but can be swapped for something else. Same for limiters, which are plugins. The [source file](https://github.com/ciscoheat/sveltekit-rate-limiter/blob/main/src/lib/server/index.ts#L24-L32) lists both interfaces.
## How to use
```ts
import { error } from '@sveltejs/kit';
import { RateLimiter } from 'sveltekit-rate-limiter/server';
const limiter = new RateLimiter({
// A rate is defined as [number, unit]
rates: {

@@ -18,3 +22,3 @@ IP: [10, 'h'], // IP address limiter

name: 'limiterid',
secret: 'SECRETKEY-SERVER-ONLY',
secret: 'SECRETKEY-SERVER-ONLY', // Use $env/static/private
rate: [2, 'm'],

@@ -27,2 +31,3 @@ preflight: true // Require preflight call (see load)

export const load = async (event) => {
// Preflight: If not called before posting, request will be limited.
limiter.cookieLimiter?.preflight(event);

@@ -33,3 +38,3 @@ };

default: async (event) => {
if (await limiter.isLimited(event)) return fail(429);
if (await limiter.isLimited(event)) throw error(429);
}

@@ -39,2 +44,14 @@ };

The limiters will be called in smallest unit and rate order, so in the example above:
```
cookie(2/min) → IPUA(5/min) → IP(10/hour)
```
Valid units are, from smallest to largest:
```
'ms' | 's' | '15s' | '30s' | 'm' | '15m' | '30m' | 'h' | '2h' | '6h' | '12h' | 'd'
```
## Creating a custom limiter

@@ -46,3 +63,3 @@

interface RateLimiterPlugin {
hash: (event: RequestEvent) => Promise<string | boolean>;
hash: (event: RequestEvent) => Promise<string | boolean | null>;
get rate(): Rate;

@@ -52,6 +69,17 @@ }

In `hash`, return a string based on a `RequestEvent`, which will be counted and checked against the rate, or a boolean to make the request fail (`false`) or succeed (`true`) no matter the current rate. The string will be hashed later.
In `hash`, return one of the following:
Here's the source for the IP + User Agent limiter, as an example:
- A `string` based on a [RequestEvent](https://kit.svelte.dev/docs/types#public-types-requestevent), which will be counted and checked against the rate.
- A `boolean`, to short-circuit the plugin chain and make the request fail (`false`) or succeed (`true`) no matter the current rate.
- Or `null`, to signify an indeterminate result and move to the next plugin in the chain, or fail the request if it's the last one.
### String hash rules
- The string will be hashed later, so you don't need to use a hash function.
- The string cannot be empty, in which case an exception will be thrown.
### Example
Here's the source for the IP + User Agent limiter:
```ts

@@ -76,3 +104,3 @@ import type { RequestEvent } from '@sveltejs/kit';

Add the limiter to `options.plugins` to use it.
Add your limiter to `options.plugins` to use it.

@@ -84,3 +112,4 @@ ```ts

plugins: [new CustomLimiter([5, 'm'])]
// The built-in limiters can be added as well.
});
```
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