Skip to content

Commit c169849

Browse files
Merge pull request #273 from ilovepixelart/feature/move-all-types-to-one-file
Types
2 parents 8d56584 + dc45b11 commit c169849

24 files changed

+263
-309
lines changed

.gitignore

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,5 +14,5 @@ npm-debug.log
1414
.idea
1515
.env
1616

17-
# Inmemmory mongo config
17+
# In-memory mongo config
1818
/globalConfig.json

.vscode/settings.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@
3030
"sonarqube",
3131
"sonarsource",
3232
"swcrc",
33-
"virtuals"
33+
"virtuals",
34+
"Webstorm"
3435
]
3536
}

src/cache/Cache.ts

Lines changed: 10 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,20 +1,17 @@
11
import ms from 'ms'
22

3-
import MemoryCacheEngine from './engine/MemoryCacheEngine'
4-
import RedisCacheEngine from './engine/RedisCacheEngine'
3+
import { MemoryCacheEngine } from './engine/MemoryCacheEngine'
4+
import { RedisCacheEngine } from './engine/RedisCacheEngine'
55

6-
import type { StringValue } from 'ms'
7-
import type ICacheEngine from '../interfaces/ICacheEngine'
8-
import type ICacheOptions from '../interfaces/ICacheOptions'
9-
import type IData from '../interfaces/IData'
6+
import type { CacheData, CacheEngine, CacheOptions, CacheTTL } from '../types'
107

