@sudobility/ratelimit_service 1.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.
Files changed (67) hide show
  1. package/CLAUDE.md +160 -0
  2. package/dist/helpers/EntitlementHelper.cjs +75 -0
  3. package/dist/helpers/EntitlementHelper.d.ts +52 -0
  4. package/dist/helpers/EntitlementHelper.d.ts.map +1 -0
  5. package/dist/helpers/EntitlementHelper.js +75 -0
  6. package/dist/helpers/EntitlementHelper.js.map +1 -0
  7. package/dist/helpers/RateLimitChecker.cjs +264 -0
  8. package/dist/helpers/RateLimitChecker.d.ts +90 -0
  9. package/dist/helpers/RateLimitChecker.d.ts.map +1 -0
  10. package/dist/helpers/RateLimitChecker.js +264 -0
  11. package/dist/helpers/RateLimitChecker.js.map +1 -0
  12. package/dist/helpers/RateLimitRouteHandler.cjs +191 -0
  13. package/dist/helpers/RateLimitRouteHandler.d.ts +70 -0
  14. package/dist/helpers/RateLimitRouteHandler.d.ts.map +1 -0
  15. package/dist/helpers/RateLimitRouteHandler.js +191 -0
  16. package/dist/helpers/RateLimitRouteHandler.js.map +1 -0
  17. package/dist/helpers/RevenueCatHelper.cjs +96 -0
  18. package/dist/helpers/RevenueCatHelper.d.ts +51 -0
  19. package/dist/helpers/RevenueCatHelper.d.ts.map +1 -0
  20. package/dist/helpers/RevenueCatHelper.js +96 -0
  21. package/dist/helpers/RevenueCatHelper.js.map +1 -0
  22. package/dist/helpers/index.cjs +10 -0
  23. package/dist/helpers/index.d.ts +4 -0
  24. package/dist/helpers/index.d.ts.map +1 -0
  25. package/dist/helpers/index.js +10 -0
  26. package/dist/helpers/index.js.map +1 -0
  27. package/dist/index.cjs +36 -0
  28. package/dist/index.d.ts +9 -0
  29. package/dist/index.d.ts.map +1 -0
  30. package/dist/index.js +36 -0
  31. package/dist/index.js.map +1 -0
  32. package/dist/middleware/hono.cjs +94 -0
  33. package/dist/middleware/hono.d.ts +63 -0
  34. package/dist/middleware/hono.d.ts.map +1 -0
  35. package/dist/middleware/hono.js +94 -0
  36. package/dist/middleware/hono.js.map +1 -0
  37. package/dist/schema/rate-limits.cjs +136 -0
  38. package/dist/schema/rate-limits.d.ts +333 -0
  39. package/dist/schema/rate-limits.d.ts.map +1 -0
  40. package/dist/schema/rate-limits.js +136 -0
  41. package/dist/schema/rate-limits.js.map +1 -0
  42. package/dist/types/entitlements.cjs +9 -0
  43. package/dist/types/entitlements.d.ts +29 -0
  44. package/dist/types/entitlements.d.ts.map +1 -0
  45. package/dist/types/entitlements.js +9 -0
  46. package/dist/types/entitlements.js.map +1 -0
  47. package/dist/types/index.cjs +20 -0
  48. package/dist/types/index.d.ts +4 -0
  49. package/dist/types/index.d.ts.map +1 -0
  50. package/dist/types/index.js +20 -0
  51. package/dist/types/index.js.map +1 -0
  52. package/dist/types/rate-limits.cjs +3 -0
  53. package/dist/types/rate-limits.d.ts +34 -0
  54. package/dist/types/rate-limits.d.ts.map +1 -0
  55. package/dist/types/rate-limits.js +3 -0
  56. package/dist/types/rate-limits.js.map +1 -0
  57. package/dist/types/responses.cjs +13 -0
  58. package/dist/types/responses.d.ts +85 -0
  59. package/dist/types/responses.d.ts.map +1 -0
  60. package/dist/types/responses.js +13 -0
  61. package/dist/types/responses.js.map +1 -0
  62. package/dist/utils/time.cjs +180 -0
  63. package/dist/utils/time.d.ts +80 -0
  64. package/dist/utils/time.d.ts.map +1 -0
  65. package/dist/utils/time.js +180 -0
  66. package/dist/utils/time.js.map +1 -0
  67. package/package.json +79 -0
