Skip to content
This repository has been archived by the owner on Jun 27, 2024. It is now read-only.

Commit

Permalink
feat(context): add cache object (#193)
Browse files Browse the repository at this point in the history
  • Loading branch information
boywithkeyboard authored Aug 22, 2023
1 parent 85f0246 commit f62bec7
Show file tree
Hide file tree
Showing 3 changed files with 129 additions and 0 deletions.
10 changes: 10 additions & 0 deletions cheetah.ts
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ export type AppContext = {
}
oauth: AppConfig['oauth']
versioning: AppConfig['versioning']
caching: AppConfig['cache']
}

export type AppConfig = {
Expand Down Expand Up @@ -104,6 +105,11 @@ export type AppConfig = {
& {
current: Version
}

cache?: {
/** A unique name for your cache. */
name: string
}
}

export class cheetah extends base<cheetah>() {
Expand All @@ -120,6 +126,7 @@ export class cheetah extends base<cheetah>() {
#oauth
#debug
#versioning
#cache

constructor({
base,
Expand All @@ -131,6 +138,7 @@ export class cheetah extends base<cheetah>() {
oauth,
debug = false,
versioning,
cache,
}: AppConfig = {}) {
super((method, pathname, handlers) => {
pathname = this.#base ? this.#base + pathname : pathname
Expand Down Expand Up @@ -167,6 +175,7 @@ export class cheetah extends base<cheetah>() {
this.#oauth = oauth
this.#debug = debug
this.#versioning = versioning
this.#cache = cache
}

/* use ---------------------------------------------------------------------- */
Expand Down Expand Up @@ -381,6 +390,7 @@ export class cheetah extends base<cheetah>() {
versioning: this.#versioning,
gateway: -1,
debugging: this.#debug,
caching: this.#cache,
}

if (this.#extensions.size > 0) {
Expand Down
118 changes: 118 additions & 0 deletions context.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
// Copyright 2023 Samuel Kopp. All rights reserved. Apache-2.0 license.
/// <reference types='./env.d.ts' />
import { encode } from 'https://deno.land/std@0.199.0/encoding/base64.ts'
import { ZodType } from 'https://deno.land/x/zod@v3.21.4/types.ts'
import { AppContext } from './cheetah.ts'
import { ObjectType, Payload } from './handler.ts'
Expand Down Expand Up @@ -40,6 +41,7 @@ export class Context<
ValidatedQuery extends ObjectType = never,
> {
#a
#c: Cache | undefined
#i
#p
#r
Expand Down Expand Up @@ -89,6 +91,16 @@ export class Context<
return this.#a
}

get cache(): Cache {
if (this.#c) {
return this.#c
}

this.#c = new Cache(this)

return this.#c
}

get dev(): boolean {
return this.#a.debugging ||
this.runtime === 'deno' && Deno.env.get('DEV') === 'true'
Expand Down Expand Up @@ -174,3 +186,109 @@ export class Exception {
}
}
}

class Cache {
#cache: globalThis.Cache | null
#context
#name

constructor(c: Context) {
this.#cache = null
this.#context = c
this.#name = c.__app.caching?.name ?? 'cheetah'
}

async set(
key: string,
value: string | Record<string, unknown> | Uint8Array,
options?: {
maxAge?: number
},
) {
if (this.#cache === null) {
this.#cache = await caches.open(this.#name)
}

this.#context.waitUntil(
this.#cache.put(
`https://${this.#name}.com/${encode(key)}`,
new Response(
typeof value === 'string' || value instanceof Uint8Array
? value
: JSON.stringify(value),
{
headers: {
'cache-control': `max-age=${options?.maxAge ?? 300}`,
},
},
),
),
)
}

get<T extends Record<string, unknown> = Record<string, unknown>>(
key: string,
type: 'json',
): Promise<T | undefined>
get<T extends string = string>(
key: string,
type: 'string',
): Promise<T | undefined>
get<T extends Uint8Array = Uint8Array>(
key: string,
type: 'buffer',
): Promise<T | undefined>

async get<T extends Record<string, unknown> | string | Uint8Array>(
key: string,
type: 'string' | 'json' | 'buffer' = 'string',
): Promise<T | undefined> {
if (this.#cache === null) {
this.#cache = await caches.open(this.#name)
}

try {
const result = await this.#cache.match(
`https://${this.#name}.com/${encode(key)}`,
)

if (!result) {
return undefined
}

const data = type === 'string'
? await result.text()
: type === 'json'
? await result.json()
: new Uint8Array(await result.arrayBuffer())

return data
} catch (_err) {
return undefined
}
}

async has(key: string) {
if (this.#cache === null) {
this.#cache = await caches.open(this.#name)
}

const result = await this.#cache.match(
`https://${this.#name}.com/${encode(key)}`,
)

return result !== undefined
}

async delete(key: string) {
if (this.#cache === null) {
this.#cache = await caches.open(this.#name)
}

this.#context.waitUntil(
this.#cache.delete(
`https://${this.#name}.com/${encode(key)}`,
),
)
}
}
1 change: 1 addition & 0 deletions x/cache.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
import { encode } from 'https://deno.land/std@0.199.0/encoding/base64.ts'
import { Context } from '../mod.ts'

/** @deprecate please use `c.cache` instead! */
export class Cache {
#cache: globalThis.Cache | null
#context
Expand Down

0 comments on commit f62bec7

Please sign in to comment.