@thangnv-dev/rate-limiter-mikroorm-node 0.0.1

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.
@@ -0,0 +1,8 @@
1
+ import { StandardError } from '@thangnv-dev/error-common';
2
+ export declare class RateLimiterQueryError extends StandardError {
3
+ constructor(operation: string, cause?: unknown);
4
+ }
5
+ export declare class RateLimiterInvalidResultError extends StandardError {
6
+ constructor(field: string, cause?: unknown);
7
+ }
8
+ //# sourceMappingURL=errors.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"errors.d.ts","sourceRoot":"","sources":["../src/errors.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,MAAM,2BAA2B,CAAA;AAIzD,qBAAa,qBAAsB,SAAQ,aAAa;gBAC1C,SAAS,EAAE,MAAM,EAAE,KAAK,CAAC,EAAE,OAAO;CAS/C;AAED,qBAAa,6BAA8B,SAAQ,aAAa;gBAClD,KAAK,EAAE,MAAM,EAAE,KAAK,CAAC,EAAE,OAAO;CAS3C"}
package/dist/errors.js ADDED
@@ -0,0 +1,25 @@
1
+ import { StandardError } from '@thangnv-dev/error-common';
2
+ const RATE_LIMITER_IMPL_PACKAGE = '@thangnv-dev/rate-limiter-mikroorm-node';
3
+ export class RateLimiterQueryError extends StandardError {
4
+ constructor(operation, cause) {
5
+ super({
6
+ package: RATE_LIMITER_IMPL_PACKAGE,
7
+ code: 'RATE_LIMITER_QUERY_FAILED',
8
+ cause,
9
+ message: `${operation} query failed`,
10
+ });
11
+ this.name = 'RateLimiterQueryError';
12
+ }
13
+ }
14
+ export class RateLimiterInvalidResultError extends StandardError {
15
+ constructor(field, cause) {
16
+ super({
17
+ package: RATE_LIMITER_IMPL_PACKAGE,
18
+ code: 'RATE_LIMITER_INVALID_RESULT',
19
+ cause,
20
+ message: `invalid rate-limiter result field: ${field}`,
21
+ });
22
+ this.name = 'RateLimiterInvalidResultError';
23
+ }
24
+ }
25
+ //# sourceMappingURL=errors.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"errors.js","sourceRoot":"","sources":["../src/errors.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,MAAM,2BAA2B,CAAA;AAEzD,MAAM,yBAAyB,GAAG,yCAAyC,CAAA;AAE3E,MAAM,OAAO,qBAAsB,SAAQ,aAAa;IACtD,YAAY,SAAiB,EAAE,KAAe;QAC5C,KAAK,CAAC;YACJ,OAAO,EAAE,yBAAyB;YAClC,IAAI,EAAE,2BAA2B;YACjC,KAAK;YACL,OAAO,EAAE,GAAG,SAAS,eAAe;SACrC,CAAC,CAAA;QACF,IAAI,CAAC,IAAI,GAAG,uBAAuB,CAAA;IACrC,CAAC;CACF;AAED,MAAM,OAAO,6BAA8B,SAAQ,aAAa;IAC9D,YAAY,KAAa,EAAE,KAAe;QACxC,KAAK,CAAC;YACJ,OAAO,EAAE,yBAAyB;YAClC,IAAI,EAAE,6BAA6B;YACnC,KAAK;YACL,OAAO,EAAE,sCAAsC,KAAK,EAAE;SACvD,CAAC,CAAA;QACF,IAAI,CAAC,IAAI,GAAG,+BAA+B,CAAA;IAC7C,CAAC;CACF"}
@@ -0,0 +1,4 @@
1
+ export { RateLimiterInvalidResultError, RateLimiterQueryError } from './errors.js';
2
+ export { KnexRateLimiter } from './rate-limiter.js';
3
+ export { Migration20260221143000RateLimiter } from './migrations/migration-20260221143000-rate-limiter.js';
4
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,6BAA6B,EAAE,qBAAqB,EAAE,MAAM,aAAa,CAAA;AAClF,OAAO,EAAE,eAAe,EAAE,MAAM,mBAAmB,CAAA;AACnD,OAAO,EAAE,kCAAkC,EAAE,MAAM,uDAAuD,CAAA"}
package/dist/index.js ADDED
@@ -0,0 +1,4 @@
1
+ export { RateLimiterInvalidResultError, RateLimiterQueryError } from './errors.js';
2
+ export { KnexRateLimiter } from './rate-limiter.js';
3
+ export { Migration20260221143000RateLimiter } from './migrations/migration-20260221143000-rate-limiter.js';
4
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,6BAA6B,EAAE,qBAAqB,EAAE,MAAM,aAAa,CAAA;AAClF,OAAO,EAAE,eAAe,EAAE,MAAM,mBAAmB,CAAA;AACnD,OAAO,EAAE,kCAAkC,EAAE,MAAM,uDAAuD,CAAA"}
@@ -0,0 +1,6 @@
1
+ import { Migration } from '@mikro-orm/migrations';
2
+ export declare class Migration20260221143000RateLimiter extends Migration {
3
+ up(): Promise<void>;
4
+ down(): Promise<void>;
5
+ }
6
+ //# sourceMappingURL=migration-20260221143000-rate-limiter.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"migration-20260221143000-rate-limiter.d.ts","sourceRoot":"","sources":["../../src/migrations/migration-20260221143000-rate-limiter.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,uBAAuB,CAAA;AAEjD,qBAAa,kCAAmC,SAAQ,SAAS;IAChD,EAAE,IAAI,OAAO,CAAC,IAAI,CAAC;IAmInB,IAAI,IAAI,OAAO,CAAC,IAAI,CAAC;CAQrC"}
@@ -0,0 +1,137 @@
1
+ import { Migration } from '@mikro-orm/migrations';
2
+ export class Migration20260221143000RateLimiter extends Migration {
3
+ async up() {
4
+ this.addSql('create schema if not exists rate_limiter;');
5
+ this.addSql(`
6
+ create table if not exists rate_limiter.buckets (
7
+ bucket_key text primary key,
8
+ capacity bigint not null check (capacity > 0),
9
+ refill_tokens bigint not null check (refill_tokens > 0),
10
+ refill_interval_ms bigint not null check (refill_interval_ms > 0),
11
+ tokens numeric not null check (tokens >= 0),
12
+ updated_at timestamptz not null default clock_timestamp(),
13
+ created_at timestamptz not null default clock_timestamp()
14
+ );
15
+ `);
16
+ this.addSql(`
17
+ create or replace function rate_limiter.take_tokens(
18
+ p_bucket_key varchar,
19
+ p_capacity bigint,
20
+ p_refill_tokens bigint,
21
+ p_refill_interval_ms bigint,
22
+ p_tokens bigint default 1
23
+ )
24
+ returns table (
25
+ allowed boolean,
26
+ remaining bigint,
27
+ retry_after_ms bigint,
28
+ rate_limit bigint
29
+ )
30
+ language plpgsql
31
+ as $$
32
+ declare
33
+ current_bucket rate_limiter.buckets%rowtype;
34
+ now_ts timestamptz := clock_timestamp();
35
+ elapsed_ms numeric;
36
+ refill_amount numeric;
37
+ refilled_tokens numeric;
38
+ requested_tokens numeric := p_tokens::numeric;
39
+ remaining_tokens numeric;
40
+ is_allowed boolean;
41
+ retry_after bigint;
42
+ begin
43
+ if p_bucket_key is null or btrim(p_bucket_key) = '' then
44
+ raise exception 'bucket_key must not be empty';
45
+ end if;
46
+ if p_capacity <= 0 then
47
+ raise exception 'capacity must be greater than 0';
48
+ end if;
49
+ if p_refill_tokens <= 0 then
50
+ raise exception 'refill_tokens must be greater than 0';
51
+ end if;
52
+ if p_refill_interval_ms <= 0 then
53
+ raise exception 'refill_interval_ms must be greater than 0';
54
+ end if;
55
+ if p_tokens <= 0 then
56
+ raise exception 'tokens must be greater than 0';
57
+ end if;
58
+
59
+ insert into rate_limiter.buckets (
60
+ bucket_key,
61
+ capacity,
62
+ refill_tokens,
63
+ refill_interval_ms,
64
+ tokens,
65
+ updated_at,
66
+ created_at
67
+ )
68
+ values (
69
+ p_bucket_key,
70
+ p_capacity,
71
+ p_refill_tokens,
72
+ p_refill_interval_ms,
73
+ p_capacity::numeric,
74
+ now_ts,
75
+ now_ts
76
+ )
77
+ on conflict (bucket_key)
78
+ do update set
79
+ capacity = excluded.capacity,
80
+ refill_tokens = excluded.refill_tokens,
81
+ refill_interval_ms = excluded.refill_interval_ms
82
+ returning * into current_bucket;
83
+
84
+ elapsed_ms := greatest(0, extract(epoch from (now_ts - current_bucket.updated_at)) * 1000);
85
+ refill_amount := (elapsed_ms * current_bucket.refill_tokens::numeric) / current_bucket.refill_interval_ms::numeric;
86
+ refilled_tokens := least(current_bucket.capacity::numeric, current_bucket.tokens + refill_amount);
87
+
88
+ if refilled_tokens >= requested_tokens then
89
+ is_allowed := true;
90
+ remaining_tokens := greatest(0, refilled_tokens - requested_tokens);
91
+ retry_after := 0;
92
+ else
93
+ is_allowed := false;
94
+ remaining_tokens := greatest(0, refilled_tokens);
95
+ retry_after := ceil(
96
+ ((requested_tokens - refilled_tokens) * current_bucket.refill_interval_ms::numeric)
97
+ / current_bucket.refill_tokens::numeric
98
+ )::bigint;
99
+ end if;
100
+
101
+ update rate_limiter.buckets
102
+ set
103
+ tokens = remaining_tokens,
104
+ updated_at = now_ts,
105
+ capacity = p_capacity,
106
+ refill_tokens = p_refill_tokens,
107
+ refill_interval_ms = p_refill_interval_ms
108
+ where bucket_key = p_bucket_key;
109
+
110
+ return query
111
+ select
112
+ is_allowed,
113
+ floor(remaining_tokens)::bigint,
114
+ retry_after,
115
+ p_capacity;
116
+ end;
117
+ $$;
118
+ `);
119
+ this.addSql(`
120
+ create or replace function rate_limiter.reset_bucket(
121
+ p_bucket_key varchar
122
+ )
123
+ returns void
124
+ language sql
125
+ as $$
126
+ delete from rate_limiter.buckets where bucket_key = p_bucket_key;
127
+ $$;
128
+ `);
129
+ }
130
+ async down() {
131
+ this.addSql('drop function if exists rate_limiter.reset_bucket(varchar);');
132
+ this.addSql('drop function if exists rate_limiter.take_tokens(varchar, bigint, bigint, bigint, bigint);');
133
+ this.addSql('drop table if exists rate_limiter.buckets;');
134
+ this.addSql('drop schema if exists rate_limiter;');
135
+ }
136
+ }
137
+ //# sourceMappingURL=migration-20260221143000-rate-limiter.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"migration-20260221143000-rate-limiter.js","sourceRoot":"","sources":["../../src/migrations/migration-20260221143000-rate-limiter.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,uBAAuB,CAAA;AAEjD,MAAM,OAAO,kCAAmC,SAAQ,SAAS;IACtD,KAAK,CAAC,EAAE;QACf,IAAI,CAAC,MAAM,CAAC,2CAA2C,CAAC,CAAA;QAExD,IAAI,CAAC,MAAM,CAAC;;;;;;;;;;KAUX,CAAC,CAAA;QAEF,IAAI,CAAC,MAAM,CAAC;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;KAsGX,CAAC,CAAA;QAEF,IAAI,CAAC,MAAM,CAAC;;;;;;;;;KASX,CAAC,CAAA;IACJ,CAAC;IAEQ,KAAK,CAAC,IAAI;QACjB,IAAI,CAAC,MAAM,CAAC,6DAA6D,CAAC,CAAA;QAC1E,IAAI,CAAC,MAAM,CACT,4FAA4F,CAC7F,CAAA;QACD,IAAI,CAAC,MAAM,CAAC,4CAA4C,CAAC,CAAA;QACzD,IAAI,CAAC,MAAM,CAAC,qCAAqC,CAAC,CAAA;IACpD,CAAC;CACF"}
@@ -0,0 +1,11 @@
1
+ import 'temporal-polyfill/global';
2
+ import { type RateLimiter, type RateLimiterTakeInput, type RateLimiterTakeResult } from '@thangnv-dev/rate-limiter-node';
3
+ import type { SqlEntityManager } from '@mikro-orm/knex';
4
+ export declare class KnexRateLimiter implements RateLimiter {
5
+ private readonly em;
6
+ constructor(em: SqlEntityManager);
7
+ take(input: RateLimiterTakeInput): Promise<RateLimiterTakeResult>;
8
+ reset(key: string): Promise<void>;
9
+ private queryRows;
10
+ }
11
+ //# sourceMappingURL=rate-limiter.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"rate-limiter.d.ts","sourceRoot":"","sources":["../src/rate-limiter.ts"],"names":[],"mappings":"AAAA,OAAO,0BAA0B,CAAA;AACjC,OAAO,EAEL,KAAK,WAAW,EAChB,KAAK,oBAAoB,EACzB,KAAK,qBAAqB,EAC3B,MAAM,gCAAgC,CAAA;AACvC,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,iBAAiB,CAAA;AAoJvD,qBAAa,eAAgB,YAAW,WAAW;IACjD,OAAO,CAAC,QAAQ,CAAC,EAAE,CAAkB;gBAEzB,EAAE,EAAE,gBAAgB;IAI1B,IAAI,CAAC,KAAK,EAAE,oBAAoB,GAAG,OAAO,CAAC,qBAAqB,CAAC;IA+CjE,KAAK,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;YAKzB,SAAS;CAYxB"}
@@ -0,0 +1,172 @@
1
+ import 'temporal-polyfill/global';
2
+ import { RATE_LIMITER_DEFAULT_TOKENS, } from '@thangnv-dev/rate-limiter-node';
3
+ import { RateLimiterInvalidResultError, RateLimiterQueryError } from './errors.js';
4
+ function isRecord(value) {
5
+ return typeof value === 'object' && value !== null;
6
+ }
7
+ function readField(record, keys) {
8
+ for (const key of keys) {
9
+ if (Object.prototype.hasOwnProperty.call(record, key)) {
10
+ return record[key];
11
+ }
12
+ }
13
+ return undefined;
14
+ }
15
+ function requireNonEmptyString(fieldName, value) {
16
+ if (typeof value !== 'string') {
17
+ throw new TypeError(`${fieldName} must be a string`);
18
+ }
19
+ const trimmed = value.trim();
20
+ if (!trimmed) {
21
+ throw new TypeError(`${fieldName} must not be empty`);
22
+ }
23
+ return trimmed;
24
+ }
25
+ function requirePositiveBigInt(fieldName, value) {
26
+ if (typeof value !== 'bigint') {
27
+ throw new TypeError(`${fieldName} must be a bigint`);
28
+ }
29
+ if (value <= 0n) {
30
+ throw new TypeError(`${fieldName} must be greater than 0`);
31
+ }
32
+ return value;
33
+ }
34
+ function durationToPositiveMillisecondBigInt(fieldName, value) {
35
+ if (!(value instanceof Temporal.Duration)) {
36
+ throw new TypeError(`${fieldName} must be a Temporal.Duration`);
37
+ }
38
+ let milliseconds;
39
+ try {
40
+ milliseconds = value.total({ unit: 'millisecond' });
41
+ }
42
+ catch (cause) {
43
+ throw new TypeError(`${fieldName} must use fixed-length time units`, { cause });
44
+ }
45
+ if (!Number.isFinite(milliseconds)) {
46
+ throw new TypeError(`${fieldName} must be finite`);
47
+ }
48
+ if (milliseconds <= 0) {
49
+ throw new TypeError(`${fieldName} must be greater than 0`);
50
+ }
51
+ return BigInt(Math.ceil(milliseconds));
52
+ }
53
+ function toDurationFromMilliseconds(value) {
54
+ if (value < 0n) {
55
+ throw new RateLimiterInvalidResultError('retry_after_ms');
56
+ }
57
+ if (value > BigInt(Number.MAX_SAFE_INTEGER)) {
58
+ throw new RateLimiterInvalidResultError('retry_after_ms');
59
+ }
60
+ return Temporal.Duration.from({ milliseconds: Number(value) });
61
+ }
62
+ function toPgBigInt(value) {
63
+ return value.toString();
64
+ }
65
+ function parseBooleanField(fieldName, value) {
66
+ if (typeof value === 'boolean') {
67
+ return value;
68
+ }
69
+ if (typeof value === 'string') {
70
+ const normalized = value.trim().toLowerCase();
71
+ if (normalized === 'true' || normalized === 't' || normalized === '1') {
72
+ return true;
73
+ }
74
+ if (normalized === 'false' || normalized === 'f' || normalized === '0') {
75
+ return false;
76
+ }
77
+ }
78
+ if (typeof value === 'number') {
79
+ if (value === 1) {
80
+ return true;
81
+ }
82
+ if (value === 0) {
83
+ return false;
84
+ }
85
+ }
86
+ throw new RateLimiterInvalidResultError(fieldName);
87
+ }
88
+ function parseBigIntField(fieldName, value) {
89
+ if (typeof value === 'bigint') {
90
+ return value;
91
+ }
92
+ if (typeof value === 'string') {
93
+ try {
94
+ return BigInt(value);
95
+ }
96
+ catch (cause) {
97
+ throw new RateLimiterInvalidResultError(fieldName, cause);
98
+ }
99
+ }
100
+ if (typeof value === 'number' && Number.isInteger(value)) {
101
+ return BigInt(value);
102
+ }
103
+ throw new RateLimiterInvalidResultError(fieldName);
104
+ }
105
+ function extractRows(rawResult) {
106
+ if (isRecord(rawResult)) {
107
+ const rows = rawResult.rows;
108
+ if (Array.isArray(rows)) {
109
+ return rows;
110
+ }
111
+ }
112
+ if (Array.isArray(rawResult)) {
113
+ if (rawResult.length === 0 || !Array.isArray(rawResult[0])) {
114
+ return rawResult;
115
+ }
116
+ const [rows] = rawResult;
117
+ if (Array.isArray(rows)) {
118
+ return rows;
119
+ }
120
+ }
121
+ return [];
122
+ }
123
+ export class KnexRateLimiter {
124
+ em;
125
+ constructor(em) {
126
+ this.em = em;
127
+ }
128
+ async take(input) {
129
+ const key = requireNonEmptyString('key', input.key);
130
+ const capacity = requirePositiveBigInt('capacity', input.capacity);
131
+ const refillTokens = input.refillTokens == null
132
+ ? capacity
133
+ : requirePositiveBigInt('refillTokens', input.refillTokens);
134
+ const refillIntervalMs = durationToPositiveMillisecondBigInt('refillInterval', input.refillInterval);
135
+ const tokens = input.tokens == null ? RATE_LIMITER_DEFAULT_TOKENS : requirePositiveBigInt('tokens', input.tokens);
136
+ const rows = await this.queryRows('select * from rate_limiter.take_tokens(?, ?::bigint, ?::bigint, ?::bigint, ?::bigint)', [
137
+ key,
138
+ toPgBigInt(capacity),
139
+ toPgBigInt(refillTokens),
140
+ toPgBigInt(refillIntervalMs),
141
+ toPgBigInt(tokens),
142
+ ], 'take');
143
+ const row = rows[0];
144
+ if (!isRecord(row)) {
145
+ throw new RateLimiterInvalidResultError('row');
146
+ }
147
+ const allowed = parseBooleanField('allowed', readField(row, ['allowed']));
148
+ const remaining = parseBigIntField('remaining', readField(row, ['remaining']));
149
+ const retryAfterMs = parseBigIntField('retry_after_ms', readField(row, ['retry_after_ms', 'retryAfterMs']));
150
+ const limit = parseBigIntField('rate_limit', readField(row, ['rate_limit', 'rateLimit', 'limit']));
151
+ return {
152
+ allowed,
153
+ remaining,
154
+ limit,
155
+ retryAfter: toDurationFromMilliseconds(retryAfterMs),
156
+ };
157
+ }
158
+ async reset(key) {
159
+ const normalizedKey = requireNonEmptyString('key', key);
160
+ await this.queryRows('select rate_limiter.reset_bucket(?) as reset_bucket', [normalizedKey], 'reset');
161
+ }
162
+ async queryRows(sql, params, operation) {
163
+ try {
164
+ const rawResult = await this.em.execute(sql, params, 'all');
165
+ return extractRows(rawResult);
166
+ }
167
+ catch (cause) {
168
+ throw new RateLimiterQueryError(operation, cause);
169
+ }
170
+ }
171
+ }
172
+ //# sourceMappingURL=rate-limiter.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"rate-limiter.js","sourceRoot":"","sources":["../src/rate-limiter.ts"],"names":[],"mappings":"AAAA,OAAO,0BAA0B,CAAA;AACjC,OAAO,EACL,2BAA2B,GAI5B,MAAM,gCAAgC,CAAA;AAEvC,OAAO,EAAE,6BAA6B,EAAE,qBAAqB,EAAE,MAAM,aAAa,CAAA;AAYlF,SAAS,QAAQ,CAAC,KAAc;IAC9B,OAAO,OAAO,KAAK,KAAK,QAAQ,IAAI,KAAK,KAAK,IAAI,CAAA;AACpD,CAAC;AAED,SAAS,SAAS,CAAC,MAA+B,EAAE,IAAuB;IACzE,KAAK,MAAM,GAAG,IAAI,IAAI,EAAE,CAAC;QACvB,IAAI,MAAM,CAAC,SAAS,CAAC,cAAc,CAAC,IAAI,CAAC,MAAM,EAAE,GAAG,CAAC,EAAE,CAAC;YACtD,OAAO,MAAM,CAAC,GAAG,CAAC,CAAA;QACpB,CAAC;IACH,CAAC;IACD,OAAO,SAAS,CAAA;AAClB,CAAC;AAED,SAAS,qBAAqB,CAAC,SAAiB,EAAE,KAAc;IAC9D,IAAI,OAAO,KAAK,KAAK,QAAQ,EAAE,CAAC;QAC9B,MAAM,IAAI,SAAS,CAAC,GAAG,SAAS,mBAAmB,CAAC,CAAA;IACtD,CAAC;IAED,MAAM,OAAO,GAAG,KAAK,CAAC,IAAI,EAAE,CAAA;IAC5B,IAAI,CAAC,OAAO,EAAE,CAAC;QACb,MAAM,IAAI,SAAS,CAAC,GAAG,SAAS,oBAAoB,CAAC,CAAA;IACvD,CAAC;IAED,OAAO,OAAO,CAAA;AAChB,CAAC;AAED,SAAS,qBAAqB,CAAC,SAAiB,EAAE,KAAc;IAC9D,IAAI,OAAO,KAAK,KAAK,QAAQ,EAAE,CAAC;QAC9B,MAAM,IAAI,SAAS,CAAC,GAAG,SAAS,mBAAmB,CAAC,CAAA;IACtD,CAAC;IACD,IAAI,KAAK,IAAI,EAAE,EAAE,CAAC;QAChB,MAAM,IAAI,SAAS,CAAC,GAAG,SAAS,yBAAyB,CAAC,CAAA;IAC5D,CAAC;IACD,OAAO,KAAK,CAAA;AACd,CAAC;AAED,SAAS,mCAAmC,CAAC,SAAiB,EAAE,KAAc;IAC5E,IAAI,CAAC,CAAC,KAAK,YAAY,QAAQ,CAAC,QAAQ,CAAC,EAAE,CAAC;QAC1C,MAAM,IAAI,SAAS,CAAC,GAAG,SAAS,8BAA8B,CAAC,CAAA;IACjE,CAAC;IAED,IAAI,YAAoB,CAAA;IACxB,IAAI,CAAC;QACH,YAAY,GAAG,KAAK,CAAC,KAAK,CAAC,EAAE,IAAI,EAAE,aAAa,EAAE,CAAC,CAAA;IACrD,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,MAAM,IAAI,SAAS,CAAC,GAAG,SAAS,mCAAmC,EAAE,EAAE,KAAK,EAAE,CAAC,CAAA;IACjF,CAAC;IAED,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,YAAY,CAAC,EAAE,CAAC;QACnC,MAAM,IAAI,SAAS,CAAC,GAAG,SAAS,iBAAiB,CAAC,CAAA;IACpD,CAAC;IACD,IAAI,YAAY,IAAI,CAAC,EAAE,CAAC;QACtB,MAAM,IAAI,SAAS,CAAC,GAAG,SAAS,yBAAyB,CAAC,CAAA;IAC5D,CAAC;IAED,OAAO,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,YAAY,CAAC,CAAC,CAAA;AACxC,CAAC;AAED,SAAS,0BAA0B,CAAC,KAAa;IAC/C,IAAI,KAAK,GAAG,EAAE,EAAE,CAAC;QACf,MAAM,IAAI,6BAA6B,CAAC,gBAAgB,CAAC,CAAA;IAC3D,CAAC;IACD,IAAI,KAAK,GAAG,MAAM,CAAC,MAAM,CAAC,gBAAgB,CAAC,EAAE,CAAC;QAC5C,MAAM,IAAI,6BAA6B,CAAC,gBAAgB,CAAC,CAAA;IAC3D,CAAC;IACD,OAAO,QAAQ,CAAC,QAAQ,CAAC,IAAI,CAAC,EAAE,YAAY,EAAE,MAAM,CAAC,KAAK,CAAC,EAAE,CAAC,CAAA;AAChE,CAAC;AAED,SAAS,UAAU,CAAC,KAAa;IAC/B,OAAO,KAAK,CAAC,QAAQ,EAAE,CAAA;AACzB,CAAC;AAED,SAAS,iBAAiB,CAAC,SAAiB,EAAE,KAAc;IAC1D,IAAI,OAAO,KAAK,KAAK,SAAS,EAAE,CAAC;QAC/B,OAAO,KAAK,CAAA;IACd,CAAC;IACD,IAAI,OAAO,KAAK,KAAK,QAAQ,EAAE,CAAC;QAC9B,MAAM,UAAU,GAAG,KAAK,CAAC,IAAI,EAAE,CAAC,WAAW,EAAE,CAAA;QAC7C,IAAI,UAAU,KAAK,MAAM,IAAI,UAAU,KAAK,GAAG,IAAI,UAAU,KAAK,GAAG,EAAE,CAAC;YACtE,OAAO,IAAI,CAAA;QACb,CAAC;QACD,IAAI,UAAU,KAAK,OAAO,IAAI,UAAU,KAAK,GAAG,IAAI,UAAU,KAAK,GAAG,EAAE,CAAC;YACvE,OAAO,KAAK,CAAA;QACd,CAAC;IACH,CAAC;IACD,IAAI,OAAO,KAAK,KAAK,QAAQ,EAAE,CAAC;QAC9B,IAAI,KAAK,KAAK,CAAC,EAAE,CAAC;YAChB,OAAO,IAAI,CAAA;QACb,CAAC;QACD,IAAI,KAAK,KAAK,CAAC,EAAE,CAAC;YAChB,OAAO,KAAK,CAAA;QACd,CAAC;IACH,CAAC;IACD,MAAM,IAAI,6BAA6B,CAAC,SAAS,CAAC,CAAA;AACpD,CAAC;AAED,SAAS,gBAAgB,CAAC,SAAiB,EAAE,KAAc;IACzD,IAAI,OAAO,KAAK,KAAK,QAAQ,EAAE,CAAC;QAC9B,OAAO,KAAK,CAAA;IACd,CAAC;IACD,IAAI,OAAO,KAAK,KAAK,QAAQ,EAAE,CAAC;QAC9B,IAAI,CAAC;YACH,OAAO,MAAM,CAAC,KAAK,CAAC,CAAA;QACtB,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,MAAM,IAAI,6BAA6B,CAAC,SAAS,EAAE,KAAK,CAAC,CAAA;QAC3D,CAAC;IACH,CAAC;IACD,IAAI,OAAO,KAAK,KAAK,QAAQ,IAAI,MAAM,CAAC,SAAS,CAAC,KAAK,CAAC,EAAE,CAAC;QACzD,OAAO,MAAM,CAAC,KAAK,CAAC,CAAA;IACtB,CAAC;IACD,MAAM,IAAI,6BAA6B,CAAC,SAAS,CAAC,CAAA;AACpD,CAAC;AAED,SAAS,WAAW,CAAO,SAAkB;IAC3C,IAAI,QAAQ,CAAC,SAAS,CAAC,EAAE,CAAC;QACxB,MAAM,IAAI,GAAG,SAAS,CAAC,IAAI,CAAA;QAC3B,IAAI,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC,EAAE,CAAC;YACxB,OAAO,IAAc,CAAA;QACvB,CAAC;IACH,CAAC;IAED,IAAI,KAAK,CAAC,OAAO,CAAC,SAAS,CAAC,EAAE,CAAC;QAC7B,IAAI,SAAS,CAAC,MAAM,KAAK,CAAC,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC;YAC3D,OAAO,SAAmB,CAAA;QAC5B,CAAC;QAED,MAAM,CAAC,IAAI,CAAC,GAAG,SAAS,CAAA;QACxB,IAAI,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC,EAAE,CAAC;YACxB,OAAO,IAAc,CAAA;QACvB,CAAC;IACH,CAAC;IAED,OAAO,EAAE,CAAA;AACX,CAAC;AAED,MAAM,OAAO,eAAe;IACT,EAAE,CAAkB;IAErC,YAAY,EAAoB;QAC9B,IAAI,CAAC,EAAE,GAAG,EAAE,CAAA;IACd,CAAC;IAED,KAAK,CAAC,IAAI,CAAC,KAA2B;QACpC,MAAM,GAAG,GAAG,qBAAqB,CAAC,KAAK,EAAE,KAAK,CAAC,GAAG,CAAC,CAAA;QACnD,MAAM,QAAQ,GAAG,qBAAqB,CAAC,UAAU,EAAE,KAAK,CAAC,QAAQ,CAAC,CAAA;QAClE,MAAM,YAAY,GAChB,KAAK,CAAC,YAAY,IAAI,IAAI;YACxB,CAAC,CAAC,QAAQ;YACV,CAAC,CAAC,qBAAqB,CAAC,cAAc,EAAE,KAAK,CAAC,YAAY,CAAC,CAAA;QAC/D,MAAM,gBAAgB,GAAG,mCAAmC,CAC1D,gBAAgB,EAChB,KAAK,CAAC,cAAc,CACrB,CAAA;QACD,MAAM,MAAM,GACV,KAAK,CAAC,MAAM,IAAI,IAAI,CAAC,CAAC,CAAC,2BAA2B,CAAC,CAAC,CAAC,qBAAqB,CAAC,QAAQ,EAAE,KAAK,CAAC,MAAM,CAAC,CAAA;QAEpG,MAAM,IAAI,GAAG,MAAM,IAAI,CAAC,SAAS,CAC/B,uFAAuF,EACvF;YACE,GAAG;YACH,UAAU,CAAC,QAAQ,CAAC;YACpB,UAAU,CAAC,YAAY,CAAC;YACxB,UAAU,CAAC,gBAAgB,CAAC;YAC5B,UAAU,CAAC,MAAM,CAAC;SACnB,EACD,MAAM,CACP,CAAA;QAED,MAAM,GAAG,GAAG,IAAI,CAAC,CAAC,CAAC,CAAA;QACnB,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,EAAE,CAAC;YACnB,MAAM,IAAI,6BAA6B,CAAC,KAAK,CAAC,CAAA;QAChD,CAAC;QAED,MAAM,OAAO,GAAG,iBAAiB,CAAC,SAAS,EAAE,SAAS,CAAC,GAAG,EAAE,CAAC,SAAS,CAAC,CAAC,CAAC,CAAA;QACzE,MAAM,SAAS,GAAG,gBAAgB,CAAC,WAAW,EAAE,SAAS,CAAC,GAAG,EAAE,CAAC,WAAW,CAAC,CAAC,CAAC,CAAA;QAC9E,MAAM,YAAY,GAAG,gBAAgB,CACnC,gBAAgB,EAChB,SAAS,CAAC,GAAG,EAAE,CAAC,gBAAgB,EAAE,cAAc,CAAC,CAAC,CACnD,CAAA;QACD,MAAM,KAAK,GAAG,gBAAgB,CAAC,YAAY,EAAE,SAAS,CAAC,GAAG,EAAE,CAAC,YAAY,EAAE,WAAW,EAAE,OAAO,CAAC,CAAC,CAAC,CAAA;QAElG,OAAO;YACL,OAAO;YACP,SAAS;YACT,KAAK;YACL,UAAU,EAAE,0BAA0B,CAAC,YAAY,CAAC;SACrD,CAAA;IACH,CAAC;IAED,KAAK,CAAC,KAAK,CAAC,GAAW;QACrB,MAAM,aAAa,GAAG,qBAAqB,CAAC,KAAK,EAAE,GAAG,CAAC,CAAA;QACvD,MAAM,IAAI,CAAC,SAAS,CAAC,qDAAqD,EAAE,CAAC,aAAa,CAAC,EAAE,OAAO,CAAC,CAAA;IACvG,CAAC;IAEO,KAAK,CAAC,SAAS,CACrB,GAAW,EACX,MAAiB,EACjB,SAAiB;QAEjB,IAAI,CAAC;YACH,MAAM,SAAS,GAAG,MAAM,IAAI,CAAC,EAAE,CAAC,OAAO,CAAC,GAAG,EAAE,MAAM,EAAE,KAAK,CAAC,CAAA;YAC3D,OAAO,WAAW,CAAO,SAAS,CAAC,CAAA;QACrC,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,MAAM,IAAI,qBAAqB,CAAC,SAAS,EAAE,KAAK,CAAC,CAAA;QACnD,CAAC;IACH,CAAC;CACF"}
package/package.json ADDED
@@ -0,0 +1,49 @@
1
+ {
2
+ "name": "@thangnv-dev/rate-limiter-mikroorm-node",
3
+ "version": "0.0.1",
4
+ "private": false,
5
+ "publishConfig": {
6
+ "access": "public"
7
+ },
8
+ "type": "module",
9
+ "main": "./dist/index.js",
10
+ "types": "./dist/index.d.ts",
11
+ "exports": {
12
+ ".": {
13
+ "types": "./dist/index.d.ts",
14
+ "default": "./dist/index.js"
15
+ }
16
+ },
17
+ "files": [
18
+ "dist"
19
+ ],
20
+ "scripts": {
21
+ "build": "tsc -p tsconfig.build.json",
22
+ "lint": "eslint .",
23
+ "typecheck": "tsc --noEmit",
24
+ "test": "vitest run"
25
+ },
26
+ "dependencies": {
27
+ "@thangnv-dev/error-common": "workspace:^",
28
+ "@thangnv-dev/rate-limiter-node": "workspace:^"
29
+ },
30
+ "devDependencies": {
31
+ "@mikro-orm/core": "^6.6.7",
32
+ "@mikro-orm/knex": "^6.6.7",
33
+ "@mikro-orm/migrations": "^6.6.7",
34
+ "@mikro-orm/postgresql": "^6.6.7",
35
+ "@thangnv-dev/mikroorm-nest": "workspace:^",
36
+ "@typescript-eslint/eslint-plugin": "^8.56.0",
37
+ "@typescript-eslint/parser": "^8.56.0",
38
+ "eslint": "^10.0.0",
39
+ "pg": "^8.18.0",
40
+ "temporal-polyfill": "^0.3.0",
41
+ "typescript": "^5.9.3",
42
+ "vitest": "^4.0.18"
43
+ },
44
+ "peerDependencies": {
45
+ "@mikro-orm/knex": "^6.6.6",
46
+ "@mikro-orm/migrations": "^6.6.6",
47
+ "temporal-polyfill": "*"
48
+ }
49
+ }