UNPKG

2.83 kBPlain TextView Raw
1// deno-lint-ignore-file no-explicit-any
2import "./_dnt.polyfills.js";
3
4import * as dntShim from "./_dnt.shims.js";
5
6import type { StorageArea, AllowedKey, Key } from 'kv-storage-interface';
7import { encodeKey, decodeKey, throwForDisallowedKey } from 'idb-key-to-string';
8
9import * as Structured from '@worker-tools/structured-json';
10
11import type { Adapter, DBProtocol, AdapterClass, DB_URL } from './adapters/mod.js';
12
13const OLD_DEFAULT_URL_KEY = 'DENO_STORAGE_AREA__DEFAULT_URL';
14const DEFAULT_URL_KEY = 'DEFAULT_KV_URL';
15const DEFAULT_STORAGE_AREA_NAME = 'default';
16
17export interface DenoStorageAreaOptions {
18 url?: DB_URL,
19 [k: string]: any,
20}
21
22export class DenoStorageArea implements StorageArea {
23 #store: Adapter;
24
25 static defaultURL?: DB_URL;
26
27 constructor(name: string = DEFAULT_STORAGE_AREA_NAME, options: DenoStorageAreaOptions = {}) {
28 const dbURL = options.url
29 || DenoStorageArea.defaultURL
30 || Reflect.get(self, DEFAULT_URL_KEY)
31 || Reflect.get(self, OLD_DEFAULT_URL_KEY)
32 || Deno.env.get(DEFAULT_URL_KEY)
33 || Deno.env.get(OLD_DEFAULT_URL_KEY)
34 || 'sqlite://';
35
36 const { protocol } = new URL(dbURL);
37 const adapters: Map<DBProtocol, AdapterClass> = (<any>dntShim.dntGlobalThis).deno_storage_area__adapters || new Map()
38 const AdapterCtor = adapters.get(protocol as DBProtocol);
39
40 if (!AdapterCtor) {
41 throw Error(`Adapter for database protocol '${protocol}' not registered. Try importing 'adapters/${protocol.replace(':', '')}.ts'`);
42 }
43
44 this.#store = new AdapterCtor({ area: name, url: dbURL });
45 }
46
47 async get<T>(key: AllowedKey): Promise<T | undefined> {
48 throwForDisallowedKey(key);
49 const s = await this.#store.get(encodeKey(key))
50 return s && Structured.parse(s);
51 }
52
53 async set<T>(key: AllowedKey, value: T | undefined): Promise<void> {
54 throwForDisallowedKey(key);
55 if (value === undefined) {
56 await this.#store.delete(encodeKey(key));
57 } else {
58 await this.#store.set(encodeKey(key), Structured.stringify(value));
59 }
60 }
61
62 async delete(key: AllowedKey) {
63 throwForDisallowedKey(key);
64 await this.#store.delete(encodeKey(key));
65 }
66
67 async clear() {
68 await this.#store.clear();
69 }
70
71 async *keys(): AsyncGenerator<Key> {
72 for await (const key of this.#store.keys()) {
73 yield decodeKey(key);
74 }
75 }
76
77 async *values<T>(): AsyncGenerator<T> {
78 for await (const value of this.#store.values()) {
79 yield Structured.parse(value);
80 }
81 }
82
83 async *entries<T>(): AsyncGenerator<[Key, T]> {
84 for await (const [key, value] of this.#store.entries()) {
85 yield [decodeKey(key), Structured.parse(value)];
86 }
87 }
88
89 backingStore() {
90 return this.#store.backingStore();
91 }
92}
93
94export type { AllowedKey, Key, DBProtocol, DB_URL };
95export { DenoStorageArea as StorageArea };