diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index e59a461..ea7aab7 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -10,8 +10,10 @@ jobs: check: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v3 - - uses: denoland/setup-deno@v1 + - uses: actions/checkout@v4 + - uses: denoland/setup-deno@v2 + with: + deno-version: v2.4.2 - run: deno fmt --check - run: deno lint - run: deno test diff --git a/adapters/mongo.ts b/adapters/mongo.ts index 53e9f35..c612901 100644 --- a/adapters/mongo.ts +++ b/adapters/mongo.ts @@ -1,11 +1,10 @@ -import { type Collection } from "https://deno.land/x/mongo@v0.31.0/mod.ts"; -import { Adapter } from "../adapter.ts"; +import type { Collection } from "https://deno.land/x/mongo@v0.34.0/mod.ts"; +import type { Adapter } from "../adapter.ts"; export class MongoAdapter implements Adapter { constructor( protected collection: Collection<{ key: string; value: string }>, - ) { - } + ) {} async setItems(items: Record) { await this.collection.deleteMany({ key: { $in: Object.keys(items) } }); @@ -21,6 +20,6 @@ export class MongoAdapter implements Adapter { } async deleteItems(items: string[]) { - await this.collection.deleteMany(items.map((v) => ({ key: v }))); + await this.collection.deleteMany({ key: { $in: items } }); } } diff --git a/adapters/postgres.ts b/adapters/postgres.ts index d792c1e..ca2cd3d 100644 --- a/adapters/postgres.ts +++ b/adapters/postgres.ts @@ -1,9 +1,8 @@ -import { Client } from "https://deno.land/x/postgres@v0.16.1/mod.ts"; -import { Adapter } from "../adapter.ts"; +import type { Client } from "https://deno.land/x/postgres@v0.19.5/mod.ts"; +import type { Adapter } from "../adapter.ts"; export class PostgresAdapter implements Adapter { - constructor(protected client: Client, protected table: string) { - } + constructor(protected client: Client, protected table: string) {} // Credits to @Satont for his awesome work in grammyjs/storages async initialize() { @@ -11,10 +10,9 @@ export class PostgresAdapter implements Adapter { key VARCHAR NOT NULL, value TEXT )`); - await this.client - .queryArray( - `CREATE UNIQUE INDEX IF NOT EXISTS IDX_${this.table} ON "${this.table}" (key)`, - ); + await this.client.queryArray( + `CREATE UNIQUE INDEX IF NOT EXISTS IDX_${this.table} ON "${this.table}" (key)`, + ); return this; } @@ -23,7 +21,9 @@ export class PostgresAdapter implements Adapter { const entries = Object.entries(items); await this.client.queryArray( `DELETE FROM "${this.table}" WHERE key IN (${ - keys.map((_, i) => `$${i + 1}`) + keys.map( + (_, i) => `$${i + 1}`, + ) })` as unknown as TemplateStringsArray, ...keys, ); diff --git a/adapters/redis.ts b/adapters/redis.ts index 735ca1d..bbfd2f9 100644 --- a/adapters/redis.ts +++ b/adapters/redis.ts @@ -1,9 +1,8 @@ -import { Redis } from "https://deno.land/x/redis@v0.26.0/mod.ts"; -import { Adapter } from "../adapter.ts"; +import type { Redis } from "https://deno.land/x/redis@v0.40.0/mod.ts"; +import type { Adapter } from "../adapter.ts"; export class RedisAdapter implements Adapter { - constructor(protected redis: Redis) { - } + constructor(protected redis: Redis) {} async setItems(items: Record) { const pipeline = this.redis.pipeline(); @@ -21,9 +20,9 @@ export class RedisAdapter implements Adapter { } const values = await pipeline.flush(); return Object.fromEntries( - values.map((v, i) => [keys[i].slice(4), v]).filter(([v]) => - typeof v === "string" - ), + values + .map((v, i) => [keys[i].slice(4), v]) + .filter(([v]) => typeof v === "string"), ); } diff --git a/deno.jsonc b/deno.jsonc new file mode 100644 index 0000000..af1843c --- /dev/null +++ b/deno.jsonc @@ -0,0 +1,5 @@ +{ + "name": "@xorgram/pls", + "exports": "./mod.ts", + "lock": false +} diff --git a/mod.ts b/mod.ts index 18751ae..2aec1c4 100644 --- a/mod.ts +++ b/mod.ts @@ -1,4 +1,4 @@ -import { Adapter } from "./adapter.ts"; +import type { Adapter } from "./adapter.ts"; export interface Config { /** @@ -70,7 +70,7 @@ export async function setup(config_?: Config) { switch (url.protocol) { case "mongodb:": { const { MongoClient } = await import( - "https://deno.land/x/mongo@v0.31.0/mod.ts" + "https://deno.land/x/mongo@v0.34.0/mod.ts" ); const client = new MongoClient(); await client.connect(uri); @@ -83,18 +83,20 @@ export async function setup(config_?: Config) { case "postgres:": case "postgresql:": { const { Client } = await import( - "https://deno.land/x/postgres@v0.16.1/mod.ts" + "https://deno.land/x/postgres@v0.19.5/mod.ts" ); const client = new Client(uri); await client.connect(); const { PostgresAdapter } = await import("./adapters/postgres.ts"); - config.adapter = await new PostgresAdapter(client, "ls") - .initialize(); + config.adapter = await new PostgresAdapter( + client, + "ls", + ).initialize(); break; } case "redis:": { const { connect, parseURL } = await import( - "https://deno.land/x/redis@v0.26.0/mod.ts" + "https://deno.land/x/redis@v0.40.0/mod.ts" ); const redis = await connect(parseURL(uri)); const { RedisAdapter } = await import("./adapters/redis.ts"); @@ -106,9 +108,7 @@ export async function setup(config_?: Config) { } } if (!config.adapter) { - throw new Error( - "PLS_CONNECTION_URI is not set, invalid or not supported", - ); + throw new Error("PLS_CONNECTION_URI is not set, invalid or not supported"); } config.ttl = typeof config_?.ttl !== "undefined" ? config_.ttl : 20000; if (config_?.include) { @@ -132,28 +132,30 @@ function flush_() { if (!adapter) { throw new Error("Cannot flush before setting up"); } - Promise.resolve().then(async () => { - const { previousItems } = config; - const currentItems = Object.fromEntries(Object.entries(localStorage)); - let toSet = Object.entries(currentItems).filter(([k]) => isIncluded(k)); - toSet = previousItems - ? toSet.filter(([k, v]) => - previousItems[k] == undefined || previousItems[k] != v - ) - : toSet; - const toDelete = previousItems - ? Object.keys(previousItems).filter((v) => - !Object.keys(currentItems).includes(v) - ) - : []; - if (toSet.length != 0) { - await adapter.setItems(Object.fromEntries(toSet)); - } - if (toDelete.length != 0) { - await adapter.deleteItems(toDelete); - } - config.previousItems = currentItems; - }).catch((err) => console.warn("Could not flush localStorage:", err)); + Promise.resolve() + .then(async () => { + const { previousItems } = config; + const currentItems = Object.fromEntries(Object.entries(localStorage)); + let toSet = Object.entries(currentItems).filter(([k]) => isIncluded(k)); + toSet = previousItems + ? toSet.filter( + ([k, v]) => previousItems[k] == undefined || previousItems[k] != v, + ) + : toSet; + const toDelete = previousItems + ? Object.keys(previousItems).filter( + (v) => !Object.keys(currentItems).includes(v), + ) + : []; + if (toSet.length != 0) { + await adapter.setItems(Object.fromEntries(toSet)); + } + if (toDelete.length != 0) { + await adapter.deleteItems(toDelete); + } + config.previousItems = currentItems; + }) + .catch((err) => console.warn("Could not flush localStorage:", err)); } export function flush() { diff --git a/test.ts b/test.ts index f91e245..2b7856a 100644 --- a/test.ts +++ b/test.ts @@ -3,11 +3,11 @@ import { assertExists, assertRejects, assertThrows, -} from "https://deno.land/std@0.151.0/testing/asserts.ts"; -import { Adapter } from "./adapter.ts"; +} from "jsr:@std/assert"; import { flush, setup } from "./mod.ts"; +import type { Adapter } from "./adapter.ts"; -const testAdapter = new class implements Adapter { +const testAdapter = new (class implements Adapter { items: Record = {}; setItems(items: Record) { @@ -23,7 +23,7 @@ const testAdapter = new class implements Adapter { Object.entries(this.items).filter(([k]) => !items.includes(k)), ); } -}(); +})(); function wait(duration = 10) { return new Promise((r) => setTimeout(r, duration));