mirror of
https://github.com/fluxerapp/fluxer
synced 2026-10-17 21:15:32 +09:00
refactor(pkgs): share vitest config and dedupe helpers (#3384)
This commit is contained in:
1 parent
5695510980
commit
575a5adbef
43 files changed
+172
-874
No files matched your search
@@ -1,18 +0,0 @@
|
||||
// SPDX-License-Identifier: AGPL-3.0-or-later
|
||||
|
||||
import type {LimitKey} from '@fluxer/constants/src/LimitConfigMetadata';
|
||||
import type {LimitConfigSnapshot, LimitConfigWireFormat} from '@fluxer/limits/src/LimitTypes';
|
||||
|
||||
export interface LimitConfigCodecOptions {
|
||||
defaults?: Record<LimitKey, number>;
|
||||
defaultsHash?: string;
|
||||
}
|
||||
|
||||
export interface ILimitConfigCodec {
|
||||
computeOverrides(
|
||||
fullLimits: Partial<Record<LimitKey, number>>,
|
||||
defaults: Record<LimitKey, number>,
|
||||
): Partial<Record<LimitKey, number>>;
|
||||
toWireFormat(config: LimitConfigSnapshot, options?: LimitConfigCodecOptions): LimitConfigWireFormat;
|
||||
fromWireFormat(wireFormat: LimitConfigWireFormat, options?: LimitConfigCodecOptions): LimitConfigSnapshot;
|
||||
}
|
||||
@@ -1,9 +0,0 @@
|
||||
// SPDX-License-Identifier: AGPL-3.0-or-later
|
||||
|
||||
import type {LimitKey} from '@fluxer/constants/src/LimitConfigMetadata';
|
||||
import type {LimitEvaluationOptions, LimitEvaluationResult, LimitMatchContext} from '@fluxer/limits/src/LimitTypes';
|
||||
|
||||
export interface ILimitEvaluator {
|
||||
resolveAll(ctx: LimitMatchContext, options?: LimitEvaluationOptions): LimitEvaluationResult;
|
||||
resolveOne(ctx: LimitMatchContext, key: LimitKey, options?: LimitEvaluationOptions): number;
|
||||
}
|
||||
@@ -1,88 +0,0 @@
|
||||
// SPDX-License-Identifier: AGPL-3.0-or-later
|
||||
|
||||
import {LIMIT_KEYS, type LimitKey} from '@fluxer/constants/src/LimitConfigMetadata';
|
||||
import type {ILimitConfigCodec, LimitConfigCodecOptions} from '@fluxer/limits/src/ILimitConfigCodec';
|
||||
import {DEFAULT_FREE_LIMITS} from '@fluxer/limits/src/LimitDefaults';
|
||||
import {computeDefaultsHash} from '@fluxer/limits/src/LimitHashing';
|
||||
import type {LimitConfigSnapshot, LimitConfigWireFormat} from '@fluxer/limits/src/LimitTypes';
|
||||
|
||||
const WIRE_COMPATIBILITY_LIMIT_KEYS: ReadonlySet<LimitKey> = new Set<LimitKey>([
|
||||
'max_guild_emojis',
|
||||
'max_guild_emojis_animated_more',
|
||||
'max_guild_emojis_animated',
|
||||
'max_guild_emojis_static_more',
|
||||
'max_guild_emojis_static',
|
||||
'max_guild_stickers_more',
|
||||
'max_guild_stickers',
|
||||
]);
|
||||
|
||||
export class LimitConfigCodec implements ILimitConfigCodec {
|
||||
computeOverrides(
|
||||
fullLimits: Partial<Record<LimitKey, number>>,
|
||||
defaults: Record<LimitKey, number>,
|
||||
): Partial<Record<LimitKey, number>> {
|
||||
const overrides: Partial<Record<LimitKey, number>> = {};
|
||||
for (const key of LIMIT_KEYS) {
|
||||
const value = fullLimits[key];
|
||||
if (value === undefined) {
|
||||
continue;
|
||||
}
|
||||
if (value !== defaults[key]) {
|
||||
overrides[key] = value;
|
||||
}
|
||||
}
|
||||
return overrides;
|
||||
}
|
||||
|
||||
private addWireCompatibilityOverrides(
|
||||
overrides: Partial<Record<LimitKey, number>>,
|
||||
fullLimits: Partial<Record<LimitKey, number>>,
|
||||
): Partial<Record<LimitKey, number>> {
|
||||
for (const key of WIRE_COMPATIBILITY_LIMIT_KEYS) {
|
||||
const value = fullLimits[key];
|
||||
if (value !== undefined) {
|
||||
overrides[key] = value;
|
||||
}
|
||||
}
|
||||
return overrides;
|
||||
}
|
||||
|
||||
toWireFormat(config: LimitConfigSnapshot, options?: LimitConfigCodecOptions): LimitConfigWireFormat {
|
||||
const defaults = options?.defaults ?? DEFAULT_FREE_LIMITS;
|
||||
const defaultsHash = options?.defaultsHash ?? computeDefaultsHash();
|
||||
const rules = config.rules.map((rule) => {
|
||||
const overrides = this.addWireCompatibilityOverrides(this.computeOverrides(rule.limits, defaults), rule.limits);
|
||||
return {
|
||||
id: rule.id,
|
||||
filters: rule.filters,
|
||||
overrides,
|
||||
};
|
||||
});
|
||||
return {
|
||||
version: 2,
|
||||
traitDefinitions: config.traitDefinitions,
|
||||
rules,
|
||||
defaultsHash,
|
||||
};
|
||||
}
|
||||
|
||||
fromWireFormat(wireFormat: LimitConfigWireFormat, options?: LimitConfigCodecOptions): LimitConfigSnapshot {
|
||||
const defaults = options?.defaults ?? DEFAULT_FREE_LIMITS;
|
||||
const rules = wireFormat.rules.map((rule) => {
|
||||
const limits: Partial<Record<LimitKey, number>> = {
|
||||
...defaults,
|
||||
...rule.overrides,
|
||||
};
|
||||
return {
|
||||
id: rule.id,
|
||||
filters: rule.filters,
|
||||
limits,
|
||||
};
|
||||
});
|
||||
return {
|
||||
version: wireFormat.version,
|
||||
traitDefinitions: wireFormat.traitDefinitions,
|
||||
rules,
|
||||
};
|
||||
}
|
||||
}
|
||||
@@ -1,22 +1,76 @@
|
||||
// SPDX-License-Identifier: AGPL-3.0-or-later
|
||||
|
||||
import type {LimitKey} from '@fluxer/constants/src/LimitConfigMetadata';
|
||||
import {LimitConfigCodec} from '@fluxer/limits/src/LimitConfigCodec';
|
||||
import {LIMIT_KEYS, type LimitKey} from '@fluxer/constants/src/LimitConfigMetadata';
|
||||
import {DEFAULT_FREE_LIMITS} from '@fluxer/limits/src/LimitDefaults';
|
||||
import {computeDefaultsHash} from '@fluxer/limits/src/LimitHashing';
|
||||
import type {LimitConfigSnapshot, LimitConfigWireFormat} from '@fluxer/limits/src/LimitTypes';
|
||||
|
||||
const defaultLimitConfigCodec = new LimitConfigCodec();
|
||||
const WIRE_COMPATIBILITY_LIMIT_KEYS: ReadonlySet<LimitKey> = new Set<LimitKey>([
|
||||
'max_guild_emojis',
|
||||
'max_guild_emojis_animated_more',
|
||||
'max_guild_emojis_animated',
|
||||
'max_guild_emojis_static_more',
|
||||
'max_guild_emojis_static',
|
||||
'max_guild_stickers_more',
|
||||
'max_guild_stickers',
|
||||
]);
|
||||
|
||||
export function computeOverrides(
|
||||
fullLimits: Partial<Record<LimitKey, number>>,
|
||||
defaults: Record<LimitKey, number>,
|
||||
): Partial<Record<LimitKey, number>> {
|
||||
return defaultLimitConfigCodec.computeOverrides(fullLimits, defaults);
|
||||
const overrides: Partial<Record<LimitKey, number>> = {};
|
||||
for (const key of LIMIT_KEYS) {
|
||||
const value = fullLimits[key];
|
||||
if (value === undefined) {
|
||||
continue;
|
||||
}
|
||||
if (value !== defaults[key]) {
|
||||
overrides[key] = value;
|
||||
}
|
||||
}
|
||||
return overrides;
|
||||
}
|
||||
|
||||
export function computeWireFormat(config: LimitConfigSnapshot): LimitConfigWireFormat {
|
||||
return defaultLimitConfigCodec.toWireFormat(config);
|
||||
const defaultsHash = computeDefaultsHash();
|
||||
const rules = config.rules.map((rule) => {
|
||||
const overrides = computeOverrides(rule.limits, DEFAULT_FREE_LIMITS);
|
||||
for (const key of WIRE_COMPATIBILITY_LIMIT_KEYS) {
|
||||
const value = rule.limits[key];
|
||||
if (value !== undefined) {
|
||||
overrides[key] = value;
|
||||
}
|
||||
}
|
||||
return {
|
||||
id: rule.id,
|
||||
filters: rule.filters,
|
||||
overrides,
|
||||
};
|
||||
});
|
||||
return {
|
||||
version: 2,
|
||||
traitDefinitions: config.traitDefinitions,
|
||||
rules,
|
||||
defaultsHash,
|
||||
};
|
||||
}
|
||||
|
||||
export function expandWireFormat(wireFormat: LimitConfigWireFormat): LimitConfigSnapshot {
|
||||
return defaultLimitConfigCodec.fromWireFormat(wireFormat);
|
||||
const rules = wireFormat.rules.map((rule) => {
|
||||
const limits: Partial<Record<LimitKey, number>> = {
|
||||
...DEFAULT_FREE_LIMITS,
|
||||
...rule.overrides,
|
||||
};
|
||||
return {
|
||||
id: rule.id,
|
||||
filters: rule.filters,
|
||||
limits,
|
||||
};
|
||||
});
|
||||
return {
|
||||
version: wireFormat.version,
|
||||
traitDefinitions: wireFormat.traitDefinitions,
|
||||
rules,
|
||||
};
|
||||
}
|
||||
@@ -1,40 +0,0 @@
|
||||
// SPDX-License-Identifier: AGPL-3.0-or-later
|
||||
|
||||
import type {LimitKey} from '@fluxer/constants/src/LimitConfigMetadata';
|
||||
import type {ILimitEvaluator} from '@fluxer/limits/src/ILimitEvaluator';
|
||||
import {DEFAULT_FREE_LIMITS} from '@fluxer/limits/src/LimitDefaults';
|
||||
import {applyRuleToResolvedLimits, ruleMatches, sortRulesBySpecificity} from '@fluxer/limits/src/LimitRuleRuntime';
|
||||
import type {
|
||||
LimitConfigSnapshot,
|
||||
LimitEvaluationOptions,
|
||||
LimitEvaluationResult,
|
||||
LimitMatchContext,
|
||||
LimitRule,
|
||||
} from '@fluxer/limits/src/LimitTypes';
|
||||
|
||||
export class LimitEvaluator implements ILimitEvaluator {
|
||||
private readonly sortedRules: Array<LimitRule>;
|
||||
|
||||
constructor(snapshot: LimitConfigSnapshot) {
|
||||
this.sortedRules = sortRulesBySpecificity(snapshot.rules);
|
||||
}
|
||||
|
||||
resolveAll(ctx: LimitMatchContext, options?: LimitEvaluationOptions): LimitEvaluationResult {
|
||||
const evaluationContext = options?.evaluationContext ?? 'user';
|
||||
const baseLimits = options?.baseLimits ?? DEFAULT_FREE_LIMITS;
|
||||
const resolvedLimits = {...baseLimits};
|
||||
for (const rule of this.sortedRules) {
|
||||
if (!ruleMatches(rule.filters, ctx)) {
|
||||
continue;
|
||||
}
|
||||
applyRuleToResolvedLimits(resolvedLimits, rule, evaluationContext);
|
||||
}
|
||||
return {
|
||||
limits: resolvedLimits,
|
||||
};
|
||||
}
|
||||
|
||||
resolveOne(ctx: LimitMatchContext, key: LimitKey, options?: LimitEvaluationOptions): number {
|
||||
return this.resolveAll(ctx, options).limits[key];
|
||||
}
|
||||
}
|
||||
@@ -1,8 +1,8 @@
|
||||
// SPDX-License-Identifier: AGPL-3.0-or-later
|
||||
|
||||
import type {LimitKey} from '@fluxer/constants/src/LimitConfigMetadata';
|
||||
import type {ILimitEvaluator} from '@fluxer/limits/src/ILimitEvaluator';
|
||||
import {LimitEvaluator} from '@fluxer/limits/src/LimitEvaluator';
|
||||
import {DEFAULT_FREE_LIMITS} from '@fluxer/limits/src/LimitDefaults';
|
||||
import {applyRuleToResolvedLimits, ruleMatches, sortRulesBySpecificity} from '@fluxer/limits/src/LimitRuleRuntime';
|
||||
import type {
|
||||
LimitConfigSnapshot,
|
||||
LimitEvaluationOptions,
|
||||
@@ -10,17 +10,19 @@ import type {
|
||||
LimitMatchContext,
|
||||
} from '@fluxer/limits/src/LimitTypes';
|
||||
|
||||
export function createLimitEvaluator(snapshot: LimitConfigSnapshot): ILimitEvaluator {
|
||||
return new LimitEvaluator(snapshot);
|
||||
}
|
||||
|
||||
export function resolveLimits(
|
||||
snapshot: LimitConfigSnapshot,
|
||||
ctx: LimitMatchContext,
|
||||
options?: LimitEvaluationOptions,
|
||||
): LimitEvaluationResult {
|
||||
const evaluator = createLimitEvaluator(snapshot);
|
||||
return evaluator.resolveAll(ctx, options);
|
||||
const evaluationContext = options?.evaluationContext ?? 'user';
|
||||
const resolvedLimits = {...(options?.baseLimits ?? DEFAULT_FREE_LIMITS)};
|
||||
for (const rule of sortRulesBySpecificity(snapshot.rules)) {
|
||||
if (ruleMatches(rule.filters, ctx)) {
|
||||
applyRuleToResolvedLimits(resolvedLimits, rule, evaluationContext);
|
||||
}
|
||||
}
|
||||
return {limits: resolvedLimits};
|
||||
}
|
||||
|
||||
export function resolveLimit(
|
||||
@@ -29,6 +31,5 @@ export function resolveLimit(
|
||||
key: LimitKey,
|
||||
options?: LimitEvaluationOptions,
|
||||
): number {
|
||||
const evaluator = createLimitEvaluator(snapshot);
|
||||
return evaluator.resolveOne(ctx, key, options);
|
||||
return resolveLimits(snapshot, ctx, options).limits[key];
|
||||
}
|
||||
Reference in new issue
Block a user