@@ -0,0 +1,85 @@
1
+ import type { RateLimits } from "./rate-limits";
2
+ /**
3
+ * Remaining rate limit information for each time period.
4
+ * undefined means unlimited for that period.
5
+ */
6
+ export interface RateLimitRemaining {
7
+ /** Remaining requests this hour. undefined if unlimited */
8
+ hourly?: number;
9
+ /** Remaining requests this day. undefined if unlimited */
10
+ daily?: number;
11
+ /** Remaining requests this month. undefined if unlimited */
12
+ monthly?: number;
13
+ }
14
+ /**
15
+ * Which rate limit period was exceeded.
16
+ */
17
+ export type ExceededLimit = "hourly" | "daily" | "monthly";
18
+ /**
19
+ * Result from checking rate limits.
20
+ */
21
+ export interface RateLimitCheckResult {
22
+ /** Whether the request is allowed */
23
+ allowed: boolean;
24
+ /** HTTP status code: 200 if allowed, 429 if rate limited */
25
+ statusCode: 200 | 429;
26
+ /** Remaining requests for each time period */
27
+ remaining: RateLimitRemaining;
28
+ /** Which limit was exceeded (only set if allowed is false) */
29
+ exceededLimit?: ExceededLimit;
30
+ /** Current limits applied to this user */
31
+ limits: RateLimits;
32
+ }
33
+ /**
34
+ * Database row type for rate limit counter.
35
+ * This matches the new schema with history tracking.
36
+ */
37
+ export interface RateLimitCounterRow {
38
+ id: string;
39
+ user_id: string;
40
+ period_type: string;
41
+ period_start: Date;
42
+ request_count: number;
43
+ created_at: Date | null;
44
+ updated_at: Date | null;
45
+ }
46
+ /**
47
+ * Valid period types for rate limiting.
48
+ */
49
+ export declare enum PeriodType {
50
+ HOURLY = "hourly",
51
+ DAILY = "daily",
52
+ MONTHLY = "monthly"
53
+ }
54
+ /**
55
+ * A single history entry for a time period.
56
+ */
57
+ export interface UsageHistoryEntry {
58
+ /** Start of the time period */
59
+ period_start: Date;
60
+ /** End of the time period (exclusive) */
61
+ period_end: Date;
62
+ /** Number of requests in this period */
63
+ request_count: number;
64
+ }
65
+ /**
66
+ * Usage history for a user and period type.
67
+ */
68
+ export interface UsageHistory {
69
+ /** User identifier */
70
+ user_id: string;
71
+ /** Type of period: 'hourly', 'daily', or 'monthly' */
72
+ period_type: PeriodType;
73
+ /** Historical entries, sorted by period_start descending (most recent first) */
74
+ entries: UsageHistoryEntry[];
75
+ }
76
+ /**
77
+ * Subscription information from RevenueCat.
78
+ */
79
+ export interface SubscriptionInfo {
80
+ /** Active entitlement names */
81
+ entitlements: string[];
82
+ /** Subscription start date (earliest active entitlement's purchase_date) */
83
+ subscriptionStartedAt: Date | null;
84
+ }
85
+ //# sourceMappingURL=responses.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"responses.d.ts","sourceRoot":"","sources":["../../src/types/responses.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,eAAe,CAAC;AAEhD;;;GAGG;AACH,MAAM,WAAW,kBAAkB;IACjC,2DAA2D;IAC3D,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,0DAA0D;IAC1D,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,4DAA4D;IAC5D,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AAED;;GAEG;AACH,MAAM,MAAM,aAAa,GAAG,QAAQ,GAAG,OAAO,GAAG,SAAS,CAAC;AAE3D;;GAEG;AACH,MAAM,WAAW,oBAAoB;IACnC,qCAAqC;IACrC,OAAO,EAAE,OAAO,CAAC;IACjB,4DAA4D;IAC5D,UAAU,EAAE,GAAG,GAAG,GAAG,CAAC;IACtB,8CAA8C;IAC9C,SAAS,EAAE,kBAAkB,CAAC;IAC9B,8DAA8D;IAC9D,aAAa,CAAC,EAAE,aAAa,CAAC;IAC9B,0CAA0C;IAC1C,MAAM,EAAE,UAAU,CAAC;CACpB;AAED;;;GAGG;AACH,MAAM,WAAW,mBAAmB;IAClC,EAAE,EAAE,MAAM,CAAC;IACX,OAAO,EAAE,MAAM,CAAC;IAChB,WAAW,EAAE,MAAM,CAAC;IACpB,YAAY,EAAE,IAAI,CAAC;IACnB,aAAa,EAAE,MAAM,CAAC;IACtB,UAAU,EAAE,IAAI,GAAG,IAAI,CAAC;IACxB,UAAU,EAAE,IAAI,GAAG,IAAI,CAAC;CACzB;AAED;;GAEG;AACH,oBAAY,UAAU;IACpB,MAAM,WAAW;IACjB,KAAK,UAAU;IACf,OAAO,YAAY;CACpB;AAED;;GAEG;AACH,MAAM,WAAW,iBAAiB;IAChC,+BAA+B;IAC/B,YAAY,EAAE,IAAI,CAAC;IACnB,yCAAyC;IACzC,UAAU,EAAE,IAAI,CAAC;IACjB,wCAAwC;IACxC,aAAa,EAAE,MAAM,CAAC;CACvB;AAED;;GAEG;AACH,MAAM,WAAW,YAAY;IAC3B,sBAAsB;IACtB,OAAO,EAAE,MAAM,CAAC;IAChB,sDAAsD;IACtD,WAAW,EAAE,UAAU,CAAC;IACxB,gFAAgF;IAChF,OAAO,EAAE,iBAAiB,EAAE,CAAC;CAC9B;AAED;;GAEG;AACH,MAAM,WAAW,gBAAgB;IAC/B,+BAA+B;IAC/B,YAAY,EAAE,MAAM,EAAE,CAAC;IACvB,4EAA4E;IAC5E,qBAAqB,EAAE,IAAI,GAAG,IAAI,CAAC;CACpC"}
@@ -0,0 +1,13 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.PeriodType = void 0;
4
+ /**
5
+ * Valid period types for rate limiting.
6
+ */
7
+ var PeriodType;
8
+ (function (PeriodType) {
9
+ PeriodType["HOURLY"] = "hourly";
10
+ PeriodType["DAILY"] = "daily";
11
+ PeriodType["MONTHLY"] = "monthly";
12
+ })(PeriodType || (exports.PeriodType = PeriodType = {}));
13
+ //# sourceMappingURL=responses.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"responses.js","sourceRoot":"","sources":["../../src/types/responses.ts"],"names":[],"mappings":";;;AAkDA;;GAEG;AACH,IAAY,UAIX;AAJD,WAAY,UAAU;IACpB,+BAAiB,CAAA;IACjB,6BAAe,CAAA;IACf,iCAAmB,CAAA;AACrB,CAAC,EAJW,UAAU,0BAAV,UAAU,QAIrB"}
@@ -0,0 +1,180 @@
1
+ "use strict";
2
+ /**
3
+ * Time utilities for rate limit period calculation.
4
+ *
5
+ * All periods are calculated in UTC:
6
+ * - Hourly: top of hour (e.g., 10:00:00Z, 11:00:00Z)
7
+ * - Daily: midnight UTC (e.g., 2025-01-15T00:00:00Z)
8
+ * - Monthly: based on subscription start date
9
+ * (e.g., if subscription started 3/5, months are 3/5-4/4, 4/5-5/4, etc.)
10
+ */
11
+ Object.defineProperty(exports, "__esModule", { value: true });
12
+ exports.getCurrentHourStart = getCurrentHourStart;
13
+ exports.getNextHourStart = getNextHourStart;
14
+ exports.getNextHourReset = getNextHourReset;
15
+ exports.getCurrentDayStart = getCurrentDayStart;
16
+ exports.getNextDayStart = getNextDayStart;
17
+ exports.getNextDayReset = getNextDayReset;
18
+ exports.getSubscriptionMonthStart = getSubscriptionMonthStart;
19
+ exports.getNextSubscriptionMonthStart = getNextSubscriptionMonthStart;
20
+ exports.getNextMonthReset = getNextMonthReset;
21
+ exports.getTimeUntilReset = getTimeUntilReset;
22
+ // ============================================================================
23
+ // Hourly Period Functions
24
+ // ============================================================================
25
+ /**
26
+ * Get the start of the current hour in UTC.
27
+ * @example 14:35:22Z → 14:00:00Z
28
+ */
29
+ function getCurrentHourStart(now = new Date()) {
30
+ return new Date(Date.UTC(now.getUTCFullYear(), now.getUTCMonth(), now.getUTCDate(), now.getUTCHours(), 0, 0, 0));
31
+ }
32
+ /**
33
+ * Get the start of the next hour in UTC.
34
+ * @example 14:35:22Z → 15:00:00Z
35
+ */
36
+ function getNextHourStart(now = new Date()) {
37
+ const next = new Date(getCurrentHourStart(now));
38
+ next.setUTCHours(next.getUTCHours() + 1);
39
+ return next;
40
+ }
41
+ /**
42
+ * Get the next hour reset timestamp.
43
+ * @deprecated Use getNextHourStart instead
44
+ */
45
+ function getNextHourReset(now = new Date()) {
46
+ return getNextHourStart(now);
47
+ }
48
+ // ============================================================================
49
+ // Daily Period Functions
50
+ // ============================================================================
51
+ /**
52
+ * Get the start of the current day in UTC (midnight).
53
+ * @example 2025-01-15T14:35:22Z → 2025-01-15T00:00:00Z
54
+ */
55
+ function getCurrentDayStart(now = new Date()) {
56
+ return new Date(Date.UTC(now.getUTCFullYear(), now.getUTCMonth(), now.getUTCDate(), 0, 0, 0, 0));
57
+ }
58
+ /**
59
+ * Get the start of the next day in UTC (midnight).
60
+ * @example 2025-01-15T14:35:22Z → 2025-01-16T00:00:00Z
61
+ */
62
+ function getNextDayStart(now = new Date()) {
63
+ const next = new Date(getCurrentDayStart(now));
64
+ next.setUTCDate(next.getUTCDate() + 1);
65
+ return next;
66
+ }
67
+ /**
68
+ * Get the next day reset timestamp.
69
+ * @deprecated Use getNextDayStart instead
70
+ */
71
+ function getNextDayReset(now = new Date()) {
72
+ return getNextDayStart(now);
73
+ }
74
+ // ============================================================================
75
+ // Monthly Period Functions (Subscription-based)
76
+ // ============================================================================
77
+ /**
78
+ * Get the start of the current subscription month.
79
+ *
80
+ * Subscription months are based on the subscription start date:
81
+ * - If subscription started on day 5, months are: 3/5-4/4, 4/5-5/4, etc.
82
+ * - If subscription started on day 31 but current month has fewer days,
83
+ * uses the last day of the month.
84
+ *
85
+ * @param subscriptionStartedAt - When the subscription started (null for no subscription)
86
+ * @param now - Current date (defaults to now)
87
+ * @returns Start of the current subscription month
88
+ *
89
+ * @example
90
+ * // Subscription started March 5, current date April 10
91
+ * getSubscriptionMonthStart(new Date('2025-03-05'), new Date('2025-04-10'))
92
+ * // Returns: 2025-04-05T00:00:00Z
93
+ *
94
+ * @example
95
+ * // Subscription started March 5, current date April 3
96
+ * getSubscriptionMonthStart(new Date('2025-03-05'), new Date('2025-04-03'))
97
+ * // Returns: 2025-03-05T00:00:00Z
98
+ */
99
+ function getSubscriptionMonthStart(subscriptionStartedAt, now = new Date()) {
100
+ // If no subscription, fall back to first of current calendar month
101
+ if (!subscriptionStartedAt) {
102
+ return new Date(Date.UTC(now.getUTCFullYear(), now.getUTCMonth(), 1, 0, 0, 0, 0));
103
+ }
104
+ const startDay = subscriptionStartedAt.getUTCDate();
105
+ const nowYear = now.getUTCFullYear();
106
+ const nowMonth = now.getUTCMonth();
107
+ const nowDay = now.getUTCDate();
108
+ // Get the last day of the current month
109
+ const lastDayOfMonth = new Date(Date.UTC(nowYear, nowMonth + 1, 0)).getUTCDate();
110
+ // Adjust start day if it's greater than days in current month
111
+ const effectiveStartDay = Math.min(startDay, lastDayOfMonth);
112
+ // Check if we're past the subscription day in this month
113
+ if (nowDay >= effectiveStartDay) {
114
+ // Current period started this month
115
+ return new Date(Date.UTC(nowYear, nowMonth, effectiveStartDay, 0, 0, 0, 0));
116
+ }
117
+ else {
118
+ // Current period started last month
119
+ const prevMonth = nowMonth === 0 ? 11 : nowMonth - 1;
120
+ const prevYear = nowMonth === 0 ? nowYear - 1 : nowYear;
121
+ // Get last day of previous month to handle day overflow
122
+ const lastDayOfPrevMonth = new Date(Date.UTC(prevYear, prevMonth + 1, 0)).getUTCDate();
123
+ const effectivePrevStartDay = Math.min(startDay, lastDayOfPrevMonth);
124
+ return new Date(Date.UTC(prevYear, prevMonth, effectivePrevStartDay, 0, 0, 0, 0));
125
+ }
126
+ }
127
+ /**
128
+ * Get the start of the next subscription month.
129
+ *
130
+ * @param subscriptionStartedAt - When the subscription started (null for no subscription)
131
+ * @param now - Current date (defaults to now)
132
+ * @returns Start of the next subscription month
133
+ */
134
+ function getNextSubscriptionMonthStart(subscriptionStartedAt, now = new Date()) {
135
+ const currentMonthStart = getSubscriptionMonthStart(subscriptionStartedAt, now);
136
+ // If no subscription, use first of next calendar month
137
+ if (!subscriptionStartedAt) {
138
+ return new Date(Date.UTC(currentMonthStart.getUTCFullYear(), currentMonthStart.getUTCMonth() + 1, 1, 0, 0, 0, 0));
139
+ }
140
+ const startDay = subscriptionStartedAt.getUTCDate();
141
+ const nextMonth = currentMonthStart.getUTCMonth() + 1;
142
+ const nextYear = nextMonth > 11
143
+ ? currentMonthStart.getUTCFullYear() + 1
144
+ : currentMonthStart.getUTCFullYear();
145
+ const normalizedMonth = nextMonth % 12;
146
+ // Get last day of next month to handle day overflow
147
+ const lastDayOfNextMonth = new Date(Date.UTC(nextYear, normalizedMonth + 1, 0)).getUTCDate();
148
+ const effectiveStartDay = Math.min(startDay, lastDayOfNextMonth);
149
+ return new Date(Date.UTC(nextYear, normalizedMonth, effectiveStartDay, 0, 0, 0, 0));
150
+ }
151
+ /**
152
+ * Get the next month reset timestamp (calendar month).
153
+ * @deprecated Use getNextSubscriptionMonthStart for subscription-based months
154
+ */
155
+ function getNextMonthReset(now = new Date()) {
156
+ return new Date(Date.UTC(now.getUTCFullYear(), now.getUTCMonth() + 1, 1, 0, 0, 0, 0));
157
+ }
158
+ // ============================================================================
159
+ // Utility Functions
160
+ // ============================================================================
161
+ /**
162
+ * Get time until reset in human-readable format.
163
+ */
164
+ function getTimeUntilReset(resetAt, now = new Date()) {
165
+ const diffMs = resetAt.getTime() - now.getTime();
166
+ if (diffMs <= 0)
167
+ return "now";
168
+ const seconds = Math.floor(diffMs / 1000);
169
+ const minutes = Math.floor(seconds / 60);
170
+ const hours = Math.floor(minutes / 60);
171
+ const days = Math.floor(hours / 24);
172
+ if (days > 0)
173
+ return `${days}d ${hours % 24}h`;
174
+ if (hours > 0)
175
+ return `${hours}h ${minutes % 60}m`;
176
+ if (minutes > 0)
177
+ return `${minutes}m`;
178
+ return `${seconds}s`;
179
+ }
180
+ //# sourceMappingURL=time.js.map
@@ -0,0 +1,80 @@
1
+ /**
2
+ * Time utilities for rate limit period calculation.
3
+ *
4
+ * All periods are calculated in UTC:
5
+ * - Hourly: top of hour (e.g., 10:00:00Z, 11:00:00Z)
6
+ * - Daily: midnight UTC (e.g., 2025-01-15T00:00:00Z)
7
+ * - Monthly: based on subscription start date
8
+ * (e.g., if subscription started 3/5, months are 3/5-4/4, 4/5-5/4, etc.)
9
+ */
10
+ /**
11
+ * Get the start of the current hour in UTC.
12
+ * @example 14:35:22Z → 14:00:00Z
13
+ */
14
+ export declare function getCurrentHourStart(now?: Date): Date;
15
+ /**
16
+ * Get the start of the next hour in UTC.
17
+ * @example 14:35:22Z → 15:00:00Z
18
+ */
19
+ export declare function getNextHourStart(now?: Date): Date;
20
+ /**
21
+ * Get the next hour reset timestamp.
22
+ * @deprecated Use getNextHourStart instead
23
+ */
24
+ export declare function getNextHourReset(now?: Date): Date;
25
+ /**
26
+ * Get the start of the current day in UTC (midnight).
27
+ * @example 2025-01-15T14:35:22Z → 2025-01-15T00:00:00Z
28
+ */
29
+ export declare function getCurrentDayStart(now?: Date): Date;
30
+ /**
31
+ * Get the start of the next day in UTC (midnight).
32
+ * @example 2025-01-15T14:35:22Z → 2025-01-16T00:00:00Z
33
+ */
34
+ export declare function getNextDayStart(now?: Date): Date;
35
+ /**
36
+ * Get the next day reset timestamp.
37
+ * @deprecated Use getNextDayStart instead
38
+ */
39
+ export declare function getNextDayReset(now?: Date): Date;
40
+ /**
41
+ * Get the start of the current subscription month.
42
+ *
43
+ * Subscription months are based on the subscription start date:
44
+ * - If subscription started on day 5, months are: 3/5-4/4, 4/5-5/4, etc.
45
+ * - If subscription started on day 31 but current month has fewer days,
46
+ * uses the last day of the month.
47
+ *
48
+ * @param subscriptionStartedAt - When the subscription started (null for no subscription)
49
+ * @param now - Current date (defaults to now)
50
+ * @returns Start of the current subscription month
51
+ *
52
+ * @example
53
+ * // Subscription started March 5, current date April 10
54
+ * getSubscriptionMonthStart(new Date('2025-03-05'), new Date('2025-04-10'))
55
+ * // Returns: 2025-04-05T00:00:00Z
56
+ *
57
+ * @example
58
+ * // Subscription started March 5, current date April 3
59
+ * getSubscriptionMonthStart(new Date('2025-03-05'), new Date('2025-04-03'))
60
+ * // Returns: 2025-03-05T00:00:00Z
61
+ */
62
+ export declare function getSubscriptionMonthStart(subscriptionStartedAt: Date | null, now?: Date): Date;
63
+ /**
64
+ * Get the start of the next subscription month.
65
+ *
66
+ * @param subscriptionStartedAt - When the subscription started (null for no subscription)
67
+ * @param now - Current date (defaults to now)
68
+ * @returns Start of the next subscription month
69
+ */
70
+ export declare function getNextSubscriptionMonthStart(subscriptionStartedAt: Date | null, now?: Date): Date;
71
+ /**
72
+ * Get the next month reset timestamp (calendar month).
73
+ * @deprecated Use getNextSubscriptionMonthStart for subscription-based months
74
+ */
75
+ export declare function getNextMonthReset(now?: Date): Date;
76
+ /**
77
+ * Get time until reset in human-readable format.
78
+ */
79
+ export declare function getTimeUntilReset(resetAt: Date, now?: Date): string;
80
+ //# sourceMappingURL=time.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"time.d.ts","sourceRoot":"","sources":["../../src/utils/time.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAMH;;;GAGG;AACH,wBAAgB,mBAAmB,CAAC,GAAG,GAAE,IAAiB,GAAG,IAAI,CAYhE;AAED;;;GAGG;AACH,wBAAgB,gBAAgB,CAAC,GAAG,GAAE,IAAiB,GAAG,IAAI,CAI7D;AAED;;;GAGG;AACH,wBAAgB,gBAAgB,CAAC,GAAG,GAAE,IAAiB,GAAG,IAAI,CAE7D;AAMD;;;GAGG;AACH,wBAAgB,kBAAkB,CAAC,GAAG,GAAE,IAAiB,GAAG,IAAI,CAY/D;AAED;;;GAGG;AACH,wBAAgB,eAAe,CAAC,GAAG,GAAE,IAAiB,GAAG,IAAI,CAI5D;AAED;;;GAGG;AACH,wBAAgB,eAAe,CAAC,GAAG,GAAE,IAAiB,GAAG,IAAI,CAE5D;AAMD;;;;;;;;;;;;;;;;;;;;;GAqBG;AACH,wBAAgB,yBAAyB,CACvC,qBAAqB,EAAE,IAAI,GAAG,IAAI,EAClC,GAAG,GAAE,IAAiB,GACrB,IAAI,CAwCN;AAED;;;;;;GAMG;AACH,wBAAgB,6BAA6B,CAC3C,qBAAqB,EAAE,IAAI,GAAG,IAAI,EAClC,GAAG,GAAE,IAAiB,GACrB,IAAI,CAsCN;AAED;;;GAGG;AACH,wBAAgB,iBAAiB,CAAC,GAAG,GAAE,IAAiB,GAAG,IAAI,CAI9D;AAMD;;GAEG;AACH,wBAAgB,iBAAiB,CAC/B,OAAO,EAAE,IAAI,EACb,GAAG,GAAE,IAAiB,GACrB,MAAM,CAcR"}
@@ -0,0 +1,180 @@
1
+ "use strict";
2
+ /**
3
+ * Time utilities for rate limit period calculation.
4
+ *
5
+ * All periods are calculated in UTC:
6
+ * - Hourly: top of hour (e.g., 10:00:00Z, 11:00:00Z)
7
+ * - Daily: midnight UTC (e.g., 2025-01-15T00:00:00Z)
8
+ * - Monthly: based on subscription start date
9
+ * (e.g., if subscription started 3/5, months are 3/5-4/4, 4/5-5/4, etc.)
10
+ */
11
+ Object.defineProperty(exports, "__esModule", { value: true });
12
+ exports.getCurrentHourStart = getCurrentHourStart;
13
+ exports.getNextHourStart = getNextHourStart;
14
+ exports.getNextHourReset = getNextHourReset;
15
+ exports.getCurrentDayStart = getCurrentDayStart;
16
+ exports.getNextDayStart = getNextDayStart;
17
+ exports.getNextDayReset = getNextDayReset;
18
+ exports.getSubscriptionMonthStart = getSubscriptionMonthStart;
19
+ exports.getNextSubscriptionMonthStart = getNextSubscriptionMonthStart;
20
+ exports.getNextMonthReset = getNextMonthReset;
21
+ exports.getTimeUntilReset = getTimeUntilReset;
22
+ // ============================================================================
23
+ // Hourly Period Functions
24
+ // ============================================================================
25
+ /**
26
+ * Get the start of the current hour in UTC.
27
+ * @example 14:35:22Z → 14:00:00Z
28
+ */
29
+ function getCurrentHourStart(now = new Date()) {
30
+ return new Date(Date.UTC(now.getUTCFullYear(), now.getUTCMonth(), now.getUTCDate(), now.getUTCHours(), 0, 0, 0));
31
+ }
32
+ /**
33
+ * Get the start of the next hour in UTC.
34
+ * @example 14:35:22Z → 15:00:00Z
35
+ */
36
+ function getNextHourStart(now = new Date()) {
37
+ const next = new Date(getCurrentHourStart(now));
38
+ next.setUTCHours(next.getUTCHours() + 1);
39
+ return next;
40
+ }
41
+ /**
42
+ * Get the next hour reset timestamp.
43
+ * @deprecated Use getNextHourStart instead
44
+ */
45
+ function getNextHourReset(now = new Date()) {
46
+ return getNextHourStart(now);
47
+ }
48
+ // ============================================================================
49
+ // Daily Period Functions
50
+ // ============================================================================
51
+ /**
52
+ * Get the start of the current day in UTC (midnight).
53
+ * @example 2025-01-15T14:35:22Z → 2025-01-15T00:00:00Z
54
+ */
55
+ function getCurrentDayStart(now = new Date()) {
56
+ return new Date(Date.UTC(now.getUTCFullYear(), now.getUTCMonth(), now.getUTCDate(), 0, 0, 0, 0));
57
+ }
58
+ /**
59
+ * Get the start of the next day in UTC (midnight).
60
+ * @example 2025-01-15T14:35:22Z → 2025-01-16T00:00:00Z
61
+ */
62
+ function getNextDayStart(now = new Date()) {
63
+ const next = new Date(getCurrentDayStart(now));
64
+ next.setUTCDate(next.getUTCDate() + 1);
65
+ return next;
66
+ }
67
+ /**
68
+ * Get the next day reset timestamp.
69
+ * @deprecated Use getNextDayStart instead
70
+ */
71
+ function getNextDayReset(now = new Date()) {
72
+ return getNextDayStart(now);
73
+ }
74
+ // ============================================================================
75
+ // Monthly Period Functions (Subscription-based)
76
+ // ============================================================================
77
+ /**
78
+ * Get the start of the current subscription month.
79
+ *
80
+ * Subscription months are based on the subscription start date:
81
+ * - If subscription started on day 5, months are: 3/5-4/4, 4/5-5/4, etc.
82
+ * - If subscription started on day 31 but current month has fewer days,
83
+ * uses the last day of the month.
84
+ *
85
+ * @param subscriptionStartedAt - When the subscription started (null for no subscription)
86
+ * @param now - Current date (defaults to now)
87
+ * @returns Start of the current subscription month
88
+ *
89
+ * @example
90
+ * // Subscription started March 5, current date April 10
91
+ * getSubscriptionMonthStart(new Date('2025-03-05'), new Date('2025-04-10'))
92
+ * // Returns: 2025-04-05T00:00:00Z
93
+ *
94
+ * @example
95
+ * // Subscription started March 5, current date April 3
96
+ * getSubscriptionMonthStart(new Date('2025-03-05'), new Date('2025-04-03'))
97
+ * // Returns: 2025-03-05T00:00:00Z
98
+ */
99
+ function getSubscriptionMonthStart(subscriptionStartedAt, now = new Date()) {
100
+ // If no subscription, fall back to first of current calendar month
101
+ if (!subscriptionStartedAt) {
102
+ return new Date(Date.UTC(now.getUTCFullYear(), now.getUTCMonth(), 1, 0, 0, 0, 0));
103
+ }
104
+ const startDay = subscriptionStartedAt.getUTCDate();
105
+ const nowYear = now.getUTCFullYear();
106
+ const nowMonth = now.getUTCMonth();
107
+ const nowDay = now.getUTCDate();
108
+ // Get the last day of the current month
109
+ const lastDayOfMonth = new Date(Date.UTC(nowYear, nowMonth + 1, 0)).getUTCDate();
110
+ // Adjust start day if it's greater than days in current month
111
+ const effectiveStartDay = Math.min(startDay, lastDayOfMonth);
112
+ // Check if we're past the subscription day in this month
113
+ if (nowDay >= effectiveStartDay) {
114
+ // Current period started this month
115
+ return new Date(Date.UTC(nowYear, nowMonth, effectiveStartDay, 0, 0, 0, 0));
116
+ }
117
+ else {
118
+ // Current period started last month
119
+ const prevMonth = nowMonth === 0 ? 11 : nowMonth - 1;
120
+ const prevYear = nowMonth === 0 ? nowYear - 1 : nowYear;
121
+ // Get last day of previous month to handle day overflow
122
+ const lastDayOfPrevMonth = new Date(Date.UTC(prevYear, prevMonth + 1, 0)).getUTCDate();
123
+ const effectivePrevStartDay = Math.min(startDay, lastDayOfPrevMonth);
124
+ return new Date(Date.UTC(prevYear, prevMonth, effectivePrevStartDay, 0, 0, 0, 0));
125
+ }
126
+ }
127
+ /**
128
+ * Get the start of the next subscription month.
129
+ *
130
+ * @param subscriptionStartedAt - When the subscription started (null for no subscription)
131
+ * @param now - Current date (defaults to now)
132
+ * @returns Start of the next subscription month
133
+ */
134
+ function getNextSubscriptionMonthStart(subscriptionStartedAt, now = new Date()) {
135
+ const currentMonthStart = getSubscriptionMonthStart(subscriptionStartedAt, now);
136
+ // If no subscription, use first of next calendar month
137
+ if (!subscriptionStartedAt) {
138
+ return new Date(Date.UTC(currentMonthStart.getUTCFullYear(), currentMonthStart.getUTCMonth() + 1, 1, 0, 0, 0, 0));
139
+ }
140
+ const startDay = subscriptionStartedAt.getUTCDate();
141
+ const nextMonth = currentMonthStart.getUTCMonth() + 1;
142
+ const nextYear = nextMonth > 11
143
+ ? currentMonthStart.getUTCFullYear() + 1
144
+ : currentMonthStart.getUTCFullYear();
145
+ const normalizedMonth = nextMonth % 12;
146
+ // Get last day of next month to handle day overflow
147
+ const lastDayOfNextMonth = new Date(Date.UTC(nextYear, normalizedMonth + 1, 0)).getUTCDate();
148
+ const effectiveStartDay = Math.min(startDay, lastDayOfNextMonth);
149
+ return new Date(Date.UTC(nextYear, normalizedMonth, effectiveStartDay, 0, 0, 0, 0));
150
+ }
151
+ /**
152
+ * Get the next month reset timestamp (calendar month).
153
+ * @deprecated Use getNextSubscriptionMonthStart for subscription-based months
154
+ */
155
+ function getNextMonthReset(now = new Date()) {
156
+ return new Date(Date.UTC(now.getUTCFullYear(), now.getUTCMonth() + 1, 1, 0, 0, 0, 0));
157
+ }
158
+ // ============================================================================
159
+ // Utility Functions
160
+ // ============================================================================
161
+ /**
162
+ * Get time until reset in human-readable format.
163
+ */
164
+ function getTimeUntilReset(resetAt, now = new Date()) {
165
+ const diffMs = resetAt.getTime() - now.getTime();
166
+ if (diffMs <= 0)
167
+ return "now";
168
+ const seconds = Math.floor(diffMs / 1000);
169
+ const minutes = Math.floor(seconds / 60);
170
+ const hours = Math.floor(minutes / 60);
171
+ const days = Math.floor(hours / 24);
172
+ if (days > 0)
173
+ return `${days}d ${hours % 24}h`;
174
+ if (hours > 0)
175
+ return `${hours}h ${minutes % 60}m`;
176
+ if (minutes > 0)
177
+ return `${minutes}m`;
178
+ return `${seconds}s`;
179
+ }
180
+ //# sourceMappingURL=time.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"time.js","sourceRoot":"","sources":["../../src/utils/time.ts"],"names":[],"mappings":"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"}
package/package.json ADDED
@@ -0,0 +1,79 @@
1
+ {
2
+ "name": "@sudobility/ratelimit_service",
3
+ "version": "1.0.1",
4
+ "description": "Shared rate limiting library based on RevenueCat entitlements",
5
+ "type": "module",
6
+ "main": "./dist/index.cjs",
7
+ "module": "./dist/index.js",
8
+ "types": "./dist/index.d.ts",
9
+ "exports": {
10
+ ".": {
11
+ "import": "./dist/index.js",
12
+ "require": "./dist/index.cjs",
13
+ "types": "./dist/index.d.ts"
14
+ },
15
+ "./middleware/hono": {
16
+ "import": "./dist/middleware/hono.js",
17
+ "require": "./dist/middleware/hono.cjs",
18
+ "types": "./dist/middleware/hono.d.ts"
19
+ },
20
+ "./schema": {
21
+ "import": "./dist/schema/rate-limits.js",
22
+ "require": "./dist/schema/rate-limits.cjs",
23
+ "types": "./dist/schema/rate-limits.d.ts"
24
+ }
25
+ },
26
+ "scripts": {
27
+ "build": "bun run build:esm && bun run build:cjs",
28
+ "build:esm": "bunx tsc -p tsconfig.esm.json",
29
+ "build:cjs": "bunx tsc -p tsconfig.cjs.json && bun run build:cjs-rename",
30
+ "build:cjs-rename": "find dist -name '*.js' -not -name '*.cjs' -exec sh -c 'cp \"$1\" \"${1%.js}.cjs\"' _ {} \\;",
31
+ "clean": "rm -rf dist",
32
+ "dev": "bunx tsc --watch",
33
+ "test": "bun test",
34
+ "test:run": "bun test",
35
+ "lint": "bunx eslint src/",
36
+ "lint:fix": "bunx eslint src/ --fix",
37
+ "typecheck": "bunx tsc --noEmit",
38
+ "format": "bunx prettier --write \"src/**/*.ts\"",
39
+ "format:check": "bunx prettier --check \"src/**/*.ts\"",
40
+ "verify": "bun run typecheck && bun run lint && bun run test && bun run build",
41
+ "prepublishOnly": "bun run clean && bun run verify"
42
+ },
43
+ "files": [
44
+ "dist/**/*",
45
+ "CLAUDE.md"
46
+ ],
47
+ "keywords": [
48
+ "rate-limiting",
49
+ "revenuecat",
50
+ "subscription",
51
+ "entitlements",
52
+ "hono",
53
+ "drizzle"
54
+ ],
55
+ "author": "Sudobility",
56
+ "license": "MIT",
57
+ "peerDependencies": {
58
+ "@sudobility/types": "^1.9.37",
59
+ "drizzle-orm": "^0.45.0",
60
+ "hono": "^4.0.0"
61
+ },
62
+ "devDependencies": {
63
+ "@sudobility/types": "^1.9.37",
64
+ "@types/bun": "latest",
65
+ "@types/node": "^24.10.1",
66
+ "@typescript-eslint/eslint-plugin": "^8.50.0",
67
+ "@typescript-eslint/parser": "^8.50.0",
68
+ "drizzle-orm": "^0.45.0",
69
+ "eslint": "^9.39.2",
70
+ "eslint-plugin-import": "^2.32.0",
71
+ "hono": "^4.10.7",
72
+ "postgres": "^3.4.7",
73
+ "prettier": "^3.7.4",
74
+ "typescript": "^5.9.3"
75
+ },
76
+ "publishConfig": {
77
+ "access": "public"
78
+ }
79
+ }