@farm.js/core 0.1.0-beta.16 → 0.1.0-beta.17

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 (215) hide show
  1. package/dist/after.d.mts +25 -0
  2. package/dist/after.d.ts +25 -0
  3. package/dist/agent-runtime.d.mts +96 -0
  4. package/dist/agent-runtime.d.ts +96 -0
  5. package/dist/api/route-manager.d.mts +66 -0
  6. package/dist/api/route-manager.d.ts +66 -0
  7. package/dist/api/runtime.d.mts +3 -0
  8. package/dist/api/runtime.d.ts +3 -0
  9. package/dist/api.d.mts +48 -0
  10. package/dist/api.d.ts +48 -0
  11. package/dist/app-B0tE1I3o.d.ts +306 -0
  12. package/dist/app-Dv2JJb7X.d.mts +306 -0
  13. package/dist/app-markdown.d.mts +24 -0
  14. package/dist/app-markdown.d.ts +24 -0
  15. package/dist/cache.d.mts +192 -0
  16. package/dist/cache.d.ts +192 -0
  17. package/dist/{chunk-AN3PQVKH.mjs → chunk-2FLBZFPG.mjs} +9 -7
  18. package/dist/chunk-2FLBZFPG.mjs.map +1 -0
  19. package/dist/chunk-E257KFBU.mjs +227 -0
  20. package/dist/chunk-E257KFBU.mjs.map +1 -0
  21. package/dist/{chunk-SLDBGSC3.mjs → chunk-JAEAE27K.mjs} +2 -2
  22. package/dist/{chunk-T2KL7VEL.mjs → chunk-PZXBQKCH.mjs} +13 -4
  23. package/dist/chunk-PZXBQKCH.mjs.map +1 -0
  24. package/dist/{chunk-UXUAWNO5.mjs → chunk-RIXKJPGI.mjs} +117 -55
  25. package/dist/chunk-RIXKJPGI.mjs.map +1 -0
  26. package/dist/{chunk-OSWV5IJB.mjs → chunk-T2M5QANG.mjs} +32 -9
  27. package/dist/chunk-T2M5QANG.mjs.map +1 -0
  28. package/dist/{chunk-BWJC5ZOD.mjs → chunk-VFDBC3W7.mjs} +2 -2
  29. package/dist/{chunk-BWJC5ZOD.mjs.map → chunk-VFDBC3W7.mjs.map} +1 -1
  30. package/dist/chunk-recovery-lnQFzcQP.d.mts +26 -0
  31. package/dist/chunk-recovery-lnQFzcQP.d.ts +26 -0
  32. package/dist/client-BT1mFQas.d.mts +447 -0
  33. package/dist/client-Nn0q4eO4.d.ts +447 -0
  34. package/dist/client-cache-CIlyBlmx.d.ts +6 -0
  35. package/dist/client-cache-D-EZ7XVW.d.mts +6 -0
  36. package/dist/client-plugins-278AvYHE.d.mts +2021 -0
  37. package/dist/client-plugins-CTQAkr7R.d.ts +2021 -0
  38. package/dist/client-plugins.d.mts +24 -0
  39. package/dist/client-plugins.d.ts +24 -0
  40. package/dist/client.d.mts +452 -0
  41. package/dist/client.d.ts +452 -0
  42. package/dist/config.d.mts +31 -0
  43. package/dist/config.d.ts +31 -0
  44. package/dist/cron.d.mts +78 -0
  45. package/dist/cron.d.ts +78 -0
  46. package/dist/deferred.d.mts +42 -0
  47. package/dist/deferred.d.ts +42 -0
  48. package/dist/deployment.d.mts +36 -0
  49. package/dist/deployment.d.ts +36 -0
  50. package/dist/{devtools-E4YNCY5J.mjs → devtools-K2ERKGNI.mjs} +3 -3
  51. package/dist/docs.cjs.map +1 -1
  52. package/dist/docs.d.mts +80 -0
  53. package/dist/docs.d.ts +80 -0
  54. package/dist/docs.mjs +3 -3
  55. package/dist/env-types.d.mts +12 -0
  56. package/dist/env-types.d.ts +12 -0
  57. package/dist/env.d.mts +45 -0
  58. package/dist/env.d.ts +45 -0
  59. package/dist/environment/vite.d.mts +22 -0
  60. package/dist/environment/vite.d.ts +22 -0
  61. package/dist/environment.d.mts +18 -0
  62. package/dist/environment.d.ts +18 -0
  63. package/dist/font.d.mts +95 -0
  64. package/dist/font.d.ts +95 -0
  65. package/dist/headers.d.mts +22 -0
  66. package/dist/headers.d.ts +22 -0
  67. package/dist/i18n/client.d.mts +32 -0
  68. package/dist/i18n/client.d.ts +32 -0
  69. package/dist/i18n/index.d.mts +20 -0
  70. package/dist/i18n/index.d.ts +20 -0
  71. package/dist/i18n/server.d.mts +30 -0
  72. package/dist/i18n/server.d.ts +30 -0
  73. package/dist/image/server.d.mts +37 -0
  74. package/dist/image/server.d.ts +37 -0
  75. package/dist/image/sharp.d.mts +7 -0
  76. package/dist/image/sharp.d.ts +7 -0
  77. package/dist/image-config-Duob7wER.d.mts +50 -0
  78. package/dist/image-config-Duob7wER.d.ts +50 -0
  79. package/dist/image.d.mts +39 -0
  80. package/dist/image.d.ts +39 -0
  81. package/dist/index.cjs +293 -58
  82. package/dist/index.cjs.map +1 -1
  83. package/dist/index.d.mts +477 -0
  84. package/dist/index.d.ts +477 -0
  85. package/dist/index.mjs +22 -18
  86. package/dist/index.mjs.map +1 -1
  87. package/dist/integration-api-CHT2OKAf.d.mts +93 -0
  88. package/dist/integration-api-CHT2OKAf.d.ts +93 -0
  89. package/dist/integrations.d.mts +24 -0
  90. package/dist/integrations.d.ts +24 -0
  91. package/dist/internal/build-runtime.cjs +306 -137
  92. package/dist/internal/build-runtime.cjs.map +1 -1
  93. package/dist/internal/build-runtime.d.mts +41 -0
  94. package/dist/internal/build-runtime.d.ts +41 -0
  95. package/dist/internal/build-runtime.mjs +7 -7
  96. package/dist/internal/client-runtime.d.mts +17 -0
  97. package/dist/internal/client-runtime.d.ts +17 -0
  98. package/dist/internal/config-runtime.cjs +140 -1
  99. package/dist/internal/config-runtime.cjs.map +1 -1
  100. package/dist/internal/config-runtime.d.mts +41 -0
  101. package/dist/internal/config-runtime.d.ts +41 -0
  102. package/dist/internal/config-runtime.mjs +2 -2
  103. package/dist/internal/metadata-image-runtime.d.mts +25 -0
  104. package/dist/internal/metadata-image-runtime.d.ts +25 -0
  105. package/dist/internal/production-node-env.d.mts +12 -0
  106. package/dist/internal/production-node-env.d.ts +12 -0
  107. package/dist/internal/production-runtime.d.mts +44 -0
  108. package/dist/internal/production-runtime.d.ts +44 -0
  109. package/dist/island-CfGru1MO.d.mts +9 -0
  110. package/dist/island-CfGru1MO.d.ts +9 -0
  111. package/dist/markdown.d.mts +60 -0
  112. package/dist/markdown.d.ts +60 -0
  113. package/dist/metadata-DmCudMw_.d.mts +22 -0
  114. package/dist/metadata-xghtOlbR.d.ts +22 -0
  115. package/dist/middleware.cjs +116 -98
  116. package/dist/middleware.cjs.map +1 -1
  117. package/dist/middleware.d.mts +171 -0
  118. package/dist/middleware.d.ts +171 -0
  119. package/dist/middleware.mjs +5 -2
  120. package/dist/navigation-errors-Dvwpzaer.d.mts +13 -0
  121. package/dist/navigation-errors-Dvwpzaer.d.ts +13 -0
  122. package/dist/navigation.d.mts +14 -0
  123. package/dist/navigation.d.ts +14 -0
  124. package/dist/observability.d.mts +335 -0
  125. package/dist/observability.d.ts +335 -0
  126. package/dist/params-BALtrRim.d.ts +15 -0
  127. package/dist/params-ry-lxqmy.d.mts +15 -0
  128. package/dist/plugin-BJDf43dc.d.mts +165 -0
  129. package/dist/plugin-BJDf43dc.d.ts +165 -0
  130. package/dist/plugin.cjs +132 -0
  131. package/dist/plugin.cjs.map +1 -1
  132. package/dist/plugin.d.mts +24 -0
  133. package/dist/plugin.d.ts +24 -0
  134. package/dist/plugin.mjs +4 -4
  135. package/dist/production-runtime-BLxSv9cU.d.ts +79 -0
  136. package/dist/production-runtime-DFN2_RXq.d.mts +79 -0
  137. package/dist/query/client.d.mts +61 -0
  138. package/dist/query/client.d.ts +61 -0
  139. package/dist/query/index.d.mts +90 -0
  140. package/dist/query/index.d.ts +90 -0
  141. package/dist/query/parsers.d.mts +25 -0
  142. package/dist/query/parsers.d.ts +25 -0
  143. package/dist/query/server.d.mts +55 -0
  144. package/dist/query/server.d.ts +55 -0
  145. package/dist/request-Cq5d6qmE.d.mts +6 -0
  146. package/dist/request-LoxDW3lp.d.ts +6 -0
  147. package/dist/request.d.mts +25 -0
  148. package/dist/request.d.ts +25 -0
  149. package/dist/resolver-DJqjLMg_.d.mts +14 -0
  150. package/dist/resolver-IH4RmPEl.d.ts +14 -0
  151. package/dist/route-runtime-DoOHzCAD.d.mts +38 -0
  152. package/dist/route-runtime-DoOHzCAD.d.ts +38 -0
  153. package/dist/router.d.mts +36 -0
  154. package/dist/router.d.ts +36 -0
  155. package/dist/routes.d.mts +226 -0
  156. package/dist/routes.d.ts +226 -0
  157. package/dist/runtime-BA9TOSu1.d.mts +231 -0
  158. package/dist/runtime-Cxpq6xZN.d.mts +27 -0
  159. package/dist/runtime-DTAQ2HDv.d.ts +231 -0
  160. package/dist/runtime-bv63eUiO.d.ts +27 -0
  161. package/dist/server-action-security.d.mts +45 -0
  162. package/dist/server-action-security.d.ts +45 -0
  163. package/dist/server-fn-client.d.mts +33 -0
  164. package/dist/server-fn-client.d.ts +33 -0
  165. package/dist/server-fn-error-DDh14a0V.d.mts +26 -0
  166. package/dist/server-fn-error-DDh14a0V.d.ts +26 -0
  167. package/dist/server-fn.d.mts +121 -0
  168. package/dist/server-fn.d.ts +121 -0
  169. package/dist/server-plugins.d.mts +57 -0
  170. package/dist/server-plugins.d.ts +57 -0
  171. package/dist/server-query-client.d.mts +51 -0
  172. package/dist/server-query-client.d.ts +51 -0
  173. package/dist/server-query.d.mts +37 -0
  174. package/dist/server-query.d.ts +37 -0
  175. package/dist/server.cjs +170 -3
  176. package/dist/server.cjs.map +1 -1
  177. package/dist/server.d.mts +51 -0
  178. package/dist/server.d.ts +51 -0
  179. package/dist/server.mjs +6 -6
  180. package/dist/storage.d.mts +52 -0
  181. package/dist/storage.d.ts +52 -0
  182. package/dist/testing.d.mts +103 -0
  183. package/dist/testing.d.ts +103 -0
  184. package/dist/transport-BmbGTXA5.d.mts +49 -0
  185. package/dist/transport-BmbGTXA5.d.ts +49 -0
  186. package/dist/types-BMxWr97v.d.mts +81 -0
  187. package/dist/types-BMxWr97v.d.ts +81 -0
  188. package/dist/types-D1A6-XvH.d.mts +73 -0
  189. package/dist/types-D1A6-XvH.d.ts +73 -0
  190. package/dist/types-DTzm4TCl.d.mts +78 -0
  191. package/dist/types-DTzm4TCl.d.ts +78 -0
  192. package/dist/utils-B6GaYNJL.d.ts +23 -0
  193. package/dist/utils-CKSHiip6.d.mts +23 -0
  194. package/dist/version.cjs +1 -1
  195. package/dist/version.cjs.map +1 -1
  196. package/dist/version.d.mts +3 -0
  197. package/dist/version.d.ts +3 -0
  198. package/dist/version.mjs +1 -1
  199. package/dist/vite.cjs +140 -2
  200. package/dist/vite.cjs.map +1 -1
  201. package/dist/vite.d.mts +24 -0
  202. package/dist/vite.d.ts +24 -0
  203. package/dist/vite.mjs +4 -4
  204. package/dist/workflows.d.mts +110 -0
  205. package/dist/workflows.d.ts +110 -0
  206. package/package.json +1 -1
  207. package/types/middleware.d.ts +36 -11
  208. package/dist/chunk-AN3PQVKH.mjs.map +0 -1
  209. package/dist/chunk-I4CUBGVF.mjs +0 -93
  210. package/dist/chunk-I4CUBGVF.mjs.map +0 -1
  211. package/dist/chunk-OSWV5IJB.mjs.map +0 -1
  212. package/dist/chunk-T2KL7VEL.mjs.map +0 -1
  213. package/dist/chunk-UXUAWNO5.mjs.map +0 -1
  214. /package/dist/{chunk-SLDBGSC3.mjs.map → chunk-JAEAE27K.mjs.map} +0 -0
  215. /package/dist/{devtools-E4YNCY5J.mjs.map → devtools-K2ERKGNI.mjs.map} +0 -0
