diff --git a/bun.lockb b/bun.lockb
index 1d2ea10..6677402 100644
Binary files a/bun.lockb and b/bun.lockb differ
diff --git a/package.json b/package.json
index 0588ad5..48043ae 100644
--- a/package.json
+++ b/package.json
@@ -33,6 +33,7 @@
},
"dependencies": {
"@imagemagick/magick-wasm": "^0.0.31",
- "lucide-svelte": "^0.456.0"
+ "lucide-svelte": "^0.456.0",
+ "wasm-vips": "^0.0.11"
}
}
diff --git a/src/app.html b/src/app.html
index d086c20..77a5ff5 100644
--- a/src/app.html
+++ b/src/app.html
@@ -4,7 +4,6 @@
-
%sveltekit.head%
diff --git a/src/lib/components/visual/Uploader.svelte b/src/lib/components/visual/Uploader.svelte
new file mode 100644
index 0000000..3d56ad2
--- /dev/null
+++ b/src/lib/components/visual/Uploader.svelte
@@ -0,0 +1,4 @@
+
+
+
diff --git a/src/lib/converters/converter.ts b/src/lib/converters/converter.ts
new file mode 100644
index 0000000..237db11
--- /dev/null
+++ b/src/lib/converters/converter.ts
@@ -0,0 +1,9 @@
+import type { IFile } from "$lib/types";
+
+export class Converter {
+ public supportedFormats: string[] = [];
+ // eslint-disable-next-line @typescript-eslint/no-unused-vars
+ public async convert(input: IFile, output: IFile): Promise {
+ throw new Error("Not implemented");
+ }
+}
diff --git a/src/lib/converters/index.svelte.ts b/src/lib/converters/index.svelte.ts
new file mode 100644
index 0000000..f593609
--- /dev/null
+++ b/src/lib/converters/index.svelte.ts
@@ -0,0 +1,15 @@
+import Vips from "wasm-vips";
+
+class Converters {
+ public vips = $state(null!);
+ public loaded = $derived(this.vips !== null);
+}
+
+export const converters = new Converters();
+
+// Vips().then((vips) => {
+// converters.vips = vips;
+// });
+
+// the above *does* work but it blocks the ui thread whilst wasm is loading
+// we can use a web worker to remedy this, see +layout.ts for details
diff --git a/src/lib/converters/vips.ts b/src/lib/converters/vips.ts
new file mode 100644
index 0000000..1a46ee2
--- /dev/null
+++ b/src/lib/converters/vips.ts
@@ -0,0 +1,9 @@
+import type { IFile } from "$lib/types";
+import { Converter } from "./converter";
+
+export class VipsConverter extends Converter {
+ public supportedFormats = [""];
+ public convert(input: IFile, output: IFile): Promise {
+ throw new Error("Not implemented");
+ }
+}
diff --git a/src/lib/index.ts b/src/lib/index.ts
deleted file mode 100644
index 856f2b6..0000000
--- a/src/lib/index.ts
+++ /dev/null
@@ -1 +0,0 @@
-// place files you want to import through the `$lib` alias in this folder.
diff --git a/src/lib/types/file.ts b/src/lib/types/file.ts
new file mode 100644
index 0000000..fe42fc0
--- /dev/null
+++ b/src/lib/types/file.ts
@@ -0,0 +1,5 @@
+export interface IFile {
+ name: string;
+ extension: string;
+ buffer: ArrayBuffer;
+}
diff --git a/src/lib/types/index.ts b/src/lib/types/index.ts
new file mode 100644
index 0000000..375123f
--- /dev/null
+++ b/src/lib/types/index.ts
@@ -0,0 +1 @@
+export * from "./file";
diff --git a/src/lib/workers/vips.ts b/src/lib/workers/vips.ts
new file mode 100644
index 0000000..8e76e12
--- /dev/null
+++ b/src/lib/workers/vips.ts
@@ -0,0 +1,9 @@
+import Vips from "wasm-vips";
+
+Vips()
+ .then((vips) => {
+ postMessage({ type: "success", vips });
+ })
+ .catch((error) => {
+ postMessage({ type: "error", error });
+ });
diff --git a/src/routes/+layout.svelte b/src/routes/+layout.svelte
index 7be3ce4..fe4774e 100644
--- a/src/routes/+layout.svelte
+++ b/src/routes/+layout.svelte
@@ -1,6 +1,7 @@
-{@render children()}
+{@render children()}
\ No newline at end of file
diff --git a/src/routes/+layout.ts b/src/routes/+layout.ts
index 25a8fed..b10c57d 100644
--- a/src/routes/+layout.ts
+++ b/src/routes/+layout.ts
@@ -1,5 +1,10 @@
-import { init } from "./util/magick";
+import { browser } from "$app/environment";
+import VipsWorker from "$lib/workers/vips?worker";
-export async function load({ fetch }) {
- await init(fetch);
-}
+export const load = () => {
+ if (!browser) return;
+ const worker = new VipsWorker();
+ worker.onmessage = (e) => {
+ console.log(e.data);
+ };
+};
diff --git a/src/routes/+page.svelte b/src/routes/+page.svelte
index e69de29..c8bb4bc 100644
--- a/src/routes/+page.svelte
+++ b/src/routes/+page.svelte
@@ -0,0 +1,11 @@
+
+
+
diff --git a/src/routes/util/magick.ts b/src/routes/util/magick.ts
deleted file mode 100644
index c2a4b39..0000000
--- a/src/routes/util/magick.ts
+++ /dev/null
@@ -1,14 +0,0 @@
-import { initializeImageMagick } from "@imagemagick/magick-wasm";
-
-export let initialized = false;
-
-export const init = async (
- fetch: (input: RequestInfo | URL, init?: RequestInit) => Promise,
-) => {
- if (initialized) return;
- const wasmBytes = await fetch("/magick.wasm").then((res) =>
- res.arrayBuffer(),
- );
- await initializeImageMagick(wasmBytes);
- initialized = true;
-};
diff --git a/vite.config.ts b/vite.config.ts
index bbf8c7d..cfe6112 100644
--- a/vite.config.ts
+++ b/vite.config.ts
@@ -1,6 +1,24 @@
-import { sveltekit } from '@sveltejs/kit/vite';
-import { defineConfig } from 'vite';
+import { sveltekit } from "@sveltejs/kit/vite";
+import { defineConfig } from "vite";
export default defineConfig({
- plugins: [sveltekit()]
+ plugins: [
+ sveltekit(),
+ {
+ name: "vips-request-middleware",
+ configureServer(server) {
+ server.middlewares.use((req, res, next) => {
+ res.setHeader(
+ "Cross-Origin-Embedder-Policy",
+ "require-corp",
+ );
+ res.setHeader("Cross-Origin-Opener-Policy", "same-origin");
+ next();
+ });
+ },
+ },
+ ],
+ optimizeDeps: {
+ exclude: ["wasm-vips"],
+ },
});