From 2a6ad97a41865795aa99d7976fdc49c141c7dbca Mon Sep 17 00:00:00 2001
From: natalie <22222885+espeon@users.noreply.github.com>
Date: Tue, 19 Nov 2024 21:43:05 -0600
Subject: [PATCH] Get project ready for deployment
---
.dockerignore | 0
.gitignore | 1 +
apps/aqua/Dockerfile | 54 +++++++++++
apps/aqua/package.json | 19 +---
.../{src => }/public/fonts/LM-bold-italic.ttf | Bin
.../public/fonts/LM-bold-italic.woff | Bin
.../public/fonts/LM-bold-italic.woff2 | Bin
apps/aqua/{src => }/public/fonts/LM-bold.ttf | Bin
apps/aqua/{src => }/public/fonts/LM-bold.woff | Bin
.../aqua/{src => }/public/fonts/LM-bold.woff2 | Bin
.../aqua/{src => }/public/fonts/LM-italic.ttf | Bin
.../{src => }/public/fonts/LM-italic.woff | Bin
.../{src => }/public/fonts/LM-italic.woff2 | Bin
.../{src => }/public/fonts/LM-regular.ttf | Bin
.../{src => }/public/fonts/LM-regular.woff | Bin
.../{src => }/public/fonts/LM-regular.woff2 | Bin
.../public/fonts/Libertinus-bold-italic.woff2 | Bin
.../public/fonts/Libertinus-bold.woff2 | Bin
.../public/fonts/Libertinus-italic.woff2 | Bin
.../public/fonts/Libertinus-regular.woff2 | Bin
.../fonts/Libertinus-semibold-italic.woff2 | Bin
.../public/fonts/Libertinus-semibold.woff2 | Bin
apps/aqua/{src => }/public/latex.css | 0
apps/aqua/src/auth/router.ts | 30 +++---
apps/aqua/src/index.ts | 25 ++---
apps/aqua/tsconfig.json | 6 +-
apps/aqua/tsup.config.ts | 15 +++
apps/viridian/go.mod | 5 -
apps/viridian/go.sum | 2 -
apps/viridian/main.go | 29 ------
apps/viridian/package.json | 11 ---
apps/viridian/server/server.go | 62 ------------
apps/viridian/types/types.go | 46 ---------
apps/viridian/worker/ffmpeg.go | 1 -
apps/viridian/worker/worker.go | 47 ----------
bun.lockb | Bin 184992 -> 184592 bytes
compose.dev.yml | 88 ++++++++++--------
compose.yaml | 17 ++++
packages/db/connect.ts | 7 +-
packages/jetstring/src/index.ts | 2 -
packages/tsconfig/base.json | 2 +-
41 files changed, 180 insertions(+), 289 deletions(-)
create mode 100644 .dockerignore
create mode 100644 apps/aqua/Dockerfile
rename apps/aqua/{src => }/public/fonts/LM-bold-italic.ttf (100%)
rename apps/aqua/{src => }/public/fonts/LM-bold-italic.woff (100%)
rename apps/aqua/{src => }/public/fonts/LM-bold-italic.woff2 (100%)
rename apps/aqua/{src => }/public/fonts/LM-bold.ttf (100%)
rename apps/aqua/{src => }/public/fonts/LM-bold.woff (100%)
rename apps/aqua/{src => }/public/fonts/LM-bold.woff2 (100%)
rename apps/aqua/{src => }/public/fonts/LM-italic.ttf (100%)
rename apps/aqua/{src => }/public/fonts/LM-italic.woff (100%)
rename apps/aqua/{src => }/public/fonts/LM-italic.woff2 (100%)
rename apps/aqua/{src => }/public/fonts/LM-regular.ttf (100%)
rename apps/aqua/{src => }/public/fonts/LM-regular.woff (100%)
rename apps/aqua/{src => }/public/fonts/LM-regular.woff2 (100%)
rename apps/aqua/{src => }/public/fonts/Libertinus-bold-italic.woff2 (100%)
rename apps/aqua/{src => }/public/fonts/Libertinus-bold.woff2 (100%)
rename apps/aqua/{src => }/public/fonts/Libertinus-italic.woff2 (100%)
rename apps/aqua/{src => }/public/fonts/Libertinus-regular.woff2 (100%)
rename apps/aqua/{src => }/public/fonts/Libertinus-semibold-italic.woff2 (100%)
rename apps/aqua/{src => }/public/fonts/Libertinus-semibold.woff2 (100%)
rename apps/aqua/{src => }/public/latex.css (100%)
create mode 100644 apps/aqua/tsup.config.ts
delete mode 100644 apps/viridian/go.mod
delete mode 100644 apps/viridian/go.sum
delete mode 100644 apps/viridian/main.go
delete mode 100644 apps/viridian/package.json
delete mode 100644 apps/viridian/server/server.go
delete mode 100644 apps/viridian/types/types.go
delete mode 100644 apps/viridian/worker/ffmpeg.go
delete mode 100644 apps/viridian/worker/worker.go
create mode 100644 compose.yaml
diff --git a/.dockerignore b/.dockerignore
new file mode 100644
index 0000000..e69de29
diff --git a/.gitignore b/.gitignore
index 6b142b0..eb95056 100644
--- a/.gitignore
+++ b/.gitignore
@@ -15,6 +15,7 @@ node_modules/
# production
/build
*/dist
+**/dist
# misc
.DS_Store
diff --git a/apps/aqua/Dockerfile b/apps/aqua/Dockerfile
new file mode 100644
index 0000000..df5aead
--- /dev/null
+++ b/apps/aqua/Dockerfile
@@ -0,0 +1,54 @@
+# Use the official Bun image as base
+FROM oven/bun:1.0 AS builder
+
+# Set working directory
+WORKDIR /app
+
+# Copy root workspace files
+COPY package.json bun.lockb ./
+
+# Copy turbo.json
+COPY turbo.json ./
+
+# Copy workspace packages
+COPY packages/db/ ./packages/db/
+COPY packages/lexicons/ ./packages/lexicons/
+COPY packages/tsconfig/ ./packages/tsconfig/
+
+# Copy the aqua app
+COPY apps/aqua/ ./apps/aqua/
+
+# Install dependencies
+RUN bun install
+
+# Build workspace packages (if needed)
+RUN bun run build --filter=@teal/db
+RUN bun run build --filter=@teal/lexicons
+
+# Build the aqua app
+WORKDIR /app/apps/aqua
+RUN bun run build
+
+# Start production image (node lts ideally)
+FROM node:bookworm-slim
+
+WORKDIR /app
+
+# Copy built assets from builder
+COPY --from=builder /app/apps/aqua/dist ./dist
+# copy base node modules
+COPY --from=builder /app/node_modules ./node_modules
+COPY --from=builder /app/apps/aqua/node_modules ./node_modules
+COPY --from=builder /app/apps/aqua/package.json ./
+
+# move public to cwd
+RUN mv ./dist/public ./public
+
+# Set environment variables
+ENV NODE_ENV=production
+
+# Expose the port your app runs on
+EXPOSE 3000
+
+# Start the application
+CMD ["npm", "run", "start"]
diff --git a/apps/aqua/package.json b/apps/aqua/package.json
index 978f3c7..5f6d7f9 100644
--- a/apps/aqua/package.json
+++ b/apps/aqua/package.json
@@ -7,8 +7,9 @@
"scripts": {
"dev": "tsx watch --clear-screen=false src/index.ts | pino-pretty",
"bun:dev": "bun run --hot src/index.ts | pino-pretty",
- "build": "tsup",
- "start": "node dist/index.js",
+ "deno:dev": "deno run --allow-net --allow-read --allow-env --allow-run --unstable --watch src/index.ts | pino-pretty",
+ "build": "tsup && cp -r public dist/",
+ "start": "node dist/index.cjs | pino-pretty",
"lexgen": "lex gen-server ./src/lexicon ./lexicons/*",
"clean": "rimraf dist coverage",
"check-types": "tsc --noEmit",
@@ -21,7 +22,7 @@
"@atproto/common": "^0.4.4",
"@atproto/identity": "^0.4.3",
"@atproto/lexicon": "^0.4.2",
- "@atproto/oauth-client-node": "^0.2.0",
+ "@atproto/oauth-client-node": "^0.2.1",
"@atproto/sync": "^0.1.5",
"@atproto/syntax": "^0.3.0",
"@atproto/xrpc-server": "^0.6.4",
@@ -49,15 +50,5 @@
"tsup": "^8.3.5",
"tsx": "^4.19.2",
"typescript": "^5.6.3"
- },
- "tsup": {
- "entry": [
- "src",
- "!src/**/__tests__/**",
- "!src/**/*.test.*"
- ],
- "splitting": false,
- "sourcemap": true,
- "clean": true
}
-}
\ No newline at end of file
+}
diff --git a/apps/aqua/src/public/fonts/LM-bold-italic.ttf b/apps/aqua/public/fonts/LM-bold-italic.ttf
similarity index 100%
rename from apps/aqua/src/public/fonts/LM-bold-italic.ttf
rename to apps/aqua/public/fonts/LM-bold-italic.ttf
diff --git a/apps/aqua/src/public/fonts/LM-bold-italic.woff b/apps/aqua/public/fonts/LM-bold-italic.woff
similarity index 100%
rename from apps/aqua/src/public/fonts/LM-bold-italic.woff
rename to apps/aqua/public/fonts/LM-bold-italic.woff
diff --git a/apps/aqua/src/public/fonts/LM-bold-italic.woff2 b/apps/aqua/public/fonts/LM-bold-italic.woff2
similarity index 100%
rename from apps/aqua/src/public/fonts/LM-bold-italic.woff2
rename to apps/aqua/public/fonts/LM-bold-italic.woff2
diff --git a/apps/aqua/src/public/fonts/LM-bold.ttf b/apps/aqua/public/fonts/LM-bold.ttf
similarity index 100%
rename from apps/aqua/src/public/fonts/LM-bold.ttf
rename to apps/aqua/public/fonts/LM-bold.ttf
diff --git a/apps/aqua/src/public/fonts/LM-bold.woff b/apps/aqua/public/fonts/LM-bold.woff
similarity index 100%
rename from apps/aqua/src/public/fonts/LM-bold.woff
rename to apps/aqua/public/fonts/LM-bold.woff
diff --git a/apps/aqua/src/public/fonts/LM-bold.woff2 b/apps/aqua/public/fonts/LM-bold.woff2
similarity index 100%
rename from apps/aqua/src/public/fonts/LM-bold.woff2
rename to apps/aqua/public/fonts/LM-bold.woff2
diff --git a/apps/aqua/src/public/fonts/LM-italic.ttf b/apps/aqua/public/fonts/LM-italic.ttf
similarity index 100%
rename from apps/aqua/src/public/fonts/LM-italic.ttf
rename to apps/aqua/public/fonts/LM-italic.ttf
diff --git a/apps/aqua/src/public/fonts/LM-italic.woff b/apps/aqua/public/fonts/LM-italic.woff
similarity index 100%
rename from apps/aqua/src/public/fonts/LM-italic.woff
rename to apps/aqua/public/fonts/LM-italic.woff
diff --git a/apps/aqua/src/public/fonts/LM-italic.woff2 b/apps/aqua/public/fonts/LM-italic.woff2
similarity index 100%
rename from apps/aqua/src/public/fonts/LM-italic.woff2
rename to apps/aqua/public/fonts/LM-italic.woff2
diff --git a/apps/aqua/src/public/fonts/LM-regular.ttf b/apps/aqua/public/fonts/LM-regular.ttf
similarity index 100%
rename from apps/aqua/src/public/fonts/LM-regular.ttf
rename to apps/aqua/public/fonts/LM-regular.ttf
diff --git a/apps/aqua/src/public/fonts/LM-regular.woff b/apps/aqua/public/fonts/LM-regular.woff
similarity index 100%
rename from apps/aqua/src/public/fonts/LM-regular.woff
rename to apps/aqua/public/fonts/LM-regular.woff
diff --git a/apps/aqua/src/public/fonts/LM-regular.woff2 b/apps/aqua/public/fonts/LM-regular.woff2
similarity index 100%
rename from apps/aqua/src/public/fonts/LM-regular.woff2
rename to apps/aqua/public/fonts/LM-regular.woff2
diff --git a/apps/aqua/src/public/fonts/Libertinus-bold-italic.woff2 b/apps/aqua/public/fonts/Libertinus-bold-italic.woff2
similarity index 100%
rename from apps/aqua/src/public/fonts/Libertinus-bold-italic.woff2
rename to apps/aqua/public/fonts/Libertinus-bold-italic.woff2
diff --git a/apps/aqua/src/public/fonts/Libertinus-bold.woff2 b/apps/aqua/public/fonts/Libertinus-bold.woff2
similarity index 100%
rename from apps/aqua/src/public/fonts/Libertinus-bold.woff2
rename to apps/aqua/public/fonts/Libertinus-bold.woff2
diff --git a/apps/aqua/src/public/fonts/Libertinus-italic.woff2 b/apps/aqua/public/fonts/Libertinus-italic.woff2
similarity index 100%
rename from apps/aqua/src/public/fonts/Libertinus-italic.woff2
rename to apps/aqua/public/fonts/Libertinus-italic.woff2
diff --git a/apps/aqua/src/public/fonts/Libertinus-regular.woff2 b/apps/aqua/public/fonts/Libertinus-regular.woff2
similarity index 100%
rename from apps/aqua/src/public/fonts/Libertinus-regular.woff2
rename to apps/aqua/public/fonts/Libertinus-regular.woff2
diff --git a/apps/aqua/src/public/fonts/Libertinus-semibold-italic.woff2 b/apps/aqua/public/fonts/Libertinus-semibold-italic.woff2
similarity index 100%
rename from apps/aqua/src/public/fonts/Libertinus-semibold-italic.woff2
rename to apps/aqua/public/fonts/Libertinus-semibold-italic.woff2
diff --git a/apps/aqua/src/public/fonts/Libertinus-semibold.woff2 b/apps/aqua/public/fonts/Libertinus-semibold.woff2
similarity index 100%
rename from apps/aqua/src/public/fonts/Libertinus-semibold.woff2
rename to apps/aqua/public/fonts/Libertinus-semibold.woff2
diff --git a/apps/aqua/src/public/latex.css b/apps/aqua/public/latex.css
similarity index 100%
rename from apps/aqua/src/public/latex.css
rename to apps/aqua/public/latex.css
diff --git a/apps/aqua/src/auth/router.ts b/apps/aqua/src/auth/router.ts
index 992d94f..29a022f 100644
--- a/apps/aqua/src/auth/router.ts
+++ b/apps/aqua/src/auth/router.ts
@@ -1,7 +1,7 @@
import { atclient } from "./client";
import { db } from "@teal/db/connect";
-import {atProtoSession} from "@teal/db/schema"
-import { eq } from "drizzle-orm"
+import { atProtoSession } from "@teal/db/schema";
+import { eq } from "drizzle-orm";
import { EnvWithCtx, TealContext } from "@/ctx";
import { Hono } from "hono";
import { tealSession } from "@teal/db/schema";
@@ -42,12 +42,12 @@ export async function callback(c: TealContext) {
maxAge: 60 * 60 * 24 * 365,
});
- if(params.get("spa")) {
+ if (params.get("spa")) {
return c.json({
provider: "atproto",
jwt: did,
accessToken: did,
- })
+ });
}
return c.redirect("/");
@@ -57,7 +57,6 @@ export async function callback(c: TealContext) {
}
}
-
// Refresh an access token from a refresh token. Should be only used in SPAs.
// Pass in 'key' and 'refresh_token' query params.
export async function refresh(c: TealContext) {
@@ -67,17 +66,20 @@ export async function refresh(c: TealContext) {
const params = new URLSearchParams(honoParams);
let key = params.get("key");
let refresh_token = params.get("refresh_token");
- if(!key || !refresh_token) {
- return Response.json({error: "Missing key or refresh_token"});
+ if (!key || !refresh_token) {
+ return Response.json({ error: "Missing key or refresh_token" });
}
// check if refresh token is valid
- let r_tk_check = await db.select().from(atProtoSession).where(eq(atProtoSession.key, key)).execute() as any;
-
- if(r_tk_check.tokenSet.refresh_token !== refresh_token) {
- return Response.json({error: "Invalid refresh token"});
+ let r_tk_check = (await db
+ .select()
+ .from(atProtoSession)
+ .where(eq(atProtoSession.key, key))
+ .execute()) as any;
+
+ if (r_tk_check.tokenSet.refresh_token !== refresh_token) {
+ return Response.json({ error: "Invalid refresh token" });
}
-
const session = await atclient.restore(key);
const did = session.did;
@@ -108,10 +110,10 @@ export async function refresh(c: TealContext) {
});
return c.json({
- provider:"atproto",
+ provider: "atproto",
jwt: did,
accessToken: did,
- })
+ });
} catch (e) {
console.error(e);
return Response.json({ error: "Could not authorize user" });
diff --git a/apps/aqua/src/index.ts b/apps/aqua/src/index.ts
index 52e5075..70a932d 100644
--- a/apps/aqua/src/index.ts
+++ b/apps/aqua/src/index.ts
@@ -1,5 +1,5 @@
import { serve } from "@hono/node-server";
-import { serveStatic } from '@hono/node-server/serve-static'
+import { serveStatic } from "@hono/node-server/serve-static";
import { Hono } from "hono";
import { db } from "@teal/db/connect";
import { getAuthRouter } from "./auth/router";
@@ -14,7 +14,7 @@ import { sanitizeUrl } from "@braintree/sanitize-url";
const HEAD = `
- `
+ `;
const logger = pino({ name: "server start" });
@@ -48,11 +48,13 @@ app.get("/", async (c) => {
home
stamp
- logout
+
-
+
`,
);
@@ -210,12 +212,13 @@ app.post("/stamp", async (c: TealContext) => {
const body = await c.req.parseBody();
let { artist, track, link } = body;
// shouldn't get a File, escape now
- if (artist instanceof File || track instanceof File || link instanceof File) return c.redirect("/stamp");
-
+ if (artist instanceof File || track instanceof File || link instanceof File)
+ return c.redirect("/stamp");
+
artist = sanitizeUrl(artist);
track = sanitizeUrl(track);
link = sanitizeUrl(link);
-
+
const agent = await getSessionAgent(c);
if (agent) {
@@ -245,8 +248,6 @@ app.post("/stamp", async (c: TealContext) => {
embed: embed,
});
- console.log(`post: ${post}`);
-
return c.html(
`
${HEAD}
@@ -272,10 +273,12 @@ app.post("/stamp", async (c: TealContext) => {
`,
);
}
- return c.html(`doesn't look like you're logged in... try logging in?
`);
+ return c.html(
+ `doesn't look like you're logged in... try logging in?
`,
+ );
});
-app.use('/*', serveStatic({ root: '/src/public' }));
+app.use("/*", serveStatic({ root: "/public" }));
const run = async () => {
logger.info("Running in " + navigator.userAgent);
diff --git a/apps/aqua/tsconfig.json b/apps/aqua/tsconfig.json
index 2f30ce2..c76b141 100644
--- a/apps/aqua/tsconfig.json
+++ b/apps/aqua/tsconfig.json
@@ -1,9 +1,11 @@
{
"extends": "@teal/tsconfig/base.json",
+ "include": ["src/**/*"],
+ "exclude": ["node_modules", "dist"],
"compilerOptions": {
+ "baseUrl": ".",
"paths": {
- "@/*": ["./src/*"],
- "+lexicons/*": ["../../lexicons/*"]
+ "@/*": ["src/*"]
}
}
}
diff --git a/apps/aqua/tsup.config.ts b/apps/aqua/tsup.config.ts
new file mode 100644
index 0000000..ab343b2
--- /dev/null
+++ b/apps/aqua/tsup.config.ts
@@ -0,0 +1,15 @@
+import { defineConfig } from "tsup";
+
+export default defineConfig({
+ format: ["cjs"],
+ entry: ["./src/index.ts"],
+ dts: false,
+ shims: true,
+ skipNodeModulesBundle: false,
+ clean: true,
+ minify: false,
+ bundle: true,
+ // https://github.com/egoist/tsup/issues/619
+ noExternal: [/(.*)/, "@teal/db", "@teal/lexicons"],
+ splitting: false,
+});
diff --git a/apps/viridian/go.mod b/apps/viridian/go.mod
deleted file mode 100644
index e84049b..0000000
--- a/apps/viridian/go.mod
+++ /dev/null
@@ -1,5 +0,0 @@
-module viridian
-
-go 1.21.5
-
-require github.com/pebbe/zmq4 v1.2.11
diff --git a/apps/viridian/go.sum b/apps/viridian/go.sum
deleted file mode 100644
index a607dbc..0000000
--- a/apps/viridian/go.sum
+++ /dev/null
@@ -1,2 +0,0 @@
-github.com/pebbe/zmq4 v1.2.11 h1:Ua5mgIaZeabUGnH7tqswkUcjkL7JYGai5e8v4hpEU9Q=
-github.com/pebbe/zmq4 v1.2.11/go.mod h1:nqnPueOapVhE2wItZ0uOErngczsJdLOGkebMxaO8r48=
diff --git a/apps/viridian/main.go b/apps/viridian/main.go
deleted file mode 100644
index dd28bb0..0000000
--- a/apps/viridian/main.go
+++ /dev/null
@@ -1,29 +0,0 @@
-package main
-
-import (
- "fmt"
- "sync"
-
- server "viridian/server"
- worker "viridian/worker"
-)
-
-func main() {
- var wg sync.WaitGroup
-
- // Run the server in a goroutine
- go server.RunServer()
-
- // Simulate workers, each running in a separate goroutine
- workerCount := worker.GetCoreCount()
- fmt.Printf("Starting %d workers\n", workerCount)
- for i := 1; i <= workerCount; i++ {
- fmt.Printf("Starting worker %d\n", i)
- workerID := fmt.Sprintf("worker-%d", i)
- wg.Add(1)
- go worker.RunWorker(workerID, &wg)
- }
-
- // Wait for all workers to complete (this won't happen in this example since workers run indefinitely)
- wg.Wait()
-}
diff --git a/apps/viridian/package.json b/apps/viridian/package.json
deleted file mode 100644
index 7718996..0000000
--- a/apps/viridian/package.json
+++ /dev/null
@@ -1,11 +0,0 @@
-{
- "name": "@teal/viridian",
- "version": "0.0.0",
- "private": true,
- "scripts": {
- "install": "go mod download",
- "build": "go build main.go",
- "dev": "go run main.go",
- "start": "go run main.go"
- }
-}
diff --git a/apps/viridian/server/server.go b/apps/viridian/server/server.go
deleted file mode 100644
index e9d19ff..0000000
--- a/apps/viridian/server/server.go
+++ /dev/null
@@ -1,62 +0,0 @@
-package server
-
-import (
- "fmt"
- "time"
-
- "viridian/types"
-
- zmq "github.com/pebbe/zmq4"
-)
-
-// RunServer launches the server that distributes jobs to workers
-func RunServer() {
- server := &types.Server{
- Jobs: []types.Job{{"job1", "pending"}, {"job2", "pending"}, {"job3", "pending"}},
- WorkerJobs: make(map[string]string),
- JobStatus: make(map[string]string),
- }
-
- // Initialize job status
- for _, job := range server.Jobs {
- server.JobStatus[job.ID] = "pending"
- }
-
- // Create a ZeroMQ ROUTER socket for distributing jobs
- socket, _ := zmq.NewSocket(zmq.ROUTER)
- defer socket.Close()
- socket.Bind("tcp://*:5555")
-
- for len(server.Jobs) > 0 {
- // Wait for a worker to send a ready message
- workerAddr, _ := socket.RecvMessage(0)
-
- fmt.Printf("Received ready message from worker %s\n", workerAddr)
-
- fmt.Print(workerAddr[2])
-
- // Lock jobs to pick the next one safely
- server.Mu.Lock()
- if len(server.Jobs) == 0 {
- server.Mu.Unlock()
- continue
- }
- job := server.Jobs[0]
- server.Jobs = server.Jobs[1:]
- server.Mu.Unlock()
-
- // Track the job for this worker
- server.TrackJob(workerAddr[0], job.ID)
-
- // Send job to the worker
- fmt.Printf("Sending job %s to worker %s\n", job.ID, workerAddr[0])
- socket.SendMessage(workerAddr[0], "", job.ID)
-
- time.Sleep(1 * time.Second) // Simulate a delay
-
- // In a real-world scenario, this would be based on a worker response
- server.MarkJobCompleted(workerAddr[0])
- }
-
- fmt.Println("All jobs processed")
-}
diff --git a/apps/viridian/types/types.go b/apps/viridian/types/types.go
deleted file mode 100644
index de715a6..0000000
--- a/apps/viridian/types/types.go
+++ /dev/null
@@ -1,46 +0,0 @@
-package types
-
-import (
- "strconv"
- "sync"
-)
-
-// Job represents a job with an ID and status
-type Job struct {
- ID string
- Status string
-}
-
-// Server represents the state of the server, including jobs, worker-job associations, and job status
-type Server struct {
- Jobs []Job // Job queue
- WorkerJobs map[string]string // Mapping worker ID -> job ID
- JobStatus map[string]string // Mapping job ID -> status
- Mu sync.Mutex // Mutex to handle concurrency
-}
-
-func (s *Server) AddJob() Job {
- s.Mu.Lock()
- defer s.Mu.Unlock()
- job := Job{"job" + strconv.Itoa(len(s.Jobs)), "pending"}
- s.Jobs = append(s.Jobs, job)
-
- return job
-}
-
-// TrackJob assigns a job to a worker and marks it as in-progress
-func (s *Server) TrackJob(workerID, jobID string) {
- s.Mu.Lock()
- defer s.Mu.Unlock()
- s.WorkerJobs[workerID] = jobID
- s.JobStatus[jobID] = "in-progress"
-}
-
-// MarkJobCompleted marks a job as completed and removes the worker-job association
-func (s *Server) MarkJobCompleted(workerID string) {
- s.Mu.Lock()
- defer s.Mu.Unlock()
- jobID := s.WorkerJobs[workerID]
- s.JobStatus[jobID] = "completed"
- delete(s.WorkerJobs, workerID) // Remove worker-job association
-}
diff --git a/apps/viridian/worker/ffmpeg.go b/apps/viridian/worker/ffmpeg.go
deleted file mode 100644
index 4df0094..0000000
--- a/apps/viridian/worker/ffmpeg.go
+++ /dev/null
@@ -1 +0,0 @@
-package worker
diff --git a/apps/viridian/worker/worker.go b/apps/viridian/worker/worker.go
deleted file mode 100644
index c8c216e..0000000
--- a/apps/viridian/worker/worker.go
+++ /dev/null
@@ -1,47 +0,0 @@
-package worker
-
-import (
- "fmt"
- "runtime"
- "sync"
- "time"
-
- zmq "github.com/pebbe/zmq4"
-)
-
-// RunWorker simulates a worker that connects to the server and processes jobs
-func RunWorker(id string, wg *sync.WaitGroup) {
- defer wg.Done()
-
- // Create a ZeroMQ REQ socket for receiving jobs
- socket, _ := zmq.NewSocket(zmq.REQ)
- defer socket.Close()
- socket.Connect("tcp://localhost:5555")
-
- for {
- // Send a ready signal to the server
- socket.SendMessage(fmt.Sprintf("READY %s", id), 0)
-
- // Receive the job
- msg, err := socket.RecvMessage(0)
- if err != nil {
- fmt.Println("Error receiving job:", err)
- continue
- }
- job := msg[0]
-
- // Process the job
- fmt.Printf("Worker %s received job: %s\n", id, job)
- socket.SendMessage(fmt.Sprintf("RECEIVED %s", job), 0)
-
- // Simulate processing the job
- fmt.Printf("Worker %s processing job: %s\n", id, job)
- socket.SendMessage(fmt.Sprintf("PROCESSING %s", job), 0)
- time.Sleep(2 * time.Second) // Simulate job processing delay
- }
-}
-
-// GetCoreCount returns the number of CPU cores on the current machine
-func GetCoreCount() int {
- return runtime.NumCPU()
-}
diff --git a/bun.lockb b/bun.lockb
index ae31aba49034a8612ca3369a7136c48f8a88a532..80581009a4d8906424630ecd48ef4ef6a6ffdb69 100755
GIT binary patch
delta 31417
zcmZ3mlzYM=?g@ID(V`tqTn}fLD{eMiF84sQM*Yl}+4}K5bL~^ND;qgY4{o@?!~g;h
zCWgz`Ke)vRVlyx>l%yu+fS4tvMM?P#3=Eo#3=F~y3=QIp3=BdH3=M3I3=Dz{3=Q8H
z7#IW?7#f~4Ffi~lFf`m`U|`^5U}(rqEJ@BtEn;YZ@)Myn6Eg#Y2m?dI3T6fdQ3i&F
zPfQT~tt<=-{PheB4Mi*vi>mTdK=v~fF*7i5GcYuyu`n?3FfcTTu`)1lGB7mwu`n=5
zFfcUCWQJJ0f{lTJmw};SHk9syiWg+&f!xpFz`?*E&cM*HmII<*h!f(_6i$fw1x5ME
zlWQ1d>V3H&7BF!_T*k)@@o8~EPG*S_1A`U^1A`a?LxU&>#0QKV5FdSDhp2nV4zb`0
zJH$aJ*dY$z1En{zLo8g*&cMLMz|fGKlwYJio9x;gV8^oZ-rsjclFM;yQ#30T}P1Q}yEGjO^hVp$U3o^S~`ien9dj?c>X&WU#LveSA&JaE5t8cD^C2O#SrHuPLJeVJ5a)O(LkzN?
z?8qX{XgE2NMZex%6=I1El=fAJq`;j}T2cdIXtM^yj0z2i`qbj2(#)I`hSypU^;fkZ
z32r}>UJ0cqL+Ls#NJ7lg0z0Z93_{m8I6)Wdw(1bWR4@$>CX)h?fRvi-h9fqJ3QqRy}sSdF~QynD0&;aup%pjPBFqgv&hWemk
zuMx!OFbBabgn0}WGB6LqLJS;Ipuz;^1DMZYE`@~vEGS_0ud00pc&Ml=mT*8
zmk-3E36Ts8(hLj@<&g{wk_-$DK2Z?yq)15d1t|u(85+!@Ar^N|X5EPy
zydVLq?FA`C1JfY>SDbv4OP^EN3ld7QlLfiOC3`a=ey+@fB)HO){M?kxw6wg*j@;sz
z8?zt*us92%M>`urCuKrxNKe+y$j{Ga2!rz7Ga*UBFcXsOU`-xa3k25EfVE6uEf$B#
z2f6j@kE=pVH!Xm;WkUg^&YN8Tabr>;#2+;o-~`feqY&bXi3Jc>))qk$e{m6nuT~5(
zN3<9so>&AaVT21H=4cc^!b_$AY)*YcPG(YZVGaYslv0SrwWW}RkzNY%P9T)FDP;gR
z88u2F7KoKX4CX9_82B~=V&Sz6i2joq5OG+Ob5{j~?_LRUNLgZ0W?o4>1H(M1#>9%u
zd{9HevLrKzQ<46mvo>U3)$^xbNRMe8#l
zNppQI#KGycU>`Tks)cwY8pIC)HJa-f7!(;88XRjO8g|t|(&F4YNLpuwieGJj__(VM
zlEhkSAt6*;3-P&pEhH`bPd>;iE(vRsOv->*TauFk@*P9R6}XSYH;J!x_zpM1Sk2gK|7dC94ulCZoev7n%mfgvXY5~Q#~
zp`=(hH@~PLV@@Z;w4P3gyh9fxs9~-#?}C_a(haeV(Hp`~DoRXFEoNYN0TtKl0Y{Bi
zLqiWlL2hbMda4lvgJw4*)n*p!f=lP@UWh@GlNI^JB|r2+Jh!nA5=4LdAl7qE4&+y7
zte#xSAHMhoKR@I0$v5TfS#1~@82l#Rm9u8;Vq{?O0kf_#GB9|7Sqe-H3?5)s1``8=
z8;HfYZgQl8J!>DRk2Kvdj?s9sfMN%u*yNdt_KbTc-&C|`qQm@
z2G_~4O4f|>lW!{7bNaC|FxW9LG%!z2G&N`JnH;HX&v<6?Ol5mUw#he@?K$Jv7#M6B
z7#bKRKU6el+&Vc@#h&Q{+vHg)c8uDSZ>rccmQ9vawPy^U9I0y0xM%WAReMeaP6h@S
z28IU4$q(hs8S^Jgs@XHHogArV&-s*-fx!f98AwKQ@=Y~+&M+fYpH=qL~Tg3{GAF28JYv160j9^O1S17X=s?(k9Dl
z+b{}Fj?%X05M*FTfh+wh$iR>R<1wC|d{f7s(QdM&u03asFvNQH$q&`c8Fx*dscX;r
zR+xdoa`Ie7YgRQ81_ryyv8L9Xbs`XlFiw7`ZqB(+gn_{VY~Dk4bJlMn3=A%lV^ys=
ztwdqsi5ljtMWPH01|Z#xizd(1w`aO9I{B8q9i!M}NdtRE?#Yn`_MDO83=Cf2=m1&2
zc=AmHd#2aolcfypI1MBi7@QzdI_8W;lV=**Gj5)I)6kyti3H3opg2^S9BE|FnIs9Z
znQ`(%9dpiEk`P}pf_%k!Lz02P3T%?1t~sla6a#}9*tH%~3=Br#m|3W5&R8}1rm;Qi
z8Yu<_9gv$@Z%Bb$4~hg1X$A%Zu>OTw=8P7TZ<^RMrc9PJwP&0&Invag^O`iwJ&8)@
z9AYw%lmm@nISxjz$&zOFoLw?-H>sO5o|rt-%$`wj@=Y^))-+iL28YSAn%11lWFfv_
zn!Hfeob#S6#C^<@6*bKn1t#A#x91F!gP6hqPVEyWM_Smko|FUWziVL4Xg2w#g*{{S
zWJybV)_d}xL?o+g%_*b+3rR&ybIuS2hzXFenWO*lOt{HIlGl1wlaW|^-*Pbp42pF`mH=!%GQq2dUB+#J!ARgnYQ+vt5x8JYML|M
zR+%hiw~sMs@=ZH?rdMi{rR?n(Qzl2++cRF6Jk#DDR8ZL4GxkoFbg<_%$f&hy@sVjF0
zHY^Z^gEi}FIO_|XWvd5P=3vd*24|gzvn2Ex7~H|e#lu<4;HWjQ?zAqkOX@r<4Tnu&%Gga|TK!F7
z>Sn{m9-D&do>)&C7BiS+tr^@9GniIxbC_}d<}k78<}e+P&0#t;EkM;4$SK7ZFm<~v
zVCvW{VPgK4Q1cikPoC*(&vao5+H)yE1H?;zGpIO`dlWo!+TZLkKV
zio1a}EY_e%25Atn0kiyUSRf2vYu06O)_XY1!WOK|*P68v&N>BW3EP2E1<1H4IBOxC
z^#ab)w+F>LNL>k>wG+L^$g@oF(f4lTG#jB@K|e{|SWJ&SCricHadvq@$}>iATj0p#nKAa9T;32d7Epk4x_Cp1Fg8%bhPA|-fx!aY
zEV?{-W~@D<|Kyvo_M8iRAmt#-p;)SIa9KMi3o&{6^va0%l0#eq}nz4TJ&3Jpx&wdOHpjJ7g`gZq+<$OhXi^($+
z>^UF%L(&2}*lL3SP=J7{{pJ9Oso?e+=g|O2Y%_!H5D#QvFq$l@Yt8BjX2qIXGgeQI
zOtR;^8_2+5&A`yWHCa)~oKqqQqKh3=jd2D9L4t*IvZ9$e=gc5TgNX^;tauv)Ysx9=
znsXWkLsT+@OkwPpESX}@c?v4V0S?r@5QqwPP-~L&atI`SvVqKEl?-KIu$g>U-I_6U
za%8GK=k`zrhA>#ujFUGE;$IH1PH!lW1yreWP78zh8SEz3M`2)dtgSia!XdVCOkS8^
z&KVI7v5g(fn*!yrfq56gA>}YD*vE1a5MMzmyQBz+&77d5!npv-W1Fm~X3lvp0%8L=
z4ml+vAvuy^vSN%m>*`1bhM>u@D%MPYBPT~?+HodFL8QU01J1Qkkbq=Xf_xqgNsx?_6O%1CVjxk(1Ws4}F^~XYnY>WboN>YAnc4QN|Kb=J
zq9@PIwq}itXJCk&EL&j163@U83Kn8dfJr7LFfasz#kM9eFvNmcLWv9vnP66RA_GI>
zWZ4`WmPDAOWfB8JI#_Z+5(7gjn8ljRzz`2+rNCK-lVLg(Qb6{DTvC|=Q+ER_7Mo+k
zlFGmk4%XU{%D`Yf`L2OA=iyXXY$TeRb26tvnls>3!WoqY32{guPDz7=7b7Trb6!Y;
zG~~dkos%UUp7m1AIjzzm0mcGKYn(-J9;obGHF;){J?G7INUXDhQW&GwWXa-srhgfe
zXBFGAF3MzJa0a#an4V@%mMXF1)XjpJ2C+9a3zkAa>1;Ptjs@K5_zdMSgVUL1HpIQG
zpk^*>X*RfglCx&r31)%v@84{Q-aSxsasC0`e)RQ68jQ1kRJJO?eCq
zVW8$T(~Z2zw<_!yIVMY1+H+dwLmUFmevJ8(XI9#CF3e|OFlAt95SaWh-kj-L{$!~t
zJ5J96NJ+&2N{Xx}3K$pyz{RG-oi*oOzCNESr=UiS5i7vLu
z3oFezKUYIcVV=BjiUoTOgoDspPynnR9NcVPFUb`w~>Z9j;|ya0l~14G^w6
z1_pC5Z(*VZOC6|96su&-`3o-m(8Qe6u%3Y-2CN9wvFojeLGm*hRF-d
z%sGu4AXOa0a^n&ZH5E|xUbIW
zKY3=SJ>#UwH#_ZFk2Hf4556
zZSdS{YtG5u4l$1zWEZ33W
z11bGJK~=JY!^5Trlo9W$TXS~yK=go1EY8C{5Iu}wH-GPeq#Q_1ZrTe85f+d$IZJyX
zHbcU9V=n`P{p7j5){M-PZ%(%7H0y(?Wt9=zNBsa5zJJ)9?
zK=iRpo+xKr&(6TW0K#kx;4w|ma3*Ml0ogQYodrJwc%Tt95dtt060p=?(
zFfgz%fM+b~!2&7_3=E((8LD6&c;X+-Lgq6wFfeFW2JAbHdQfQF=
z0H{6?4RUr6ln*Ylh?ZwyV5o$K19Ya30Ur&D
zm^x@;=!TjDqCw{NK>0nORWcwpLV$sRVY2N^`^hmgIlyUZ3P_rPfdL!M!@$6>0P3WL
zP<0?0Wc5-gA4G$~U^$czqCrkr0Zlt=pyD7Jl(sfP&D#Xd1`G@go1hA?(I5@mp=oC?
zNaN(#S>pAe6n2;ak|2&kbz`GJ&N>d2$3}zXPeP;a9MrrE4B+`RhBr{>e}IaAg3@0Y
z80x_(5wz3@WHvG_2Fgz$&(o9+23gC%z(Ylg7$?il7Ow||2R|ct+KWLQYC0WhNLHby
zg&;p@FoNgb80Tnh{1V1`NO+V&1wb^YhOB||
zk!er}fvN(KR0A{|8$lcf1_o?2sIqE@%7bW-#hp+-hz6P0BLX$37b*d!C(F)<9?D0iK|&iq5d+e&8N_2?U;xn|
z<`xjaz`%e^gJSpuRGexwD5gP~kZJ}pLfS=Vp$^4IgOp5GSSSK6O)r3W3=9k)T8@E%
z;TzF9?mtup@knI1{AZCk>Sa(IBQQRF@o-mInzkFff2t{r
z%2^dEPYexmr5Y1MJ!m;CgFaLvB{axD1E@J5nuCFX!Ga0W;B{ew#Dgyrr0@)YstaJM
zhX@2ieGm$j0MQ^HMnHWS2^B}CK|;|``4|v~fq?;;=44=CNQIi44y7}p4l0G}D+47P
zklqRq!N9-(qCpl{L!$&F4=Np6q4FRa#B7He*a@Y(p+4(lf+XF^AVr|IAJn2LP(FwT
zh0Gi%zaGW_(IByTOpvDg5~#t;K!OYm3?Ld5#LJ-uu3!SMd0^NEl_!&~2O9t~V+YjW
zoltrgNRWYn0Yrmbd(=YnlpfCko-lk
zJ(JCr@`3BM%TVng8YF!MEX}}h6)Fy*LCot=@f#ox0|Nty1~G3z#czW+3=9m!&>*FE
zL3sdV;XM!!oQWYFKTy>Mig{kB7$r2wXxyDYu>T>wKu|z}I(;BJK{Uu=$elfqI5HoU
zR4MNK>3~dS01s1uS)kq^$i>K=K9B^6Kic_Y0CoC6!2zN{@q_5=34??g7!U%W0${ZB
z#{lXKf)dnd=MU709PRuu*n^s^pv*$E&K)RY;_H2mcK$%YkJ6b0bqzqBK9B^62Ibh%
z&L5N>I(+hs)4Y@ap7v&Rp6q!he6q(G-pOmvcr&_A{&^;R@{cpTlVi_%
zGrCV+c{Y6VinF|vdCz$>dQOf!7d|=S9Pi}4=e!xcCv%<;pUiQdcXIA|Z${tAJI{wt
z-f^CHvg`$KM*qo~7s4lJT;QF2_JTKK;AF{*;gcmU@=mV3=*<{B`Q*j$$tN!IPS(BT
z%@{hl@>2NZic7qc?_Tm|44cU}pf
z+;N3>^4lxkjIom~uZB;yxXL?u?p1Hb_{lG?hEINRm3Ol5HE+hm$uqBoPo8m&ckf4`$&ok1
zCr8}moxJy^H)Hl>&RgM=Id1Vz&b{T$m^*prt?Myc0h8#2wzrx_7-9OD9*}4WC?bmv{2ryWWiDlQr*!
zPu94{JGu9sH)G}GoA<&e-?+y++4jCSWA)_D`{9#2?(_J#IOF`uFJFgGe({=jvhN#j#)Xq-z6qZ^;|=fRzi+%57f<$l8_u|7^1`>_
zj7ul~d>hWVY;xecaK`16SH25pTrrvPeK_OF$&v5F8COl-_&%I*^<>Tu;f!l0Cw>TL
zTswK^hj7MqlLbG9Gp?VU`7xYv!{mb>!x=YDmi!dXxM_0Xr*Ov2lTUsMXWTMb@pCxi
z*2$Hh!x^_tzW6zuarrNR$#1`U
zGwz*i`7M01#W&u`bH8~r?w|bfTR7u^$&TN{84pgL`8}NR(BzNb!x;}x_WTjfcx3Xz
zAK{EgC;$8r&UkEc;LmWzm<7|wWa`a}?QfBH*C#_;Jc7#Vq|`!X?lGd`R?lZi2$@zL~;AnNgS
zPiDqwXJkf~cp{e}brI(*s!;!x^7XUkRdKOlM?e3}<{fJrYE{n!XW4y`Ij=#u(1{
zW_lusdOLk5h3npGV)Hp%gN}?_AhTx-i$w|-vkNV014P~GkP=rp5DpL
z7(Ts&n~`_=Tadut>6Sc<;nOX673@2OlHv^tF79-i)l%e}V*lfCOUs8NC_Vr?2E^44=M&pOJSu
zuK=SrBj@x;0mks@5dw_7)Axb|xTkXpGKNp*5M<~u)C50Kor%MPk@=mW6X7pwho_-P}Z~`QtE5hi_C_24T1QZ}5
zpa200h)>rP1qFyGC_qFRy%{B^-vkNV014QNF?usfPwx~11&A0ZKtKYr(=Ek80U{0x
z5OGFtM)~P4K>{y80=^QA-i(UVXG(y=Ljn{YAOYp+o|2&OkOYN?B%?Q@>hzx=fgd1&
zSSdztM)m0{r9j~!1qu&oMsG&V>5{M-Uy;Br{4roR?`g?8N(T^r+0!Vo9Pchl?STjE>W1f+(lyA3>D!bWat=a7LHu3qh3Y^q(NgZF-<8V>qMx^p&b0
zPpg7Ft;Xoh=s7)74diJxkf%Wc-qShNL7r9zd0L&(o6&drPLRM3kbtZPqc@}f^h^zq
zr!_#H1_=aCm(&D#T9c7ydW|Nd4`cB3lOTZ;nvA^Db+s718AGR6YJn1g7AO&b1j46l
zYJ(DiHYgEjGkP;dPQM8fxB(Kd)nW8zjGo@914;xsphN%?h@Eb!3km~WP#EYkdNamP
ze+d$J0TS@lWAtWBoIXfqc>yv
z^pysn@Gt;{hasakW9IZoLr{1ag2DqNkUgE#2oxShpztta^k&SRz7r&{10*18%;?RS
zKRweJ6duN)@Bj%EPM0(Rg@*|!5tuM~GZs%j2@*H~63{he^kyubUTF#n4^vQhfCS2?
zYnp+=!weK2W{lp9mD6v61a5!?Y|RVM0EkPk+2?_~IMsLRE>7G`M;fyWQ7lNqP=|8O)!>9kSV&t11XU*uv
z*gk!wH7FRYLBU|d=*`$UJ<c7!QcQ229Ut?
z>6(t9U~mKlgCnCi{~G0=77V>GYokjNXhZr$@Sj!owXD9w33$(>Xmr;o$)a4-ZCf#F5zM$~%1%(GlVDEHGKTvr1fx^R&
z(VKDq^p_xk7a##&e@1V{gVSgFgTlif6doXf!_z$jK;aPp3XcFrZ^on3e}V*lfCOR#
z8NC^gPhS}b3Xecgcmy$eGoG9t83YQCAW(RK1Wr%q3b$VqOC_KVI
z=>sHieY$2iC_KVJ;StX0&3JSAO_0D1kbrFjsM#>RGXfMI5uoq@3EZ7-83_uHNKkl0
zGI}%KpZ+qEF`soF0|Nu+_QG1m^Nf=($gynyQObA+%;KES2VS7mux-0;9HTiKqs{cx
z6vlc+_U(-6jK3KtFOU-fX_%JD$N>>!XM)hb87CjuVKdz!n^A$$cY0zrqdG+VIpg$#
zTt*4TgzcTVjPi`E`JiJzrWe*S_Jhpf{Tl$;a?T#ez#sr}&|}8!22G3-V8=}NDPrVc
zniw;^zmZW5BwWD^(gbqt4_3zf=^v{Zg`ox-#xVwiGcumto?FZKnUQhg
z^u&5bVb=5g3=9IGZRYXYZ`3nxWt^_i#Hca-{sBhA?e`Bbnux)f|D-?`rSgJ=|4DIa
z+y;$MFfd%WJN@}>Mq9{S3T+FkOi9;04>G=Spb@Z1+BOOvFAXS%7I2u
zbQvJyvY@3cAj3d&{X!tuGB7aggc{7nz`y{StOg11f{Jl7Ffe=s2{14)?1qYgR$baa
z#rD8_2b%3IXM{|}?}e@m;$vW7Xa>22fq~%wR5NH+Hx{b-AR}ZMh5!QtLp&(`F)%P3
zhN=@}0PiaYt2_b~135SoEW*HW6e?B^nnMI1Qp3Q&a11I48kq+zhy=O*I3xJf2hdp<
z441Le?vTf*cg;;tUK7O_1Z+816&Wf!3={X8@lj!SDboCdt6S&Z%G>4Encg>6C0aArcK
zo*zk1vwr7k=(-rP8
zvP}PRk5Psdw9e}6tL*vG`cu%C&60kon9wB+XadcF5whIj4ihB7
zA7)};&|sXd_K-0u5R}+KOGCCZftTQej*I|p@BnRv0G+kK09uFyT5>X}R2a6dYi)BGE3R=PK&cMI`THh1G1X;kY1}ZR^7#JFvAlV7Dbf$-ifgz8HfdRC>
zCyI%I0kmKUv`9M|w5ErFfdQ1o;ushh5*Qd55*Zk#Pk+Ry%9t~K?;}QIKG5RsPzLY@
z7X~$^>Hi)vD%DFcF)&CnF)&CmF@P6;{a|EZ_{qq?@Qaaw0kodek&%G`G>3DS39^9Y
zC=&z2aV7?Ejsh)!0WE=WW?*0dt+oNJyaBDo0j*2yU}Rv}z{tR`k&%I66C(oyXbsw0owb|;L8BsX2Jkk+!V&dzyMk+)X&7g
zFoB7IA)1MS0kk>_w4A$u?XVq#!8&BVZPh6$2|zkt@9GcquMvhFlSNOqmU
z$iM)~n-dus7(lBmK?j?3GeQ;+f>s?)W@G>t_n=i+p!MY|85kH=F)%Q!hOScwtvgd;
zf~?WG#>Bt?TDt>U?y~|^imqg2U|7J&zyMkX30kSy0}3+GYD5MGhHVTC4C@#e7}kSw
zH3I{~O(q5g(833v9B`#>m3#ifpRZ^gmwTuZ;nzk`OmU$cj6?~AA
zli}NR(Pxa|ZeJM~82T9@(x8F!qXN=nQpqdF(5!8atm0QW
z0jUR7aiD?*RO5hZCs3^gs?9)UJxC0s2P6(+gDMPAMFJ87(N<79p!(TB$9FOCPoMdm
zQQa1ll|gj`Xh{;NFjt0dW&suOpn@M%FUT^0k0k;faRfTpk^!{Z2o!&Y)Biqal&%M@
zo3vyA@8SZNi6CcyoD9l=plvD+pjmtd@ZKWO;WZ3t(1l9j4B#Dz3^fek&1|5pa}3qc
zEgcmM;3HiaKqZ4c17y2LDYQ}sl}NVGj3^7*TmULoK*bBFr~&0rZ)mOs^u6fC07Wn;94w+M%T*C=0eu-};I%oVSC4fnh$VMaRIvuxPsEYsPri
z#h{p(Ui+FcS{AgCp3Fz7NeF#Kj6cMg|5xP{R|n2AYw9frF8OfgM_-a)XvLGcqu6f!cUbJ)jLFLXe`boPay&Fo0@q2}TA61yCECk%2*$k%0ju4ib|DHK!RF7-Se37^FcBFGdCid1xsKDm6iR
zK_w`N29=(mQdEbLfkBHAavrcYl-6TpU@&52U@%}5U|`T^WMD94gzSpA%`ko2TSm8f
z6GjFGPmpgx!GeVS7#SD>85tNrfedOogWB+*btj^v-kp@E>cAy3x
zsG$eix)ICBz!1*Jz!1jBz!1vFz!1X7z!1&Iz!1gAz!1sEz!1U6zz~BZ29g6|kUU5Z
zWDclw(*vEF%)r2q4(idQfm)8Bpk-hH7k}!Y@`({roxzGjP!XEV$iM(RRHfVr46R?&FsGSCCM1U$#
zP=yKV8!lyJU|7P)zyPX5K`j`Nr66&T9UwN02I&P=whI`iPy4{gR}a$<(gSilNG&J_
zfy@S}1vOYe0Ra*RiGeC-kRA{pWDcl#g)9!@gXBPVgWLp4ULZDTuLsC1kX}$55!4u3
z0SW||A)rhGYGQ#L3Tixp3;~50C}D#f0CF6tk
zpzIII`JjF(sI=MxD!mvP7(ks~P-l1tBLhPUD3^n38&LOTJ0kXU-{svw8lWMp8t
z%m~?naURqdWn^GD&B(xT3e+(JHM>E*3Q+IjA|nICB}N7Y(73`CMh1qfj0_AQ&7d)b
z8_==})bRs#T01_1@+$*_h|To4PmF5QJ3cWsO;`EMD8$$|-TX77q8aSq@tgcM=MOz#
zJP
z^hqX0V?6_~18S!i>N1JR88I-x4kdS8TwZ>IX}vcSW1NAWiJlPy!_4W9dQ4)hh71g!
zn5OG}Wt3oCF@3iVlO&_x^u(`>l8kB7_v6H&?0odKd*k2My3St;R&EGVzG8a)
zH%3WQ-2Q+av2J!~zszm+UrkJmhI*zToeUY%&wgVxMsuslcSe|7rC~>q>V}8&Mo+cc
z&%_vKtY;3=yKy?VI+G;hp6MUem?RlbOy}2Nl4QIx{o;2`QQRNSSW?lTnhD?e6)LMumOra;SHyHepvNl;#@5{m%XQXEYaxCnq
z^oKyjFOD=
zr$_%{l$3#;?XJDMl8o8Y75{_NY$J$QHhn!4lO$ux^tb;QB^ev1pa07!X$m`fT{_|O#Fl8W04Byd
zLp=jM69xv@A?;bw`cZo?v#5X)fHBznOQy^IW0aKM06n#Rc8w0})5G5%f)p546|CPEOATQDDbQGF=y&zTh9DgemN3dB0m_zw!$9X@RsE=z)4=u*2u?Iy>IE8~AG_
z6QhBiDaa`dP&Y&T&6vGi@js(1BctzBdnO#7gg9~P0VY3aV8Oxy5(wL47@6c48QG^B
zGBbhlG*bAO;0O^@28JkE@b;#LpS((2MI9D=U}E%xicG)9$RssgjG0La)lBJFX2@``
zKI7!+ai9ntqXmNs>`|`g>L;Nk)z7j36FVaPRcFAl|9z{vhh|^h_2eV@8OeH0)q|
ziTTwtdsl=QK}|G(n+Q<{GdO6vJS&r=H1zoUhO06M?gVc+vIMNl5ELz_RzjRJeE}ag(6!+HK1l2Gce%R3bA#17#oumqy6+kHYQ0%kLlfP
zOp>?)+t`G`aQc3b0uEJ3Y-AL#`~Qo7b*2booQa+RC`}7Z|IEhZ%cwBjk)27BQEPfM
zJCiY^&Gdc{&wctzcBYro6IH>R+8TEA&ejY+@yJ<(5j5-vYSPb|zLtYYQhG7;=zl%_
zx9!)SJee-SXlH8(GT&g`^oJZwl8n2i{|2dpox!XWApYg=KBhR3Is-jJ13iPQ)Ac!-
zBuyVf4{84RRcBQj%fg=^1?C`&7(S|k+fogC&un$$nCTXca0A2iT23ZOX#q9xFmFTj
z29Ai-%$6JxNc~{Qz@RjJBPWw2qv`b1Aa$N<44@(9hKBf4?$W%xtD=q!E|3PCQ0cXY7C%3gNCmC
zI|XjvdEAOnaB+Gg7n89x?1q3$SueBAH-0;T>j!Y%VmbXh7n7tZ?D7P@vP>YS}qmmYd0#QF3}9HfmJGYT?^uz}eP
z)8B#&oiyE1gh`kkBENLHA`g=!}TBo;QEo0mya8g`k$iEj<^HA_M#
zBh0CrK9P?}SP|kp*c}8xb{Di|WCfQal&ze;PzdI+{nLASnIsvnPJbv0*9klJ|KdUc
z*&`Y+{Si7lrr+jea<$Dif@B2PtpfM%?Vr2aXs;zmp%J((0=u~21be`Aw->pG5Hgde
z$MP{rVhs$4R&5NnG&jR(w+n;m)QC*)=VxMt
zgqsK(*w5ftf;kLZvVv%b-D%LlvL+*5(5eDq<=*Lk`9YOB)a8?{-zaDG&gwuY$eV5`
zz$D3-HQif)Nm3eHii23uFuh)Y$ygd&^cY&|85%KoO+O1V0h=Qs3czV!lCfdBv>+2S
zE`-@3QsCedu?Cxi%`XsD*c=Cuxu-dOo*=I505%mI!;*|r(_e!u2M0IIa&Q=nSb>$n
zF4I5`Cx{hTa|l=uIB^M2ZxCW)lg64sz^cIMO_Fi{^xZ=6yukr6`nA^d4?;{5rmzb$
zW;I-Bm^}HI5V+m~*V?eFH8R`OgoDD?20&$u7#R4b+X^#D3d8Q$(7P(~VxR1%zXFV_
zr)LT?DKf5|-Yv{z%(!~`eqkm_Q>;lF-2B28ZAM@jZ~_rg0JCAYu9*3p*|u=fmMU;E
z0?UB2mLwxMB88{ti7>HAV~a?Lk*BBki!e!=V$INC)36n55Ut>N6rTP8WC7Of2-Xjd
zUr9!A%nDDp6J=tP#ul>>BeSN*i!w=q7Rm52LH&s>8X=0o(I`Cq0LVzJ869jtxagB)
z+&lfZD3hc#)@%<}Cp=wWjA^U1BJ>K8;!cl$Tb8QSfTI`ODbSw&UyMnT(Qdk=IFqq3
zX2s(*Jzkv2nlWtpY;h(@Y1ow{TC>(oSW=Z!4K~LJ)OOCCeqNjj)I5JF&ScD}FkM!H
z$(WIGdY}Z8BqQVWYzZbwY1kzjvqiVRl4{+P4X)LUL7Ek(&j%^jntoY=$(PZ3x}qeL
zBqP&wYe^2cCb64J1HPv)(f^jb{xQY#ZWo7XQ
zRI2g?BEeRGyUvXv;3@Y8L#~gnwcJElm>6?IAa_2TnEud)NrVkN5Wq4$QHDv9(R})P
z8746~0|o}zoh(s|b8fqRpI^Yl7-tG;e1g?Tn!@f>d6Nk&L@
zEcROJfzzVE^s}-|lF~`gOIsfPJG)N9gm(rLs8MMIN;&1z8ReKH87EBlmtzu_HDG{U
z^OE41%&pWJdJF7OaG-&eNJ_)5dl8g8I$h#|#Wg0zIA|)UncghNWX#w(eLIM{I{mdA
zlQGkynCS}gOcJKBYgo4afAfh;>Xa%Aqluo8IjGYJyQn2_*1LBO3oiac$XHCzm1mNa
zhFgb%7U*D>Ml)xFV7@t3cE|@
znWHMlS7(J6_UYP6OzE(0&!p*Vm6#-@
z(Z{Wn7{TLKCJYSorax3-f{%k`h@SvI`)3uE0b;?W<(r=-cvb@n2cyu%F>l`Ie3Ntj;GiNwHeWNl{
zI-~n^NfoB8jE2+Ct1wAQ!|uS@^&rYim4i(koFKu~Z`gEZRVHI;*yTAD-6ea4-~8$Y
zr$g`{L*Dd2kOJ6UJb@gh1%;h4A}k;aEkGTE-s$sInIst(PtOMpQEi-lS(V9`QG2=~
zhzAjrhF#h7|C)X<(~FsQ(41_{zyMKz(7afU$yge8bC3S2c6OdSht$BXH3W6>Awy7%
zkWn%Cz?Z{xdvzvBQ%2}jgU0Vd(%4+GXCkr+>}sFu*Owd)U&AK}Ey)cS7@(tM&=D@^
z(Ao0ox7C>>rC}EY*=aozezW4295hS}7#N_+A+DM3q`~CJC_H^4XlPDm`f3d(Nom+E
zKCfSPYl*}*gM!ltGN5NV{XR$?M7cEVmY@mWmM+*O%iILE0$ef8p02COB+0m8y1OQm
zF=Nv7YE33d8T91I1n*JbD4f1QlS#r9cAb#lk^Qole~jevzJjd+
zmw2_)|7tQxO5;#q#K0gr-B623l2L8CH;95bozZxDy%v+CDeQV73(fGD!$)MD!Bs1G
zI7|$B0a2ikZYBSPY&%ec$^48Q}
zlGC3UFiA0{PX}v-1P^2YADInt2xHguSW_lR#<|nq8i9v}&KojGGD6%SeG_^;l)Ute
zC13VGzY4JqG&Y0kI*6@|wbQeWn2Z^r%_N8!j8JQ!=C@8~H)b*>(tKl>`;TG&7RB1qe%>90W)q!V;#6jV8AeEdZ87Qv9x&?WO&EWeu-*Lv!E2%`9^w%h73EW@3&%-l!jf~wO`@e
znh)*v2H^S(+>wB^(iu6Y^I9`WN=tS_8sGbMX5X?7mGA^A(!#=Krq=iQm8;2Y0$)7k=4(KCtnWfN2J}`~mm2^rqjnW&({+d5(J>se+d4Xo;
z3?VIEa0_0Nv3mM%8zy6}1RKa=*aq9_Q5Tq`rw7|Ise*1Ao?dCoByX511YY3SaDs9D
zEZIqmrgaHH`UTH}P94v>%~?KO2)sJ9LFJo>XtLRpcL%1Qv}LkqWS!1w$0V<~-4k*f
z*{RRdZR-wJzCYy&3HI;i6P9T%lQh0O-P4Xq-hGWX_++_;+o9D
z`TmQT+&kfq~1W)WS}|aC*TfMv3Xi?U?$v7uqwW
zFl~S0$fVrI^#Q7i;rw*L3rvbqDTziIR>ccl{;i9;ct0kP#RIgG4YXGFJSYJ2K#R%^
zIB!4&Ii?F-U{dFR>6xB!kx7Fq0JNSDwBqx^^jQ~~+$2G#T5*H!FNUl?ZUC)(0?oem
KO=rBsG#>!tFZcEU
delta 32119
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
diff --git a/compose.dev.yml b/compose.dev.yml
index 201f531..c01804d 100644
--- a/compose.dev.yml
+++ b/compose.dev.yml
@@ -1,46 +1,60 @@
services:
- traefik:
- image: traefik:v2.10
- container_name: traefik
- command:
- - "--api.insecure=true"
- - "--providers.file.directory=/etc/traefik/dynamic"
- - "--providers.file.watch=true"
- - "--entrypoints.web.address=:80"
+ aqua-api:
+ build:
+ context: .
+ dockerfile: apps/aqua/Dockerfile
+ container_name: aqua-app
ports:
- - "80:80" # HTTP
- - "8080:8080" # Dashboard
- volumes:
- - ./traefik/dynamic:/etc/traefik/dynamic:ro
+ - "3000:3000"
networks:
- app_network
- extra_hosts:
- - "host.docker.internal:host-gateway" # This allows reaching host machine
+ depends_on:
+ - postgres
+ - redis
+ env_file:
+ - .env
+ # traefik:
+ # image: traefik:v2.10
+ # container_name: traefik
+ # command:
+ # - "--api.insecure=true"
+ # - "--providers.file.directory=/etc/traefik/dynamic"
+ # - "--providers.file.watch=true"
+ # - "--entrypoints.web.address=:80"
+ # ports:
+ # - "80:80" # HTTP
+ # - "8080:8080" # Dashboard
+ # volumes:
+ # - ./traefik/dynamic:/etc/traefik/dynamic:ro
+ # networks:
+ # - app_network
+ # extra_hosts:
+ # - "host.docker.internal:host-gateway" # This allows reaching host machine
- postgres:
- image: postgres:latest
- container_name: postgres_db
- environment:
- POSTGRES_USER: postgres
- POSTGRES_PASSWORD: yourpassword
- POSTGRES_DB: yourdatabase
- ports:
- - "5432:5432"
- volumes:
- - postgres_data:/var/lib/postgresql/data
- networks:
- - app_network
+ # postgres:
+ # image: postgres:latest
+ # container_name: postgres_db
+ # environment:
+ # POSTGRES_USER: postgres
+ # POSTGRES_PASSWORD: yourpassword
+ # POSTGRES_DB: yourdatabase
+ # ports:
+ # - "5432:5432"
+ # volumes:
+ # - postgres_data:/var/lib/postgresql/data
+ # networks:
+ # - app_network
- redis:
- image: redis:latest
- container_name: redis_cache
- ports:
- - "6379:6379"
- volumes:
- - redis_data:/data
- command: redis-server --appendonly yes
- networks:
- - app_network
+ # redis:
+ # image: redis:latest
+ # container_name: redis_cache
+ # ports:
+ # - "6379:6379"
+ # volumes:
+ # - redis_data:/data
+ # command: redis-server --appendonly yes
+ # networks:
+ # - app_network
networks:
app_network:
diff --git a/compose.yaml b/compose.yaml
new file mode 100644
index 0000000..5ad0e58
--- /dev/null
+++ b/compose.yaml
@@ -0,0 +1,17 @@
+services:
+ aqua-api:
+ build:
+ context: .
+ dockerfile: apps/aqua/Dockerfile
+ container_name: aqua-api
+ # pass through db.sqlite
+ volumes:
+ - ./db.sqlite:/app/db.sqlite
+ ports:
+ - "3000:3000"
+ env_file:
+ - .env
+
+volumes:
+ postgres_data:
+ redis_data:
diff --git a/packages/db/connect.ts b/packages/db/connect.ts
index 990b09e..56f206c 100644
--- a/packages/db/connect.ts
+++ b/packages/db/connect.ts
@@ -3,16 +3,13 @@ import * as schema from "@teal/db/schema";
import process from "node:process";
import path from "node:path";
-console.log(
- "Loading SQLite file at",
- path.join(process.cwd(), "../../db.sqlite"),
-);
+console.log("Loading SQLite file at", path.join(process.cwd(), "./db.sqlite"));
export const db = drizzle({
connection:
// default is in project root / db.sqlite
process.env.DATABASE_URL ??
- "file:" + path.join(process.cwd(), "../../db.sqlite"),
+ "file:" + path.join(process.cwd(), "./db.sqlite"),
// doesn't seem to work?
//casing: "snake_case",
schema: schema,
diff --git a/packages/jetstring/src/index.ts b/packages/jetstring/src/index.ts
index abecc4d..516c561 100644
--- a/packages/jetstring/src/index.ts
+++ b/packages/jetstring/src/index.ts
@@ -2,8 +2,6 @@ import type { Database } from "@teal/db/connect";
import { db } from "@teal/db/connect";
import { status } from "@teal/db/schema";
import { CommitCreateEvent, Jetstream } from "@skyware/jetstream";
-import { server } from "@teal/lexicons/generated/server/types";
-import ws from "ws";
class Handler {
private static instance: Handler;
diff --git a/packages/tsconfig/base.json b/packages/tsconfig/base.json
index 0b817f7..6313223 100644
--- a/packages/tsconfig/base.json
+++ b/packages/tsconfig/base.json
@@ -1,7 +1,7 @@
{
"$schema": "https://json.schemastore.org/tsconfig",
"compilerOptions": {
- "target": "ES2021",
+ "target": "ESNext",
"module": "ESNext",
"moduleResolution": "node",
"esModuleInterop": true,
--
2.51.2