@@ -32,6 +32,7 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
32
32
  var middleware_exports = {};
33
33
  __export(middleware_exports, {
34
34
  MiddlewareManager: () => MiddlewareManager,
35
+ UnsupportedRateLimitStorageError: () => UnsupportedRateLimitStorageError,
35
36
  _runWithMiddlewareContext: () => _runWithMiddlewareContext,
36
37
  _runWithMiddlewareData: () => _runWithMiddlewareData,
37
38
  applyProductionMiddlewareHeaders: () => applyProductionMiddlewareHeaders,
@@ -44,89 +45,76 @@ __export(middleware_exports, {
44
45
  getMiddlewareValue: () => getMiddlewareValue,
45
46
  getRateLimitStatus: () => getRateLimitStatus,
46
47
  hasMiddlewareData: () => hasMiddlewareData,
48
+ memoryRateLimitStorage: () => memoryRateLimitStorage,
47
49
  middleware: () => middleware,
48
50
  unwrapMiddleware: () => unwrapMiddleware
49
51
  });
50
52
  module.exports = __toCommonJS(middleware_exports);
51
53
 
52
- // src/storage/index.ts
53
- var import_unstorage = require("unstorage");
54
- var import_memory = __toESM(require("unstorage/drivers/memory"));
55
- function createMemoryStorage() {
56
- return (0, import_unstorage.createStorage)({
57
- driver: (0, import_memory.default)()
58
- });
59
- }
60
- __name(createMemoryStorage, "createMemoryStorage");
61
- var GLOBAL_STORAGE_KEY = /* @__PURE__ */ Symbol.for("farmjs.storage.global");
62
- function readGlobalStorage() {
63
- return globalThis[GLOBAL_STORAGE_KEY];
64
- }
65
- __name(readGlobalStorage, "readGlobalStorage");
66
- function writeGlobalStorage(storage) {
67
- globalThis[GLOBAL_STORAGE_KEY] = storage;
68
- return storage;
69
- }
70
- __name(writeGlobalStorage, "writeGlobalStorage");
71
- function getActiveGlobalStorage() {
72
- const existing = readGlobalStorage();
73
- if (existing) {
74
- return existing;
54
+ // src/middleware/chain.ts
55
+ var DEFAULT_MEMORY_RATE_LIMIT_ENTRIES = 1e5;
56
+ var _UnsupportedRateLimitStorageError = class _UnsupportedRateLimitStorageError extends TypeError {
57
+ constructor() {
58
+ super(
59
+ "RateLimitStorage must implement atomic increment(key, windowMs). Legacy get/set adapters can lose increments under concurrency. Use memoryRateLimitStorage() for one process or redisRateLimitStorage() from @farm.js/cache-redis for production."
60
+ );
61
+ this.name = "UnsupportedRateLimitStorageError";
75
62
  }
76
- return writeGlobalStorage(createMemoryStorage());
77
- }
78
- __name(getActiveGlobalStorage, "getActiveGlobalStorage");
79
- var globalStorage = getActiveGlobalStorage();
80
- function normalizeMountKey(base) {
81
- return (base || "").trim().replace(/^[:/\\]+|[:/\\]+$/g, "").replace(/[\\/]+/g, ":");
82
- }
83
- __name(normalizeMountKey, "normalizeMountKey");
84
- function getStorage(namespace) {
85
- globalStorage = getActiveGlobalStorage();
86
- const base = normalizeMountKey(namespace);
87
- if (!base) {
88
- return globalStorage;
63
+ };
64
+ __name(_UnsupportedRateLimitStorageError, "UnsupportedRateLimitStorageError");
65
+ var UnsupportedRateLimitStorageError = _UnsupportedRateLimitStorageError;
66
+ function memoryRateLimitStorage(options = {}) {
67
+ const maxEntries = options.maxEntries ?? DEFAULT_MEMORY_RATE_LIMIT_ENTRIES;
68
+ if (!Number.isSafeInteger(maxEntries) || maxEntries <= 0) {
69
+ throw new TypeError("memoryRateLimitStorage maxEntries must be a positive safe integer.");
70
+ }
71
+ const records = /* @__PURE__ */ new Map();
72
+ function read(key, now) {
73
+ const record = records.get(key);
74
+ if (!record) return null;
75
+ if (record.resetAt <= now) {
76
+ records.delete(key);
77
+ return null;
78
+ }
79
+ return record;
80
+ }
81
+ __name(read, "read");
82
+ function pruneExpired(now) {
83
+ for (const [key, record] of records) {
84
+ if (record.resetAt <= now) records.delete(key);
85
+ }
89
86
  }
90
- const namespaced = (0, import_unstorage.prefixStorage)(globalStorage, base);
87
+ __name(pruneExpired, "pruneExpired");
91
88
  return {
92
- ...namespaced,
93
- async clear() {
94
- const keys = await namespaced.getKeys();
95
- await Promise.all(keys.map((key) => namespaced.removeItem(key)));
89
+ increment(key, windowMs) {
90
+ if (!Number.isSafeInteger(windowMs) || windowMs <= 0) {
91
+ throw new TypeError("Rate-limit windowMs must be a positive safe integer.");
92
+ }
93
+ const now = Date.now();
94
+ const current = read(key, now);
95
+ if (current) {
96
+ const next2 = { count: current.count + 1, resetAt: current.resetAt };
97
+ records.set(key, next2);
98
+ return next2;
99
+ }
100
+ if (records.size >= maxEntries) pruneExpired(now);
101
+ if (records.size >= maxEntries) {
102
+ throw new Error(
103
+ `Process-local rate-limit storage reached its ${maxEntries} active-key capacity. Configure a shared production adapter or increase maxEntries.`
104
+ );
105
+ }
106
+ const next = { count: 1, resetAt: now + windowMs };
107
+ records.set(key, next);
108
+ return next;
109
+ },
110
+ get(key) {
111
+ const record = read(key, Date.now());
112
+ return record ? { ...record } : null;
96
113
  }
97
114
  };
98
115
  }
99
- __name(getStorage, "getStorage");
100
-
101
- // src/middleware/chain.ts
102
- function getRateLimitStorage() {
103
- return getStorage("ratelimit");
104
- }
105
- __name(getRateLimitStorage, "getRateLimitStorage");
106
- var defaultRateLimitStorage = {
107
- async get(key) {
108
- const storage = getRateLimitStorage();
109
- const value = await storage.getItem(key);
110
- return value ?? null;
111
- },
112
- async set(key, value, ttl) {
113
- const storage = getRateLimitStorage();
114
- await storage.setItem(key, value, ttl ? { ttl } : void 0);
115
- },
116
- async delete(key) {
117
- const storage = getRateLimitStorage();
118
- await storage.removeItem(key);
119
- },
120
- async ttl(key) {
121
- const storage = getRateLimitStorage();
122
- const record = await storage.getItem(key);
123
- if (!record || !record.resetAt) {
124
- return null;
125
- }
126
- const remainingMs = record.resetAt - Date.now();
127
- return remainingMs > 0 ? Math.ceil(remainingMs / 1e3) : null;
128
- }
129
- };
116
+ __name(memoryRateLimitStorage, "memoryRateLimitStorage");
117
+ var defaultRateLimitStorage = memoryRateLimitStorage();
130
118
  function parseTimeWindow(window) {
131
119
  const match = window.match(/^(\d+)(ms|s|m|h|d)$/);
132
120
  if (!match) throw new Error(`Invalid time window: ${window}`);
@@ -139,52 +127,73 @@ function parseTimeWindow(window) {
139
127
  h: 60 * 60 * 1e3,
140
128
  d: 24 * 60 * 60 * 1e3
141
129
  };
142
- return value * multipliers[unit];
130
+ const windowMs = value * multipliers[unit];
131
+ if (!Number.isSafeInteger(windowMs) || windowMs <= 0) {
132
+ throw new Error(`Invalid time window: ${window}`);
133
+ }
134
+ return windowMs;
143
135
  }
144
136
  __name(parseTimeWindow, "parseTimeWindow");
145
137
  function createRateLimitMiddleware(config) {
138
+ if (!Number.isSafeInteger(config.requests) || config.requests <= 0) {
139
+ throw new TypeError("Rate limit requests must be a positive safe integer.");
140
+ }
146
141
  const windowMs = parseTimeWindow(config.window);
147
142
  const storage = config.storage || defaultRateLimitStorage;
143
+ assertAtomicRateLimitStorage(storage);
148
144
  return async (ctx, next) => {
149
145
  const key = config.keyGenerator ? config.keyGenerator(ctx) : `${ctx.request.socket.remoteAddress}:${ctx.pathname}`;
146
+ const current = await storage.increment(key, windowMs);
147
+ assertRateLimitIncrementResult(current);
150
148
  const now = Date.now();
151
- const ttlSeconds = Math.ceil(windowMs / 1e3);
152
- const record = await storage.get(key);
153
- if (record && now > record.resetAt) {
154
- await storage.delete(key);
155
- }
156
- const current = await storage.get(key);
157
- if (!current) {
158
- await storage.set(
159
- key,
160
- {
161
- count: 1,
162
- resetAt: now + windowMs
163
- },
164
- ttlSeconds
165
- );
166
- return next();
167
- }
168
- if (current.count >= config.requests) {
149
+ const resetIn = Math.max(1, Math.ceil((current.resetAt - now) / 1e3));
150
+ const remaining = Math.max(0, config.requests - current.count);
151
+ setRateLimitHeaders(ctx, config.requests, remaining, resetIn, Math.ceil(windowMs / 1e3));
152
+ if (current.count > config.requests) {
153
+ setMiddlewareResponseHeader(ctx, "Retry-After", String(resetIn));
169
154
  if (config.onLimit) {
170
155
  const result = await config.onLimit(ctx);
171
- if (result) return;
156
+ if (result) return result;
172
157
  }
173
158
  ctx.json(
174
159
  {
175
160
  error: "Rate limit exceeded",
176
- retryAfter: Math.ceil((current.resetAt - now) / 1e3)
161
+ retryAfter: resetIn
177
162
  },
178
163
  429
179
164
  );
180
165
  return;
181
166
  }
182
- current.count++;
183
- await storage.set(key, current, ttlSeconds);
184
167
  return next();
185
168
  };
186
169
  }
187
170
  __name(createRateLimitMiddleware, "createRateLimitMiddleware");
171
+ function assertAtomicRateLimitStorage(storage) {
172
+ if (!storage || typeof storage.increment !== "function") {
173
+ throw new UnsupportedRateLimitStorageError();
174
+ }
175
+ }
176
+ __name(assertAtomicRateLimitStorage, "assertAtomicRateLimitStorage");
177
+ function assertRateLimitIncrementResult(result) {
178
+ if (!result || !Number.isSafeInteger(result.count) || result.count <= 0 || !Number.isFinite(result.resetAt) || result.resetAt <= 0) {
179
+ throw new TypeError(
180
+ "RateLimitStorage.increment() must return a positive integer count and a resetAt timestamp."
181
+ );
182
+ }
183
+ }
184
+ __name(assertRateLimitIncrementResult, "assertRateLimitIncrementResult");
185
+ function setRateLimitHeaders(ctx, limit, remaining, resetIn, windowSeconds) {
186
+ setMiddlewareResponseHeader(ctx, "RateLimit-Policy", `"farm";q=${limit};w=${windowSeconds}`);
187
+ setMiddlewareResponseHeader(ctx, "RateLimit", `"farm";r=${remaining};t=${resetIn}`);
188
+ }
189
+ __name(setRateLimitHeaders, "setRateLimitHeaders");
190
+ function setMiddlewareResponseHeader(ctx, name, value) {
191
+ ctx.headers.set(name, value);
192
+ if (!ctx.response.headersSent && !ctx.response.writableEnded) {
193
+ ctx.response.setHeader(name, value);
194
+ }
195
+ }
196
+ __name(setMiddlewareResponseHeader, "setMiddlewareResponseHeader");
188
197
  function matchPattern(pattern, pathname) {
189
198
  if (pattern instanceof RegExp) {
190
199
  return pattern.test(pathname);
@@ -334,6 +343,15 @@ var _MiddlewareChainImpl = class _MiddlewareChainImpl {
334
343
  __name(_MiddlewareChainImpl, "MiddlewareChainImpl");
335
344
  var MiddlewareChainImpl = _MiddlewareChainImpl;
336
345
  async function getRateLimitStatus(key, limit, storage = defaultRateLimitStorage) {
346
+ if (!Number.isSafeInteger(limit) || limit <= 0) {
347
+ throw new TypeError("Rate limit must be a positive safe integer.");
348
+ }
349
+ assertAtomicRateLimitStorage(storage);
350
+ if (typeof storage.get !== "function") {
351
+ throw new TypeError(
352
+ "getRateLimitStatus() requires a RateLimitStorage adapter that implements get(key)."
353
+ );
354
+ }
337
355
  const record = await storage.get(key);
338
356
  if (!record) {
339
357
  return {
@@ -345,6 +363,7 @@ async function getRateLimitStatus(key, limit, storage = defaultRateLimitStorage)
345
363
  isLimited: false
346
364
  };
347
365
  }
366
+ assertRateLimitIncrementResult(record);
348
367
  const now = Date.now();
349
368
  if (record.resetAt && now > record.resetAt) {
350
369
  return {
@@ -365,9 +384,6 @@ async function getRateLimitStatus(key, limit, storage = defaultRateLimitStorage)
365
384
  const remainingMs = record.resetAt - now;
366
385
  resetIn = remainingMs > 0 ? Math.ceil(remainingMs / 1e3) : null;
367
386
  resetAt = new Date(record.resetAt);
368
- } else if (storage.ttl) {
369
- resetIn = await storage.ttl(key);
370
- resetAt = resetIn ? new Date(now + resetIn * 1e3) : null;
371
387
  }
372
388
  return {
373
389
  requests,
@@ -2130,6 +2146,7 @@ __name(farmMiddlewarePlugin, "farmMiddlewarePlugin");
2130
2146
  // Annotate the CommonJS export names for ESM import in node:
2131
2147
  0 && (module.exports = {
2132
2148
  MiddlewareManager,
2149
+ UnsupportedRateLimitStorageError,
2133
2150
  _runWithMiddlewareContext,
2134
2151
  _runWithMiddlewareData,
2135
2152
  applyProductionMiddlewareHeaders,
@@ -2142,6 +2159,7 @@ __name(farmMiddlewarePlugin, "farmMiddlewarePlugin");
2142
2159
  getMiddlewareValue,
2143
2160
  getRateLimitStatus,
2144
2161
  hasMiddlewareData,
2162
+ memoryRateLimitStorage,
2145
2163
  middleware,
2146
2164
  unwrapMiddleware
2147
2165
  });