diff --git a/deno.json b/deno.json index 3c6019e..e8b5e98 100644 --- a/deno.json +++ b/deno.json @@ -30,6 +30,7 @@ "@lib/": "./lib/", "@/": "./", "@libsql/client": "npm:@libsql/client@^0.17.0", + "@libsql/linux-x64-gnu": "npm:@libsql/linux-x64-gnu@^0.5.22", "@openai/openai": "jsr:@openai/openai@^6.16.0", "@preact-icons/tb": "jsr:@preact-icons/tb@^1.0.14", "@std/http": "jsr:@std/http@^1.0.23", @@ -88,13 +89,11 @@ }, "allowScripts": { "allow": [ - "npm:sharp@0.34.5" - ], - "deny": [ + "npm:sharp@0.34.5", + "npm:esbuild@0.27.2", "npm:esbuild@0.18.20", "npm:esbuild@0.25.12", - "npm:esbuild@0.25.7", - "npm:esbuild@0.27.2" + "npm:esbuild@0.25.7" ] } } diff --git a/deno.lock b/deno.lock index d815636..8992920 100644 --- a/deno.lock +++ b/deno.lock @@ -44,6 +44,7 @@ "npm:@babel/core@^7.28.0": "7.28.5", "npm:@babel/preset-react@^7.27.1": "7.28.5_@babel+core@7.28.5", "npm:@libsql/client@0.17": "0.17.0", + "npm:@libsql/linux-x64-gnu@~0.5.22": "0.5.22", "npm:@mjackson/node-fetch-server@0.7": "0.7.0", "npm:@opentelemetry/api@^1.9.0": "1.9.0", "npm:@preact/signals@^2.2.1": "2.5.1_preact@10.28.2", @@ -2887,6 +2888,7 @@ "jsr:@std/media-types@^1.1.0", "jsr:@zaubrik/djwt@^3.0.2", "npm:@libsql/client@0.17", + "npm:@libsql/linux-x64-gnu@~0.5.22", "npm:@preact/signals@^2.5.0", "npm:@tailwindcss/vite@^4.1.12", "npm:defuddle@~0.6.6", diff --git a/drizzle/0000_dashing_sunspot.sql b/drizzle/0000_dashing_sunspot.sql index a42c6ad..fffa7ce 100644 --- a/drizzle/0000_dashing_sunspot.sql +++ b/drizzle/0000_dashing_sunspot.sql @@ -1,20 +1,22 @@ CREATE TABLE `performance` ( - `path` text NOT NULL, - `search` text, - `time` integer NOT NULL, - `created_at` integer DEFAULT (current_timestamp) + `path` text NOT NULL, + `search` text, + `time` integer NOT NULL, + `created_at` integer DEFAULT (CURRENT_TIMESTAMP) ); + --> statement-breakpoint CREATE TABLE `session` ( - `id` text PRIMARY KEY NOT NULL, - `created_at` integer DEFAULT (current_timestamp), - `expires_at` integer NOT NULL, - `user_id` text NOT NULL + `id` text PRIMARY KEY NOT NULL, + `created_at` integer DEFAULT (CURRENT_TIMESTAMP), + `expires_at` integer NOT NULL, + `user_id` text NOT NULL ); + --> statement-breakpoint CREATE TABLE `user` ( - `id` text PRIMARY KEY NOT NULL, - `created_at` integer DEFAULT (current_timestamp) NOT NULL, - `email` text NOT NULL, - `name` text NOT NULL + `id` text PRIMARY KEY NOT NULL, + `created_at` integer DEFAULT (CURRENT_TIMESTAMP) NOT NULL, + `email` text NOT NULL, + `name` text NOT NULL ); diff --git a/drizzle/0001_classy_justin_hammer.sql b/drizzle/0001_classy_justin_hammer.sql index 73e05a3..c4963a0 100644 --- a/drizzle/0001_classy_justin_hammer.sql +++ b/drizzle/0001_classy_justin_hammer.sql @@ -1 +1,4 @@ -ALTER TABLE `performance` ALTER COLUMN "created_at" TO "created_at" integer DEFAULT (STRFTIME('%s', 'now') * 1000); \ No newline at end of file +ALTER TABLE + `performance` +ALTER COLUMN + "created_at" TO "created_at" integer DEFAULT (STRFTIME('%s', 'now') * 1000); diff --git a/drizzle/0002_chubby_vance_astro.sql b/drizzle/0002_chubby_vance_astro.sql index 1d1bfd7..11a79cd 100644 --- a/drizzle/0002_chubby_vance_astro.sql +++ b/drizzle/0002_chubby_vance_astro.sql @@ -1,7 +1,7 @@ CREATE TABLE `image` ( - `created_at` integer DEFAULT (current_timestamp), - `url` text NOT NULL, - `average` text NOT NULL, - `blurhash` text NOT NULL, - `mime` text NOT NULL + `created_at` integer DEFAULT (CURRENT_TIMESTAMP), + `url` text NOT NULL, + `average` text NOT NULL, + `blurhash` text NOT NULL, + `mime` text NOT NULL ); diff --git a/drizzle/0003_watery_purple_man.sql b/drizzle/0003_watery_purple_man.sql index 097de92..d95bf79 100644 --- a/drizzle/0003_watery_purple_man.sql +++ b/drizzle/0003_watery_purple_man.sql @@ -1,7 +1,7 @@ CREATE TABLE `document` ( - `name` text NOT NULL, - `last_modified` integer NOT NULL, - `contentType` text NOT NULL, - `size` integer NOT NULL, - `perm` text NOT NULL + `name` text NOT NULL, + `last_modified` integer NOT NULL, + `contentType` text NOT NULL, + `size` integer NOT NULL, + `perm` text NOT NULL ); diff --git a/drizzle/0004_fat_captain_marvel.sql b/drizzle/0004_fat_captain_marvel.sql index a36a684..fc70d49 100644 --- a/drizzle/0004_fat_captain_marvel.sql +++ b/drizzle/0004_fat_captain_marvel.sql @@ -1,13 +1,38 @@ -PRAGMA foreign_keys=OFF;--> statement-breakpoint -CREATE TABLE `__new_document` ( - `name` text PRIMARY KEY NOT NULL, - `last_modified` integer NOT NULL, - `contentType` text NOT NULL, - `size` integer NOT NULL, - `perm` text NOT NULL -); +PRAGMA foreign_keys = OFF; + --> statement-breakpoint -INSERT INTO `__new_document`("name", "last_modified", "contentType", "size", "perm") SELECT "name", "last_modified", "contentType", "size", "perm" FROM `document`;--> statement-breakpoint -DROP TABLE `document`;--> statement-breakpoint -ALTER TABLE `__new_document` RENAME TO `document`;--> statement-breakpoint -PRAGMA foreign_keys=ON; \ No newline at end of file +CREATE TABLE `__new_document` ( + `name` text PRIMARY KEY NOT NULL, + `last_modified` integer NOT NULL, + `contentType` text NOT NULL, + `size` integer NOT NULL, + `perm` text NOT NULL +); + +--> statement-breakpoint +INSERT INTO + `__new_document`( + "name", + "last_modified", + "contentType", + "size", + "perm" + ) +SELECT + "name", + "last_modified", + "contentType", + "size", + "perm" +FROM + `document`; + +--> statement-breakpoint +DROP TABLE `document`; + +--> statement-breakpoint +ALTER TABLE + `__new_document` RENAME TO `document`; + +--> statement-breakpoint +PRAGMA foreign_keys = ON; diff --git a/drizzle/0005_illegal_roland_deschain.sql b/drizzle/0005_illegal_roland_deschain.sql index a8ddf75..c852f02 100644 --- a/drizzle/0005_illegal_roland_deschain.sql +++ b/drizzle/0005_illegal_roland_deschain.sql @@ -1 +1,2 @@ -ALTER TABLE `document` RENAME COLUMN "contentType" TO "content_type"; \ No newline at end of file +ALTER TABLE + `document` RENAME COLUMN "contentType" TO "content_type"; diff --git a/drizzle/0006_acoustic_the_initiative.sql b/drizzle/0006_acoustic_the_initiative.sql index 4391aeb..d1dbe2c 100644 --- a/drizzle/0006_acoustic_the_initiative.sql +++ b/drizzle/0006_acoustic_the_initiative.sql @@ -1 +1,4 @@ -ALTER TABLE `document` ADD `content` text; \ No newline at end of file +ALTER TABLE + `document` +ADD + `content` text; diff --git a/drizzle/0007_silly_synch.sql b/drizzle/0007_silly_synch.sql index af46e2d..8c88fed 100644 --- a/drizzle/0007_silly_synch.sql +++ b/drizzle/0007_silly_synch.sql @@ -1 +1,4 @@ -ALTER TABLE `document` ALTER COLUMN "content" TO "content" text NOT NULL; \ No newline at end of file +ALTER TABLE + `document` +ALTER COLUMN + "content" TO "content" text NOT NULL; diff --git a/drizzle/0008_loud_mephisto.sql b/drizzle/0008_loud_mephisto.sql index f8fee86..f75179e 100644 --- a/drizzle/0008_loud_mephisto.sql +++ b/drizzle/0008_loud_mephisto.sql @@ -1 +1,4 @@ -ALTER TABLE `document` ALTER COLUMN "content" TO "content" text; \ No newline at end of file +ALTER TABLE + `document` +ALTER COLUMN + "content" TO "content" text; diff --git a/drizzle/0009_free_robin_chapel.sql b/drizzle/0009_free_robin_chapel.sql index c9f6443..ce18d09 100644 --- a/drizzle/0009_free_robin_chapel.sql +++ b/drizzle/0009_free_robin_chapel.sql @@ -1,12 +1,17 @@ CREATE TABLE `cache` ( - `scope` text NOT NULL, - `key` text PRIMARY KEY NOT NULL, - `json` text, - `binary` blob, - `created_at` integer DEFAULT (current_timestamp), - `expires_at` integer + `scope` text NOT NULL, + `key` text PRIMARY KEY NOT NULL, + `json` text, + `binary` blob, + `created_at` integer DEFAULT (CURRENT_TIMESTAMP), + `expires_at` integer ); + --> statement-breakpoint -CREATE INDEX `key_idx` ON `cache` (`key`);--> statement-breakpoint -CREATE INDEX `scope_idx` ON `cache` (`scope`);--> statement-breakpoint -CREATE INDEX `name_idx` ON `document` (`name`); \ No newline at end of file +CREATE INDEX `key_idx` ON `cache` (`key`); + +--> statement-breakpoint +CREATE INDEX `scope_idx` ON `cache` (`scope`); + +--> statement-breakpoint +CREATE INDEX `name_idx` ON `document` (`name`); diff --git a/drizzle/0010_youthful_tyrannus.sql b/drizzle/0010_youthful_tyrannus.sql index 01f1491..0fa65f6 100644 --- a/drizzle/0010_youthful_tyrannus.sql +++ b/drizzle/0010_youthful_tyrannus.sql @@ -1 +1,2 @@ -ALTER TABLE `image` RENAME COLUMN "blurhash" TO "thumbhash"; \ No newline at end of file +ALTER TABLE + `image` RENAME COLUMN "blurhash" TO "thumbhash"; diff --git a/drizzle/0011_reflective_frank_castle.sql b/drizzle/0011_reflective_frank_castle.sql index 892f9d3..9087749 100644 --- a/drizzle/0011_reflective_frank_castle.sql +++ b/drizzle/0011_reflective_frank_castle.sql @@ -1,7 +1,22 @@ -DROP INDEX "key_idx";--> statement-breakpoint -DROP INDEX "scope_idx";--> statement-breakpoint -DROP INDEX "name_idx";--> statement-breakpoint -ALTER TABLE `image` ALTER COLUMN "created_at" TO "created_at" integer DEFAULT (unixepoch());--> statement-breakpoint -CREATE INDEX `key_idx` ON `cache` (`key`);--> statement-breakpoint -CREATE INDEX `scope_idx` ON `cache` (`scope`);--> statement-breakpoint +DROP INDEX "key_idx"; + +--> statement-breakpoint +DROP INDEX "scope_idx"; + +--> statement-breakpoint +DROP INDEX "name_idx"; + +--> statement-breakpoint +ALTER TABLE + `image` +ALTER COLUMN + "created_at" TO "created_at" integer DEFAULT (unixepoch()); + +--> statement-breakpoint +CREATE INDEX `key_idx` ON `cache` (`key`); + +--> statement-breakpoint +CREATE INDEX `scope_idx` ON `cache` (`scope`); + +--> statement-breakpoint CREATE INDEX `name_idx` ON `document` (`name`); diff --git a/drizzle/meta/0011_snapshot.json b/drizzle/meta/0011_snapshot.json index ac316a5..2494226 100644 --- a/drizzle/meta/0011_snapshot.json +++ b/drizzle/meta/0011_snapshot.json @@ -306,4 +306,4 @@ "internal": { "indexes": {} } -} \ No newline at end of file +} diff --git a/drizzle/meta/_journal.json b/drizzle/meta/_journal.json index a4c5d06..f0b4ff0 100644 --- a/drizzle/meta/_journal.json +++ b/drizzle/meta/_journal.json @@ -87,4 +87,4 @@ "breakpoints": true } ] -} \ No newline at end of file +} diff --git a/lib/db/schema.ts b/lib/db/schema.ts index 3574ddd..979c29c 100644 --- a/lib/db/schema.ts +++ b/lib/db/schema.ts @@ -12,7 +12,9 @@ export const userTable = sqliteTable("user", { id: text() .primaryKey(), createdAt: integer("created_at", { mode: "timestamp" }) - .default(sql`(current_timestamp)`) + .default(sql` + (CURRENT_TIMESTAMP) + `) .notNull(), email: text() .notNull(), @@ -24,7 +26,9 @@ export const sessionTable = sqliteTable("session", { id: text("id") .primaryKey(), createdAt: integer("created_at", { mode: "timestamp_ms" }).default( - sql`(current_timestamp)`, + sql` + (CURRENT_TIMESTAMP) + `, ), expiresAt: integer("expires_at", { mode: "timestamp" }) .notNull(), @@ -38,12 +42,16 @@ export const performanceTable = sqliteTable("performance", { time: int().notNull(), createdAt: integer("created_at", { mode: "timestamp_ms", - }).default(sql`(STRFTIME('%s', 'now') * 1000)`), + }).default(sql` + (STRFTIME('%s', 'now') * 1000) + `), }); export const imageTable = sqliteTable("image", { createdAt: integer("created_at", { mode: "timestamp" }).default( - sql`(unixepoch())`, + sql` + (unixepoch()) + `, ), url: text().notNull(), average: text().notNull(), @@ -70,7 +78,9 @@ export const cacheTable = sqliteTable("cache", { json: text({ mode: "json" }), binary: blob(), createdAt: integer("created_at", { mode: "timestamp" }).default( - sql`(current_timestamp)`, + sql` + (CURRENT_TIMESTAMP) + `, ), expiresAt: integer("expires_at", { mode: "timestamp" }), }, (table) => { diff --git a/lib/image.ts b/lib/image.ts index dc3490c..c0a0ffd 100644 --- a/lib/image.ts +++ b/lib/image.ts @@ -8,7 +8,6 @@ import { DATA_DIR } from "@lib/env.ts"; import { db } from "@lib/db/sqlite.ts"; import { imageTable } from "@lib/db/schema.ts"; import { eq } from "drizzle-orm"; -import sharp from "sharp"; const log = createLogger("cache/image"); @@ -158,6 +157,8 @@ async function resizeImage( mediaType: string; }, ) { + const sharp = (await import("sharp")).default; + try { log.debug("Resizing image", { params }); @@ -211,6 +212,8 @@ async function resizeImage( async function createThumbhash( image: Uint8Array, ): Promise<{ hash: string; average: string }> { + const sharp = (await import("sharp")).default; + try { const resizedImage = await sharp(image) .resize(100, 100, { fit: "cover" }) // Keep aspect ratio within bounds @@ -238,6 +241,8 @@ async function createThumbhash( * Verifies that an image buffer contains valid image data */ async function verifyImage(imageBuffer: Uint8Array): Promise { + const sharp = (await import("sharp")).default; + try { const metadata = await sharp(imageBuffer).metadata(); return !!(metadata.width && metadata.height && metadata.format);