halt-rate 0.3.0 → 0.4.0
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/README.md +9 -1
- package/dist/adapters/fastify.d.mts +29 -0
- package/dist/adapters/fastify.d.ts +29 -0
- package/dist/adapters/fastify.js +38 -0
- package/dist/adapters/fastify.js.map +1 -0
- package/dist/adapters/fastify.mjs +35 -0
- package/dist/adapters/fastify.mjs.map +1 -0
- package/dist/adapters/graphql.d.mts +22 -0
- package/dist/adapters/graphql.d.ts +22 -0
- package/dist/adapters/graphql.js +51 -0
- package/dist/adapters/graphql.js.map +1 -0
- package/dist/adapters/graphql.mjs +49 -0
- package/dist/adapters/graphql.mjs.map +1 -0
- package/dist/adapters/hono.d.mts +30 -0
- package/dist/adapters/hono.d.ts +30 -0
- package/dist/adapters/hono.js +56 -0
- package/dist/adapters/hono.js.map +1 -0
- package/dist/adapters/hono.mjs +54 -0
- package/dist/adapters/hono.mjs.map +1 -0
- package/dist/adapters/next.js +3 -2
- package/dist/adapters/next.js.map +1 -1
- package/dist/adapters/next.mjs +3 -2
- package/dist/adapters/next.mjs.map +1 -1
- package/dist/index.d.mts +49 -1
- package/dist/index.d.ts +49 -1
- package/dist/index.js +69 -2
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +68 -3
- package/dist/index.mjs.map +1 -1
- package/package.json +66 -11
package/dist/index.mjs
CHANGED
|
@@ -484,7 +484,8 @@ var RateLimiter = class {
|
|
|
484
484
|
return decision2;
|
|
485
485
|
}
|
|
486
486
|
const store = this.store;
|
|
487
|
-
|
|
487
|
+
const cacheKey = `${policy.name}|${policy.algorithm}|${policy.limit}|${policy.window}|${policy.burst}`;
|
|
488
|
+
let algorithm = this.algorithmCache.get(cacheKey);
|
|
488
489
|
if (!algorithm) {
|
|
489
490
|
if (policy.algorithm === "token_bucket" /* TOKEN_BUCKET */) {
|
|
490
491
|
algorithm = new TokenBucket(policy.burst, policy.limit, policy.window);
|
|
@@ -498,7 +499,7 @@ var RateLimiter = class {
|
|
|
498
499
|
} else {
|
|
499
500
|
throw new Error(`Algorithm ${policy.algorithm} not implemented`);
|
|
500
501
|
}
|
|
501
|
-
this.algorithmCache.set(
|
|
502
|
+
this.algorithmCache.set(cacheKey, algorithm);
|
|
502
503
|
}
|
|
503
504
|
const span = this.otelTracer?.startSpan?.("halt.check", { attributes: { policy: policy.name, key } });
|
|
504
505
|
const state = store.get(storageKey);
|
|
@@ -1093,6 +1094,70 @@ function getPlanPolicy(planName) {
|
|
|
1093
1094
|
return PLAN_TIERS[normalized];
|
|
1094
1095
|
}
|
|
1095
1096
|
|
|
1097
|
+
// src/core/registry.ts
|
|
1098
|
+
var PolicyRegistry = class {
|
|
1099
|
+
constructor(initial = []) {
|
|
1100
|
+
this.policies = /* @__PURE__ */ new Map();
|
|
1101
|
+
for (const p of initial) this.register(p);
|
|
1102
|
+
}
|
|
1103
|
+
/** Add or replace a policy (keyed by `policy.name`). */
|
|
1104
|
+
register(policy) {
|
|
1105
|
+
this.policies.set(policy.name, policy);
|
|
1106
|
+
return this;
|
|
1107
|
+
}
|
|
1108
|
+
get(name) {
|
|
1109
|
+
return this.policies.get(name);
|
|
1110
|
+
}
|
|
1111
|
+
has(name) {
|
|
1112
|
+
return this.policies.has(name);
|
|
1113
|
+
}
|
|
1114
|
+
/** Mutate fields of an existing policy at runtime (e.g. `{ limit: 500 }`). */
|
|
1115
|
+
update(name, patch) {
|
|
1116
|
+
const existing = this.policies.get(name);
|
|
1117
|
+
if (!existing) throw new Error(`Unknown policy: ${name}`);
|
|
1118
|
+
const updated = { ...existing, ...patch, name: existing.name };
|
|
1119
|
+
if (patch.limit !== void 0 && patch.burst === void 0) {
|
|
1120
|
+
delete updated.burst;
|
|
1121
|
+
}
|
|
1122
|
+
this.policies.set(name, updated);
|
|
1123
|
+
return updated;
|
|
1124
|
+
}
|
|
1125
|
+
remove(name) {
|
|
1126
|
+
return this.policies.delete(name);
|
|
1127
|
+
}
|
|
1128
|
+
list() {
|
|
1129
|
+
return [...this.policies.values()];
|
|
1130
|
+
}
|
|
1131
|
+
/**
|
|
1132
|
+
* Build a resolver for the limiter's `policy` option.
|
|
1133
|
+
* @param selector maps a request to a registered policy name.
|
|
1134
|
+
*/
|
|
1135
|
+
resolver(selector) {
|
|
1136
|
+
return (request) => {
|
|
1137
|
+
const name = selector(request);
|
|
1138
|
+
const policy = this.policies.get(name);
|
|
1139
|
+
if (!policy) throw new Error(`Unknown policy: ${name}`);
|
|
1140
|
+
return policy;
|
|
1141
|
+
};
|
|
1142
|
+
}
|
|
1143
|
+
};
|
|
1144
|
+
function cachedPolicyResolver(loader, options = {}) {
|
|
1145
|
+
const ttlMs = options.ttlMs ?? 5e3;
|
|
1146
|
+
const keyFn = options.key ?? (() => "__default__");
|
|
1147
|
+
const cache = /* @__PURE__ */ new Map();
|
|
1148
|
+
return async (request) => {
|
|
1149
|
+
const key = keyFn(request);
|
|
1150
|
+
const now = Date.now();
|
|
1151
|
+
const hit = cache.get(key);
|
|
1152
|
+
if (hit && hit.expires > now) {
|
|
1153
|
+
return hit.policy;
|
|
1154
|
+
}
|
|
1155
|
+
const policy = await loader(request);
|
|
1156
|
+
cache.set(key, { policy, expires: now + ttlMs });
|
|
1157
|
+
return policy;
|
|
1158
|
+
};
|
|
1159
|
+
}
|
|
1160
|
+
|
|
1096
1161
|
// src/core/quota.ts
|
|
1097
1162
|
var QuotaPeriod = /* @__PURE__ */ ((QuotaPeriod2) => {
|
|
1098
1163
|
QuotaPeriod2["HOURLY"] = "hourly";
|
|
@@ -1611,6 +1676,6 @@ var OpenTelemetryMetrics = class {
|
|
|
1611
1676
|
}
|
|
1612
1677
|
};
|
|
1613
1678
|
|
|
1614
|
-
export { Algorithm, CompositeTelemetry, InMemoryStore, KeyStrategy, LoggingTelemetry, MetricsTelemetry, OpenTelemetryMetrics, PENALTY_LENIENT, PENALTY_MODERATE, PENALTY_STRICT, PenaltyManager, QUOTA_ENTERPRISE_MONTHLY, QUOTA_FREE_DAILY, QUOTA_FREE_MONTHLY, QUOTA_PRO_DAILY, QUOTA_PRO_MONTHLY, QuotaManager, QuotaPeriod, RateLimiter, RedisStore, StatsCollector, extractors_exports as extractors, isAtomicStore, normalizePolicy, presets_exports as presets, toHeaders };
|
|
1679
|
+
export { Algorithm, CompositeTelemetry, InMemoryStore, KeyStrategy, LoggingTelemetry, MetricsTelemetry, OpenTelemetryMetrics, PENALTY_LENIENT, PENALTY_MODERATE, PENALTY_STRICT, PenaltyManager, PolicyRegistry, QUOTA_ENTERPRISE_MONTHLY, QUOTA_FREE_DAILY, QUOTA_FREE_MONTHLY, QUOTA_PRO_DAILY, QUOTA_PRO_MONTHLY, QuotaManager, QuotaPeriod, RateLimiter, RedisStore, StatsCollector, cachedPolicyResolver, extractors_exports as extractors, isAtomicStore, normalizePolicy, presets_exports as presets, toHeaders };
|
|
1615
1680
|
//# sourceMappingURL=index.mjs.map
|
|
1616
1681
|
//# sourceMappingURL=index.mjs.map
|