Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

chore(gatsby): Convert cache.js to TypeScript #20626

Merged
merged 9 commits into from
Jan 16, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 1 addition & 2 deletions jest.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -34,8 +34,7 @@ module.exports = {
`__tests__/fixtures`,
],
transform: {
"^.+\\.js$": `<rootDir>/jest-transformer.js`,
"^.+\\.tsx?$": `<rootDir>/jest-transformer.js`,
"^.+\\.[jt]sx?$": `<rootDir>/jest-transformer.js`,
},
moduleNameMapper: {
"^highlight.js$": `<rootDir>/node_modules/highlight.js/lib/index.js`,
Expand Down
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
"@babel/plugin-transform-typescript": "^7.7.4",
"@babel/runtime": "^7.7.7",
"@lerna/prompt": "3.18.5",
"@types/cache-manager": "^2.10.1",
"@types/express": "^4.17.2",
"@types/fs-extra": "^8.0.1",
"@types/got": "^9.6.9",
Expand Down
Original file line number Diff line number Diff line change
@@ -1,3 +1,7 @@
import Cache from "../cache"
import fs from "fs-extra"
import manager from "cache-manager"

const mockErrorValue = jest.fn()
const mockResultValue = jest.fn()

Expand All @@ -6,10 +10,10 @@ jest.mock(`cache-manager`, () => {
caching: jest.fn(),
multiCaching: jest.fn(() => {
return {
get: jest.fn((key, callback) => {
get: jest.fn((_key, callback) => {
callback(mockErrorValue(), mockResultValue())
}),
set: jest.fn((key, value, args, callback) => {
set: jest.fn((_key, _value, _args, callback) => {
callback(mockErrorValue())
}),
}
Expand All @@ -21,16 +25,14 @@ jest.mock(`fs-extra`, () => {
ensureDirSync: jest.fn(),
}
})
const Cache = require(`../cache`)
const fs = require(`fs-extra`)
const manager = require(`cache-manager`)

beforeEach(() => {
manager.caching.mockReset()
fs.ensureDirSync.mockReset()
;(manager.caching as jest.Mock).mockReset()
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Prettier insists

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

that's normal :) because else it could be a return function of mockReset

;(fs.ensureDirSync as jest.Mock).mockReset()
})

const getCache = (options = { name: `__test__` }) => new Cache(options).init()
const getCache = (options = { name: `__test__` }): Cache =>
new Cache(options).init()

describe(`cache`, () => {
it(`it can be instantiated`, () => {
Expand All @@ -40,6 +42,8 @@ describe(`cache`, () => {
it(`it can swap out cache store`, () => {
const store = {
custom: true,
get: jest.fn(),
set: jest.fn(),
}

new Cache({
Expand Down Expand Up @@ -96,14 +100,28 @@ describe(`cache`, () => {
it(`both are promises`, () => {
const cache = getCache()

const containsThenMethod = result =>
const containsThenMethod = (result): void =>
expect(result).toEqual(
expect.objectContaining({ then: expect.any(Function) })
)

containsThenMethod(cache.get(`a`))
containsThenMethod(cache.set(`a`, `b`))
})

it(`throws if set is called without initting`, () => {
const cache = new Cache({ name: `__test__` })
return expect(cache.set(`a`, `b`)).rejects.toThrowError(
`Cache wasn't initialised yet, please run the init method first`
)
})

it(`throws if get is called without initting`, () => {
const cache = new Cache({ name: `__test__` })
return expect(cache.get(`a`)).rejects.toThrowError(
`Cache wasn't initialised yet, please run the init method first`
)
})
})

describe(`set`, () => {
Expand All @@ -125,18 +143,17 @@ describe(`cache`, () => {
describe(`get`, () => {
it(`resolves to the found value`, () => {
const cache = getCache()

mockResultValue.mockReturnValueOnce(`result`)

return expect(cache.get()).resolves.toBe(`result`)
return expect(cache.get(``)).resolves.toBe(`result`)
})

it(`resolves to undefined on caching error`, () => {
const cache = getCache()

mockErrorValue.mockReturnValueOnce(true)

return expect(cache.get()).resolves.toBeUndefined()
return expect(cache.get(``)).resolves.toBeUndefined()
})
})
})
58 changes: 0 additions & 58 deletions packages/gatsby/src/utils/cache.js

This file was deleted.

83 changes: 83 additions & 0 deletions packages/gatsby/src/utils/cache.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
import manager, { Store, StoreConfig, CachingConfig } from "cache-manager"
import fs from "fs-extra"
import fsStore from "cache-manager-fs-hash"
import path from "path"

const MAX_CACHE_SIZE = 250
const TTL = Number.MAX_SAFE_INTEGER

interface ICacheProperties {
name?: string
store?: Store
}

export default class Cache {
public name: string
public store: Store
public cache?: manager.Cache

constructor({ name = `db`, store = fsStore }: ICacheProperties = {}) {
this.name = name
this.store = store
}

get directory(): string {
return path.join(process.cwd(), `.cache/caches/${this.name}`)
}

init(): Cache {
fs.ensureDirSync(this.directory)

const configs: StoreConfig[] = [
{
store: `memory`,
max: MAX_CACHE_SIZE,
ttl: TTL,
},
{
store: this.store,
ttl: TTL,
options: {
path: this.directory,
ttl: TTL,
},
},
]

const caches = configs.map(cache => manager.caching(cache))

this.cache = manager.multiCaching(caches)

return this
}

get<T = unknown>(key): Promise<T | undefined> {
return new Promise(resolve => {
if (!this.cache) {
throw new Error(
`Cache wasn't initialised yet, please run the init method first`
)
}
this.cache.get<T>(key, (err, res) => {
resolve(err ? undefined : res)
})
})
}

set<T>(
pvdz marked this conversation as resolved.
Show resolved Hide resolved
key: string,
value: T,
args: CachingConfig = { ttl: TTL }
): Promise<T | undefined> {
return new Promise(resolve => {
if (!this.cache) {
throw new Error(
`Cache wasn't initialised yet, please run the init method first`
)
}
this.cache.set(key, value, args, err => {
resolve(err ? undefined : value)
})
})
}
}
4 changes: 2 additions & 2 deletions packages/gatsby/src/utils/get-cache.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
const Cache = require(`./cache`)
const Cache = require(`./cache`).default

let caches = new Map()
const caches = new Map()

module.exports = function getCache(name) {
let cache = caches.get(name)
Expand Down
2 changes: 2 additions & 0 deletions tsconfig.json
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
{
"compilerOptions": {
"target": "ESNext",
"moduleResolution": "node",
"noUnusedLocals": true,
"noUnusedParameters": true,
"noImplicitReturns": true,
Expand Down
5 changes: 5 additions & 0 deletions yarn.lock
Original file line number Diff line number Diff line change
Expand Up @@ -3789,6 +3789,11 @@
"@types/connect" "*"
"@types/node" "*"

"@types/cache-manager@^2.10.1":
version "2.10.1"
resolved "https://registry.yarnpkg.com/@types/cache-manager/-/cache-manager-2.10.1.tgz#c7bc354be7988659e139e10fc7bde4b221f7f128"
integrity sha512-oJhVIOeC8dX9RZ7OtEZvZ/6cHF5aQWoRcuJ7KwK3Xb69hIIdElpWzfJ35fOXvYOgoyRXA34jFrD8lqEjDWz37w==

"@types/color-name@^1.1.1":
version "1.1.1"
resolved "https://registry.yarnpkg.com/@types/color-name/-/color-name-1.1.1.tgz#1c1261bbeaa10a8055bbc5d8ab84b7b2afc846a0"
Expand Down