11-
class CacheEngine {
12-
#engine!: ICacheEngine
13-
#defaultTTL: number
14-
#debug: boolean
8+
export class Cache {
9+
readonly #engine!: CacheEngine
10+
readonly #defaultTTL: number
11+
readonly #debug: boolean
1512
readonly #engines = ['memory', 'redis'] as const
1613

17-
constructor(cacheOptions: ICacheOptions) {
14+
constructor(cacheOptions: CacheOptions) {
1815
if (!this.#engines.includes(cacheOptions.engine)) {
1916
throw new Error(`Invalid engine name: ${cacheOptions.engine}`)
2017
}
@@ -40,7 +37,7 @@ class CacheEngine {
4037
this.#debug = cacheOptions.debug === true
4138
}
4239

43-
async get(key: string): Promise<IData> {
40+
async get(key: string): Promise<CacheData> {
4441
const cacheEntry = await this.#engine.get(key)
4542
if (this.#debug) {
4643
const cacheHit = cacheEntry != null ? 'HIT' : 'MISS'
@@ -49,7 +46,7 @@ class CacheEngine {
4946
return cacheEntry
5047
}
5148

52-
async set(key: string, value: IData, ttl: number | StringValue | null): Promise<void> {
49+
async set(key: string, value: CacheData, ttl: CacheTTL | null): Promise<void> {
5350
const givenTTL = typeof ttl === 'string' ? ms(ttl) : ttl
5451
const actualTTL = givenTTL ?? this.#defaultTTL
5552
await this.#engine.set(key, value, actualTTL)
@@ -76,5 +73,3 @@ class CacheEngine {
7673
return this.#engine.close()
7774
}
7875
}
79-
80-
export default CacheEngine

src/cache/engine/MemoryCacheEngine.ts

Lines changed: 5 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,15 @@
11
import ms from 'ms'
22

3-
import type { StringValue } from 'ms'
4-
import type ICacheEngine from '../../interfaces/ICacheEngine'
5-
import type IData from '../../interfaces/IData'
3+
import type { CacheData, CacheEngine, CacheTTL } from '../../types'
64

7-
class MemoryCacheEngine implements ICacheEngine {
8-
#cache: Map<string, { value: IData; expiresAt: number } | undefined>
5+
export class MemoryCacheEngine implements CacheEngine {
6+
readonly #cache: Map<string, { value: CacheData; expiresAt: number } | undefined>
97

108
constructor() {
119
this.#cache = new Map()
1210
}
1311

14-
get(key: string): IData {
12+
get(key: string): CacheData {
1513
const item = this.#cache.get(key)
1614
if (!item || item.expiresAt < Date.now()) {
1715
this.del(key)
@@ -20,7 +18,7 @@ class MemoryCacheEngine implements ICacheEngine {
2018
return item.value
2119
}
2220

23-
set(key: string, value: IData, ttl?: number | StringValue): void {
21+
set(key: string, value: CacheData, ttl?: CacheTTL): void {
2422
const givenTTL = typeof ttl === 'string' ? ms(ttl) : ttl
2523
const actualTTL = givenTTL ?? Number.POSITIVE_INFINITY
2624
this.#cache.set(key, {
@@ -41,5 +39,3 @@ class MemoryCacheEngine implements ICacheEngine {
4139
// do nothing
4240
}
4341
}
44-
45-
export default MemoryCacheEngine

src/cache/engine/RedisCacheEngine.ts

Lines changed: 6 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -5,12 +5,10 @@ import ms from 'ms'
55
import { convertToObject } from '../../version'
66

77
import type { Redis, RedisOptions } from 'ioredis'
8-
import type { StringValue } from 'ms'
9-
import type ICacheEngine from '../../interfaces/ICacheEngine'
10-
import type IData from '../../interfaces/IData'
8+
import type { CacheData, CacheEngine, CacheTTL } from '../../types'
119

12-
class RedisCacheEngine implements ICacheEngine {
13-
#client: Redis
10+
export class RedisCacheEngine implements CacheEngine {
11+
readonly #client: Redis
1412

1513
constructor(options: RedisOptions) {
1614
if (!options.keyPrefix) {
@@ -19,20 +17,20 @@ class RedisCacheEngine implements ICacheEngine {
1917
this.#client = new IORedis(options)
2018
}
2119

22-
async get(key: string): Promise<IData> {
20+
async get(key: string): Promise<CacheData> {
2321
try {
2422
const value = await this.#client.get(key)
2523
if (value === null) {
2624
return undefined
2725
}
28-
return EJSON.parse(value) as IData
26+
return EJSON.parse(value) as CacheData
2927
} catch (err) {
3028
console.error(err)
3129
return undefined
3230
}
3331
}
3432

35-
async set(key: string, value: IData, ttl?: number | StringValue): Promise<void> {
33+
async set(key: string, value: CacheData, ttl?: CacheTTL): Promise<void> {
3634
try {
3735
const givenTTL = typeof ttl === 'string' ? ms(ttl) : ttl
3836
const actualTTL = givenTTL ?? Number.POSITIVE_INFINITY
@@ -55,5 +53,3 @@ class RedisCacheEngine implements ICacheEngine {
5553
await this.#client.quit()
5654
}
5755
}
58-
59-
export default RedisCacheEngine

src/extend/aggregate.ts

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,10 @@
11
import { getKey } from '../key'
22

33
import type { Mongoose } from 'mongoose'
4-
import type { StringValue } from 'ms'
5-
import type Cache from '../cache/Cache'
4+
import type { Cache } from '../cache/Cache'
5+
import type { CacheTTL } from '../types'
66

7-
export default function extendQuery(mongoose: Mongoose, cache: Cache): void {
7+
export function extendAggregate(mongoose: Mongoose, cache: Cache): void {
88
const mongooseExec = mongoose.Aggregate.prototype.exec
99

1010
mongoose.Aggregate.prototype.getCacheKey = function () {
@@ -19,7 +19,7 @@ export default function extendQuery(mongoose: Mongoose, cache: Cache): void {
1919
return this._ttl
2020
}
2121

22-
mongoose.Aggregate.prototype.cache = function (ttl?: number | StringValue, customKey?: string) {
22+
mongoose.Aggregate.prototype.cache = function (ttl?: CacheTTL, customKey?: string) {
2323
this._ttl = ttl ?? null
2424
this._key = customKey ?? null
2525
return this

src/extend/query.ts

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,10 @@
11
import { getKey } from '../key'
22

33
import type { Mongoose } from 'mongoose'
4-
import type { StringValue } from 'ms'
5-
import type Cache from '../cache/Cache'
4+
import type { Cache } from '../cache/Cache'
5+
import type { CacheTTL } from '../types'
66

7-
export default function extendQuery(mongoose: Mongoose, cache: Cache): void {
7+
export function extendQuery(mongoose: Mongoose, cache: Cache): void {
88
const mongooseExec = mongoose.Query.prototype.exec
99

1010
mongoose.Query.prototype.getCacheKey = function () {
@@ -33,7 +33,7 @@ export default function extendQuery(mongoose: Mongoose, cache: Cache): void {
3333
return this._ttl
3434
}
3535

36-
mongoose.Query.prototype.cache = function (ttl?: number | StringValue, customKey?: string) {
36+
mongoose.Query.prototype.cache = function (ttl?: CacheTTL, customKey?: string) {
3737
this._ttl = ttl ?? null
3838
this._key = customKey ?? null
3939
return this

src/interfaces/ICacheEngine.ts

Lines changed: 0 additions & 12 deletions
This file was deleted.

src/interfaces/ICacheOptions.ts

Lines changed: 0 additions & 11 deletions
This file was deleted.

src/interfaces/IData.ts

Lines changed: 0 additions & 3 deletions
This file was deleted.

src/plugin.ts

Lines changed: 11 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,17 @@
1-
import Cache from './cache/Cache'
2-
import extendAggregate from './extend/aggregate'
3-
import extendQuery from './extend/query'
1+
import { Cache } from './cache/Cache'
2+
import { extendAggregate } from './extend/aggregate'
3+
import { extendQuery } from './extend/query'
44

55
import type { Mongoose } from 'mongoose'
6-
import type { StringValue } from 'ms'
7-
import type ICacheOptions from './interfaces/ICacheOptions'
6+
import type { CacheOptions, CacheTTL } from './types'
87

98
declare module 'mongoose' {
109
interface Query<ResultType, DocType, THelpers, RawDocType> {
11-
cache: (this: Query<ResultType, DocType, THelpers, RawDocType>, ttl?: number | StringValue, customKey?: string) => this
10+
cache: (this: Query<ResultType, DocType, THelpers, RawDocType>, ttl?: CacheTTL, customKey?: string) => this
1211
_key: string | null
1312
getCacheKey: (this: Query<ResultType, DocType, THelpers, RawDocType>) => string
14-
_ttl: number | StringValue | null
15-
getCacheTTL: (this: Query<ResultType, DocType, THelpers, RawDocType>) => number | StringValue | null
13+
_ttl: CacheTTL | null
14+
getCacheTTL: (this: Query<ResultType, DocType, THelpers, RawDocType>) => CacheTTL | null
1615
op?: string
1716
_path?: unknown
1817
_fields?: unknown
@@ -21,11 +20,11 @@ declare module 'mongoose' {
2120
}
2221

2322
interface Aggregate<ResultType> {
24-
cache: (this: Aggregate<ResultType>, ttl?: number | StringValue, customKey?: string) => this
23+
cache: (this: Aggregate<ResultType>, ttl?: CacheTTL, customKey?: string) => this
2524
_key: string | null
2625
getCacheKey: (this: Aggregate<ResultType>) => string
27-
_ttl: number | StringValue | null
28-
getCacheTTL: (this: Aggregate<ResultType>) => number | StringValue | null
26+
_ttl: CacheTTL | null
27+
getCacheTTL: (this: Aggregate<ResultType>) => CacheTTL | null
2928
}
3029
}
3130

@@ -37,7 +36,7 @@ class CacheMongoose {
3736
// Private constructor to prevent external instantiation
3837
}
3938

40-
public static init(mongoose: Mongoose, cacheOptions: ICacheOptions): CacheMongoose {
39+
public static init(mongoose: Mongoose, cacheOptions: CacheOptions): CacheMongoose {
4140
if (!CacheMongoose.#instance) {
4241
CacheMongoose.#instance = new CacheMongoose()
4342
CacheMongoose.#instance.cache = new Cache(cacheOptions)

src/types.ts

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
import type { RedisOptions } from 'ioredis'
2+
import type { StringValue } from 'ms'
3+
4+
export type CacheTTL = number | StringValue
5+
6+
export type CacheData = Record<string, unknown> | Record<string, unknown>[] | unknown[] | number | undefined
7+
8+
export type CacheOptions = {
9+
engine: 'memory' | 'redis'
10+
engineOptions?: RedisOptions
11+
defaultTTL?: CacheTTL
12+
debug?: boolean
13+
}
14+
15+
export interface CacheEngine {
16+
get: (key: string) => Promise<CacheData> | CacheData
17+
set: (key: string, value: CacheData, ttl?: CacheTTL) => Promise<void> | void
18+
del: (key: string) => Promise<void> | void
19+
clear: () => Promise<void> | void
20+
close: () => Promise<void> | void
21+
}

src/version.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,11 @@
11
import mongoose from 'mongoose'
22
import { satisfies } from 'semver'
33

4-
import type IData from './interfaces/IData'
4+
import type { CacheData } from './types'
55

66
export const isMongooseLessThan7 = satisfies(mongoose.version, '<7')
77

8-
export const convertToObject = <T>(value: (T & { toObject?: () => IData }) | undefined): IData => {
8+
export const convertToObject = <T>(value: (T & { toObject?: () => CacheData }) | undefined): CacheData => {
99
if (isMongooseLessThan7) {
1010
if (value != null && typeof value === 'object' && !Array.isArray(value) && value.toObject) {
1111
return value.toObject()

tests/cache-debug.test.ts

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2,9 +2,9 @@ import { afterAll, afterEach, beforeAll, beforeEach, describe, expect, it, vi }
22

33
import mongoose from 'mongoose'
44
import CacheMongoose from '../src/plugin'
5-
import server from './mongo/server'
5+
import { server } from './mongo/server'
66

7-
import User from './models/User'
7+
import { UserModel } from './models/User'
88

99
describe('cache-debug', async () => {
1010
const instance = server('cache-debug')
@@ -36,7 +36,7 @@ describe('cache-debug', async () => {
3636

3737
describe('debug scenarios', () => {
3838
it('should create a use and and query it two time first is cache miss second is hit, also clear by key and global', async () => {
39-
const user = await User.create({
39+
const user = await UserModel.create({
4040
name: 'John Doe',
4141
role: 'admin',
4242
})
@@ -49,14 +49,14 @@ describe('cache-debug', async () => {
4949
const cacheClearRegExp = /\[ts-cache-mongoose\] CLEAR/
5050
const cacheDelRegExp = /\[ts-cache-mongoose\] DEL '.*?'/
5151

52-
const userCacheMiss = await User.findById(user._id).cache(ttl, key).exec()
52+
const userCacheMiss = await UserModel.findById(user._id).cache(ttl, key).exec()
5353
expect(console.log).toHaveBeenCalledWith(expect.stringMatching(cacheMissRegExp))
5454
expect(userCacheMiss).not.toBeNull()
5555
expect(userCacheMiss?._id.toString()).toBe(user._id.toString())
5656
expect(userCacheMiss?.name).toEqual(user.name)
5757
expect(userCacheMiss?.role).toEqual(user.role)
5858

59-
const userCacheHit = await User.findById(user._id).cache(ttl, key).exec()
59+
const userCacheHit = await UserModel.findById(user._id).cache(ttl, key).exec()
6060
expect(console.log).toHaveBeenCalledWith(expect.stringMatching(cacheSetRegExp))
6161
expect(console.log).toHaveBeenCalledWith(expect.stringMatching(cacheHitRegExp))
6262
expect(userCacheHit).not.toBeNull()

0 commit comments

Comments
 (0)