@lunora/ratelimit 1.0.0-alpha.13 → 1.0.0-alpha.15
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.d.mts +40 -6
- package/dist/index.d.ts +40 -6
- package/dist/index.mjs +1 -1
- package/dist/packem_shared/{RateLimiter-BcVZuxFA.mjs → RateLimiter-uPXzD0St.mjs} +1 -1
- package/dist/packem_shared/createDbStore-CwJBMxDQ.mjs +1 -0
- package/dist/packem_shared/dbRateLimit-CrjZatIs.mjs +1 -0
- package/package.json +2 -2
- package/dist/packem_shared/createDbStore-VpnhCmRx.mjs +0 -1
- package/dist/packem_shared/dbRateLimit-D7voUQX3.mjs +0 -1
package/dist/index.d.mts
CHANGED
|
@@ -278,21 +278,33 @@ interface RateLimitDatabaseQuery {
|
|
|
278
278
|
first: () => Promise<Record<string, unknown> | null>;
|
|
279
279
|
withIndex: (indexName: string, range: (q: RateLimitDatabaseIndexRange) => RateLimitDatabaseIndexRange) => RateLimitDatabaseQuery;
|
|
280
280
|
}
|
|
281
|
+
/**
|
|
282
|
+
* The READ slice — everything the store needs to answer `RateLimiter.getValue`
|
|
283
|
+
* and `check`, which the docs describe as projecting the stored value forward to
|
|
284
|
+
* the current clock. A `QueryCtx`'s `ctx.db` is a reader and satisfies this.
|
|
285
|
+
*
|
|
286
|
+
* Split out because requiring the writer for a pure read meant "how many
|
|
287
|
+
* requests does this user have left" could not be answered from a query context
|
|
288
|
+
* at all — every remaining-quota display had to cast, and a cast that appears
|
|
289
|
+
* often enough stops carrying information. The distinction was already in the
|
|
290
|
+
* methods: `getValue`/`check` read, `limit`/`reset` write.
|
|
291
|
+
*/
|
|
292
|
+
interface RateLimitDatabaseReader {
|
|
293
|
+
query: (table: string) => RateLimitDatabaseQuery;
|
|
294
|
+
}
|
|
281
295
|
/**
|
|
282
296
|
* The slice of the Lunora ORM writer (`ctx.db` on a mutation/action) the store
|
|
283
297
|
* needs. The real `DatabaseWriter` is structurally assignable, so pass `ctx.db`
|
|
284
298
|
* directly — declared here (rather than imported) to keep `@lunora/ratelimit`
|
|
285
299
|
* free of a runtime dependency on `@lunora/server`.
|
|
286
300
|
*/
|
|
287
|
-
interface RateLimitDatabase {
|
|
301
|
+
interface RateLimitDatabase extends RateLimitDatabaseReader {
|
|
288
302
|
delete: <T extends string>(id: Id<T>) => Promise<void>;
|
|
289
303
|
insert: <T extends string>(table: T, document: Record<string, unknown>) => Promise<Id<T>>;
|
|
290
304
|
patch: <T extends string>(id: Id<T>, patch: Record<string, unknown>) => Promise<void>;
|
|
291
|
-
query: (table: string) => RateLimitDatabaseQuery;
|
|
292
305
|
}
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
db: RateLimitDatabase;
|
|
306
|
+
/** The table/column/index knobs shared by the read-only and read-write stores. */
|
|
307
|
+
interface DatabaseStoreLocation {
|
|
296
308
|
/** Index that resolves a row by its key column. Defaults to `by_key`. */
|
|
297
309
|
index?: string;
|
|
298
310
|
/** Column storing the opaque key. Defaults to `key`. */
|
|
@@ -300,6 +312,14 @@ interface DatabaseStoreOptions {
|
|
|
300
312
|
/** Table holding one row per `(name, key)` pair. Defaults to `rateLimits`. */
|
|
301
313
|
table?: string;
|
|
302
314
|
}
|
|
315
|
+
interface DatabaseStoreOptions extends DatabaseStoreLocation {
|
|
316
|
+
/** The Lunora ORM writer — `ctx.db` inside a mutation or action. */
|
|
317
|
+
db: RateLimitDatabase;
|
|
318
|
+
}
|
|
319
|
+
interface ReadOnlyDatabaseStoreOptions extends DatabaseStoreLocation {
|
|
320
|
+
/** The Lunora ORM reader — `ctx.db` inside a query. */
|
|
321
|
+
db: RateLimitDatabaseReader;
|
|
322
|
+
}
|
|
303
323
|
/**
|
|
304
324
|
* Store backed by a Lunora table through `ctx.db`, for durable per-DO limits
|
|
305
325
|
* inside a procedure (the procedure context exposes no raw SQL). Declare a
|
|
@@ -318,6 +338,20 @@ interface DatabaseStoreOptions {
|
|
|
318
338
|
* under the DO's input gate, so it is atomic against concurrent calls.
|
|
319
339
|
*/
|
|
320
340
|
declare const createDatabaseStore: (options: DatabaseStoreOptions) => RateLimitStore;
|
|
341
|
+
/**
|
|
342
|
+
* Read-only counterpart to {@link createDatabaseStore}, for a query context.
|
|
343
|
+
*
|
|
344
|
+
* `get` behaves identically — same table, index and key column — so
|
|
345
|
+
* `RateLimiter.getValue` / `check` report exactly what the writing store would.
|
|
346
|
+
* `set` and `delete` are the only difference: they throw rather than silently
|
|
347
|
+
* doing nothing, because a limiter that appears to consume budget and does not
|
|
348
|
+
* is worse than one that refuses.
|
|
349
|
+
*
|
|
350
|
+
* This mirrors the split Lunora already makes for `ctx.storage`, which is a
|
|
351
|
+
* `ReadOnlyStorage` in a query and a full `Storage` in an action — the
|
|
352
|
+
* capability difference is visible in the type instead of discovered at runtime.
|
|
353
|
+
*/
|
|
354
|
+
declare const createReadOnlyDatabaseStore: (options: ReadOnlyDatabaseStoreOptions) => RateLimitStore;
|
|
321
355
|
/**
|
|
322
356
|
* DB-backed rate-limit middleware sugar. Collapses the common
|
|
323
357
|
*
|
|
@@ -406,4 +440,4 @@ interface RatelimitApiContext<Context> {
|
|
|
406
440
|
*/
|
|
407
441
|
declare const ratelimitPlugin: <Context = unknown>(limiter: LimiterResolver<Context>) => Plugin<Record<never, never>, Context, Context & RatelimitApiContext<Context>>;
|
|
408
442
|
declare const VERSION = "0.0.0";
|
|
409
|
-
export { type DatabaseStoreOptions as DbStoreOptions, type EvaluateOptions, type EvaluateResult, type LimiterResolver, type RateLimitArgs, type RateLimitConfig, type RateLimitConfigMap, type RateLimitDatabase as RateLimitDb, type RateLimitDatabaseIndexRange as RateLimitDbIndexRange, type RateLimitDatabaseQuery as RateLimitDbQuery, RateLimitError, type RateLimitKind, type RateLimitMiddlewareOptions, type RateLimitReason, type RateLimitStatus, type RateLimitStore, type RateLimitValue, RateLimiter, type RateLimiterOptions, type RatelimitApiContext, type SqlLike, type SqlStoreOptions, VERSION, availableAt, createDatabaseStore as createDbStore, createMemoryStore, createSqlStore, databaseRateLimit as dbRateLimit, evaluate, rateLimit, ratelimitPlugin };
|
|
443
|
+
export { type DatabaseStoreOptions as DbStoreOptions, type EvaluateOptions, type EvaluateResult, type LimiterResolver, type RateLimitArgs, type RateLimitConfig, type RateLimitConfigMap, type RateLimitDatabase as RateLimitDb, type RateLimitDatabaseIndexRange as RateLimitDbIndexRange, type RateLimitDatabaseQuery as RateLimitDbQuery, type RateLimitDatabaseReader as RateLimitDbReader, RateLimitError, type RateLimitKind, type RateLimitMiddlewareOptions, type RateLimitReason, type RateLimitStatus, type RateLimitStore, type RateLimitValue, RateLimiter, type RateLimiterOptions, type RatelimitApiContext, type ReadOnlyDatabaseStoreOptions as ReadOnlyDbStoreOptions, type SqlLike, type SqlStoreOptions, VERSION, availableAt, createDatabaseStore as createDbStore, createMemoryStore, createReadOnlyDatabaseStore as createReadOnlyDbStore, createSqlStore, databaseRateLimit as dbRateLimit, evaluate, rateLimit, ratelimitPlugin };
|
package/dist/index.d.ts
CHANGED
|
@@ -278,21 +278,33 @@ interface RateLimitDatabaseQuery {
|
|
|
278
278
|
first: () => Promise<Record<string, unknown> | null>;
|
|
279
279
|
withIndex: (indexName: string, range: (q: RateLimitDatabaseIndexRange) => RateLimitDatabaseIndexRange) => RateLimitDatabaseQuery;
|
|
280
280
|
}
|
|
281
|
+
/**
|
|
282
|
+
* The READ slice — everything the store needs to answer `RateLimiter.getValue`
|
|
283
|
+
* and `check`, which the docs describe as projecting the stored value forward to
|
|
284
|
+
* the current clock. A `QueryCtx`'s `ctx.db` is a reader and satisfies this.
|
|
285
|
+
*
|
|
286
|
+
* Split out because requiring the writer for a pure read meant "how many
|
|
287
|
+
* requests does this user have left" could not be answered from a query context
|
|
288
|
+
* at all — every remaining-quota display had to cast, and a cast that appears
|
|
289
|
+
* often enough stops carrying information. The distinction was already in the
|
|
290
|
+
* methods: `getValue`/`check` read, `limit`/`reset` write.
|
|
291
|
+
*/
|
|
292
|
+
interface RateLimitDatabaseReader {
|
|
293
|
+
query: (table: string) => RateLimitDatabaseQuery;
|
|
294
|
+
}
|
|
281
295
|
/**
|
|
282
296
|
* The slice of the Lunora ORM writer (`ctx.db` on a mutation/action) the store
|
|
283
297
|
* needs. The real `DatabaseWriter` is structurally assignable, so pass `ctx.db`
|
|
284
298
|
* directly — declared here (rather than imported) to keep `@lunora/ratelimit`
|
|
285
299
|
* free of a runtime dependency on `@lunora/server`.
|
|
286
300
|
*/
|
|
287
|
-
interface RateLimitDatabase {
|
|
301
|
+
interface RateLimitDatabase extends RateLimitDatabaseReader {
|
|
288
302
|
delete: <T extends string>(id: Id<T>) => Promise<void>;
|
|
289
303
|
insert: <T extends string>(table: T, document: Record<string, unknown>) => Promise<Id<T>>;
|
|
290
304
|
patch: <T extends string>(id: Id<T>, patch: Record<string, unknown>) => Promise<void>;
|
|
291
|
-
query: (table: string) => RateLimitDatabaseQuery;
|
|
292
305
|
}
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
db: RateLimitDatabase;
|
|
306
|
+
/** The table/column/index knobs shared by the read-only and read-write stores. */
|
|
307
|
+
interface DatabaseStoreLocation {
|
|
296
308
|
/** Index that resolves a row by its key column. Defaults to `by_key`. */
|
|
297
309
|
index?: string;
|
|
298
310
|
/** Column storing the opaque key. Defaults to `key`. */
|
|
@@ -300,6 +312,14 @@ interface DatabaseStoreOptions {
|
|
|
300
312
|
/** Table holding one row per `(name, key)` pair. Defaults to `rateLimits`. */
|
|
301
313
|
table?: string;
|
|
302
314
|
}
|
|
315
|
+
interface DatabaseStoreOptions extends DatabaseStoreLocation {
|
|
316
|
+
/** The Lunora ORM writer — `ctx.db` inside a mutation or action. */
|
|
317
|
+
db: RateLimitDatabase;
|
|
318
|
+
}
|
|
319
|
+
interface ReadOnlyDatabaseStoreOptions extends DatabaseStoreLocation {
|
|
320
|
+
/** The Lunora ORM reader — `ctx.db` inside a query. */
|
|
321
|
+
db: RateLimitDatabaseReader;
|
|
322
|
+
}
|
|
303
323
|
/**
|
|
304
324
|
* Store backed by a Lunora table through `ctx.db`, for durable per-DO limits
|
|
305
325
|
* inside a procedure (the procedure context exposes no raw SQL). Declare a
|
|
@@ -318,6 +338,20 @@ interface DatabaseStoreOptions {
|
|
|
318
338
|
* under the DO's input gate, so it is atomic against concurrent calls.
|
|
319
339
|
*/
|
|
320
340
|
declare const createDatabaseStore: (options: DatabaseStoreOptions) => RateLimitStore;
|
|
341
|
+
/**
|
|
342
|
+
* Read-only counterpart to {@link createDatabaseStore}, for a query context.
|
|
343
|
+
*
|
|
344
|
+
* `get` behaves identically — same table, index and key column — so
|
|
345
|
+
* `RateLimiter.getValue` / `check` report exactly what the writing store would.
|
|
346
|
+
* `set` and `delete` are the only difference: they throw rather than silently
|
|
347
|
+
* doing nothing, because a limiter that appears to consume budget and does not
|
|
348
|
+
* is worse than one that refuses.
|
|
349
|
+
*
|
|
350
|
+
* This mirrors the split Lunora already makes for `ctx.storage`, which is a
|
|
351
|
+
* `ReadOnlyStorage` in a query and a full `Storage` in an action — the
|
|
352
|
+
* capability difference is visible in the type instead of discovered at runtime.
|
|
353
|
+
*/
|
|
354
|
+
declare const createReadOnlyDatabaseStore: (options: ReadOnlyDatabaseStoreOptions) => RateLimitStore;
|
|
321
355
|
/**
|
|
322
356
|
* DB-backed rate-limit middleware sugar. Collapses the common
|
|
323
357
|
*
|
|
@@ -406,4 +440,4 @@ interface RatelimitApiContext<Context> {
|
|
|
406
440
|
*/
|
|
407
441
|
declare const ratelimitPlugin: <Context = unknown>(limiter: LimiterResolver<Context>) => Plugin<Record<never, never>, Context, Context & RatelimitApiContext<Context>>;
|
|
408
442
|
declare const VERSION = "0.0.0";
|
|
409
|
-
export { type DatabaseStoreOptions as DbStoreOptions, type EvaluateOptions, type EvaluateResult, type LimiterResolver, type RateLimitArgs, type RateLimitConfig, type RateLimitConfigMap, type RateLimitDatabase as RateLimitDb, type RateLimitDatabaseIndexRange as RateLimitDbIndexRange, type RateLimitDatabaseQuery as RateLimitDbQuery, RateLimitError, type RateLimitKind, type RateLimitMiddlewareOptions, type RateLimitReason, type RateLimitStatus, type RateLimitStore, type RateLimitValue, RateLimiter, type RateLimiterOptions, type RatelimitApiContext, type SqlLike, type SqlStoreOptions, VERSION, availableAt, createDatabaseStore as createDbStore, createMemoryStore, createSqlStore, databaseRateLimit as dbRateLimit, evaluate, rateLimit, ratelimitPlugin };
|
|
443
|
+
export { type DatabaseStoreOptions as DbStoreOptions, type EvaluateOptions, type EvaluateResult, type LimiterResolver, type RateLimitArgs, type RateLimitConfig, type RateLimitConfigMap, type RateLimitDatabase as RateLimitDb, type RateLimitDatabaseIndexRange as RateLimitDbIndexRange, type RateLimitDatabaseQuery as RateLimitDbQuery, type RateLimitDatabaseReader as RateLimitDbReader, RateLimitError, type RateLimitKind, type RateLimitMiddlewareOptions, type RateLimitReason, type RateLimitStatus, type RateLimitStore, type RateLimitValue, RateLimiter, type RateLimiterOptions, type RatelimitApiContext, type ReadOnlyDatabaseStoreOptions as ReadOnlyDbStoreOptions, type SqlLike, type SqlStoreOptions, VERSION, availableAt, createDatabaseStore as createDbStore, createMemoryStore, createReadOnlyDatabaseStore as createReadOnlyDbStore, createSqlStore, databaseRateLimit as dbRateLimit, evaluate, rateLimit, ratelimitPlugin };
|
package/dist/index.mjs
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
import{availableAt as o,evaluate as a}from"./packem_shared/availableAt-DITZ7jdT.mjs";import{default as i}from"./packem_shared/dbRateLimit-
|
|
1
|
+
import{availableAt as o,evaluate as a}from"./packem_shared/availableAt-DITZ7jdT.mjs";import{default as i}from"./packem_shared/dbRateLimit-CrjZatIs.mjs";import{default as l}from"./packem_shared/RateLimitError-xJ2Iv-i7.mjs";import{rateLimit as x}from"./packem_shared/rateLimit-DLcwK-84.mjs";import{ratelimitPlugin as c}from"./packem_shared/ratelimitPlugin-D1QHZF9b.mjs";import{RateLimiter as b}from"./packem_shared/RateLimiter-uPXzD0St.mjs";import{createDbStore as u,createMemoryStore as L,createReadOnlyDbStore as n,createSqlStore as s}from"./packem_shared/createDbStore-CwJBMxDQ.mjs";const e="0.0.0";export{l as RateLimitError,b as RateLimiter,e as VERSION,o as availableAt,u as createDbStore,L as createMemoryStore,n as createReadOnlyDbStore,s as createSqlStore,i as dbRateLimit,a as evaluate,x as rateLimit,c as ratelimitPlugin};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{LunoraError as n}from"@lunora/errors";import{availableAt as p,evaluate as N}from"./availableAt-DITZ7jdT.mjs";import d from"./RateLimitError-xJ2Iv-i7.mjs";import{createMemoryStore as g}from"./createDbStore-
|
|
1
|
+
import{LunoraError as n}from"@lunora/errors";import{availableAt as p,evaluate as N}from"./availableAt-DITZ7jdT.mjs";import d from"./RateLimitError-xJ2Iv-i7.mjs";import{createMemoryStore as g}from"./createDbStore-CwJBMxDQ.mjs";const v=(r,t)=>t===void 0?encodeURIComponent(r):`${encodeURIComponent(r)}:${encodeURIComponent(t)}`,b=(r,t)=>{let e=0;for(let i=0;i<r.length;i+=1)e=e*31+r.charCodeAt(i)|0;return Math.abs(e)%t},w=(r,t)=>t>1?{...r,capacity:(r.capacity??r.rate)/t,rate:r.rate/t}:r,I=(r,t,e)=>{const i=v(r,t);return e>1?Array.from({length:e},(o,s)=>`${i}#${String(s)}`):[i]},f=(r,t,e)=>{const i=v(r,t);return e>1?`${i}#${String(b(i,e))}`:i};class R{config;denyList;normalize;now;store;constructor(t){this.config=t.config,this.denyList=new Set(t.denyList),this.normalize=t.normalize??(e=>e),this.now=t.now??Date.now,this.store=t.store??g();for(const[e,i]of Object.entries(this.config)){if(i.shards!==void 0&&(!Number.isInteger(i.shards)||i.shards<1))throw new n("INTERNAL",`rate limit "${e}": shards must be a positive integer`);if(!Number.isFinite(i.period)||i.period<=0)throw new n("INTERNAL",`rate limit "${e}": period must be a positive number`);if(!Number.isFinite(i.rate)||i.rate<=0)throw new n("INTERNAL",`rate limit "${e}": rate must be a positive number`);if(i.capacity!==void 0&&(!Number.isFinite(i.capacity)||i.capacity<0))throw new n("INTERNAL",`rate limit "${e}": capacity must be a non-negative number`)}}async check(t,e={}){return this.run(t,e,!1)}async getValue(t,e={}){const i=this.resolve(t),o=i.shards??1,s=this.now(),a=e.key===void 0?void 0:this.normalize(e.key),m=f(t,a,o),c=p(w(i,o),await this.store.get(m),s);return{config:i,ts:c.ts,value:c.value}}async limit(t,e={}){return this.run(t,e,!0)}async reset(t,e={}){const i=this.resolve(t).shards??1,o=e.key===void 0?void 0:this.normalize(e.key);await Promise.all(I(t,o,i).map(s=>Promise.resolve(this.store.delete(s))))}resolve(t){const e=this.config[t];if(!e)throw new n("INTERNAL",`rate limit "${t}" is not configured`);return e}async run(t,e,i){const o=this.resolve(t),s=e.key===void 0?void 0:this.normalize(e.key);if(s!==void 0&&(this.denyList.has(s)||this.denyList.has(e.key))){const l={ok:!1,reason:"deny",retryAfter:Number.POSITIVE_INFINITY};if(e.throws)throw new d(l);return l}const a=e.count??1;if(!Number.isInteger(a)||a<=0)throw new n("INTERNAL",`rate limit "${t}": count must be a positive integer`);const m=o.shards??1,c=f(t,s,m),y=await this.store.get(c),{status:h,value:u}=N(w(o,m),y,{consume:i,count:a,now:this.now(),reserve:e.reserve??!1});if(u!==void 0&&await this.store.set(c,u),!h.ok&&e.throws)throw new d(h);return h}}export{R as RateLimiter};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
const p=()=>{const t=new Map;return{delete:e=>{t.delete(e)},get:e=>t.get(e),set:(e,s)=>{t.set(e,s)}}},u=(t,e,...s)=>t.exec.call(t,e,...s).toArray(),y=t=>{const{sql:e}=t,s=t.table??"_lunora_rate_limits";return u(e,`CREATE TABLE IF NOT EXISTS "${s}" (k TEXT PRIMARY KEY, value REAL NOT NULL, ts INTEGER NOT NULL, prev REAL)`),{delete:n=>{u(e,`DELETE FROM "${s}" WHERE k = ?`,n)},get:n=>{const l=u(e,`SELECT value, ts, prev FROM "${s}" WHERE k = ?`,n)[0];if(!l)return;const c={ts:l.ts,value:l.value};return l.prev!==null&&(c.prev=l.prev),c},set:(n,l)=>{u(e,`INSERT INTO "${s}" (k, value, ts, prev) VALUES (?, ?, ?, ?) ON CONFLICT(k) DO UPDATE SET value = excluded.value, ts = excluded.ts, prev = excluded.prev`,n,l.value,l.ts,l.prev??null)}}},E=t=>{const{db:e}=t,s=t.table??"rateLimits",n=t.index??"by_key",l=t.keyField??"key",c=new Map,o=async a=>{const r=await e.query(s).withIndex(n,i=>i.eq(l,a)).first();return c.set(a,r?r._id:void 0),r},v=async a=>(c.has(a)||await o(a),c.get(a));return{delete:async a=>{const r=await v(a);r!==void 0&&await e.delete(r),c.delete(a)},get:async a=>{const r=await o(a);if(!r)return;const i={ts:r.ts,value:r.value};return r.prev!==null&&r.prev!==void 0&&(i.prev=r.prev),i},set:async(a,r)=>{const i=await v(a),d={[l]:a,ts:r.ts,value:r.value};r.prev!==void 0&&(d.prev=r.prev),i===void 0?c.set(a,await e.insert(s,d)):await e.patch(i,d)}}},b=t=>{const e=n=>{throw new Error(`@lunora/ratelimit: \`${n}\` needs a writable \`ctx.db\`, but this store was created with \`createReadOnlyDbStore\` (a query context). Use \`createDbStore\` from a mutation or action; a query can only call \`getValue\`/\`check\`.`)},s=E({...t,db:{delete:()=>e("delete"),insert:()=>e("insert"),patch:()=>e("patch"),query:t.db.query.bind(t.db)}});return{delete:()=>e("reset"),get:s.get,set:()=>e("limit")}};export{E as createDbStore,p as createMemoryStore,b as createReadOnlyDbStore,y as createSqlStore};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{rateLimit as a}from"./rateLimit-DLcwK-84.mjs";import{RateLimiter as i}from"./RateLimiter-uPXzD0St.mjs";import{createDbStore as m}from"./createDbStore-CwJBMxDQ.mjs";const p=(t,o,r={})=>a(e=>new i({config:t,store:m({db:e.db,...r.store})}),o,r);export{p as default};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@lunora/ratelimit",
|
|
3
|
-
"version": "1.0.0-alpha.
|
|
3
|
+
"version": "1.0.0-alpha.15",
|
|
4
4
|
"description": "Rate limiting: token-bucket / fixed-window / sliding-window algorithms, deny list, sharding, pluggable stores, and procedure middleware",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"cloudflare",
|
|
@@ -46,7 +46,7 @@
|
|
|
46
46
|
"access": "public"
|
|
47
47
|
},
|
|
48
48
|
"dependencies": {
|
|
49
|
-
"@lunora/errors": "1.0.0-alpha.
|
|
49
|
+
"@lunora/errors": "1.0.0-alpha.12"
|
|
50
50
|
},
|
|
51
51
|
"engines": {
|
|
52
52
|
"node": "^22.15.0 || >=24.11.0"
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
const d=()=>{const a=new Map;return{delete:t=>{a.delete(t)},get:t=>a.get(t),set:(t,l)=>{a.set(t,l)}}},n=(a,t,...l)=>a.exec.call(a,t,...l).toArray(),p=a=>{const{sql:t}=a,l=a.table??"_lunora_rate_limits";return n(t,`CREATE TABLE IF NOT EXISTS "${l}" (k TEXT PRIMARY KEY, value REAL NOT NULL, ts INTEGER NOT NULL, prev REAL)`),{delete:u=>{n(t,`DELETE FROM "${l}" WHERE k = ?`,u)},get:u=>{const s=n(t,`SELECT value, ts, prev FROM "${l}" WHERE k = ?`,u)[0];if(!s)return;const v={ts:s.ts,value:s.value};return s.prev!==null&&(v.prev=s.prev),v},set:(u,s)=>{n(t,`INSERT INTO "${l}" (k, value, ts, prev) VALUES (?, ?, ?, ?) ON CONFLICT(k) DO UPDATE SET value = excluded.value, ts = excluded.ts, prev = excluded.prev`,u,s.value,s.ts,s.prev??null)}}},T=a=>{const{db:t}=a,l=a.table??"rateLimits",u=a.index??"by_key",s=a.keyField??"key",v=new Map,o=async r=>{const e=await t.query(l).withIndex(u,i=>i.eq(s,r)).first();return v.set(r,e?e._id:void 0),e},E=async r=>(v.has(r)||await o(r),v.get(r));return{delete:async r=>{const e=await E(r);e!==void 0&&await t.delete(e),v.delete(r)},get:async r=>{const e=await o(r);if(!e)return;const i={ts:e.ts,value:e.value};return e.prev!==null&&e.prev!==void 0&&(i.prev=e.prev),i},set:async(r,e)=>{const i=await E(r),c={[s]:r,ts:e.ts,value:e.value};e.prev!==void 0&&(c.prev=e.prev),i===void 0?v.set(r,await t.insert(l,c)):await t.patch(i,c)}}};export{T as createDbStore,d as createMemoryStore,p as createSqlStore};
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
import{rateLimit as a}from"./rateLimit-DLcwK-84.mjs";import{RateLimiter as i}from"./RateLimiter-BcVZuxFA.mjs";import{createDbStore as m}from"./createDbStore-VpnhCmRx.mjs";const b=(t,o,r={})=>a(e=>new i({config:t,store:m({db:e.db,...r.store})}),o,r);export{b as default};
|