A Docker-like CLI and HTTP API for managing headless VMs
1import { Effect } from "effect";
2import type { DeleteResult, InsertResult } from "kysely";
3import { ctx } from "./context.ts";
4import type { Image } from "./db.ts";
5import { DbError } from "./errors.ts";
6
7export const listImages = (): Effect.Effect<Image[], DbError, never> =>
8 Effect.tryPromise({
9 try: () => ctx.db.selectFrom("images").selectAll().execute(),
10 catch: (error) =>
11 new DbError({
12 message: error instanceof Error ? error.message : String(error),
13 }),
14 });
15
16export const getImage = (
17 id: string,
18): Effect.Effect<Image | undefined, DbError, never> =>
19 Effect.tryPromise({
20 try: () =>
21 ctx.db
22 .selectFrom("images")
23 .selectAll()
24 .where((eb) =>
25 eb.or([
26 eb.and([
27 eb("repository", "=", id.split(":")[0]),
28 eb("tag", "=", id.split(":")[1] || "latest"),
29 ]),
30 eb("id", "=", id),
31 eb("digest", "=", id),
32 ])
33 )
34 .executeTakeFirst(),
35 catch: (error) =>
36 new DbError({
37 message: error instanceof Error ? error.message : String(error),
38 }),
39 });
40
41export const saveImage = (
42 image: Image,
43): Effect.Effect<InsertResult[], DbError, never> =>
44 Effect.tryPromise({
45 try: () =>
46 ctx.db
47 .insertInto("images")
48 .values(image)
49 .onConflict((oc) =>
50 oc.column("repository").column("tag").doUpdateSet({
51 size: image.size,
52 path: image.path,
53 format: image.format,
54 digest: image.digest,
55 })
56 )
57 .execute(),
58 catch: (error) =>
59 new DbError({
60 message: error instanceof Error ? error.message : String(error),
61 }),
62 });
63
64export const deleteImage = (
65 id: string,
66): Effect.Effect<DeleteResult[], DbError, never> =>
67 Effect.tryPromise({
68 try: () =>
69 ctx.db
70 .deleteFrom("images")
71 .where((eb) =>
72 eb.or([
73 eb.and([
74 eb("repository", "=", id.split(":")[0]),
75 eb("tag", "=", id.split(":")[1] || "latest"),
76 ]),
77 eb("id", "=", id),
78 ])
79 )
80 .execute(),
81 catch: (error) =>
82 new DbError({
83 message: error instanceof Error ? error.message : String(error),
84 }),
85 });