ts-cache-mongoose 2.0.0 → 2.1.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/src/ms.ts CHANGED
@@ -4,52 +4,63 @@ const h = m * 60
4
4
  const d = h * 24
5
5
  const w = d * 7
6
6
  const y = d * 365.25
7
+ const mo = y / 12
7
8
 
8
- // NOSONAR regex from ms package, intentionally covers all time unit aliases
9
- const RE = /^(-?(?:\d+)?\.?\d+)\s*(milliseconds?|msecs?|ms|seconds?|secs?|s|minutes?|mins?|m|hours?|hrs?|h|days?|d|weeks?|w|years?|yrs?|y)?$/i
10
-
11
- const UNITS: Record<string, number> = {
12
- years: y,
13
- year: y,
14
- yrs: y,
15
- yr: y,
16
- y,
17
- weeks: w,
18
- week: w,
19
- w,
20
- days: d,
21
- day: d,
22
- d,
23
- hours: h,
24
- hour: h,
25
- hrs: h,
26
- hr: h,
27
- h,
28
- minutes: m,
29
- minute: m,
30
- mins: m,
31
- min: m,
32
- m,
33
- seconds: s,
34
- second: s,
35
- secs: s,
36
- sec: s,
37
- s,
9
+ export const UNITS = {
38
10
  milliseconds: 1,
39
11
  millisecond: 1,
40
12
  msecs: 1,
41
13
  msec: 1,
42
14
  ms: 1,
43
- }
15
+ seconds: s,
16
+ second: s,
17
+ secs: s,
18
+ sec: s,
19
+ s,
20
+ minutes: m,
21
+ minute: m,
22
+ mins: m,
23
+ min: m,
24
+ m,
25
+ hours: h,
26
+ hour: h,
27
+ hrs: h,
28
+ hr: h,
29
+ h,
30
+ days: d,
31
+ day: d,
32
+ d,
33
+ weeks: w,
34
+ week: w,
35
+ w,
36
+ months: mo,
37
+ month: mo,
38
+ mo,
39
+ years: y,
40
+ year: y,
41
+ yrs: y,
42
+ yr: y,
43
+ y,
44
+ } as const satisfies Record<string, number>
45
+
46
+ export type Unit = keyof typeof UNITS
47
+
48
+ export type Duration = number | `${number}` | `${number}${Unit}` | `${number} ${Unit}`
49
+
50
+ const unitPattern = Object.keys(UNITS)
51
+ .sort((a, b) => b.length - a.length)
52
+ .join('|')
53
+
54
+ const RE = new RegExp(String.raw`^(-?(?:\d+)?\.?\d+)\s*(${unitPattern})?$`, 'i')
44
55
 
