prefer type-only imports in testing utilities
This commit is contained in:
parent
e7015d4f8e
commit
b013649a41
8 changed files with 27 additions and 25 deletions
|
|
@ -3,8 +3,7 @@
|
||||||
* SPDX-License-Identifier: AGPL-3.0-only
|
* SPDX-License-Identifier: AGPL-3.0-only
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import { Inject, Injectable, OnApplicationShutdown } from '@nestjs/common';
|
import { Inject, Injectable, type OnApplicationShutdown } from '@nestjs/common';
|
||||||
import * as Redis from 'ioredis';
|
|
||||||
import {
|
import {
|
||||||
MemoryKVCache,
|
MemoryKVCache,
|
||||||
MemorySingleCache,
|
MemorySingleCache,
|
||||||
|
|
@ -26,6 +25,7 @@ import { DI } from '@/di-symbols.js';
|
||||||
import { TimeService, type TimerHandle } from '@/global/TimeService.js';
|
import { TimeService, type TimerHandle } from '@/global/TimeService.js';
|
||||||
import { InternalEventService } from '@/global/InternalEventService.js';
|
import { InternalEventService } from '@/global/InternalEventService.js';
|
||||||
import { callAllOn } from '@/misc/call-all.js';
|
import { callAllOn } from '@/misc/call-all.js';
|
||||||
|
import type * as Redis from 'ioredis';
|
||||||
|
|
||||||
// This is the one place that's *supposed* to new() up caches.
|
// This is the one place that's *supposed* to new() up caches.
|
||||||
/* eslint-disable no-restricted-syntax */
|
/* eslint-disable no-restricted-syntax */
|
||||||
|
|
|
||||||
|
|
@ -4,13 +4,14 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import { Inject, Injectable, OnApplicationShutdown } from '@nestjs/common';
|
import { Inject, Injectable, OnApplicationShutdown } from '@nestjs/common';
|
||||||
import Redis from 'ioredis';
|
|
||||||
import { DI } from '@/di-symbols.js';
|
import { DI } from '@/di-symbols.js';
|
||||||
|
import { bindThis } from '@/decorators.js';
|
||||||
import type { GlobalEvents, InternalEventTypes } from '@/core/GlobalEventService.js';
|
import type { GlobalEvents, InternalEventTypes } from '@/core/GlobalEventService.js';
|
||||||
import type { Config } from '@/config.js';
|
import type { Config } from '@/config.js';
|
||||||
import { bindThis } from '@/decorators.js';
|
import type Redis from 'ioredis';
|
||||||
|
|
||||||
export type Listener<K extends keyof InternalEventTypes> = (value: InternalEventTypes[K], key: K, isLocal: boolean) => void | Promise<void>;
|
export type EventTypes = InternalEventTypes;
|
||||||
|
export type Listener<K extends keyof EventTypes> = (value: EventTypes[K], key: K, isLocal: boolean) => void | Promise<void>;
|
||||||
|
|
||||||
export interface ListenerProps {
|
export interface ListenerProps {
|
||||||
ignoreLocal?: boolean,
|
ignoreLocal?: boolean,
|
||||||
|
|
@ -19,7 +20,7 @@ export interface ListenerProps {
|
||||||
|
|
||||||
@Injectable()
|
@Injectable()
|
||||||
export class InternalEventService implements OnApplicationShutdown {
|
export class InternalEventService implements OnApplicationShutdown {
|
||||||
private readonly listeners = new Map<keyof InternalEventTypes, Map<Listener<keyof InternalEventTypes>, ListenerProps>>();
|
private readonly listeners = new Map<keyof EventTypes, Map<Listener<keyof EventTypes>, ListenerProps>>();
|
||||||
|
|
||||||
constructor(
|
constructor(
|
||||||
@Inject(DI.redisForSub)
|
@Inject(DI.redisForSub)
|
||||||
|
|
@ -35,7 +36,7 @@ export class InternalEventService implements OnApplicationShutdown {
|
||||||
}
|
}
|
||||||
|
|
||||||
@bindThis
|
@bindThis
|
||||||
public on<K extends keyof InternalEventTypes>(type: K, listener: Listener<K>, props?: ListenerProps): void {
|
public on<K extends keyof EventTypes>(type: K, listener: Listener<K>, props?: ListenerProps): void {
|
||||||
let set = this.listeners.get(type);
|
let set = this.listeners.get(type);
|
||||||
if (!set) {
|
if (!set) {
|
||||||
set = new Map();
|
set = new Map();
|
||||||
|
|
@ -43,16 +44,16 @@ export class InternalEventService implements OnApplicationShutdown {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Functionally, this is just a set with metadata on the values.
|
// Functionally, this is just a set with metadata on the values.
|
||||||
set.set(listener as Listener<keyof InternalEventTypes>, props ?? {});
|
set.set(listener as Listener<keyof EventTypes>, props ?? {});
|
||||||
}
|
}
|
||||||
|
|
||||||
@bindThis
|
@bindThis
|
||||||
public off<K extends keyof InternalEventTypes>(type: K, listener: Listener<K>): void {
|
public off<K extends keyof EventTypes>(type: K, listener: Listener<K>): void {
|
||||||
this.listeners.get(type)?.delete(listener as Listener<keyof InternalEventTypes>);
|
this.listeners.get(type)?.delete(listener as Listener<keyof EventTypes>);
|
||||||
}
|
}
|
||||||
|
|
||||||
@bindThis
|
@bindThis
|
||||||
public async emit<K extends keyof InternalEventTypes>(type: K, value: InternalEventTypes[K]): Promise<void> {
|
public async emit<K extends keyof EventTypes>(type: K, value: EventTypes[K]): Promise<void> {
|
||||||
await this.emitInternal(type, value, true);
|
await this.emitInternal(type, value, true);
|
||||||
await this.redisForPub.publish(this.config.host, JSON.stringify({
|
await this.redisForPub.publish(this.config.host, JSON.stringify({
|
||||||
channel: 'internal',
|
channel: 'internal',
|
||||||
|
|
@ -61,7 +62,7 @@ export class InternalEventService implements OnApplicationShutdown {
|
||||||
}
|
}
|
||||||
|
|
||||||
@bindThis
|
@bindThis
|
||||||
private async emitInternal<K extends keyof InternalEventTypes>(type: K, value: InternalEventTypes[K], isLocal: boolean): Promise<void> {
|
private async emitInternal<K extends keyof EventTypes>(type: K, value: EventTypes[K], isLocal: boolean): Promise<void> {
|
||||||
const listeners = this.listeners.get(type);
|
const listeners = this.listeners.get(type);
|
||||||
if (!listeners) {
|
if (!listeners) {
|
||||||
return;
|
return;
|
||||||
|
|
@ -84,7 +85,7 @@ export class InternalEventService implements OnApplicationShutdown {
|
||||||
if (obj.channel === 'internal') {
|
if (obj.channel === 'internal') {
|
||||||
const { type, body } = obj.message as GlobalEvents['internal']['payload'];
|
const { type, body } = obj.message as GlobalEvents['internal']['payload'];
|
||||||
if (!isLocalInternalEvent(body) || body._pid !== process.pid) {
|
if (!isLocalInternalEvent(body) || body._pid !== process.pid) {
|
||||||
await this.emitInternal(type, body as InternalEventTypes[keyof InternalEventTypes], false);
|
await this.emitInternal(type, body as EventTypes[keyof EventTypes], false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -3,7 +3,7 @@
|
||||||
* SPDX-License-Identifier: AGPL-3.0-only
|
* SPDX-License-Identifier: AGPL-3.0-only
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import { Injectable, OnApplicationShutdown } from '@nestjs/common';
|
import { Injectable, type OnApplicationShutdown } from '@nestjs/common';
|
||||||
import { bindThis } from '@/decorators.js';
|
import { bindThis } from '@/decorators.js';
|
||||||
|
|
||||||
const timerTokenSymbol = Symbol('timerToken');
|
const timerTokenSymbol = Symbol('timerToken');
|
||||||
|
|
|
||||||
|
|
@ -3,9 +3,9 @@
|
||||||
* SPDX-License-Identifier: AGPL-3.0-only
|
* SPDX-License-Identifier: AGPL-3.0-only
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import * as Redis from 'ioredis';
|
import type * as Redis from 'ioredis';
|
||||||
import { bindThis } from '@/decorators.js';
|
import { bindThis } from '@/decorators.js';
|
||||||
import { TimeService } from '@/global/TimeService.js';
|
import type { TimeService } from '@/global/TimeService.js';
|
||||||
|
|
||||||
export interface RedisCacheServices extends MemoryCacheServices {
|
export interface RedisCacheServices extends MemoryCacheServices {
|
||||||
readonly redisClient: Redis.Redis
|
readonly redisClient: Redis.Redis
|
||||||
|
|
|
||||||
|
|
@ -3,11 +3,11 @@
|
||||||
* SPDX-License-Identifier: AGPL-3.0-only
|
* SPDX-License-Identifier: AGPL-3.0-only
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import * as Redis from 'ioredis';
|
|
||||||
import { Injectable } from '@nestjs/common';
|
import { Injectable } from '@nestjs/common';
|
||||||
import { GodOfTimeService } from './GodOfTimeService.js';
|
import { GodOfTimeService } from './GodOfTimeService.js';
|
||||||
import { MockInternalEventService } from './MockInternalEventService.js';
|
import { MockInternalEventService } from './MockInternalEventService.js';
|
||||||
import { MockRedis } from './MockRedis.js';
|
import { MockRedis } from './MockRedis.js';
|
||||||
|
import type * as Redis from 'ioredis';
|
||||||
import type { QuantumKVOpts } from '@/misc/QuantumKVCache.js';
|
import type { QuantumKVOpts } from '@/misc/QuantumKVCache.js';
|
||||||
import type { RedisKVCacheOpts, RedisSingleCacheOpts, MemoryCacheOpts } from '@/misc/cache.js';
|
import type { RedisKVCacheOpts, RedisSingleCacheOpts, MemoryCacheOpts } from '@/misc/cache.js';
|
||||||
import type { TimeService } from '@/global/TimeService.js';
|
import type { TimeService } from '@/global/TimeService.js';
|
||||||
|
|
|
||||||
|
|
@ -3,7 +3,8 @@
|
||||||
* SPDX-License-Identifier: AGPL-3.0-only
|
* SPDX-License-Identifier: AGPL-3.0-only
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import * as Redis from 'ioredis';
|
import { Redis as RedisConstructor } from 'ioredis';
|
||||||
|
import type * as Redis from 'ioredis';
|
||||||
|
|
||||||
export type RedisKey = Redis.RedisKey;
|
export type RedisKey = Redis.RedisKey;
|
||||||
export type RedisString = Buffer | string;
|
export type RedisString = Buffer | string;
|
||||||
|
|
@ -14,7 +15,7 @@ export type RedisCallback<T = unknown> = Redis.Callback<T>;
|
||||||
export type Ok = 'OK';
|
export type Ok = 'OK';
|
||||||
export const ok = 'OK' as const;
|
export const ok = 'OK' as const;
|
||||||
|
|
||||||
export type FakeRedis = Redis.Redis;
|
export type FakeRedis = RedisConstructor;
|
||||||
export interface FakeRedisConstructor {
|
export interface FakeRedisConstructor {
|
||||||
new (): FakeRedis;
|
new (): FakeRedis;
|
||||||
}
|
}
|
||||||
|
|
@ -25,7 +26,7 @@ export interface FakeRedisConstructor {
|
||||||
export const FakeRedis: FakeRedisConstructor = createFakeRedis();
|
export const FakeRedis: FakeRedisConstructor = createFakeRedis();
|
||||||
|
|
||||||
function createFakeRedis(): FakeRedisConstructor {
|
function createFakeRedis(): FakeRedisConstructor {
|
||||||
class FakeRedis implements Partial<Redis.Redis> {
|
class FakeRedis implements Partial<RedisConstructor> {
|
||||||
async connect(callback?: RedisCallback<void>): Promise<void> {
|
async connect(callback?: RedisCallback<void>): Promise<void> {
|
||||||
// no-op
|
// no-op
|
||||||
callback?.(null);
|
callback?.(null);
|
||||||
|
|
@ -71,8 +72,8 @@ function createFakeRedis(): FakeRedisConstructor {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const fakeProto = FakeRedis.prototype as Partial<Redis.Redis>;
|
const fakeProto = FakeRedis.prototype as Partial<RedisConstructor>;
|
||||||
const redisProto = Redis.Redis.prototype as Partial<Redis.Redis>;
|
const redisProto = RedisConstructor.prototype as Partial<RedisConstructor>;
|
||||||
|
|
||||||
// Override all methods and accessors from Redis
|
// Override all methods and accessors from Redis
|
||||||
for (const [key, property] of allProps(redisProto)) {
|
for (const [key, property] of allProps(redisProto)) {
|
||||||
|
|
@ -102,7 +103,7 @@ function createFakeRedis(): FakeRedisConstructor {
|
||||||
|
|
||||||
// test
|
// test
|
||||||
const test = new FakeRedis();
|
const test = new FakeRedis();
|
||||||
if (!(test instanceof Redis.Redis)) {
|
if (!(test instanceof RedisConstructor)) {
|
||||||
throw new Error('failed to extend');
|
throw new Error('failed to extend');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -4,7 +4,7 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import { Injectable } from '@nestjs/common';
|
import { Injectable } from '@nestjs/common';
|
||||||
import { TimeService, Timer } from '@/global/TimeService.js';
|
import { TimeService, type Timer } from '@/global/TimeService.js';
|
||||||
import { addPatch, type DatePatch } from '@/misc/patch-date.js';
|
import { addPatch, type DatePatch } from '@/misc/patch-date.js';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
||||||
|
|
@ -7,7 +7,7 @@ import { Injectable } from '@nestjs/common';
|
||||||
import { FakeRedis, ok, type RedisString } from './FakeRedis.js';
|
import { FakeRedis, ok, type RedisString } from './FakeRedis.js';
|
||||||
import type { RedisKey, RedisNumber, RedisValue, RedisCallback, Ok } from './FakeRedis.js';
|
import type { RedisKey, RedisNumber, RedisValue, RedisCallback, Ok } from './FakeRedis.js';
|
||||||
import type { ChainableCommander } from 'ioredis';
|
import type { ChainableCommander } from 'ioredis';
|
||||||
import { TimeService, NativeTimeService } from '@/global/TimeService.js';
|
import { NativeTimeService, type TimeService } from '@/global/TimeService.js';
|
||||||
import { bindThis } from '@/decorators.js';
|
import { bindThis } from '@/decorators.js';
|
||||||
|
|
||||||
export interface MockRedisConstructor {
|
export interface MockRedisConstructor {
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue