From 2ded6b7ce936bafeb1b882a8ab0698247a070164 Mon Sep 17 00:00:00 2001 From: Cotton Hou Date: Fri, 1 Nov 2024 12:30:27 +0800 Subject: [PATCH] wip --- adapter/unstable-cloudflare-kv.ts | 132 ++++++++++++++++++++++++++++++ app.tsx | 4 +- deno.json | 1 + deploy/unstable-cloudflare.ts | 49 +++++++++++ 4 files changed, 184 insertions(+), 2 deletions(-) create mode 100644 adapter/unstable-cloudflare-kv.ts create mode 100644 deploy/unstable-cloudflare.ts diff --git a/adapter/unstable-cloudflare-kv.ts b/adapter/unstable-cloudflare-kv.ts new file mode 100644 index 0000000..0c79ec5 --- /dev/null +++ b/adapter/unstable-cloudflare-kv.ts @@ -0,0 +1,132 @@ +import { getContext } from 'hono/context-storage'; + +import * as v from 'valibot'; + +import type { Adapter, AdapterGen } from './index.ts'; + + + + + +export function gen_cloudflare_kv (ns: string): AdapterGen { + + return () => hook(ns); + +} + + + + + +function hook (ns: string): Adapter { + + return { + + async get (id) { + + const kv = get_kv(ns); + const key = prefix_urls(id); + + const { success, output } = await kv.get(key).then(safe_url); + + if (success === true) { + return output; + } + + }, + + async put (id, link, { ttl } = {}) { + + const kv = get_kv(ns); + const key = prefix_urls(id); + + const exist = await kv.get(key); + + if (exist != null) { + return false; + } + + const expirationTtl = ttl?.seconds(); + + const metadata = { + create_date: new Date().toISOString(), + }; + + await kv.put(key, link, { expirationTtl, metadata }); + + return true; + + }, + + async del (id) { + + const kv = get_kv(ns); + const key = prefix_urls(id); + + await kv.delete(key); + + return true; + + }, + + [Symbol.dispose] () { + // noop + }, + + }; + +} + + + + + +interface KVNamespace { + + get (key: string): Promise; + + put (key: string, value: string, opts?: { + + expirationTtl?: number, + metadata?: object, + + }): Promise; + + delete (key: string): Promise; + +} + + + + + +function get_kv (ns: string): KVNamespace { + + type Env = { + Bindings: Record, + }; + + const { [ns]: kv } = getContext().env; + + v.assert(safe_kv, kv); + + return kv; + +} + + + + + +const safe_kv = v.object({ + + get: v.function(), + put: v.function(), + delete: v.function(), + +}, 'invalid worker kv'); + +const safe_url = v.safeParser(v.pipe(v.string(), v.url())); + +const prefix_urls = (id: string) => 'v1/urls:'.concat(id); + diff --git a/app.tsx b/app.tsx index 312a9db..af06def 100644 --- a/app.tsx +++ b/app.tsx @@ -33,8 +33,8 @@ export async function create_app ( { + init = noop, auth = noop, - async_local_storage = noop, cache_name = 'assets-v1', ttl_in_ms = nothing(), signing_nav = false, @@ -49,7 +49,7 @@ export async function create_app ( return extend(new Hono().get('/static/*', cached(cache_name))) - .use(async_local_storage) + .use(init) .use(layout) diff --git a/deno.json b/deno.json index 9581f52..2b1188f 100644 --- a/deno.json +++ b/deno.json @@ -19,6 +19,7 @@ "dev": "deno serve --port 3000 -N=esm.sh:443 -R=./db -W=./db --watch dev.ts" }, "exports": { + "./deploy/unstable-cloudflare": "./deploy/unstable-cloudflare.ts", "./deploy/deno": "./deploy/deno.ts", "./helper": "./helper.ts", "./app": "./app.tsx", diff --git a/deploy/unstable-cloudflare.ts b/deploy/unstable-cloudflare.ts new file mode 100644 index 0000000..ee6ce6f --- /dev/null +++ b/deploy/unstable-cloudflare.ts @@ -0,0 +1,49 @@ +import type { MiddlewareHandler } from 'hono/types'; +import { contextStorage } from 'hono/context-storage'; + +import { create_app } from '../app.tsx'; +import { gen_cloudflare_kv } from '../adapter/unstable-cloudflare-kv.ts'; +import { gen_fnv1a_hash } from '../encoder/npm-pure.ts'; + + + + + +export function make ({ + + auth, kv_path, cache_name, ttl_in_ms, hash_seed, hash_enlarge, + signing_nav, signing_site, + +}: { + + auth?: MiddlewareHandler, + kv_path: string, + cache_name?: string, + ttl_in_ms?: number, + hash_seed?: string, + hash_enlarge?: boolean, + signing_nav?: boolean, + signing_site?: string, + +}): Promise { + + const hash = gen_fnv1a_hash({ + key: hash_seed, + large: hash_enlarge, + }); + + const storage = gen_cloudflare_kv(kv_path); + + const init = contextStorage(); + + return create_app(hash, storage, { + init, + auth, + cache_name, + ttl_in_ms, + signing_nav, + signing_site, + }); + +} +