45
- export const ms = (val: string): number => {
56
+ export const ms = (val: Duration): number => {
46
57
  const str = String(val)
47
- if (str.length > 100) return 0
58
+ if (str.length > 100) return Number.NaN
48
59
 
49
60
  const match = RE.exec(str)
50
- if (!match) return 0
61
+ if (!match) return Number.NaN
51
62
 
52
63
  const n = Number.parseFloat(match[1] ?? '')
53
64
  const type = (match[2] ?? 'ms').toLowerCase()
54
- return n * (UNITS[type] ?? 0)
65
+ return n * (UNITS[type as Unit] ?? 0)
55
66
  }
package/src/types.ts CHANGED
@@ -1,19 +1,20 @@
1
1
  import type { RedisOptions } from 'ioredis'
2
+ import type { Duration } from './ms'
2
3
 
3
- export type CacheTTL = number | string
4
+ export type { Duration } from './ms'
4
5
 
5
6
  export type CacheData = Record<string, unknown> | Record<string, unknown>[] | unknown[] | number | undefined
6
7
 
7
8
  export type CacheOptions = {
8
9
  engine: 'memory' | 'redis'
9
10
  engineOptions?: RedisOptions
10
- defaultTTL?: CacheTTL
11
+ defaultTTL?: Duration
11
12
  debug?: boolean
12
13
  }
13
14
 
14
15
  export interface CacheEngine {
15
16
  get: (key: string) => Promise<CacheData> | CacheData
16
- set: (key: string, value: CacheData, ttl?: CacheTTL) => Promise<void> | void
17
+ set: (key: string, value: CacheData, ttl?: Duration) => Promise<void> | void
17
18
  del: (key: string) => Promise<void> | void
18
19
  clear: () => Promise<void> | void
19
20
  close: () => Promise<void> | void
package/tests/ms.test.ts CHANGED
@@ -1,68 +1,78 @@
1
1
  import { describe, expect, it } from 'vitest'
2
2
 
3
- import { ms } from '../src/ms'
3
+ import { ms, UNITS } from '../src/ms'
4
+
5
+ const { s, m, h, d, w, mo, y } = UNITS
4
6
 
5
7
  describe('ms', () => {
8
+ it('should parse milliseconds', () => {
9
+ expect(ms('100ms')).toBe(100)
10
+ expect(ms('500 milliseconds')).toBe(500)
11
+ expect(ms('1 millisecond')).toBe(1)
12
+ expect(ms('200 msec')).toBe(200)
13
+ expect(ms('300 msecs')).toBe(300)
14
+ })
15
+
6
16
  it('should parse seconds', () => {
7
- expect(ms('1s')).toBe(1000)
8
- expect(ms('5 seconds')).toBe(5000)
9
- expect(ms('30 sec')).toBe(30000)
10
- expect(ms('1 second')).toBe(1000)
11
- expect(ms('2 secs')).toBe(2000)
17
+ expect(ms('1s')).toBe(s)
18
+ expect(ms('5 seconds')).toBe(5 * s)
19
+ expect(ms('30 sec')).toBe(30 * s)
20
+ expect(ms('1 second')).toBe(s)
21
+ expect(ms('2 secs')).toBe(2 * s)
12
22
  })
13
23
 
14
24
  it('should parse minutes', () => {
15
- expect(ms('1m')).toBe(60000)
16
- expect(ms('5 minutes')).toBe(300000)
17
- expect(ms('1 minute')).toBe(60000)
18
- expect(ms('2 min')).toBe(120000)
19
- expect(ms('3 mins')).toBe(180000)
25
+ expect(ms('1m')).toBe(m)
26
+ expect(ms('5 minutes')).toBe(5 * m)
27
+ expect(ms('1 minute')).toBe(m)
28
+ expect(ms('2 min')).toBe(2 * m)
29
+ expect(ms('3 mins')).toBe(3 * m)
20
30
  })
21
31
 
22
32
  it('should parse hours', () => {
23
- expect(ms('1h')).toBe(3600000)
24
- expect(ms('2 hours')).toBe(7200000)
25
- expect(ms('1 hour')).toBe(3600000)
26
- expect(ms('3 hr')).toBe(10800000)
27
- expect(ms('4 hrs')).toBe(14400000)
33
+ expect(ms('1h')).toBe(h)
34
+ expect(ms('2 hours')).toBe(2 * h)
35
+ expect(ms('1 hour')).toBe(h)
36
+ expect(ms('3 hr')).toBe(3 * h)
37
+ expect(ms('4 hrs')).toBe(4 * h)
28
38
  })
29
39
 
30
40
  it('should parse days', () => {
31
- expect(ms('1d')).toBe(86400000)
32
- expect(ms('2 days')).toBe(172800000)
33
- expect(ms('1 day')).toBe(86400000)
41
+ expect(ms('1d')).toBe(d)
42
+ expect(ms('2 days')).toBe(2 * d)
43
+ expect(ms('1 day')).toBe(d)
34
44
  })
35
45
 
36
46
  it('should parse weeks', () => {
37
- expect(ms('1w')).toBe(604800000)
38
- expect(ms('2 weeks')).toBe(1209600000)
39
- expect(ms('1 week')).toBe(604800000)
47
+ expect(ms('1w')).toBe(w)
48
+ expect(ms('2 weeks')).toBe(2 * w)
49
+ expect(ms('1 week')).toBe(w)
40
50
  })
41
51
 
42
- it('should parse years', () => {
43
- expect(ms('1y')).toBe(31557600000)
44
- expect(ms('1 year')).toBe(31557600000)
45
- expect(ms('2 yrs')).toBe(63115200000)
46
- expect(ms('1 yr')).toBe(31557600000)
52
+ it('should parse months', () => {
53
+ expect(ms('1mo')).toBe(mo)
54
+ expect(ms('1 month')).toBe(mo)
55
+ expect(ms('2 months')).toBe(2 * mo)
56
+ expect(ms('6mo')).toBe(6 * mo)
57
+ expect(ms('0.5mo')).toBe(0.5 * mo)
47
58
  })
48
59
 
49
- it('should parse milliseconds', () => {
50
- expect(ms('100ms')).toBe(100)
51
- expect(ms('500 milliseconds')).toBe(500)
52
- expect(ms('1 millisecond')).toBe(1)
53
- expect(ms('200 msec')).toBe(200)
54
- expect(ms('300 msecs')).toBe(300)
60
+ it('should parse years', () => {
61
+ expect(ms('1y')).toBe(y)
62
+ expect(ms('1 year')).toBe(y)
63
+ expect(ms('2 yrs')).toBe(2 * y)
64
+ expect(ms('1 yr')).toBe(y)
55
65
  })
56
66
 
57
67
  it('should parse decimal values', () => {
58
- expect(ms('1.5h')).toBe(5400000)
59
- expect(ms('0.5d')).toBe(43200000)
60
- expect(ms('.5s')).toBe(500)
68
+ expect(ms('1.5h')).toBe(1.5 * h)
69
+ expect(ms('0.5d')).toBe(0.5 * d)
70
+ expect(ms('.5s')).toBe(0.5 * s)
61
71
  })
62
72
 
63
73
  it('should parse negative values', () => {
64
- expect(ms('-1s')).toBe(-1000)
65
- expect(ms('-3m')).toBe(-180000)
74
+ expect(ms('-1s')).toBe(-s)
75
+ expect(ms('-3m')).toBe(-3 * m)
66
76
  })
67
77
 
68
78
  it('should default to milliseconds without unit', () => {
@@ -71,23 +81,33 @@ describe('ms', () => {
71
81
  })
72
82
 
73
83
  it('should be case insensitive', () => {
74
- expect(ms('1S')).toBe(1000)
75
- expect(ms('1M')).toBe(60000)
76
- expect(ms('1H')).toBe(3600000)
84
+ // @ts-expect-error runtime check
85
+ expect(ms('1S')).toBe(s)
86
+ // @ts-expect-error runtime check
87
+ expect(ms('1M')).toBe(m)
88
+ // @ts-expect-error runtime check
89
+ expect(ms('1H')).toBe(h)
77
90
  })
78
91
 
79
- it('should return 0 for invalid strings', () => {
80
- expect(ms('invalid')).toBe(0)
81
- expect(ms('')).toBe(0)
82
- expect(ms('abc123')).toBe(0)
92
+ it('should return NaN for invalid strings', () => {
93
+ // @ts-expect-error testing invalid input
94
+ expect(ms('invalid')).toBeNaN()
95
+ // @ts-expect-error testing invalid input
96
+ expect(ms('')).toBeNaN()
97
+ // @ts-expect-error testing invalid input
98
+ expect(ms('abc123')).toBeNaN()
83
99
  })
84
100
 
85
- it('should return 0 for strings longer than 100 characters', () => {
86
- expect(ms('a'.repeat(101))).toBe(0)
101
+ it('should return NaN for strings longer than 100 characters', () => {
102
+ // @ts-expect-error testing invalid input
103
+ expect(ms('a'.repeat(101))).toBeNaN()
87
104
  })
88
105
 
89
106
  it('should handle whitespace between number and unit', () => {
90
- expect(ms('1 s')).toBe(1000)
91
- expect(ms('5 minutes')).toBe(300000)
107
+ expect(ms('1 s')).toBe(s)
108
+ expect(ms('5 minutes')).toBe(5 * m)
109
+ expect(ms('1 mo')).toBe(mo)
110
+ expect(ms('1 week')).toBe(w)
111
+ expect(ms('1 year')).toBe(y)
92
112
  })
93
113
  })
package/tsconfig.json CHANGED
@@ -1,8 +1,8 @@
1
1
  {
2
2
  "include": ["src"],
3
3
  "compilerOptions": {
4
- "target": "ES2021",
5
- "lib": ["ES2021"],
4
+ "target": "ES2022",
5
+ "lib": ["ES2022"],
6
6
  "types": ["node"],
7
7
  "module": "Preserve",
8
8
  "moduleResolution": "bundler",
@@ -18,7 +18,6 @@
18
18
  "experimentalDecorators": true,
19
19
  "exactOptionalPropertyTypes": true,
20
20
  "forceConsistentCasingInFileNames": true,
21
- "importHelpers": true,
22
21
  "isolatedModules": true,
23
22
  "noEmitOnError": true,
24
23
  "noFallthroughCasesInSwitch": true,