Compare commits

...

1324 commits
v0.3.0 ... main

Author SHA1 Message Date
Jesse Wierzbinski 6462669e9e
chore(packages/client): 🔖 Release 0.2.1
Some checks failed
CodeQL Scan / Analyze (javascript-typescript) (push) Failing after 0s
Build Docker Images / lint (push) Failing after 7s
Build Docker Images / check (push) Failing after 7s
Build Docker Images / tests (push) Failing after 6s
Build Docker Images / detect-circular (push) Failing after 6s
Deploy Docs to GitHub Pages / build (push) Failing after 0s
Build Docker Images / build (server, Dockerfile, ${{ github.repository_owner }}/server) (push) Has been skipped
Build Docker Images / build (worker, Worker.Dockerfile, ${{ github.repository_owner }}/worker) (push) Has been skipped
Deploy Docs to GitHub Pages / Deploy (push) Has been skipped
Mirror to Codeberg / Mirror (push) Failing after 0s
Nix Build / check (push) Failing after 0s
Test Publish / build (client) (push) Failing after 0s
Test Publish / build (sdk) (push) Failing after 0s
2025-11-21 12:17:15 +01:00
Jesse Wierzbinski d18f135fbd
refactor(packages/client): 🔥 Remove broken SSO login code 2025-11-21 12:17:02 +01:00
Jesse Wierzbinski 59ad71964b
feat(api): Add FormData support in SSO login 2025-11-21 12:16:47 +01:00
Jesse Wierzbinski bf890aec15
fix(packages/client): 🚨 Remove useless default value 2025-11-21 11:03:16 +01:00
Jesse Wierzbinski 9cf85e951e
test(api): Remove bad streaming timeline tests 2025-11-21 11:02:22 +01:00
Jesse Wierzbinski 814d63554f
chore(packages/client): 🔖 Release 0.2.0 2025-11-21 11:00:40 +01:00
Jesse Wierzbinski ce650a69d4
feat(packages/client): Add SSO login helper to client 2025-11-21 10:59:28 +01:00
Jesse Wierzbinski 5e84fb66f9
chore: ⬆️ Upgrade dependencies
Some checks failed
CodeQL Scan / Analyze (javascript-typescript) (push) Failing after 0s
Build Docker Images / lint (push) Failing after 7s
Build Docker Images / check (push) Failing after 7s
Build Docker Images / tests (push) Failing after 6s
Build Docker Images / detect-circular (push) Failing after 6s
Deploy Docs to GitHub Pages / build (push) Failing after 0s
Build Docker Images / build (server, Dockerfile, ${{ github.repository_owner }}/server) (push) Has been skipped
Build Docker Images / build (worker, Worker.Dockerfile, ${{ github.repository_owner }}/worker) (push) Has been skipped
Deploy Docs to GitHub Pages / Deploy (push) Has been skipped
Mirror to Codeberg / Mirror (push) Failing after 1s
Nix Build / check (push) Failing after 0s
Test Publish / build (client) (push) Failing after 0s
Test Publish / build (sdk) (push) Failing after 0s
2025-11-21 09:00:37 +01:00
Jesse Wierzbinski 1430d6f7e7
chore: ⬆️ Upgrade to Bun 1.3.2 2025-11-21 08:49:19 +01:00
Jesse Wierzbinski f00ac1a590
chore: ⬆️ Upgrade dependencies 2025-11-21 08:31:02 +01:00
Jesse Wierzbinski f260064083
fix: 🚨 Remove useless function overloading 2025-11-21 07:26:35 +01:00
Gaspard Wierzbinski f2e9c862a6
Merge pull request #42 from versia-pub/refactor/openid
Rewrite old authentication code and go OpenID-only
2025-11-21 07:21:01 +01:00
Jesse Wierzbinski 82bb92768c
fix: 🐛 Set test pattern in DeepSource code analysis config 2025-11-21 06:53:50 +01:00
Jesse Wierzbinski c63b2b320b
fix(config): 💚 Fix incorrect CI config 2025-11-21 06:50:41 +01:00
Jesse Wierzbinski a9dbd2cc4e
fix: 🔥 Remove old tests and docs related to old auth endpoints 2025-11-21 06:45:12 +01:00
Jesse Wierzbinski ae207c10b6
fix: 💚 Update Nix hash 2025-11-03 00:17:57 +01:00
Jesse Wierzbinski 955a933fe9
refactor(api): 🔥 Remove old forced OpenID auth code 2025-10-24 19:12:40 +02:00
Jesse Wierzbinski 45c3f6ae3f
fix(database): 🐛 Cascade application ID deletion 2025-10-24 18:45:07 +02:00
Jesse Wierzbinski bfa7a06958
fix(database): 🐛 Fix applications table not getting deleted correctly during migration 2025-10-24 18:19:22 +02:00
Jesse Wierzbinski c93071666a
fix(packages/client): 🐛 Remove nonexistent options from client's media API
Some checks failed
CodeQL Scan / Analyze (javascript-typescript) (push) Failing after 0s
Build Docker Images / lint (push) Failing after 6s
Build Docker Images / check (push) Failing after 6s
Build Docker Images / tests (push) Failing after 6s
Build Docker Images / detect-circular (push) Failing after 7s
Deploy Docs to GitHub Pages / build (push) Failing after 0s
Build Docker Images / build (server, Dockerfile, ${{ github.repository_owner }}/server) (push) Has been skipped
Build Docker Images / build (worker, Worker.Dockerfile, ${{ github.repository_owner }}/worker) (push) Has been skipped
Deploy Docs to GitHub Pages / Deploy (push) Has been skipped
Mirror to Codeberg / Mirror (push) Failing after 0s
Nix Build / check (push) Failing after 0s
Test Publish / build (client) (push) Failing after 0s
Test Publish / build (sdk) (push) Failing after 0s
2025-08-28 07:07:33 +02:00
Jesse Wierzbinski 0d53436f7e
ci: 💚 Fix CI docs
Some checks failed
CodeQL Scan / Analyze (javascript-typescript) (push) Failing after 1s
Build Docker Images / lint (push) Failing after 8s
Build Docker Images / check (push) Failing after 8s
Build Docker Images / tests (push) Failing after 8s
Build Docker Images / detect-circular (push) Failing after 8s
Build Docker Images / build (server, Dockerfile, ${{ github.repository_owner }}/server) (push) Has been skipped
Deploy Docs to GitHub Pages / build (push) Failing after 1s
Build Docker Images / build (worker, Worker.Dockerfile, ${{ github.repository_owner }}/worker) (push) Has been skipped
Deploy Docs to GitHub Pages / Deploy (push) Has been skipped
Mirror to Codeberg / Mirror (push) Failing after 1s
Nix Build / check (push) Failing after 1s
Test Publish / build (client) (push) Failing after 1s
Test Publish / build (sdk) (push) Failing after 1s
2025-08-22 20:46:38 +02:00
Jesse Wierzbinski d8f9f47814
ci: 💚 Add detect-circular as dependency for docker build 2025-08-22 20:45:11 +02:00
Jesse Wierzbinski b46f7828a5
feat: 🔒 Harden Systemd unit config 2025-08-22 20:44:26 +02:00
Jesse Wierzbinski 1a0a27bee1
refactor(database): 🚚 Rename Application to Client everywhere 2025-08-21 01:21:32 +02:00
Jesse Wierzbinski 6f97903f3b
fix(api): Fix all failing tests 2025-08-21 01:15:38 +02:00
Jesse Wierzbinski 1bfc5fb013
refactor(api): ♻️ Rewrite full authentication code to go OpenID-only 2025-08-21 00:45:58 +02:00
Jesse Wierzbinski 4eae4cd062
feat: 🔒 Harden Systemd unit config 2025-08-09 17:15:05 +02:00
Jesse Wierzbinski a6c9d6cd4f
chore: 🐛 Update Nix hashes
Some checks failed
CodeQL Scan / Analyze (javascript-typescript) (push) Failing after 0s
Build Docker Images / lint (push) Failing after 7s
Build Docker Images / check (push) Failing after 6s
Build Docker Images / tests (push) Failing after 6s
Build Docker Images / build (server, Dockerfile, ${{ github.repository_owner }}/server) (push) Has been skipped
Build Docker Images / build (worker, Worker.Dockerfile, ${{ github.repository_owner }}/worker) (push) Has been skipped
Build Docker Images / detect-circular (push) Failing after 6s
Deploy Docs to GitHub Pages / build (push) Failing after 0s
Deploy Docs to GitHub Pages / Deploy (push) Has been skipped
Mirror to Codeberg / Mirror (push) Failing after 0s
Nix Build / check (push) Failing after 0s
Test Publish / build (client) (push) Failing after 0s
Test Publish / build (sdk) (push) Failing after 0s
2025-07-07 06:11:21 +02:00
Jesse Wierzbinski b5e9e35427
refactor: 🔥 Remove plugin functionality, move OpenID plugin to core 2025-07-07 05:52:11 +02:00
Gaspard Wierzbinski 278bf960cb
Merge pull request #41 from versia-pub/refactor/packages
Refactor/packages
2025-07-07 05:16:09 +02:00
Jesse Wierzbinski 0bf5f7c983
fix: 🚨 Fix further DeepSource issues 2025-07-07 05:12:23 +02:00
Jesse Wierzbinski 870b6dbe85
fix: 🚨 Fix Deepsource warnings 2025-07-07 05:08:34 +02:00
Jesse Wierzbinski 2fffbcbede
fix: 🐛 Fix weird imports failing build 2025-07-07 04:52:46 +02:00
Jesse Wierzbinski 551b9a94fe
ci: 💚 Use correct name in CI 2025-07-07 04:39:36 +02:00
Jesse Wierzbinski 24d4150da4
refactor: ⬆️ Upgrade to Zod v4 and hono-openapi 0.5.0 2025-07-07 03:42:35 +02:00
Jesse Wierzbinski add2429606
docs: 📝 Improve Copilot instructions file
Some checks failed
Mirror to Codeberg / Mirror (push) Failing after 0s
Test Publish / build (client) (push) Failing after 1s
Test Publish / build (sdk) (push) Failing after 0s
2025-07-06 05:06:05 +02:00
Jesse Wierzbinski eb096c5991
fix: 💚 Fix the Nix build, remove dependency on PNPM 2025-07-06 02:25:06 +02:00
Jesse Wierzbinski 30bb801f9f
fix: 💚 Fix Docker image builds 2025-07-06 02:10:44 +02:00
Jesse Wierzbinski 6d7c545c88
chore: ⬆️ Upgrade Bun to 1.2.18 2025-07-06 02:03:27 +02:00
Jesse Wierzbinski a1300466f4
chore: ⬆️ Upgrade dependencies 2025-07-06 02:02:48 +02:00
Jesse Wierzbinski 90b6399407
refactor: ♻️ Rewrite build system to fit the monorepo architecture
Some checks failed
Mirror to Codeberg / Mirror (push) Failing after 0s
Test Publish / build (client) (push) Failing after 1s
Test Publish / build (sdk) (push) Failing after 0s
2025-07-04 06:29:43 +02:00
Jesse Wierzbinski 7de4b573e3
refactor(worker): 🚚 Move queue code to plugin-kit package
Some checks failed
Mirror to Codeberg / Mirror (push) Failing after 1s
Test Publish / build (client) (push) Failing after 1s
Test Publish / build (sdk) (push) Failing after 1s
2025-06-29 22:56:52 +02:00
Jesse Wierzbinski dc802ff5f6
feat(api): Begin work on Streaming API 2025-06-29 22:23:03 +02:00
Jesse Wierzbinski 59cd519337
fix(api): 🐛 Fix error when masto-fe stupidly sends empty spoiler_text
Some checks failed
Mirror to Codeberg / Mirror (push) Failing after 0s
Test Publish / build (client) (push) Failing after 0s
Test Publish / build (sdk) (push) Failing after 0s
2025-06-23 18:53:40 +02:00
Jesse Wierzbinski aff51b651c
refactor: ♻️ Rewrite logging logic into a unified package
Some checks failed
Mirror to Codeberg / Mirror (push) Failing after 0s
Test Publish / build (client) (push) Failing after 0s
Test Publish / build (sdk) (push) Failing after 0s
2025-06-22 18:43:03 +02:00
Jesse Wierzbinski e1bd389bf1
refactor: 🔥 Remove Devcontainer
It was useless and nobody has ever used it once.
2025-06-22 17:56:54 +02:00
Jesse Wierzbinski 2310e8b33d
chore: ⬆️ Upgrade Bun to 1.2.17 2025-06-22 17:55:50 +02:00
Jesse Wierzbinski 129bc97b09
chore: ⬆️ Upgrade dependencies 2025-06-22 17:53:53 +02:00
Jesse Wierzbinski 1a666e8371
refactor: ♻️ [BROKEN] Refactor Nix build to use fetchBunDeps PR 2025-06-22 17:46:29 +02:00
Jesse Wierzbinski 03940cd8fd
fix: 📄 Add licenses to both JSR packages
Some checks failed
Mirror to Codeberg / Mirror (push) Failing after 0s
Test Publish / build (client) (push) Failing after 0s
Test Publish / build (sdk) (push) Failing after 0s
2025-06-17 19:59:37 +02:00
Jesse Wierzbinski 1f03017327
refactor: 🚚 Rename @versia/kit to @versia-server/kit
Some checks failed
Mirror to Codeberg / Mirror (push) Failing after 0s
Test Publish / build (client) (push) Failing after 0s
Test Publish / build (sdk) (push) Failing after 0s
2025-06-15 23:50:34 +02:00
Jesse Wierzbinski 3798e170d0
refactor: 🚚 Move more utilities into packages 2025-06-15 23:43:27 +02:00
Jesse Wierzbinski 5cae547f8d
chore: 💚 Update Nix hashes 2025-06-15 22:26:43 +02:00
Jesse Wierzbinski fde70fa61a
refactor: 🚚 Move testing to its own sub-package 2025-06-15 22:17:33 +02:00
Jesse Wierzbinski a211772309
fix: 🐛 Fix Nix build
Some checks failed
Mirror to Codeberg / Mirror (push) Failing after 0s
Test Publish / build (client) (push) Failing after 0s
Test Publish / build (sdk) (push) Failing after 0s
2025-06-15 19:23:11 +02:00
Jesse Wierzbinski a6d3ebbeef
refactor: 🚚 Organize code into sub-packages, instead of a single large package 2025-06-15 04:38:20 +02:00
Jesse Wierzbinski 79742f47dc
chore(api): 🔥 Remove clustering ability from API worker
Some checks failed
CodeQL Scan / Analyze (javascript-typescript) (push) Failing after 1s
Build Docker Images / lint (push) Failing after 7s
Build Docker Images / check (push) Failing after 6s
Build Docker Images / tests (push) Failing after 6s
Deploy Docs to GitHub Pages / build (push) Failing after 0s
Build Docker Images / build (server, Dockerfile, ${{ github.repository_owner }}/server) (push) Has been skipped
Build Docker Images / build (worker, Worker.Dockerfile, ${{ github.repository_owner }}/worker) (push) Has been skipped
Deploy Docs to GitHub Pages / Deploy (push) Has been skipped
Mirror to Codeberg / Mirror (push) Failing after 0s
Nix Build / check (push) Failing after 1s
Test Publish / build (client) (push) Failing after 0s
Test Publish / build (sdk) (push) Failing after 0s
2025-06-15 02:28:02 +02:00
Jesse Wierzbinski 4cc6284eb4
chore: ⬆️ Upgrade dependencies 2025-06-15 02:24:56 +02:00
Jesse Wierzbinski 13d43e8e71
fix: 🐛 Fix Nix build
Some checks failed
CodeQL Scan / Analyze (javascript-typescript) (push) Failing after 0s
Build Docker Images / lint (push) Failing after 6s
Build Docker Images / check (push) Failing after 7s
Build Docker Images / tests (push) Failing after 6s
Deploy Docs to GitHub Pages / build (push) Failing after 0s
Build Docker Images / build (server, Dockerfile, ${{ github.repository_owner }}/server) (push) Has been skipped
Build Docker Images / build (worker, Worker.Dockerfile, ${{ github.repository_owner }}/worker) (push) Has been skipped
Deploy Docs to GitHub Pages / Deploy (push) Has been skipped
Mirror to Codeberg / Mirror (push) Failing after 0s
Nix Build / check (push) Failing after 0s
Test Publish / build (client) (push) Failing after 0s
Test Publish / build (sdk) (push) Failing after 0s
2025-06-04 16:24:09 +02:00
Jesse Wierzbinski 0ae8f632b5
chore: ⬆️ Upgrade to Bun 1.2.15
Some checks failed
CodeQL Scan / Analyze (javascript-typescript) (push) Failing after 0s
Build Docker Images / lint (push) Failing after 6s
Build Docker Images / check (push) Failing after 6s
Build Docker Images / tests (push) Failing after 7s
Deploy Docs to GitHub Pages / build (push) Failing after 1s
Build Docker Images / build (server, Dockerfile, ${{ github.repository_owner }}/server) (push) Has been skipped
Build Docker Images / build (worker, Worker.Dockerfile, ${{ github.repository_owner }}/worker) (push) Has been skipped
Deploy Docs to GitHub Pages / Deploy (push) Has been skipped
Mirror to Codeberg / Mirror (push) Failing after 1s
Nix Build / check (push) Failing after 1s
Test Publish / build (client) (push) Failing after 1s
Test Publish / build (sdk) (push) Failing after 1s
2025-06-04 16:20:24 +02:00
Jesse Wierzbinski 85aceb2e48
chore: ⬆️ Upgrade dependencies 2025-06-04 16:18:49 +02:00
Jesse Wierzbinski 0692aa6efa
fix(federation): 👽 Add Reactions to list of supported extensions
Some checks failed
CodeQL Scan / Analyze (javascript-typescript) (push) Failing after 1s
Build Docker Images / lint (push) Failing after 8s
Build Docker Images / check (push) Failing after 7s
Build Docker Images / tests (push) Failing after 7s
Deploy Docs to GitHub Pages / build (push) Failing after 0s
Build Docker Images / build (server, Dockerfile, ${{ github.repository_owner }}/server) (push) Has been skipped
Build Docker Images / build (worker, Worker.Dockerfile, ${{ github.repository_owner }}/worker) (push) Has been skipped
Deploy Docs to GitHub Pages / Deploy (push) Has been skipped
Mirror to Codeberg / Mirror (push) Failing after 0s
Nix Build / check (push) Failing after 0s
Test Publish / build (client) (push) Failing after 0s
Test Publish / build (sdk) (push) Failing after 0s
2025-05-28 20:42:29 +02:00
Jesse Wierzbinski 15e291b487
chore(packages/client): 🔖 Release 0.2.0-alpha.4 2025-05-28 17:19:04 +02:00
Jesse Wierzbinski 343a507ecc
feat(federation): Federate Reactions 2025-05-28 17:17:03 +02:00
Jesse Wierzbinski fa1dd69e2d
feat(api): Make Reactions API correctly output whether a reaction is remote 2025-05-28 17:07:24 +02:00
Jesse Wierzbinski e0adaca2a2
feat(federation): Add inbound Reaction processing 2025-05-28 16:50:59 +02:00
Jesse Wierzbinski 1fba91f772
chore(config): 👽 Update JSON schema files
Some checks failed
CodeQL Scan / Analyze (javascript-typescript) (push) Failing after 0s
Build Docker Images / lint (push) Failing after 8s
Build Docker Images / check (push) Failing after 7s
Build Docker Images / tests (push) Failing after 8s
Deploy Docs to GitHub Pages / build (push) Failing after 0s
Build Docker Images / build (server, Dockerfile, ${{ github.repository_owner }}/server) (push) Has been skipped
Build Docker Images / build (worker, Worker.Dockerfile, ${{ github.repository_owner }}/worker) (push) Has been skipped
Deploy Docs to GitHub Pages / Deploy (push) Has been skipped
Mirror to Codeberg / Mirror (push) Failing after 0s
Nix Build / check (push) Failing after 0s
Test Publish / build (client) (push) Failing after 0s
Test Publish / build (sdk) (push) Failing after 0s
2025-05-28 03:06:49 +02:00
Jesse Wierzbinski 710f965144
fix(federation): 🔒 Enforce content filters for remote content as well 2025-05-28 02:59:26 +02:00
Jesse Wierzbinski c737aeba8e
fix(api): 🐛 Enforce emoji shortcode filters 2025-05-28 02:45:53 +02:00
Jesse Wierzbinski 9eac364e01
refactor(database): 🔥 Always import SQL operators directly from drizzle
Some checks failed
CodeQL Scan / Analyze (javascript-typescript) (push) Failing after 0s
Build Docker Images / lint (push) Failing after 7s
Build Docker Images / tests (push) Failing after 7s
Deploy Docs to GitHub Pages / build (push) Failing after 0s
Build Docker Images / build (server, Dockerfile, ${{ github.repository_owner }}/server) (push) Has been skipped
Build Docker Images / build (worker, Worker.Dockerfile, ${{ github.repository_owner }}/worker) (push) Has been skipped
Deploy Docs to GitHub Pages / Deploy (push) Has been skipped
Mirror to Codeberg / Mirror (push) Failing after 0s
Nix Build / check (push) Failing after 0s
Test Publish / build (client) (push) Failing after 0s
Test Publish / build (sdk) (push) Failing after 0s
Build Docker Images / check (push) Failing after 7s
2025-05-26 19:00:24 +02:00
Jesse Wierzbinski d3f411915f
chore(packages/client): 🔖 Release 0.2.0-alpha.3 2025-05-26 18:42:20 +02:00
Jesse Wierzbinski 7bd07801f2
feat(api): Add support for batch account data API 2025-05-26 18:41:45 +02:00
Jesse Wierzbinski 287f428a83
fix(api): 🐛 Add Reaction custom emoji data in statuses 2025-05-26 15:13:56 +02:00
Jesse Wierzbinski 8c0a20a743
chore(packages/client): 🔖 Release 0.2.0-alpha.2
Some checks failed
Build Docker Images / lint (push) Failing after 7s
Build Docker Images / check (push) Failing after 7s
Build Docker Images / tests (push) Failing after 7s
Deploy Docs to GitHub Pages / build (push) Failing after 0s
CodeQL Scan / Analyze (javascript-typescript) (push) Failing after 0s
Build Docker Images / build (server, Dockerfile, ${{ github.repository_owner }}/server) (push) Has been skipped
Build Docker Images / build (worker, Worker.Dockerfile, ${{ github.repository_owner }}/worker) (push) Has been skipped
Deploy Docs to GitHub Pages / Deploy (push) Has been skipped
Mirror to Codeberg / Mirror (push) Failing after 0s
Nix Build / check (push) Failing after 0s
Test Publish / build (client) (push) Failing after 0s
Test Publish / build (sdk) (push) Failing after 0s
2025-05-26 11:05:02 +02:00
Jesse Wierzbinski 6d85dbdfcb
fix(packages/client): 🐛 Fix client types, and add missing banner schema for Instance 2025-05-26 11:04:09 +02:00
Jesse Wierzbinski 77cd27a458
ci: 👷 Add CI workflow to publish packages 2025-05-26 09:08:14 +02:00
Jesse Wierzbinski e5e688a154
fix: 🐛 Add type: json specifier to all JSON imports 2025-05-26 08:55:06 +02:00
Jesse Wierzbinski fa5be6bd6a
chore: 🐛 Add jsr registry file to SDK package 2025-05-26 08:52:30 +02:00
Jesse Wierzbinski bf9840bd14
ci: 💚 Fix test publish CI 2025-05-26 08:47:27 +02:00
Jesse Wierzbinski 0551b8e12d
chore: 🔖 Set version to 0.9.0-alpha.0
Some checks failed
CodeQL Scan / Analyze (javascript-typescript) (push) Failing after 0s
Build Docker Images / lint (push) Failing after 7s
Build Docker Images / check (push) Failing after 6s
Build Docker Images / tests (push) Failing after 6s
Deploy Docs to GitHub Pages / build (push) Failing after 0s
Build Docker Images / build (server, Dockerfile, ${{ github.repository_owner }}/server) (push) Has been skipped
Build Docker Images / build (worker, Worker.Dockerfile, ${{ github.repository_owner }}/worker) (push) Has been skipped
Deploy Docs to GitHub Pages / Deploy (push) Has been skipped
Mirror to Codeberg / Mirror (push) Failing after 0s
Nix Build / check (push) Failing after 0s
Test Publish / build (client) (push) Failing after 0s
Test Publish / build (sdk) (push) Failing after 0s
2025-05-25 16:14:24 +02:00
Jesse Wierzbinski 9722b94eae
feat(api): Add Emoji Reactions 2025-05-25 16:11:56 +02:00
Jesse Wierzbinski 70974d3c35
chore: ⬆️ Upgrade dependencies
Some checks failed
Build Docker Images / check (push) Failing after 6s
CodeQL Scan / Analyze (javascript-typescript) (push) Failing after 0s
Build Docker Images / tests (push) Failing after 6s
Deploy Docs to GitHub Pages / build (push) Failing after 0s
Build Docker Images / build (server, Dockerfile, ${{ github.repository_owner }}/server) (push) Has been skipped
Build Docker Images / build (worker, Worker.Dockerfile, ${{ github.repository_owner }}/worker) (push) Has been skipped
Deploy Docs to GitHub Pages / Deploy (push) Has been skipped
Mirror to Codeberg / Mirror (push) Failing after 0s
Nix Build / check (push) Failing after 0s
Test Publish / build (client) (push) Failing after 0s
Test Publish / build (sdk) (push) Failing after 0s
Build Docker Images / lint (push) Failing after 6s
2025-05-23 19:21:49 +02:00
Jesse Wierzbinski 99a7658956
refactor: 🏷️ Update tsconfig.json and fix resulting errors
Some checks failed
Build Docker Images / build (server, Dockerfile, ${{ github.repository_owner }}/server) (push) Has been skipped
Build Docker Images / build (worker, Worker.Dockerfile, ${{ github.repository_owner }}/worker) (push) Has been skipped
Deploy Docs to GitHub Pages / build (push) Failing after 1s
Deploy Docs to GitHub Pages / Deploy (push) Has been skipped
Mirror to Codeberg / Mirror (push) Failing after 0s
Nix Build / check (push) Failing after 0s
CodeQL Scan / Analyze (javascript-typescript) (push) Failing after 0s
Build Docker Images / lint (push) Failing after 8s
Build Docker Images / check (push) Failing after 8s
Build Docker Images / tests (push) Failing after 8s
Test Publish / build (client) (push) Failing after 0s
Test Publish / build (sdk) (push) Failing after 0s
2025-05-23 17:29:27 +02:00
Jesse Wierzbinski 64068f9d23
docs: 📝 Update changelog
Some checks failed
CodeQL Scan / Analyze (javascript-typescript) (push) Failing after 0s
Build Docker Images / lint (push) Failing after 7s
Build Docker Images / check (push) Failing after 7s
Build Docker Images / tests (push) Failing after 6s
Deploy Docs to GitHub Pages / build (push) Failing after 0s
Build Docker Images / build (server, Dockerfile, ${{ github.repository_owner }}/server) (push) Has been skipped
Build Docker Images / build (worker, Worker.Dockerfile, ${{ github.repository_owner }}/worker) (push) Has been skipped
Deploy Docs to GitHub Pages / Deploy (push) Has been skipped
Mirror to Codeberg / Mirror (push) Failing after 0s
Nix Build / check (push) Failing after 0s
Test Publish / build (client) (push) Failing after 0s
Test Publish / build (sdk) (push) Failing after 0s
2025-05-19 15:16:00 +02:00
Jesse Wierzbinski 1d96db5313
Merge branch 'chore/v0.8' of https://github.com/versia-pub/server into chore/v0.8 2025-05-19 15:07:50 +02:00
Jesse Wierzbinski e64457c7e2
chore: 🔖 Set all versions to v0.8 2025-05-19 15:07:08 +02:00
Jesse Wierzbinski 6bb4f90c18
chore: 🔖 Set all versions to v0.8 2025-05-19 15:06:48 +02:00
Jesse Wierzbinski e50c8b6a5b
docs: 📝 Update docs to reflect latest changes 2025-05-19 15:05:22 +02:00
Jesse Wierzbinski d12bbb2a1b
ci: 👷 Correctly populate NPM token 2025-05-19 14:44:02 +02:00
Jesse Wierzbinski 0fc94cab3b
ci(api): 🐛 Fix public test workflow 2025-05-19 14:37:48 +02:00
Jesse Wierzbinski affe456fb8
chore: ⬆️ Upgrade dependencies 2025-05-19 14:35:27 +02:00
Jesse Wierzbinski 980b902927
chore: ⬆️ Upgrade Bun to 1.2.13
Some checks failed
Build Docker Images / lint (push) Failing after 6s
CodeQL Scan / Analyze (javascript-typescript) (push) Failing after 0s
Build Docker Images / check (push) Failing after 6s
Build Docker Images / tests (push) Failing after 7s
Deploy Docs to GitHub Pages / build (push) Failing after 0s
Build Docker Images / build (server, Dockerfile, ${{ github.repository_owner }}/server) (push) Has been skipped
Build Docker Images / build (worker, Worker.Dockerfile, ${{ github.repository_owner }}/worker) (push) Has been skipped
Deploy Docs to GitHub Pages / Deploy (push) Has been skipped
Mirror to Codeberg / Mirror (push) Failing after 0s
Nix Build / check (push) Failing after 0s
Test Publish / build (client) (push) Failing after 0s
Test Publish / build (sdk) (push) Failing after 0s
2025-05-16 01:51:06 +02:00
Jesse Wierzbinski 7f23aa893b
chore: ⬆️ Upgrade dependencies 2025-05-16 01:50:19 +02:00
Jesse Wierzbinski 5dfcfc548f
refactor(api): ♻️ Make SDK and client package only use resources in their own package
Some checks failed
CodeQL Scan / Analyze (javascript-typescript) (push) Failing after 1s
Build Docker Images / lint (push) Failing after 7s
Build Docker Images / check (push) Failing after 6s
Build Docker Images / tests (push) Failing after 6s
Deploy Docs to GitHub Pages / build (push) Failing after 0s
Build Docker Images / build (server, Dockerfile, ${{ github.repository_owner }}/server) (push) Has been skipped
Build Docker Images / build (worker, Worker.Dockerfile, ${{ github.repository_owner }}/worker) (push) Has been skipped
Deploy Docs to GitHub Pages / Deploy (push) Has been skipped
Mirror to Codeberg / Mirror (push) Failing after 0s
Nix Build / check (push) Failing after 1s
Test Publish / build (client) (push) Failing after 0s
Test Publish / build (sdk) (push) Failing after 0s
2025-05-13 11:51:59 +02:00
Jesse Wierzbinski c0060f1baf
test(federation): Add test for Note deletion 2025-05-13 11:06:50 +02:00
Jesse Wierzbinski 58bcbc4da7
fix(federation): 🐛 Properly handle manually_approves_followers
Some checks failed
CodeQL Scan / Analyze (javascript-typescript) (push) Failing after 1s
Build Docker Images / lint (push) Failing after 7s
Build Docker Images / check (push) Failing after 6s
Build Docker Images / tests (push) Failing after 6s
Deploy Docs to GitHub Pages / build (push) Failing after 0s
Build Docker Images / build (server, Dockerfile, ${{ github.repository_owner }}/server) (push) Has been skipped
Build Docker Images / build (worker, Worker.Dockerfile, ${{ github.repository_owner }}/worker) (push) Has been skipped
Deploy Docs to GitHub Pages / Deploy (push) Has been skipped
Mirror to Codeberg / Mirror (push) Failing after 0s
Nix Build / check (push) Failing after 0s
2025-05-09 18:47:28 +02:00
Jesse Wierzbinski 4d8fe93188
chore: ⬆️ Upgrade dependencies
Some checks failed
CodeQL Scan / Analyze (javascript-typescript) (push) Failing after 0s
Build Docker Images / lint (push) Failing after 6s
Build Docker Images / check (push) Failing after 6s
Build Docker Images / tests (push) Failing after 6s
Deploy Docs to GitHub Pages / build (push) Failing after 0s
Build Docker Images / build (server, Dockerfile, ${{ github.repository_owner }}/server) (push) Has been skipped
Build Docker Images / build (worker, Worker.Dockerfile, ${{ github.repository_owner }}/worker) (push) Has been skipped
Deploy Docs to GitHub Pages / Deploy (push) Has been skipped
Mirror to Codeberg / Mirror (push) Failing after 0s
Nix Build / check (push) Failing after 0s
2025-05-08 12:57:24 +02:00
Jesse Wierzbinski cf08479c48
chore: ⬆️ Upgrade dependencies
Some checks failed
CodeQL Scan / Analyze (javascript-typescript) (push) Failing after 0s
Build Docker Images / lint (push) Failing after 6s
Build Docker Images / check (push) Failing after 6s
Build Docker Images / tests (push) Failing after 6s
Build Docker Images / build (server, Dockerfile, ${{ github.repository_owner }}/server) (push) Has been skipped
Build Docker Images / build (worker, Worker.Dockerfile, ${{ github.repository_owner }}/worker) (push) Has been skipped
Deploy Docs to GitHub Pages / build (push) Failing after 0s
Deploy Docs to GitHub Pages / Deploy (push) Has been skipped
Mirror to Codeberg / Mirror (push) Failing after 0s
Nix Build / check (push) Failing after 0s
2025-05-05 18:03:57 +02:00
Jesse Wierzbinski ddb3cfc978
perf(api): Store user and post metrics directly in database instead of recalculating them on-the-fly
Some checks failed
CodeQL Scan / Analyze (javascript-typescript) (push) Failing after 0s
Build Docker Images / lint (push) Failing after 6s
Build Docker Images / check (push) Failing after 6s
Build Docker Images / tests (push) Failing after 6s
Deploy Docs to GitHub Pages / build (push) Failing after 1s
Build Docker Images / build (server, Dockerfile, ${{ github.repository_owner }}/server) (push) Has been skipped
Build Docker Images / build (worker, Worker.Dockerfile, ${{ github.repository_owner }}/worker) (push) Has been skipped
Deploy Docs to GitHub Pages / Deploy (push) Has been skipped
Mirror to Codeberg / Mirror (push) Failing after 1s
Nix Build / check (push) Failing after 1s
2025-05-04 16:38:37 +02:00
Jesse Wierzbinski cd12ccd6c1
feat(federation): Implement Share federation support
Some checks failed
CodeQL Scan / Analyze (javascript-typescript) (push) Failing after 0s
Build Docker Images / lint (push) Failing after 6s
Build Docker Images / check (push) Failing after 7s
Build Docker Images / tests (push) Failing after 6s
Build Docker Images / build (server, Dockerfile, ${{ github.repository_owner }}/server) (push) Has been skipped
Build Docker Images / build (worker, Worker.Dockerfile, ${{ github.repository_owner }}/worker) (push) Has been skipped
Deploy Docs to GitHub Pages / build (push) Failing after 0s
Deploy Docs to GitHub Pages / Deploy (push) Has been skipped
Mirror to Codeberg / Mirror (push) Failing after 0s
Nix Build / check (push) Failing after 0s
2025-05-02 12:48:47 +02:00
Jesse Wierzbinski ec69fc2ac0
feat(api): Add media attachments to RSS and Atom feeds
Some checks failed
CodeQL Scan / Analyze (javascript-typescript) (push) Failing after 0s
Build Docker Images / lint (push) Failing after 8s
Build Docker Images / check (push) Failing after 6s
Build Docker Images / tests (push) Failing after 7s
Deploy Docs to GitHub Pages / build (push) Failing after 0s
Build Docker Images / build (server, Dockerfile, ${{ github.repository_owner }}/server) (push) Has been skipped
Build Docker Images / build (worker, Worker.Dockerfile, ${{ github.repository_owner }}/worker) (push) Has been skipped
Deploy Docs to GitHub Pages / Deploy (push) Has been skipped
Mirror to Codeberg / Mirror (push) Failing after 0s
Nix Build / check (push) Failing after 0s
2025-05-01 22:47:29 +02:00
Jesse Wierzbinski 3832328aaf
feat(api): Add RSS and Atom feed functionality 2025-05-01 22:35:32 +02:00
Jesse Wierzbinski 70aff2df68
fix: 🐛 Re-add mathjax dependency
Required for building docs
2025-05-01 22:02:45 +02:00
Jesse Wierzbinski 55329eaae0
chore: ⬆️ Upgrade Bun to 1.2.11 2025-05-01 16:30:58 +02:00
Jesse Wierzbinski 4a4f72fd66
chore: ⬆️ Upgrade dependencies 2025-05-01 16:27:34 +02:00
Jesse Wierzbinski 441c7714d9
fix(api): 🐛 Fix source not being correctly saved when creating notes 2025-05-01 15:52:00 +02:00
Jesse Wierzbinski 294924fc49
fix(api): 🐛 Don't allow replying to reblogs
Some checks failed
CodeQL Scan / Analyze (javascript-typescript) (push) Failing after 0s
Build Docker Images / lint (push) Failing after 6s
Build Docker Images / check (push) Failing after 6s
Build Docker Images / tests (push) Failing after 6s
Deploy Docs to GitHub Pages / build (push) Failing after 0s
Build Docker Images / build (server, Dockerfile, ${{ github.repository_owner }}/server) (push) Has been skipped
Build Docker Images / build (worker, Worker.Dockerfile, ${{ github.repository_owner }}/worker) (push) Has been skipped
Deploy Docs to GitHub Pages / Deploy (push) Has been skipped
Mirror to Codeberg / Mirror (push) Failing after 0s
Nix Build / check (push) Failing after 0s
2025-05-01 04:36:08 +02:00
Jesse Wierzbinski 2155ca12be
fix(federation): 🐛 Fix remote interactions not sending out notifications 2025-05-01 03:19:38 +02:00
Jesse Wierzbinski 8874688054
fix(api): 🐛 Massively increase lookup ratelimit 2025-05-01 03:03:14 +02:00
Jesse Wierzbinski cf75679d7f
fix: 🐛 Remove usage of old cli start command 2025-05-01 01:58:22 +02:00
Jesse Wierzbinski 37cbe12c4d
fix: 🐛 Copy detect-libc inside node_modules
Some checks failed
CodeQL Scan / Analyze (javascript-typescript) (push) Failing after 0s
Build Docker Images / lint (push) Failing after 6s
Build Docker Images / check (push) Failing after 6s
Build Docker Images / tests (push) Failing after 6s
Deploy Docs to GitHub Pages / build (push) Failing after 0s
Build Docker Images / build (worker, Worker.Dockerfile, ${{ github.repository_owner }}/worker) (push) Has been skipped
Build Docker Images / build (server, Dockerfile, ${{ github.repository_owner }}/server) (push) Has been skipped
Deploy Docs to GitHub Pages / Deploy (push) Has been skipped
Mirror to Codeberg / Mirror (push) Failing after 0s
Nix Build / check (push) Failing after 0s
2025-04-30 21:26:35 +02:00
Jesse Wierzbinski d2531e8ace
fix: 🐛 Fix incorrect worker Dockerfile executable
Some checks failed
CodeQL Scan / Analyze (javascript-typescript) (push) Failing after 1s
Build Docker Images / lint (push) Failing after 7s
Build Docker Images / check (push) Failing after 6s
Build Docker Images / tests (push) Failing after 7s
Deploy Docs to GitHub Pages / build (push) Failing after 0s
Build Docker Images / build (worker, Worker.Dockerfile, ${{ github.repository_owner }}/worker) (push) Has been skipped
Build Docker Images / build (server, Dockerfile, ${{ github.repository_owner }}/server) (push) Has been skipped
Deploy Docs to GitHub Pages / Deploy (push) Has been skipped
Mirror to Codeberg / Mirror (push) Failing after 0s
Nix Build / check (push) Failing after 0s
2025-04-30 02:53:58 +02:00
Jesse Wierzbinski 9e08248f0c
refactor: 🎨 De-clutter flake
Some checks failed
CodeQL Scan / Analyze (javascript-typescript) (push) Failing after 0s
Build Docker Images / lint (push) Failing after 6s
Build Docker Images / check (push) Failing after 6s
Build Docker Images / tests (push) Failing after 6s
Deploy Docs to GitHub Pages / build (push) Failing after 0s
Build Docker Images / build (server, Dockerfile, ${{ github.repository_owner }}/server) (push) Has been skipped
Build Docker Images / build (worker, Worker.Dockerfile, ${{ github.repository_owner }}/worker) (push) Has been skipped
Deploy Docs to GitHub Pages / Deploy (push) Has been skipped
Mirror to Codeberg / Mirror (push) Failing after 0s
Nix Build / check (push) Failing after 0s
2025-04-20 17:08:46 +02:00
Jesse Wierzbinski 138f4fade3
refactor(database): ♻️ Use Bun.SQL instead of pg
Some checks failed
CodeQL Scan / Analyze (javascript-typescript) (push) Failing after 1s
Build Docker Images / lint (push) Failing after 7s
Build Docker Images / check (push) Failing after 7s
Build Docker Images / tests (push) Failing after 7s
Deploy Docs to GitHub Pages / build (push) Failing after 0s
Build Docker Images / build (server, Dockerfile, ${{ github.repository_owner }}/server) (push) Has been skipped
Build Docker Images / build (worker, Worker.Dockerfile, ${{ github.repository_owner }}/worker) (push) Has been skipped
Deploy Docs to GitHub Pages / Deploy (push) Has been skipped
Mirror to Codeberg / Mirror (push) Failing after 0s
Nix Build / check (push) Failing after 0s
2025-04-19 14:15:08 +02:00
Jesse Wierzbinski f95f57c4d4
chore: ⬆️ Upgrade to Bun 1.2.10 2025-04-19 13:29:35 +02:00
Jesse Wierzbinski fd9145b7a8
chore: 🔥 Remove useless file 2025-04-19 13:27:25 +02:00
Jesse Wierzbinski 8ae4f3815a
fix(federation): 🚑 Fix broken inbound federation and add end-to-end testing for federation 2025-04-19 13:16:53 +02:00
Jesse Wierzbinski 85ef96fc7f
fix(federation): 🐛 Use explicit header object destructuring in inbox processing
Some checks failed
CodeQL Scan / Analyze (javascript-typescript) (push) Failing after 0s
Build Docker Images / lint (push) Failing after 6s
Build Docker Images / check (push) Failing after 6s
Build Docker Images / tests (push) Failing after 6s
Deploy Docs to GitHub Pages / build (push) Failing after 0s
Build Docker Images / build (server, Dockerfile, ${{ github.repository_owner }}/server) (push) Has been skipped
Build Docker Images / build (worker, Worker.Dockerfile, ${{ github.repository_owner }}/worker) (push) Has been skipped
Deploy Docs to GitHub Pages / Deploy (push) Has been skipped
Mirror to Codeberg / Mirror (push) Failing after 1s
Nix Build / check (push) Failing after 1s
2025-04-18 14:58:04 +02:00
Jesse Wierzbinski 6edb0310d8
fix(api): 🐛 Don't require JWT cookie for static content in bull-board UI 2025-04-18 14:38:00 +02:00
Jesse Wierzbinski 054b8bc5cb
fix(federation): 🐛 Fix incorrect destructuring causing federation issues 2025-04-18 14:27:53 +02:00
Jesse Wierzbinski 1d17831454
chore: Remove unused dependencies
Some checks failed
CodeQL Scan / Analyze (javascript-typescript) (push) Failing after 0s
Build Docker Images / lint (push) Failing after 6s
Build Docker Images / check (push) Failing after 6s
Build Docker Images / tests (push) Failing after 5s
Deploy Docs to GitHub Pages / build (push) Failing after 0s
Build Docker Images / build (server, Dockerfile, ${{ github.repository_owner }}/server) (push) Has been skipped
Build Docker Images / build (worker, Worker.Dockerfile, ${{ github.repository_owner }}/worker) (push) Has been skipped
Deploy Docs to GitHub Pages / Deploy (push) Has been skipped
Mirror to Codeberg / Mirror (push) Failing after 0s
Nix Build / check (push) Failing after 0s
2025-04-16 17:31:34 +02:00
Jesse Wierzbinski 98616ceefb
chore: ⬆️ Upgrade dependencies 2025-04-16 17:03:28 +02:00
Jesse Wierzbinski ffa0c209b6
fix(api): 👽 Use new Scalar API
Some checks failed
CodeQL Scan / Analyze (javascript-typescript) (push) Failing after 0s
Build Docker Images / lint (push) Failing after 6s
Build Docker Images / check (push) Failing after 6s
Build Docker Images / tests (push) Failing after 6s
Deploy Docs to GitHub Pages / build (push) Failing after 0s
Build Docker Images / build (server, Dockerfile, ${{ github.repository_owner }}/server) (push) Has been skipped
Build Docker Images / build (worker, Worker.Dockerfile, ${{ github.repository_owner }}/worker) (push) Has been skipped
Deploy Docs to GitHub Pages / Deploy (push) Has been skipped
Mirror to Codeberg / Mirror (push) Failing after 0s
Nix Build / check (push) Failing after 0s
2025-04-16 16:40:47 +02:00
Jesse Wierzbinski a2e907390f
fix(api): 🐛 Don't use URL in Versia entity schemas, fixes OpenAPI 2025-04-16 16:35:17 +02:00
Jesse Wierzbinski 0a712128a5
fix(api): 🐛 Fix OpenID provider logos not showing up
Some checks failed
CodeQL Scan / Analyze (javascript-typescript) (push) Failing after 1s
Build Docker Images / lint (push) Failing after 7s
Build Docker Images / check (push) Failing after 6s
Build Docker Images / tests (push) Failing after 6s
Deploy Docs to GitHub Pages / build (push) Failing after 0s
Build Docker Images / build (server, Dockerfile, ${{ github.repository_owner }}/server) (push) Has been skipped
Build Docker Images / build (worker, Worker.Dockerfile, ${{ github.repository_owner }}/worker) (push) Has been skipped
Deploy Docs to GitHub Pages / Deploy (push) Has been skipped
Mirror to Codeberg / Mirror (push) Failing after 0s
Nix Build / check (push) Failing after 0s
2025-04-15 22:59:05 +02:00
Jesse Wierzbinski d54527454f
build: 🚑 Remove old workaround that isn't needed anymore 2025-04-15 21:45:21 +02:00
Jesse Wierzbinski f35aae6c44
chore: 💚 Update dependency hash 2025-04-15 21:39:16 +02:00
Jesse Wierzbinski fb5c3fcd12
refactor(config): 🔥 Remove dependency on c12, use confbox instead 2025-04-15 21:37:36 +02:00
Jesse Wierzbinski da1e209f9e
fix: 🐛 Replace dataDir with module path 2025-04-15 21:07:47 +02:00
Jesse Wierzbinski d6b15b1b85
fix: 🐛 Disable msgpackr native acceleration in Nix deployment
It keeps causing issues with the module loading and being annoying to work with in general
2025-04-15 21:04:08 +02:00
Jesse Wierzbinski 26f2dca5d6
fix(config): 🐛 Make vapid key schema more consistent with other key schemas 2025-04-15 20:46:29 +02:00
Jesse Wierzbinski 88944712fe
fix(config): 🐛 Trigger vapid key autogeneration even when block is not commented out 2025-04-15 20:43:32 +02:00
Jesse Wierzbinski b67d86dc57
fix: 🐛 Fix NixOS module passing incorrect environment variable 2025-04-15 20:31:25 +02:00
Jesse Wierzbinski dad99e854d
fix: 🐛 Fix NixOS module incorrect systemd definitions 2025-04-15 20:27:50 +02:00
Jesse Wierzbinski 2d4465617b
fix: 🐛 Fix more errors in NixOS module definition 2025-04-15 20:19:24 +02:00
Jesse Wierzbinski d46befbd1d
fix: 🐛 Fix NixOS module definitions 2025-04-15 18:11:14 +02:00
Jesse Wierzbinski 765348c440
fix: 🐛 Fix Nix module errors when importing
Some checks failed
CodeQL Scan / Analyze (javascript-typescript) (push) Failing after 0s
Build Docker Images / lint (push) Failing after 6s
Build Docker Images / check (push) Failing after 6s
Build Docker Images / tests (push) Failing after 6s
Deploy Docs to GitHub Pages / build (push) Failing after 1s
Build Docker Images / build (server, Dockerfile, ${{ github.repository_owner }}/server) (push) Has been skipped
Build Docker Images / build (worker, Worker.Dockerfile, ${{ github.repository_owner }}/worker) (push) Has been skipped
Deploy Docs to GitHub Pages / Deploy (push) Has been skipped
Mirror to Codeberg / Mirror (push) Failing after 1s
Nix Build / check (push) Failing after 1s
2025-04-15 14:15:36 +02:00
Jesse Wierzbinski 404d63f6d0
feat(media): Add path_style and path configuration to S3 2025-04-15 13:28:12 +02:00
Jesse Wierzbinski 5bb4e967a7
fix: 📝 Fix typo in Nix docs 2025-04-15 13:05:00 +02:00
Jesse Wierzbinski c26e896afe
docs: 📝 Document Nix installation 2025-04-15 13:03:52 +02:00
Jesse Wierzbinski 2d921438a9
feat: Add DevShell to flake 2025-04-15 11:32:11 +02:00
Jesse Wierzbinski 385997cdcc
feat: Add NixOS module 2025-04-15 11:15:17 +02:00
Jesse Wierzbinski 37bc4458e5
test: 🧪 Fix failing tests due to incorrect cwd resolving
Some checks failed
CodeQL Scan / Analyze (javascript-typescript) (push) Failing after 0s
Build Docker Images / lint (push) Failing after 6s
Build Docker Images / check (push) Failing after 6s
Build Docker Images / tests (push) Failing after 5s
Deploy Docs to GitHub Pages / build (push) Failing after 0s
Build Docker Images / build (server, Dockerfile, ${{ github.repository_owner }}/server) (push) Has been skipped
Build Docker Images / build (worker, Worker.Dockerfile, ${{ github.repository_owner }}/worker) (push) Has been skipped
Deploy Docs to GitHub Pages / Deploy (push) Has been skipped
Mirror to Codeberg / Mirror (push) Failing after 0s
Nix Build / check (push) Failing after 0s
2025-04-14 17:30:01 +02:00
Jesse Wierzbinski 1beb18e321
build: 🏗️ Package Worker 2025-04-14 17:13:36 +02:00
Jesse Wierzbinski 5a4ce29206
build: 🏗️ Make Nix build great again 2025-04-14 16:51:00 +02:00
Jesse Wierzbinski 1679585c4c
fix: 🚨 Enable more Biome 2.0 rules
Some checks failed
CodeQL Scan / Analyze (javascript-typescript) (push) Failing after 4s
Build Docker Images / lint (push) Failing after 10s
Build Docker Images / check (push) Failing after 10s
Build Docker Images / tests (push) Failing after 6s
Deploy Docs to GitHub Pages / build (push) Failing after 0s
Build Docker Images / build (server, Dockerfile, ${{ github.repository_owner }}/server) (push) Has been skipped
Build Docker Images / build (worker, Worker.Dockerfile, ${{ github.repository_owner }}/worker) (push) Has been skipped
Deploy Docs to GitHub Pages / Deploy (push) Has been skipped
Mirror to Codeberg / Mirror (push) Failing after 0s
Nix Build / check (push) Failing after 0s
2025-04-10 19:56:42 +02:00
Jesse Wierzbinski 963173cdae
chore: ⬆️ Upgrade to Biome 2.0 2025-04-10 19:15:31 +02:00
Jesse Wierzbinski e7aec8752c
refactor(database): 🔥 Remove unnecessary Redis connections 2025-04-10 18:58:44 +02:00
Jesse Wierzbinski dc1b58a791
chore: ⬆️ Upgrade Bun to 1.2.9 2025-04-10 18:53:01 +02:00
Jesse Wierzbinski dbde49b9bd
chore: ⬆️ Upgrade dependencies 2025-04-10 18:50:41 +02:00
Gaspard Wierzbinski 7e44e55b3f
Merge pull request #36 from versia-pub/refactor/federation
Some checks failed
CodeQL Scan / Analyze (javascript-typescript) (push) Failing after 54s
Build Docker Images / lint (push) Successful in 28s
Build Docker Images / check (push) Successful in 53s
Build Docker Images / tests (push) Failing after 6s
Build Docker Images / build (server, Dockerfile, ${{ github.repository_owner }}/server) (push) Has been skipped
Build Docker Images / build (worker, Worker.Dockerfile, ${{ github.repository_owner }}/worker) (push) Has been skipped
Deploy Docs to GitHub Pages / build (push) Failing after 12s
Mirror to Codeberg / Mirror (push) Failing after 0s
Deploy Docs to GitHub Pages / Deploy (push) Has been skipped
Nix Build / check (push) Failing after 32m28s
Refactor/federation
2025-04-09 02:18:14 +02:00
Jesse Wierzbinski 1d301d72ae
fix: 🚨 Fix DeepSource linter warnings 2025-04-09 02:15:00 +02:00
Jesse Wierzbinski 45e5460975
docs(federation): 📝 Update SDK documentation 2025-04-08 21:54:55 +02:00
Jesse Wierzbinski f79b0bc999
refactor(federation): 🔥 Refactor Note federation and creation code 2025-04-08 18:13:30 +02:00
Jesse Wierzbinski 54b2dfb78d
refactor(federation): 🔥 Remove confusing User federation methods 2025-04-08 17:27:08 +02:00
Jesse Wierzbinski 9ff9b90f6b
refactor(federation): ♻️ Refactor User federation code 2025-04-08 16:59:18 +02:00
Jesse Wierzbinski d638610361
refactor(federation): ♻️ Rewrite federation SDK 2025-04-08 16:01:10 +02:00
Jesse Wierzbinski ad1dc13a51
chore: ⬆️ Upgrade dependencies
Some checks failed
CodeQL Scan / Analyze (javascript-typescript) (push) Failing after 1m1s
Build Docker Images / lint (push) Successful in 38s
Build Docker Images / check (push) Successful in 51s
Build Docker Images / tests (push) Failing after 6s
Build Docker Images / build (server, Dockerfile, ${{ github.repository_owner }}/server) (push) Has been skipped
Build Docker Images / build (worker, Worker.Dockerfile, ${{ github.repository_owner }}/worker) (push) Has been skipped
Deploy Docs to GitHub Pages / build (push) Failing after 6s
Mirror to Codeberg / Mirror (push) Failing after 0s
Deploy Docs to GitHub Pages / Deploy (push) Has been skipped
Nix Build / check (push) Failing after 5s
2025-04-07 21:51:59 +02:00
Jesse Wierzbinski 2908fcc9e8
fix(worker): 🐛 Remove old bull-board patch, use official fix instead
Explicitely specifying the path prevents the module from using `eval`
2025-04-07 21:50:43 +02:00
Jesse Wierzbinski 512e0295a2
fix(config): 🐛 Fix bundling errors related to config
Some checks failed
CodeQL Scan / Analyze (javascript-typescript) (push) Failing after 52s
Build Docker Images / check (push) Failing after 5m20s
Build Docker Images / tests (push) Failing after 6s
Build Docker Images / build (server, Dockerfile, ${{ github.repository_owner }}/server) (push) Has been skipped
Build Docker Images / build (worker, Worker.Dockerfile, ${{ github.repository_owner }}/worker) (push) Has been skipped
Deploy Docs to GitHub Pages / build (push) Failing after 13s
Mirror to Codeberg / Mirror (push) Failing after 0s
Deploy Docs to GitHub Pages / Deploy (push) Has been skipped
Build Docker Images / lint (push) Successful in 26s
Nix Build / check (push) Failing after 32m35s
2025-04-06 22:11:18 +02:00
Jesse Wierzbinski 12740a2d06
feat(config): Allow specifying config path via env variable 2025-04-06 21:40:00 +02:00
Jesse Wierzbinski 838f2fd4cf
fix: 🐛 Fix cyclical imports causing crashes 2025-04-06 21:18:24 +02:00
Jesse Wierzbinski 52630e7042
chore: ⬆️ Upgrade dependencies 2025-04-06 20:58:00 +02:00
Jesse Wierzbinski 40b34e4855
fix: 🐛 Fix build error because of missing library
Some checks failed
CodeQL Scan / Analyze (javascript-typescript) (push) Failing after 5s
Build Docker Images / lint (push) Failing after 10s
Build Docker Images / check (push) Failing after 10s
Build Docker Images / tests (push) Failing after 6s
Build Docker Images / build (server, Dockerfile, ${{ github.repository_owner }}/server) (push) Has been skipped
Build Docker Images / build (worker, Worker.Dockerfile, ${{ github.repository_owner }}/worker) (push) Has been skipped
Deploy Docs to GitHub Pages / build (push) Failing after 4s
Mirror to Codeberg / Mirror (push) Failing after 0s
Deploy Docs to GitHub Pages / Deploy (push) Has been skipped
Nix Build / check (push) Failing after 5s
2025-04-01 21:07:56 +02:00
Jesse Wierzbinski 9840b5e10f
fix(config): 🐛 Expand contexts in which the config will autogenerate keys 2025-04-01 20:32:43 +02:00
Jesse Wierzbinski 14855b9dfe
fix: 🐛 Update example docker-compose.yml
Some checks failed
CodeQL Scan / Analyze (javascript-typescript) (push) Failing after 45s
Build Docker Images / lint (push) Successful in 28s
Build Docker Images / check (push) Successful in 50s
Build Docker Images / tests (push) Failing after 6s
Build Docker Images / build (server, Dockerfile, ${{ github.repository_owner }}/server) (push) Has been skipped
Build Docker Images / build (worker, Worker.Dockerfile, ${{ github.repository_owner }}/worker) (push) Has been skipped
Deploy Docs to GitHub Pages / build (push) Failing after 12s
Mirror to Codeberg / Mirror (push) Failing after 0s
Deploy Docs to GitHub Pages / Deploy (push) Has been skipped
Nix Build / check (push) Failing after 32m30s
2025-04-01 16:05:51 +02:00
Jesse Wierzbinski 844fbf7c9e
docs: 📝 Update installation documentation to match latest guidelines 2025-04-01 13:52:47 +02:00
Jesse Wierzbinski 7a6b93a36c
chore: ⬆️ Upgrade Bun to 1.2.8 2025-04-01 13:18:14 +02:00
Jesse Wierzbinski dc1ddb758d
fix(media): 🐛 Don't proxy media from trusted origins, use new ProxiedUrl class
Some checks failed
CodeQL Scan / Analyze (javascript-typescript) (push) Failing after 6s
Build Docker Images / lint (push) Failing after 10s
Build Docker Images / check (push) Failing after 11s
Build Docker Images / tests (push) Failing after 27s
Build Docker Images / build (server, Dockerfile, ${{ github.repository_owner }}/server) (push) Has been skipped
Build Docker Images / build (worker, Worker.Dockerfile, ${{ github.repository_owner }}/worker) (push) Has been skipped
Deploy Docs to GitHub Pages / build (push) Failing after 6s
Mirror to Codeberg / Mirror (push) Failing after 0s
Deploy Docs to GitHub Pages / Deploy (push) Has been skipped
Nix Build / check (push) Failing after 5s
2025-03-30 23:44:50 +02:00
Jesse Wierzbinski 411fcd8af5
refactor(api): ♻️ Reduce complexity of a few functions 2025-03-30 23:17:11 +02:00
Jesse Wierzbinski 25ea870f71
refactor: ♻️ Don't use Bun global 2025-03-30 23:06:34 +02:00
Jesse Wierzbinski d55668d529
fix(database): 💩 Replace uuid_generate_v7 in migrations to a dummy PostgreSQL function
Prevents a fatal error when running migrations on vanilla PostgreSQL instance without the pg_uuidv7 extension
2025-03-30 22:32:04 +02:00
Jesse Wierzbinski dde085464c
fix(database): 🐛 Remove some leftover parts of pg_uuidv7 2025-03-30 22:21:01 +02:00
Jesse Wierzbinski 9d79543951
ci: 👷 Use vanilla PostgreSQL 17 in CI tests 2025-03-30 22:12:40 +02:00
Jesse Wierzbinski 37f68bbffd
refactor(database): Remove dependency on pg_uuidv7 extension 2025-03-30 22:10:33 +02:00
Jesse Wierzbinski 2bb3731187
fix: 🐛 Correctly set youch to beta version 2025-03-30 21:45:51 +02:00
Jesse Wierzbinski ed06d0b54c
chore: ⬆️ Upgrade dependencies 2025-03-30 21:15:02 +02:00
Jesse Wierzbinski c68bfdf6e1
refactor(federation): ♻️ Simplify inbox processing by using ApiError 2025-03-30 21:13:47 +02:00
Jesse Wierzbinski 757c227f00
fix(federation): 🐛 Update user processing to not refetch user when its data is already available 2025-03-30 21:02:36 +02:00
Jesse Wierzbinski c9a1581932
feat(api): Implement duration controls on mutes 2025-03-30 20:54:47 +02:00
Jesse Wierzbinski 9d1d56bd08
feat(api): Implement indexing toggle and followers/following privacy settings 2025-03-30 20:32:42 +02:00
Jesse Wierzbinski 666eef063c
chore: 📝 Update changelog 2025-03-30 19:56:46 +02:00
Jesse Wierzbinski 1b983f9334
fix(api): 🐛 Fix routes using incorrect path parameter notation
Some checks failed
CodeQL Scan / Analyze (javascript-typescript) (push) Failing after 44s
Build Docker Images / lint (push) Successful in 29s
Build Docker Images / check (push) Failing after 5m42s
Build Docker Images / tests (push) Failing after 6s
Build Docker Images / build (server, Dockerfile, ${{ github.repository_owner }}/server) (push) Has been skipped
Build Docker Images / build (worker, Worker.Dockerfile, ${{ github.repository_owner }}/worker) (push) Has been skipped
Deploy Docs to GitHub Pages / build (push) Failing after 13s
Mirror to Codeberg / Mirror (push) Failing after 0s
Deploy Docs to GitHub Pages / Deploy (push) Has been skipped
Nix Build / check (push) Failing after 32m30s
2025-03-29 03:59:06 +01:00
Jesse Wierzbinski e5b7325379
fix: 🐛 Remove broken import from dependency 2025-03-29 03:39:55 +01:00
Jesse Wierzbinski 58342e86e1
refactor(api): ♻️ Move from @hono/zod-openapi to hono-openapi
hono-openapi is easier to work with and generates better OpenAPI definitions
2025-03-29 03:30:06 +01:00
Jesse Wierzbinski 0576aff972
chore: ⬆️ Upgrade dependencies
Some checks failed
CodeQL Scan / Analyze (javascript-typescript) (push) Failing after 46s
Build Docker Images / lint (push) Successful in 33s
Build Docker Images / check (push) Successful in 1m6s
Build Docker Images / tests (push) Failing after 6s
Build Docker Images / build (server, Dockerfile, ${{ github.repository_owner }}/server) (push) Has been skipped
Build Docker Images / build (worker, Worker.Dockerfile, ${{ github.repository_owner }}/worker) (push) Has been skipped
Deploy Docs to GitHub Pages / build (push) Failing after 12s
Mirror to Codeberg / Mirror (push) Failing after 0s
Deploy Docs to GitHub Pages / Deploy (push) Has been skipped
Nix Build / check (push) Failing after 32m37s
2025-03-28 22:26:20 +01:00
Jesse Wierzbinski cd4cfa6a70
fix(api): 🐛 Add tags to all API routes that were missing one 2025-03-28 22:12:07 +01:00
Jesse Wierzbinski d75254fc71
refactor(federation): 🚚 Change Like path from /objects/{id} to /likes/{id} 2025-03-28 22:06:42 +01:00
Jesse Wierzbinski 3d3e64edab
feat(api): Implement rate limiting
Some checks failed
CodeQL Scan / Analyze (javascript-typescript) (push) Failing after 42s
Build Docker Images / lint (push) Successful in 31s
Build Docker Images / check (push) Successful in 1m3s
Build Docker Images / tests (push) Failing after 6s
Build Docker Images / build (server, Dockerfile, ${{ github.repository_owner }}/server) (push) Has been skipped
Build Docker Images / build (worker, Worker.Dockerfile, ${{ github.repository_owner }}/worker) (push) Has been skipped
Deploy Docs to GitHub Pages / build (push) Failing after 13s
Mirror to Codeberg / Mirror (push) Failing after 0s
Deploy Docs to GitHub Pages / Deploy (push) Has been skipped
Nix Build / check (push) Failing after 33m18s
2025-03-27 20:12:00 +01:00
Jesse Wierzbinski 1993231663
feat(api): 🧑‍💻 Improve error quality with Youch 2025-03-27 19:08:38 +01:00
Jesse Wierzbinski 58b4d7454f
refactor(api): ♻️ Serve frontend from static files instead of proxying another process 2025-03-27 18:51:22 +01:00
Jesse Wierzbinski 5f8c57b3e1
chore: ⬆️ Upgrade Bun to 1.2.7 2025-03-27 14:41:43 +01:00
Jesse Wierzbinski ebb0f52f1e
chore: ⬆️ Upgrade dependencies 2025-03-27 14:16:22 +01:00
Jesse Wierzbinski c674a1309c
feat(api): Add OpenAPI visualizer
Some checks failed
CodeQL Scan / Analyze (javascript-typescript) (push) Failing after 53s
Build Docker Images / lint (push) Failing after 10s
Build Docker Images / check (push) Failing after 10s
Build Docker Images / tests (push) Failing after 6s
Build Docker Images / build (server, Dockerfile, ${{ github.repository_owner }}/server) (push) Has been skipped
Build Docker Images / build (worker, Worker.Dockerfile, ${{ github.repository_owner }}/worker) (push) Has been skipped
Deploy Docs to GitHub Pages / build (push) Failing after 5s
Mirror to Codeberg / Mirror (push) Failing after 0s
Deploy Docs to GitHub Pages / Deploy (push) Has been skipped
Nix Build / check (push) Failing after 5s
2025-03-24 15:25:40 +01:00
Jesse Wierzbinski 65e2e19ff1
refactor(api): ♻️ Properly reuse error messages and schemas 2025-03-24 14:42:09 +01:00
Jesse Wierzbinski 7112a66e4c
refactor: Refactor tests to not use module mocks, so bun test can be used
Some checks failed
CodeQL Scan / Analyze (javascript-typescript) (push) Failing after 45s
Build Docker Images / lint (push) Successful in 27s
Build Docker Images / check (push) Successful in 1m7s
Build Docker Images / tests (push) Failing after 6s
Build Docker Images / build (server, Dockerfile, ${{ github.repository_owner }}/server) (push) Has been skipped
Build Docker Images / build (worker, Worker.Dockerfile, ${{ github.repository_owner }}/worker) (push) Has been skipped
Deploy Docs to GitHub Pages / build (push) Failing after 12s
Mirror to Codeberg / Mirror (push) Failing after 0s
Deploy Docs to GitHub Pages / Deploy (push) Has been skipped
Nix Build / check (push) Failing after 32m31s
2025-03-23 04:12:28 +01:00
Jesse Wierzbinski ec506241f0
test(api): Remove old tests and introduce new, better ones
Some checks failed
CodeQL Scan / Analyze (javascript-typescript) (push) Failing after 6s
Build Docker Images / lint (push) Successful in 50s
Build Docker Images / check (push) Successful in 1m24s
Build Docker Images / tests (push) Failing after 8s
Build Docker Images / build (server, Dockerfile, ${{ github.repository_owner }}/server) (push) Has been skipped
Build Docker Images / build (worker, Worker.Dockerfile, ${{ github.repository_owner }}/worker) (push) Has been skipped
Deploy Docs to GitHub Pages / build (push) Failing after 15s
Mirror to Codeberg / Mirror (push) Failing after 0s
Deploy Docs to GitHub Pages / Deploy (push) Has been skipped
Nix Build / check (push) Failing after 33m5s
2025-03-23 03:34:17 +01:00
Jesse Wierzbinski f1ef85b314
fix: 🏷️ Remove unnecessary ts-expect-error
Some checks failed
CodeQL Scan / Analyze (javascript-typescript) (push) Failing after 5s
Build Docker Images / lint (push) Failing after 10s
Build Docker Images / check (push) Failing after 10s
Build Docker Images / tests (push) Failing after 6s
Build Docker Images / build (server, Dockerfile, ${{ github.repository_owner }}/server) (push) Has been skipped
Build Docker Images / build (worker, Worker.Dockerfile, ${{ github.repository_owner }}/worker) (push) Has been skipped
Deploy Docs to GitHub Pages / build (push) Failing after 5s
Mirror to Codeberg / Mirror (push) Failing after 1s
Deploy Docs to GitHub Pages / Deploy (push) Has been skipped
Nix Build / check (push) Failing after 5s
2025-03-22 18:17:53 +01:00
Jesse Wierzbinski 2a1a164d59
fix: 🐛 Recreate broken lockfile 2025-03-22 18:10:48 +01:00
Jesse Wierzbinski 8d1af1b0cd
refactor(api): 🔥 Remove old @versia/client version 2025-03-22 18:04:47 +01:00
Jesse Wierzbinski 54e282b03c
refactor(api): ♻️ Refactor all tests to use new client 2025-03-22 17:32:46 +01:00
Jesse Wierzbinski b6373dc185
fix: 🚨 Use ts-expect-error over ts-ignore
Some checks failed
CodeQL Scan / Analyze (javascript-typescript) (push) Failing after 45s
Build Docker Images / lint (push) Successful in 30s
Build Docker Images / check (push) Successful in 1m11s
Build Docker Images / tests (push) Failing after 6s
Build Docker Images / build (server, Dockerfile, ${{ github.repository_owner }}/server) (push) Has been skipped
Build Docker Images / build (worker, Worker.Dockerfile, ${{ github.repository_owner }}/worker) (push) Has been skipped
Deploy Docs to GitHub Pages / build (push) Failing after 5s
Mirror to Codeberg / Mirror (push) Failing after 1s
Deploy Docs to GitHub Pages / Deploy (push) Has been skipped
Nix Build / check (push) Failing after 5s
2025-03-22 04:06:37 +01:00
Jesse Wierzbinski 84b9fc3719
refactor(api): ♻️ Refactor test code to use new client 2025-03-22 04:04:06 +01:00
Jesse Wierzbinski 232ce83e4d
refactor(api): 🔥 Remove old ID lookup API 2025-03-22 03:34:59 +01:00
Jesse Wierzbinski dd38a3900c
chore: ⬆️ Upgrade dependencies
Some checks failed
CodeQL Scan / Analyze (javascript-typescript) (push) Failing after 58s
Build Docker Images / lint (push) Successful in 30s
Build Docker Images / check (push) Failing after 1m11s
Build Docker Images / tests (push) Failing after 6s
Build Docker Images / build (server, Dockerfile, ${{ github.repository_owner }}/server) (push) Has been skipped
Build Docker Images / build (worker, Worker.Dockerfile, ${{ github.repository_owner }}/worker) (push) Has been skipped
Deploy Docs to GitHub Pages / build (push) Failing after 16s
Mirror to Codeberg / Mirror (push) Failing after 0s
Deploy Docs to GitHub Pages / Deploy (push) Has been skipped
Nix Build / check (push) Failing after 33m10s
2025-03-22 02:38:01 +01:00
Jesse Wierzbinski c2d270e4e3
chore: ⬆️ Upgrade Bun to 1.2.5 2025-03-22 02:36:18 +01:00
Jesse Wierzbinski 3fe07a79b8
refactor(api): ♻️ Move all client schema code to new package 2025-03-22 02:34:03 +01:00
Jesse Wierzbinski 52602c3da7
chore: ⬆️ Upgrade dependencies
Some checks failed
CodeQL Scan / Analyze (javascript-typescript) (push) Failing after 56s
Build Docker Images / lint (push) Failing after 10s
Build Docker Images / check (push) Failing after 11s
Build Docker Images / tests (push) Failing after 6s
Build Docker Images / build (server, Dockerfile, ${{ github.repository_owner }}/server) (push) Has been skipped
Build Docker Images / build (worker, Worker.Dockerfile, ${{ github.repository_owner }}/worker) (push) Has been skipped
Deploy Docs to GitHub Pages / build (push) Failing after 5s
Mirror to Codeberg / Mirror (push) Failing after 1s
Deploy Docs to GitHub Pages / Deploy (push) Has been skipped
Nix Build / check (push) Failing after 5s
2025-03-16 17:01:07 +01:00
Jesse Wierzbinski 956a5fd2b3
chore: ⚰️ Remove unused dependencies
Some checks failed
CodeQL Scan / Analyze (javascript-typescript) (push) Failing after 5s
Build Docker Images / lint (push) Failing after 10s
Build Docker Images / check (push) Failing after 10s
Build Docker Images / tests (push) Failing after 6s
Build Docker Images / build (server, Dockerfile, ${{ github.repository_owner }}/server) (push) Has been skipped
Build Docker Images / build (worker, Worker.Dockerfile, ${{ github.repository_owner }}/worker) (push) Has been skipped
Deploy Docs to GitHub Pages / build (push) Failing after 5s
Mirror to Codeberg / Mirror (push) Failing after 0s
Deploy Docs to GitHub Pages / Deploy (push) Has been skipped
Nix Build / check (push) Failing after 5s
2025-02-26 00:37:54 +01:00
Jesse Wierzbinski 764061b4be
fix: 🔊 Automatically create logs folder if it doesn't exist 2025-02-26 00:28:05 +01:00
Gaspard Wierzbinski 457a4054b7
Merge pull request #35 from versia-pub/refactor/cli
Rewrite CLI
2025-02-26 00:14:47 +01:00
Jesse Wierzbinski ce64afe283
fix(cli): 🚨 Use RegExp literal instead of .match() 2025-02-26 00:12:31 +01:00
Jesse Wierzbinski f98d7ec560
fix: 📌 Recalculate lockfile 2025-02-26 00:09:22 +01:00
Jesse Wierzbinski 21b4f8a024
Merge branch 'main' into refactor/cli 2025-02-26 00:07:44 +01:00
Jesse Wierzbinski 5b756ea2dd
refactor(cli): ♻️ Rewrite CLI with Clerk. Removes a bunch of commands now covered by API. 2025-02-26 00:00:21 +01:00
Jesse Wierzbinski fc1877c6cc
chore: ⬆️ Upgrade Bun to 1.2.3
Some checks failed
CodeQL Scan / Analyze (javascript-typescript) (push) Failing after 58s
Build Docker Images / lint (push) Successful in 33s
Build Docker Images / check (push) Failing after 5m31s
Build Docker Images / tests (push) Failing after 8s
Build Docker Images / build (server, Dockerfile, ${{ github.repository_owner }}/server) (push) Has been skipped
Build Docker Images / build (worker, Worker.Dockerfile, ${{ github.repository_owner }}/worker) (push) Has been skipped
Deploy Docs to GitHub Pages / build (push) Failing after 17s
Mirror to Codeberg / Mirror (push) Failing after 0s
Deploy Docs to GitHub Pages / Deploy (push) Has been skipped
Nix Build / check (push) Failing after 32m49s
2025-02-25 23:33:22 +01:00
Jesse Wierzbinski f114f9a51a
chore: ⬆️ Upgrade dependencies 2025-02-25 23:32:05 +01:00
Jesse Wierzbinski 066220ffbd
feat: Add Copilot Instructions file 2025-02-25 23:18:39 +01:00
Jesse Wierzbinski e19a1b061a
chore(federation): ⬆️ Upgrade dependencies
Some checks failed
CodeQL Scan / Analyze (javascript-typescript) (push) Failing after 41s
Build Docker Images / lint (push) Successful in 31s
Build Docker Images / check (push) Successful in 1m1s
Build Docker Images / tests (push) Failing after 6s
Build Docker Images / build (server, Dockerfile, ${{ github.repository_owner }}/server) (push) Has been skipped
Build Docker Images / build (worker, Worker.Dockerfile, ${{ github.repository_owner }}/worker) (push) Has been skipped
Deploy Docs to GitHub Pages / build (push) Failing after 12s
Mirror to Codeberg / Mirror (push) Failing after 1s
Deploy Docs to GitHub Pages / Deploy (push) Has been skipped
Nix Build / check (push) Failing after 32m23s
2025-02-18 12:18:52 +01:00
Jesse Wierzbinski 28577d017a
docs: 📝 Update changelog
Some checks failed
CodeQL Scan / Analyze (javascript-typescript) (push) Failing after 5s
Build Docker Images / lint (push) Failing after 10s
Build Docker Images / check (push) Failing after 10s
Build Docker Images / tests (push) Failing after 6s
Build Docker Images / build (server, Dockerfile, ${{ github.repository_owner }}/server) (push) Has been skipped
Build Docker Images / build (worker, Worker.Dockerfile, ${{ github.repository_owner }}/worker) (push) Has been skipped
Deploy Docs to GitHub Pages / build (push) Failing after 5s
Mirror to Codeberg / Mirror (push) Failing after 0s
Deploy Docs to GitHub Pages / Deploy (push) Has been skipped
Nix Build / check (push) Failing after 4s
2025-02-18 00:59:55 +01:00
Jesse Wierzbinski 7fc7959712
chore: ⬆️ Upgrade dependencies 2025-02-17 23:33:12 +01:00
Jesse Wierzbinski 6622ee9020
refactor(federation): ♻️ Move Versia Note URIs to /notes, instead of /objects 2025-02-17 23:31:39 +01:00
Jesse Wierzbinski 4063d58d79
chore: ⬆️ Upgrade dependencies
Some checks failed
CodeQL Scan / Analyze (javascript-typescript) (push) Failing after 1m1s
Build Docker Images / lint (push) Failing after 10s
Build Docker Images / check (push) Failing after 11s
Build Docker Images / tests (push) Failing after 5s
Build Docker Images / build (server, Dockerfile, ${{ github.repository_owner }}/server) (push) Has been skipped
Build Docker Images / build (worker, Worker.Dockerfile, ${{ github.repository_owner }}/worker) (push) Has been skipped
Deploy Docs to GitHub Pages / build (push) Failing after 4s
Mirror to Codeberg / Mirror (push) Failing after 0s
Deploy Docs to GitHub Pages / Deploy (push) Has been skipped
Nix Build / check (push) Failing after 5s
2025-02-17 13:09:26 +01:00
Jesse Wierzbinski ed9ffe34f4
feat(federation): ⬆️ Upgrade to Versia 0.5 2025-02-17 13:07:43 +01:00
Jesse Wierzbinski e6c7e8a597
docs: 📝 Remove support for from-source installs
Some checks failed
CodeQL Scan / Analyze (javascript-typescript) (push) Failing after 5s
Build Docker Images / lint (push) Failing after 10s
Build Docker Images / check (push) Failing after 10s
Build Docker Images / tests (push) Failing after 6s
Build Docker Images / build (server, Dockerfile, ${{ github.repository_owner }}/server) (push) Has been skipped
Build Docker Images / build (worker, Worker.Dockerfile, ${{ github.repository_owner }}/worker) (push) Has been skipped
Deploy Docs to GitHub Pages / build (push) Failing after 5s
Deploy Docs to GitHub Pages / Deploy (push) Has been skipped
Mirror to Codeberg / Mirror (push) Failing after 0s
Nix Build / check (push) Failing after 5s
2025-02-15 18:49:31 +01:00
Jesse Wierzbinski e5b44cb946
docs: 💸 Add Fastly sponsorship note 2025-02-15 14:43:17 +01:00
Gaspard Wierzbinski 131fd1c6e9
Merge pull request #34 from versia-pub/refactor/config
Some checks failed
CodeQL Scan / Analyze (javascript-typescript) (push) Failing after 47s
Build Docker Images / lint (push) Successful in 30s
Build Docker Images / check (push) Successful in 1m1s
Build Docker Images / tests (push) Failing after 6s
Build Docker Images / build (server, Dockerfile, ${{ github.repository_owner }}/server) (push) Has been skipped
Build Docker Images / build (worker, Worker.Dockerfile, ${{ github.repository_owner }}/worker) (push) Has been skipped
Deploy Docs to GitHub Pages / build (push) Failing after 12s
Mirror to Codeberg / Mirror (push) Failing after 1s
Deploy Docs to GitHub Pages / Deploy (push) Has been skipped
Nix Build / check (push) Failing after 32m28s
Overhaul config system
2025-02-15 02:59:06 +01:00
Jesse Wierzbinski ef57198220
fix(config): 💚 Enable Challenges in CI tests 2025-02-15 02:54:22 +01:00
Jesse Wierzbinski 935ad72936
fix: 🚨 Throw new error instead of using process.exit() 2025-02-15 02:53:08 +01:00
Jesse Wierzbinski bf42f3d677
fix(config): 💚 Enable Sonic in the CI tests 2025-02-15 02:51:57 +01:00
Jesse Wierzbinski 045b7d6083
fix(config): 🐛 Update JSON schema for config 2025-02-15 02:48:39 +01:00
Jesse Wierzbinski 54fd81f076
refactor(config): ♻️ Redo config structure from scratch, simplify validation code, improve checks, add support for loading sensitive data from paths 2025-02-15 02:47:29 +01:00
Jesse Wierzbinski d4afd84019
refactor(media): 🐛 Use hono/proxy in media proxy
Some checks failed
CodeQL Scan / Analyze (javascript-typescript) (push) Failing after 38s
Build Docker Images / lint (push) Successful in 28s
Build Docker Images / check (push) Failing after 5m26s
Build Docker Images / tests (push) Failing after 6s
Build Docker Images / build (server, Dockerfile, ${{ github.repository_owner }}/server) (push) Has been skipped
Build Docker Images / build (worker, Worker.Dockerfile, ${{ github.repository_owner }}/worker) (push) Has been skipped
Deploy Docs to GitHub Pages / build (push) Failing after 14s
Mirror to Codeberg / Mirror (push) Failing after 0s
Deploy Docs to GitHub Pages / Deploy (push) Has been skipped
Nix Build / check (push) Failing after 32m28s
2025-02-14 18:16:07 +01:00
Jesse Wierzbinski 3fe9926fcf
chore: ⬆️ Upgrade dependencies 2025-02-14 18:09:15 +01:00
Gaspard Wierzbinski 416e3009a0
Merge pull request #33 from versia-pub/refactor/types
Overhaul OpenAPI schemas and validation
2025-02-14 18:04:41 +01:00
Gaspard Wierzbinski 276f82882f
Merge branch 'main' into refactor/types 2025-02-14 17:59:18 +01:00
Jesse Wierzbinski 59a3463c72
fix(api): 🚨 Use shorthand property syntax everywhere, remove useless template literals 2025-02-14 17:55:54 +01:00
Jesse Wierzbinski 6a810529bc
refactor(api): 🏷️ Finish OpenAPI documentation refactor 2025-02-14 17:49:34 +01:00
Jesse Wierzbinski 1856176de5
refactor(api): 🏷️ Port almost all remaining v1 endpoints to OpenAPI 2025-02-14 16:44:32 +01:00
Jesse Wierzbinski 247a8fbce3
refactor(api): 🏷️ Port more misc endpoints to use new schemas
Some checks failed
Mirror to Codeberg / Mirror (push) Failing after 0s
2025-02-13 02:34:44 +01:00
Jesse Wierzbinski e3e285571e
refactor(api): 🏷️ Port all /api/v1/accounts to use new schemas
Some checks failed
Mirror to Codeberg / Mirror (push) Failing after 0s
2025-02-13 01:31:15 +01:00
Jesse Wierzbinski a0ce18337a
refactor(api): 🏷️ Use more new schemas 2025-02-12 23:33:07 +01:00
Jesse Wierzbinski bff1c5f734
refactor(api): 🏷️ Begin porting all code over to new schemas 2025-02-12 23:25:22 +01:00
Jesse Wierzbinski fda1167234
feat(api): 🏷️ Finish porting full Mastodon API to OpenAPI 2025-02-12 23:04:44 +01:00
Jesse Wierzbinski 6ff27ede73
feat(cli): Add token generation command to CLI
Some checks failed
CodeQL Scan / Analyze (javascript-typescript) (push) Failing after 51s
Build Docker Images / lint (push) Successful in 28s
Build Docker Images / check (push) Successful in 54s
Build Docker Images / tests (push) Failing after 6s
Build Docker Images / build (server, Dockerfile, ${{ github.repository_owner }}/server) (push) Has been skipped
Build Docker Images / build (worker, Worker.Dockerfile, ${{ github.repository_owner }}/worker) (push) Has been skipped
Deploy Docs to GitHub Pages / build (push) Failing after 12s
Deploy Docs to GitHub Pages / Deploy (push) Has been skipped
Mirror to Codeberg / Mirror (push) Failing after 0s
Nix Build / check (push) Failing after 32m24s
2025-02-11 18:51:28 +01:00
Jesse Wierzbinski 03d3a2d3d4
feat(cli): Implement note recalculation command 2025-02-11 18:39:38 +01:00
Jesse Wierzbinski 264e2fe8ac
feat(api): 🏷️ Port Role and CustomEmoji OpenAPI schemas
Some checks failed
Mirror to Codeberg / Mirror (push) Failing after 1s
2025-02-11 18:22:39 +01:00
Jesse Wierzbinski e5f222c529
chore: Remove unused dependencies
Some checks failed
CodeQL Scan / Analyze (javascript-typescript) (push) Failing after 2m19s
Build Docker Images / lint (push) Successful in 51s
Build Docker Images / check (push) Successful in 1m9s
Build Docker Images / tests (push) Failing after 10s
Build Docker Images / build (server, Dockerfile, ${{ github.repository_owner }}/server) (push) Has been skipped
Build Docker Images / build (worker, Worker.Dockerfile, ${{ github.repository_owner }}/worker) (push) Has been skipped
Deploy Docs to GitHub Pages / build (push) Failing after 22s
Deploy Docs to GitHub Pages / Deploy (push) Has been skipped
Mirror to Codeberg / Mirror (push) Failing after 1s
Nix Build / check (push) Failing after 3m32s
2025-02-05 22:57:05 +01:00
Jesse Wierzbinski 546b7446b9
chore: ⬆️ Upgrade dependencies
Some checks failed
CodeQL Scan / Analyze (javascript-typescript) (push) Failing after 5m26s
Build Docker Images / lint (push) Successful in 50s
Build Docker Images / check (push) Successful in 1m13s
Build Docker Images / tests (push) Failing after 40s
Build Docker Images / build (server, Dockerfile, ${{ github.repository_owner }}/server) (push) Has been skipped
Build Docker Images / build (worker, Worker.Dockerfile, ${{ github.repository_owner }}/worker) (push) Has been skipped
Deploy Docs to GitHub Pages / build (push) Failing after 25s
Deploy Docs to GitHub Pages / Deploy (push) Has been skipped
Mirror to Codeberg / Mirror (push) Failing after 0s
Nix Build / check (push) Failing after 3m49s
2025-02-05 22:50:47 +01:00
Jesse Wierzbinski 7c622730dc
feat(api): 🏷️ Port Status OpenAPI schemas from Mastodon API docs 2025-02-05 22:49:07 +01:00
Jesse Wierzbinski 2aeada4904
feat(api): 🏷️ Port Account OpenAPI schemas from Mastodon API docs 2025-02-05 21:49:39 +01:00
Jesse Wierzbinski 76d1ccc859
refactor(api): ♻️ Use URL literal instead of strings 2025-02-01 16:32:18 +01:00
Jesse Wierzbinski 99fac323c8
chore: ⬆️ Upgrade Bun to 1.2.2 2025-02-01 11:10:57 +01:00
Jesse Wierzbinski ff7b11440d
chore: ⬆️ Upgrade dependencies 2025-02-01 11:07:36 +01:00
Gaspard Wierzbinski 450058213d
Merge pull request #32 from versia-pub/refactor/media
Refactor and simplify the media pipeline
2025-02-01 11:02:28 +01:00
Jesse Wierzbinski 1d2ea36fac
refactor: 🔥 Remove old pre Bun 1.2 compile error check
Bun 1.2 now default to actually throwing an error instead of always succeeding
2025-01-29 17:25:04 +01:00
Jesse Wierzbinski bf071c1b27
chore: 🔥 Remove old S3 client dependency 2025-01-29 17:23:32 +01:00
Jesse Wierzbinski 9ba6237f13
refactor(media): ♻️ Massively simplify media pipeline with Bun.S3 2025-01-29 17:21:40 +01:00
Jesse Wierzbinski f60663506a
fix(api): 🐛 Add missing attributes to /api/v1/instance 2025-01-29 16:05:04 +01:00
Jesse Wierzbinski 29cbe7d293
chore: ⬆️ Upgrade Bun to 1.2.1 2025-01-28 19:32:03 +01:00
Jesse Wierzbinski ba431e2b11
refactor(database): ♻️ Make user avatar and header into a Media instead of plaintext 2025-01-28 19:07:55 +01:00
Jesse Wierzbinski bc961b70bb
refactor(database): 🔥 Simplify media management code 2025-01-28 18:06:33 +01:00
Jesse Wierzbinski cf1104d762
refactor(database): ♻️ Make emojis use a Media instead of just rawdogging the URI 2025-01-28 17:43:43 +01:00
Jesse Wierzbinski c7aae24d42
style(database): 🚚 Reorder declarations of db tables
Putting relations next to the tables makes it easier to not break everything
2025-01-28 17:06:28 +01:00
Jesse Wierzbinski 8ac476fe66
chore: ⬆️ Upgrade dependencies 2025-01-28 16:55:43 +01:00
Jesse Wierzbinski 3216fc339a
refactor(database): ♻️ Move Note <-> Media relations to a many-to-many model instead of one-to-many 2025-01-23 20:36:09 +01:00
Jesse Wierzbinski 9c30dacda7
refactor(database): ♻️ Use ContentFormat to store media data 2025-01-23 19:37:17 +01:00
Jesse Wierzbinski 2f61cd8f0a
refactor(database): 🚚 Rename "Attachment" to "Media" 2025-01-23 16:08:42 +01:00
Jesse Wierzbinski bbd56b600d
refactor: 👷 Switch to Bun's text lockfile 2025-01-23 15:48:12 +01:00
Jesse Wierzbinski c4339e64bd
chore: ⬆️ Upgrade Bun to 1.2.0 2025-01-23 15:28:16 +01:00
Jesse Wierzbinski e32b6f9f8e
chore: ⬆️ Upgrade dependencies 2025-01-23 15:15:34 +01:00
Jesse Wierzbinski 88bb724ae0
chore: ⬆️ Upgrade dependencies 2025-01-17 14:18:31 +01:00
Jesse Wierzbinski 24efc77770
fix: 🚑 Put Sharp back into the API worker
The Attachment processor needs it for metadata
2025-01-07 15:16:51 +01:00
Jesse Wierzbinski 11ba1ab5c8
fix(api): 🐛 Fix failing build
The node_modules directory didn't exist, so cp threw an error
2025-01-07 14:10:54 +01:00
Jesse Wierzbinski b086e65404
refactor(worker): Move blurhash processing to worker 2025-01-06 19:45:32 +01:00
Jesse Wierzbinski 8188a6ffc7
refactor: 🔥 Remove sharp from api worker output 2025-01-06 19:31:42 +01:00
Jesse Wierzbinski ded8799a9c
fix: 🚑 Bundle Sharp into worker 2025-01-06 19:30:51 +01:00
Jesse Wierzbinski 80b874e5fb
refactor(api): Move media processing to background job 2025-01-06 19:21:57 +01:00
Jesse Wierzbinski dcdc8c7365
fix(api): 🐛 Fix user registration incorrectly counting remote users as local 2025-01-06 18:14:09 +01:00
Jesse Wierzbinski 0e9db83279
style: 🚨 Run Biome 2025-01-02 04:52:30 +01:00
Jesse Wierzbinski 3484b1e1a1
fix(api): 🐛 Improve notification text 2025-01-02 04:49:36 +01:00
Jesse Wierzbinski 1c543723fb
fix(api): 🐛 Use aesgcm, not aes128gcm during push notifications
Mastodon's server hates aes128gcm
2025-01-02 04:36:28 +01:00
Jesse Wierzbinski bedc25bacf
fix(api): 🐛 Properly await notification result 2025-01-02 04:27:52 +01:00
Jesse Wierzbinski cde2836982
fix(api): 👽 Ignore what the Mastodon docs say, they're wrong 2025-01-02 04:13:12 +01:00
Jesse Wierzbinski 5d64ecd04f
fix(api): 🐛 Switch base64 version to base64url in subscriptions 2025-01-02 04:02:29 +01:00
Jesse Wierzbinski ea0afdaf22
fix(api): 🐛 Make validation on push subscription more lax 2025-01-02 03:53:38 +01:00
Jesse Wierzbinski 59cf4e384a
fix(api): 🐛 Correctly calculate user based on token 2025-01-02 03:36:54 +01:00
Jesse Wierzbinski 8706c7b405
feat(federation): Add Push Queue to Bull Board 2025-01-02 03:27:26 +01:00
Jesse Wierzbinski 85de7b8ddc
ci: 🐛 Fix bug causing worker Docker image to be a copy of Server 2025-01-02 03:22:18 +01:00
Jesse Wierzbinski c58c8c6cc8
fix(api): 🐛 Correctly start push worker 2025-01-02 03:12:59 +01:00
Jesse Wierzbinski 7b3158c102
fix(api): 🚑 Fix incorrect builds
Everything under api/ should be a route, or it messes up bundling
2025-01-02 02:55:56 +01:00
Jesse Wierzbinski d839c274b1
feat(api): Finish push notification delivery 2025-01-02 02:45:40 +01:00
Jesse Wierzbinski d096ab830c
feat(api): Add initial Push Notifications support 2025-01-02 01:29:33 +01:00
Jesse Wierzbinski acd2bcb469
feat: 🧑‍💻 Add VSCode launch json 2025-01-01 23:42:14 +01:00
Jesse Wierzbinski 1137782f2a
ci: 🐛 Remove unnecessary permissions from tests 2024-12-31 17:38:13 +01:00
Jesse Wierzbinski 9d88fdbe53
ci: ♻️ Make tests, linting and checks pass before build is run 2024-12-31 17:35:27 +01:00
Jesse Wierzbinski deada6cbd9
ci: ♻️ Merge Worker & Server build into one CI file 2024-12-31 17:21:49 +01:00
Jesse Wierzbinski fbd352e23c
fix: 🚑 Correctly apply patches to bull-board 2024-12-31 17:16:16 +01:00
Jesse Wierzbinski 82da70bcac
refactor(api): ♻️ Group note/account fetching code in some routes 2024-12-30 21:30:10 +01:00
Jesse Wierzbinski 16f302c2dc
refactor(api): ♻️ Simplify route schema definitions 2024-12-30 20:26:56 +01:00
Jesse Wierzbinski 4926d6ff5d
refactor(api): 🔥 Remove all useless route metadata objects 2024-12-30 20:18:48 +01:00
Jesse Wierzbinski a9ea5eb672
chore: ⬆️ Upgrade TypeScript peer dependency to latest 2024-12-30 19:41:36 +01:00
Jesse Wierzbinski 09f30db83a
refactor(api): ♻️ Remove useless authorization checks 2024-12-30 19:38:41 +01:00
Jesse Wierzbinski dc12b269f5
refactor(api): ♻️ Improve authentication checker API 2024-12-30 19:18:31 +01:00
Jesse Wierzbinski 621dd7e9d9
refactor(api): ♻️ Upgrade zod-openapi to 0.18.3
Needed to add "as const" to all middleware handlers :)
2024-12-30 18:20:22 +01:00
Jesse Wierzbinski fbfd237f27
refactor(api): ♻️ Throw ApiError instead of returning error JSON 2024-12-30 18:00:23 +01:00
Jesse Wierzbinski c14621ee06
refactor(api): 🔥 Simplify oauth authorize handler 2024-12-30 16:47:48 +01:00
Jesse Wierzbinski 44d7264b79
refactor: 🔥 Remove deprecated ioredis type package 2024-12-30 16:20:47 +01:00
Jesse Wierzbinski a7b29d563e
fix(api): 🏷️ Use context.body for 204 responses 2024-12-30 16:18:28 +01:00
Jesse Wierzbinski 6af6bde12a
chore: ⬆️ Upgrade dependencies 2024-12-30 16:07:10 +01:00
Jesse Wierzbinski 8d2451cafc
chore: 🔖 Bump version to 0.8.0-alpha 2024-12-30 16:05:45 +01:00
Jesse Wierzbinski 20970a76fd
chore: ⬆️ Upgrade Bun to 1.1.42 2024-12-22 11:57:32 +01:00
Jesse Wierzbinski c621d9251e
chore: ⬆️ Upgrade dependencies 2024-12-22 11:56:52 +01:00
Jesse Wierzbinski 7268bd74f7
fix(api): ✏️ Remove extra attribute on NoteReaction
Was left there by mistake
2024-12-19 15:45:06 +01:00
Jesse Wierzbinski 98d63d85d4
docs(api): 📝 Document Reactions API 2024-12-19 15:41:56 +01:00
Jesse Wierzbinski 6f97f9f8f1
refactor(database): ♻️ Clean up database schema 2024-12-18 21:52:53 +01:00
Jesse Wierzbinski c334cd9cc8
chore: ⬆️ Upgrade Bun to 1.1.40 2024-12-18 20:46:26 +01:00
Jesse Wierzbinski 1509786090
chore: ⬆️ Upgrade dependencies 2024-12-18 20:42:40 +01:00
Jesse Wierzbinski f67fed12e0
feat(database): Add Reaction database class 2024-12-18 20:01:26 +01:00
Jesse Wierzbinski e00182cf54
feat(database): Add reactions table to database schema 2024-12-18 19:25:45 +01:00
Jesse Wierzbinski 4fdb96930f
fix(api): 🐛 Fetch media content-type from data, instead of doing naive guesses 2024-12-16 23:57:21 +01:00
Jesse Wierzbinski 6f67881d96
feat(api): Add ability to set URL as avatar or banner 2024-12-16 15:46:11 +01:00
Jesse Wierzbinski 41341cf252
docs: 📝 Improve README 2024-12-16 14:47:51 +01:00
Gaspard Wierzbinski 43b87dbfd3
docs: 📖 Add license for Versia assets 2024-12-15 15:09:01 +01:00
Jesse Wierzbinski e293bd280d
fix(api): 🐛 Fix duplicated mentions, general refactorings 2024-12-09 15:30:18 +01:00
Jesse Wierzbinski 84a0a07ea6
ci: 👷 Add the short commit SHA as a docker container tag 2024-12-09 15:08:32 +01:00
Jesse Wierzbinski 0ae9cfe26c
refactor(federation): ♻️ More federation logic cleanup 2024-12-09 15:01:19 +01:00
Jesse Wierzbinski 83399ba5f1
refactor(database): ♻️ Simplify User and Note logic further 2024-12-09 13:50:46 +01:00
Jesse Wierzbinski a8541bdc44
refactor(database): ♻️ Simplify Note and User federation logic 2024-12-09 13:36:15 +01:00
Jesse Wierzbinski cbbf49905b
fix(federation): 🐛 Fix remote emojis being incorrectly marked as local 2024-12-09 13:11:23 +01:00
Jesse Wierzbinski c94dd7c59d
fix(api): 🐛 Don't transform raw URLs as if they were attachments 2024-12-09 12:43:53 +01:00
Jesse Wierzbinski 8796f694bc
feat(api): 🚩 Add emoji shortcode size controls 2024-12-09 11:09:40 +01:00
Jesse Wierzbinski cfefd56a55
feat(api): 👽 Expose emoji limits in /api/v2/instance 2024-12-09 11:02:15 +01:00
Jesse Wierzbinski c8b909db08
chore: ⬆️ Upgrade Bun to 1.1.38 2024-12-09 10:57:24 +01:00
Jesse Wierzbinski 0708b3c45d
chore: ⬆️ Upgrade dependencies 2024-12-09 10:56:56 +01:00
Jesse Wierzbinski b14fa17e1a
feat(config): 🚩 Add emoji size/description size controls 2024-12-09 10:55:04 +01:00
Jesse Wierzbinski 5074ac788f
fix(api): 🐛 Force text content-type header on all empty responses
Fixes a problem where the content-type would default to application/json
2024-12-07 13:24:24 +01:00
Jesse Wierzbinski 06376cf58a
fix(api): 🐛 Correctly return empty body without content-type headers, when returning empty responses 2024-12-07 12:20:06 +01:00
Jesse Wierzbinski 2743528727
fix(api): 🐛 Fix emoji editing always making the emoji non-global 2024-12-07 11:12:17 +01:00
Jesse Wierzbinski 57e17e7607
fix(cli): 🏷️ Handle possible undefined values on some variables 2024-12-02 15:43:56 +01:00
Jesse Wierzbinski e4768620e2
fix(api): 🐛 Fix account lookup address parsing (again) 2024-12-02 15:40:20 +01:00
Jesse Wierzbinski 91da99c934
feat(federation): Handle instances not existing 2024-12-02 15:07:05 +01:00
Jesse Wierzbinski deee65ad6d
refactor(api): ♻️ Refactor user lookup endpoint 2024-12-02 15:00:37 +01:00
Jesse Wierzbinski ca42df1dfd
fix(api): 🐛 Properly include global field in API emojis 2024-11-29 21:49:41 +01:00
Jesse Wierzbinski 46933c1bef
fix(api): Fix tests expecting null instead of undefined in Roles API 2024-11-28 11:24:56 +01:00
Jesse Wierzbinski d1d7ca25a4
chore(api): ⬆️ Upgrade @versia/client to 0.1.1 2024-11-28 11:21:11 +01:00
Jesse Wierzbinski caa071d353
docs(api): 🐛 Fix incorrect Role API docs 2024-11-28 11:04:22 +01:00
Jesse Wierzbinski 594e8ca4e6
docs(api): 🐛 Add proper parameters to Roles API docs 2024-11-28 10:59:14 +01:00
Jesse Wierzbinski eb405d33cd
fix(api): 🐛 Don't use null in Role properties 2024-11-28 10:54:44 +01:00
Jesse Wierzbinski 8f339669b5
chore: ⬆️ Upgrade Bun to 1.1.37 2024-11-28 10:27:17 +01:00
Jesse Wierzbinski cd4b021aec
chore: ⬆️ Upgrade dependencies 2024-11-28 10:26:28 +01:00
Jesse Wierzbinski 4e38749ccb
docs(api): 📝 Update Roles API docs and changelog 2024-11-26 15:41:08 +01:00
Jesse Wierzbinski 49c53de99e
feat(api): Overhaul Role API, add ability to edit roles and assign/unassign them from any user 2024-11-26 15:27:39 +01:00
Jesse Wierzbinski 7431c1e21d
fix: 🏗️ Update file to patch's location in builder 2024-11-25 23:25:37 +01:00
Jesse Wierzbinski 49a301663a
feat(federation): Use instance messaging to send errors to remote instance 2024-11-25 23:14:42 +01:00
Jesse Wierzbinski a037448ebb
refactor(federation): ♻️ Remove Response return semantics from inbox worker 2024-11-25 23:11:17 +01:00
Jesse Wierzbinski 025d5bea94
docs: 📝 Restrict reference docker-compose permissions 2024-11-25 22:21:00 +01:00
Jesse Wierzbinski ece36f6adc
fix: 💚 Also include repo owner in worker image name 2024-11-25 21:58:41 +01:00
Jesse Wierzbinski 87bb0b6bcb
fix: 💚 Make worker CI build use correct image name 2024-11-25 21:56:57 +01:00
Jesse Wierzbinski 1b98381242
feat: Split off queue workers into a separate worker process 2024-11-25 21:54:31 +01:00
Jesse Wierzbinski 0b3e74107e
refactor(federation): ♻️ Make user inbox use the delayed processing 2024-11-25 21:17:52 +01:00
Jesse Wierzbinski a6574249df
docs: 📝 Update Changelog 2024-11-25 21:00:18 +01:00
Jesse Wierzbinski 55256e3568
refactor(config): 🚩 Remove enable flag on Redis queue config 2024-11-25 20:55:55 +01:00
Jesse Wierzbinski fb9a0feac8
fix: 💚 Add Redis to GitHub tester 2024-11-25 20:54:06 +01:00
Jesse Wierzbinski c899f12893
feat(federation): Prioritize delivery to instance inbox, and use delivery queue in more places 2024-11-25 20:50:55 +01:00
Jesse Wierzbinski 7a73a1a24e
feat(federation): Store remote instance shared inbox and extensions as well 2024-11-25 20:37:00 +01:00
Jesse Wierzbinski 5fc6c4dcfa
feat(federation): Implement queue for fetches 2024-11-25 20:29:59 +01:00
Jesse Wierzbinski 79cf43d752
refactor(api): 🛂 Increase JWT cookie lifetime to 2 weeks 2024-11-25 20:25:42 +01:00
Jesse Wierzbinski eb466a0cc7
feat(federation): Implement Shared Inboxes 2024-11-25 17:05:53 +01:00
Jesse Wierzbinski 756f67c0f3
feat(federation): Implement Instance Messaging Extension 2024-11-25 16:54:46 +01:00
Jesse Wierzbinski 4594c69808
docs: 📝 Update changelog 2024-11-25 14:27:34 +01:00
Jesse Wierzbinski 61b773ed11
feat(federation): Add config option to control automatic queue purge time 2024-11-25 13:53:14 +01:00
Jesse Wierzbinski 048dd6b0ab
fix: 🐛 Use CommonJS resolve instead of ESM one in Bull-Board UI 2024-11-25 13:37:58 +01:00
Jesse Wierzbinski fb84db3ea7
fix: 🐛 Correctly include bull-board UI package in dist 2024-11-25 13:24:14 +01:00
Jesse Wierzbinski ecc7d1eee7
feat(federation): Add UI to view BullMQ metadata 2024-11-25 13:09:28 +01:00
Jesse Wierzbinski 8a920218ea
feat(federation): Add queue to note delivery 2024-11-25 11:29:48 +01:00
Jesse Wierzbinski 3ef361f521
fix(federation): 🐛 Correctly remove listeners after job processing finishes 2024-11-25 08:59:48 +01:00
Jesse Wierzbinski 3e19b11609
refactor: 🔊 Fix duplicate logs 2024-11-24 23:13:29 +01:00
Jesse Wierzbinski 005a3a2721
fix(federation): 🚑 Don't always try to use instance key when an instance is not the request signer 2024-11-24 23:01:47 +01:00
Jesse Wierzbinski 34370a082a
refactor(federation): ♻️ Make Instance updateFromRemote non-static 2024-11-24 22:48:34 +01:00
Jesse Wierzbinski 8b23eb888d
refactor(cli): ♻️ Rewrite instance fetch command to refetch instances instead 2024-11-24 22:45:41 +01:00
Jesse Wierzbinski 50ebc12783
fix(federation): 🐛 Show error for inbox failures 2024-11-24 22:33:51 +01:00
Jesse Wierzbinski d527947182
fix(federation): 🐛 Correctly handle job failures in inboxes 2024-11-24 22:28:29 +01:00
Jesse Wierzbinski c59ebef851
feat(federation): Add more debugging to inbox processing 2024-11-24 22:17:45 +01:00
Jesse Wierzbinski be69407c01
refactor(federation): 🔊 Logging color tweaks 2024-11-24 22:10:23 +01:00
Jesse Wierzbinski 40e7903d90
feat(federation): 🔊 Add processing finished log 2024-11-24 22:06:32 +01:00
Jesse Wierzbinski b333ecc816
refactor(federation): 🔊 Add more logging to some federation logic 2024-11-24 22:01:14 +01:00
Jesse Wierzbinski ef0cca671a
feat(federation): Add Redis online check 2024-11-24 22:01:01 +01:00
Jesse Wierzbinski b320ddf3ae
refactor(federation): ♻️ Queue all incoming inbox processing events 2024-11-24 21:35:59 +01:00
Jesse Wierzbinski 26f1407efe
chore: 📝 Update changelog 2024-11-24 20:20:56 +01:00
Jesse Wierzbinski 8d968fa98c
chore: ⬆️ Upgrade dependencies 2024-11-24 17:54:42 +01:00
Jesse Wierzbinski 340ed7b258
fix(federation): 🐛 Correctly handle non-lowercase acct queries in account lookups 2024-11-24 17:42:30 +01:00
Jesse Wierzbinski 259fba17a7
fix(federation): 🐛 Make an empty allowed_ip list for bridge correctly allow any IP 2024-11-24 16:54:24 +01:00
Jesse Wierzbinski b55237cdc8
refactor(federation): ♻️ Allow ActivityPub bridge requests to omit all signature headers, including x-signed-by 2024-11-24 16:40:23 +01:00
Jesse Wierzbinski 80b5184d6a
test(api): 🐛 Fix S3 tests 2024-11-24 16:32:05 +01:00
Jesse Wierzbinski 59b069ce2c
fix(api): 🐛 Specify content-type when uploading to S3 2024-11-24 13:16:52 +01:00
Jesse Wierzbinski 6301121900
refactor(cli): 🔥 Removed unused variables 2024-11-24 00:48:41 +01:00
Jesse Wierzbinski 083b77bbb9
feat(cli): Add automatic setup script 2024-11-24 00:46:40 +01:00
Jesse Wierzbinski 36b25e0307
feat(cli): Add direct password option to CLI 2024-11-24 00:37:26 +01:00
Jesse Wierzbinski da369e604c
fix(api): 🐛 Fix lookup endpoints thinking local user is remote 2024-11-23 23:09:59 +01:00
Jesse Wierzbinski ace6921447
refactor(federation): ♻️ Correctly handle bridge requests and instance signatures in user inboxes 2024-11-23 23:02:18 +01:00
Jesse Wierzbinski afc5a74a40
fix: 🚑 Correctly use Musl version of Sharp in the production build 2024-11-23 14:35:04 +01:00
Jesse Wierzbinski 5b6924810e
chore: ⬆️ Upgrade Bun to 1.1.36 2024-11-23 14:27:26 +01:00
Jesse Wierzbinski fb9dbcdff0
chore: ⬆️ Upgrade dependencies 2024-11-23 14:26:58 +01:00
Jesse Wierzbinski 8444ff5741
fix(federation): 🐛 Use correct URL for bridge queries 2024-11-22 22:17:25 +01:00
Jesse Wierzbinski 217d3c286d
feat(api): Allow divs and spans in HTML 2024-11-22 19:12:52 +01:00
Jesse Wierzbinski fa0d48b88d
fix(api): 🐛 Use consistent user address matching patterns 2024-11-22 16:53:36 +01:00
Jesse Wierzbinski 569ba8bf2d
fix(api): 🔒 Correctly put all URIs in profiles through proxy 2024-11-22 15:06:46 +01:00
Jesse Wierzbinski bd1f09837b
fix(api): 🐛 Correctly handle underscores when parsing usernames 2024-11-22 14:51:11 +01:00
Jesse Wierzbinski bbfd26bb64
docs: 📝 Point to v0.7.0 installation info in docs instead of main branch 2024-11-21 20:34:21 +01:00
Jesse Wierzbinski 66c5c6e62d
fix(api): 🐛 Also validate other username characters in username changes 2024-11-21 09:31:37 +01:00
Jesse Wierzbinski 2fea17fdaa
fix(api): 🐛 Make uppercase usernames send errors during registration again 2024-11-21 09:26:03 +01:00
Jesse Wierzbinski a3b745358b
fix(api): 🐛 Automatically make all usernames lowercase 2024-11-21 09:23:25 +01:00
Jesse Wierzbinski 5dd8b872d9
chore: 📝 Update changelog for 0.7.0 release 2024-11-21 08:05:47 +01:00
Jesse Wierzbinski 9682cd0f99
fix(api): 🔒 Correctly check for note ownership when editing 2024-11-19 17:26:14 +01:00
Jesse Wierzbinski 653cf712ea
fix(api): 🚑 Correctly check visibility in timelines 2024-11-19 17:07:11 +01:00
Jesse Wierzbinski c20e6eb3b8
feat(federation): Add registration info to nodeinfo 2024-11-19 15:29:21 +01:00
Jesse Wierzbinski 055ee417cb
feat(federation): Implement user statistics and node data in nodeinfo 2024-11-19 15:24:15 +01:00
Jesse Wierzbinski 1837a6feb4
fix(federation): 🐛 Make nodeinfo correctly return JSON instead of redirect 2024-11-19 14:41:12 +01:00
Jesse Wierzbinski bfbaa7ce2c
fix(api): 🐛 Correctly sanitize checkbox inputs 2024-11-19 11:32:16 +01:00
Jesse Wierzbinski dc8a64355a
feat(api): Allow disabled checkbox inputs in rich text 2024-11-19 11:20:24 +01:00
Jesse Wierzbinski 32f71b3adf
fix(api): 🐛 Allow for forcing registrations via OpenID and disabling regular signups 2024-11-18 19:53:52 +01:00
Jesse Wierzbinski 8d2d9bd7fa
fix(config): 🚑 Use correct key in example config 2024-11-18 19:29:24 +01:00
Jesse Wierzbinski aac94e578f
chore: ⬆️ Upgrade dependencies 2024-11-18 13:46:06 +01:00
Jesse Wierzbinski d6fe6d2068
docs: Add favicon to docs 2024-11-10 15:41:00 +01:00
Jesse Wierzbinski bfa44e3f34
fix(api): 🐛 Fix for changed HTTP response code in Emoji API 2024-11-10 15:38:08 +01:00
Gaspard Wierzbinski b0645855ec
Merge pull request #30 from versia-pub/feat/vitepress-docs
Rewrite documentation to use VitePress
2024-11-10 15:35:02 +01:00
Jesse Wierzbinski 83f573c14f
refactor: 🚚 Point to new docs site everywhere 2024-11-10 15:33:21 +01:00
Jesse Wierzbinski cbcfe51362
feat: Enable clean URLs for docs 2024-11-10 15:29:43 +01:00
Jesse Wierzbinski 9796280a55
ci: 👷 Add automatic docs building and deployment 2024-11-10 15:28:27 +01:00
Jesse Wierzbinski 06a8dd1c0a
refactor: 📝 Move documentation to a custom VitePress site 2024-11-10 15:24:34 +01:00
Jesse Wierzbinski 19d8680289
feat(api): Add timeline benchmark 2024-11-10 13:08:43 +01:00
Jesse Wierzbinski 3ec5118771
refactor(plugin): ♻️ Move plugin loading to PluginLoader class 2024-11-10 13:08:26 +01:00
Jesse Wierzbinski 95b8eb6e20
chore: ⬆️ Upgrade dependencies 2024-11-07 13:24:11 +01:00
Jesse Wierzbinski b2405bd118
docs: 📝 Clarify wording in contribution guide 2024-11-07 13:15:58 +01:00
Jesse Wierzbinski 93ebeba368
Revert "refactor(database): ♻️ Correctly use @versia/kit imports everywhere"
This reverts commit 2f94884d37.
2024-11-04 15:20:53 +01:00
Jesse Wierzbinski 2f94884d37
refactor(database): ♻️ Correctly use @versia/kit imports everywhere 2024-11-04 15:06:23 +01:00
Jesse Wierzbinski 02c3c9d0bf
refactor: 🏷️ Move all types that represent ORM abstractions to ORM class static properties 2024-11-04 14:58:17 +01:00
Jesse Wierzbinski ca31830fb3
revert(api): 🔥 Use Notification's schema declaration instead of declaring it again every time 2024-11-04 14:35:27 +01:00
Jesse Wierzbinski 8765a45240
ci: 💚 Correctly name CI mirror workflow 2024-11-04 11:40:08 +01:00
Jesse Wierzbinski 2860323294
ci: 💚 Correctly name the mirror workflow 2024-11-04 11:38:02 +01:00
Jesse Wierzbinski 4552d3712b
ci: 💚 Inherit secrets in mirror workflow 2024-11-04 11:36:52 +01:00
Jesse Wierzbinski cd5ef61ce5
ci: 💚 Correctly add CI secret 2024-11-04 11:35:59 +01:00
Jesse Wierzbinski ad3a417b03
ci: 👷 Add Codeberg mirror CI 2024-11-04 11:29:26 +01:00
Jesse Wierzbinski e732a3df03
refactor(database): ♻️ Move Notifications to their own ORM abstractions 2024-11-04 10:43:30 +01:00
Jesse Wierzbinski 14ace17ad4
chore: ⬆️ Upgrade Bun to 1.1.34 2024-11-04 10:10:32 +01:00
Jesse Wierzbinski 9f7850a9b1
chore: ⬆️ Upgrade dependencies 2024-11-04 10:09:55 +01:00
Jesse Wierzbinski 845041e4db
refactor(database): ♻️ Move Token to its own ORM abstraction, optimize familiar_followers route 2024-11-03 17:45:21 +01:00
Jesse Wierzbinski 962c159ddd
chore: ⬆️ Upgrade dependencies 2024-11-02 00:46:24 +01:00
Jesse Wierzbinski 2eb0509fd3
refactor: 🚨 Turn on a few more linter rules 2024-11-02 00:45:48 +01:00
Jesse Wierzbinski c1dcdc78ae
refactor: ♻️ Always use explicit types in every function 2024-11-02 00:43:33 +01:00
Jesse Wierzbinski 54cea29ce9
refactor: 🚨 Always explicitely state member accessibility 2024-11-01 21:20:12 +01:00
Jesse Wierzbinski 7a73b8db91
refactor(database): 🚚 Only import ORM table data from @versia/kit 2024-11-01 21:05:54 +01:00
Jesse Wierzbinski 2f8b85a299
refactor(database): 🚚 Only import ORM abstractions from @versia/kit 2024-11-01 20:57:16 +01:00
Jesse Wierzbinski f26493140f
refactor(federation): ♻️ Move incoming federation handling to custom class 2024-11-01 20:42:32 +01:00
Jesse Wierzbinski d570e8c200
chore: ⬆️ Upgrade dependencies 2024-11-01 00:27:47 +01:00
Jesse Wierzbinski 1298b3732e
fix(api): 🐛 Fix false values not correctly falling back to generic mime type 2024-10-31 23:19:19 +01:00
Jesse Wierzbinski d06301ed72
refactor(federation): ♻️ Refactor user inbox API to reduce complexity 2024-10-28 13:13:50 +01:00
Jesse Wierzbinski 7638a094f4
refactor(api): 🔥 Remove unused function 2024-10-28 12:31:46 +01:00
Jesse Wierzbinski 074d0e3dcc
chore: ⬆️ Upgrade dependencies 2024-10-26 15:05:45 +02:00
Jesse Wierzbinski 64b263a1c1
fix(federation): 🐛 Update old version of federation SDK 2024-10-24 19:18:21 +02:00
Jesse Wierzbinski 0a31b7a8f6
feat(federation): Implement inbound federation of likes and like deletion 2024-10-24 19:08:28 +02:00
Jesse Wierzbinski df84572148
fix(api): 🐛 Fix missing FormData acceptance for registration route 2024-10-24 18:48:11 +02:00
Jesse Wierzbinski 3b704b4c8c
fix(plugin): 🐛 Fix misleading error message related to plugin initialization 2024-10-24 18:41:11 +02:00
Jesse Wierzbinski 11bb0a6f49
feat(cli): Add generate-keys CLI command 2024-10-24 18:18:39 +02:00
Jesse Wierzbinski 33f16bb9b1
docs: 📝 Update installation docs 2024-10-24 18:00:26 +02:00
Jesse Wierzbinski f494f76f82
feat(federation): Federate likes and unlikes 2024-10-24 17:31:39 +02:00
Jesse Wierzbinski 5a26bdf2f8
refactor(database): 🚚 Move Likes to our custom ORM 2024-10-24 17:20:00 +02:00
Jesse Wierzbinski e52e230ce3
refactor(database): 🚚 Move database ORM code to classes/database
The old directory, packages/database-interface, was confusingly named so it was better to move it here
2024-10-24 16:28:38 +02:00
Jesse Wierzbinski 120ba0fb81
chore: ⬆️ Upgrade Bun to 1.1.33 2024-10-24 16:21:53 +02:00
Jesse Wierzbinski 807aa986b0
chore: ⬆️ Upgrade Bun to 1.1.32 2024-10-23 18:02:32 +02:00
Jesse Wierzbinski 6338f711ad
chore: ⬆️ Upgrade dependencies 2024-10-23 18:01:40 +02:00
Jesse Wierzbinski 9e96eca032
refactor(database): ♻️ Move Applications to our custom ORM 2024-10-23 17:56:47 +02:00
Jesse Wierzbinski e8827bccfa
chore: ⬆️ Upgrade dependencies 2024-10-14 18:08:23 +02:00
Jesse Wierzbinski d000914f61
fix(plugin): 🐛 Don't incorrectly call errorSearchParams before initialization in callback 2024-10-11 17:23:51 +02:00
Jesse Wierzbinski a265e9df41
fix(plugin): 🐛 Add missing plugin middleware to some OIDC plugin routes 2024-10-11 17:16:03 +02:00
Jesse Wierzbinski d2dcdce763
fix(api): 🐛 Fix incorrect order of function parameters 2024-10-11 17:09:51 +02:00
Jesse Wierzbinski d84ae38573
fix(api): 🐛 Fix missing nullish coalescing 2024-10-11 17:07:17 +02:00
Jesse Wierzbinski a1aa49e089
ci(config): 🔥 Remove old oidc key from CI config 2024-10-11 17:04:03 +02:00
Jesse Wierzbinski 9f1e89b592
refactor(config): 🔥 Remove old oidc section in config 2024-10-11 17:03:33 +02:00
Jesse Wierzbinski ce781f3336
refactor(database): ♻️ Use new Drizzle count API 2024-10-11 15:46:05 +02:00
Jesse Wierzbinski 7f17074d16
chore: ⬆️ Upgrade dependencies 2024-10-11 15:40:54 +02:00
Jesse Wierzbinski 7cdbb8ba6f
chore: ⬆️ Upgrade Bun to 1.1.30 2024-10-11 15:20:46 +02:00
Jesse Wierzbinski 04651746bb
refactor(plugin): 🚚 Move SSO login callback route to OpenID plugin 2024-10-11 15:15:06 +02:00
Jesse Wierzbinski 777a39faf5
refactor(plugin): 🚚 Move SSO login route to OpenID plugin 2024-10-11 14:39:25 +02:00
Jesse Wierzbinski 6cf97e5dd7
chore: ⬆️ Upgrade dependencies 2024-10-07 12:59:54 +02:00
Jesse Wierzbinski 0557d52afe
refactor(plugin): 🚚 Move JWKS well-known endpoint to OpenID plugin 2024-10-07 12:52:22 +02:00
Jesse Wierzbinski 2e827814de
ci(config): 🐛 Fix CI config to pass new config checks 2024-10-06 16:03:40 +02:00
Jesse Wierzbinski 33b375f3ae
chore: 📝 Update changelog 2024-10-06 15:56:28 +02:00
Jesse Wierzbinski f26ab0f0e6
feat(plugin): Add override settings to plugin loading 2024-10-06 15:55:15 +02:00
Jesse Wierzbinski c0805ff125
fix(config): 🐛 Make some default config values more sensible 2024-10-04 18:36:32 +02:00
Jesse Wierzbinski f9dcbb1be8
refactor: 🚨 Enable noUndeclaredDependencies for Biome 2024-10-04 15:38:02 +02:00
Jesse Wierzbinski 728ccc9002
chore: ⬆️ Upgrade dependencies 2024-10-04 15:35:43 +02:00
Jesse Wierzbinski df29091c44
refactor: 🔥 Remove package version pinning from Dockerfile 2024-10-04 15:31:46 +02:00
Jesse Wierzbinski c4ff5aa2fb
fix: 💚 Add missing symbols 2024-10-04 15:30:05 +02:00
Jesse Wierzbinski d61e366a29
ci: 📌 Set libstc++ version to ^13.0.0 2024-10-04 15:28:36 +02:00
Jesse Wierzbinski 40f9b46392
fix: 💚 Fix incorrect Dockerfile syntax 2024-10-04 15:25:54 +02:00
Jesse Wierzbinski b53307c824
refactor: 🚚 Explicitely add extensions to all imports 2024-10-04 15:22:48 +02:00
Jesse Wierzbinski b5b7014c00
refactor: 🚨 Add empty default case to OpenID grant_type handler 2024-10-03 19:06:24 +02:00
Jesse Wierzbinski 2537e3cd48
refactor: 🚨 Make more class methods static 2024-10-03 19:02:13 +02:00
Jesse Wierzbinski 5ec19f037a
refactor: 🚨 Remove unnecessary function overloads 2024-10-03 13:54:09 +02:00
Jesse Wierzbinski 835cdc3f18
refactor: 🚨 Make class methods that don't use this static 2024-10-03 13:51:19 +02:00
Jesse Wierzbinski 53688095cc
refactor: 🚨 Don't use wildcard imports 2024-10-03 13:44:55 +02:00
Jesse Wierzbinski bec3e4ea70
refactor: 🚨 Consolidate consecutive RUN calls 2024-10-03 13:43:19 +02:00
Jesse Wierzbinski 3fade63567
refactor: 🚨 Use shortand property syntax for object literals 2024-10-03 13:41:58 +02:00
Jesse Wierzbinski 48ffe97849
refactor: 🚨 Pin all package versions in Docker images 2024-10-03 13:30:49 +02:00
Jesse Wierzbinski 360ec4817c
fix(api): 🚨 Correct duplicate assignments 2024-10-03 13:26:53 +02:00
Jesse Wierzbinski 8da9567ca2
refactor(api): 🚨 Don't export a mutable value 2024-10-03 13:26:00 +02:00
Jesse Wierzbinski 076e930369
refactor: 🚨 Remove process.exit usage 2024-10-03 11:59:26 +02:00
Jesse Wierzbinski b1d8595a7c
refactor: 🚨 Remove unnecessary async keywords 2024-10-03 11:43:16 +02:00
Jesse Wierzbinski 132bec4d5b
fix(api): 🐛 Fix incorrect ?? placement
This would not set a default value of 20
2024-10-03 10:31:57 +02:00
Jesse Wierzbinski 5ed3f04d48
refactor: 🚨 Simplify boolean return 2024-10-03 10:30:22 +02:00
Jesse Wierzbinski a4aafc202c
refactor(cli): 🔥 Remove useless bin files in CLI 2024-10-03 10:29:25 +02:00
Jesse Wierzbinski 5e1ec8778c
fix: 🚨 Correct useless template literal 2024-10-03 10:27:41 +02:00
Jesse Wierzbinski 06315e8a81
fix: 🚨 Replace ts-ignore with ts-expect-error 2024-10-03 10:26:58 +02:00
Jesse Wierzbinski f523e5d355
feat: Add Deepsource config file 2024-10-03 10:24:39 +02:00
Jesse Wierzbinski 3879763971
refactor(plugin): ♻️ Add more exports to @versia/kit for database behaviour 2024-09-30 14:34:43 +02:00
Jesse Wierzbinski 23300ae93e
chore: ⬆️ Upgrade dependencies 2024-09-30 13:53:14 +02:00
Jesse Wierzbinski 3f3cf8ec39
perf: 🔥 Remove useless @hono/zod-validator dependency (replaced by @hono/zod-openapi) 2024-09-30 13:50:25 +02:00
Jesse Wierzbinski 1e84fa6e41
docs: 📝 Update changelog and README 2024-09-30 13:49:04 +02:00
Jesse Wierzbinski 19213ec29e
refactor(api): ♻️ Move token endpoint to OpenID plugin, add revoke endpoint 2024-09-30 13:42:12 +02:00
Jesse Wierzbinski 2254c3d39c
refactor(api): 🔥 Remove useless allowedMethods from route meta info 2024-09-27 13:08:47 +02:00
Jesse Wierzbinski b040c88445
refactor(api): ♻️ Finish first pass of OpenAPI refactor 2024-09-27 13:00:12 +02:00
Jesse Wierzbinski 5e80122e81
chore: ⬆️ Upgrade dependencies 2024-09-25 12:36:19 +02:00
Jesse Wierzbinski 74ec563ba5
refactor(api): ♻️ Move all SSO account linking endpoint logic to OpenID plugin 2024-09-25 12:31:35 +02:00
Jesse Wierzbinski 6d4b4eb13b
fix(api): 🐛 Fix incorrect test case 2024-09-24 17:03:27 +02:00
Jesse Wierzbinski 96d1805925
refactor(api): ♻️ Move /api/v1/sso to OpenID plugin 2024-09-24 14:42:39 +02:00
Jesse Wierzbinski c7ec678a3e
fix: 💚 Run every test file separately instead of using the global bun test command 2024-09-23 13:20:30 +02:00
Jesse Wierzbinski de8b8e2cc0
ci: 💚 Add debug for CI 2024-09-23 13:06:22 +02:00
Jesse Wierzbinski c7ae7f3042
refactor: 🔥 Remove superflous logger call 2024-09-23 12:03:10 +02:00
Jesse Wierzbinski 08ce64e9b9
fix: 🔊 Fix logging code to not run in tests 2024-09-23 12:01:02 +02:00
Jesse Wierzbinski c993b7207e
fix(config): 💚 Fix incorrect CI config 2024-09-23 11:56:18 +02:00
Jesse Wierzbinski c7221ae9d1
refactor(plugin): ♻️ Remove mandatory manifest inside Plugin constructor 2024-09-23 11:54:42 +02:00
Jesse Wierzbinski d224d7b9b8
feat(plugin): Add dynamic plugin and manifest loader 2024-09-23 11:51:15 +02:00
Jesse Wierzbinski f623f2c1a0
refactor(plugin): ♻️ Move plugin manifests to json file, add JSON schema 2024-09-23 10:34:14 +02:00
Jesse Wierzbinski 3bcb7225bf
chore: ⬆️ Upgrade Bun to 1.1.29 2024-09-23 10:02:30 +02:00
Jesse Wierzbinski ea248c96c4
chore: ⬆️ Upgrade dependencies 2024-09-23 10:01:40 +02:00
Jesse Wierzbinski 24172b5138
fix: 🚑 Patch federation library to work around a bug in Bun's bundling
Fixes build failures
2024-09-23 10:00:06 +02:00
Jesse Wierzbinski 5aa1c4e625
refactor(api): ♻️ More OpenAPI refactoring work 2024-09-16 15:29:09 +02:00
Jesse Wierzbinski 6d9e385a04
chore: ⬆️ Upgrade dependencies 2024-09-16 12:34:33 +02:00
Jesse Wierzbinski 9e3311e29f
refactor(api): ♻️ Refactor roles, SSO and timelines to new OpenAPI route format 2024-09-16 12:30:05 +02:00
Jesse Wierzbinski 739bbe935b
refactor(api): ♻️ More OpenAPI refactoring 2024-09-15 14:59:21 +02:00
Jesse Wierzbinski b755fc5d62
refactor(api): ♻️ Move more API routes to new OpenAPI format 2024-09-15 14:28:47 +02:00
Jesse Wierzbinski 166d1c59a5
refactor: 🔥 Remove some code already provided by LogTape 2024-09-15 13:47:26 +02:00
Jesse Wierzbinski 12f7fa4047
fix(api): 🐛 Remove useless null check 2024-09-14 17:34:12 +02:00
Jesse Wierzbinski ad2d47d174
chore: ⬆️ Upgrade Bun to 1.1.27 2024-09-14 17:33:02 +02:00
Jesse Wierzbinski 2e41bfeee4
chore: ⬆️ Upgrade dependencies 2024-09-14 17:32:32 +02:00
Jesse Wierzbinski a05a0b313f
fix(api): 🐛 Fix logging causing crashes when parsing FormData 2024-09-14 17:30:02 +02:00
Jesse Wierzbinski cf149b737a
chore: ⬆️ Upgrade dependencies 2024-09-05 15:16:08 +02:00
Jesse Wierzbinski d335965b2e
chore: 📝 Update changelog 2024-09-04 23:40:22 +02:00
Jesse Wierzbinski d63196b5ee
fix(api): 🐛 Only decode URI, not full URI component, in application's redirect_url 2024-09-04 23:31:58 +02:00
Jesse Wierzbinski 53184bbe99
fix: 💚 Make CI config valid again 2024-09-04 23:22:48 +02:00
Jesse Wierzbinski bfd4c7884e
fix(api): 🐛 Also encode OAuth authorize endpoint response 2024-09-04 23:21:52 +02:00
Jesse Wierzbinski ac906acbe2
fix(api): 🐛 Encode redirect URI 2024-09-04 23:18:08 +02:00
Jesse Wierzbinski e68832683f
fix(api): 🐛 Correctly use Hono primitives in OpenID redirect 2024-09-04 23:15:33 +02:00
Jesse Wierzbinski 7f8ade5fc1
fix(api): 🐛 Correctly decode URI component when obtaining token.
Prevents redirect_uri mismatch by normalizing URL encoding
2024-09-04 23:11:16 +02:00
Jesse Wierzbinski 9dc143060f
refactor: 🔊 Don't use debugRequest for logging middleware (doesn't output a body) 2024-09-04 23:08:11 +02:00
Jesse Wierzbinski 128a21cd47
fix: 💚 Fix incorrect CI config 2024-09-04 23:04:07 +02:00
Jesse Wierzbinski 45c131dfed
fix(api): 🐛 Don't clone body twice 2024-09-04 22:59:39 +02:00
Jesse Wierzbinski 5d2aa82247
feat(api): Add response logging 2024-09-04 22:52:43 +02:00
Jesse Wierzbinski b5411c01e4
fix: ✏️ Fix typos 2024-09-04 21:55:23 +02:00
Jesse Wierzbinski 6c56b582b3
chore: ⬆️ Upgrade Bun to 1.1.26 2024-09-04 21:51:53 +02:00
Jesse Wierzbinski c0fafcdfda
chore: ⬆️ Upgrade dependencies 2024-09-04 21:44:49 +02:00
Jesse Wierzbinski d51bae52c6
refactor(plugin): ♻️ Move parts of OpenID logic to plugin 2024-08-29 20:32:04 +02:00
Jesse Wierzbinski 69d7d50239
refactor(api): ♻️ Remove old redirect() and response() in favour of Hono's builtins 2024-08-28 17:01:56 +02:00
Jesse Wierzbinski 691716f7eb
chore: 🔥 Move special GitHub files to another repository 2024-08-28 03:28:03 +02:00
Jesse Wierzbinski 878abd1c77
chore: ⬆️ Upgrade dependencies 2024-08-28 00:28:35 +02:00
Jesse Wierzbinski 5f090c3259
chore: ♻️ Use new branding 2024-08-28 00:06:49 +02:00
Jesse Wierzbinski f9023893af
refactor: 🚚 Point everything to the new GitHub org 2024-08-27 21:40:42 +02:00
Jesse Wierzbinski 47c666894c
refactor: ♻️ Refactor tests to use a simpler syntax 2024-08-27 21:25:26 +02:00
Jesse Wierzbinski 6ed1bd747f
refactor(api): ♻️ Refactor more routes to use OpenAPI 2024-08-27 20:14:10 +02:00
Jesse Wierzbinski 5554038f44
style: 🚨 Run Biome 2024-08-27 18:56:20 +02:00
Jesse Wierzbinski bcbc9e6bf1
refactor(api): ♻️ Refactor more routes into OpenAPI-compatible formats 2024-08-27 18:55:02 +02:00
Jesse Wierzbinski 02cb8bcd4f
feat(api): Add Swagger UI and OpenAPI endpoint 2024-08-27 18:09:15 +02:00
Jesse Wierzbinski f03542b37e
fix(api): 🚑 Make server start again when NUM_CPUS is undefined 2024-08-27 18:00:39 +02:00
Jesse Wierzbinski b0b750c05d
refactor(api): ♻️ Convery more routes to use OpenAPI 2024-08-27 17:40:58 +02:00
Jesse Wierzbinski 1ab1c68d36
refactor(api): 🚚 Refactor authentication middleware and implement some OpenAPI routes 2024-08-27 17:20:36 +02:00
Jesse Wierzbinski edf5edca9f
refactor(api): 🔥 Remove old mastodon-compatible login endpoints 2024-08-27 16:47:58 +02:00
Jesse Wierzbinski 184dae75ba
chore: 📝 Update Changelog 2024-08-27 16:46:10 +02:00
Jesse Wierzbinski bec60fbf96
refactor(api): 🔥 Remove Glitch-FE explicit support 2024-08-27 16:45:05 +02:00
Jesse Wierzbinski df466ecaa0
refactor(api): ♻️ Use OpenAPIHono instead of Hono in preparation for future changes 2024-08-27 16:40:11 +02:00
Jesse Wierzbinski 3c1b330d4b
refactor(api): 🚚 Use api/ for API routes instead of server/api/ 2024-08-27 16:37:23 +02:00
Jesse Wierzbinski dfc0bf4595
chore: ⬆️ Upgrade dependencies 2024-08-27 16:01:10 +02:00
Jesse Wierzbinski cea0544686
fix(federation): 🏷️ Correctly make InstanceMetadata description a string 2024-08-27 15:51:41 +02:00
Jesse Wierzbinski fbb845f7f8
refactor(federation): 🚚 Move old function to User 2024-08-27 15:50:14 +02:00
Jesse Wierzbinski 3b2c0d3b5a
chore(federation): ⬆️ Upgrade dependencies 2024-08-27 02:40:09 +02:00
Jesse Wierzbinski 4bf3c44959
fix(federation): 🐛 Change incorrect X-Date to X-Nonce 2024-08-27 02:26:00 +02:00
Jesse Wierzbinski 9cd53ce58a
fix(federation): 🐛 Correctly parse instance hostname (not a URL) 2024-08-27 02:21:09 +02:00
Jesse Wierzbinski df5e06ca8a
fix(federation): 🐛 Make HTTP header validation lowercase 2024-08-27 02:17:07 +02:00
Jesse Wierzbinski 9a917e2801
refactor(federation): 🔥 Remove 0.3.1 from list of supported versions 2024-08-27 01:59:39 +02:00
Jesse Wierzbinski 60ca66395c
fix(cli): 🐛 Fix incorrect path after build 2024-08-27 01:52:29 +02:00
Jesse Wierzbinski 0da6d508f3
fix: 🐛 Add correct Nix output hash 2024-08-26 20:23:47 +02:00
Jesse Wierzbinski 0ac540132a
chore: 💚 Update Nix hashes 2024-08-26 19:53:43 +02:00
Jesse Wierzbinski fbe86043b7
refactor(api): ♻️ Replace old client library with new version (@versia/client) 2024-08-26 19:40:15 +02:00
Jesse Wierzbinski 7708bff31f
chore(federation): Remove old federation SDK 2024-08-26 19:34:54 +02:00
Jesse Wierzbinski 334c429bfa
fix(federation): 🐛 Correctly validate outbound Collections 2024-08-26 19:34:21 +02:00
Jesse Wierzbinski 42e198ca0e
chore(federation): 👽 Finish initial Versia Working Draft 4 update 2024-08-26 19:27:40 +02:00
Jesse Wierzbinski c3fa867e74
chore(federation): 👽 Initial Versia Working Draft 4.0 support 2024-08-26 19:06:49 +02:00
Jesse Wierzbinski 9c71c3fe51
chore: ⬆️ Upgrade dependencies 2024-08-26 18:15:14 +02:00
Jesse Wierzbinski bc0943c569
feat(database): Implement read replicas for database 2024-08-26 18:04:22 +02:00
Jesse Wierzbinski c75306c58b
chore: 🚚 Rename Nix package to use new site 2024-08-26 17:45:14 +02:00
Gaspard Wierzbinski 5c817fdb57
Merge pull request #27 from snaakey/nix
ci: Add nix workflow
2024-08-26 13:52:06 +02:00
emily 082df183d3
ci: Add nix workflow 2024-08-25 22:36:53 +02:00
Gaspard Wierzbinski a7e8b2d405
Merge pull request #26 from snaakey/nix
feat: nix flake overlay
2024-08-25 17:57:55 +02:00
emily 9aad2d0b27
feat: nix flake overlay 2024-08-25 17:52:04 +02:00
Gaspard Wierzbinski a3817564f7
Merge pull request #25 from snaakey/nix
fix nix package and add nix binary cache
2024-08-25 13:11:24 +02:00
emily a88af8cb18
feat: Add nix binary cache 2024-08-24 18:46:19 +02:00
emily c95296b82c
fix: nix package 2024-08-24 18:37:18 +02:00
emily 877b216eae
refactor: nix flake 2024-08-24 18:23:57 +02:00
Jesse Wierzbinski 832f72160f
refactor: 🚚 Use more Versia branding and assets 2024-08-24 15:34:49 +02:00
Jesse Wierzbinski 3d5a693d71
refactor: ♻️ Use node:cluster instead of Web Workers 2024-08-23 18:43:13 +02:00
Jesse Wierzbinski 6617413222
chore: ⬆️ Upgrade Bun to 1.1.25 2024-08-23 17:22:18 +02:00
Jesse Wierzbinski cfd9d0ceb1
chore: ⬆️ Upgrade dependencies 2024-08-23 17:21:04 +02:00
Jesse Wierzbinski 3912314a83
fix: 🐛 Allow all headers during CORS 2024-08-19 21:56:14 +02:00
Jesse Wierzbinski 4d98034a79
fix: 🔥 Remove Prometheus integration as it is causing issues 2024-08-19 21:53:39 +02:00
Jesse Wierzbinski 5f0ef971f4
fix: 🐛 Only apply security headers to /api/* 2024-08-19 21:26:13 +02:00
Jesse Wierzbinski f3dd229dcb
feat: Implement Prometheus support 2024-08-19 21:23:47 +02:00
Jesse Wierzbinski 26749e576a
feat: Add more utility middleware 2024-08-19 21:17:25 +02:00
Jesse Wierzbinski 866692c1dc
refactor: ♻️ Use native Hono return functions instead of custom ones 2024-08-19 21:03:59 +02:00
Jesse Wierzbinski 7e2f333945
refactor: ♻️ Use a typed wrapper for all API endpoints 2024-08-19 20:06:38 +02:00
Jesse Wierzbinski b0e49855f5
fix: 🏷️ Temporarily suppress type error until packages get rebranding 2024-08-19 15:21:00 +02:00
Jesse Wierzbinski 771097d037
refactor: 🚚 Begin rebranding to Versia Server 2024-08-19 15:16:01 +02:00
Jesse Wierzbinski 64cef5c6d6
fix: 🐛 Fix incorrect path in import 2024-08-19 14:49:36 +02:00
Jesse Wierzbinski 82daa0c74f
chore: ⬆️ Upgrade Bun to 1.1.24 2024-08-19 14:47:12 +02:00
Jesse Wierzbinski eeafabe4dd
chore: ⬆️ Upgrade dependencies 2024-08-19 14:46:20 +02:00
Jesse Wierzbinski 526ae6cfdd
Merge branch 'main' of github.com:lysand-org/lysand 2024-08-19 14:43:57 +02:00
Jesse Wierzbinski 4a1ad9dd96
refactor: 🔥 Remove old config-manager symlink 2024-08-19 14:43:54 +02:00
emily f480036454 feat: Add nix package 2024-08-16 20:29:57 +02:00
emily f678d51542 refactor: flake 2024-08-16 20:29:57 +02:00
April John 4e6e3425ce fix: staging bundle 2024-08-13 14:59:03 +02:00
April John 2f46e75659 fix: staging bundle 2024-08-13 14:03:58 +02:00
April John 78eaa5478c fix: staging bundle 2024-08-13 13:49:17 +02:00
April John a17c634c16 fix: staging bundle 2024-08-13 13:27:10 +02:00
April John 9c1ca570b6 fix: staging bundle 2024-08-13 13:24:48 +02:00
April John 5b6a7557bb feat: staging builds 2024-08-13 13:19:13 +02:00
April John 92db74acf3 rm: nix build 2024-08-13 12:04:46 +02:00
Jesse Wierzbinski 26dc389010
fix: 🔥 Remove old useless post-build patches 2024-08-09 18:49:23 +02:00
Jesse Wierzbinski a80234c445
chore: 🔥 Remove stuff @cutestnekoaqua added by accident 2024-08-09 13:14:38 +02:00
Jesse Wierzbinski 2d7792e936
refactor: 🔥 Remove Husky 2024-08-09 13:10:39 +02:00
Jesse Wierzbinski d43c96e591
chore: ⬆️ Upgrade Bun to 1.1.22 2024-08-09 13:10:02 +02:00
Jesse Wierzbinski 5a159226db
chore: ⬆️ Upgrade dependencies 2024-08-09 13:09:27 +02:00
aprilthepink e588e98f4e feat: flake 2024-08-08 23:42:51 +02:00
Jesse Wierzbinski 8b96401c71
chore: ⬆️ Upgrade dependencies 2024-08-07 01:24:51 +02:00
Gaspard Wierzbinski 838debec25
fix(federation): Send Undos to the followee when unfollowing 2024-08-02 18:28:47 +02:00
DevMiner d2113e349f fix(federation): unfollows don't send Undos to the followee 2024-08-02 17:53:29 +02:00
Jesse Wierzbinski 1368dac77e
chore: ⬆️ Upgrade dependencies (patch Hono until my PR merges) 2024-07-28 01:22:59 +02:00
Jesse Wierzbinski 6445ceedc8
chore: ⬆️ Upgrade Bun to 1.1.21 2024-07-28 00:38:42 +02:00
Jesse Wierzbinski 0194b471a8
feat: Enable Sentry's extra error data integration 2024-07-27 22:44:21 +02:00
Jesse Wierzbinski 3baac85cf7
refactor: ♻️ Rewrite relationship system 2024-07-27 20:46:19 +02:00
Jesse Wierzbinski 62b68a64ac
fix: 🐛 Explicitely set log severity to "info" 2024-07-27 15:43:30 +02:00
Jesse Wierzbinski 7563315750
fix(federation): 🚚 Rename statuses to correct name, Notes 2024-07-26 21:37:09 +02:00
Jesse Wierzbinski 627afffdb2
fix(federation): ✏️ Correct typo causing incorrect URIs 2024-07-26 21:29:37 +02:00
Jesse Wierzbinski 903415161e
fix(federation): 🐛 Fix issues with note federation URIs 2024-07-26 21:19:41 +02:00
Jesse Wierzbinski 92a80d97c2
fix(federation): 🐛 Force add content-type http header 2024-07-26 20:35:26 +02:00
Jesse Wierzbinski 5162000a1f
chore: ⬆️ Upgrade SDK version 2024-07-26 20:22:52 +02:00
Jesse Wierzbinski 385bdc13da
fix(federation): 🐛 Send correct headers in inbox requests 2024-07-26 19:51:08 +02:00
Jesse Wierzbinski 5826acbf24
docs: 📝 Update CHANGELOG 2024-07-26 19:33:54 +02:00
Jesse Wierzbinski eb96544e68
fix(federation): 🐛 Remove usage of Origin header during federation 2024-07-26 19:26:35 +02:00
Jesse Wierzbinski 558ae72c82
fix(federation): 🐛 Fix new notes being federated to ALL remote users, regardless of visibility 2024-07-26 19:21:03 +02:00
Jesse Wierzbinski 2f823317c2
refactor(federation): 🔥 Remove old code and simplify federation requests 2024-07-26 18:51:39 +02:00
Jesse Wierzbinski ad9ed2598c
refactor(federation): ⬆️ Refactor code to use v2.2 of federation SDK 2024-07-26 18:07:11 +02:00
Jesse Wierzbinski aca837cb16
feat(federation): Log signatures generated when serving entites via HTTP 2024-07-26 17:32:03 +02:00
Jesse Wierzbinski 1216e278e8
fix(federation): 🐛 Fix some errors not being ignored properly 2024-07-26 17:20:37 +02:00
Jesse Wierzbinski db2d582295
chore: ⬆️ Upgrade dependencies 2024-07-26 00:58:56 +02:00
Jesse Wierzbinski 505f7712d6
fix(config): 🐛 Add trace propagation targets to Sentry example config 2024-07-26 00:50:03 +02:00
Jesse Wierzbinski 6ae13265fa
feat(federation): Make server actor available on /users/actor 2024-07-26 00:32:33 +02:00
Jesse Wierzbinski 420a0d05dc
feat: Add git commit SHAs to Sentry release 2024-07-26 00:20:58 +02:00
Jesse Wierzbinski 152e42fd30
fix: 💚 Move git commit env var in last step of Dockerfile to avoid it being removed 2024-07-26 00:17:54 +02:00
Jesse Wierzbinski 39d9b4c031
ci: 💚 Correctly input Git SHA into docker build 2024-07-26 00:10:42 +02:00
Jesse Wierzbinski bc25896ed8
feat(config): 🧑‍💻 Add custom tracing URL support to Sentry config 2024-07-26 00:02:48 +02:00
Jesse Wierzbinski 7d1522cc1e
feat(config): Add JSON schema for config 2024-07-25 23:51:00 +02:00
Jesse Wierzbinski d20988afa1
feat(federation): Add signatures to all users and objects served 2024-07-24 23:42:00 +02:00
Jesse Wierzbinski 5a52ac005b
fix(federation): 🚑 Don't re-parse response as JSON when FederationRequester has done so already 2024-07-24 19:25:14 +02:00
Jesse Wierzbinski 0bc6a89706
feat(api): Add more Sentry logging 2024-07-24 19:04:00 +02:00
Jesse Wierzbinski daba8e8178
refactor(federation): ♻️ Refactor code to use less fetch calls and instead use FederationRequester 2024-07-24 18:52:30 +02:00
Jesse Wierzbinski 833f261392
fix(config): 🚑 Add default value for Sentry config 2024-07-24 18:15:33 +02:00
Jesse Wierzbinski 59be7cb55f
chore: 📝 Update changelog for 0.7.0 2024-07-24 18:13:45 +02:00
Jesse Wierzbinski 5061735da7
feat: Add Sentry support 2024-07-24 18:10:29 +02:00
Jesse Wierzbinski 0679971cc0
feat(api): Log all server errors in logs 2024-07-24 17:19:23 +02:00
Jesse Wierzbinski 98a2549a3d
chore: ⬆️ Upgrade dependencies 2024-07-24 16:39:12 +02:00
Jesse Wierzbinski 8213ca62e0
chore: ⬆️ Upgrade @lysand-org/federation to latest 2024-07-23 00:13:46 +02:00
Jesse Wierzbinski 8a6d71d958
feat(api): 🏷️ Only allow JSON values in JSON HTTP responses 2024-07-22 22:02:17 +02:00
Jesse Wierzbinski d4894c362e
refactor(api): ♻️ Remove password2 from password resets (done on client) 2024-07-22 21:29:02 +02:00
Jesse Wierzbinski 0645203d97
docs: 📝 Clarify installation pitfalls 2024-07-22 21:02:41 +02:00
Jesse Wierzbinski f3902f8c7b
fix(api): 🛂 Default grant_type to authorization_code in token requests 2024-07-22 15:54:53 +02:00
Jesse Wierzbinski 757eb835e9
feat(api): Redirect browsers to frontend when accessing raw Lysand objects 2024-07-21 22:37:12 +02:00
Jesse Wierzbinski cf5684cf26
feat(api): Add debug query parameter when viewing raw Lysand objects 2024-07-21 22:33:15 +02:00
Jesse Wierzbinski 7f48c990e7
feat(api): Add global server error handler 2024-07-20 00:30:13 +02:00
Jesse Wierzbinski 23d091f7ce
fix(federation): 🐛 Make WebFinger always search for local users 2024-07-20 00:18:44 +02:00
Jesse Wierzbinski b5b8831073
fix(federation): 🐛 Output error when requesting remote users through /users 2024-07-20 00:17:35 +02:00
Jesse Wierzbinski 42ff591e48
fix(federation): 🐛 Fix fetching of ActivityPub users not working anymore 2024-07-17 15:37:36 +02:00
Jesse Wierzbinski 0e054e7cba
fix(federation): 🐛 Put the ActivityPub link first in WebFinger to work around Misskey bug 2024-07-17 15:08:21 +02:00
Jesse Wierzbinski 896d22616d
chore: ⬆️ Upgrade dependencies 2024-07-17 14:49:36 +02:00
Jesse Wierzbinski 42144a578b
chore: ⬆️ Upgrade Bun to 1.1.20 2024-07-17 14:48:45 +02:00
Jesse Wierzbinski fea19eeb2e
feat(federation): Add WebFinger forwarding to bridge for ActivityPub requests 2024-07-17 14:46:43 +02:00
Jesse Wierzbinski be881f18cd
feat(api): Add new endpoint to get a user by its username 2024-07-17 14:02:29 +02:00
Jesse Wierzbinski 407eb5e205
feat(api): Make account searches case-insensitive 2024-07-17 01:26:24 +02:00
Jesse Wierzbinski 7c285ee14d
feat(api): Add refetching API 2024-07-17 01:20:18 +02:00
Jesse Wierzbinski f081941474
test: 🐛 Delete test users after all tests 2024-07-17 00:50:59 +02:00
Jesse Wierzbinski cc8a97ae79
fix(config): 🐛 Make bridge url default to undefined, not "" 2024-07-16 23:36:36 +02:00
Jesse Wierzbinski f2c9814171
fix(config): 🐛 Ensure bridge config is optional 2024-07-16 23:33:11 +02:00
Jesse Wierzbinski aae99c804a
fix(federation): 🐛 Don't try to fetch from ActivityPub instances if no bridge is configured 2024-07-16 23:30:52 +02:00
Jesse Wierzbinski ff315af230
feat(federation): Add ActivityPub bridge support with CLI command 2024-07-16 23:29:20 +02:00
Jesse Wierzbinski 153aa061f0
ci: 👷 Add new typecheck CI action 2024-07-16 20:17:35 +02:00
Jesse Wierzbinski ba56c98e35
chore(federation): ⬆️ Upgrade @lysand-org/federation to 2.1.1 2024-07-16 20:17:18 +02:00
Jesse Wierzbinski da16a5d4c2
chore: ⬆️ Upgrade dependencies 2024-07-16 20:10:04 +02:00
Jesse Wierzbinski 74b194b1f4
fix: 👷 Correctly add Node during Docker build 2024-07-11 13:34:24 +02:00
Jesse Wierzbinski 65abaa9c7b
feat: 👷 Add linting workflow, add Node to Docker building step 2024-07-11 13:25:31 +02:00
Jesse Wierzbinski be3bced531
chore: ⬆️ Upgrade Bun to 1.1.18 2024-07-11 13:21:16 +02:00
Jesse Wierzbinski 939815510c
refactor: ⬆️ Upgrade dependencies, use JSR for Hono 2024-07-11 12:56:28 +02:00
Jesse Wierzbinski 57b295ccf2
fix(cli): 🐛 Don't federate changes to remote users, initialize search indexer on all CLI commands 2024-06-29 22:55:50 -10:00
Jesse Wierzbinski 49a2552e96
docs: 📝 Fix for slightly incorrect docs 2024-06-29 22:36:00 -10:00
Jesse Wierzbinski b111a41f01
chore: ⬆️ Upgrade dependencies 2024-06-29 22:25:15 -10:00
Jesse Wierzbinski cea9452127
refactor(federation): ♻️ Replace WebFinger code with @lysand-org/federation logic, add new debug command 2024-06-29 22:24:10 -10:00
Jesse Wierzbinski 38c8ea24a9
refactor(federation): 🔥 Remove some old SQL queries for Instances 2024-06-29 21:08:03 -10:00
Jesse Wierzbinski f2b0de779b
refactor: ♻️ Store instance federation protocol in database, refactor fetcher 2024-06-29 20:58:39 -10:00
Jesse Wierzbinski 6dc51ab323
fix: 🐛 Externalize acorn because it builds weirdly and leads to errors 2024-06-29 01:27:03 -10:00
Jesse Wierzbinski 03f5965755
fix: 🐛 Hack a fix for incorrect bundler output 2024-06-29 00:06:09 -10:00
Jesse Wierzbinski 84bdb75d77
fix: 🐛 Fix v2 search API not working at all 2024-06-28 23:59:01 -10:00
Jesse Wierzbinski 93b8609411
feat: Add CLI command to rebuild index 2024-06-28 23:58:43 -10:00
Jesse Wierzbinski 19c15f7e96
refactor: ♻️ Replace Meilisearch with Sonic 2024-06-28 23:40:44 -10:00
Jesse Wierzbinski 2cf1537a7e
chore: ♻️ Replace all @ts-ignore with @ts-expect-error 2024-06-28 21:33:19 -10:00
Jesse Wierzbinski a8132e8d53
docs: 📝 Improve contribution docs 2024-06-28 21:31:17 -10:00
Jesse Wierzbinski 5f7c77a3d8
fix: 🐛 Fix files without a filename crashing the media manager 2024-06-28 21:00:02 -10:00
Jesse Wierzbinski e95cabb304
fix: 🐛 Properly install and import the S3 client 2024-06-28 20:49:17 -10:00
Jesse Wierzbinski 106e34848a
refactor(api): 🏷️ Replace API types with those from @lysand-org/client 2024-06-28 20:36:15 -10:00
Jesse Wierzbinski 99b8c35f7b
chore: ⬆️ Upgrade dependencies 2024-06-28 20:15:07 -10:00
Jesse Wierzbinski faf829437d
refactor: ♻️ Rewrite media management code 2024-06-28 20:10:02 -10:00
Jesse Wierzbinski d09f74e58a
refactor: 🚚 Rename functions, move getUrl to Attachment 2024-06-28 17:50:56 -10:00
Jesse Wierzbinski 11c3931007
docs: 📝 Add changelog for 0.7, update README with new features 2024-06-28 17:44:42 -10:00
Jesse Wierzbinski e1555e6fe7
test(api): Add test to check state parameter during oauth 2024-06-26 17:00:09 -10:00
Jesse Wierzbinski a6c5f320e3
fix(api): 🚑 Remove hack to get text 2024-06-26 16:14:12 -10:00
Jesse Wierzbinski a93085ae1d
fix(api): 🐛 Allow empty website in app creation to fix issue with Traewelling 2024-06-26 15:39:48 -10:00
Jesse Wierzbinski e59c3aa625
fix(api): 🐛 Fix body not being logged in request debugging 2024-06-26 15:31:51 -10:00
Jesse Wierzbinski de75310b61
fix: 🐛 Fix request logs not showing up when starting server via CLI 2024-06-26 15:16:50 -10:00
Jesse Wierzbinski 556ef83ecf
fix: 🐛 Fix LogTape expecting a Deno global to exist (patch) 2024-06-26 15:06:57 -10:00
Jesse Wierzbinski 3004ec2350
chore: ⬆️ Upgrade Bun to 1.1.17 2024-06-26 14:46:22 -10:00
Jesse Wierzbinski d29603275a
refactor(api): ♻️ Use Web Workers instead of spawning the same process once for each thread 2024-06-26 14:44:08 -10:00
Jesse Wierzbinski bc8220c8f9
refactor: ♻️ Replace logging system with @logtape/logtape 2024-06-26 13:11:39 -10:00
Jesse Wierzbinski 75992dfe62
fix(api): 🐛 Disable CSP upgrade-insecure-requests when using Tor 2024-06-25 18:46:16 -10:00
Jesse Wierzbinski ae3d5813cf
fix(api): 🐛 Fix frontend proxy breaking when host is different than base_url 2024-06-25 18:31:57 -10:00
Jesse Wierzbinski 51cbb22eb0
fix(config): 🐛 Allow empty proxy address (in case config value isn't set) 2024-06-25 18:00:03 -10:00
Jesse Wierzbinski b8b822e553
feat(config): Add support for HTTP proxies on outgoing requests 2024-06-25 17:13:40 -10:00
Jesse Wierzbinski 0ecb65de29
refactor: ♻️ Move config checker code into its own file 2024-06-25 16:30:51 -10:00
Jesse Wierzbinski 8a774fa05d
refactor(plugin): ♻️ Use enum instead of strings 2024-06-21 23:44:21 -10:00
Jesse Wierzbinski 98f8ec071c
feat(plugin): Initialize new plugin system 2024-06-21 18:22:53 -10:00
Jesse Wierzbinski 1b427cf225
chore: ⬆️ Upgrade dependencies 2024-06-20 19:15:18 -10:00
Jesse Wierzbinski 70cd00cfa8
refactor(federation): ⬆️ Use @lysand-org/federation v2.0.0 2024-06-19 13:21:02 -10:00
Jesse Wierzbinski 47ce60494a
chore: ⬆️ Upgrade Bun to 1.1.14 2024-06-19 13:04:01 -10:00
Jesse Wierzbinski 84f2312508
chore: ⬆️ Upgrade dependencies 2024-06-19 13:01:54 -10:00
Jesse Wierzbinski f5330b6134
feat: Add more metadata to v2 instance API endpoint 2024-06-19 12:02:47 -10:00
Jesse Wierzbinski e9f504aa0c
fix(api): 🐛 Proxy all OIDC provider icons 2024-06-18 20:56:29 -10:00
Jesse Wierzbinski 6e7d16864a
chore: 🧑‍💻 Add list of recommended vscode extensions 2024-06-18 20:56:12 -10:00
Jesse Wierzbinski f341f58a73
fix(api): 🐛 Properly edit username when asked via API 2024-06-18 18:39:34 -10:00
Jesse Wierzbinski e013362ac4
fix(api): 🛂 Fix two variables with the same name causing incorrect data to be returned 2024-06-18 18:01:13 -10:00
Jesse Wierzbinski 32538586dc
docs: 🐛 Fix incorrect path in docs 2024-06-17 19:47:15 -10:00
Jesse Wierzbinski 925179211a
docs: 🐛 Fix incorrect filename 2024-06-17 11:13:16 -10:00
Jesse Wierzbinski 65498e7bd7
fix(api): 🐛 Fix Cloudflare R2 incorrectly serving SVG images as XML 2024-06-16 01:50:32 -10:00
Jesse Wierzbinski de9dca5735
feat(config): Add option to never convert vector images 2024-06-16 01:39:16 -10:00
Jesse Wierzbinski 6ef3a854d9
feat(api): Allow animated media to be uploaded 2024-06-16 01:15:49 -10:00
Jesse Wierzbinski d33a61e713
fix(api): 🐛 Properly disable challenges when config option is set 2024-06-15 20:27:31 -10:00
Jesse Wierzbinski a0d56c044b
docs: 📝 Update some outdated documentation info 2024-06-14 00:02:33 -10:00
Jesse Wierzbinski 731fc9847c
fix(api): 🚚 Rename "id" to "hash" 2024-06-13 23:55:39 -10:00
Jesse Wierzbinski 2ec7e512e0
fix(api): 🐛 Fix local media endpoint not being correctly registered
Expected only a name, forgot about the file hash
2024-06-13 23:54:47 -10:00
Jesse Wierzbinski c764cc044d
fix: 🚑 Sleep process instead of exiting it on error
Avoids Docker's auto-restart policy from causing infinite reboots and hanging the system
2024-06-13 23:44:46 -10:00
Jesse Wierzbinski 7ba0eb82f1
docs: 📝 Add info about possible errors during installation 2024-06-13 23:42:24 -10:00
Jesse Wierzbinski afeffdbd13
fix(config): 🔥 Remove tos_url from example config (not used anymore) 2024-06-13 23:30:55 -10:00
Jesse Wierzbinski b7f8f6689e
fix(config): 🐛 Fix crashes with default config values 2024-06-13 23:29:41 -10:00
Jesse Wierzbinski edbe6e45b2
fix: 🐛 Fix incorrect docs, make exit code 0 instead of 1 2024-06-13 23:26:20 -10:00
Jesse Wierzbinski 641e712272
fix: 📝 Update docker-compose file 2024-06-13 23:11:01 -10:00
Jesse Wierzbinski 99f14ba114
feat(api): Automatically register user when connecting with OIDC profile not already existing 2024-06-13 23:05:04 -10:00
Jesse Wierzbinski 70a669a29c
docs(api): 📝 Document API parameter to change username 2024-06-13 22:19:15 -10:00
Jesse Wierzbinski cfa0ab4ac9
chore: ⬆️ Upgrade dependencies 2024-06-13 22:06:50 -10:00
Jesse Wierzbinski 279ccf078f
chore: 🚨 Disable linter cognitive complexity by default 2024-06-13 22:04:22 -10:00
Jesse Wierzbinski 8f9472b221
feat(api): Implement Challenges API 2024-06-13 22:03:51 -10:00
Jesse Wierzbinski 924ff9b2d4
refactor(api): 🚚 Change ApiRouteMetadata structure to be more consistent 2024-06-13 18:03:17 -10:00
Jesse Wierzbinski 00fd751c2a
fix(federation): 🐛 Fix mention URIs in Lysand Notes being empty string for local users 2024-06-13 11:53:41 -10:00
Jesse Wierzbinski 0359ba13c4
fix(api): 🛂 Don't automatically remove trailing slashes from OIDC issuer URLs 2024-06-13 11:33:07 -10:00
Jesse Wierzbinski c3271ba264
docs: 📝 More work on JSDoc 2024-06-12 22:52:03 -10:00
Jesse Wierzbinski 527137f279
chore: ⬆️ Upgrade dependencies 2024-06-12 20:39:53 -10:00
Jesse Wierzbinski 83275be536
refactor: ⚰️ Remove dead code and useless files 2024-06-12 20:34:17 -10:00
Jesse Wierzbinski 98f3ab23d8
refactor(api): 🎨 Simplify expressions 2024-06-12 20:20:49 -10:00
Jesse Wierzbinski 36d70fb612
refactor(api): 🎨 Simplify bait middleware 2024-06-12 19:38:57 -10:00
Jesse Wierzbinski d301d4da09
refactor(api): 🎨 Don't use node:crypto for random strings 2024-06-12 19:38:26 -10:00
Jesse Wierzbinski d8cb1d475b
refactor(api): 🎨 Refactor emojis into their own class 2024-06-12 18:52:01 -10:00
Jesse Wierzbinski c61f519a34
refactor(api): 🎨 Refactor complex functions into smaller ones 2024-06-12 18:16:59 -10:00
Jesse Wierzbinski a1e02d0d78
refactor: 🚨 Turn every linter rule on and fix issues (there were a LOT :3) 2024-06-12 16:26:43 -10:00
Jesse Wierzbinski 2e98859153
refactor(database): ♻️ Move Attachment into its own class 2024-06-12 15:03:57 -10:00
Jesse Wierzbinski 5565bf00de
refactor(database): 🎨 Improve database handlers to have more consistent naming and methods 2024-06-12 14:45:07 -10:00
Jesse Wierzbinski a6159b9d55
feat(api): Preliminary captcha support database tables 2024-06-12 13:48:58 -10:00
Jesse Wierzbinski 9d8c2e81e9
refactor(database): 🚚 Move drizzle migrations to their own folder 2024-06-12 13:10:40 -10:00
Jesse Wierzbinski b17b2be683
fix(api): 🔒 Properly proxy role icons through media proxy 2024-06-11 18:57:04 -10:00
Jesse Wierzbinski 3d1cc52d14
docs: ✏️ Fix typos in docs 2024-06-11 14:42:29 -10:00
Jesse Wierzbinski ddaaa38fce
chore: ⬆️ Update Bun to 1.1.13 2024-06-11 14:40:55 -10:00
Jesse Wierzbinski efe202ea27
feat(api): Add Lysand roles to user accounts 2024-06-11 14:29:59 -10:00
Jesse Wierzbinski 4f2c98390c
chore: 📦 Update dependencies 2024-06-11 13:43:33 -10:00
Jesse Wierzbinski c4da7e1484
fix(api): 🐛 Fix incorrect relationships being returned (small rewrite) 2024-06-11 13:42:36 -10:00
Jesse Wierzbinski 20d1a5f39e
feat(api): Add requested_by to relationships 2024-06-11 12:32:38 -10:00
Jesse Wierzbinski ffcf01e3cd
feat(api): Add TOS and Privacy Policy support 2024-06-11 09:55:40 -10:00
Jesse Wierzbinski e9e33432c2
fix: 🐛 Make sure reverse proxies don't tamper with URLs 2024-06-10 16:24:32 -10:00
Jesse Wierzbinski 9f262c12d6
fix: 🛂 Remove code parameter from redirect URI 2024-06-10 16:15:29 -10:00
Jesse Wierzbinski 876b0dcde8
fix: 🛂 Don't remove iss from current URL 2024-06-10 16:11:42 -10:00
Jesse Wierzbinski 5a7b3d0f25
fix: 🛂 Remove iss parameter from OIDC redirect URL 2024-06-10 16:08:57 -10:00
Jesse Wierzbinski 80c9b10c36
fix: 🛂 Remove uninitialized variable access 2024-06-10 16:04:47 -10:00
Jesse Wierzbinski f0c69cfb33
chore: 📦 Update packages 2024-06-10 16:00:52 -10:00
Jesse Wierzbinski b3bace4d53
fix(api): 🛂 Fix incorrect redirect URI passed to external OIDC providers, normalize issuer URL 2024-06-10 15:58:51 -10:00
Jesse Wierzbinski dae37d47a3
fix(api): Don't use markdown-it-anchor when rendering Markdown 2024-06-09 18:04:20 -10:00
Jesse Wierzbinski 8da4b07642
chore: 📦 Update packages 2024-06-09 16:16:21 -10:00
Jesse Wierzbinski d2f5aaf114
fix(api): 🐛 Add default role with default permissions in roles API 2024-06-09 16:14:36 -10:00
Jesse Wierzbinski 11369649c0
fix(api): 🐛 Give correct URI/URL values for notes in API 2024-06-09 15:17:03 -10:00
Jesse Wierzbinski c6c71bebb7
chore: 📦 Update packages 2024-06-08 15:36:50 -10:00
Jesse Wierzbinski 1163dacbd6
chore: 🐛 Update lockfile 2024-06-07 23:08:38 -10:00
Jesse Wierzbinski deb532c970
chore: 📦 Update packages 2024-06-07 23:08:15 -10:00
Jesse Wierzbinski 3f90625429
chore: 🐛 Change --apply to --write in precommit linting 2024-06-07 19:32:47 -10:00
Jesse Wierzbinski 4902f078a8
feat(api): Add permissions to every route and permission config 2024-06-07 18:57:29 -10:00
Jesse Wierzbinski 19823d8eca
feat(api): Add Roles API 2024-06-07 17:31:17 -10:00
Jesse Wierzbinski 46f41199ac
chore: 📦 Update packages 2024-06-07 15:36:17 -10:00
Jesse Wierzbinski e229c30a9f
chore: 📦 Use NPM version of @lysand-org/federation 2024-06-07 15:33:00 -10:00
Jesse Wierzbinski 43544a44da
fix(api): 🐛 Fix some redirect URIs breaking the oauth redirection code 2024-06-07 14:08:27 -10:00
Jesse Wierzbinski 06e97bbf0a
fix(api): 🐛 Set proxy redirect to manual 2024-06-07 13:58:49 -10:00
Jesse Wierzbinski 43b41b793f
Merge branch 'main' of github.com:lysand-org/lysand 2024-06-07 13:52:22 -10:00
Jesse Wierzbinski 56e32e2c20
fix(api): 🐛 Add debug statement to proxy 2024-06-07 13:52:11 -10:00
Gaspard Wierzbinski 71d4c82573
Merge pull request #15 from skyeforeverblue/patch-1
Pedantic bullshit :>
2024-06-06 12:59:01 -10:00
Skye Chappelle 5c02477c52
Pedantic readme update 2024-06-06 18:55:10 -04:00
Jesse Wierzbinski 8f09ea4c60
feat(federation): Add support for federation of note editing 2024-06-05 21:04:52 -10:00
Jesse Wierzbinski 3e94a9d491
fix(api): 🐛 Fix incorrect editing of note attachments (when attachments are removed) 2024-06-05 20:35:56 -10:00
Jesse Wierzbinski 88ad7178bf
feat(federation): Federate note deletions 2024-06-05 19:25:49 -10:00
Jesse Wierzbinski 431bc9c715
fix(federation): 🐛 Add missing SQL AND 2024-06-05 19:15:10 -10:00
Jesse Wierzbinski 0eee4a1f20
fix(federation): 🐛 Don't try to federate to local users 2024-06-05 19:12:23 -10:00
Jesse Wierzbinski 32cb0ea733
fix(federation): 🐛 Fix profile edits not being federated 2024-06-05 19:08:34 -10:00
Jesse Wierzbinski 4c22b0edcc
feat(federation): Federate user profile changes to other instances 2024-06-05 18:58:28 -10:00
Jesse Wierzbinski f8196f72f9
feat(federation): Add user refetching, support for Undo in federation 2024-06-05 18:49:06 -10:00
Jesse Wierzbinski 908fdcaa79
feat(api): Add real filename to proxy 2024-06-05 18:07:22 -10:00
Jesse Wierzbinski 7f4e39e08b
fix(api): 🐛 Explicitely set Content-Encoding to an empty value in proxy to avoid Traefik v3.0 errors 2024-06-05 16:35:25 -10:00
Jesse Wierzbinski 5efd832e64
fix(api): 🐛 Another attempt at a fix 2024-06-05 16:26:19 -10:00
Jesse Wierzbinski a319d1e628
fix(api): 🐛 Attempt 2 at fixing proxy bug 2024-06-05 16:07:56 -10:00
Jesse Wierzbinski 29b98fd1d1
fix(api): 🐛 (hopefully) fix some media not being decoded well on proxy 2024-06-05 15:56:40 -10:00
Jesse Wierzbinski f4af0e2407
fix(api): 🐛 Prevent non-images uploaded from not being saved to object storage 2024-06-05 15:40:37 -10:00
Jesse Wierzbinski 268ced27ef
test(api): Add more tests for favourite and unfavourite 2024-06-03 21:23:00 -10:00
Jesse Wierzbinski 1d55570abd
fix(api): 🐛 Fix bugs where favourite/unfavourite could return negative values (+ add tests) 2024-06-03 21:12:55 -10:00
Jesse Wierzbinski d2767b0862
chore: 📦 Update packages in package.json too 2024-06-03 21:11:56 -10:00
Jesse Wierzbinski e6a4800bd1
chore: 📦 Update Bun to 1.1.12 2024-06-03 16:11:47 -10:00
Jesse Wierzbinski 381094c12d
chore: 📦 Update all dependencies to latest version 2024-06-03 16:08:42 -10:00
Jesse Wierzbinski f904ad33ba
refactor: ♻️ Clean up Dockerfile to not require Node to build 2024-05-28 22:14:20 -10:00
Jesse Wierzbinski ade9bd08fa
ci: 💚 Checkout with recursive submodules correctly 2024-05-28 15:19:39 -10:00
Jesse Wierzbinski f87bcbd0da
chore: ⚰️ Remove dead code and unused imports 2024-05-28 15:14:24 -10:00
Jesse Wierzbinski 3a37790315
chore: 🔖 Set version to 0.7.0 2024-05-28 15:03:20 -10:00
Jesse Wierzbinski 0706541546
refactor: 🚚 Add slash to typescript path shortcuts 2024-05-28 14:59:49 -10:00
Jesse Wierzbinski 5b658984a5
refactor: Only delete old test users once at preload 2024-05-28 14:51:55 -10:00
Jesse Wierzbinski f5a0f52b93
fix: 💚 Remove --frozen-lockfile during CI, as the build and dev Bun version differ and cause issues 2024-05-28 14:43:15 -10:00
Jesse Wierzbinski fbe0e35587
refactor(federation): ♻️ Refactor inbox code to use new package builtins 2024-05-28 14:36:15 -10:00
Jesse Wierzbinski fbc0c2c586
chore: 📦 Replace bun-types with @types/bun 2024-05-28 13:58:38 -10:00
Jesse Wierzbinski a87a474a62
chore: 📦 Update Bun to 1.1.10 2024-05-28 13:50:38 -10:00
Jesse Wierzbinski ddaa7269ba
chore: 📦 Add submodule to lysand-api, for feature testing 2024-05-28 13:49:24 -10:00
Jesse Wierzbinski 241ad8232d
fix(federation): 🐛 Hopefully fix the Great Signature Bug 2024-05-23 20:08:30 -10:00
Jesse Wierzbinski 75043bae15
feat(federation): Log signed string to debug as well 2024-05-23 19:46:22 -10:00
Jesse Wierzbinski fd59d9ebae
chore: 📦 Update all packages 2024-05-23 19:05:26 -10:00
Jesse Wierzbinski fc98c95892
chore(federation): Add sender public key to federation debugging 2024-05-23 19:04:05 -10:00
Jesse Wierzbinski f5605e6814
build: 📦 Update Bun to 1.1.9 2024-05-21 15:41:48 -10:00
Jesse Wierzbinski 14851fa93e
chore: 📦 Update all packages to their latest version 2024-05-21 15:33:36 -10:00
Jesse Wierzbinski fd38161769
fix(federation): 🐛 Fix debug logger not correctly outputting 2024-05-21 15:23:48 -10:00
Jesse Wierzbinski eab61b38f1
feat(federation): Add bridge tokens, federation request debugging 2024-05-21 14:59:03 -10:00
Jesse Wierzbinski 673b7d0bae
fix(api): 🐛 Automatically rewrite http to https in federation 2024-05-17 11:42:42 -10:00
Jesse Wierzbinski c28628ebb3
feat(api): Add safeguard for incorrectly configured proxies 2024-05-17 09:38:38 -10:00
Jesse Wierzbinski 7a591a024e
feat(federation): Add bridge support to Lysand 2024-05-17 07:56:13 -10:00
Jesse Wierzbinski a603b602e6
fix(federation): 🐛 Fix multiple incorrect outputs in federation routes 2024-05-17 07:39:59 -10:00
Jesse Wierzbinski b4b8f51a5a
chore: 🚨 Run format 2024-05-16 23:39:10 -10:00
Jesse Wierzbinski 36f7299a77
chore(build): ⬆️ Update federation lib to 1.1.5 2024-05-16 23:38:21 -10:00
Jesse Wierzbinski dfe678ffae
refactor(federation): ♻️ Use new federation package to send inbox requests 2024-05-16 22:47:30 -10:00
Jesse Wierzbinski 820591dddc
fix(cli): ⚰️ Remove old placeholder code and replace it with real code 2024-05-16 22:41:38 -10:00
Jesse Wierzbinski 398da5fc3f
fix(federation): 🐛 Fix federation bug with already consumed body 2024-05-16 22:37:06 -10:00
Jesse Wierzbinski e2362604c7
test(api): Add tests for password reset 2024-05-16 22:34:42 -10:00
Jesse Wierzbinski 24288c95b5
feat(api): Implement password resets 2024-05-16 22:27:41 -10:00
Jesse Wierzbinski 1365987a1c
fix(federation): 🚑 Correct user inbox endpoint API route 2024-05-16 21:51:49 -10:00
Jesse Wierzbinski 0a82cdc59e
docs(config): 📝 Explain what redirect URL to put in OIDC config 2024-05-16 21:30:27 -10:00
Jesse Wierzbinski 606c7e290c
chore: 📦 Update all packages to latest version 2024-05-16 21:00:43 -10:00
Jesse Wierzbinski ec62906221
chore: 🔖 Update version to 0.6.0 2024-05-16 20:59:21 -10:00
Jesse Wierzbinski d4e1c0d95d
fix(api): 🐛 Fix incorrect OAuth2 linking logic 2024-05-16 20:58:27 -10:00
Jesse Wierzbinski 2db4f25ba6
feat(config): Allow frontend route customization and forcing OIDC 2024-05-16 18:05:06 -10:00
Jesse Wierzbinski b34166de93
docs(api): 📝 Document all API changes 2024-05-16 15:50:13 -10:00
Jesse Wierzbinski b1216a43f2
refactor(api): ♻️ Change route names, improve API endpoints to be more consistent with Mastodon API 2024-05-16 15:49:59 -10:00
Jesse Wierzbinski a6eb826b04
docs: 📝 Update contributing guide 2024-05-16 09:50:37 -10:00
Jesse Wierzbinski 517f0c631e
refactor: 🔨 Also run bun install in pre-commit hooks 2024-05-15 17:32:05 -10:00
Jesse Wierzbinski 119f9ea97b
fix(build): 💚 Update Lockfile 2024-05-15 17:29:46 -10:00
Jesse Wierzbinski 060b3980ba
fix(build): 🐛 Make the prepare command use bunx 2024-05-15 17:28:37 -10:00
Jesse Wierzbinski 11460a83ad
refactor(build): 🐛 Promote Husky to dependency 2024-05-15 17:26:59 -10:00
Jesse Wierzbinski 6fdc8b2b9a
fix(build): 🐛 More shenanigans?? 2024-05-15 17:25:27 -10:00
Jesse Wierzbinski 075a23124b
feat: Add Husky 2024-05-15 17:19:45 -10:00
Jesse Wierzbinski 2b5b82b465
fix: 🐛 Fix all TypeScript issues 2024-05-15 17:07:34 -10:00
Jesse Wierzbinski 29aa43f4ce
fix(build): 🐛 Continuation of previous commit 2024-05-15 16:51:59 -10:00
Jesse Wierzbinski 023b80f411
fix(build): 🐛 Changed the CI test config so it is valid 2024-05-15 16:50:07 -10:00
Jesse Wierzbinski fb31375b74
refactor(config): 🔥 Replace config validation with Zod 2024-05-15 16:37:25 -10:00
Jesse Wierzbinski 093337dd4f
refactor(federation): 🔥 Remove old types and federation code 2024-05-14 14:38:30 -10:00
Jesse Wierzbinski 5fd6a4e43d
feat(federation): Replace old types and federation validators with @lysand-org/federation 2024-05-14 14:35:13 -10:00
Jesse Wierzbinski 25d087a54b
feat(build): Start Lysand from CLI in prod 2024-05-13 11:54:51 -10:00
Jesse Wierzbinski 6b83336fa3
fix(api): Fix a test sending a body with a GET request 2024-05-13 11:48:58 -10:00
Jesse Wierzbinski 6c3fcf699e
feat(api): Add support for multithreaded API servers 2024-05-13 11:36:46 -10:00
Jesse Wierzbinski e502a2d8c8
fix(federation): 🐛 Fix missing regex error message 2024-05-13 11:35:36 -10:00
Jesse Wierzbinski 5e87f85851
refactor(federation): 🦺 Update Lysand object validatio to be stricter 2024-05-13 11:33:39 -10:00
Jesse Wierzbinski eb976250a4
fix(api): 🐛 Fix post editing not working with JSON content-type 2024-05-12 19:25:56 -10:00
Jesse Wierzbinski b83d76abf6
fix(api): 🐛 Fix only one emoji being parsed per post 2024-05-12 19:14:37 -10:00
Jesse Wierzbinski 0d4d894fd4
docs: 📝 Update docs to add guidance on setting up OIDC 2024-05-12 18:55:34 -10:00
Jesse Wierzbinski 7f6aeeb859
feat(api): Add secret rudimentary OIDC account linking support 2024-05-12 18:34:35 -10:00
Jesse Wierzbinski ff43b19122
fix(api): 🐛 Fix OIDC 2024-05-12 18:01:51 -10:00
Jesse Wierzbinski 29d7b09677
fix(api): 🐛 Deleting emojis now removes them from object storage 2024-05-12 16:52:19 -10:00
Jesse Wierzbinski 7846a03bcf
fix(api): 🐛 Fix incorrect content_type when uploading and converting emojis 2024-05-12 16:30:26 -10:00
Jesse Wierzbinski 4f070c9b65
fix(api): 🔒 Replace bad webfinger regex with good one 2024-05-12 16:27:40 -10:00
Jesse Wierzbinski 9ad0f88ff2
fix(api): 🐛 Local media uploader: don't error out when a file has already been uploaded 2024-05-12 16:18:07 -10:00
Jesse Wierzbinski da2520e60e
feat(api): Add user emoji upload capabilities 2024-05-12 16:09:57 -10:00
Jesse Wierzbinski 980f4c8021
fix(api): 🐛 Forbid uploading emojis with the same shortcode 2024-05-12 15:17:15 -10:00
Jesse Wierzbinski 8e5d68144c
fix(api): 🐛 Fix regression in emoji parsing caused by incorrectly changed regex 2024-05-12 15:07:55 -10:00
Jesse Wierzbinski c6c92e716f
fix(api): Remove code that checks for missing filenames 2024-05-12 14:35:55 -10:00
aprilthepink c4910fb7f9 feat: nix shell
Signed-off-by: aprilthepink <aprl@acab.dev>
2024-05-13 02:30:52 +02:00
Jesse Wierzbinski 303928f960
refactor(api): 🔥 Refactor media uploader code 2024-05-12 14:30:27 -10:00
Jesse Wierzbinski 9566387273
fix(api): 🐛 Fix oauth token endpoint returning an ISO-8601 string instead of a unix timestamp 2024-05-12 14:01:37 -10:00
Jesse Wierzbinski ff14e5a5d3
fix(api): 🐛 Fix auth could not error when token was wrong and authorization required on a route 2024-05-12 13:53:49 -10:00
Jesse Wierzbinski 14d3a243a2
fix(api): 🐛 Add safeguards to emoji upload routes 2024-05-12 13:43:58 -10:00
Jesse Wierzbinski 67bee695e6
feat(api): Add safeguard when using formdata without a boundary 2024-05-12 13:21:06 -10:00
Jesse Wierzbinski 3f9ec0bc80
feat(api): Add support for urn:ietf:wg:oauth:2.0:oob oauth redirect URI 2024-05-12 12:24:15 -10:00
Gaspard Wierzbinski e07337340d
Merge pull request #14 from lysand-org/feat/nixify
feat: flake devshell
2024-05-12 12:06:39 -10:00
aprilthepink a17b9a739e feat: flake devshell
Signed-off-by: aprilthepink <aprl@acab.dev>
2024-05-12 23:58:58 +02:00
Jesse Wierzbinski 6859ab5775
fix(api): 🐛 Fix incorrect ancestor order in note context endpoint 2024-05-11 16:44:00 -10:00
Jesse Wierzbinski 4713d0f93f
fix(api): 🐛 Add JSON support to every form that doesn't have a file parameter 2024-05-11 15:51:01 -10:00
Jesse Wierzbinski 9f0eab03f2
fix(api): 🐛 Add JSON support to /api/v1/statuses/:id 2024-05-11 15:47:25 -10:00
Jesse Wierzbinski 77cab0962d
chore: 📦 Update all packages to latest version 2024-05-11 15:36:47 -10:00
Jesse Wierzbinski 6205718f0d
chore: 📦 Update Bun to 1.1.8 2024-05-11 15:34:57 -10:00
Jesse Wierzbinski 2cde8d2dd9
test(api): Fix a failing test in CI due to tests assuming we use S3 2024-05-11 15:33:32 -10:00
Jesse Wierzbinski 8fedd1a07d
feat(api): Add new admin emoji API 2024-05-11 15:27:28 -10:00
Jesse Wierzbinski b979daa39a
feat(api): Allow more HTML tags in Markdown 2024-05-11 15:27:19 -10:00
Jesse Wierzbinski 4ce5dfeae3
fix(api): 🔒 Remove client_secret during oauth consent flow 2024-05-09 15:56:46 -10:00
Jesse Wierzbinski 5b03d93ef8
fix(build): ⬇️ Downgrade Bun to 1.1.4 in the building stage of the Dockerfile 2024-05-08 16:39:54 -10:00
Jesse Wierzbinski 692db9a334
fix(build): 🐛 Fix build error with unzipit by making it external 2024-05-08 16:29:41 -10:00
Jesse Wierzbinski 5bdb8360ea
feat(cli): Add more emoji commands to CLI (add, delete, list, import) 2024-05-08 16:07:33 -10:00
Jesse Wierzbinski e48f57a3d8
perf(database): Improve performance when fetching timelines by fetching all data in a single SQL query 2024-05-08 13:19:53 -10:00
Jesse Wierzbinski 26dfd14aaf
test(api): Add tests for account registration endpoint 2024-05-08 12:54:44 -10:00
Jesse Wierzbinski 20629b1712
fix(api): 🐛 oh my god stop breaking 2024-05-08 12:41:27 -10:00
Jesse Wierzbinski f71c8a50d3
fix(api): 🐛 Fix incorrect zod types in registration 2024-05-08 12:37:28 -10:00
Jesse Wierzbinski 52e29e2dee
Fix megalodon accounts not registering 2024-05-08 12:34:01 -10:00
Jesse Wierzbinski 3c3814a3c1
fix(api): 🐛 Fix favourited attribute not being correct on serialized API notes 2024-05-08 11:51:47 -10:00
Jesse Wierzbinski 5fcbcd0f07
fix(api): 🐛 Fix bug where likes wouldn't appear on API notes 2024-05-08 10:57:42 -10:00
Jesse Wierzbinski a9629b825b
fix(api): 🎨 Do wizardry on qs middleware to also work on multipart formData 2024-05-08 01:16:16 -10:00
Jesse Wierzbinski 2acd281c76
fix(cli): 🐛 Disable pretty dates when outputting data as JSON or CSV 2024-05-08 00:41:59 -10:00
Jesse Wierzbinski f0f9c78cc6
fix(cli): 🐛 Don't skip password hash when a password is provided manually 2024-05-08 08:23:44 +00:00
Jesse Wierzbinski 4b51985149
chore: 📦 Update packages 2024-05-08 08:15:11 +00:00
Jesse Wierzbinski c7423d7421
fix(api): 🐛 Fix slightly incorrect error message when logging in with wrong credentials 2024-05-08 08:09:22 +00:00
Jesse Wierzbinski f9c9a7d527
feat(api): 🎨 Allow login with either username or email 2024-05-08 08:02:05 +00:00
Jesse Wierzbinski 47c88dd7dd
fix(cli): 🐛 Remove plugin-help from oclif as it was causing bundling errors 2024-05-08 07:26:17 +00:00
Jesse Wierzbinski 19c14ef3fc
fix(cli): 🐛 Remove file extension from oclif entrypoint config
Allows both .ts and .js to be used (in dev and when bundled)
2024-05-08 00:39:34 +00:00
Jesse Wierzbinski a1fc86761d
build(cli): 🐛 Add package.json into build to make oclif happy 2024-05-08 00:35:00 +00:00
Jesse Wierzbinski 04cd140f6d
fix(cli): 🐛 Fix CLI not working in build
Missing code in cli/index.ts does that to you
2024-05-08 00:30:45 +00:00
Jesse Wierzbinski 6b17b91235
fix(build): 🐛 Modify CLI to properly bundle 2024-05-08 00:24:21 +00:00
Jesse Wierzbinski 0d278e4fa9
build(build): 🎨 Edit build script to look nicer and build CLI 2024-05-08 00:10:42 +00:00
Jesse Wierzbinski fc06b35c09
feat(cli): Add new CLI commands, move to project root 2024-05-08 00:10:14 +00:00
Jesse Wierzbinski 68f16f9101
ci(build): 🔒 Add SBOM and provenance data to all automatic Docker builds 2024-05-07 23:49:47 +00:00
Jesse Wierzbinski a621ff7271
fix(build): 🐛 Fix a bug preventing building caused by an old build command being used in Dockerfile 2024-05-07 23:42:38 +00:00
Jesse Wierzbinski 06c30b8af2
feat(cli): ♻️ Begin new CLI rewrite with oclif 2024-05-07 07:41:02 +00:00
Jesse Wierzbinski 7b05a34cce
refactor: 🔥 Remove dead code 2024-05-07 03:13:37 +00:00
Jesse Wierzbinski 592f7c0ac2
docs: 📝 Update docker-compose to make Lysand default to the latest tag 2024-05-06 19:23:32 +00:00
Jesse Wierzbinski af354a5fb8
docs: 📝 Update README to talk about Markdown support in Lysand 2024-05-06 19:20:41 +00:00
Jesse Wierzbinski b244889fd2
docs: 📝 Update docker-compose to add api host env variable to frontend 2024-05-06 19:17:33 +00:00
Jesse Wierzbinski 2f578de01a
docs: 📝 Update docs 2024-05-06 18:26:56 +00:00
Jesse Wierzbinski c22158c687
chore(build): 🐛 Fix Dockerfile, update bun-node version 2024-05-06 17:57:35 +00:00
Jesse Wierzbinski 8822aae0d3
chore: 📦 Update dependencies 2024-05-06 17:52:03 +00:00
Jesse Wierzbinski ad4466a260
fix(api): 🐛 Fix proxy returning incorrect media due to compression 2024-05-06 17:50:50 +00:00
Jesse Wierzbinski 8557867ad8
fix(api): 🐛 Fix incorrect proxy behaviour 2024-05-06 17:31:12 +00:00
Jesse Wierzbinski afda1f1211
fix(api): 🐛 Fix incorrect boolean/string comparisons in status creation endpoint 2024-05-06 09:20:23 +00:00
Jesse Wierzbinski 2779b76f44
fix(api): 🐛 Fix various data encoding bugs 2024-05-06 09:14:43 +00:00
Jesse Wierzbinski de4381e151
fix(api): 🐛 Respond to OPTIONS requests with empty CORS response 2024-05-06 08:54:57 +00:00
Jesse Wierzbinski e6749d9b72
fix(api): 🔥 Correctly coerce limit to an int in account statuses endpoint 2024-05-06 08:47:26 +00:00
Jesse Wierzbinski 31ef6865d8
refactor: 🧑‍💻 Add cloc to devcontainer 2024-05-06 08:46:22 +00:00
Jesse Wierzbinski e249b61969
fix(api): 🐛 Add jsonOrForm to /oauth/token 2024-05-06 08:42:58 +00:00
Jesse Wierzbinski ddab167018
fix(api): 🐛 Fix incorrect OAuth changes 2024-05-06 08:40:26 +00:00
Jesse Wierzbinski d5076590c6
fix(api): 🐛 Fix incorrect providers being returned by oauth providers endpoint 2024-05-06 08:36:00 +00:00
Jesse Wierzbinski 516bfb72e7
fix(build): 🐛 Add bodyOrJson middleware to server/api/v1/apps 2024-05-06 08:31:12 +00:00
Jesse Wierzbinski 959dd27ad6
refactor(api): 🎨 Finish Hono refactor 2024-05-06 08:19:42 +00:00
Jesse Wierzbinski 826a260e90
refactor(api): ♻️ Move to Hono for HTTP 2024-05-06 07:16:33 +00:00
Jesse Wierzbinski 2237be3689
chore: 📝 Update README and License 2024-05-05 11:35:27 -10:00
Jesse Wierzbinski f006efbfb2
fix(api): 🔥 Remove pleroma attribute on users 2024-05-05 10:55:40 -10:00
Jesse Wierzbinski 5f785c391d
refactor(api): 🎨 Switch to base64url for proxy url encoding instead of plaintext 2024-05-04 21:02:25 -10:00
Jesse Wierzbinski 3be9d1d6ce
fix(api): 🐛 Also wrap instance banner and thumbnail in proxy 2024-05-04 19:22:21 -10:00
Jesse Wierzbinski 972bd4f4a2
chore(build): 📦 Update Bun and packages 2024-05-04 19:19:07 -10:00
Jesse Wierzbinski 550e8977cf
fix(api): 🐛 Fix media proxy having incorrect headers 2024-05-04 19:17:57 -10:00
Jesse Wierzbinski ead34b818f
feat(api): 🔒 Make all media be proxied through an internal proxy 2024-05-04 19:13:23 -10:00
Jesse Wierzbinski 9547cd097a
fix(api): 🐛 Disable custom security headers on frontends 2024-05-05 02:30:29 +00:00
Jesse Wierzbinski d73ff674a1
feat: 🧑‍💻 Add Devcontainers support 2024-05-05 02:30:10 +00:00
Jesse Wierzbinski 6a0188c93e
chore: 🔨 Add character count script 2024-05-02 19:20:32 -10:00
Jesse Wierzbinski 154f17ab12
refactor(api): 📦 Change sanitizer from DOMPurify to xss 2024-05-02 17:20:24 -10:00
Jesse Wierzbinski a430db5c30
fix(build): 🐛 Fix happy-dom 2024-05-02 15:29:36 -10:00
Jesse Wierzbinski 4f0db2dfba
chore: Remove jsdom and types 2024-05-02 14:55:29 -10:00
Jesse Wierzbinski 5ef7564ee8
fix(build): 🐛 aaa 2024-05-02 14:44:49 -10:00
Jesse Wierzbinski c251853194
fix(build): 🐛 fuck youuu JSDom 2024-05-02 14:39:33 -10:00
Jesse Wierzbinski 4058ddc08e
fix(build): 🐛 Move JSDom to be external 2024-05-02 14:33:35 -10:00
Jesse Wierzbinski d884c8cff2
fix(build): 🐛 fuck you JSDom 2024-05-02 14:25:20 -10:00
Jesse Wierzbinski 74873fe924
fix(api): 🚑 Replace isomorphic-dompurify with plain jsdom and dompurify 2024-05-02 14:21:09 -10:00
Jesse Wierzbinski a339b7fa94
fix(frontend): 🐛 Add unsafe-inline to CSP for frontend 2024-05-02 14:05:14 -10:00
Jesse Wierzbinski 74b9083551
fix(api): 🚑 Fix incorrect Content-Security-Policy on frontend 2024-05-02 13:57:36 -10:00
Jesse Wierzbinski 7a90abeaec
fix: 🎨 Switch from happy-dom to jsdom for HTML sanitization 2024-05-02 13:53:10 -10:00
Jesse Wierzbinski 68badc5caa
chore: 📦 Remove old isomorphic-dompurify dependency 2024-05-02 13:26:17 -10:00
Jesse Wierzbinski febddc2a8b
feat(api): Reimplement HTML sanitization 2024-05-02 13:25:32 -10:00
Jesse Wierzbinski cac726ac1b
refactor(api): 🎨 Add better headers when serving API requests and client requests 2024-05-02 12:46:21 -10:00
Jesse Wierzbinski 4077f937b4
chore(build): 📦 Revert bun-node version to 1.1.5 2024-05-01 19:04:22 -10:00
Jesse Wierzbinski 035d90c763
chore: 📦 Update packages and Bun version 2024-05-01 18:59:39 -10:00
Jesse Wierzbinski d2d8151f35
test(api): Fix failing OAuth test (bug) 2024-05-01 18:58:07 -10:00
Jesse Wierzbinski 76b29aef9a
fix(api): 🐛 Only send code query parameter when doing OAuth redirects 2024-05-01 18:49:33 -10:00
Jesse Wierzbinski 166048479e
docs: 📝 Update docs 2024-05-01 18:45:27 -10:00
Jesse Wierzbinski 0baa9dd12d
fix(api): 🐛 Fix OAuth login bugs 2024-05-01 18:34:24 -10:00
Jesse Wierzbinski edf62aa015
fix(api): 🐛 Fix incorrect error being returned when registering goes wrong 2024-04-28 14:15:33 -10:00
Jesse Wierzbinski 2ea5612759
fix(api): 🐛 Error out on registration when email is already taken 2024-04-28 14:09:34 -10:00
Jesse Wierzbinski 065b37f091
fix(api): 🐛 Automatically trim every relevant API request field to remove extra whitespace 2024-04-28 14:05:07 -10:00
Jesse Wierzbinski aee47e6df4
fix(api): 🚑 Fix using an incorrect email or password giving weird errors 2024-04-28 13:47:14 -10:00
Jesse Wierzbinski 48f2fa1b94
chore: 📦 Update dependencies and Bun 2024-04-27 21:38:42 -10:00
Jesse Wierzbinski de0214c77e
fix(api): 🐛 Fix quote serialization in API again 2024-04-27 20:15:08 -10:00
Jesse Wierzbinski e8632caeac
fix(api): 🐛 Fix incorrect quote API serialization 2024-04-27 20:08:01 -10:00
Jesse Wierzbinski db35ba6f93
refactor(database): ♻️ Cleanup Notes database declaration 2024-04-26 11:19:01 -10:00
Jesse Wierzbinski a45a4b3652
fix(api): 🐛 Fix issues with quotes not being serialized to API properly 2024-04-26 11:18:37 -10:00
Jesse Wierzbinski b37921d0a3
fix(api): 🐛 Fix reblog notifications not having proper notes attached 2024-04-26 10:13:02 -10:00
Jesse Wierzbinski ce0cfb4152
chore: 🐛 Remove the -dev from package.json 2024-04-25 15:59:18 -10:00
Jesse Wierzbinski 761e81bd3f
chore: 🔖 Update Lysand version to 0.5-dev in package.json 2024-04-25 15:58:51 -10:00
Jesse Wierzbinski 50ea9461e2
feat(api): Put the correct lysand version everywhere, add a new lysand_version field in the instance metadata endpoints 2024-04-25 15:57:57 -10:00
Jesse Wierzbinski 03750d5e86
feat(api): Add banner attribute to instance metadata endpoints (v1 and v2) 2024-04-25 12:40:45 -10:00
Jesse Wierzbinski 1b7b71eaec
refactor(api): 🎨 Refactor request parser 2024-04-25 08:50:30 -10:00
Jesse Wierzbinski 3247e90131
chore: 🎨 Apply Biome format 2024-04-24 19:22:19 -10:00
Jesse Wierzbinski 3521dd5eb7
fix(api): 🐛 Properly sort users in account search by closeness to query 2024-04-24 19:21:44 -10:00
Jesse Wierzbinski 1f44405ac3
fix(api): Change spoofed Mastodon build to Glitch-Soc from vanilla mastodon 2024-04-24 18:49:20 -10:00
Jesse Wierzbinski 7976e4b810
fix(build): 🚑 Fix Lysand not starting due to missing sed command 2024-04-24 18:43:53 -10:00
Jesse Wierzbinski cde106a5db
feat(api): Add profile fields with emojis and Markdown to users 2024-04-24 18:37:55 -10:00
Jesse Wierzbinski 6373b8ae78
fix(api): 🐛 Spoof server as Mastodon 4.3.0 for clients that selectively enable features based off of the version 2024-04-24 18:31:27 -10:00
Jesse Wierzbinski 9e9998ea82
refactor(api): 🎨 Move createLocalUser to a static method of User 2024-04-24 17:48:39 -10:00
Jesse Wierzbinski 9d70778abd
refactor(api): 🎨 Move User methods into their own class similar to Note 2024-04-24 17:40:27 -10:00
Jesse Wierzbinski abc8f1ae16
refactor(api): 🎨 Improve Markdown parsing with markdown-it instead of marked 2024-04-22 11:02:09 -10:00
Jesse Wierzbinski 436e805789
chore: 📦 Update NPM dependencies 2024-04-22 09:56:31 -10:00
Jesse Wierzbinski 1aef094fc2
refactor(frontend): 🐛 Refactor frontend/glitch resolution strategy to prevent bugs 2024-04-22 09:48:18 -10:00
Jesse Wierzbinski 5dd6ea4d10
feat(frontend): Add Cache-Control header to frontends served 2024-04-21 22:37:34 -10:00
Jesse Wierzbinski 9834825184
feat(api): 🐛 Change consent route from /oauth/redirect to /oauth/consent 2024-04-21 21:36:45 -10:00
Jesse Wierzbinski 99822a716d
feat(federation): Add avatar attribute to WebFinger 2024-04-19 07:55:32 -10:00
Jesse Wierzbinski d892ff68fd
chore: 📦 Update packages, scripts and run linting 2024-04-17 23:04:07 -10:00
Jesse Wierzbinski 7d6f85d096
test(api): Give JWT key to GitHub Actions test build 2024-04-17 22:55:37 -10:00
Jesse Wierzbinski 5cb48b2f3b
feat(api): Make Lysand a full OAuth2/OpenID Connect provider as well as still Mastodon compatible 2024-04-17 22:42:12 -10:00
Jesse Wierzbinski f9f4a99cb9
fix(api): 🐛 Fix incorrect db fetching code breaking OAuth2 2024-04-17 15:56:17 -10:00
Jesse Wierzbinski 9804180123
fix(api): 🐛 Fix /api/v1/instance wrong SQL query causing 500s 2024-04-17 15:55:53 -10:00
Jesse Wierzbinski 203ea4b482
refactor(database): 🐛 Don't allow token userId to be null 2024-04-17 15:54:30 -10:00
Jesse Wierzbinski 633e92d4e9
feat: Allow specifying custom TLS certificate, key and CA 2024-04-17 15:53:42 -10:00
Jesse Wierzbinski a37e8e92c5
feat(api): Implement filters API v2 (with some routes missing) 2024-04-17 13:47:03 -10:00
Jesse Wierzbinski ce082f8e6a
fix(federation): 🐛 Fix objects endpoint not returning correctly formatted element 2024-04-17 12:47:26 -10:00
Jesse Wierzbinski 534a6136c1
test: 💚 Fix wrong config value causing CI tests to fail 2024-04-16 22:40:54 -10:00
Jesse Wierzbinski 3e43d130a0
ci: 📦 Update checkout action to v4 2024-04-16 22:30:24 -10:00
Jesse Wierzbinski 1266c46a61
ci: 🐛 Remove cosign signing (broken right now) 2024-04-16 22:27:31 -10:00
Jesse Wierzbinski ebcd38870f
ci: 🎨 Make CI Docker build more traditional, and probably work again too 2024-04-16 22:24:31 -10:00
Jesse Wierzbinski 7e0cc9e0a8
docs: 📝 Reformat lists of endpoints 2024-04-16 22:02:16 -10:00
Jesse Wierzbinski f5591b2b13
fix(build): 🐛 Revert bun-node container version to 1.1.3 (1.1.4 does not exist yet) 2024-04-16 21:10:47 -10:00
Jesse Wierzbinski 0929683c51
chore: 📦 Update all dependencies to latest version and Bun to 1.1.4 2024-04-16 21:09:28 -10:00
Jesse Wierzbinski bf0153627e
feat(api): Implement /api/v1/markers 2024-04-16 21:04:03 -10:00
Jesse Wierzbinski 88b3ec7b43
refactor(database): 🎨 Update database and schema names to be clearer 2024-04-16 20:36:01 -10:00
Jesse Wierzbinski 9081036c6d
refactor(database): 🎨 Refactor note handling into its own class instead of separate functions 2024-04-16 18:09:21 -10:00
Jesse Wierzbinski 2998cb4deb
fix(frontend): 🐛 Fix incorrect branding on glitch-soc 2024-04-16 11:36:45 -10:00
Jesse Wierzbinski fc4e0d1958
docs(frontend): 📝 Add docs on how to enable the use of the glitch-soc 2024-04-16 11:34:21 -10:00
Jesse Wierzbinski d441fca1a1
fix(federation): 🐛 Fix wrong URI being generated in federated posts 2024-04-16 11:20:18 -10:00
Jesse Wierzbinski 47040ad273
feat(federation): Allow objects to be fetched via their ID 2024-04-16 11:18:47 -10:00
Jesse Wierzbinski 895826a5f8
fix(frontend): 🐛 Fix missing Lysand branding on glitch-fe 2024-04-16 07:24:57 -10:00
Jesse Wierzbinski 8b429fada6
fix(cli): 🚑 Make cli work again (wasn't connecting to database so it would hang) 2024-04-15 22:47:48 -10:00
Jesse Wierzbinski 214f4d5a3e
refactor(frontend): 🎨 Make code look better 2024-04-15 22:15:52 -10:00
Jesse Wierzbinski 6a419a2015
fix(api): 🐛 Fix incorrect function order causing Lysand branding not to be applied in glitch-soc 2024-04-15 21:54:39 -10:00
Jesse Wierzbinski 852a393c78
style(api): 🎨 Run Biome 2024-04-15 21:47:16 -10:00
Jesse Wierzbinski 7bf5d628b6
refactor(frontend): 🎨 Make glitch-soc server prettier 2024-04-15 21:46:49 -10:00
Jesse Wierzbinski 10b4378a68
feat(frontend): Implement glitch-soc logout 2024-04-15 21:23:06 -10:00
Jesse Wierzbinski 59455f9ece
refactor(build): 🎨 Make build routes automatically scanned rather than manually added 2024-04-15 21:13:34 -10:00
Jesse Wierzbinski 87d4473276
fix(api): 🐛 Add new notifications route to routes file 2024-04-15 20:50:01 -10:00
Jesse Wierzbinski 5030d03404
feat(api): Implement glitch-soc /v1/notifications/destroy_multiple route 2024-04-15 20:48:36 -10:00
Jesse Wierzbinski 6dff872822
fix(api): 🐛 Add new routes to routes file 2024-04-15 20:27:49 -10:00
Jesse Wierzbinski 94f9586592
fix(frontend): 🎨 Make the glitch-soc session cookie last a week instead of for the session 2024-04-15 20:09:38 -10:00
Jesse Wierzbinski 245d4844f5
test(api): 🔥 Clean up old duplicated tests 2024-04-15 20:04:13 -10:00
Jesse Wierzbinski 0ca8000186
feat(api): Add dismiss, id and clear API endpoints for notifications 2024-04-15 20:00:40 -10:00
Jesse Wierzbinski 47133ac3fe
feat(api): Add notifications for follow requests again and mentions 2024-04-15 19:40:35 -10:00
Jesse Wierzbinski 06bcbbe451
fix(api): 🐛 Fix statuses not saving the user's applicationId 2024-04-15 16:09:16 -10:00
Jesse Wierzbinski a5a5d57c81
test(api): 🎨 Remove temporary code 2024-04-15 15:02:59 -10:00
Jesse Wierzbinski 6063b3ff44
fix(api): 🐛 Fix string query values being incorrectly casted as booleans 2024-04-15 15:02:25 -10:00
Jesse Wierzbinski 937b2c3cde
refactor: 🎨 Remove useless function parameter (status.instanceId doesnt exist anymore) 2024-04-15 14:41:33 -10:00
Jesse Wierzbinski 19f442ec65
fix(api): 🐛 Fix incorrect database columns in status queries
Column instanceId of status didn't actually do anything and it was removed
2024-04-15 14:40:40 -10:00
Jesse Wierzbinski 8fc725639c
refactor(frontend): 🎨 Change glitch-soc cookie name to _session_id 2024-04-15 13:22:46 -10:00
Jesse Wierzbinski 866cd4345d
feat(frontend): Allow glitch-soc users to login to their account 2024-04-15 13:20:39 -10:00
Jesse Wierzbinski de60f37393
fix(frontend): 🐛 Improve glitch support by rewriting served files more 2024-04-15 11:20:18 -10:00
Jesse Wierzbinski ffc45c5869
fix(database): 🐛 Fix incorrect column name used in queries 2024-04-15 09:01:51 -10:00
Jesse Wierzbinski 972ced1f10
feat(frontend): Finish glitch frontend implementation 2024-04-15 08:50:06 -10:00
Jesse Wierzbinski e5e8099883
fix(api): 🐛 Fix rules being duplicated in API
Having default values merged with the existing config was incorrectly causing extra values to appear in rules
2024-04-15 08:22:56 -10:00
Jesse Wierzbinski a1c261f47d
feat(api): 🐛 Add hint attributes to rules to satisfy glitch-soc 2024-04-15 08:18:20 -10:00
Jesse Wierzbinski 71d2c7ae3b
feat(api): Add rules to /api/v2/instance 2024-04-15 08:03:10 -10:00
Jesse Wierzbinski 9e3e02cabd
refactor(frontend): 🎨 Make glitch-soc be served on / not on /web 2024-04-15 00:54:35 -10:00
Jesse Wierzbinski ff6a91f916
feat(frontend): Allow usage of glitch-soc as frontend (alpha) 2024-04-15 00:46:19 -10:00
Jesse Wierzbinski 1aacf7d743
feat(api): 🐛 Provide non-static avatar and header URL for users when a static version does not exist 2024-04-14 21:59:40 -10:00
Jesse Wierzbinski 95a79a4585
fix(api): 🐛 Make thumbnail url for attachments default to attachment url 2024-04-14 20:35:53 -10:00
Jesse Wierzbinski d6ce448c1c
fix(build): 🐛 Fix new routes not being added to build 2024-04-14 20:13:17 -10:00
Jesse Wierzbinski fe71f3628c
feat(api): Implement /api/v2/instance route 2024-04-14 20:10:18 -10:00
Jesse Wierzbinski 505273e064
fix: 🚑 Fix server not starting when built because of incorrect import 2024-04-14 19:13:11 -10:00
Jesse Wierzbinski 96a2fbf178
feat(api): Implement /v1/instance/rules and /v1/instance/extended_description 2024-04-14 19:08:16 -10:00
Jesse Wierzbinski 5b0d2014ff
fix(build): 🚑 Update build file to not fail
Build file was still depending on frontend being included with the project, which it is not anymore
2024-04-14 15:48:20 -10:00
Jesse Wierzbinski a7969f6ebd
refactor(frontend): 🔥 Move frontend out of this repository, allow any frontend to be used
Adds a new configuration option to put your frontend's URL
2024-04-14 15:35:56 -10:00
Jesse Wierzbinski ac3ef0ea06
fix(database): 🚑 Fixed migrations not running on fresh databases
Incorrect SQL data in migrations would cause freshly created database to fail migrations
2024-04-14 13:41:11 -10:00
Jesse Wierzbinski 2e2b91d7a5
docs: 📝 Updated documentation for Lysand 0.4
Updated outdated documentation in preparation for the release of Lysand 0.4
2024-04-14 13:33:02 -10:00
Gaspard Wierzbinski 5e9e05826b
Merge pull request #12 from lysand-org/coc-patch-1
[fix] add contributor contact info to COC
2024-04-14 11:59:35 -10:00
April John 8dd228352c
[fix] add contributor contact info to COC 2024-04-14 23:29:33 +02:00
Jesse Wierzbinski 402c3ad926
Remove bloat in logs, remove -o flag in entrypoint 2024-04-14 03:27:50 -10:00
Jesse Wierzbinski 939d93bfda
Add automatic decoding of URIs when parsing queries 2024-04-14 03:20:57 -10:00
Jesse Wierzbinski b43e563106
Add more notification types to keep Soapbox happy 2024-04-14 03:18:33 -10:00
Jesse Wierzbinski 76056f76d4
Fix notifications erroring in certain cases 2024-04-14 03:12:39 -10:00
Jesse Wierzbinski 55ea57391b
Correct wrong notification endpoint returns 2024-04-14 03:11:15 -10:00
Jesse Wierzbinski 372a209d32
Prevent getting notifications from yourself 2024-04-14 03:05:55 -10:00
Jesse Wierzbinski 325ecbfc53
Make status creation API more permissive 2024-04-14 03:01:56 -10:00
Jesse Wierzbinski 4cee92f22d
Will this fix it? 2024-04-14 02:56:20 -10:00
Jesse Wierzbinski c756686de5
please sir can i have some more logging 2024-04-14 02:53:31 -10:00
Jesse Wierzbinski 38b598b6b7
Logggg 2024-04-14 02:47:04 -10:00
Jesse Wierzbinski 5d4af4adbd
Fixes for incorrect parsing of FormData 2024-04-14 02:37:37 -10:00
Jesse Wierzbinski f8309ca3c1
temporarily log request data 2024-04-14 02:30:47 -10:00
Jesse Wierzbinski 89590d5a3d
Remove old logs 2024-04-14 02:24:42 -10:00
Jesse Wierzbinski 013f0b4459
Also add to other layer 2024-04-14 02:19:04 -10:00
Jesse Wierzbinski 94f91b41cd
Add libstdc++ to container builds 2024-04-14 02:18:17 -10:00
Jesse Wierzbinski 44b99a9b4d
I lied i logged again 2024-04-14 02:13:02 -10:00
Jesse Wierzbinski 4db9b1c544
Last log i promise 2024-04-14 02:12:32 -10:00
Jesse Wierzbinski 047dda076b
More logging! 2024-04-14 02:10:00 -10:00
Jesse Wierzbinski f94fffd434
Fix incorrect validation of route 2024-04-14 02:03:22 -10:00
Jesse Wierzbinski 86dd0eb7ef
why is this broken 2024-04-14 01:57:26 -10:00
Jesse Wierzbinski e575075006
More logging 2024-04-14 01:52:50 -10:00
Jesse Wierzbinski da09d10e9a
More debug logging 2024-04-14 01:46:39 -10:00
Jesse Wierzbinski 8da0f55869
Add more debug logging 2024-04-14 01:44:17 -10:00
Jesse Wierzbinski 8939d17b8a
Disable minification for debugging 2024-04-14 01:37:32 -10:00
Jesse Wierzbinski e67dc07473
Fix errors flagged by Biome 2024-04-14 01:22:47 -10:00
Jesse Wierzbinski 27354f2d74
Delete old type files 2024-04-14 01:22:02 -10:00
Jesse Wierzbinski ab6fe6988c
Refactor debugging and logging more 2024-04-14 01:20:55 -10:00
Jesse Wierzbinski 82c6dc17a8
Update Mastodon API types 2024-04-14 00:53:21 -10:00
Jesse Wierzbinski 58cd284a84
Delete old Prisma folder 2024-04-14 00:37:06 -10:00
Jesse Wierzbinski 0b1c1ba128
Switch all routes to use Zod for strict validation 2024-04-14 00:36:25 -10:00
Jesse Wierzbinski 53fa9ca545
Code cleanup, refresh lockfile 2024-04-13 22:16:03 -10:00
Jesse Wierzbinski bc051ed043
Code cleanup, add color and pretty dates to LogManagers 2024-04-13 22:12:41 -10:00
Jesse Wierzbinski 327a716b12
Add new ServerHandler package which handles requests 2024-04-13 21:51:00 -10:00
Jesse Wierzbinski 3cdd685035
Clean up old console.log statements 2024-04-13 19:27:19 -10:00
Jesse Wierzbinski 354493133c
Reorganize FE 2024-04-13 19:26:29 -10:00
Jesse Wierzbinski e27a80c40a
Cleanup Nitro config 2024-04-13 18:19:30 -10:00
Jesse Wierzbinski 6bff15f6d6
Cleanup Dockerfile 2024-04-13 18:15:15 -10:00
Jesse Wierzbinski 4a3de1fd9e
Replace Bash with POSIX sh in Docker image 2024-04-13 18:14:09 -10:00
Jesse Wierzbinski 5737ed43cb
Change Docker container to use Alpine (without Musl) 2024-04-13 18:10:53 -10:00
Jesse Wierzbinski fe0cfa547b
Cleanup files and packages 2024-04-13 18:10:37 -10:00
Jesse Wierzbinski bc296194b6
Replaces regexes with magic-regexp, simplify code 2024-04-13 17:49:32 -10:00
Jesse Wierzbinski b1ee6e5684
Finish full migration to Drizzle 2024-04-13 15:26:19 -10:00
Jesse Wierzbinski 0ca77e9dcc
Clean up database with new schema 2024-04-13 15:21:38 -10:00
Jesse Wierzbinski a65249b79d
Remove Prisma once and for all 2024-04-13 14:46:33 -10:00
Jesse Wierzbinski 90d522eaa3
Convert remaining routes to Drizzle 2024-04-13 14:07:05 -10:00
Jesse Wierzbinski 05e45ff5aa
More conversions to Drizzle 2024-04-13 02:24:57 -10:00
Jesse Wierzbinski ad0bf1a350
More work on converting old Prisma calls to Drizzle 2024-04-13 02:20:12 -10:00
Jesse Wierzbinski 66922faa51
Fix error caused by no emojis on a federated post 2024-04-11 18:31:51 -10:00
Jesse Wierzbinski 0af63dda3c
fix: Null value being set in updatedAt column when creating user 2024-04-11 18:23:36 -10:00
Jesse Wierzbinski 87cf7d6408
Add warning if Content-Type header is missing 2024-04-11 18:19:04 -10:00
Jesse Wierzbinski 2b02cfa00a
Don't display full host in mentions if user is local 2024-04-11 15:52:09 -10:00
Jesse Wierzbinski a1b251dfdf
Bugfix quote posts with mentions not working 2024-04-11 13:55:58 -10:00
Jesse Wierzbinski 310f8d2739
Mom, I'm debugging in production again! 2024-04-11 13:43:31 -10:00
Jesse Wierzbinski ed58b7e67f
Remove wrong test 2024-04-11 13:13:46 -10:00
Jesse Wierzbinski 3ccff003f5
Add more tests, fix roiutes 2024-04-11 13:12:23 -10:00
Jesse Wierzbinski 0469187876
Begin work on sending emails 2024-04-11 11:50:05 -10:00
Jesse Wierzbinski a4f6ce42c6
Don't accidentally send mixed content to the client 2024-04-11 04:01:12 -10:00
Jesse Wierzbinski 6b3c604c33
Add new tests to server routes 2024-04-11 03:52:44 -10:00
Jesse Wierzbinski 6263c667e8
Wrong database names and columns used 2024-04-11 02:18:46 -10:00
Jesse Wierzbinski df939a6a7a
Fix not working routes 2024-04-11 02:12:16 -10:00
Jesse Wierzbinski f7abe06a60
Begin moving project to use Drizzle instead of prisma 2024-04-11 01:39:07 -10:00
Jesse Wierzbinski b107bed935
Reduce siwe of frontend 2024-04-10 17:05:05 -10:00
Jesse Wierzbinski dcdee7e4bf
Fix emoji parsing in the remote emoji fetcher 2024-04-10 16:13:09 -10:00
Jesse Wierzbinski 275244b941
Resolve custom emojis from federated posts 2024-04-10 15:40:43 -10:00
Jesse Wierzbinski ec7b5dcbab
Add fetching of attachments when fetching a remote post 2024-04-10 15:31:33 -10:00
Jesse Wierzbinski 5024eee5db
Safeguard for local users 2024-04-10 12:47:44 -10:00
Jesse Wierzbinski b076d61d36
Add automatic WebFinger resolution for users that are not found in mentions 2024-04-10 12:47:02 -10:00
Jesse Wierzbinski 742913a911
Don't replace text mentions twice 2024-04-10 12:41:06 -10:00
Jesse Wierzbinski fde0ff509e
Fixes for mentions being wrong 2024-04-10 12:21:42 -10:00
Jesse Wierzbinski 63f046d281
one last fix please 2024-04-09 23:47:11 -10:00
Jesse Wierzbinski 607711c8b4
Other fix 2024-04-09 23:41:29 -10:00
Jesse Wierzbinski d444f53286
Last fix for today 2024-04-09 23:38:48 -10:00
Jesse Wierzbinski 1c8847ac6d
Few bugfixes 2024-04-09 23:33:21 -10:00
Jesse Wierzbinski 35438860c2
Drop useless database fields 2024-04-09 23:33:13 -10:00
Jesse Wierzbinski f490cfce78
Add more metadata to instance endpoint 2024-04-09 22:54:36 -10:00
Jesse Wierzbinski 38a6f9a809
Add resolving of threads, mentions and quote posts 2024-04-09 22:37:58 -10:00
Jesse Wierzbinski cf295a596a
Add ability to accept and reject remote follows if account is locked 2024-04-09 22:07:03 -10:00
Jesse Wierzbinski f72671fb07
Folreq fix 2024-04-09 21:54:15 -10:00
Jesse Wierzbinski dbb96027b8
going hogwild with the logging 2024-04-09 21:45:20 -10:00
Jesse Wierzbinski fc492c827b
More logging enabling 2024-04-09 21:36:28 -10:00
Jesse Wierzbinski 820d05c997
Add FollowAccept handling 2024-04-09 21:24:23 -10:00
Jesse Wierzbinski 27a287ab4d
Wrong order in follower acceptance 2024-04-09 21:18:41 -10:00
Jesse Wierzbinski 1a27be9542
Fix federation bug preventing proper federation 2024-04-09 21:13:45 -10:00
Jesse Wierzbinski b92d8256a4
Logging 2024-04-09 21:04:46 -10:00
Jesse Wierzbinski b30dd98f73
Add more debug data 2024-04-09 20:57:29 -10:00
Jesse Wierzbinski 80d592de48
Add other thing to logger 2024-04-09 20:51:09 -10:00
Jesse Wierzbinski 985190c683
Fix to unfollow route 2024-04-09 20:42:07 -10:00
Jesse Wierzbinski 8bcf46641c
Fix headers in Federation and User entities 2024-04-09 20:37:38 -10:00
Jesse Wierzbinski 34499bfecb
Return null on WebFinger 404 2024-04-09 20:27:16 -10:00
Jesse Wierzbinski cb85b4a1de
Only mark as followed in database if federation works 2024-04-09 20:22:36 -10:00
Jesse Wierzbinski 5aeb50b7d5
Fix promises not being awaited 2024-04-09 20:14:33 -10:00
Jesse Wierzbinski b1d7073217
Make lookup also work on local users 2024-04-09 20:13:17 -10:00
Jesse Wierzbinski 59cd8c9bd1
Add lookup Mastodon API route 2024-04-09 20:09:57 -10:00
Jesse Wierzbinski 06f98c36bb
Resolve user if not found when verifying signing 2024-04-09 19:59:36 -10:00
Jesse Wierzbinski 8ef8054351
Add more logging 2024-04-09 19:56:46 -10:00
Jesse Wierzbinski f56e4f623a
Add following 2024-04-09 19:51:00 -10:00
Jesse Wierzbinski 7da7febd00
Add status federation 2024-04-09 19:24:07 -10:00
Jesse Wierzbinski 4acc04cd93
Make WebFinger resolve work 2024-04-09 19:13:13 -10:00
Jesse Wierzbinski fcf952e1f3
Add Lysand well-known route 2024-04-09 18:33:35 -10:00
Jesse Wierzbinski d5817e985d
Modify WebFinger behaviour, add user searching 2024-04-09 18:22:57 -10:00
Jesse Wierzbinski ae9698c647
Add WebFinger endpoints 2024-04-09 17:45:19 -10:00
Jesse Wierzbinski ee6b6bce34
Fix incorrect MIME type when uploading emojis 2024-04-09 17:16:40 -10:00
Jesse Wierzbinski c26bf72542
Disable automatic builds on self-hosted runner for performance reasons 2024-04-09 17:10:30 -10:00
Jesse Wierzbinski 100a1f957b
Enable minification 2024-04-09 17:02:19 -10:00
Jesse Wierzbinski dc2fb029f5
Fix various file upload issues across server 2024-04-09 16:54:33 -10:00
Jesse Wierzbinski 724b11da4b
Fixes for Lysand types 2024-04-09 16:47:06 -10:00
Jesse Wierzbinski 4ce0e06e41
Remove old console.log 2024-04-09 16:46:59 -10:00
Jesse Wierzbinski 86278563d6
Re-add missing Prisma part 2024-04-09 16:14:05 -10:00
Jesse Wierzbinski a58c81c8e9
Implement federation of statuses 2024-04-09 16:05:02 -10:00
Jesse Wierzbinski 8563c97403
Fix conversion between database and Lysand types 2024-04-09 13:54:10 -10:00
Jesse Wierzbinski 6d0a8a6478
Add Lysand types as package 2024-04-09 04:16:09 -10:00
Jesse Wierzbinski 8ecdc6261e
Make all media be uploaded with a unique hash 2024-04-09 03:51:22 -10:00
Jesse Wierzbinski be6b692a7b
Update Blurhash algorithm 2024-04-09 03:18:04 -10:00
Jesse Wierzbinski b91eb110cc
Check for width and height before making blurhash 2024-04-09 03:08:48 -10:00
Jesse Wierzbinski bf169623c9
Remove libvips installation 2024-04-09 03:06:18 -10:00
Jesse Wierzbinski 7439a5f2c7
Remove useless line 2024-04-09 03:04:06 -10:00
Jesse Wierzbinski 78089fbbe7
Fix for ARM building 2024-04-09 03:00:48 -10:00
Jesse Wierzbinski eab8b1ab63
Change Sharp versions 2024-04-09 02:51:03 -10:00
Jesse Wierzbinski 27260dff68
Fixes for different base_url and bind url 2024-04-09 02:05:54 -10:00
Jesse Wierzbinski 8ec34f7138
Remove old pages/ directory 2024-04-09 01:55:03 -10:00
Jesse Wierzbinski 577b866bb3
Refactor API URL configuration 2024-04-09 01:48:13 -10:00
Jesse Wierzbinski d9198cfddf
Replace URL with HTTP too 2024-04-09 01:42:53 -10:00
Jesse Wierzbinski e552a32f24
Update file paths in entrypoint.sh 2024-04-09 01:29:12 -10:00
Jesse Wierzbinski e59f82fa16
Revert a Dockerfile line 2024-04-09 01:22:11 -10:00
Jesse Wierzbinski 077d686d19
More Docker fixes 2024-04-09 01:20:23 -10:00
Jesse Wierzbinski bfd394c21e
Fix docker build 2024-04-09 01:17:53 -10:00
Jesse Wierzbinski dc17cffd75
Switch frontend server to Nuxt 2024-04-09 01:14:53 -10:00
Jesse Wierzbinski 9476770cdb
Make mentions appear in new posts 2024-04-08 22:54:39 -10:00
Jesse Wierzbinski b5f31fc4e4
Prevent incorrect username registration 2024-04-08 22:40:57 -10:00
Jesse Wierzbinski 39a365e15a
Work on prettier UI and more errors 2024-04-08 20:51:52 -10:00
Jesse Wierzbinski db37510370
Add interface to view post and user JSON data 2024-04-08 18:33:59 -10:00
Jesse Wierzbinski 342a8011f1
Fix for follower/following timelines being wrong 2024-04-08 16:40:35 -10:00
Jesse Wierzbinski 8bda61e099
Fixes for wrong follows 2024-04-08 16:26:48 -10:00
Jesse Wierzbinski 6c60191ab2
Add follow notifications and follow request 2024-04-08 16:12:54 -10:00
Jesse Wierzbinski 5afa0c334a
Remove unnecessary undefined 2024-04-08 15:49:54 -10:00
Jesse Wierzbinski ba19eda09d
Fix for notifications showing up to the wrong users 2024-04-08 15:49:33 -10:00
Jesse Wierzbinski 1438387362
Disable CSP on client pages 2024-04-08 13:30:22 -10:00
Jesse Wierzbinski 958ede4074
Update lockfile 2024-04-08 13:27:07 -10:00
Jesse Wierzbinski d82cfb0d80
Allow forms to be submitted (whoops) 2024-04-08 13:24:49 -10:00
Jesse Wierzbinski 41d8ed4eea
Put old Sharp version back 2024-04-07 18:41:15 -10:00
Jesse Wierzbinski d6fda6bb28
Update version to 0.3.1 2024-04-07 18:24:22 -10:00
Jesse Wierzbinski 78734dc8d5
Fix image URLs being wrong 2024-04-07 18:07:11 -10:00
Jesse Wierzbinski e4f82e2fa9
Add new default placeholder avatars 2024-04-07 17:55:12 -10:00
Jesse Wierzbinski 6917def011
Incorrent content-type sent for clients 2024-04-07 17:37:30 -10:00
Jesse Wierzbinski 58613c958c
Typo 2024-04-07 17:30:11 -10:00
Jesse Wierzbinski e26d604a54
Refactors, bugfixing 2024-04-07 17:28:18 -10:00
Jesse Wierzbinski 5812618170
Fix incorrect order causing wrong timeline Link headers 2024-04-07 16:36:14 -10:00
Jesse Wierzbinski d3a625e084
Fix pagination bug 2024-04-07 16:32:45 -10:00
Jesse Wierzbinski e0335c33a9
Timeline refactors 2024-04-07 16:24:18 -10:00
Jesse Wierzbinski 69ffd5fafc
fixes 2024-04-07 12:36:26 -10:00
Jesse Wierzbinski 391da7f799
More Link header shenanigans 2024-04-07 12:33:53 -10:00
Jesse Wierzbinski 564b47c21a
Fix Link header on account statuses 2024-04-07 12:29:31 -10:00
Jesse Wierzbinski 48ff510889
relax notification limit 2024-04-07 12:13:05 -10:00
Jesse Wierzbinski 2c704bd57c
Update ID validation to use UUIDv7 format 2024-04-07 12:08:14 -10:00
Jesse Wierzbinski 02c63c4c6f
Fixes for UUID errors 2024-04-07 12:03:38 -10:00
Jesse Wierzbinski 61723305e5
Fix for misbehaving clients 2024-04-07 11:44:36 -10:00
Jesse Wierzbinski e72a4e76d6
temporarily disable sanitization 2024-04-07 04:05:06 -10:00
Jesse Wierzbinski 36671b68b0
Add libvips install to container 2024-04-07 03:55:38 -10:00
Jesse Wierzbinski c85218ee9a
Add Sharp build files to Dockerfile 2024-04-07 03:53:52 -10:00
Jesse Wierzbinski 8eb6fba897
More Sharp fixes 2024-04-07 03:50:03 -10:00
Jesse Wierzbinski 8473062c24
More Sharp fixes 2024-04-07 03:28:04 -10:00
Jesse Wierzbinski 9618ded96a
Fix sharp install 2024-04-07 03:19:21 -10:00
Jesse Wierzbinski 8a40531d76
Include Sharp in Docker build 2024-04-07 03:14:51 -10:00
Jesse Wierzbinski 885ec12780
Build errors 2024-04-07 03:05:46 -10:00
Jesse Wierzbinski 0c720956a1
More bugfixes 2024-04-07 03:03:33 -10:00
Jesse Wierzbinski a6bec1efa7
Disable Pleroma fields on instance 2024-04-07 02:50:02 -10:00
Jesse Wierzbinski e71c2ef5c9
Fix wrong again in token date format 2024-04-07 02:47:19 -10:00
Jesse Wierzbinski 25d7a798ae
Update dates to ISO 2024-04-07 02:44:29 -10:00
Jesse Wierzbinski 0d373b8866
already used fix 2024-04-07 02:39:27 -10:00
Jesse Wierzbinski ba712a33f3
Absolute URI fixes 2024-04-07 02:33:55 -10:00
Jesse Wierzbinski 1115b72ca6
Fix JSON parse error with Megalodon 2024-04-07 02:30:45 -10:00
Jesse Wierzbinski 26596bb987
Bugfixes 2024-04-07 02:26:19 -10:00
Jesse Wierzbinski 0f07ca94a3
Fix CSP 2024-04-07 02:02:11 -10:00
Jesse Wierzbinski e20454bf58
Fix wrong CSP causing issues for HTTPS 2024-04-07 01:51:41 -10:00
Jesse Wierzbinski 4343a114a8
Fix pages not building 2024-04-07 01:45:15 -10:00
Jesse Wierzbinski 301189ba3e
Uncomment forgotten comment 2024-04-07 01:38:17 -10:00
Jesse Wierzbinski 1fae2ce63f
aaaaaaaa 2024-04-07 01:37:00 -10:00
Jesse Wierzbinski 04b76aaabc
Fix entrypoint 2024-04-07 01:34:21 -10:00
Jesse Wierzbinski afa760d893
actually run program 2024-04-07 01:29:32 -10:00
Jesse Wierzbinski 0dd4d2c88e
Fix wrong copy location 2024-04-07 01:03:57 -10:00
Jesse Wierzbinski fca06c6394
Copy Prisma folder in production 2024-04-07 01:02:54 -10:00
Jesse Wierzbinski 1124f83773
AHHH 2024-04-07 01:00:52 -10:00
Jesse Wierzbinski bd96cfc83f
more horrific, horrific build patching 2024-04-07 00:58:17 -10:00
Jesse Wierzbinski 6a358ce898
Update Prisma binary execution path 2024-04-07 00:45:20 -10:00
Jesse Wierzbinski 79f278e0bf
Add migrations to start script 2024-04-07 00:42:06 -10:00
Jesse Wierzbinski 742edb24b5
another fix 2024-04-07 00:35:27 -10:00
Jesse Wierzbinski 21711960df
Update Dockerfile and LogManager 2024-04-07 00:18:21 -10:00
Jesse Wierzbinski ae2173e8b1
Update Docker labels and binaryTargets 2024-04-06 23:34:16 -10:00
Jesse Wierzbinski 257243aa0c
Fix Docker build again 2024-04-06 23:22:45 -10:00
Jesse Wierzbinski ea1d7b1510
More work on fixing Docker build 2024-04-06 22:56:15 -10:00
Jesse Wierzbinski 015177e3a2
Fix wrong command in Dockerfile 2024-04-06 21:05:21 -10:00
Jesse Wierzbinski dfc4b624a4
Update shebang to use bash instead of sh 2024-04-06 20:50:08 -10:00
Jesse Wierzbinski a821e89722
Allow GitHub actions to write to container registry 2024-04-06 20:27:09 -10:00
Jesse Wierzbinski e88c5f3fd0
Finally make the Docker build work 2024-04-06 20:13:09 -10:00
Jesse Wierzbinski b580d1a24a
Remove old ESLint test action 2024-04-06 19:36:53 -10:00
Jesse Wierzbinski af0d627f19
Replace eslint and prettier with Biome 2024-04-06 19:30:49 -10:00
Jesse Wierzbinski 4a5a2ea590
Add Biome 2024-04-06 18:45:05 -10:00
Jesse Wierzbinski 43cce22c07
Update packages 2024-04-06 18:19:55 -10:00
Jesse Wierzbinski 6a54c5b805
Replace config manager with unjs/c12 2024-04-06 18:16:54 -10:00
Jesse Wierzbinski 6b2e4044b6
Create logfile if it doesnt exist 2024-04-06 17:50:32 -10:00
Jesse Wierzbinski 53cd73262c
Add screenshots of Lysand's web client for desktop and mobile 2024-03-13 18:04:49 -10:00
Jesse Wierzbinski d6f1cd1347
Fix build errors and testing errors 2024-03-13 17:39:32 -10:00
Jesse Wierzbinski f02344fa0d
Add more OAuth scopes to current routes 2024-03-13 17:03:05 -10:00
Jesse Wierzbinski 9ec3d96f9d
Add new OAuth verification page 2024-03-13 17:02:50 -10:00
Jesse Wierzbinski 626b2cb311
Preliminary multi-protocol support work 2024-03-13 12:02:01 -10:00
Jesse Wierzbinski e227522c55
Fix type error 2024-03-13 07:36:43 -10:00
Jesse Wierzbinski 501b8bf78a
Add automatic log folder creation 2024-03-13 07:28:12 -10:00
Jesse Wierzbinski 626bc03dbd
Update README about new Postgres images 2024-03-13 06:36:38 -10:00
Jesse Wierzbinski 9579ddacfb
Re-enable minification 2024-03-13 06:35:11 -10:00
Jesse Wierzbinski 480fcb363f
Add bait mode, fix bugs 2024-03-12 22:10:32 -10:00
Jesse Wierzbinski d633116571
Fix failing tests, reorganize packages 2024-03-12 08:44:43 -10:00
Jesse Wierzbinski 83288afd88
Wrong variable 2024-03-12 08:37:20 -10:00
Jesse Wierzbinski 4a559e290e
Fix cli parser bug where it wouldn't add default config 2024-03-12 08:36:39 -10:00
Jesse Wierzbinski b8d2f8a940
Update base_url and bind in config.workflow.toml 2024-03-12 08:33:17 -10:00
Jesse Wierzbinski 986cc8a89c
Try and fix some building issues 2024-03-12 08:27:50 -10:00
Jesse Wierzbinski d29915456c
Try again with the Lysand postgres image 2024-03-12 07:44:42 -10:00
Jesse Wierzbinski 0122794d83
Actions testing 2024-03-12 07:32:09 -10:00
Jesse Wierzbinski 1e0eb8b30b
test changing image 2024-03-11 22:16:44 -10:00
Jesse Wierzbinski 99ab5e2e56
Re-add healthcheck command 2024-03-11 22:03:33 -10:00
Jesse Wierzbinski b0ddba9bc8
Edit IP in workflow config 2024-03-11 22:00:46 -10:00
Jesse Wierzbinski bcaf09cf02
aaa 2024-03-11 21:59:24 -10:00
Jesse Wierzbinski 1fb1bbd5f1
Fix wrong host in config 2024-03-11 21:56:34 -10:00
Jesse Wierzbinski 43f36964c1
Remove healthcjheck from container 2024-03-11 21:55:11 -10:00
Jesse Wierzbinski 6c3cda9e6c
Add configuration to auto run tests in GitHub Actions 2024-03-11 21:48:08 -10:00
736 changed files with 165157 additions and 22277 deletions

18
.deepsource.toml Normal file
View file

@ -0,0 +1,18 @@
version = 1
test_patterns = ["**/*.test.ts"]
[[analyzers]]
name = "shell"
[[analyzers]]
name = "javascript"
[analyzers.meta]
environment = ["nodejs"]
[[analyzers]]
name = "docker"
[analyzers.meta]
dockerfile_paths = ["Dockerfile"]

9
.editorconfig Normal file
View file

@ -0,0 +1,9 @@
root = true
[*]
charset = utf-8
end_of_line = lf
indent_style = space
insert_final_newline = true
tab_width = 4
trim_trailing_whitespace = true

1
.envrc Normal file
View file

@ -0,0 +1 @@
use flake

View file

@ -1,22 +0,0 @@
module.exports = {
extends: [
"eslint:recommended",
"plugin:@typescript-eslint/strict-type-checked",
"plugin:@typescript-eslint/stylistic",
"plugin:prettier/recommended",
],
parser: "@typescript-eslint/parser",
parserOptions: {
project: "./tsconfig.json",
},
ignorePatterns: ["node_modules/", "dist/", ".eslintrc.cjs"],
plugins: ["@typescript-eslint"],
root: true,
rules: {
"@typescript-eslint/no-unsafe-assignment": "off",
"@typescript-eslint/no-unsafe-argument": "off",
"@typescript-eslint/no-explicit-any": "off",
"@typescript-eslint/consistent-type-exports": "error",
"@typescript-eslint/consistent-type-imports": "error"
},
};

View file

@ -1,39 +0,0 @@
---
name: Bug report
about: Create a report to help us improve
title: ''
labels: bug
assignees: ''
---
## Describe the bug
A clear and concise description of what the bug is.
## Steps to reproduce
Steps to reproduce the behavior, such as a cURL command, HTTP request, situation or code repository
## Expected behavior
A clear and concise description of what you expected to happen.
## Screenshots
If applicable, add screenshots to help explain your problem.
## Logs
Please upload logs onto a service like [Pastebin](https://pastebin.com/) or [Hastebin](https://hastebin.com/) and paste the link here. Don't paste the logs directly into the GitHub issue, as it just looks ugly and is hard to read.
## Environment
- OS: [e.g. Fedora 39]
- Bun version
- Postgres version
- Lysand commit ID or version
## Additional context
Add any other context about the problem here.

View file

@ -1,28 +0,0 @@
---
name: Feature request
about: Suggest an idea for this project
title: ''
labels: enhancement
assignees: ''
---
## Is your feature request related to a problem? Please describe.
A clear and concise description of what the problem is, such as "I'm always frustrated when [...]" or "I can't do [...]"
## Describe the solution you'd like
What would you like to see implemented?
## Describe alternatives you've considered
If applicable, describe any alternative solutions or features you've considered.
## Additional context
Add any other context or screenshots about the feature request here.
## Are you willing to work on this feature?
If you are willing to work on this feature, please say so here.

474
.github/config.workflow.toml vendored Normal file
View file

@ -0,0 +1,474 @@
# You can change the URL to the commit/tag you are using
#:schema https://raw.githubusercontent.com/versia-pub/server/main/config/config.schema.json
# All values marked as "sensitive" can be set to "PATH:/path/to/file" to read the value from a file (e.g. a secret manager)
[postgres]
# PostgreSQL database configuration
host = "localhost"
port = 5432
username = "versia"
# Sensitive value
password = "versia"
database = "versia"
# Additional read-only replicas
# [[postgres.replicas]]
# host = "other-host"
# port = 5432
# username = "versia"
# password = "mycoolpassword2"
# database = "replica1"
[redis.queue]
# A Redis database used for managing queues.
# Required for federation
host = "localhost"
port = 6379
# Sensitive value
# password = "test"
database = 0
# A Redis database used for caching SQL queries.
# Optional, can be the same as the queue instance
# [redis.cache]
# host = "localhost"
# port = 6380
# database = 1
# password = ""
# Search and indexing configuration
[search]
# Enable indexing and searching?
enabled = false
# Optional if search is disabled
[search.sonic]
host = "localhost"
port = 40007
# Sensitive value
password = ""
[registration]
# Can users sign up freely?
allow = true
# NOT IMPLEMENTED
require_approval = false
# Message to show to users when registration is disabled
# message = "ran out of spoons to moderate registrations, sorry"
[http]
# URL that the instance will be accessible at
base_url = "http://0.0.0.0:8080"
# Address to bind to (0.0.0.0 is suggested for proxies)
bind = "0.0.0.0"
bind_port = 8080
# Bans IPv4 or IPv6 IPs (wildcards, networks and ranges are supported)
banned_ips = []
# Banned user agents, regex format
banned_user_agents = [
# "curl\/7.68.0",
# "wget\/1.20.3",
]
# URL to an eventual HTTP proxy
# Will be used for all outgoing requests
# proxy_address = "http://localhost:8118"
# TLS configuration. You should probably be using a reverse proxy instead of this
# [http.tls]
# key = "/path/to/key.pem"
# cert = "/path/to/cert.pem"
# Sensitive value
# passphrase = "awawa"
# ca = "/path/to/ca.pem"
[frontend]
# Enable custom frontends (warning: not enabling this will make Versia Server only accessible via the Mastodon API)
# Frontends also control the OpenID flow, so if you disable this, you will need to use the Mastodon frontend
enabled = true
# Path that frontend files are served from
# Edit this property to serve custom frontends
# If this is not set, Versia Server will also check
# the VERSIA_FRONTEND_PATH environment variable
# path = ""
[frontend.routes]
# Special routes for your frontend, below are the defaults for Versia-FE
# Can be set to a route already used by Versia Server, as long as it is on a different HTTP method
# e.g. /oauth/authorize is a POST-only route, so you can serve a GET route at /oauth/authorize
# home = "/"
# login = "/oauth/authorize"
# consent = "/oauth/consent"
# register = "/register"
# password_reset = "/oauth/reset"
[frontend.settings]
# Arbitrary key/value pairs to be passed to the frontend
# This can be used to set up custom themes, etc on supported frontends.
# theme = "dark"
# NOT IMPLEMENTED
[email]
# Enable email sending
send_emails = false
# If send_emails is true, the following settings are required
# [email.smtp]
# SMTP server to use for sending emails
# server = "smtp.example.com"
# port = 465
# username = "test@example.com"
# Sensitive value
# password = "password123"
# tls = true
[media]
# Can be "s3" or "local", where "local" uploads the file to the local filesystem
# Changing this value will not retroactively apply to existing data
# Don't forget to fill in the s3 config :3
backend = "local"
# If media backend is "local", this is the folder where the files will be stored
# Can be any path
uploads_path = "uploads"
[media.conversion]
# Whether to automatically convert images to another format on upload
convert_images = false
# Can be: "image/jxl", "image/webp", "image/avif", "image/png", "image/jpeg", "image/heif", "image/gif"
# JXL support will likely not work
convert_to = "image/webp"
# Also convert SVG images?
convert_vectors = false
# [s3]
# Can be left commented if you don't use the S3 media backend
# endpoint = "https://s3.example.com"
# Sensitive value
# access_key = "XXXXX"
# Sensitive value
# secret_access_key = "XXX"
# region = "us-east-1"
# bucket_name = "versia"
# public_url = "https://cdn.example.com"
[validation]
# Checks user data
# Does not retroactively apply to previously entered data
[validation.accounts]
max_displayname_characters = 50
max_username_characters = 30
max_bio_characters = 5000
max_avatar_bytes = 5_000_000
max_header_bytes = 5_000_000
# Regex is allowed here
disallowed_usernames = [
"well-known",
"about",
"activities",
"api",
"auth",
"dev",
"inbox",
"internal",
"main",
"media",
"nodeinfo",
"notice",
"oauth",
"objects",
"proxy",
"push",
"registration",
"relay",
"settings",
"status",
"tag",
"users",
"web",
"search",
"mfa",
]
max_field_count = 10
max_field_name_characters = 1000
max_field_value_characters = 1000
max_pinned_notes = 20
[validation.notes]
max_characters = 5000
allowed_url_schemes = [
"http",
"https",
"ftp",
"dat",
"dweb",
"gopher",
"hyper",
"ipfs",
"ipns",
"irc",
"xmpp",
"ircs",
"magnet",
"mailto",
"mumble",
"ssb",
"gemini",
]
max_attachments = 16
[validation.media]
max_bytes = 40_000_000
max_description_characters = 1000
# An empty array allows all MIME types
allowed_mime_types = []
[validation.emojis]
max_bytes = 1_000_000
max_shortcode_characters = 100
max_description_characters = 1000
[validation.polls]
max_options = 20
max_option_characters = 500
min_duration_seconds = 60
# 100 days
max_duration_seconds = 8_640_000
[validation.emails]
# Blocks over 10,000 common tempmail domains
disallow_tempmail = false
# Regex is allowed here
disallowed_domains = []
[validation.challenges]
# "Challenges" (aka captchas) are a way to verify that a user is human
# Versia Server's challenges use no external services, and are proof-of-work based
# This means that they do not require any user interaction, instead
# they require the user's computer to do a small amount of work
# The difficulty of the challenge, higher is will take more time to solve
difficulty = 50000
# Challenge expiration time in seconds
expiration = 300 # 5 minutes
# Leave this empty to generate a new key
# Sensitive value
key = "YBpAV0KZOeM/MZ4kOb2E9moH9gCUr00Co9V7ncGRJ3wbd/a9tLDKKFdI0BtOcnlpfx0ZBh0+w3WSvsl0TsesTg=="
# Block content that matches these regular expressions
[validation.filters]
note_content = [
# "(https?://)?(www\\.)?youtube\\.com/watch\\?v=[a-zA-Z0-9_-]+",
# "(https?://)?(www\\.)?youtu\\.be/[a-zA-Z0-9_-]+",
]
emoji_shortcode = []
username = []
displayname = []
bio = []
[notifications]
# Web Push Notifications configuration.
# Leave out to disable.
[notifications.push]
# Subject field embedded in the push notification
# subject = "mailto:joe@example.com"
#
[notifications.push.vapid_keys]
# VAPID keys for push notifications
# Run Versia Server with those values missing to generate new keys
# Sensitive value
public = "BBanhyj2_xWwbTsWld3T49VcAoKZHrVJTzF1f6Av2JwQY_wUi3CF9vZ0WeEcACRj6EEqQ7N35CkUh5epF7n4P_s"
# Sensitive value
private = "Eujaz7NsF0rKZOVrAFL7mMpFdl96f591ERsRn81unq0"
[defaults]
# Default visibility for new notes
# Can be public, unlisted, private or direct
# Private only sends to followers, unlisted doesn't show up in timelines
visibility = "public"
# Default language for new notes (ISO code)
language = "en"
# Default avatar, must be a valid URL or left out for a placeholder avatar
# avatar = ""
# Default header, must be a valid URL or left out for none
# header = ""
# A style name from https://www.dicebear.com/styles
placeholder_style = "thumbs"
[queues]
# Controls the delivery queue (for outbound federation)
[queues.delivery]
# Time in seconds to remove completed jobs
remove_after_complete_seconds = 31536000
# Time in seconds to remove failed jobs
remove_after_failure_seconds = 31536000
# Controls the inbox processing queue (for inbound federation)
[queues.inbox]
# Time in seconds to remove completed jobs
remove_after_complete_seconds = 31536000
# Time in seconds to remove failed jobs
remove_after_failure_seconds = 31536000
# Controls the fetch queue (for remote data refreshes)
[queues.fetch]
# Time in seconds to remove completed jobs
remove_after_complete_seconds = 31536000
# Time in seconds to remove failed jobs
remove_after_failure_seconds = 31536000
# Controls the push queue (for push notification delivery)
[queues.push]
# Time in seconds to remove completed jobs
remove_after_complete_seconds = 31536000
# Time in seconds to remove failed jobs
remove_after_failure_seconds = 31536000
# Controls the media queue (for media processing)
[queues.media]
# Time in seconds to remove completed jobs
remove_after_complete_seconds = 31536000
# Time in seconds to remove failed jobs
remove_after_failure_seconds = 31536000
[federation]
# This is a list of domain names, such as "mastodon.social" or "pleroma.site"
# These changes will not retroactively apply to existing data before they were changed
# For that, please use the CLI (in a later release)
# These instances will not be federated with
blocked = []
# These instances' data will only be shown to followers, not in public timelines
followers_only = []
[federation.discard]
# These objects will be discarded when received from these instances
reports = []
deletes = []
updates = []
media = []
follows = []
# If instance reactions are blocked, likes will also be discarded
likes = []
reactions = []
banners = []
avatars = []
# For bridge software, such as versia-pub/activitypub
# Bridges must be hosted separately from the main Versia Server process
# [federation.bridge]
# Only versia-ap exists for now
# software = "versia-ap"
# If this is empty, any bridge with the correct token
# will be able to send data to your instance
# v4, v6, ranges and wildcards are supported
# allowed_ips = ["192.168.1.0/24"]
# Token for the bridge software
# Bridge must have the same token!
# Sensitive value
# token = "mycooltoken"
# url = "https://ap.versia.social"
[instance]
name = "Versia"
description = "A Versia Server instance"
# Paths to instance long description, terms of service, and privacy policy
# These will be parsed as Markdown
#
# extended_description_path = "config/extended_description.md"
# tos_path = "config/tos.md"
# privacy_policy_path = "config/privacy_policy.md"
# Primary instance languages. ISO 639-1 codes.
languages = ["en"]
[instance.contact]
email = "staff@yourinstance.com"
[instance.branding]
# logo = "https://cdn.example.com/logo.png"
# banner = "https://cdn.example.com/banner.png"
# Used for federation. If left empty or missing, the server will generate one for you.
[instance.keys]
# Sensitive value
public = "MCowBQYDK2VwAyEASN0V5OWRbhRCnuhxfRLqpUOfszHozvrLLVhlIYLNTZM="
# Sensitive value
private = "MC4CAQAwBQYDK2VwBCIEIKaxDGMaW71OcCGMY+GKTZPtLPNlTvMFe3G5qXVHPhQM"
[[instance.rules]]
# Short description of the rule
text = "No hate speech"
# Longer version of the rule with additional information
hint = "Hate speech includes slurs, threats, and harassment."
[[instance.rules]]
text = "No spam"
# [[instance.rules]]
# ...etc
[permissions]
# Control default permissions for users
# Note that an anonymous user having a permission will not allow them
# to do things that require authentication (e.g. 'owner:notes' -> posting a note will need
# auth, but viewing a note will not)
# See https://server.versia.pub/api/roles#list-of-permissions for a list of all permissions
# Defaults to being able to login and manage their own content
# anonymous = []
# Defaults to identical to anonymous
# default = []
# Defaults to being able to manage all instance data, content, and users
# admin = []
[logging]
# Available levels: trace, debug, info, warning, error, fatal
log_level = "info" # For console output
# [logging.file]
# path = "logs/versia.log"
# log_level = "info"
#
# [logging.file.rotation]
# max_size = 10_000_000 # 10 MB
# max_files = 10 # Keep 10 rotated files
#
# https://sentry.io support
# [logging.sentry]
# dsn = "https://example.com"
# debug = false
# sample_rate = 1.0
# traces_sample_rate = 1.0
# Can also be regex
# trace_propagation_targets = []
# max_breadcrumbs = 100
# environment = "production"
# log_level = "info"
[authentication]
# Run Versia Server with this value missing to generate a new key
key = "ZWcwanRaQAqY3ChUro/Jey9XGQjzsxEed5iqTp4yFr8W6vEnXdz91F/Pu/uf7HBMbNeIK7V6aHsM0lq9onrO8Q=="
# The provider MUST support OpenID Connect with .well-known discovery
# Most notably, GitHub does not support this
# Redirect URLs in your OpenID provider can be set to this:
# <base_url>/oauth/sso/<provider_id>/callback*
# The asterisk is important, as it allows for any query parameters to be passed
# Authentik for example uses regex so it can be set to (regex):
# <base_url>/oauth/sso/<provider_id>/callback.*
# [[authentication.openid_providers]]
# name = "CPlusPatch ID"
# id = "cpluspatch-id"
# This MUST match the provider's issuer URI, including the trailing slash (or lack thereof)
# url = "https://id.cpluspatch.com/application/o/versia-testing/"
# client_id = "XXXX"
# Sensitive value
# client_secret = "XXXXX"
# icon = "https://cpluspatch.com/images/icons/logo.svg"

22
.github/copilot-instructions.md vendored Normal file
View file

@ -0,0 +1,22 @@
We use full TypeScript and ESM with Bun for our codebase. Please include relevant and detailed JSDoc comments for all functions and classes. Use explicit type annotations for all variables and function return values, such as:
```typescript
/**
* Adds two numbers together.
*
* @param {number} a
* @param {number} b
* @returns {number}
*/
const add = (a: number, b: number): number => a + b;
```
We always write TypeScript with double quotes and four spaces for indentation, so when your responses include TypeScript code, please follow those conventions.
Our codebase uses Drizzle as an ORM, which is exposed in the `@versia-server/kit/db` and `@versia-server/kit/tables` packages. This project uses a monorepo structure with Bun as the package manager.
The app has two modes: worker and API. The worker mode is used for background tasks, while the API mode serves HTTP requests. The entry point for the worker is `worker.ts`, and for the API, it is `api.ts`.
Run the typechecker with `bun run typecheck` to ensure that all TypeScript code is type-checked correctly. Run tests with `bun test` to ensure that all tests pass. Run the linter and formatter with `bun lint` to ensure that the code adheres to our style guidelines, and `bun lint --write` to automatically fix minor/formatting issues.
Cover all new functionality with tests, and ensure that all tests pass before submitting your code.

27
.github/workflows/check.yml vendored Normal file
View file

@ -0,0 +1,27 @@
name: Check Types
on:
workflow_call:
jobs:
tests:
runs-on: ubuntu-latest
permissions:
contents: read
steps:
- name: Checkout code
uses: actions/checkout@v4
with:
submodules: recursive
- name: Setup Bun
uses: oven-sh/setup-bun@v2
- name: Install NPM packages
run: |
bun install
- name: Run typechecks
run: |
bun run typecheck

27
.github/workflows/circular-imports.yml vendored Normal file
View file

@ -0,0 +1,27 @@
name: Check Circular Imports
on:
workflow_call:
jobs:
tests:
runs-on: ubuntu-latest
permissions:
contents: read
steps:
- name: Checkout code
uses: actions/checkout@v4
with:
submodules: recursive
- name: Setup Bun
uses: oven-sh/setup-bun@v2
- name: Install NPM packages
run: |
bun install
- name: Run typechecks
run: |
bun run detect-circular

View file

@ -9,7 +9,7 @@
# the `language` matrix defined below to confirm you have the correct set of # the `language` matrix defined below to confirm you have the correct set of
# supported CodeQL languages. # supported CodeQL languages.
# #
name: "CodeQL" name: "CodeQL Scan"
on: on:
push: push:
@ -46,11 +46,11 @@ jobs:
steps: steps:
- name: Checkout repository - name: Checkout repository
uses: actions/checkout@v3 uses: actions/checkout@v4
# Initializes the CodeQL tools for scanning. # Initializes the CodeQL tools for scanning.
- name: Initialize CodeQL - name: Initialize CodeQL
uses: github/codeql-action/init@v2 uses: github/codeql-action/init@v3
with: with:
languages: ${{ matrix.language }} languages: ${{ matrix.language }}
# If you wish to specify custom queries, you can do so here or in a config file. # If you wish to specify custom queries, you can do so here or in a config file.
@ -63,7 +63,7 @@ jobs:
# Autobuild attempts to build any compiled languages (C/C++, C#, Go, Java, or Swift). # Autobuild attempts to build any compiled languages (C/C++, C#, Go, Java, or Swift).
# If this step fails, then you should remove it and run the build manually (see below) # If this step fails, then you should remove it and run the build manually (see below)
- name: Autobuild - name: Autobuild
uses: github/codeql-action/autobuild@v2 uses: github/codeql-action/autobuild@v3
# Command-line programs to run using the OS shell. # Command-line programs to run using the OS shell.
# 📚 See https://docs.github.com/en/actions/using-workflows/workflow-syntax-for-github-actions#jobsjob_idstepsrun # 📚 See https://docs.github.com/en/actions/using-workflows/workflow-syntax-for-github-actions#jobsjob_idstepsrun
@ -76,6 +76,6 @@ jobs:
# ./location_of_script_within_repo/buildscript.sh # ./location_of_script_within_repo/buildscript.sh
- name: Perform CodeQL Analysis - name: Perform CodeQL Analysis
uses: github/codeql-action/analyze@v2 uses: github/codeql-action/analyze@v3
with: with:
category: "/language:${{matrix.language}}" category: "/language:${{matrix.language}}"

View file

@ -1,96 +0,0 @@
name: Build and publish Docker image
# This workflow uses actions that are not certified by GitHub.
# They are provided by a third-party and are governed by
# separate terms of service, privacy policy, and support
# documentation.
on:
schedule:
- cron: "22 5 * * *"
push:
branches: ["main"]
# Publish semver tags as releases.
tags: ["v*.*.*"]
pull_request:
branches: ["main"]
env:
# Use docker.io for Docker Hub if empty
REGISTRY: ghcr.io
# github.repository as <account>/<repo>
IMAGE_NAME: ${{ github.repository }}
jobs:
build:
runs-on: ubuntu-latest
permissions:
contents: read
packages: write
# This is used to complete the identity challenge
# with sigstore/fulcio when running outside of PRs.
id-token: write
steps:
- name: Checkout repository
uses: actions/checkout@v3
# Install the cosign tool except on PR
# https://github.com/sigstore/cosign-installer
- name: Install cosign
if: github.event_name != 'pull_request'
uses: sigstore/cosign-installer@6e04d228eb30da1757ee4e1dd75a0ec73a653e06 #v3.1.1
with:
cosign-release: "v2.1.1"
# Set up BuildKit Docker container builder to be able to build
# multi-platform images and export cache
# https://github.com/docker/setup-buildx-action
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@f95db51fddba0c2d1ec667646a06c2ce06100226 # v3.0.0
# Login against a Docker registry except on PR
# https://github.com/docker/login-action
- name: Log into registry ${{ env.REGISTRY }}
if: github.event_name != 'pull_request'
uses: docker/login-action@343f7c4344506bcbf9b4de18042ae17996df046d # v3.0.0
with:
registry: ${{ env.REGISTRY }}
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}
# Extract metadata (tags, labels) for Docker
# https://github.com/docker/metadata-action
- name: Extract Docker metadata
id: meta
uses: docker/metadata-action@96383f45573cb7f253c731d3b3ab81c87ef81934 # v5.0.0
with:
images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}
# Build and push Docker image with Buildx (don't push on PR)
# https://github.com/docker/build-push-action
- name: Build and push Docker image
id: build-and-push
uses: docker/build-push-action@v5.1.0
with:
context: .
push: ${{ github.event_name != 'pull_request' }}
tags: ${{ steps.meta.outputs.tags }}
labels: ${{ steps.meta.outputs.labels }}
cache-from: type=gha
cache-to: type=gha,mode=max
# Sign the resulting Docker image digest except on PRs.
# This will only write to the public Rekor transparency log when the Docker
# repository is public to avoid leaking data. If you would like to publish
# transparency data even for private images, pass --force to cosign below.
# https://github.com/sigstore/cosign
- name: Sign the published Docker image
if: ${{ github.event_name != 'pull_request' }}
env:
# https://docs.github.com/en/actions/security-guides/security-hardening-for-github-actions#using-an-intermediate-environment-variable
TAGS: ${{ steps.meta.outputs.tags }}
DIGEST: ${{ steps.build-and-push.outputs.digest }}
# This step uses the identity token to provision an ephemeral certificate
# against the sigstore community Fulcio instance.
run: echo "${TAGS}" | xargs -I {} cosign sign --yes {}@${DIGEST}

98
.github/workflows/docker.yml vendored Normal file
View file

@ -0,0 +1,98 @@
name: Build Docker Images
on:
push:
branches: ["*"]
# Publish semver tags as releases.
tags: ["v*.*.*"]
pull_request:
branches: ["main"]
jobs:
lint:
uses: ./.github/workflows/lint.yml
check:
uses: ./.github/workflows/check.yml
tests:
uses: ./.github/workflows/tests.yml
detect-circular:
uses: ./.github/workflows/circular-imports.yml
build:
if: ${{ success() }}
needs: [lint, check, tests, detect-circular]
runs-on: ubuntu-latest
permissions:
contents: read
packages: write
# This is used to complete the identity challenge
# with sigstore/fulcio when running outside of PRs.
id-token: write
strategy:
matrix:
include:
- container: worker
image_name: ${{ github.repository_owner }}/worker
dockerfile: Worker.Dockerfile
- container: server
image_name: ${{ github.repository_owner }}/server
dockerfile: Dockerfile
env:
REGISTRY: ghcr.io
steps:
- name: Checkout repository
uses: actions/checkout@v4
with:
submodules: recursive
- name: Setup QEMU
uses: docker/setup-qemu-action@v3
with:
platforms: all
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3
- name: Log into registry ${{ env.REGISTRY }}
if: github.event_name != 'pull_request'
uses: docker/login-action@v3
with:
registry: ${{ env.REGISTRY }}
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}
- name: Extract Docker metadata
id: meta
uses: docker/metadata-action@v5
with:
images: ${{ env.REGISTRY }}/${{ matrix.image_name }}
tags: |
type=schedule
type=ref,event=branch
type=ref,event=tag
type=ref,event=pr
type=sha
- name: Get the commit hash
run: echo "GIT_COMMIT=$(git rev-parse --short ${{ github.sha }})" >> $GITHUB_ENV
- name: Build and push Docker image
id: build-and-push
uses: docker/build-push-action@v5
with:
context: .
push: ${{ github.event_name != 'pull_request' }}
tags: ${{ steps.meta.outputs.tags }}
labels: ${{ steps.meta.outputs.labels }}
build-args: |
GIT_COMMIT=${{ env.GIT_COMMIT }}
file: ${{ matrix.dockerfile }}
provenance: mode=max
sbom: true
platforms: linux/amd64,linux/arm64
cache-from: type=gha
cache-to: type=gha,mode=max

56
.github/workflows/docs.yml vendored Normal file
View file

@ -0,0 +1,56 @@
name: Deploy Docs to GitHub Pages
on:
push:
branches: [main]
workflow_dispatch:
# Sets permissions of the GITHUB_TOKEN to allow deployment to GitHub Pages
permissions:
contents: read
pages: write
id-token: write
# Allow only one concurrent deployment, skipping runs queued between the run in-progress and latest queued.
# However, do NOT cancel in-progress runs as we want to allow these production deployments to complete.
concurrency:
group: pages
cancel-in-progress: false
jobs:
build:
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v4
with:
fetch-depth: 0
- uses: oven-sh/setup-bun@v2
- name: Setup Pages
uses: actions/configure-pages@v4
- name: Install dependencies
run: bun install
- name: Build with VitePress
run: bun run --filter="@versia-server/api" docs:build
- name: Upload artifact
uses: actions/upload-pages-artifact@v3
with:
path: packages/api/docs/.vitepress/dist
# Deployment job
deploy:
environment:
name: github-pages
url: ${{ steps.deployment.outputs.page_url }}
needs: build
runs-on: ubuntu-latest
name: Deploy
steps:
- name: Deploy to GitHub Pages
id: deployment
uses: actions/deploy-pages@v4

View file

@ -1,52 +0,0 @@
# This workflow uses actions that are not certified by GitHub.
# They are provided by a third-party and are governed by
# separate terms of service, privacy policy, and support
# documentation.
# ESLint is a tool for identifying and reporting on patterns
# found in ECMAScript/JavaScript code.
# More details at https://github.com/eslint/eslint
# and https://eslint.org
name: ESLint Checks
on:
push:
branches: ["main"]
pull_request:
# The branches below must be a subset of the branches above
branches: ["main"]
schedule:
- cron: "35 17 * * 3"
jobs:
eslint:
name: Run eslint scanning
runs-on: ubuntu-latest
permissions:
contents: read
security-events: write
actions: read # only required for a private repository by github/codeql-action/upload-sarif to get the Action run status
steps:
- name: Checkout code
uses: actions/checkout@v3
- name: Setup Bun
uses: oven-sh/setup-bun@v1
- name: Install NPM packages
run: |
bun install
- name: Generate Prisma Client
run: |
bunx prisma generate
- name: Run ESLint
run: |
bunx eslint . --config .eslintrc.cjs --ext .js,.jsx,.ts,.tsx --format @microsoft/eslint-formatter-sarif --output-file eslint-results.sarif
continue-on-error: true
- name: Upload analysis results to GitHub
uses: github/codeql-action/upload-sarif@v2
with:
sarif_file: eslint-results.sarif
wait-for-processing: true

27
.github/workflows/lint.yml vendored Normal file
View file

@ -0,0 +1,27 @@
name: Lint & Format
on:
workflow_call:
jobs:
tests:
runs-on: ubuntu-latest
permissions:
contents: read
steps:
- name: Checkout code
uses: actions/checkout@v4
with:
submodules: recursive
- name: Setup Bun
uses: oven-sh/setup-bun@v2
- name: Install NPM packages
run: |
bun install
- name: Run linting
run: |
bunx @biomejs/biome ci .

8
.github/workflows/mirror.yml vendored Normal file
View file

@ -0,0 +1,8 @@
name: Mirror to Codeberg
on: [push]
jobs:
mirror:
name: Mirror
uses: versia-pub/.github/.github/workflows/mirror.yml@main
secrets: inherit

25
.github/workflows/nix-flake.yml vendored Normal file
View file

@ -0,0 +1,25 @@
name: Nix Build
on:
pull_request:
push:
branches: ["*"]
workflow_dispatch:
jobs:
check:
runs-on: ubuntu-latest
permissions:
id-token: "write"
contents: "read"
steps:
- uses: actions/checkout@v4
- uses: DeterminateSystems/nix-installer-action@main
with:
extra-conf: accept-flake-config = true
- uses: DeterminateSystems/magic-nix-cache-action@main
- uses: DeterminateSystems/flake-checker-action@main
- name: Build default package
run: nix build .
- name: Check flakes
run: nix flake check --allow-import-from-derivation

48
.github/workflows/publish.yml vendored Normal file
View file

@ -0,0 +1,48 @@
name: Build & Publish Packages
on:
workflow_dispatch:
inputs:
package:
description: "Package to publish"
required: true
type: choice
options:
- client
- sdk
tag:
description: "NPM tag to use"
required: true
type: choice
default: nightly
options:
- latest
- nightly
permissions:
contents: read
# For provenance generation
id-token: write
jobs:
publish:
runs-on: ubuntu-latest
environment: NPM Deploy
steps:
- name: Checkout
uses: actions/checkout@v4
- uses: oven-sh/setup-bun@v2
- name: Install
run: bun install --frozen-lockfile
- name: Publish to NPM
working-directory: packages/${{ inputs.package }}
run: bun publish --provenance --tag ${{ inputs.tag }} --access public
env:
NPM_CONFIG_TOKEN: ${{ secrets.NPM_TOKEN }}
- name: Publish to JSR
working-directory: packages/${{ inputs.package }}
run: bunx jsr publish --allow-slow-types --allow-dirty

36
.github/workflows/test-publish.yml vendored Normal file
View file

@ -0,0 +1,36 @@
name: Test Publish
on:
push:
permissions:
contents: read
# For provenance generation
id-token: write
jobs:
# Build job
build:
runs-on: ubuntu-latest
environment: NPM Deploy
strategy:
matrix:
package: ["sdk", "client"]
steps:
- name: Checkout
uses: actions/checkout@v4
- uses: oven-sh/setup-bun@v2
- name: Install
run: bun install --frozen-lockfile
- name: Publish to NPM
working-directory: packages/${{ matrix.package }}
env:
NPM_CONFIG_TOKEN: ${{ secrets.NPM_TOKEN }}
run: bun publish --dry-run --access public
- name: Publish to JSR
working-directory: packages/${{ matrix.package }}
run: bunx jsr publish --allow-slow-types --allow-dirty --dry-run

53
.github/workflows/tests.yml vendored Normal file
View file

@ -0,0 +1,53 @@
name: Tests
on:
workflow_call:
jobs:
tests:
runs-on: ubuntu-latest
services:
postgres:
image: postgres:17-alpine
ports:
- 5432:5432
env:
POSTGRES_DB: versia
POSTGRES_USER: versia
POSTGRES_PASSWORD: versia
volumes:
- versia-data:/var/lib/postgresql/data
options: --health-cmd pg_isready
--health-interval 10s
--health-timeout 5s
--health-retries 5
redis:
image: redis:latest
ports:
- 6379:6379
options: --health-cmd "redis-cli ping"
--health-interval 10s
--health-timeout 5s
--health-retries 5
permissions:
contents: read
steps:
- name: Checkout code
uses: actions/checkout@v4
with:
submodules: recursive
- name: Setup Bun
uses: oven-sh/setup-bun@v2
- name: Install NPM packages
run: |
bun install
- name: Move workflow config to config folder
run: |
mv .github/config.workflow.toml config/config.toml
- name: Run tests
run: |
bun run test

17
.gitignore vendored
View file

@ -117,6 +117,10 @@ out
.nuxt .nuxt
dist dist
# Nix build output
result
# Gatsby files # Gatsby files
.cache/ .cache/
@ -172,4 +176,15 @@ config/config.internal.toml
uploads/ uploads/
pages/dist pages/dist
log.txt log.txt
*.log *.log
build
config/extended_description_test.md
*.pem
oclif.manifest.json
.direnv/
tsconfig.tsbuildinfo
# Vitepress Docs
*/.vitepress/dist
*/.vitepress/cache

7
.madgerc Normal file
View file

@ -0,0 +1,7 @@
{
"detectiveOptions": {
"ts": {
"skipTypeImports": true
}
}
}

1
.npmrc Normal file
View file

@ -0,0 +1 @@
@jsr:registry=https://npm.jsr.io

View file

@ -1,9 +0,0 @@
{
"tabWidth": 4,
"useTabs": true,
"arrowParens": "avoid",
"bracketSameLine": true,
"bracketSpacing": true,
"jsxSingleQuote": false,
"trailingComma": "es5"
}

13
.vscode/extensions.json vendored Normal file
View file

@ -0,0 +1,13 @@
{
"recommendations": [
"biomejs.biome",
"ms-vscode-remote.remote-containers",
"oven.bun-vscode",
"vivaxy.vscode-conventional-commits",
"EditorConfig.EditorConfig",
"tamasfe.even-better-toml",
"YoavBls.pretty-ts-errors",
"eamodio.gitlens"
],
"unwantedRecommendations": []
}

54
.vscode/launch.json vendored
View file

@ -1,18 +1,48 @@
{ {
"version": "0.2.0",
"configurations": [ "configurations": [
{ {
"type": "node", "type": "bun",
"name": "vscode-jest-tests.v2.lysand",
"request": "launch",
"args": [
"test",
"${jest.testFile}"
],
"cwd": "/home/jessew/Dev/lysand",
"console": "integratedTerminal",
"internalConsoleOptions": "neverOpen", "internalConsoleOptions": "neverOpen",
"disableOptimisticBPs": true, "request": "launch",
"program": "/home/jessew/.bun/bin/bun" "name": "Debug File",
"program": "${file}",
"cwd": "${workspaceFolder}",
"stopOnEntry": false,
"watchMode": false
},
{
"type": "bun",
"internalConsoleOptions": "neverOpen",
"request": "launch",
"name": "Run File",
"program": "${file}",
"cwd": "${workspaceFolder}",
"watchMode": false
},
{
"type": "bun",
"internalConsoleOptions": "neverOpen",
"request": "attach",
"name": "Attach Bun",
"url": "ws://localhost:6499/",
"stopOnEntry": false
},
{
"type": "bun",
"internalConsoleOptions": "neverOpen",
"request": "launch",
"name": "Run index.ts",
"program": "${workspaceFolder}/index.ts",
"cwd": "${workspaceFolder}",
"watchMode": true
},
{
"type": "bun",
"internalConsoleOptions": "neverOpen",
"request": "launch",
"name": "Run tests",
"program": "test"
} }
] ]
} }

16
.vscode/settings.json vendored
View file

@ -1,5 +1,15 @@
{ {
"typescript.tsdk": "node_modules/typescript/lib", "typescript.tsdk": "node_modules/typescript/lib",
"jest.jestCommandLine": "/home/jessew/.bun/bin/bun test", "conventionalCommits.scopes": [
"jest.rootPath": "." "database",
"api",
"cli",
"federation",
"config",
"worker",
"media",
"packages/client",
"packages/sdk"
],
"languageToolLinter.languageTool.ignoredWordsInWorkspace": ["versia"]
} }

268
API.md
View file

@ -1,268 +0,0 @@
# API
The Lysand project uses the Mastodon API to interact with clients. However, the moderation API is custom-made for Lysand Server, as it allows for more fine-grained control over the server's behavior.
## Flags, ModTags and ModNotes
Flags are used by Lysand Server to automatically attribute tags to a status or account based on rules. ModTags and ModNotes are used by moderators to manually tag and take notes on statuses and accounts.
The difference between flags and modtags is that flags are automatically attributed by the server, while modtags are manually attributed by moderators.
### Flag Types
- `content_filter`: (Statuses only) The status contains content that was filtered by the server's content filter.
- `bio_filter`: (Accounts only) The account's bio contains content that was filtered by the server's content filter.
- `emoji_filter`: The status or account contains an emoji that was filtered by the server's content filter.
- `reported`: The status or account was previously reported by a user.
- `suspended`: The status or account was previously suspended by a moderator.
- `silenced`: The status or account was previously silenced by a moderator.
### ModTag Types
ModTag do not have set types and can be anything. Lysand Server autosuggest previously used tags when a moderator is adding a new tag to avoid duplicates.
### Data Format
```ts
type Flag = {
id: string,
// One of the following two fields will be present
flaggedStatus?: Status,
flaggedUser?: User,
flagType: string,
createdAt: string,
}
type ModTag = {
id: string,
// One of the following two fields will be present
taggedStatus?: Status,
taggedUser?: User,
mod: User,
tag: string,
createdAt: string,
}
type ModNote = {
id: string,
// One of the following two fields will be present
notedStatus?: Status,
notedUser?: User,
mod: User,
note: string,
createdAt: string,
}
```
The `User` and `Status` types are the same as the ones in the Mastodon API.
## Moderation API Routes
### `GET /api/v1/moderation/accounts/:id`
Returns full moderation data and flags for the account with the given ID.
Output format:
```ts
{
id: string, // Same ID as in account field
flags: Flag[],
modtags: ModTag[],
modnotes: ModNote[],
account: User,
}
```
### `GET /api/v1/moderation/statuses/:id`
Returns full moderation data and flags for the status with the given ID.
Output format:
```ts
{
id: string, // Same ID as in status field
flags: Flag[],
modtags: ModTag[],
modnotes: ModNote[],
status: Status,
}
```
### `POST /api/v1/moderation/accounts/:id/modtags`
Params:
- `tag`: string
Adds a modtag to the account with the given ID
### `POST /api/v1/moderation/statuses/:id/modtags`
Params:
- `tag`: string
Adds a modtag to the status with the given ID
### `POST /api/v1/moderation/accounts/:id/modnotes`
Params:
- `note`: string
Adds a modnote to the account with the given ID
### `POST /api/v1/moderation/statuses/:id/modnotes`
Params:
- `note`: string
Adds a modnote to the status with the given ID
### `DELETE /api/v1/moderation/accounts/:id/modtags/:modtag_id`
Deletes the modtag with the given ID from the account with the given ID
### `DELETE /api/v1/moderation/statuses/:id/modtags/:modtag_id`
Deletes the modtag with the given ID from the status with the given ID
### `DELETE /api/v1/moderation/accounts/:id/modnotes/:modnote_id`
Deletes the modnote with the given ID from the account with the given ID
### `DELETE /api/v1/moderation/statuses/:id/modnotes/:modnote_id`
Deletes the modnote with the given ID from the status with the given ID
### `GET /api/v1/moderation/modtags`
Returns a list of all modtags previously used by moderators
Output format:
```ts
{
tags: string[],
}
```
### `GET /api/v1/moderation/accounts/flags/search`
Allows moderators to search for accounts based on their flags, this can also include status flags
Params:
- `limit`: Number
- `min_id`: String. Returns results immediately newer than this ID. In effect, sets a cursor at this ID and paginates forward.
- `max_id`: String. All results returned will be lesser than this ID. In effect, sets an upper bound on results.
- `since_id`: String. All results returned will be greater than this ID. In effect, sets a lower bound on results.
- `flags`: String (optional). Comma-separated list of flag types to filter by. Can be left out to return accounts with at least one flag
- `flag_count`: Number (optional). Minimum number of flags to filter by
- `include_statuses`: Boolean (optional). If true, includes status flags in the search results
- `account_id`: Array of strings (optional). Filters accounts by account ID
This method returns a `Link` header the same way Mastodon does, to allow for pagination.
Output format:
```ts
{
accounts: {
account: User,
modnotes: ModNote[],
flags: Flag[],
statuses?: {
status: Status,
modnotes: ModNote[],
flags: Flag[],
}[],
}[],
}
```
### `GET /api/v1/moderation/statuses/flags/search`
Allows moderators to search for statuses based on their flags
Params:
- `limit`: Number
- `min_id`: String. Returns results immediately newer than this ID. In effect, sets a cursor at this ID and paginates forward.
- `max_id`: String. All results returned will be lesser than this ID. In effect, sets an upper bound on results.
- `since_id`: String. All results returned will be greater than this ID. In effect, sets a lower bound on results.
- `flags`: String (optional). Comma-separated list of flag types to filter by. Can be left out to return statuses with at least one flag
- `flag_count`: Number (optional). Minimum number of flags to filter by
- `account_id`: Array of strings (optional). Filters statuses by account ID
This method returns a `Link` header the same way Mastodon does, to allow for pagination.
Output format:
```ts
{
statuses: {
status: Status,
modnotes: ModNote[],
flags: Flag[],
}[],
}
```
### `GET /api/v1/moderation/accounts/modtags/search`
Allows moderators to search for accounts based on their modtags
Params:
- `limit`: Number
- `min_id`: String. Returns results immediately newer than this ID. In effect, sets a cursor at this ID and paginates forward.
- `max_id`: String. All results returned will be lesser than this ID. In effect, sets an upper bound on results.
- `since_id`: String. All results returned will be greater than this ID. In effect, sets a lower bound on results.
- `tags`: String (optional). Comma-separated list of tags to filter by. Can be left out to return accounts with at least one tag
- `tag_count`: Number (optional). Minimum number of tags to filter by
- `include_statuses`: Boolean (optional). If true, includes status tags in the search results
- `account_id`: Array of strings (optional). Filters accounts by account ID
This method returns a `Link` header the same way Mastodon does, to allow for pagination.
Output format:
```ts
{
accounts: {
account: User,
modnotes: ModNote[],
modtags: ModTag[],
statuses?: {
status: Status,
modnotes: ModNote[],
modtags: ModTag[],
}[],
}[],
}
```
### `GET /api/v1/moderation/statuses/modtags/search`
Allows moderators to search for statuses based on their modtags
Params:
- `limit`: Number
- `min_id`: String. Returns results immediately newer than this ID. In effect, sets a cursor at this ID and paginates forward.
- `max_id`: String. All results returned will be lesser than this ID. In effect, sets an upper bound on results.
- `since_id`: String. All results returned will be greater than this ID. In effect, sets a lower bound on results.
- `tags`: String (optional). Comma-separated list of tags to filter by. Can be left out to return statuses with at least one tag
- `tag_count`: Number (optional). Minimum number of tags to filter by
- `account_id`: Array of strings (optional). Filters statuses by account ID
- `include_statuses`: Boolean (optional). If true, includes status tags in the search results
This method returns a `Link` header the same way Mastodon does, to allow for pagination.
Output format:
```ts
{
statuses: {
status: Status,
modnotes: ModNote[],
modtags: ModTag[],
}[],
}
```

184
CHANGELOG.md Normal file
View file

@ -0,0 +1,184 @@
# `0.9.0` (upcoming)
## Features
### API
- [x] 🥺 Emoji Reactions are now available! You can react to any note with custom emojis.
- [x] 🔎 Added support for [batch account data API](https://docs.joinmastodon.org/methods/accounts/#index).
### Backend
- [x] 🚀 Upgraded Bun to `1.3.2`
# `0.8.0` • Federation 2: Electric Boogaloo
## Backwards Compatibility
Versia Server `0.8.0` is **not** backwards-compatible with `0.7.0`. This release includes some breaking changes to the database schema and configuration file.
Please see [Database Changes](#database-changes) and [New Configuration](#new-configuration) for more information.
## Features
### Federation
- [x] 🦄 Updated to [`Versia 0.5`](https://versia.pub/changelog).
- [x] 📦 Added support for new Versia features:
- [x] [**Instance Messaging Extension**](https://versia.pub/extensions/instance-messaging)
- [x] [**Shared Inboxes**](https://versia.pub/federation#inboxes)
- [x] 🔗 Changed entity URIs to be more readable (`example.org/objects/:id` → `example.org/{notes,likes,...}/:id`)
### API
- [x] 📲 Added [Push Notifications](https://docs.joinmastodon.org/methods/push) support.
- [x] 📖 Overhauled OpenAPI schemas to match [Mastodon API docs](https://docs.joinmastodon.org)
- [x] 👷 Improved [**Roles API**](https://server.versia.pub/api/roles) to allow for full role control (create, update, delete, assign).
- [x] ✏️ `<div>` and `<span>` tags are now allowed in Markdown.
- [x] 🔥 Removed nonstandard `/api/v1/accounts/id` endpoint (the same functionality was already possible with other endpoints).
- [x] ✨️ Implemented rate limiting support for API endpoints.
- [x] 🔒 Implemented `is_indexable` and `is_hiding_collections` fields to the [**Accounts API**](https://docs.joinmastodon.org/methods/accounts/#update_credentials).
- [x] ✨️ Muting other users now lets you specify a duration, after which the mute will be automatically removed.
- [x] 📰 All accounts now have an RSS/Atom feed attached to them.
### CLI
- [x] ⌨️ New commands!
- [x] ✨️ `cli user token` to generate API tokens.
- [x] 👷 Error messages are now prettier!
### Frontend
The way frontend is built and served has been changed. In the past, it was required to have a second process serving a frontend, which `versia-server` would proxy requests to. This is no longer the case.
Versia Server now serves static files directly from a configurable path, and `versia-fe` has been updated to support this.
### Backend
- [x] 🚀 Upgraded Bun to `1.2.13`
- [x] 🔥 Removed dependency on the `pg_uuidv7` extension. Versia Server can now be used with "vanilla" PostgreSQL.
- [x] 🖼️ Simplified media pipeline: this will improve S3 performance
- [x] 📈 It is now possible to disable media proxying for your CDN (offloading considerable bandwidth to your more optimized CDN).
- [x] 👷 Outbound federation, inbox processing, data fetching and media processing are now handled by a queue system.
- [x] 🌐 An administration panel is available at `/admin/queues` to monitor and manage queues.
- [x] 🔥 Removed support for **from-source** installations, as Versia Server is designed around containerization and maintaining support was a large burden.
- [x] ❄️ A [**Nix**](https://nixos.org/) package is now available for this project, packaged as a [Flake](https://wiki.nixos.org/wiki/Flakes). A **NixOS** module is also provided.
## New Configuration
Configuration parsing and validation has been overhauled. Unfortunately, this means that since a bunch of options have been renamed, you'll need to redownload [the default configuration file](config/config.example.toml) and reapply your changes.
## Database Changes
Various media-related attributes have been merged into a single `Medias` table. This will require a migration in order to preserve the old data.
Since very few instances are running `0.7.0`, we have decided to "rawdog it" instead of making a proper migration script (as that would take a ton of time that we don't have).
In the case that you've been running secret instances in the shadows, let us know and we'll help you out.
## Bug Fixes
- 🐛 All URIs in custom Markdown text are now correctly proxied.
- 🐛 Fixed several issues with the [ActivityPub Federation Bridge](https://github.com/versia-pub/activitypub) preventing it from operating properly.
- 🐛 Fixed incorrect content-type on some media when using S3.
- 🐛 All media content-type is now correctly fetched, instead of guessed from the file extension as before.
- 🐛 Fixed OpenAPI schema generation and `/docs` endpoint.
- 🐛 Logs folder is now automatically created if it doesn't exist.
- 🐛 Media hosted on the configured S3 bucket and on the local filesystem is no longer unnecessarily proxied.
- 🐛 Likes and Shares now federate properly.
# `0.7.0` • The Auth and APIs Update
> [!WARNING]
> This release marks the rename of the project from `Lysand` to `Versia`.
## Backwards Compatibility
Versia Server `0.7.0` is backwards compatible with `0.6.0`. However, some new features may not be available to older clients. Notably, `versia-fe` has had major improvements and will not work with `0.6.0`.
## Features
- Upgraded Bun to `1.1.34`. This brings performance upgrades and better stability.
- Added support for the [ActivityPub Federation Bridge](https://github.com/versia-pub/activitypub).
- Added support for the [Sonic](https://github.com/valeriansaliou/sonic) search indexer.
- Note deletions are now federated.
- Note edits are now federated.
- Added support for [Sentry](https://sentry.io).
- Added option for more federation debug logging.
- Added [**Roles API**](https://server.versia.pub/api/roles).
- Added [**Permissions API**](https://server.versia.pub/api/roles) and enabled it for every route.
- Added [**TOS and Privacy Policy**](https://server.versia.pub/api/mastodon) endpoints.
- Added [**Challenge API**](https://server.versia.pub/api/challenges). (basically CAPTCHAS). This can be enabled/disabled by administrators. No `versia-fe` support yet.
- Added ability to refetch user data from remote instances.
- Added ability to change the `username` of a user. ([Mastodon API extension](https://server.versia.pub/api/mastodon#api-v1-accounts-update-credentials)).
- Added an endpoint to get a user by its username.
- Add OpenID Connect registration support. Admins can now disable username/password registration entirely and still allow users to sign up via OpenID Connect.
- Add option to never convert vector images to a raster format.
- Refactor logging system to be more robust and easier to use. Log files are now automatically rotated.
- Add support for HTTP proxies.
- Add support for serving Versia over a Tor hidden service.
- Add global server error handler, to properly return 500 error messages to clients.
- Sign all federation HTTP requests.
- Add JSON schema for configuration file.
- Rewrite federation stack
- Updated federation to Versia 0.4
- Implement OAuth2 token revocation
- Add new **Plugin API**
## Plugin System
A new plugin system for extending Versia Server has been added in this release!
> [!NOTE]
>
> This is an internal feature and is not documented. Support for third-party plugins will be given on a "if we have time" basis, until the API is fully stabilized and documented
Plugins using this framework support:
- [x] Plugin hotswapping and hotreloading
- [x] Manifest files (JSON, JSON5, JSONC supported) with metadata (JSON schema provided)
- [x] Installation by dropping a folder into the plugins/ directory
- [x] Support for plugins having their own NPM dependencies
- [x] Support for storing plugins' configuration in the main config.toml (single source of truth)
- [x] Schema-based strict config validation (plugins can specify their own schemas)
- [x] Full type-safety
- [x] Custom hooks
- [x] FFI compatibility (with `bun:ffi` or Node's FFI)
- [x] Custom API route registration or overriding or middlewaring
- [x] Automatic OpenAPI schema generation for all installed plugins
- [x] End-to-end and unit testing supported
- [x] Automatic user input validation for API routes with schemas (specify a schema for the route and the server will take care of validating everything)
- [x] Access to internal database abstractions
- [x] Support for sending raw SQL to database (type-safe!)
- [x] Plugin autoload on startup with override controls (enable/disable)
As a demonstration of the power of this system and an effort to modularize the codebase further, OpenID functionality has been moved to a plugin. This plugin is required for login.
## Bug Fixes
- Fix favouriting/unfavouriting sometimes returning negative counts.
- Non-images will now properly be uploaded to object storage.
- Make account searches case-insensitive
- Fix image decoding error when passing media through proxy.
- OpenID Connect now correctly remembers and passes `state` parameter.
- OpenID Connect will not reject some correct but weird redirect URIs.
- Markdown posts will not have invisible anchor tags anymore (this messed up accessibility).
- Reverse proxies incorrectly reporting an HTTPS request as HTTP will now be handled correctly during OpenID Connect flows.
- API Relationships will now correctly return `requested_by`.
- Make process wait for Ctrl+C to exit on error, instead of exiting immediately. This fixes some issues with Docker restarting endlessly.
- Animated media will now stay animated when uploaded.
- Some instance metadata will no longer be missing from `/api/v2/instabnce` endpoint. In fact, it will now be more complete than Mastodon's implementation.
- The Origin HTTP header will no longer be used to determine the origin of a request. This was a security issue.
- New notes will no longer incorrectly be federated to _all_ remote users at once.
- Fix [Elk Client](https://elk.zone/) not being able to log in.
## Removals
- Remove old logging system, to be replaced by a new one.
- Removed Meilisearch support, in favor of Sonic. Follow instructions in the [installation guide](https://server.versia.pub/setup/installation) to set up Sonic.
- Removed explicit Glitch-FE support. Glitch-FE will still work, but must be hosted separately like any other frontend.
## Miscellaneous
- Remove Node.js from Docker build.
- Update all dependencies.

View file

@ -1,133 +0,0 @@
# Contributor Covenant Code of Conduct
## Our Pledge
We as members, contributors, and leaders pledge to make participation in our
community a harassment-free experience for everyone, regardless of age, body
size, visible or invisible disability, ethnicity, sex characteristics, gender
identity and expression, level of experience, education, socio-economic status,
nationality, personal appearance, race, caste, color, religion, or sexual
identity and orientation.
We pledge to act and interact in ways that contribute to an open, welcoming,
diverse, inclusive, and healthy community.
## Our Standards
Examples of behavior that contributes to a positive environment for our
community include:
* Demonstrating empathy and kindness toward other people
* Being respectful of differing opinions, viewpoints, and experiences
* Giving and gracefully accepting constructive feedback
* Accepting responsibility and apologizing to those affected by our mistakes,
and learning from the experience
* Focusing on what is best not just for us as individuals, but for the overall
community
Examples of unacceptable behavior include:
* The use of sexualized language or imagery, and sexual attention or advances of
any kind
* Trolling, insulting or derogatory comments, and personal or political attacks
* Public or private harassment
* Publishing others' private information, such as a physical or email address,
without their explicit permission
* Other conduct which could reasonably be considered inappropriate in a
professional setting
## Enforcement Responsibilities
Community leaders are responsible for clarifying and enforcing our standards of
acceptable behavior and will take appropriate and fair corrective action in
response to any behavior that they deem inappropriate, threatening, offensive,
or harmful.
Community leaders have the right and responsibility to remove, edit, or reject
comments, commits, code, wiki edits, issues, and other contributions that are
not aligned to this Code of Conduct, and will communicate reasons for moderation
decisions when appropriate.
## Scope
This Code of Conduct applies within all community spaces, and also applies when
an individual is officially representing the community in public spaces.
Examples of representing our community include using an official e-mail address,
posting via an official social media account, or acting as an appointed
representative at an online or offline event.
## Enforcement
Instances of abusive, harassing, or otherwise unacceptable behavior may be
reported to the community leaders responsible for enforcement at
[INSERT CONTACT METHOD].
All complaints will be reviewed and investigated promptly and fairly.
All community leaders are obligated to respect the privacy and security of the
reporter of any incident.
## Enforcement Guidelines
Community leaders will follow these Community Impact Guidelines in determining
the consequences for any action they deem in violation of this Code of Conduct:
### 1. Correction
**Community Impact**: Use of inappropriate language or other behavior deemed
unprofessional or unwelcome in the community.
**Consequence**: A private, written warning from community leaders, providing
clarity around the nature of the violation and an explanation of why the
behavior was inappropriate. A public apology may be requested.
### 2. Warning
**Community Impact**: A violation through a single incident or series of
actions.
**Consequence**: A warning with consequences for continued behavior. No
interaction with the people involved, including unsolicited interaction with
those enforcing the Code of Conduct, for a specified period of time. This
includes avoiding interactions in community spaces as well as external channels
like social media. Violating these terms may lead to a temporary or permanent
ban.
### 3. Temporary Ban
**Community Impact**: A serious violation of community standards, including
sustained inappropriate behavior.
**Consequence**: A temporary ban from any sort of interaction or public
communication with the community for a specified period of time. No public or
private interaction with the people involved, including unsolicited interaction
with those enforcing the Code of Conduct, is allowed during this period.
Violating these terms may lead to a permanent ban.
### 4. Permanent Ban
**Community Impact**: Demonstrating a pattern of violation of community
standards, including sustained inappropriate behavior, harassment of an
individual, or aggression toward or disparagement of classes of individuals.
**Consequence**: A permanent ban from any sort of public interaction within the
community.
## Attribution
This Code of Conduct is adapted from the [Contributor Covenant][homepage],
version 2.1, available at
[https://www.contributor-covenant.org/version/2/1/code_of_conduct.html][v2.1].
Community Impact Guidelines were inspired by
[Mozilla's code of conduct enforcement ladder][Mozilla CoC].
For answers to common questions about this code of conduct, see the FAQ at
[https://www.contributor-covenant.org/faq][FAQ]. Translations are available at
[https://www.contributor-covenant.org/translations][translations].
[homepage]: https://www.contributor-covenant.org
[v2.1]: https://www.contributor-covenant.org/version/2/1/code_of_conduct.html
[Mozilla CoC]: https://github.com/mozilla/diversity
[FAQ]: https://www.contributor-covenant.org/faq
[translations]: https://www.contributor-covenant.org/translations

View file

@ -1,88 +1,73 @@
# Contributing to Lysand # Contributing to Versia
> [!NOTE] > [!NOTE]
> This document was authored by [@CPlusPatch](https://github.com/CPlusPatch). > This document was authored by [@CPlusPatch](https://github.com/CPlusPatch).
Thank you for your interest in contributing to Lysand! We welcome contributions from everyone, regardless of their level of experience or expertise. Thank you for your interest in contributing to Versia Server! We welcome contributions from everyone, regardless of their level of experience or expertise.
# Tech Stack # Tech Stack
Lysand is built using the following technologies: Versia Server is built using the following technologies:
- [Bun](https://bun.sh) - A JavaScript runtime similar to Node.js, but faster and with more features - [Bun](https://bun.sh) - A JavaScript runtime similar to Node.js, but faster and with more features
- [PostgreSQL](https://www.postgresql.org/) - A relational database - [PostgreSQL](https://www.postgresql.org/) - A relational database
- [`pg_uuidv7`](https://github.com/fboulnois/pg_uuidv7) - A PostgreSQL extension that provides a UUIDv7 data type - [`pg_uuidv7`](https://github.com/fboulnois/pg_uuidv7) - A PostgreSQL extension that provides a UUIDv7 data type
- [UnoCSS](https://unocss.dev) - A utility-first CSS framework, used for the login page
- [Docker](https://www.docker.com/) - A containerization platform, used for development and deployment - [Docker](https://www.docker.com/) - A containerization platform, used for development and deployment
- [Sharp](https://sharp.pixelplumbing.com/) - An image processing library, used for fast image resizing and converting - [Sharp](https://sharp.pixelplumbing.com/) - An image processing library, used for fast image resizing and converting
- [TypeScript](https://www.typescriptlang.org/) - A typed superset of JavaScript - [TypeScript](https://www.typescriptlang.org/) - A typed superset of JavaScript
- [ESLint](https://eslint.org/) - A JavaScript linter
- [Prettier](https://prettier.io/) - A code formatter
## Getting Started ## Getting Started
To get started, please follow these steps: To get started, please follow these steps:
1. Fork the repository, clone it on your local system and make your own branch 1. Install the [Bun](https://bun.sh) runtime:
2. Install the [Bun](https://bun.sh) runtime:
```sh ```sh
curl -fsSL https://bun.sh/install | bash curl -fsSL https://bun.sh/install | bash
``` ```
1. Clone this repository 2. Clone this repository
```bash ```bash
git clone https://github.com/lysand-org/lysand.git git clone https://github.com/versia-pub/server.git
``` ```
2. Install the dependencies 3. Install the dependencies
```bash ```bash
bun install bun install
``` ```
3. Set up a PostgreSQL database, using the `pg_uuidv7` extension 1. Set up a PostgreSQL database (you need a special extension, please look at [the database documentation](https://server.versia.pub/setup/database))
You may use the following [Dockerfile](Postgres.Dockerfile) to set it up: 2. Copy the `config/config.example.toml` file to `config/config.toml` and edit it to set up the database connection and other settings.
```Dockerfile
# Use the latest Postgres Docker image based on Alpine
FROM postgres:alpine
# Set working directory ## HTTPS development
WORKDIR /usr/src/app
# Install curl To develop with HTTPS, you need to generate a self-signed certificate. We will use [`mkcert`](https://github.com/FiloSottile/mkcert) for this purpose.
RUN apk add --no-cache curl
RUN cd "$(mktemp -d)" \ 1. Install `mkcert`:
&& curl -LO "https://github.com/fboulnois/pg_uuidv7/releases/download/v1.3.0/{pg_uuidv7.tar.gz,SHA256SUMS}" \ 2. Generate a certificate for the domain you are using:
&& tar xf pg_uuidv7.tar.gz \ ```sh
&& sha256sum -c SHA256SUMS \ mkcert -install
&& PG_MAJOR=$(pg_config --version | sed 's/^.* \([0-9]\{1,\}\).*$/\1/') \ # You can change the domain to whatever you want, but it must resolve via /etc/hosts
&& cp "$PG_MAJOR/pg_uuidv7.so" "$(pg_config --pkglibdir)" \ # *.localhost domains are automatically aliased to localhost by DNS
&& cp sql/pg_uuidv7--1.3.sql pg_uuidv7.control "$(pg_config --sharedir)/extension" mkcert -key-file config/versia.localhost-key.pem -cert-file config/versia.localhost.pem versia.localhost
# Add a script to run the CREATE EXTENSION command ```
RUN echo '#!/bin/sh\npsql -U "$POSTGRES_USER" -d "$POSTGRES_DB" -c "CREATE EXTENSION pg_uuidv7;"' > /docker-entrypoint-initdb.d/init.sh 3. Edit the config to use your database and HTTPS certificates, e.g:
```toml
[http]
base_url = "https://versia.localhost:9900"
bind = "versia.localhost"
bind_port = 9900 # Change the port to whatever you want
# Make the entrypoint script executable [http.tls]
RUN chmod +x /docker-entrypoint-initdb.d/init.sh enabled = true
key = "config/versia.localhost-key.pem"
cert = "config/versia.localhost.pem"
passphrase = ""
ca = ""
``` ```
4. Copy the `config.toml.example` file to `config.toml` and fill in the values (you can leave most things to the default, but you will need to configure things such as the database connection) Now, running the server will use the certificate you generated.
> [!WARNING]
> You should disable Prisma Redis caching while developing, as it can mess up tests
5. Generate the Prisma client:
```bash
bun prisma generate
```
6. Run migrations:
```bash
bun migrate
```
## Testing your changes ## Testing your changes
@ -93,53 +78,46 @@ bun dev
If your port number is lower than 1024, you may need to run the command as root. If your port number is lower than 1024, you may need to run the command as root.
### Running the Vite server
To start the Vite server, run:
```sh
bun vite:dev
```
This should be run in a separate terminal window. The Vite server is used to serve the frontend assets and to provide hot module reloading.
## Running tests ## Running tests
To run the tests, run: To run the tests, run:
```sh ```sh
bun test bun run test
``` ```
The tests are located in the `tests/` directory and follow a Jest-like syntax. The server does not need to be started before running the tests, as the tests will spawn their own Lysand server instance. The `bun test` command will cause errors due to Bun bugs ([oven-sh/bun#7823](https://github.com/oven-sh/bun/issues/7823)). Use the `test` script instead.
The tests are located all around the codebase (filename `*.test.ts`) and follow a Jest-like syntax. The server should be shut down before running the tests.
## Code style ## Code style
We use ESLint and Prettier to enforce a consistent code style. To check if your code is compliant, run: We use [Biome](https://biomejs.dev) to enforce a consistent code style. To check if your code is compliant, run:
```sh ```sh
bun lint bun lint
``` ```
To automatically fix the issues, run: To automatically fix the issues, run:
```sh ```sh
bun lint --fix bun lint --write
``` ```
You should have the [ESLint](https://marketplace.visualstudio.com/items?itemName=dbaeumer.vscode-eslint) and [Prettier](https://marketplace.visualstudio.com/items?itemName=esbenp.prettier-vscode) extensions installed in VSCode, if you use it. From the ESLint extension, you can automatically fix the issues with `Ctrl+Shift+P` and `ESLint: Fix all auto-fixable Problems`. You can also install the Biome Visual Studio Code extension and have it format your code automatically on save.
ESLint and Prettier are also integrated in the CI pipeline, so your code will be automatically checked when you push it. If the pipeline fails, you will need to fix the issues before your pull request can be merged. ### TypeScript
Code style such as brackets, spaces/tabs, etc are enforced by Prettier's ESLint plugin. You can find the simple configuration in the `.prettierrc` file. Linting should not be ignored, except if they are false positives, in which case you can use a comment to disable the rule for the line or the file. If you need to disable a rule, please add a comment explaining why.
### ESLint rules
ESLint errors should not be ignored, except if they are false positives, in which case you can use a comment to disable the rule for the line or the file. If you need to disable a rule, please add a comment explaining why.
TypeScript errors should be ignored with `// @ts-expect-error` comments, as well as with a reason for being ignored. TypeScript errors should be ignored with `// @ts-expect-error` comments, as well as with a reason for being ignored.
To scan for all TypeScript errors, run:
```sh
bun typecheck
```
### Commit messages ### Commit messages
We use [Conventional Commits](https://www.conventionalcommits.org/en/v1.0.0/) for our commit messages. This allows us to automatically generate the changelog and the version number. We use [Conventional Commits](https://www.conventionalcommits.org) for our commit messages. This allows us to automatically generate the changelog and the version number, while also making it easier to understand what changes were made in each commit.
> **Note**: I don't actually enforce this rule, but it would be great if you could follow it.
### Pull requests ### Pull requests
@ -151,13 +129,15 @@ We use Bun's integrated testing system to write tests. You can find more informa
Tests **should** be written for all API routes and all functions that are not trivial. If you are not sure whether you should write a test for something, you probably should. Tests **should** be written for all API routes and all functions that are not trivial. If you are not sure whether you should write a test for something, you probably should.
To help with the creation of tests, you may find [GitHub Copilot](https://copilot.github.com/) useful (or some of its free alternatives like [Codeium](https://codeium.com/)). Please do not blindly copy the code that it generates, but use it as a starting point for your own tests. I recognize that writing tests is very tedious, which is why LLMs can come in handy. #### Adding per-route tests
To add tests for a route, create a `route_file_name.test.ts` file in the same directory as the route itself. See [this example](/api/api/v1/timelines/home.test.ts) for help writing tests.
### Writing documentation ### Writing documentation
Documentation for the Lysand protocol is available on [lysand.org](https://lysand.org/). If you are thinking of modifying the protocol, please make sure to send a pull request over there to get it approved and merged before you send your pull request here. Documentation for the Versia protocol is available on [versia.pub](https://versia.pub/). If you are thinking of modifying the protocol, please make sure to send a pull request over there to get it approved and merged before you send your pull request here.
This project should not need much documentation, but if you think that something needs to be documented, please add it to the README or contribution guide. This project should not need much documentation, but if you think that something needs to be documented, please add it to the README, docs or contribution guide.
## Reporting bugs ## Reporting bugs
@ -166,11 +146,11 @@ If you find a bug, please open an issue on GitHub. Please make sure to include t
- The steps to reproduce the bug - The steps to reproduce the bug
- The expected behavior - The expected behavior
- The actual behavior - The actual behavior
- The version of Lysand you are using - The version of Versia Server you are using
- The version of Bun you are using - The version of Bun you are using
- The version of PostgreSQL you are using - The version of PostgreSQL you are using
- Your operating system and version - Your operating system and version
# License # License
Lysand is licensed under the [AGPLv3](https://www.gnu.org/licenses/agpl-3.0.en.html) license. By contributing to Lysand, you agree to license your contributions under the same license. Versia Server is licensed under the [AGPLv3 or later](https://www.gnu.org/licenses/agpl-3.0.en.html) license. By contributing to Versia, you agree to license your contributions under the same license.

View file

@ -1,46 +1,51 @@
# use the official Bun image # Node is required for building the project
# see all versions at https://hub.docker.com/r/oven/bun/tags FROM imbios/bun-node:latest-23-alpine AS base
FROM oven/bun:1.0.30-alpine as base
WORKDIR /usr/src/app
# Required for Prisma to work # Install dependencies into temp directory
# COPY --from=node:18-alpine /usr/local/bin/node /usr/local/bin/node # This will cache them and speed up future builds
# install dependencies into temp directory
# this will cache them and speed up future builds
FROM base AS install FROM base AS install
# install with --production (exclude devDependencies)
RUN mkdir -p /temp RUN mkdir -p /temp
COPY . /temp COPY . /temp
WORKDIR /temp WORKDIR /temp
RUN bun install --frozen-lockfile --production RUN bun install --production
# Build Vite in pages FROM base AS build
RUN bunx --bun vite build pages
# Copy the project
RUN mkdir -p /temp
COPY . /temp
# Copy dependencies
COPY --from=install /temp/node_modules /temp/node_modules
# Build the project # Build the project
RUN bun run build.ts WORKDIR /temp
RUN bun run build api
WORKDIR /temp/dist WORKDIR /temp/dist
# copy production dependencies and source code into final image # Copy production dependencies and source code into final image
FROM base AS release FROM oven/bun:1.3.2-alpine
# Create app directory # Install libstdc++ for Bun and create app directory
RUN mkdir -p /app RUN mkdir -p /app
COPY --from=install /temp/dist /app/dist
COPY --from=build /temp/dist /app/dist
COPY entrypoint.sh /app COPY entrypoint.sh /app
LABEL org.opencontainers.image.authors="Gaspard Wierzbinski (https://cpluspatch.com)"
LABEL org.opencontainers.image.source="https://github.com/versia-pub/server"
LABEL org.opencontainers.image.vendor="Versia Pub"
LABEL org.opencontainers.image.licenses="AGPL-3.0-or-later"
LABEL org.opencontainers.image.title="Versia Server"
LABEL org.opencontainers.image.description="Versia Server Docker image"
LABEL org.opencontainers.image.authors "Gaspard Wierzbinski (https://cpluspatch.dev)" # Set current Git commit hash as an environment variable
LABEL org.opencontainers.image.source "https://github.com/lysand-org/lysand" ARG GIT_COMMIT
LABEL org.opencontainers.image.vendor "Lysand Org" ENV GIT_COMMIT=$GIT_COMMIT
LABEL org.opencontainers.image.licenses "AGPL-3.0"
LABEL org.opencontainers.image.title "Lysand Server"
LABEL org.opencontainers.image.description "Lysand Server docker image"
# CD to app # CD to app
WORKDIR /app WORKDIR /app
ENV NODE_ENV=production ENV NODE_ENV=production
ENTRYPOINT [ "/bin/sh", "/app/entrypoint.sh" ]
# Run migrations and start the server # Run migrations and start the server
ENTRYPOINT [ "./entrypoint.sh" "start" ] CMD [ "bun", "run", "api.js" ]

View file

@ -1,21 +0,0 @@
# Use the latest Postgres Docker image based on Alpine
FROM postgres:alpine
# Set working directory
WORKDIR /usr/src/app
# Install curl
RUN apk add --no-cache curl
RUN cd "$(mktemp -d)" \
&& curl -LO "https://github.com/fboulnois/pg_uuidv7/releases/download/v1.3.0/{pg_uuidv7.tar.gz,SHA256SUMS}" \
&& tar xf pg_uuidv7.tar.gz \
&& sha256sum -c SHA256SUMS \
&& PG_MAJOR=$(pg_config --version | sed 's/^.* \([0-9]\{1,\}\).*$/\1/') \
&& cp "$PG_MAJOR/pg_uuidv7.so" "$(pg_config --pkglibdir)" \
&& cp sql/pg_uuidv7--1.3.sql pg_uuidv7.control "$(pg_config --sharedir)/extension"
# Add a script to run the CREATE EXTENSION command
RUN echo '#!/bin/sh\npsql -U "$POSTGRES_USER" -d "$POSTGRES_DB" -c "CREATE EXTENSION pg_uuidv7;"' > /docker-entrypoint-initdb.d/init.sh
# Make the entrypoint script executable
RUN chmod +x /docker-entrypoint-initdb.d/init.sh

531
README.md
View file

@ -1,21 +1,52 @@
<p align="center"> <div align="center">
<a href="https://lysand.org"><img src="https://cdn-web.cpluspatch.com/lysand.webp" alt="Lysand Logo" height=130></a> <a href="https://versia.pub">
</p> <picture>
<source media="(prefers-color-scheme: dark)" srcset="https://cdn.versia.pub/branding/logo-dark.svg">
<source media="(prefers-color-scheme: light)" srcset="https://cdn.versia.pub/branding/logo-light.svg">
<img src="https://cdn.versia.pub/branding/logo-dark.svg" alt="Versia Logo" height="110" />
</picture>
</a>
</div>
![Postgres](https://img.shields.io/badge/postgres-%23316192.svg?style=for-the-badge&logo=postgresql&logoColor=white) ![Bun](https://img.shields.io/badge/Bun-%23000000.svg?style=for-the-badge&logo=bun&logoColor=white) ![VS Code Insiders](https://img.shields.io/badge/VS%20Code%20Insiders-35b393.svg?style=for-the-badge&logo=visual-studio-code&logoColor=white) ![TypeScript](https://img.shields.io/badge/typescript-%23007ACC.svg?style=for-the-badge&logo=typescript&logoColor=white) ![Linux](https://img.shields.io/badge/Linux-FCC624?style=for-the-badge&logo=linux&logoColor=black) ![Docker](https://img.shields.io/badge/docker-%230db7ed.svg?style=for-the-badge&logo=docker&logoColor=white) ![ESLint](https://img.shields.io/badge/ESLint-4B3263?style=for-the-badge&logo=eslint&logoColor=white) [![Contributor Covenant](https://img.shields.io/badge/Contributor%20Covenant-2.1-4baaaa?style=for-the-badge)](code_of_conduct.md)
<h2 align="center">
<strong><code>Versia Server</code></strong>
</h2>
<div align="center">
<img src="https://cdn.jsdelivr.net/gh/devicons/devicon@latest/icons/typescript/typescript-original.svg" height="42" width="52" alt="TypeScript logo">
<img src="https://cdn.jsdelivr.net/gh/devicons/devicon/icons/postgresql/postgresql-original.svg" height="42" width="52" alt="PostgreSQL logo">
<img src="https://cdn.jsdelivr.net/gh/devicons/devicon/icons/docker/docker-original.svg" height="42" width="52" alt="Docker logo">
<img src="https://cdn.jsdelivr.net/gh/devicons/devicon/icons/bun/bun-original.svg" height="42" width="52" alt="Bun logo">
<img src="https://cdn.jsdelivr.net/gh/devicons/devicon/icons/vscode/vscode-original.svg" height="42" width="52" alt="VSCode logo">
<img src="https://cdn.jsdelivr.net/gh/devicons/devicon/icons/sentry/sentry-original.svg" height="42" width="52" alt="Sentry logo">
<img src="https://cdn.jsdelivr.net/gh/devicons/devicon/icons/linux/linux-original.svg" height="42" width="52" alt="Linux logo">
</div>
<br/>
## What is this? ## What is this?
This is a project to create a federated social network based on the [Lysand](https://lysand.org) protocol. It is currently in alpha phase, with basic federation and almost complete Mastodon API support. **Versia Server** (formerly Lysand Server) is a federated social network server based on the [Versia](https://versia.pub) protocol. It is currently in beta phase, with basic federation and almost complete Mastodon API support.
This project aims to be a fully featured social network, with a focus on privacy, security, and performance. It implements the Mastodon API for support with clients that already support Mastodon or Pleroma. ### Goals
> [!NOTE] - **Privacy**: Versia Server is designed to be as private as possible. Unnecessary data is not stored, and data that is stored is done so securely.
> This project is not affiliated with Mastodon or Pleroma, and is not a fork of either project. It is a new project built from the ground up. - **Configurability**: High configurability is a key feature of Versia Server. Almost every aspect of the server can be configured to suit your needs. If you feel like something is missing, please open an issue.
- **Security**: Versia Server is designed with security in mind. It is built with modern security practices and technologies, and is constantly updated to ensure the highest level of security.
- **Performance**: Efficiency and speed are a key focus of Versia Server. The design is non-monolithic, and is built to be as fast as possible.
- **Mastodon API compatibility**: Versia Server is designed to be compatible with the Mastodon API, with [`glitch-soc`](https://github.com/glitch-soc/mastodon) extensions.
### Anti-Goals
- **Monolithic design**: Modularity and scaling is important to this project. This means that it is not a single, monolithic application, but rather a collection of smaller, more focused applications. (API layer, queue, database, frontend, etc.)
- **Complexity**: Both in code and in function, Versia Server should be as simple as possible. This does not mean adding no features or functionality, but rather that the features and functionality that are added should be well-written and easy to understand.
- **Bloat**: Versia Server should not be bloated with unnecessary features, packages, dependencies or code. It should be as lightweight as possible, while still being feature-rich.
## Features ## Features
- [x] Inbound federation - [x] Versia Working Draft 4 federation (partial)
- [x] Hyper fast (thousands of HTTP requests per second) - [x] Hyper fast (thousands of HTTP requests per second)
- [x] S3 or local media storage - [x] S3 or local media storage
- [x] Deduplication of uploaded files - [x] Deduplication of uploaded files
@ -23,340 +54,204 @@ This project aims to be a fully featured social network, with a focus on privacy
- [x] Configurable defaults - [x] Configurable defaults
- [x] Full regex-based filters for posts, users and media - [x] Full regex-based filters for posts, users and media
- [x] Custom emoji support - [x] Custom emoji support
- [x] Users can upload their own emojis for themselves
- [x] Automatic image conversion to WebP or other formats - [x] Automatic image conversion to WebP or other formats
- [x] Scripting-compatible CLI with JSON and CSV outputs - [x] Scripting-compatible CLI with JSON and CSV outputs
- [ ] Moderation tools - [x] Markdown support just about everywhere: posts, profiles, profile fields, etc. Code blocks, tables, and more are supported.
- [ ] Full Mastodon API support - [ ] Advanced moderation tools (work in progress)
- [ ] Outbound federation - [x] Fully compliant Mastodon API support (partial)
- [x] Glitch-SOC extensions
- [x] Full compatibility with many clients such as Megalodon
- [x] Ability to use your own frontends
- [x] Non-monolithic architecture, microservices can be hosted in infinite amounts on infinite servers
- [x] Ability to use all your threads
- [x] Support for SSO providers, as well as SSO-only registration.
- [x] Fully written in TypeScript and thoroughly unit tested
- [x] Automatic signed container builds for easy deployment
- [x] Docker and Podman supported
- [x] Invisible, Proof-of-Work local CAPTCHA for API requests
- [x] Advanced Roles and Permissions API.
- [x] HTTP proxy support
- [x] Tor hidden service support
- [x] Sentry logging support
- [x] Ability to change the domain name in a single config change, without any database edits
## Benchmarks ## Screenshots
> [!NOTE] You can visit [social.lysand.org](https://social.lysand.org) to see a live instance of Versia Server with Versia-FE.
> These benchmarks are not representative of real-world performance, and are only meant to be used as a rough guide. Load, and therefore performance, will vary depending on the server's hardware and software configuration, as well as user activity.
### Timeline Benchmarks
You may run the following command to benchmark the `/api/v1/timelines/home` endpoint:
```bash
TOKEN=token_here bun benchmark:timeline <request_count>
```
The `request_count` variable is optional and defaults to 100. `TOKEN` is your personal user token, used to login to the API.
On a quad-core laptop:
```
$ bun run benchmarks/timelines.ts 100
✓ All requests succeeded
✓ 100 requests fulfilled in 0.12611s
```
```
$ bun run benchmarks/timelines.ts 1000
✓ All requests succeeded
✓ 1000 requests fulfilled in 0.90925s
```
```
$ bun run benchmarks/timelines.ts 10000
✓ All requests succeeded
✓ 10000 requests fulfilled in 12.44852s
```
Lysand is extremely fast and can handle thousands of HTTP requests per second on a good server.
## How do I run it? ## How do I run it?
### Requirements Please see the [installation guide](https://server.versia.pub/setup/installation) for more information on how to install Versia.
- The [Bun Runtime](https://bun.sh), version 1.0.30 or later (usage of the latest version is recommended)
- A PostgreSQL database
- (Optional but recommended) A Linux-based operating system
- (Optional if you want search) A working Meiliseach instance
> [!WARNING]
> Lysand has not been tested on Windows or MacOS. It is recommended to use a Linux-based operating system to run Lysand.
>
> We will not be offerring support to Windows or MacOS users. If you are using one of these operating systems, please use a virtual machine or container to run Lysand.
### Installation
1. Clone this repository
```bash
git clone https://github.com/lysand-org/lysand.git
```
2. Install the dependencies
```bash
bun install
```
3. Set up a PostgreSQL database, using the `pg_uuidv7` extension
You may use the following [Dockerfile](Postgres.Dockerfile) to set it up:
```Dockerfile
# Use the latest Postgres Docker image based on Alpine
FROM postgres:alpine
# Set working directory
WORKDIR /usr/src/app
# Install curl
RUN apk add --no-cache curl
RUN cd "$(mktemp -d)" \
&& curl -LO "https://github.com/fboulnois/pg_uuidv7/releases/download/v1.3.0/{pg_uuidv7.tar.gz,SHA256SUMS}" \
&& tar xf pg_uuidv7.tar.gz \
&& sha256sum -c SHA256SUMS \
&& PG_MAJOR=$(pg_config --version | sed 's/^.* \([0-9]\{1,\}\).*$/\1/') \
&& cp "$PG_MAJOR/pg_uuidv7.so" "$(pg_config --pkglibdir)" \
&& cp sql/pg_uuidv7--1.3.sql pg_uuidv7.control "$(pg_config --sharedir)/extension"
# Add a script to run the CREATE EXTENSION command
RUN echo '#!/bin/sh\npsql -U "$POSTGRES_USER" -d "$POSTGRES_DB" -c "CREATE EXTENSION pg_uuidv7;"' > /docker-entrypoint-initdb.d/init.sh
# Make the entrypoint script executable
RUN chmod +x /docker-entrypoint-initdb.d/init.sh
```
4. Copy the `config.toml.example` file to `config.toml` and fill in the values (you can leave most things to the default, but you will need to configure things such as the database connection)
5. Run migrations:
```bash
bun migrate
```
6. (If you want search)
Create a Meilisearch instance (using Docker is recommended). For a [`docker-compose`] file, copy the `meilisearch` service from the [`docker-compose.yml`](docker-compose.yml) file.
Set up Meiliseach's API key by passing the `MEILI_MASTER_KEY` environment variable to the server. Then, enale and configure search in the config file.
7. Build everything:
```bash
bun prod-build
```
You may now start the server with `bun start`. It lives in the `dist/` directory, all the other code can be removed from this point onwards.
In fact, the `bun start` script merely runs `bun run dist/index.js --prod`!
### Running
To run the server, simply run the following command:
```bash
bun start
```
### Using the CLI
Lysand includes a built-in CLI for managing the server. To use it, simply run the following command:
```bash
bun cli help
```
If you are running a production build, you will need to run `bun run dist/cli.js` or `./entrypoint.sh cli` instead.
You can use the `help` command to see a list of available commands. These include creating users, deleting users and more. Each command also has a `--help,-h` flag that you can use to see more information about the command.
#### Scripting with the CLI
Some CLI commands that return data as tables can be used in scripts. To convert them to JSON or CSV, some commands allow you to specify a `--format` flag that can be either `"json"` or `"csv"`. See `bun cli help` or `bun cli <command> -h` for more information.
Flags can be used in any order and anywhere in the script (except for the `bun cli` command itself). The command arguments themselves must be in the correct order, however.
### Rebuilding the Search Index
You may use the `bun cli index rebuild` command to automatically push all posts and users to Meilisearch, if it is configured. This is useful if you have just set up Meilisearch, or if you accidentally deleted something.
### Using Database Commands
The `bun prisma` commands allows you to use Prisma commands without needing to add in environment variables for the database config. Just run Prisma commands as you would normally, replacing `bunx prisma` with `bun prisma`.
## With Docker
> [!NOTE]
> Docker is currently broken, as Bun with Prisma does not work well with Docker yet for unknown reasons. The following instructions are for when this is fixed.
>
> These instructions will probably also work with Podman and other container runtimes.
You can also run Lysand using Docker. To do so, you can:
1. Acquire the Postgres Dockerfile from above
2. Use this repository's [`docker-compose.yml`](docker-compose.yml) file
3. Create the `lysand-net` docker network:
```bash
docker network create lysand-net
```
1. Fill in the config file (see [Installation](#installation))
2. Run the following command:
```bash
docker-compose up -d
```
You may need root privileges to run Docker commands.
### Running CLI commands inside Docker
You can run CLI commands inside Docker using the following command:
```bash
sudo docker exec -it lysand sh entrypoint.sh cli ...
```
### Running migrations inside Docker
You can run migrations inside Docker using the following command (if needed):
```bash
sudo docker exec -it lysand sh entrypoint.sh prisma migrate deploy
```
## Contributing ## Contributing
Contributions are welcome! Please see the [CONTRIBUTING.md](CONTRIBUTING.md) file for more information. Contributions are welcome! Please see the [CONTRIBUTING.md](CONTRIBUTING.md) file for more information.
## Planned Extra Features
- Send notifications to moderators when a report is received
- Email notifications on certain actions
## Federation ## Federation
> [!WARNING]
> Federation has not been tested outside of automated tests. It is not recommended to use this software in production.
The following extensions are currently supported or being worked on: The following extensions are currently supported or being worked on:
- `org.lysand:custom_emojis`: Custom emojis - `pub.versia:custom_emojis`: Custom emojis
- `pub.versia:instance_messaging`: Instance Messaging
- `pub.versia:likes`: Likes
- `pub.versia:share`: Share
- `pub.versia:reactions`: Reactions
## API ## API
Lysand implements the Mastodon API, with some extensions. The API is currently in early alpha, and is not recommended for use in production. Versia Server implements the Mastodon API (as well as `glitch-soc` extensions). The API is currently almost fully complete, with some fringe functionality still being worked on.
Working endpoints are: Working endpoints are:
- `/api/v1/accounts` - [x] `/api/v1/accounts/:id/block`
- `/api/v1/accounts/:id` - [x] `/api/v1/accounts/:id/follow`
- `/api/v1/accounts/:id/statuses` - [x] `/api/v1/accounts/:id/followers`
- `/api/v1/accounts/:id/follow` - [x] `/api/v1/accounts/:id/following`
- `/api/v1/accounts/:id/unfollow` - [ ] `/api/v1/accounts/:id/lists`
- `/api/v1/accounts/:id/block` - [x] `/api/v1/accounts/:id/mute`
- `/api/v1/accounts/:id/unblock` - [x] `/api/v1/accounts/:id/note`
- `/api/v1/accounts/:id/mute` - [x] `/api/v1/accounts/:id/pin`
- `/api/v1/accounts/:id/unmute` - [x] `/api/v1/accounts/:id/remove_from_followers`
- `/api/v1/accounts/:id/pin` - [x] `/api/v1/accounts/:id/statuses`
- `/api/v1/accounts/:id/unpin` - [x] `/api/v1/accounts/:id/unblock`
- `/api/v1/accounts/:id/note` - [x] `/api/v1/accounts/:id/unfollow`
- `/api/v1/accounts/:id/remove_from_followers` - [x] `/api/v1/accounts/:id/unmute`
- `/api/v1/accounts/relationships` - [x] `/api/v1/accounts/:id/unpin`
- `/api/v1/accounts/update_credentials` - [x] `/api/v1/accounts/:id`
- `/api/v1/accounts/verify_credentials` - [x] `/api/v1/accounts/familiar_followers`
- `/api/v1/accounts/familiar_followers` - [x] `/api/v1/accounts/relationships`
- `/api/v1/profile/avatar` (`DELETE`) - [x] `/api/v1/accounts/update_credentials`
- `/api/v1/profile/header` (`DELETE`) - [x] `/api/v1/accounts/verify_credentials`
- `/api/v1/statuses/:id` (`GET`, `DELETE`) - [x] `/api/v1/accounts`
- `/api/v1/statuses/:id/context` - [ ] `/api/v1/announcements/:id/dismiss`
- `/api/v1/statuses/:id/favourite` - [ ] `/api/v1/announcements/:id/reactions/:name` (`PUT`, `DELETE`)
- `/api/v1/statuses/:id/unfavourite` - [ ] `/api/v1/announcements`
- `/api/v1/statuses/:id/favourited_by` - [x] `/api/v1/apps/verify_credentials`
- `/api/v1/statuses/:id/reblogged_by` - [x] `/api/v1/apps`
- `/api/v1/statuses/:id/reblog` - [x] `/api/v1/blocks`
- `/api/v1/statuses/:id/unreblog` - [ ] `/api/v1/conversations/:id/read`
- `/api/v1/statuses/:id/pin` - [ ] `/api/v1/conversations/:id`
- `/api/v1/statuses/:id/unpin` - [ ] `/api/v1/conversations`
- `/api/v1/statuses` - [x] `/api/v1/custom_emojis`
- `/api/v1/timelines/public` - [ ] `/api/v1/directory`
- `/api/v1/timelines/home` - [ ] `/api/v1/domain_blocks` (`GET`, `POST`, `DELETE`)
- `/api/v1/apps` - [ ] `/api/v1/endorsements`
- `/api/v1/instance` - [x] `/api/v1/favourites`
- `/api/v1/custom_emojis` - [ ] `/api/v1/featured_tags/:id` (`DELETE`)
- `/api/v1/apps/verify_credentials` - [ ] `/api/v1/featured_tags/suggestions`
- `/oauth/authorize` - [ ] `/api/v1/featured_tags` (`GET`, `POST`)
- `/oauth/token` - [x] `/api/v1/follow_requests/:account_id/authorize`
- `/api/v1/blocks` - [x] `/api/v1/follow_requests/:account_id/reject`
- `/api/v1/mutes` - [x] `/api/v1/follow_requests`
- `/api/v2/media` - [ ] `/api/v1/follow_suggestions`
- `/api/v1/notifications` - [ ] `/api/v1/followed_tags`
- [ ] `/api/v1/instance/activity`
- [ ] `/api/v1/instance/domain_blocks`
- [x] `/api/v1/instance/extended_description`
- [ ] `/api/v1/instance/peers`
- [x] `/api/v1/instance/rules`
- [x] `/api/v1/instance`
- [ ] `/api/v1/lists/:id/accounts` (`GET`, `POST`, `DELETE`)
- [ ] `/api/v1/lists/:id` (`GET`, `PUT`, `DELETE`)
- [ ] `/api/v1/lists` (`GET`, `POST`)
- [x] `/api/v1/markers` (`GET`, `POST`)
- [x] `/api/v1/media/:id`
- [x] `/api/v1/mutes`
- [x] `/api/v1/notifications/:id/dismiss`
- [x] `/api/v1/notifications/:id`
- [x] `/api/v1/notifications/clear`
- [x] `/api/v1/notifications`
- [ ] `/api/v1/polls/:id/votes`
- [ ] `/api/v1/polls/:id`
- [ ] `/api/v1/preferences`
- [x] `/api/v1/profile/avatar` (`DELETE`)
- [x] `/api/v1/profile/header` (`DELETE`)
- [ ] `/api/v1/reports`
- [ ] `/api/v1/scheduled_statuses/:id` (`GET`, `PUT`, `DELETE`)
- [ ] `/api/v1/scheduled_statuses`
- [ ] `/api/v1/statuses/:id/bookmark`
- [x] `/api/v1/statuses/:id/context`
- [x] `/api/v1/statuses/:id/favourite`
- [x] `/api/v1/statuses/:id/favourited_by`
- [ ] `/api/v1/statuses/:id/history`
- [x] `/api/v1/statuses/:id/mute`
- [x] `/api/v1/statuses/:id/pin`
- [x] `/api/v1/statuses/:id/reblog`
- [x] `/api/v1/statuses/:id/reblogged_by`
- [x] `/api/v1/statuses/:id/source`
- [ ] `/api/v1/statuses/:id/translate`
- [ ] `/api/v1/statuses/:id/unbookmark`
- [x] `/api/v1/statuses/:id/unfavourite`
- [x] `/api/v1/statuses/:id/unmute`
- [x] `/api/v1/statuses/:id/unpin`
- [x] `/api/v1/statuses/:id/unreblog`
- [x] `/api/v1/statuses/:id` (`GET`, `DELETE`)
- [x] `/api/v1/statuses/:id` (`PUT`)
- [x] `/api/v1/statuses`
- [ ] `/api/v1/suggestions/:account_id` (`DELETE`)
- [ ] `/api/v1/tags/:id/follow`
- [ ] `/api/v1/tags/:id/unfollow`
- [ ] `/api/v1/tags/:id`
- [x] `/api/v1/timelines/home`
- [ ] `/api/v1/timelines/list/:list_id`
- [x] `/api/v1/timelines/public`
- [ ] `/api/v1/timelines/tag/:hashtag`
- [ ] `/api/v1/trends/links`
- [ ] `/api/v1/trends/statuses`
- [ ] `/api/v1/trends/tags`
- [ ] `/api/v2/filters/:filter_id/keywords` (`GET`, `POST`)
- [ ] `/api/v2/filters/:filter_id/statuses` (`GET`, `POST`)
- [x] `/api/v2/filters/:id` (`GET`, `PUT`, `DELETE`)
- [ ] `/api/v2/filters/keywords/:id` (`GET`, `PUT`, `DELETE`)
- [ ] `/api/v2/filters/statuses/:id` (`GET`, `DELETE`)
- [x] `/api/v2/filters` (`GET`, `POST`)
- [x] `/api/v2/instance`
- [x] `/api/v2/media`
- [x] `/api/v2/search`
- [ ] `/api/v2/suggestions`
- [x] `/oauth/authorize`
- [x] `/oauth/token`
- [x] `/oauth/revoke`
- Admin API
Tests needed but completed: ### Main work to do for API
- `/api/v1/media/:id` - [ ] Announcements
- `/api/v2/media` - [ ] Polls
- `/api/v1/favourites` - [ ] Tags
- `/api/v1/accounts/:id/followers` - [ ] Lists
- `/api/v1/accounts/:id/following` - [ ] Scheduled statuses
- `/api/v2/search` - [ ] WebSockets
- [ ] Push notifications
- [ ] Trends
- [ ] Suggestions
- [ ] Bookmarks
- [ ] Translation
- [ ] Reports
- [ ] Admin API
Endpoints left: ## Versia Server API
- `/api/v1/reports` For Versia Server's own custom API, please see the [API documentation](https://server.versia.pub/api/emojis).
- `/api/v1/accounts/:id/lists`
- `/api/v1/follow_requests`
- `/api/v1/follow_requests/:account_id/authorize`
- `/api/v1/follow_requests/:account_id/reject`
- `/api/v1/follow_suggestions`
- `/api/v1/domain_blocks` (`GET`, `POST`, `DELETE`)
- `/api/v2/filters` (`GET`, `POST`)
- `/api/v2/filters/:id` (`GET`, `PUT`, `DELETE`)
- `/api/v2/filters/:filter_id/keywords` (`GET`, `POST`)
- `/api/v2/filters/keywords/:id` (`GET`, `PUT`, `DELETE`)
- `/api/v2/filters/:filter_id/statuses` (`GET`, `POST`)
- `/api/v2/filters/statuses/:id` (`GET`, `DELETE`)
- `/api/v1/endorsements`
- `/api/v1/featured_tags` (`GET`, `POST`)
- `/api/v1/featured_tags/:id` (`DELETE`)
- `/api/v1/featured_tags/suggestions`
- `/api/v1/preferences`
- `/api/v1/followed_tags`
- `/api/v2/suggestions`
- `/api/v1/suggestions/:account_id` (`DELETE`)
- `/api/v1/tags/:id`
- `/api/v1/tags/:id/follow`
- `/api/v1/tags/:id/unfollow`
- `/api/v1/statuses/:id/translate`
- `/api/v1/statuses/:id/bookmark`
- `/api/v1/statuses/:id/unbookmark`
- `/api/v1/statuses/:id/mute`
- `/api/v1/statuses/:id/unmute`
- `/api/v1/statuses/:id` (`PUT`)
- `/api/v1/statuses/:id/history`
- `/api/v1/statuses/:id/source`
- `/api/v1/polls/:id`
- `/api/v1/polls/:id/votes`
- `/api/v1/scheduled_statuses`
- `/api/v1/scheduled_statuses/:id` (`GET`, `PUT`, `DELETE`)
- `/api/v1/timelines/tag/:hashtag`
- `/api/v1/timelines/list/:list_id`
- `/api/v1/conversations`
- `/api/v1/conversations/:id`
- `/api/v1/conversations/:id/read`
- `/api/v1/lists` (`GET`, `POST`)
- `/api/v1/lists/:id` (`GET`, `PUT`, `DELETE`)
- `/api/v1/markers` (`GET`, `POST`)
- `/api/v1/lists/:id/accounts` (`GET`, `POST`, `DELETE`)
- `/api/v1/notifications/:id`
- `/api/v1/notifications/clear`
- `/api/v1/notifications/:id/dismiss`
- `/api/v2/instance`
- `/api/v1/instance/peers`
- `/api/v1/instance/activity`
- `/api/v1/instance/rules`
- `/api/v1/instance/domain_blocks`
- `/api/v1/instance/extended_description`
- `/api/v1/directory`
- `/api/v1/trends/tags`
- `/api/v1/trends/statuses`
- `/api/v1/trends/links`
- `/api/v1/announcements`
- `/api/v1/announcements/:id/dismiss`
- `/api/v1/announcements/:id/reactions/:name` (`PUT`, `DELETE`)
- Admin API
WebSocket Streaming API also needed to be added (and push notifications)
## License ## License
This project is licensed under the [AGPL-3.0](LICENSE). This project is licensed under the [AGPL-3.0-or-later](LICENSE).
All Versia assets (icon, logo, banners, etc) are licensed under [CC-BY-NC-SA-4.0](https://creativecommons.org/licenses/by-nc-sa/4.0)
## Thanks!
Thanks to [**Fastly**](https://fastly.com) for providing us with support and resources to build Versia!
<br />
<p align="center">
<a href="https://fastly.com">
<picture>
<source media="(prefers-color-scheme: dark)" srcset="assets/fastly-red.svg">
<source media="(prefers-color-scheme: light)" srcset="assets/fastly-red.svg">
<img src="assets/fastly-red.svg" alt="Fastly Logo" height="110" />
</picture>
</a>
</p>

View file

@ -1,22 +0,0 @@
# Security Policy
## Supported Versions
For now, only the released latest version of Lysand is supported for security updates. This will change as Lysand exits alpha status.
## Reporting a Vulnerability
If you find a vulnerability, please report it to [@CPlusPatch](https://github.com/CPlusPatch) at the following contact endpoints:
- [Matrix](https://matrix.to/#/@jesse:cpluspatch.dev)
- [E-mail](mailto:contact@cpluspatch.com)
Please do not report vulnerabilities publicly until they have been patched. If you would like to be credited for your discovery, please include your name and/or GitHub username in your report.
## Vulnerability Disclosure Policy
Lysand is an open-source project, and as such, we welcome security researchers to audit our code and report vulnerabilities. We will do our best to patch vulnerabilities as quickly as possible, and will credit researchers for their discoveries if they wish to be credited.
For security reasons, we ask that you do not publicly disclose vulnerabilities until they have been patched. We will do our best to patch vulnerabilities as quickly as possible, and will credit researchers for their discoveries if they wish to be credited.
Thank you for helping to keep Lysand secure! :3

51
Worker.Dockerfile Normal file
View file

@ -0,0 +1,51 @@
# Node is required for building the project
FROM imbios/bun-node:latest-23-alpine AS base
# Install dependencies into temp directory
# This will cache them and speed up future builds
FROM base AS install
RUN mkdir -p /temp
COPY . /temp
WORKDIR /temp
RUN bun install --production
FROM base AS build
# Copy the project
RUN mkdir -p /temp
COPY . /temp
# Copy dependencies
COPY --from=install /temp/node_modules /temp/node_modules
# Build the project
WORKDIR /temp
RUN bun run build worker
WORKDIR /temp/dist
# Copy production dependencies and source code into final image
FROM oven/bun:1.3.2-alpine
# Install libstdc++ for Bun and create app directory
RUN mkdir -p /app
COPY --from=build /temp/dist /app/dist
COPY entrypoint.sh /app
LABEL org.opencontainers.image.authors="Gaspard Wierzbinski (https://cpluspatch.com)"
LABEL org.opencontainers.image.source="https://github.com/versia-pub/server"
LABEL org.opencontainers.image.vendor="Versia Pub"
LABEL org.opencontainers.image.licenses="AGPL-3.0-or-later"
LABEL org.opencontainers.image.title="Versia Server Worker"
LABEL org.opencontainers.image.description="Versia Server Worker Docker image"
# Set current Git commit hash as an environment variable
ARG GIT_COMMIT
ENV GIT_COMMIT=$GIT_COMMIT
# CD to app
WORKDIR /app
ENV NODE_ENV=production
ENTRYPOINT [ "/bin/sh", "/app/entrypoint.sh" ]
# Run migrations and start the server
CMD [ "bun", "run", "worker.js" ]

19
api.ts Normal file
View file

@ -0,0 +1,19 @@
import process from "node:process";
import { appFactory } from "@versia-server/api";
import { config } from "@versia-server/config";
import { Youch } from "youch";
import { createServer } from "@/server.ts";
process.on("SIGINT", () => {
process.exit();
});
process.on("uncaughtException", async (error) => {
const youch = new Youch();
console.error(await youch.toANSI(error));
});
await import("@versia-server/api/setup");
createServer(config, await appFactory());

1
assets/fastly-black.svg Normal file
View file

@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 198.27"><g id="Layer_2" data-name="Layer 2"><g id="Layer_1-2" data-name="Layer 1"><g id="Fastly_Logo_-_Red" data-name="Fastly Logo - Red"><g id="Fastly_Logo_-_Red-2" data-name="Fastly Logo - Red"><polygon points="348.44 20.35 348.44 153.94 388.57 153.94 388.57 133.53 375.31 133.53 375.31 0 348.44 0 348.44 20.35"/><path d="M0,133.53H13.64V69.08H0V51.35l13.64-2.24V31.17C13.64,9.43,18.37,0,46.09,0A115.17,115.17,0,0,1,65.38,2L61.7,23.85a49.78,49.78,0,0,0-9-.78c-9.76,0-12.23,1-12.23,10.51V49.11H60.79v20H40.51v64.45H54v20.4H0Z"/><path d="M334.78,127.08a53.11,53.11,0,0,1-10.54.84c-11.06.27-10.1-3.36-10.1-13.78V69.08h21v-20h-21V0H287.27V119.71c0,23.5,5.8,34.23,31.08,34.23,6,0,14.21-1.54,20.42-2.87Z"/><path d="M501.7,133.63a10.14,10.14,0,1,1-10.19,10.14,10.14,10.14,0,0,1,10.19-10.14m0,18.68a8.55,8.55,0,0,0,8.51-8.54,8.5,8.5,0,1,0-8.51,8.54m1.88-3.56-2.05-3h-1.42v3h-2.29v-10H502c2.46,0,4,1.24,4,3.45a3,3,0,0,1-2.08,3.09l2.49,3.42Zm-3.47-5h1.82c1,0,1.74-.4,1.74-1.5s-.7-1.45-1.68-1.45h-1.88Z"/><path d="M253.72,69V65.46A115.8,115.8,0,0,0,233.14,64c-12.5,0-14,6.63-14,10.23,0,5.08,1.74,7.83,15.29,10.79,19.8,4.45,39.69,9.09,39.69,33.64,0,23.29-12,35.32-37.21,35.32-16.88,0-33.26-3.63-45.76-6.8V127.08h20.35v3.56c8.75,1.69,17.93,1.52,22.73,1.52,13.34,0,15.49-7.17,15.49-11,0-5.29-3.82-7.83-16.32-10.37-23.56-4-42.25-12.07-42.25-36,0-22.65,15.14-31.54,40.37-31.54,17.09,0,30.08,2.65,42.59,5.83V69Z"/><path d="M127.84,85.09,118,93.69a5.25,5.25,0,1,0,3.19,3.2l8.72-9.75Z"/><path d="M171.25,127.07V43.46H144.37V51a55,55,0,0,0-18.11-6.77v-9.1h3.28V28.28H102.48v6.83h3.28v9.17a55.32,55.32,0,1,0,38.76,101.87l4.77,7.78h28.38V127.07Zm-26.64-26.83A28.42,28.42,0,0,1,117.73,127v-3.18h-3.22V127a28.43,28.43,0,0,1-26.68-26.89H91V96.91H87.85a28.42,28.42,0,0,1,26.66-26.65v3.16h3.22V70.25A28.42,28.42,0,0,1,144.61,97h-3.2v3.22Z"/><path d="M456.58,49.11H512v20H498.75l-34,83.62c-9.74,23.48-25.74,45.59-50.1,45.59a93.67,93.67,0,0,1-19.5-2l2.43-24.39a68.7,68.7,0,0,0,10.63,1.1c11.3,0,24-7,28-19.19L401.82,69.06H388.57v-20H444v20H430.78l19.51,48h0l19.51-48H456.58Z"/></g></g></g></g></svg>

After

Width:  |  Height:  |  Size: 2.1 KiB

1
assets/fastly-red.svg Normal file
View file

@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 198.27"><defs><style>.cls-1{fill:#ff282d;}</style></defs><g id="Layer_2" data-name="Layer 2"><g id="Layer_1-2" data-name="Layer 1"><g id="Fastly_Logo_-_Red" data-name="Fastly Logo - Red"><g id="Fastly_Logo_-_Red-2" data-name="Fastly Logo - Red"><polygon class="cls-1" points="348.44 20.35 348.44 153.94 388.57 153.94 388.57 133.53 375.31 133.53 375.31 0 348.44 0 348.44 20.35"/><path class="cls-1" d="M0,133.53H13.64V69.08H0V51.35l13.64-2.24V31.17C13.64,9.43,18.37,0,46.09,0A115.17,115.17,0,0,1,65.38,2L61.7,23.85a49.78,49.78,0,0,0-9-.78c-9.76,0-12.23,1-12.23,10.51V49.11H60.79v20H40.51v64.45H54v20.4H0Z"/><path class="cls-1" d="M334.78,127.08a53.11,53.11,0,0,1-10.54.84c-11.06.27-10.1-3.36-10.1-13.78V69.08h21v-20h-21V0H287.27V119.71c0,23.5,5.8,34.23,31.08,34.23,6,0,14.21-1.54,20.42-2.87Z"/><path class="cls-1" d="M501.7,133.63a10.14,10.14,0,1,1-10.19,10.14,10.14,10.14,0,0,1,10.19-10.14m0,18.68a8.55,8.55,0,0,0,8.51-8.54,8.5,8.5,0,1,0-8.51,8.54m1.88-3.56-2.05-3h-1.42v3h-2.29v-10H502c2.46,0,4,1.24,4,3.45a3,3,0,0,1-2.08,3.09l2.49,3.42Zm-3.47-5h1.82c1,0,1.74-.4,1.74-1.5s-.7-1.45-1.68-1.45h-1.88Z"/><path class="cls-1" d="M253.72,69V65.46A115.8,115.8,0,0,0,233.14,64c-12.5,0-14,6.63-14,10.23,0,5.08,1.74,7.83,15.29,10.79,19.8,4.45,39.69,9.09,39.69,33.64,0,23.29-12,35.32-37.21,35.32-16.88,0-33.26-3.63-45.76-6.8V127.08h20.35v3.56c8.75,1.69,17.93,1.52,22.73,1.52,13.34,0,15.49-7.17,15.49-11,0-5.29-3.82-7.83-16.32-10.37-23.56-4-42.25-12.07-42.25-36,0-22.65,15.14-31.54,40.37-31.54,17.09,0,30.08,2.65,42.59,5.83V69Z"/><path class="cls-1" d="M127.84,85.09,118,93.69a5.25,5.25,0,1,0,3.19,3.2l8.72-9.75Z"/><path class="cls-1" d="M171.25,127.07V43.46H144.37V51a55,55,0,0,0-18.11-6.77v-9.1h3.28V28.28H102.48v6.83h3.28v9.17a55.32,55.32,0,1,0,38.76,101.87l4.77,7.78h28.38V127.07Zm-26.64-26.83A28.42,28.42,0,0,1,117.73,127v-3.18h-3.22V127a28.43,28.43,0,0,1-26.68-26.89H91V96.91H87.85a28.42,28.42,0,0,1,26.66-26.65v3.16h3.22V70.25A28.42,28.42,0,0,1,144.61,97h-3.2v3.22Z"/><path class="cls-1" d="M456.58,49.11H512v20H498.75l-34,83.62c-9.74,23.48-25.74,45.59-50.1,45.59a93.67,93.67,0,0,1-19.5-2l2.43-24.39a68.7,68.7,0,0,0,10.63,1.1c11.3,0,24-7,28-19.19L401.82,69.06H388.57v-20H444v20H430.78l19.51,48h0l19.51-48H456.58Z"/></g></g></g></g></svg>

After

Width:  |  Height:  |  Size: 2.2 KiB

1
assets/fastly-white.svg Normal file
View file

@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 198.27"><defs><style>.cls-1{fill:#fff;}</style></defs><g id="Layer_2" data-name="Layer 2"><g id="Layer_1-2" data-name="Layer 1"><g id="Fastly_Logo_-_Red" data-name="Fastly Logo - Red"><g id="Fastly_Logo_-_Red-2" data-name="Fastly Logo - Red"><polygon class="cls-1" points="348.44 20.35 348.44 153.94 388.57 153.94 388.57 133.53 375.31 133.53 375.31 0 348.44 0 348.44 20.35"/><path class="cls-1" d="M0,133.53H13.64V69.08H0V51.35l13.64-2.24V31.17C13.64,9.43,18.37,0,46.09,0A115.17,115.17,0,0,1,65.38,2L61.7,23.85a49.78,49.78,0,0,0-9-.78c-9.76,0-12.23,1-12.23,10.51V49.11H60.79v20H40.51v64.45H54v20.4H0Z"/><path class="cls-1" d="M334.78,127.08a53.11,53.11,0,0,1-10.54.84c-11.06.27-10.1-3.36-10.1-13.78V69.08h21v-20h-21V0H287.27V119.71c0,23.5,5.8,34.23,31.08,34.23,6,0,14.21-1.54,20.42-2.87Z"/><path class="cls-1" d="M501.7,133.63a10.14,10.14,0,1,1-10.19,10.14,10.14,10.14,0,0,1,10.19-10.14m0,18.68a8.55,8.55,0,0,0,8.51-8.54,8.5,8.5,0,1,0-8.51,8.54m1.88-3.56-2.05-3h-1.42v3h-2.29v-10H502c2.46,0,4,1.24,4,3.45a3,3,0,0,1-2.08,3.09l2.49,3.42Zm-3.47-5h1.82c1,0,1.74-.4,1.74-1.5s-.7-1.45-1.68-1.45h-1.88Z"/><path class="cls-1" d="M253.72,69V65.46A115.8,115.8,0,0,0,233.14,64c-12.5,0-14,6.63-14,10.23,0,5.08,1.74,7.83,15.29,10.79,19.8,4.45,39.69,9.09,39.69,33.64,0,23.29-12,35.32-37.21,35.32-16.88,0-33.26-3.63-45.76-6.8V127.08h20.35v3.56c8.75,1.69,17.93,1.52,22.73,1.52,13.34,0,15.49-7.17,15.49-11,0-5.29-3.82-7.83-16.32-10.37-23.56-4-42.25-12.07-42.25-36,0-22.65,15.14-31.54,40.37-31.54,17.09,0,30.08,2.65,42.59,5.83V69Z"/><path class="cls-1" d="M127.84,85.09,118,93.69a5.25,5.25,0,1,0,3.19,3.2l8.72-9.75Z"/><path class="cls-1" d="M171.25,127.07V43.46H144.37V51a55,55,0,0,0-18.11-6.77v-9.1h3.28V28.28H102.48v6.83h3.28v9.17a55.32,55.32,0,1,0,38.76,101.87l4.77,7.78h28.38V127.07Zm-26.64-26.83A28.42,28.42,0,0,1,117.73,127v-3.18h-3.22V127a28.43,28.43,0,0,1-26.68-26.89H91V96.91H87.85a28.42,28.42,0,0,1,26.66-26.65v3.16h3.22V70.25A28.42,28.42,0,0,1,144.61,97h-3.2v3.22Z"/><path class="cls-1" d="M456.58,49.11H512v20H498.75l-34,83.62c-9.74,23.48-25.74,45.59-50.1,45.59a93.67,93.67,0,0,1-19.5-2l2.43-24.39a68.7,68.7,0,0,0,10.63,1.1c11.3,0,24-7,28-19.19L401.82,69.06H388.57v-20H444v20H430.78l19.51,48h0l19.51-48H456.58Z"/></g></g></g></g></svg>

After

Width:  |  Height:  |  Size: 2.2 KiB

1363
beemovie.txt Normal file

File diff suppressed because it is too large Load diff

View file

@ -1,18 +0,0 @@
const timeBefore = performance.now();
const requests: Promise<Response>[] = [];
// Repeat 1000 times
for (let i = 0; i < 1000; i++) {
requests.push(
fetch(`https://mastodon.social`, {
method: "GET",
})
);
}
await Promise.all(requests);
const timeAfter = performance.now();
console.log(`Time taken: ${timeAfter - timeBefore}ms`);

View file

@ -1 +0,0 @@
//

46
benchmarks/timeline.ts Normal file
View file

@ -0,0 +1,46 @@
import type { Status } from "@versia/client/schemas";
import {
fakeRequest,
getTestStatuses,
getTestUsers,
} from "@versia-server/tests";
import { bench, run } from "mitata";
import type { z } from "zod";
const { users, tokens, deleteUsers } = await getTestUsers(5);
await getTestStatuses(40, users[0]);
const testTimeline = async (): Promise<void> => {
const response = await fakeRequest("/api/v1/timelines/home", {
headers: {
Authorization: `Bearer ${tokens[0].data.accessToken}`,
},
});
const objects = (await response.json()) as z.infer<typeof Status>[];
if (objects.length !== 20) {
throw new Error("Invalid response (not 20 objects)");
}
};
const testInstance = async (): Promise<void> => {
const response = await fakeRequest("/api/v2/instance", {
headers: {
Authorization: `Bearer ${tokens[0].data.accessToken}`,
},
});
const object = (await response.json()) as Record<string, unknown>;
if (typeof object !== "object") {
throw new Error("Invalid response (not an object)");
}
};
bench("timeline", testTimeline).range("amount", 1, 1000);
bench("instance", testInstance).range("amount", 1, 1000);
await run();
await deleteUsers();

View file

@ -1,56 +0,0 @@
/**
* Usage: TOKEN=your_token_here bun benchmark:timeline <request_count>
*/
import chalk from "chalk";
import { ConfigManager } from "config-manager";
const config = await new ConfigManager({}).getConfig();
const token = process.env.TOKEN;
const requestCount = Number(process.argv[2]) || 100;
if (!token) {
console.log(
`${chalk.red(
"✗"
)} No token provided. Provide one via the TOKEN environment variable.`
);
process.exit(1);
}
const fetchTimeline = () =>
fetch(`${config.http.base_url}/api/v1/timelines/home`, {
headers: {
Authorization: `Bearer ${token}`,
},
}).then(res => res.ok);
const timeNow = performance.now();
const requests = Array.from({ length: requestCount }, () => fetchTimeline());
Promise.all(requests)
.then(results => {
const timeTaken = performance.now() - timeNow;
if (results.every(t => t)) {
console.log(`${chalk.green("✓")} All requests succeeded`);
} else {
console.log(
`${chalk.red("✗")} ${
results.filter(t => !t).length
} requests failed`
);
}
console.log(
`${chalk.green("✓")} ${
requests.length
} requests fulfilled in ${chalk.bold(
(timeTaken / 1000).toFixed(5)
)}s`
);
})
.catch(err => {
console.log(`${chalk.red("✗")} ${err}`);
process.exit(1);
});

178
biome.json Normal file
View file

@ -0,0 +1,178 @@
{
"$schema": "https://biomejs.dev/schemas/2.3.4/schema.json",
"assist": {
"actions": {
"source": {
"organizeImports": "on"
}
}
},
"vcs": {
"clientKind": "git",
"enabled": true,
"useIgnoreFile": true
},
"linter": {
"enabled": true,
"rules": {
"style": {
"useNamingConvention": {
"level": "warn",
"options": {
"requireAscii": false,
"strictCase": false,
"conventions": [
{
"selector": {
"kind": "typeProperty"
},
"formats": [
"camelCase",
"CONSTANT_CASE",
"PascalCase",
"snake_case"
]
},
{
"selector": {
"kind": "objectLiteralProperty",
"scope": "any"
},
"formats": [
"camelCase",
"CONSTANT_CASE",
"PascalCase",
"snake_case"
]
}
]
}
},
"useLiteralEnumMembers": "error",
"noNegationElse": "error",
"noYodaExpression": "error",
"useBlockStatements": "error",
"useCollapsedElseIf": "error",
"useConsistentArrayType": {
"level": "error",
"options": {
"syntax": "shorthand"
}
},
"useConsistentBuiltinInstantiation": "error",
"useExplicitLengthCheck": "error",
"useForOf": "error",
"useNodeAssertStrict": "error",
"useShorthandAssign": "error",
"useThrowNewError": "error",
"useThrowOnlyError": "error",
"useNodejsImportProtocol": "error",
"useAsConstAssertion": "error",
"useEnumInitializers": "error",
"useSelfClosingElements": "error",
"useConst": "error",
"useSingleVarDeclarator": "error",
"noUnusedTemplateLiteral": "error",
"useNumberNamespace": "error",
"useAtIndex": "warn",
"noInferrableTypes": "error",
"useCollapsedIf": "warn",
"useExponentiationOperator": "error",
"useTemplate": "error",
"noParameterAssign": "error",
"noNonNullAssertion": "error",
"useDefaultParameterLast": "error",
"useConsistentMemberAccessibility": {
"level": "warn",
"options": {
"accessibility": "explicit"
}
},
"useImportType": "error",
"useExportType": "error",
"noUselessElse": "error",
"noProcessEnv": "error",
"useShorthandFunctionType": "error",
"useArrayLiterals": "error",
"noCommonJs": "warn",
"noExportedImports": "warn",
"noSubstr": "warn",
"useTrimStartEnd": "warn",
"noRestrictedImports": {
"options": {
"paths": {
"~/packages/": "Use the appropriate package instead of importing from the packages directory directly."
}
},
"level": "error"
}
},
"performance": {
"noDynamicNamespaceImportAccess": "warn"
},
"correctness": {
"useImportExtensions": "error",
"noConstantMathMinMaxClamp": "error",
"noUndeclaredDependencies": "error",
"noUnusedFunctionParameters": "error",
"noUnusedImports": "error",
"noUnusedPrivateClassMembers": "error"
},
"nursery": {
"noFloatingPromises": "error"
},
"complexity": {
"noForEach": "error",
"noImportantStyles": "off",
"noUselessStringConcat": "error",
"useDateNow": "error",
"noUselessStringRaw": "warn",
"noUselessEscapeInRegex": "warn",
"useSimplifiedLogicExpression": "error",
"useWhile": "error",
"useNumericLiterals": "error",
"noArguments": "error",
"noCommaOperator": "error"
},
"suspicious": {
"noDuplicateTestHooks": "error",
"noOctalEscape": "error",
"noTemplateCurlyInString": "warn",
"noEmptyBlockStatements": "error",
"useAdjacentOverloadSignatures": "warn",
"useGuardForIn": "warn",
"noDuplicateElseIf": "warn",
"noEvolvingTypes": "error",
"noIrregularWhitespace": "warn",
"noExportsInTest": "error",
"noVar": "error",
"useAwait": "error",
"useErrorMessage": "error",
"useNumberToFixedDigitsArgument": "error"
}
}
},
"overrides": [
{
"includes": ["**/packages/client/versia/client.ts"],
"linter": {
"rules": {
"style": {
"useNamingConvention": "off"
}
}
}
}
],
"formatter": {
"enabled": true,
"indentStyle": "space",
"indentWidth": 4
},
"javascript": {
"globals": ["HTMLRewriter", "BufferEncoding"]
},
"files": {
"includes": ["**"]
}
}

View file

@ -1,43 +1,55 @@
// Delete dist directory import process from "node:process";
import { rm, cp, mkdir, exists } from "fs/promises"; import { $, build, file, write } from "bun";
import manifest from "./package.json" with { type: "json" };
if (!(await exists("./pages/dist"))) { console.log("Building...");
console.log("Please build the Vite server first, or use `bun prod-build`");
process.exit(1); await $`rm -rf dist && mkdir dist`;
const type = process.argv[2] as "api" | "worker";
if (type !== "api" && type !== "worker") {
throw new Error("Invalid build type. Use 'api' or 'worker'.");
} }
console.log(`Building at ${process.cwd()}`); const packages = Object.keys(manifest.dependencies)
.filter((dep) => dep.startsWith("@versia"))
.filter((dep) => dep !== "@versia-server/tests");
await rm("./dist", { recursive: true }); await build({
entrypoints: [`./${type}.ts`],
await mkdir(process.cwd() + "/dist"); outdir: "dist",
target: "bun",
//bun build --entrypoints ./index.ts ./prisma.ts ./cli.ts --outdir dist --target bun --splitting --minify --external bullmq,@prisma/client splitting: true,
await Bun.build({ minify: true,
entrypoints: [ external: [...packages],
process.cwd() + "/index.ts",
process.cwd() + "/prisma.ts",
process.cwd() + "/cli.ts",
],
outdir: process.cwd() + "/dist",
target: "bun",
splitting: true,
minify: true,
external: ["bullmq"],
}).then(output => {
if (!output.success) {
console.log(output.logs);
}
}); });
// Create pages directory console.log("Copying files...");
// mkdir ./dist/pages
await mkdir(process.cwd() + "/dist/pages");
// Copy Vite build output to dist // Copy each package into dist/node_modules
// cp -r ./pages/dist ./dist/pages for (const pkg of packages) {
await cp(process.cwd() + "/pages/dist", process.cwd() + "/dist/pages/", { const directory = pkg.split("/")[1] || pkg;
recursive: true, await $`mkdir -p dist/node_modules/${pkg}`;
}); // Copy the built package files
await $`cp -rL packages/${directory}/{dist,package.json} dist/node_modules/${pkg}`;
console.log(`Built!`); // Rewrite package.json "exports" field to point to the dist directory and use .js extension
const packageJsonPath = `dist/node_modules/${pkg}/package.json`;
const packageJson = await file(packageJsonPath).json();
for (const [key, value] of Object.entries(packageJson.exports) as [
string,
{ import?: string },
][]) {
if (value.import) {
packageJson.exports[key] = {
import: value.import
.replace("./", "./dist/")
.replace(/\.ts$/, ".js"),
};
}
}
await write(packageJsonPath, JSON.stringify(packageJson, null, 4));
}
console.log("Build complete!");

1739
bun.lock Normal file

File diff suppressed because it is too large Load diff

BIN
bun.lockb

Binary file not shown.

View file

@ -1,2 +1,8 @@
[install.scopes] [install.scopes]
"@jsr" = "https://npm.jsr.io" "@jsr" = "https://npm.jsr.io"
[test]
preload = ["./packages/tests/setup.ts"]
[install]
linker = "hoisted"

View file

@ -1,64 +0,0 @@
import type { APActivity, APActor } from "activitypub-types";
export class RemoteActor {
private actorData: APActor | null;
private actorUri: string;
constructor(actor: APActor | string) {
if (typeof actor === "string") {
this.actorUri = actor;
this.actorData = null;
} else {
this.actorUri = actor.id || "";
this.actorData = actor;
}
}
public async fetch() {
const response = await fetch(this.actorUri);
const actorJson = (await response.json()) as APActor;
this.actorData = actorJson;
}
public getData() {
return this.actorData;
}
}
export class RemoteActivity {
private data: APActivity | null;
private uri: string;
constructor(uri: string, data: APActivity | null) {
this.uri = uri;
this.data = data;
}
public async fetch() {
const response = await fetch(this.uri);
const json = (await response.json()) as APActivity;
this.data = json;
}
public getData() {
return this.data;
}
public async getActor() {
if (!this.data) {
throw new Error("No data");
}
if (Array.isArray(this.data.actor)) {
throw new Error("Multiple actors");
}
if (typeof this.data.actor === "string") {
const actor = new RemoteActor(this.data.actor);
await actor.fetch();
return actor.getData();
}
return new RemoteActor(this.data.actor as any);
}
}

View file

@ -0,0 +1,17 @@
/**
* @packageDocumentation
* @module MediaManager/Utils
*/
import { SHA256 } from "bun";
/**
* Generates a SHA-256 hash for a given file.
* @param file - The file to hash.
* @returns A promise that resolves to the SHA-256 hash of the file in hex format.
*/
export const getMediaHash = async (file: File): Promise<string> => {
const arrayBuffer = await file.arrayBuffer();
const hash = new SHA256().update(arrayBuffer).digest("hex");
return hash;
};

View file

@ -0,0 +1,63 @@
import { describe, expect, it } from "bun:test";
import { mockModule } from "@versia-server/tests";
import sharp from "sharp";
import { calculateBlurhash } from "./blurhash.ts";
describe("BlurhashPreprocessor", () => {
it("should calculate blurhash for a valid image", async () => {
const inputBuffer = await sharp({
create: {
width: 100,
height: 100,
channels: 3,
background: { r: 255, g: 0, b: 0 },
},
})
.png()
.toBuffer();
const inputFile = new File([inputBuffer as BlobPart], "test.png", {
type: "image/png",
});
const result = await calculateBlurhash(inputFile);
expect(result).toBeTypeOf("string");
expect(result).not.toBe("");
});
it("should return null blurhash for an invalid image", async () => {
const invalidFile = new File(["invalid image data"], "invalid.png", {
type: "image/png",
});
const result = await calculateBlurhash(invalidFile);
expect(result).toBeNull();
});
it("should handle errors during blurhash calculation", async () => {
const inputBuffer = await sharp({
create: {
width: 100,
height: 100,
channels: 3,
background: { r: 255, g: 0, b: 0 },
},
})
.png()
.toBuffer();
const inputFile = new File([inputBuffer as BlobPart], "test.png", {
type: "image/png",
});
using __ = await mockModule("blurhash", () => ({
encode: (): void => {
throw new Error("Test error");
},
}));
const result = await calculateBlurhash(inputFile);
expect(result).toBeNull();
});
});

View file

@ -0,0 +1,37 @@
import { encode } from "blurhash";
import sharp from "sharp";
export const calculateBlurhash = async (file: File): Promise<string | null> => {
try {
const arrayBuffer = await file.arrayBuffer();
const metadata = await sharp(arrayBuffer).metadata();
return new Promise<string | null>((resolve) => {
sharp(arrayBuffer)
.raw()
.ensureAlpha()
.toBuffer((err, buffer) => {
if (err) {
resolve(null);
return;
}
try {
resolve(
encode(
new Uint8ClampedArray(buffer),
metadata?.width ?? 0,
metadata?.height ?? 0,
4,
4,
) as string,
);
} catch {
resolve(null);
}
});
});
} catch {
return null;
}
};

View file

@ -0,0 +1,134 @@
import { describe, expect, it } from "bun:test";
import sharp from "sharp";
import { convertImage } from "./image-conversion.ts";
describe("ImageConversionPreprocessor", () => {
it("should convert a JPEG image to WebP", async () => {
const inputBuffer = await sharp({
create: {
width: 100,
height: 100,
channels: 3,
background: { r: 255, g: 0, b: 0 },
},
})
.jpeg()
.toBuffer();
const inputFile = new File([inputBuffer as BlobPart], "test.jpg", {
type: "image/jpeg",
});
const result = await convertImage(inputFile, "image/webp");
expect(result.type).toBe("image/webp");
expect(result.name).toBe("test.webp");
const resultBuffer = await result.arrayBuffer();
const metadata = await sharp(resultBuffer).metadata();
expect(metadata.format).toBe("webp");
});
it("should not convert SVG when convert_vector is false", async () => {
const svgContent =
'<svg xmlns="http://www.w3.org/2000/svg"><rect width="100" height="100" fill="red"/></svg>';
const inputFile = new File([svgContent], "test.svg", {
type: "image/svg+xml",
});
const result = await convertImage(inputFile, "image/webp");
expect(result).toBe(inputFile);
});
it("should convert SVG when convert_vector is true", async () => {
const svgContent =
'<svg xmlns="http://www.w3.org/2000/svg"><rect width="100" height="100" fill="red"/></svg>';
const inputFile = new File([svgContent], "test.svg", {
type: "image/svg+xml",
});
const result = await convertImage(inputFile, "image/webp", {
convertVectors: true,
});
expect(result.type).toBe("image/webp");
expect(result.name).toBe("test.webp");
});
it("should not convert unsupported file types", async () => {
const inputFile = new File(["test content"], "test.txt", {
type: "text/plain",
});
const result = await convertImage(inputFile, "image/webp");
expect(result).toBe(inputFile);
});
it("should throw an error for unsupported output format", async () => {
const inputBuffer = await sharp({
create: {
width: 100,
height: 100,
channels: 3,
background: { r: 255, g: 0, b: 0 },
},
})
.png()
.toBuffer();
const inputFile = new File([inputBuffer as BlobPart], "test.png", {
type: "image/png",
});
await expect(convertImage(inputFile, "image/bmp")).rejects.toThrow(
"Unsupported output format: image/bmp",
);
});
it("should convert animated GIF to WebP while preserving animation", async () => {
// Create a simple animated GIF
const inputBuffer = await sharp({
create: {
width: 100,
height: 100,
channels: 4,
background: { r: 255, g: 0, b: 0, alpha: 1 },
},
})
.gif()
.toBuffer();
const inputFile = new File([inputBuffer as BlobPart], "animated.gif", {
type: "image/gif",
});
const result = await convertImage(inputFile, "image/webp");
expect(result.type).toBe("image/webp");
expect(result.name).toBe("animated.webp");
const resultBuffer = await result.arrayBuffer();
const metadata = await sharp(resultBuffer).metadata();
expect(metadata.format).toBe("webp");
});
it("should handle files with spaces in the name", async () => {
const inputBuffer = await sharp({
create: {
width: 100,
height: 100,
channels: 3,
background: { r: 255, g: 0, b: 0 },
},
})
.png()
.toBuffer();
const inputFile = new File(
[inputBuffer as BlobPart],
"test image with spaces.png",
{ type: "image/png" },
);
const result = await convertImage(inputFile, "image/webp");
expect(result.type).toBe("image/webp");
expect(result.name).toBe("test image with spaces.webp");
});
});

View file

@ -0,0 +1,109 @@
/**
* @packageDocumentation
* @module MediaManager/Preprocessors
*/
import sharp from "sharp";
/**
* Supported input media formats.
*/
const supportedInputFormats = [
"image/png",
"image/jpeg",
"image/webp",
"image/avif",
"image/svg+xml",
"image/gif",
"image/tiff",
];
/**
* Supported output media formats.
*/
const supportedOutputFormats = [
"image/jpeg",
"image/png",
"image/webp",
"image/avif",
"image/gif",
"image/tiff",
];
/**
* Checks if a file is convertible.
* @param file - The file to check.
* @returns True if the file is convertible, false otherwise.
*/
const isConvertible = (
file: File,
options?: { convertVectors?: boolean },
): boolean => {
if (file.type === "image/svg+xml" && !options?.convertVectors) {
return false;
}
return supportedInputFormats.includes(file.type);
};
/**
* Extracts the filename from a path.
* @param path - The path to extract the filename from.
* @returns The extracted filename.
*/
const extractFilenameFromPath = (path: string): string => {
const pathParts = path.split(/(?<!\\)\//);
return pathParts.at(-1) as string;
};
/**
* Replaces the file extension in the filename.
* @param fileName - The original filename.
* @param newExtension - The new extension.
* @returns The filename with the new extension.
*/
const getReplacedFileName = (fileName: string, newExtension: string): string =>
extractFilenameFromPath(fileName).replace(/\.[^/.]+$/, `.${newExtension}`);
/**
* Converts an image file to the format specified in the configuration.
*
* @param file - The image file to convert.
* @param targetFormat - The target format to convert to.
* @returns The converted image file.
*/
export const convertImage = async (
file: File,
targetFormat: string,
options?: {
convertVectors?: boolean;
},
): Promise<File> => {
if (!isConvertible(file, options)) {
return file;
}
if (!supportedOutputFormats.includes(targetFormat)) {
throw new Error(`Unsupported output format: ${targetFormat}`);
}
const sharpCommand = sharp(await file.arrayBuffer(), {
animated: true,
});
const commandName = targetFormat.split("/")[1] as
| "jpeg"
| "png"
| "webp"
| "avif"
| "gif"
| "tiff";
const convertedBuffer = await sharpCommand[commandName]().toBuffer();
return new File(
[convertedBuffer as BlobPart],
getReplacedFileName(file.name, commandName),
{
type: targetFormat,
lastModified: Date.now(),
},
);
};

1751
cli.ts

File diff suppressed because it is too large Load diff

36
cli/index.ts Normal file
View file

@ -0,0 +1,36 @@
import { completionsPlugin } from "@clerc/plugin-completions";
import { friendlyErrorPlugin } from "@clerc/plugin-friendly-error";
import { helpPlugin } from "@clerc/plugin-help";
import { notFoundPlugin } from "@clerc/plugin-not-found";
import { versionPlugin } from "@clerc/plugin-version";
import { setupDatabase } from "@versia-server/kit/db";
import { searchManager } from "@versia-server/kit/search";
import { Clerc } from "clerc";
import pkg from "../package.json" with { type: "json" };
import { rebuildIndexCommand } from "./index/rebuild.ts";
import { refetchInstanceCommand } from "./instance/refetch.ts";
import { createUserCommand } from "./user/create.ts";
import { deleteUserCommand } from "./user/delete.ts";
import { refetchUserCommand } from "./user/refetch.ts";
import { generateTokenCommand } from "./user/token.ts";
await setupDatabase(false);
await searchManager.connect(true);
Clerc.create()
.scriptName("cli")
.name("Versia Server CLI")
.description("CLI interface for Versia Server")
.version(pkg.version)
.use(helpPlugin())
.use(versionPlugin())
.use(completionsPlugin())
.use(notFoundPlugin())
.use(friendlyErrorPlugin())
.command(createUserCommand)
.command(deleteUserCommand)
.command(generateTokenCommand)
.command(refetchUserCommand)
.command(rebuildIndexCommand)
.command(refetchInstanceCommand)
.parse();

62
cli/index/rebuild.ts Normal file
View file

@ -0,0 +1,62 @@
import { config } from "@versia-server/config";
import { SonicIndexType, searchManager } from "@versia-server/kit/search";
// @ts-expect-error - Root import is required or the Clec type definitions won't work
// biome-ignore lint/correctness/noUnusedImports: Root import is required or the Clec type definitions won't work
import { defineCommand, type Root } from "clerc";
import ora from "ora";
export const rebuildIndexCommand = defineCommand(
{
name: "index rebuild",
description: "Rebuild the search index.",
parameters: ["<type>"],
flags: {
"batch-size": {
description: "Number of records to process at once",
type: Number,
alias: "b",
default: 100,
},
},
},
async (context) => {
const { "batch-size": batchSize } = context.flags;
const { type } = context.parameters;
if (!config.search.enabled) {
throw new Error(
"Search is not enabled in the instance configuration.",
);
}
const spinner = ora("Rebuilding search indexes").start();
switch (type) {
case "accounts":
await searchManager.rebuildSearchIndexes(
[SonicIndexType.Accounts],
batchSize,
(progress) => {
spinner.text = `Rebuilding search indexes (${(progress * 100).toFixed(2)}%)`;
},
);
break;
case "statuses":
await searchManager.rebuildSearchIndexes(
[SonicIndexType.Statuses],
batchSize,
(progress) => {
spinner.text = `Rebuilding search indexes (${(progress * 100).toFixed(2)}%)`;
},
);
break;
default: {
throw new Error(
"Invalid index type. Can be 'accounts' or 'statuses'.",
);
}
}
spinner.succeed("Search indexes rebuilt");
},
);

37
cli/instance/refetch.ts Normal file
View file

@ -0,0 +1,37 @@
import { Instance } from "@versia-server/kit/db";
import { FetchJobType, fetchQueue } from "@versia-server/kit/queues/fetch";
import { Instances } from "@versia-server/kit/tables";
import chalk from "chalk";
// @ts-expect-error - Root import is required or the Clec type definitions won't work
// biome-ignore lint/correctness/noUnusedImports: Root import is required or the Clec type definitions won't work
import { defineCommand, type Root } from "clerc";
import { eq } from "drizzle-orm";
export const refetchInstanceCommand = defineCommand(
{
name: "instance refetch",
description: "Refetches metadata from remote instances.",
parameters: ["<url_or_host>"],
},
async (context) => {
const { urlOrHost } = context.parameters;
const host = URL.canParse(urlOrHost)
? new URL(urlOrHost).host
: urlOrHost;
const instance = await Instance.fromSql(eq(Instances.baseUrl, host));
if (!instance) {
throw new Error(`Instance ${chalk.gray(host)} not found.`);
}
await fetchQueue.add(FetchJobType.Instance, {
uri: new URL(`https://${instance.data.baseUrl}`).origin,
});
console.info(
`Refresh job enqueued for ${chalk.gray(instance.data.baseUrl)}.`,
);
},
);

90
cli/user/create.ts Normal file
View file

@ -0,0 +1,90 @@
import { config } from "@versia-server/config";
import { User } from "@versia-server/kit/db";
import { searchManager } from "@versia-server/kit/search";
import { Users } from "@versia-server/kit/tables";
import chalk from "chalk";
// @ts-expect-error - Root import is required or the Clec type definitions won't work
// biome-ignore lint/correctness/noUnusedImports: Root import is required or the Clec type definitions won't work
import { defineCommand, type Root } from "clerc";
import { and, eq, isNull } from "drizzle-orm";
import { renderUnicodeCompact } from "uqr";
export const createUserCommand = defineCommand(
{
name: "user create",
description: "Create a new user.",
parameters: ["<username>"],
flags: {
password: {
description: "Password for the new user",
type: String,
alias: "p",
},
email: {
description: "Email for the new user",
type: String,
alias: "e",
},
admin: {
description: "Make the new user an admin",
type: Boolean,
alias: "a",
},
},
},
async (context) => {
const { admin, email, password } = context.flags;
const { username } = context.parameters;
if (!/^[a-z0-9_-]+$/.test(username)) {
throw new Error("Username must be alphanumeric and lowercase.");
}
// Check if user already exists
const existingUser = await User.fromSql(
and(eq(Users.username, username), isNull(Users.instanceId)),
);
if (existingUser) {
throw new Error(`User ${chalk.gray(username)} is taken.`);
}
const user = await User.register(username, {
email,
password,
isAdmin: admin,
});
// Add to search index
await searchManager.addUser(user);
if (!user) {
throw new Error("Failed to create user.");
}
console.info(`User ${chalk.gray(username)} created.`);
if (!password) {
const token = await user.resetPassword();
const link = new URL(
`${config.frontend.routes.password_reset}?${new URLSearchParams(
{
token,
},
)}`,
config.http.base_url,
);
console.info(`Password reset link for ${chalk.gray(username)}:`);
console.info(chalk.blue(link.href));
const qrcode = renderUnicodeCompact(link.href, {
border: 2,
});
// Pad all lines of QR code with spaces
console.info(`\n ${qrcode.replaceAll("\n", "\n ")}`);
}
},
);

60
cli/user/delete.ts Normal file
View file

@ -0,0 +1,60 @@
import confirm from "@inquirer/confirm";
import chalk from "chalk";
// @ts-expect-error - Root import is required or the Clec type definitions won't work
// biome-ignore lint/correctness/noUnusedImports: Root import is required or the Clec type definitions won't work
import { defineCommand, type Root } from "clerc";
import { retrieveUser } from "../utils.ts";
export const deleteUserCommand = defineCommand(
{
name: "user delete",
alias: "user rm",
description:
"Delete a user from the database. Can use username or handle.",
parameters: ["<username_or_handle>"],
flags: {
confirm: {
description: "Ask for confirmation before deleting the user",
type: Boolean,
alias: "c",
default: true,
},
},
},
async (context) => {
const { confirm: confirmFlag } = context.flags;
const { usernameOrHandle } = context.parameters;
const user = await retrieveUser(usernameOrHandle);
if (!user) {
throw new Error(`User ${chalk.gray(usernameOrHandle)} not found.`);
}
console.info(`About to delete user ${chalk.gray(user.data.username)}!`);
console.info(`Username: ${chalk.blue(user.data.username)}`);
console.info(`Display Name: ${chalk.blue(user.data.displayName)}`);
console.info(`Created At: ${chalk.blue(user.data.createdAt)}`);
console.info(
`Instance: ${chalk.blue(user.data.instance?.baseUrl || "Local")}`,
);
if (confirmFlag) {
const choice = await confirm({
message: `Are you sure you want to delete this user? ${chalk.red(
"This is irreversible.",
)}`,
});
if (!choice) {
throw new Error("Operation aborted.");
}
}
await user.delete();
console.info(
`User ${chalk.gray(user.data.username)} has been deleted.`,
);
},
);

43
cli/user/refetch.ts Normal file
View file

@ -0,0 +1,43 @@
import { User } from "@versia-server/kit/db";
import chalk from "chalk";
// @ts-expect-error - Root import is required or the Clec type definitions won't work
// biome-ignore lint/correctness/noUnusedImports: Root import is required or the Clec type definitions won't work
import { defineCommand, type Root } from "clerc";
import ora from "ora";
import { retrieveUser } from "../utils.ts";
export const refetchUserCommand = defineCommand(
{
name: "user refetch",
description: "Refetches user data from their remote instance.",
parameters: ["<handle>"],
},
async (context) => {
const { handle } = context.parameters;
const user = await retrieveUser(handle);
if (!user) {
throw new Error(`User ${chalk.gray(handle)} not found.`);
}
if (user.local) {
throw new Error(
"This user is local and as such cannot be refetched.",
);
}
const spinner = ora("Refetching user").start();
try {
await User.fromVersia(user.uri);
} catch (error) {
spinner.fail(
`Failed to refetch user ${chalk.gray(user.data.username)}`,
);
throw error;
}
spinner.succeed(`User ${chalk.gray(user.data.username)} refetched.`);
},
);

50
cli/user/token.ts Normal file
View file

@ -0,0 +1,50 @@
import { Client, Token } from "@versia-server/kit/db";
import { randomUUIDv7 } from "bun";
import chalk from "chalk";
// @ts-expect-error - Root import is required or the Clec type definitions won't work
// biome-ignore lint/correctness/noUnusedImports: Root import is required or the Clec type definitions won't work
import { defineCommand, type Root } from "clerc";
import { randomString } from "@/math.ts";
import { retrieveUser } from "../utils.ts";
export const generateTokenCommand = defineCommand(
{
name: "user token",
description: "Generates a new access token for a user.",
parameters: ["<username>"],
},
async (context) => {
const { username } = context.parameters;
const user = await retrieveUser(username);
if (!user) {
throw new Error(`User ${chalk.gray(username)} not found.`);
}
const application = await Client.insert({
id:
user.id +
Buffer.from(
crypto.getRandomValues(new Uint8Array(32)),
).toString("base64"),
name: "Versia",
redirectUris: [],
scopes: ["openid", "profile", "email"],
secret: "",
});
const token = await Token.insert({
id: randomUUIDv7(),
accessToken: randomString(64, "base64url"),
scopes: ["read", "write", "follow"],
userId: user.id,
clientId: application.id,
});
console.info(
`Token generated for user ${chalk.gray(user.data.username)}.`,
);
console.info(`Access Token: ${chalk.blue(token.data.accessToken)}`);
},
);

23
cli/utils.ts Normal file
View file

@ -0,0 +1,23 @@
import { Instance, User } from "@versia-server/kit/db";
import { parseUserAddress } from "@versia-server/kit/parsers";
import { Users } from "@versia-server/kit/tables";
import { and, eq, isNull } from "drizzle-orm";
export const retrieveUser = async (
usernameOrHandle: string,
): Promise<User | null> => {
const { username, domain } = parseUserAddress(usernameOrHandle);
const instance = domain ? await Instance.resolveFromHost(domain) : null;
const user = await User.fromSql(
and(
eq(Users.username, username),
instance
? eq(Users.instanceId, instance.data.id)
: isNull(Users.instanceId),
),
);
return user;
};

1
config/config Symbolic link
View file

@ -0,0 +1 @@
../config

View file

@ -1,289 +1,480 @@
[database] # You can change the URL to the commit/tag you are using
#:schema https://raw.githubusercontent.com/versia-pub/server/main/config/config.schema.json
# All values marked as "sensitive" can be set to "PATH:/path/to/file" to read the value from a file (e.g. a secret manager)
[postgres]
# PostgreSQL database configuration
host = "localhost" host = "localhost"
port = 5432 port = 5432
username = "lysand" username = "versia"
password = "password123" # Sensitive value
database = "lysand" password = "mycoolpassword"
database = "versia"
# Additional read-only replicas
# [[postgres.replicas]]
# host = "other-host"
# port = 5432
# username = "versia"
# password = "mycoolpassword2"
# database = "replica1"
[redis.queue] [redis.queue]
# A Redis database used for managing queues.
# Required for federation
host = "localhost" host = "localhost"
port = 6379 port = 6379
password = "" # Sensitive value
# password = "test"
database = 0 database = 0
[redis.cache] # A Redis database used for caching SQL queries.
host = "localhost" # Optional, can be the same as the queue instance
port = 6379 # [redis.cache]
password = "" # host = "localhost"
database = 1 # port = 6380
# database = 1
# password = ""
# Search and indexing configuration
[search]
# Enable indexing and searching?
enabled = false enabled = false
[meilisearch] # Optional if search is disabled
host = "localhost" # [search.sonic]
port = 40007 # host = "localhost"
api_key = "" # port = 7700
enabled = true # Sensitive value
# password = "test"
[signups] [registration]
# URL of your Terms of Service # Can users sign up freely?
tos_url = "https://example.com/tos" allow = true
# Whether to enable registrations or not # NOT IMPLEMENTED
registration = true require_approval = false
rules = [ # Message to show to users when registration is disabled
"Do not harass others", # message = "ran out of spoons to moderate registrations, sorry"
"Be nice to people",
"Don't spam",
"Don't post illegal content",
]
# Delete this section if you don't want to use custom OAuth providers
# This is an example configuration
# The provider MUST support OpenID Connect with .well-known discovery
# Most notably, GitHub does not support this
[[oidc.providers]]
name = "CPlusPatch ID"
id = "cpluspatch-id"
url = "https://id.cpluspatch.com/application/o/lysand-testing/"
client_id = "XXXXXXXXXXXXXXXX"
client_secret = "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX"
icon = "https://cpluspatch.com/images/icons/logo.svg"
[http] [http]
base_url = "https://lysand.social" # URL that the instance will be accessible at
bind = "http://localhost" base_url = "https://example.com"
bind_port = "8080" # Address to bind to (0.0.0.0 is suggested for proxies)
bind = "0.0.0.0"
bind_port = 8080
# Bans IPv4 or IPv6 IPs (wildcards, networks and ranges are supported) # Bans IPv4 or IPv6 IPs (wildcards, networks and ranges are supported)
banned_ips = [] banned_ips = []
# Banned user agents, regex format
banned_user_agents = [
# "curl\/7.68.0",
# "wget\/1.20.3",
]
[smtp] # URL to an eventual HTTP proxy
# Will be used for all outgoing requests
# proxy_address = "http://localhost:8118"
# TLS configuration. You should probably be using a reverse proxy instead of this
# [http.tls]
# key = "/path/to/key.pem"
# cert = "/path/to/cert.pem"
# Sensitive value
# passphrase = "awawa"
# ca = "/path/to/ca.pem"
[frontend]
# Enable custom frontends (warning: not enabling this will make Versia Server only accessible via the Mastodon API)
# Frontends also control the OpenID flow, so if you disable this, you will need to use the Mastodon frontend
enabled = true
# Path that frontend files are served from
# Edit this property to serve custom frontends
# If this is not set, Versia Server will also check
# the VERSIA_FRONTEND_PATH environment variable
# path = ""
[frontend.routes]
# Special routes for your frontend, below are the defaults for Versia-FE
# Can be set to a route already used by Versia Server, as long as it is on a different HTTP method
# e.g. /oauth/authorize is a POST-only route, so you can serve a GET route at /oauth/authorize
# home = "/"
# login = "/oauth/authorize"
# consent = "/oauth/consent"
# register = "/register"
# password_reset = "/oauth/reset"
[frontend.settings]
# Arbitrary key/value pairs to be passed to the frontend
# This can be used to set up custom themes, etc on supported frontends.
# theme = "dark"
# NOT IMPLEMENTED
[email]
# Enable email sending
send_emails = false
# If send_emails is true, the following settings are required
# [email.smtp]
# SMTP server to use for sending emails # SMTP server to use for sending emails
server = "smtp.example.com" # server = "smtp.example.com"
port = 465 # port = 465
username = "test@example.com" # username = "test@example.com"
password = "password123" # Sensitive value
tls = true # password = "password123"
# tls = true
[media] [media]
# Can be "s3" or "local", where "local" uploads the file to the local filesystem # Can be "s3" or "local", where "local" uploads the file to the local filesystem
# If you need to change this value after setting up your instance, you must move all the files # Changing this value will not retroactively apply to existing data
# from one backend to the other manually # Don't forget to fill in the s3 config :3
backend = "s3" backend = "s3"
# Whether to check the hash of media when uploading to avoid duplication
deduplicate_media = true
# If media backend is "local", this is the folder where the files will be stored # If media backend is "local", this is the folder where the files will be stored
local_uploads_folder = "uploads" # Can be any path
uploads_path = "uploads"
[media.conversion] [media.conversion]
convert_images = false # Whether to automatically convert images to another format on upload
# Can be: "jxl", "webp", "avif", "png", "jpg", "heif" convert_images = true
# Can be: "image/jxl", "image/webp", "image/avif", "image/png", "image/jpeg", "image/heif", "image/gif"
# JXL support will likely not work # JXL support will likely not work
convert_to = "webp" convert_to = "image/webp"
# Also convert SVG images?
convert_vectors = false
[s3] # [s3]
# Can be left blank if you don't use the S3 media backend # Can be left commented if you don't use the S3 media backend
endpoint = "https://s3-us-west-2.amazonaws.com" # endpoint = "https://s3.example.com"
access_key = "" # Sensitive value
secret_access_key = "" # access_key = "XXXXX"
region = "us-west-2" # Sensitive value
bucket_name = "lysand" # secret_access_key = "XXX"
public_url = "https://cdn.example.com" # region = "us-east-1"
# bucket_name = "versia"
[email] # public_url = "https://cdn.example.com"
# Sends an email to moderators when a report is received # Adds a prefix to the uploaded files
# NOT IMPLEMENTED # path = "versia"
send_on_report = false # Use path-style URLs during upload (e.g. https://s3.example.com/versia)
# Sends an email to moderators when a user is suspended # instead of the default virtual-hosted style (e.g. https://versia.s3.example.com)
# NOT IMPLEMENTED # This is required for some S3-compatible services, such as MinIO
send_on_suspend = false # path_style = true
# Sends an email to moderators when a user is unsuspended
# NOT IMPLEMENTED
send_on_unsuspend = false
[validation] [validation]
# Self explanatory # Checks user data
max_displayname_size = 50 # Does not retroactively apply to previously entered data
max_bio_size = 160 [validation.accounts]
max_note_size = 5000 max_displayname_characters = 50
max_avatar_size = 5_000_000 max_username_characters = 30
max_header_size = 5_000_000 max_bio_characters = 5000
max_media_size = 40_000_000 max_avatar_bytes = 5_000_000
max_media_attachments = 10 max_header_bytes = 5_000_000
max_media_description_size = 1000 # Regex is allowed here
max_poll_options = 20 disallowed_usernames = [
max_poll_option_size = 500 "well-known",
min_poll_duration = 60 "about",
max_poll_duration = 1893456000 "activities",
max_username_size = 30 "api",
# An array of strings, defaults are from Akkoma "auth",
username_blacklist = [ "dev",
".well-known", "inbox",
"~", "internal",
"about", "main",
"activities", "media",
"api", "nodeinfo",
"auth", "notice",
"dev", "oauth",
"inbox", "objects",
"internal", "proxy",
"main", "push",
"media", "registration",
"nodeinfo", "relay",
"notice", "settings",
"oauth", "status",
"objects", "tag",
"proxy", "users",
"push", "web",
"registration", "search",
"relay", "mfa",
"settings",
"status",
"tag",
"users",
"web",
"search",
"mfa",
] ]
# Whether to blacklist known temporary email providers max_field_count = 10
blacklist_tempmail = false max_field_name_characters = 1000
# Additional email providers to blacklist max_field_value_characters = 1000
email_blacklist = [] max_pinned_notes = 20
# Valid URL schemes, otherwise the URL is parsed as text
url_scheme_whitelist = [
"http",
"https",
"ftp",
"dat",
"dweb",
"gopher",
"hyper",
"ipfs",
"ipns",
"irc",
"xmpp",
"ircs",
"magnet",
"mailto",
"mumble",
"ssb",
"gemini",
] # NOT IMPLEMENTED
enforce_mime_types = false [validation.notes]
allowed_mime_types = [ max_characters = 5000
"image/jpeg", allowed_url_schemes = [
"image/png", "http",
"image/gif", "https",
"image/heic", "ftp",
"image/heif", "dat",
"image/webp", "dweb",
"image/avif", "gopher",
"video/webm", "hyper",
"video/mp4", "ipfs",
"video/quicktime", "ipns",
"video/ogg", "irc",
"audio/wave", "xmpp",
"audio/wav", "ircs",
"audio/x-wav", "magnet",
"audio/x-pn-wave", "mailto",
"audio/vnd.wave", "mumble",
"audio/ogg", "ssb",
"audio/vorbis", "gemini",
"audio/mpeg",
"audio/mp3",
"audio/webm",
"audio/flac",
"audio/aac",
"audio/m4a",
"audio/x-m4a",
"audio/mp4",
"audio/3gpp",
"video/x-ms-asf",
] ]
max_attachments = 16
[validation.media]
max_bytes = 40_000_000
max_description_characters = 1000
# An empty array allows all MIME types
allowed_mime_types = []
[validation.emojis]
max_bytes = 1_000_000
max_shortcode_characters = 100
max_description_characters = 1000
[validation.polls]
max_options = 20
max_option_characters = 500
min_duration_seconds = 60
# 100 days
max_duration_seconds = 8_640_000
[validation.emails]
# Blocks over 10,000 common tempmail domains
disallow_tempmail = false
# Regex is allowed here
disallowed_domains = []
# [validation.challenges]
# "Challenges" (aka captchas) are a way to verify that a user is human
# Versia Server's challenges use no external services, and are proof-of-work based
# This means that they do not require any user interaction, instead
# they require the user's computer to do a small amount of work
# The difficulty of the challenge, higher is will take more time to solve
# difficulty = 50000
# Challenge expiration time in seconds
# expiration = 300 # 5 minutes
# Leave this empty to generate a new key
# Sensitive value
# key = ""
# Block content that matches these regular expressions
[validation.filters]
note_content = [
# "(https?://)?(www\\.)?youtube\\.com/watch\\?v=[a-zA-Z0-9_-]+",
# "(https?://)?(www\\.)?youtu\\.be/[a-zA-Z0-9_-]+",
]
emoji_shortcode = []
username = []
displayname = []
bio = []
[notifications]
# Web Push Notifications configuration.
# Leave out to disable.
# [notifications.push]
# Subject field embedded in the push notification
# subject = "mailto:joe@example.com"
#
# [notifications.push.vapid_keys]
# VAPID keys for push notifications
# Run Versia Server with those values missing to generate new keys
# Sensitive value
# public = ""
# Sensitive value
# private = ""
[defaults] [defaults]
# Default visibility for new notes # Default visibility for new notes
# Can be public, unlisted, private or direct
# Private only sends to followers, unlisted doesn't show up in timelines
visibility = "public" visibility = "public"
# Default language for new notes # Default language for new notes (ISO code)
language = "en" language = "en"
# Default avatar, must be a valid URL or "" # Default avatar, must be a valid URL or left out for a placeholder avatar
avatar = "" # avatar = ""
# Default header, must be a valid URL or "" # Default header, must be a valid URL or left out for none
header = "" # header = ""
# A style name from https://www.dicebear.com/styles
placeholder_style = "thumbs"
[activitypub] [queues]
# Use ActivityPub Tombstones instead of deleting objects # Controls the delivery queue (for outbound federation)
use_tombstones = true [queues.delivery]
# Fetch all members of collections (followers, following, etc) when receiving them # Time in seconds to remove completed jobs
# WARNING: This can be a lot of data, and is not recommended remove_after_complete_seconds = 31536000
fetch_all_collection_members = false # NOT IMPLEMENTED # Time in seconds to remove failed jobs
remove_after_failure_seconds = 31536000
# The following values must be instance domain names without "https" or glob patterns # Controls the inbox processing queue (for inbound federation)
# Rejects all activities from these instances (fediblocking) [queues.inbox]
reject_activities = [] # Time in seconds to remove completed jobs
# Force posts from this instance to be followers only remove_after_complete_seconds = 31536000
force_followers_only = [] # NOT IMPLEMENTED # Time in seconds to remove failed jobs
# Discard all reports from these instances remove_after_failure_seconds = 31536000
discard_reports = [] # NOT IMPLEMENTED
# Discard all deletes from these instances
discard_deletes = []
# Discard all updates (edits) from these instances
discard_updates = []
# Discard all banners from these instances
discard_banners = [] # NOT IMPLEMENTED
# Discard all avatars from these instances
discard_avatars = [] # NOT IMPLEMENTED
# Discard all follow requests from these instances
discard_follows = []
# Force set these instances' media as sensitive
force_sensitive = [] # NOT IMPLEMENTED
# Remove theses instances' media
remove_media = [] # NOT IMPLEMENTED
# Whether to verify HTTP signatures for every request (warning: can slow down your server # Controls the fetch queue (for remote data refreshes)
# significantly depending on processing power) [queues.fetch]
authorized_fetch = false # Time in seconds to remove completed jobs
remove_after_complete_seconds = 31536000
# Time in seconds to remove failed jobs
remove_after_failure_seconds = 31536000
# Controls the push queue (for push notification delivery)
[queues.push]
# Time in seconds to remove completed jobs
remove_after_complete_seconds = 31536000
# Time in seconds to remove failed jobs
remove_after_failure_seconds = 31536000
# Controls the media queue (for media processing)
[queues.media]
# Time in seconds to remove completed jobs
remove_after_complete_seconds = 31536000
# Time in seconds to remove failed jobs
remove_after_failure_seconds = 31536000
[federation]
# This is a list of domain names, such as "mastodon.social" or "pleroma.site"
# These changes will not retroactively apply to existing data before they were changed
# For that, please use the CLI (in a later release)
# These instances will not be federated with
blocked = []
# These instances' data will only be shown to followers, not in public timelines
followers_only = []
[federation.discard]
# These objects will be discarded when received from these instances
reports = []
deletes = []
updates = []
media = []
follows = []
# If instance reactions are blocked, likes will also be discarded
likes = []
reactions = []
banners = []
avatars = []
# For bridge software, such as versia-pub/activitypub
# Bridges must be hosted separately from the main Versia Server process
# [federation.bridge]
# Only versia-ap exists for now
# software = "versia-ap"
# If this is empty, any bridge with the correct token
# will be able to send data to your instance
# v4, v6, ranges and wildcards are supported
# allowed_ips = ["192.168.1.0/24"]
# Token for the bridge software
# Bridge must have the same token!
# Sensitive value
# token = "mycooltoken"
# url = "https://ap.versia.social"
[instance] [instance]
name = "Lysand" name = "Versia"
description = "A test instance of Lysand" description = "A Versia Server instance"
# URL to your instance logo (jpg files should be renamed to jpeg)
logo = ""
# URL to your instance banner (jpg files should be renamed to jpeg)
banner = ""
# Paths to instance long description, terms of service, and privacy policy
# These will be parsed as Markdown
#
# extended_description_path = "config/extended_description.md"
# tos_path = "config/tos.md"
# privacy_policy_path = "config/privacy_policy.md"
[filters] # Primary instance languages. ISO 639-1 codes.
# Drop notes with these regex filters (only applies to new activities) languages = ["en"]
note_filters = [
# "(https?://)?(www\\.)?youtube\\.com/watch\\?v=[a-zA-Z0-9_-]+", [instance.contact]
# "(https?://)?(www\\.)?youtu\\.be/[a-zA-Z0-9_-]+", # email = "staff@yourinstance.com"
]
# Drop users with these regex filters (only applies to new activities) [instance.branding]
username_filters = [] # logo = "https://cdn.example.com/logo.png"
# Drop users with these regex filters (only applies to new activities) # banner = "https://cdn.example.com/banner.png"
displayname_filters = []
# Drop users with these regex filters (only applies to new activities) # Used for federation. If left empty or missing, the server will generate one for you.
bio_filters = [] # [instance.keys]
emoji_filters = [] # NOT IMPLEMENTED # Sensitive value
# public = ""
# Sensitive value
# private = ""
[[instance.rules]]
# Short description of the rule
text = "No hate speech"
# Longer version of the rule with additional information
hint = "Hate speech includes slurs, threats, and harassment."
[[instance.rules]]
text = "No spam"
# [[instance.rules]]
# ...etc
[permissions]
# Control default permissions for users
# Note that an anonymous user having a permission will not allow them
# to do things that require authentication (e.g. 'owner:notes' -> posting a note will need
# auth, but viewing a note will not)
# See https://server.versia.pub/api/roles#list-of-permissions for a list of all permissions
# Defaults to being able to login and manage their own content
# anonymous = []
# Defaults to identical to anonymous
# default = []
# Defaults to being able to manage all instance data, content, and users
# admin = []
[logging] [logging]
# Log all requests (warning: this is a lot of data)
log_requests = true
# Log request and their contents (warning: this is a lot of data)
log_requests_verbose = false
# For GDPR compliance, you can disable logging of IPs
log_ip = false
# Log all filtered objects # Available levels: trace, debug, info, warning, error, fatal
log_filters = true log_level = "info" # For console output
[ratelimits] # [logging.file]
# Amount to multiply every route's duration by # path = "logs/versia.log"
duration_coeff = 1.0 # log_level = "info"
# Amount to multiply every route's max by #
max_coeff = 1.0 # [logging.file.rotation]
# max_size = 10_000_000 # 10 MB
# max_files = 10 # Keep 10 rotated files
#
# https://sentry.io support
# [logging.sentry]
# dsn = "https://example.com"
# debug = false
# sample_rate = 1.0
# traces_sample_rate = 1.0
# Can also be regex
# trace_propagation_targets = []
# max_breadcrumbs = 100
# environment = "production"
# log_level = "info"
[custom_ratelimits] [authentication]
# Add in any API route in this style here # Run Versia Server with this value missing to generate a new key
"/api/v1/timelines/public" = { duration = 60, max = 200 } # key = ""
# The provider MUST support OpenID Connect with .well-known discovery
# Most notably, GitHub does not support this
# Redirect URLs in your OpenID provider can be set to this:
# <base_url>/oauth/sso/<provider_id>/callback*
# The asterisk is important, as it allows for any query parameters to be passed
# Authentik for example uses regex so it can be set to (regex):
# <base_url>/oauth/sso/<provider_id>/callback.*
# [[authentication.openid_providers]]
# name = "CPlusPatch ID"
# id = "cpluspatch-id"
# This MUST match the provider's issuer URI, including the trailing slash (or lack thereof)
# url = "https://id.cpluspatch.com/application/o/versia-testing/"
# client_id = "XXXX"
# Sensitive value
# client_secret = "XXXXX"
# icon = "https://cpluspatch.com/images/icons/logo.svg"

2851
config/config.schema.json Normal file

File diff suppressed because it is too large Load diff

View file

@ -1,20 +0,0 @@
import { Queue } from "bullmq";
import { PrismaClient } from "@prisma/client";
import { ConfigManager } from "config-manager";
const config = await new ConfigManager({}).getConfig();
const client = new PrismaClient({
datasourceUrl: `postgresql://${config.database.username}:${config.database.password}@${config.database.host}:${config.database.port}/${config.database.database}`,
});
const federationQueue = new Queue("federation", {
connection: {
host: config.redis.queue.host,
port: Number(config.redis.queue.port),
password: config.redis.queue.password || undefined,
db: config.redis.queue.database || undefined,
},
});
export { client, federationQueue };

View file

@ -1,39 +0,0 @@
import type { APIApplication } from "~types/entities/application";
import type { Application } from "@prisma/client";
import { client } from "~database/datasource";
/**
* Represents an application that can authenticate with the API.
*/
/**
* Retrieves the application associated with the given access token.
* @param token The access token to retrieve the application for.
* @returns The application associated with the given access token, or null if no such application exists.
*/
export const getFromToken = async (
token: string
): Promise<Application | null> => {
const dbToken = await client.token.findFirst({
where: {
access_token: token,
},
include: {
application: true,
},
});
return dbToken?.application || null;
};
/**
* Converts this application to an API application.
* @returns The API application representation of this application.
*/
export const applicationToAPI = (app: Application): APIApplication => {
return {
name: app.name,
website: app.website,
vapid_key: app.vapid_key,
};
};

View file

@ -1,69 +0,0 @@
import type { Attachment } from "@prisma/client";
import type { ConfigType } from "config-manager";
import { MediaBackendType } from "media-manager";
import type { APIAsyncAttachment } from "~types/entities/async_attachment";
import type { APIAttachment } from "~types/entities/attachment";
export const attachmentToAPI = (
attachment: Attachment
): APIAsyncAttachment | APIAttachment => {
let type = "unknown";
if (attachment.mime_type.startsWith("image/")) {
type = "image";
} else if (attachment.mime_type.startsWith("video/")) {
type = "video";
} else if (attachment.mime_type.startsWith("audio/")) {
type = "audio";
}
return {
id: attachment.id,
type: type as any,
url: attachment.url,
remote_url: attachment.remote_url,
preview_url: attachment.thumbnail_url,
text_url: null,
meta: {
width: attachment.width || undefined,
height: attachment.height || undefined,
fps: attachment.fps || undefined,
size:
attachment.width && attachment.height
? `${attachment.width}x${attachment.height}`
: undefined,
duration: attachment.duration || undefined,
length: attachment.size?.toString() || undefined,
aspect:
attachment.width && attachment.height
? attachment.width / attachment.height
: undefined,
original: {
width: attachment.width || undefined,
height: attachment.height || undefined,
size:
attachment.width && attachment.height
? `${attachment.width}x${attachment.height}`
: undefined,
aspect:
attachment.width && attachment.height
? attachment.width / attachment.height
: undefined,
},
// Idk whether size or length is the right value
},
description: attachment.description,
blurhash: attachment.blurhash,
};
};
export const getUrl = (name: string, config: ConfigType) => {
// eslint-disable-next-line @typescript-eslint/no-unsafe-enum-comparison
if (config.media.backend === MediaBackendType.LOCAL) {
return `${config.http.base_url}/media/${name}`;
// eslint-disable-next-line @typescript-eslint/no-unsafe-enum-comparison
} else if (config.media.backend === MediaBackendType.S3) {
return `${config.s3.public_url}/${name}`;
}
return "";
};

View file

@ -1,97 +0,0 @@
import type { APIEmoji } from "~types/entities/emoji";
import type { Emoji as LysandEmoji } from "~types/lysand/extensions/org.lysand/custom_emojis";
import { client } from "~database/datasource";
import type { Emoji } from "@prisma/client";
/**
* Represents an emoji entity in the database.
*/
/**
* Used for parsing emojis from local text
* @param text The text to parse
* @returns An array of emojis
*/
export const parseEmojis = async (text: string): Promise<Emoji[]> => {
const regex = /:[a-zA-Z0-9_]+:/g;
const matches = text.match(regex);
if (!matches) return [];
return await client.emoji.findMany({
where: {
shortcode: {
in: matches.map(match => match.replace(/:/g, "")),
},
instanceId: null,
},
include: {
instance: true,
},
});
};
export const addEmojiIfNotExists = async (emoji: LysandEmoji) => {
const existingEmoji = await client.emoji.findFirst({
where: {
shortcode: emoji.name,
instance: null,
},
});
if (existingEmoji) return existingEmoji;
return await client.emoji.create({
data: {
shortcode: emoji.name,
url: emoji.url[0].content,
alt: emoji.alt || null,
content_type: emoji.url[0].content_type,
visible_in_picker: true,
},
});
};
/**
* Converts the emoji to an APIEmoji object.
* @returns The APIEmoji object.
*/
export const emojiToAPI = (emoji: Emoji): APIEmoji => {
return {
shortcode: emoji.shortcode,
static_url: emoji.url, // TODO: Add static version
url: emoji.url,
visible_in_picker: emoji.visible_in_picker,
category: undefined,
};
};
export const emojiToLysand = (emoji: Emoji): LysandEmoji => {
return {
name: emoji.shortcode,
url: [
{
content: emoji.url,
content_type: emoji.content_type,
},
],
alt: emoji.alt || undefined,
};
};
/**
* Converts the emoji to an ActivityPub object.
* @returns The ActivityPub object.
*/
export const emojiToActivityPub = (emoji: Emoji): any => {
// replace any with your ActivityPub Emoji type
return {
type: "Emoji",
name: `:${emoji.shortcode}:`,
updated: new Date().toISOString(),
icon: {
type: "Image",
url: emoji.url,
mediaType: emoji.content_type,
alt: emoji.alt || undefined,
},
};
};

View file

@ -1,49 +0,0 @@
import type { Instance } from "@prisma/client";
import { client } from "~database/datasource";
import type { ServerMetadata } from "~types/lysand/Object";
/**
* Represents an instance in the database.
*/
/**
* Adds an instance to the database if it doesn't already exist.
* @param url
* @returns Either the database instance if it already exists, or a newly created instance.
*/
export const addInstanceIfNotExists = async (
url: string
): Promise<Instance> => {
const origin = new URL(url).origin;
const hostname = new URL(url).hostname;
const found = await client.instance.findFirst({
where: {
base_url: hostname,
},
});
if (found) return found;
// Fetch the instance configuration
const metadata = (await fetch(`${origin}/.well-known/lysand`).then(res =>
res.json()
)) as Partial<ServerMetadata>;
if (metadata.type !== "ServerMetadata") {
throw new Error("Invalid instance metadata");
}
if (!(metadata.name && metadata.version)) {
throw new Error("Invalid instance metadata");
}
return await client.instance.create({
data: {
base_url: hostname,
name: metadata.name,
version: metadata.version,
logo: metadata.logo as any,
},
});
};

View file

@ -1,86 +0,0 @@
/* eslint-disable @typescript-eslint/no-unsafe-member-access */
import type { Like as LysandLike } from "~types/lysand/Object";
import type { Like } from "@prisma/client";
import { client } from "~database/datasource";
import type { UserWithRelations } from "./User";
import type { StatusWithRelations } from "./Status";
import { ConfigManager } from "config-manager";
const config = await new ConfigManager({}).getConfig();
/**
* Represents a Like entity in the database.
*/
export const toLysand = (like: Like): LysandLike => {
return {
id: like.id,
author: (like as any).liker?.uri,
type: "Like",
created_at: new Date(like.createdAt).toISOString(),
object: (like as any).liked?.uri,
uri: `${config.http.base_url}/actions/${like.id}`,
};
};
/**
* Create a like
* @param user User liking the status
* @param status Status being liked
*/
export const createLike = async (
user: UserWithRelations,
status: StatusWithRelations
) => {
await client.like.create({
data: {
likedId: status.id,
likerId: user.id,
},
});
if (status.author.instanceId === user.instanceId) {
// Notify the user that their post has been favourited
await client.notification.create({
data: {
accountId: user.id,
type: "favourite",
notifiedId: status.authorId,
statusId: status.id,
},
});
} else {
// TODO: Add database jobs for federating this
}
};
/**
* Delete a like
* @param user User deleting their like
* @param status Status being unliked
*/
export const deleteLike = async (
user: UserWithRelations,
status: StatusWithRelations
) => {
await client.like.deleteMany({
where: {
likedId: status.id,
likerId: user.id,
},
});
// Notify the user that their post has been favourited
await client.notification.deleteMany({
where: {
accountId: user.id,
type: "favourite",
notifiedId: status.authorId,
statusId: status.id,
},
});
if (user.instanceId === null && status.author.instanceId !== null) {
// User is local, federate the delete
// TODO: Federate this
}
};

View file

@ -1,23 +0,0 @@
import type { Notification } from "@prisma/client";
import type { APINotification } from "~types/entities/notification";
import { type StatusWithRelations, statusToAPI } from "./Status";
import { type UserWithRelations, userToAPI } from "./User";
export type NotificationWithRelations = Notification & {
status: StatusWithRelations | null;
account: UserWithRelations;
};
export const notificationToAPI = async (
notification: NotificationWithRelations
): Promise<APINotification> => {
return {
account: userToAPI(notification.account),
created_at: new Date(notification.createdAt).toISOString(),
id: notification.id,
type: notification.type,
status: notification.status
? await statusToAPI(notification.status, notification.account)
: undefined,
};
};

View file

@ -1,87 +0,0 @@
/* eslint-disable @typescript-eslint/no-unsafe-return */
/* eslint-disable @typescript-eslint/no-unsafe-member-access */
import type { LysandObject } from "@prisma/client";
import { client } from "~database/datasource";
import type { LysandObjectType } from "~types/lysand/Object";
/**
* Represents a Lysand object in the database.
*/
export const createFromObject = async (object: LysandObjectType) => {
const foundObject = await client.lysandObject.findFirst({
where: { remote_id: object.id },
include: {
author: true,
},
});
if (foundObject) {
return foundObject;
}
const author = await client.lysandObject.findFirst({
where: { uri: (object as any).author },
});
return await client.lysandObject.create({
data: {
authorId: author?.id,
created_at: new Date(object.created_at),
extensions: object.extensions || {},
remote_id: object.id,
type: object.type,
uri: object.uri,
// Rest of data (remove id, author, created_at, extensions, type, uri)
extra_data: Object.fromEntries(
Object.entries(object).filter(
([key]) =>
![
"id",
"author",
"created_at",
"extensions",
"type",
"uri",
].includes(key)
)
),
},
});
};
export const toLysand = (lyObject: LysandObject): LysandObjectType => {
return {
id: lyObject.remote_id || lyObject.id,
created_at: new Date(lyObject.created_at).toISOString(),
type: lyObject.type,
uri: lyObject.uri,
// @ts-expect-error This works, I promise
...lyObject.extra_data,
extensions: lyObject.extensions,
};
};
export const isPublication = (lyObject: LysandObject): boolean => {
return lyObject.type === "Note" || lyObject.type === "Patch";
};
export const isAction = (lyObject: LysandObject): boolean => {
return [
"Like",
"Follow",
"Dislike",
"FollowAccept",
"FollowReject",
"Undo",
"Announce",
].includes(lyObject.type);
};
export const isActor = (lyObject: LysandObject): boolean => {
return lyObject.type === "User";
};
export const isExtension = (lyObject: LysandObject): boolean => {
return lyObject.type === "Extension";
};

View file

@ -1,197 +0,0 @@
import { Worker } from "bullmq";
import { client, federationQueue } from "~database/datasource";
import {
statusAndUserRelations,
statusToLysand,
type StatusWithRelations,
} from "./Status";
import type { User } from "@prisma/client";
import { ConfigManager } from "config-manager";
const config = await new ConfigManager({}).getConfig();
export const federationWorker = new Worker(
"federation",
async job => {
await job.updateProgress(0);
switch (job.name) {
case "federation": {
// eslint-disable-next-line @typescript-eslint/no-unsafe-member-access
const statusId = job.data.id as string;
const status = await client.status.findUnique({
where: { id: statusId },
include: statusAndUserRelations,
});
if (!status) return;
// Only get remote users that follow the author of the status, and the remote mentioned users
const peopleToSendTo = await client.user.findMany({
where: {
OR: [
["public", "unlisted", "private"].includes(
status.visibility
)
? {
relationships: {
some: {
subjectId: status.authorId,
following: true,
},
},
instanceId: {
not: null,
},
}
: {},
// Mentioned users
{
id: {
in: status.mentions.map(m => m.id),
},
instanceId: {
not: null,
},
},
],
},
});
let peopleDone = 0;
// Spawn sendToServer job for each user
for (const person of peopleToSendTo) {
await federationQueue.add("sendToServer", {
id: statusId,
user: person,
});
peopleDone++;
await job.updateProgress(
Math.round((peopleDone / peopleToSendTo.length) * 100)
);
}
break;
}
case "sendToServer": {
// eslint-disable-next-line @typescript-eslint/no-unsafe-member-access
const statusId = job.data.id as string;
// eslint-disable-next-line @typescript-eslint/no-unsafe-member-access
const user = job.data.user as User;
const status = await client.status.findUnique({
where: { id: statusId },
include: statusAndUserRelations,
});
if (!status) return;
const response = await federateStatusTo(
status,
status.author,
user
);
if (response.status !== 200) {
throw new Error(
`Federation error: ${response.status} ${response.statusText}`
);
}
break;
}
}
await job.updateProgress(100);
return true;
},
{
connection: {
host: config.redis.queue.host,
port: config.redis.queue.port,
password: config.redis.queue.password,
db: config.redis.queue.database || undefined,
},
removeOnComplete: {
count: 400,
},
removeOnFail: {
count: 3000,
},
}
);
/**
* Convert a string into an ArrayBuffer
* from https://developers.google.com/web/updates/2012/06/How-to-convert-ArrayBuffer-to-and-from-String
*/
export const str2ab = (str: string) => {
const buf = new ArrayBuffer(str.length);
const bufView = new Uint8Array(buf);
for (let i = 0, strLen = str.length; i < strLen; i++) {
bufView[i] = str.charCodeAt(i);
}
return buf;
};
export const federateStatusTo = async (
status: StatusWithRelations,
sender: User,
user: User
) => {
const privateKey = await crypto.subtle.importKey(
"pkcs8",
str2ab(atob(user.privateKey ?? "")),
"Ed25519",
false,
["sign"]
);
const digest = await crypto.subtle.digest(
"SHA-256",
new TextEncoder().encode("request_body")
);
// eslint-disable-next-line @typescript-eslint/no-unsafe-member-access
const userInbox = new URL((user.endpoints as any).inbox);
const date = new Date();
const signature = await crypto.subtle.sign(
"Ed25519",
privateKey,
new TextEncoder().encode(
`(request-target): post ${userInbox.pathname}\n` +
`host: ${userInbox.host}\n` +
`date: ${date.toUTCString()}\n` +
`digest: SHA-256=${btoa(
String.fromCharCode(...new Uint8Array(digest))
)}\n`
)
);
const signatureBase64 = btoa(
String.fromCharCode(...new Uint8Array(signature))
);
return fetch(userInbox, {
method: "POST",
headers: {
"Content-Type": "application/json",
Date: date.toUTCString(),
Origin: config.http.base_url,
Signature: `keyId="${sender.uri}",algorithm="ed25519",headers="(request-target) host date digest",signature="${signatureBase64}"`,
},
body: JSON.stringify(statusToLysand(status)),
});
};
export const addStatusFederationJob = async (statusId: string) => {
await federationQueue.add("federation", {
id: statusId,
});
};

View file

@ -1,88 +0,0 @@
import type { Relationship, User } from "@prisma/client";
import type { APIRelationship } from "~types/entities/relationship";
import { client } from "~database/datasource";
/**
* Stores Mastodon API relationships
*/
/**
* Creates a new relationship between two users.
* @param owner The user who owns the relationship.
* @param other The user who is the subject of the relationship.
* @returns The newly created relationship.
*/
export const createNewRelationship = async (
owner: User,
other: User
): Promise<Relationship> => {
return await client.relationship.create({
data: {
ownerId: owner.id,
subjectId: other.id,
languages: [],
following: false,
showingReblogs: false,
notifying: false,
followedBy: false,
blocking: false,
blockedBy: false,
muting: false,
mutingNotifications: false,
requested: false,
domainBlocking: false,
endorsed: false,
note: "",
},
});
};
export const checkForBidirectionalRelationships = async (
user1: User,
user2: User,
createIfNotExists = true
): Promise<boolean> => {
const relationship1 = await client.relationship.findFirst({
where: {
ownerId: user1.id,
subjectId: user2.id,
},
});
const relationship2 = await client.relationship.findFirst({
where: {
ownerId: user2.id,
subjectId: user1.id,
},
});
if (!relationship1 && !relationship2 && createIfNotExists) {
await createNewRelationship(user1, user2);
await createNewRelationship(user2, user1);
}
return !!relationship1 && !!relationship2;
};
/**
* Converts the relationship to an API-friendly format.
* @returns The API-friendly relationship.
*/
export const relationshipToAPI = (rel: Relationship): APIRelationship => {
return {
blocked_by: rel.blockedBy,
blocking: rel.blocking,
domain_blocking: rel.domainBlocking,
endorsed: rel.endorsed,
followed_by: rel.followedBy,
following: rel.following,
id: rel.subjectId,
muting: rel.muting,
muting_notifications: rel.mutingNotifications,
notifying: rel.notifying,
requested: rel.requested,
showing_reblogs: rel.showingReblogs,
languages: rel.languages,
note: rel.note,
};
};

View file

@ -1,698 +0,0 @@
/* eslint-disable @typescript-eslint/no-unsafe-member-access */
import type { UserWithRelations } from "./User";
import {
fetchRemoteUser,
parseMentionsUris,
userRelations,
userToAPI,
} from "./User";
import { client } from "~database/datasource";
import type { LysandPublication, Note } from "~types/lysand/Object";
import { htmlToText } from "html-to-text";
import { getBestContentType } from "@content_types";
import {
Prisma,
type Application,
type Emoji,
type Relationship,
type Status,
type User,
} from "@prisma/client";
import { emojiToAPI, emojiToLysand, parseEmojis } from "./Emoji";
import type { APIStatus } from "~types/entities/status";
import { applicationToAPI } from "./Application";
import { attachmentToAPI } from "./Attachment";
import type { APIAttachment } from "~types/entities/attachment";
import { sanitizeHtml } from "@sanitization";
import { parse } from "marked";
import linkifyStr from "linkify-string";
import linkifyHtml from "linkify-html";
import { addStausToMeilisearch } from "@meilisearch";
import { ConfigManager } from "config-manager";
const config = await new ConfigManager({}).getConfig();
export const statusAndUserRelations: Prisma.StatusInclude = {
author: {
include: userRelations,
},
application: true,
emojis: true,
inReplyToPost: {
include: {
author: {
include: userRelations,
},
application: true,
emojis: true,
inReplyToPost: {
include: {
author: true,
},
},
instance: true,
mentions: true,
pinnedBy: true,
_count: {
select: {
replies: true,
},
},
},
},
reblogs: true,
attachments: true,
instance: true,
mentions: {
include: userRelations,
},
pinnedBy: true,
_count: {
select: {
replies: true,
likes: true,
reblogs: true,
},
},
reblog: {
include: {
author: {
include: userRelations,
},
application: true,
emojis: true,
inReplyToPost: {
include: {
author: true,
},
},
instance: true,
mentions: {
include: userRelations,
},
pinnedBy: true,
_count: {
select: {
replies: true,
},
},
},
},
quotingPost: {
include: {
author: {
include: userRelations,
},
application: true,
emojis: true,
inReplyToPost: {
include: {
author: true,
},
},
instance: true,
mentions: true,
pinnedBy: true,
_count: {
select: {
replies: true,
},
},
},
},
likes: {
include: {
liker: true,
},
},
};
const statusRelations = Prisma.validator<Prisma.StatusDefaultArgs>()({
include: statusAndUserRelations,
});
export type StatusWithRelations = Prisma.StatusGetPayload<
typeof statusRelations
>;
/**
* Represents a status (i.e. a post)
*/
/**
* Returns whether this status is viewable by a user.
* @param user The user to check.
* @returns Whether this status is viewable by the user.
*/
export const isViewableByUser = (status: Status, user: User | null) => {
if (status.authorId === user?.id) return true;
if (status.visibility === "public") return true;
else if (status.visibility === "unlisted") return true;
else if (status.visibility === "private") {
// @ts-expect-error Prisma TypeScript types dont include relations
return !!(user?.relationships as Relationship[]).find(
rel => rel.id === status.authorId
);
} else {
// @ts-expect-error Prisma TypeScript types dont include relations
return user && (status.mentions as User[]).includes(user);
}
};
export const fetchFromRemote = async (uri: string): Promise<Status | null> => {
// Check if already in database
const existingStatus: StatusWithRelations | null =
await client.status.findFirst({
where: {
uri: uri,
},
include: statusAndUserRelations,
});
if (existingStatus) return existingStatus;
const status = await fetch(uri);
if (status.status === 404) return null;
const body = (await status.json()) as LysandPublication;
const content = getBestContentType(body.contents);
const emojis = await parseEmojis(content?.content || "");
const author = await fetchRemoteUser(body.author);
let replyStatus: Status | null = null;
let quotingStatus: Status | null = null;
if (body.replies_to.length > 0) {
replyStatus = await fetchFromRemote(body.replies_to[0]);
}
if (body.quotes.length > 0) {
quotingStatus = await fetchFromRemote(body.quotes[0]);
}
return await createNewStatus({
account: author,
content: content?.content || "",
content_type: content?.content_type,
application: null,
// TODO: Add visibility
visibility: "public",
spoiler_text: body.subject || "",
uri: body.uri,
sensitive: body.is_sensitive,
emojis: emojis,
mentions: await parseMentionsUris(body.mentions),
reply: replyStatus
? {
status: replyStatus,
user: (replyStatus as any).author,
}
: undefined,
quote: quotingStatus || undefined,
});
};
/**
* Return all the ancestors of this post,
*/
// eslint-disable-next-line @typescript-eslint/require-await, @typescript-eslint/no-unused-vars
export const getAncestors = async (
status: StatusWithRelations,
fetcher: UserWithRelations | null
) => {
const ancestors: StatusWithRelations[] = [];
let currentStatus = status;
while (currentStatus.inReplyToPostId) {
const parent = await client.status.findFirst({
where: {
id: currentStatus.inReplyToPostId,
},
include: statusAndUserRelations,
});
if (!parent) break;
ancestors.push(parent);
currentStatus = parent;
}
// Filter for posts that are viewable by the user
const viewableAncestors = ancestors.filter(ancestor =>
isViewableByUser(ancestor, fetcher)
);
return viewableAncestors;
};
/**
* Return all the descendants of this post (recursive)
* Temporary implementation, will be replaced with a recursive SQL query when Prisma adds support for it
*/
// eslint-disable-next-line @typescript-eslint/require-await, @typescript-eslint/no-unused-vars
export const getDescendants = async (
status: StatusWithRelations,
fetcher: UserWithRelations | null,
depth = 0
) => {
const descendants: StatusWithRelations[] = [];
const currentStatus = status;
// Fetch all children of children of children recursively calling getDescendants
const children = await client.status.findMany({
where: {
inReplyToPostId: currentStatus.id,
},
include: statusAndUserRelations,
});
for (const child of children) {
descendants.push(child);
if (depth < 20) {
const childDescendants = await getDescendants(
child,
fetcher,
depth + 1
);
descendants.push(...childDescendants);
}
}
// Filter for posts that are viewable by the user
const viewableDescendants = descendants.filter(descendant =>
isViewableByUser(descendant, fetcher)
);
return viewableDescendants;
};
/**
* Creates a new status and saves it to the database.
* @param data The data for the new status.
* @returns A promise that resolves with the new status.
*/
export const createNewStatus = async (data: {
account: User;
application: Application | null;
content: string;
visibility: APIStatus["visibility"];
sensitive: boolean;
spoiler_text: string;
emojis?: Emoji[];
content_type?: string;
uri?: string;
mentions?: User[];
media_attachments?: string[];
reply?: {
status: Status;
user: User;
};
quote?: Status;
}) => {
// Get people mentioned in the content (match @username or @username@domain.com mentions)
const mentionedPeople =
data.content.match(/@[a-zA-Z0-9_]+(@[a-zA-Z0-9_]+)?/g) ?? [];
let mentions = data.mentions || [];
// Parse emojis
const emojis = await parseEmojis(data.content);
data.emojis = data.emojis ? [...data.emojis, ...emojis] : emojis;
// Get list of mentioned users
if (mentions.length === 0) {
mentions = await client.user.findMany({
where: {
OR: mentionedPeople.map(person => ({
username: person.split("@")[1],
instance: {
base_url: person.split("@")[2],
},
})),
},
include: userRelations,
});
}
let formattedContent;
// Get HTML version of content
if (data.content_type === "text/markdown") {
formattedContent = linkifyHtml(
await sanitizeHtml(await parse(data.content))
);
} else if (data.content_type === "text/x.misskeymarkdown") {
// Parse as MFM
} else {
// Parse as plaintext
formattedContent = linkifyStr(data.content);
// Split by newline and add <p> tags
formattedContent = formattedContent
.split("\n")
.map(line => `<p>${line}</p>`)
.join("\n");
}
let status = await client.status.create({
data: {
authorId: data.account.id,
applicationId: data.application?.id,
content: formattedContent,
contentSource: data.content,
contentType: data.content_type,
visibility: data.visibility,
sensitive: data.sensitive,
spoilerText: data.spoiler_text,
emojis: {
connect: data.emojis.map(emoji => {
return {
id: emoji.id,
};
}),
},
attachments: data.media_attachments
? {
connect: data.media_attachments.map(attachment => {
return {
id: attachment,
};
}),
}
: undefined,
inReplyToPostId: data.reply?.status.id,
quotingPostId: data.quote?.id,
instanceId: data.account.instanceId || undefined,
isReblog: false,
uri:
data.uri ||
`${config.http.base_url}/statuses/FAKE-${crypto.randomUUID()}`,
mentions: {
connect: mentions.map(mention => {
return {
id: mention.id,
};
}),
},
},
include: statusAndUserRelations,
});
// Update URI
status = await client.status.update({
where: {
id: status.id,
},
data: {
uri: data.uri || `${config.http.base_url}/statuses/${status.id}`,
},
include: statusAndUserRelations,
});
// Create notification
if (status.inReplyToPost) {
await client.notification.create({
data: {
notifiedId: status.inReplyToPost.authorId,
accountId: status.authorId,
type: "mention",
statusId: status.id,
},
});
}
// Add to search index
await addStausToMeilisearch(status);
return status;
};
export const editStatus = async (
status: StatusWithRelations,
data: {
content: string;
visibility?: APIStatus["visibility"];
sensitive: boolean;
spoiler_text: string;
emojis?: Emoji[];
content_type?: string;
uri?: string;
mentions?: User[];
media_attachments?: string[];
}
) => {
// Get people mentioned in the content (match @username or @username@domain.com mentions
const mentionedPeople =
data.content.match(/@[a-zA-Z0-9_]+(@[a-zA-Z0-9_]+)?/g) ?? [];
let mentions = data.mentions || [];
// Parse emojis
const emojis = await parseEmojis(data.content);
data.emojis = data.emojis ? [...data.emojis, ...emojis] : emojis;
// Get list of mentioned users
if (mentions.length === 0) {
mentions = await client.user.findMany({
where: {
OR: mentionedPeople.map(person => ({
username: person.split("@")[1],
instance: {
base_url: person.split("@")[2],
},
})),
},
include: userRelations,
});
}
let formattedContent;
// Get HTML version of content
if (data.content_type === "text/markdown") {
formattedContent = linkifyHtml(
await sanitizeHtml(await parse(data.content))
);
} else if (data.content_type === "text/x.misskeymarkdown") {
// Parse as MFM
} else {
// Parse as plaintext
formattedContent = linkifyStr(data.content);
// Split by newline and add <p> tags
formattedContent = formattedContent
.split("\n")
.map(line => `<p>${line}</p>`)
.join("\n");
}
const newStatus = await client.status.update({
where: {
id: status.id,
},
data: {
content: formattedContent,
contentSource: data.content,
contentType: data.content_type,
visibility: data.visibility,
sensitive: data.sensitive,
spoilerText: data.spoiler_text,
emojis: {
connect: data.emojis.map(emoji => {
return {
id: emoji.id,
};
}),
},
attachments: data.media_attachments
? {
connect: data.media_attachments.map(attachment => {
return {
id: attachment,
};
}),
}
: undefined,
mentions: {
connect: mentions.map(mention => {
return {
id: mention.id,
};
}),
},
},
include: statusAndUserRelations,
});
return newStatus;
};
export const isFavouritedBy = async (status: Status, user: User) => {
return !!(await client.like.findFirst({
where: {
likerId: user.id,
likedId: status.id,
},
}));
};
/**
* Converts this status to an API status.
* @returns A promise that resolves with the API status.
*/
export const statusToAPI = async (
status: StatusWithRelations,
user?: UserWithRelations
): Promise<APIStatus> => {
return {
id: status.id,
in_reply_to_id: status.inReplyToPostId || null,
in_reply_to_account_id: status.inReplyToPost?.authorId || null,
// @ts-expect-error Prisma TypeScript types dont include relations
account: userToAPI(status.author),
created_at: new Date(status.createdAt).toISOString(),
application: status.application
? applicationToAPI(status.application)
: null,
card: null,
content: status.content,
emojis: status.emojis.map(emoji => emojiToAPI(emoji)),
// eslint-disable-next-line @typescript-eslint/no-unnecessary-condition
favourited: !!(status.likes ?? []).find(
like => like.likerId === user?.id
),
// eslint-disable-next-line @typescript-eslint/no-unnecessary-condition
favourites_count: (status.likes ?? []).length,
// eslint-disable-next-line @typescript-eslint/no-unnecessary-condition
media_attachments: (status.attachments ?? []).map(
a => attachmentToAPI(a) as APIAttachment
),
// @ts-expect-error Prisma TypeScript types dont include relations
mentions: status.mentions.map(mention => userToAPI(mention)),
language: null,
muted: user
? user.relationships.find(r => r.subjectId == status.authorId)
?.muting || false
: false,
pinned: status.pinnedBy.find(u => u.id === user?.id) ? true : false,
// TODO: Add pols
poll: null,
reblog: status.reblog
? await statusToAPI(status.reblog as unknown as StatusWithRelations)
: null,
reblogged: !!(await client.status.findFirst({
where: {
authorId: user?.id,
reblogId: status.id,
},
})),
reblogs_count: status._count.reblogs,
replies_count: status._count.replies,
sensitive: status.sensitive,
spoiler_text: status.spoilerText,
tags: [],
uri: `${config.http.base_url}/statuses/${status.id}`,
visibility: "public",
url: `${config.http.base_url}/statuses/${status.id}`,
bookmarked: false,
quote: status.quotingPost
? await statusToAPI(
status.quotingPost as unknown as StatusWithRelations
)
: null,
quote_id: status.quotingPost?.id || undefined,
};
};
/* export const statusToActivityPub = async (
status: StatusWithRelations
// user?: UserWithRelations
): Promise<any> => {
// replace any with your ActivityPub type
return {
"@context": [
"https://www.w3.org/ns/activitystreams",
"https://mastodon.social/schemas/litepub-0.1.jsonld",
],
id: `${config.http.base_url}/users/${status.authorId}/statuses/${status.id}`,
type: "Note",
summary: status.spoilerText,
content: status.content,
published: new Date(status.createdAt).toISOString(),
url: `${config.http.base_url}/users/${status.authorId}/statuses/${status.id}`,
attributedTo: `${config.http.base_url}/users/${status.authorId}`,
to: ["https://www.w3.org/ns/activitystreams#Public"],
cc: [], // add recipients here
sensitive: status.sensitive,
attachment: (status.attachments ?? []).map(
a => attachmentToActivityPub(a) as ActivityPubAttachment // replace with your function
),
tag: [], // add tags here
replies: {
id: `${config.http.base_url}/users/${status.authorId}/statuses/${status.id}/replies`,
type: "Collection",
totalItems: status._count.replies,
},
likes: {
id: `${config.http.base_url}/users/${status.authorId}/statuses/${status.id}/likes`,
type: "Collection",
totalItems: status._count.likes,
},
shares: {
id: `${config.http.base_url}/users/${status.authorId}/statuses/${status.id}/shares`,
type: "Collection",
totalItems: status._count.reblogs,
},
inReplyTo: status.inReplyToPostId
? `${config.http.base_url}/users/${status.inReplyToPost?.authorId}/statuses/${status.inReplyToPostId}`
: null,
visibility: "public", // adjust as needed
// add more fields as needed
};
}; */
export const statusToLysand = (status: StatusWithRelations): Note => {
return {
type: "Note",
created_at: new Date(status.createdAt).toISOString(),
id: status.id,
author: status.authorId,
uri: `${config.http.base_url}/users/${status.authorId}/statuses/${status.id}`,
contents: [
{
content: status.content,
content_type: "text/html",
},
{
// Content converted to plaintext
content: htmlToText(status.content),
content_type: "text/plain",
},
],
// TODO: Add attachments
attachments: [],
is_sensitive: status.sensitive,
mentions: status.mentions.map(mention => mention.uri),
quotes: status.quotingPost ? [status.quotingPost.uri] : [],
replies_to: status.inReplyToPostId ? [status.inReplyToPostId] : [],
subject: status.spoilerText,
extensions: {
"org.lysand:custom_emojis": {
emojis: status.emojis.map(emoji => emojiToLysand(emoji)),
},
// TODO: Add polls and reactions
},
};
};

View file

@ -1,6 +0,0 @@
/**
* The type of token.
*/
export enum TokenType {
BEARER = "Bearer",
}

View file

@ -1,470 +0,0 @@
import type { APIAccount } from "~types/entities/account";
import type { User as LysandUser } from "~types/lysand/Object";
import { htmlToText } from "html-to-text";
import type { User } from "@prisma/client";
import { Prisma } from "@prisma/client";
import { client } from "~database/datasource";
import { addEmojiIfNotExists, emojiToAPI, emojiToLysand } from "./Emoji";
import { addInstanceIfNotExists } from "./Instance";
import type { APISource } from "~types/entities/source";
import { addUserToMeilisearch } from "@meilisearch";
import { ConfigManager, type ConfigType } from "config-manager";
const configManager = new ConfigManager({});
const config = await configManager.getConfig();
export interface AuthData {
user: UserWithRelations | null;
token: string;
}
/**
* Represents a user in the database.
* Stores local and remote users
*/
export const userRelations: Prisma.UserInclude = {
emojis: true,
instance: true,
likes: true,
relationships: true,
relationshipSubjects: true,
pinnedNotes: true,
_count: {
select: {
statuses: true,
likes: true,
},
},
};
const userRelations2 = Prisma.validator<Prisma.UserDefaultArgs>()({
include: userRelations,
});
export type UserWithRelations = Prisma.UserGetPayload<typeof userRelations2>;
/**
* Get the user's avatar in raw URL format
* @param config The config to use
* @returns The raw URL for the user's avatar
*/
export const getAvatarUrl = (user: User, config: ConfigType) => {
if (!user.avatar) return config.defaults.avatar;
if (config.media.backend === "local") {
return `${config.http.base_url}/media/${user.avatar}`;
} else if (config.media.backend === "s3") {
return `${config.s3.public_url}/${user.avatar}`;
}
return "";
};
/**
* Get the user's header in raw URL format
* @param config The config to use
* @returns The raw URL for the user's header
*/
export const getHeaderUrl = (user: User, config: ConfigType) => {
if (!user.header) return config.defaults.header;
if (config.media.backend === "local") {
return `${config.http.base_url}/media/${user.header}`;
} else if (config.media.backend === "s3") {
return `${config.s3.public_url}/${user.header}`;
}
return "";
};
export const getFromRequest = async (req: Request): Promise<AuthData> => {
// Check auth token
const token = req.headers.get("Authorization")?.split(" ")[1] || "";
return { user: await retrieveUserFromToken(token), token };
};
export const fetchRemoteUser = async (uri: string) => {
// Check if user not already in database
const foundUser = await client.user.findUnique({
where: {
uri,
},
include: userRelations,
});
if (foundUser) return foundUser;
const response = await fetch(uri, {
method: "GET",
headers: {
"Content-Type": "application/json",
Accept: "application/json",
},
});
const data = (await response.json()) as Partial<LysandUser>;
if (
!(
data.id &&
data.username &&
data.uri &&
data.created_at &&
data.disliked &&
data.featured &&
data.liked &&
data.followers &&
data.following &&
data.inbox &&
data.outbox &&
data.public_key
)
) {
throw new Error("Invalid user data");
}
// Parse emojis and add them to database
const userEmojis =
data.extensions?.["org.lysand:custom_emojis"]?.emojis ?? [];
const user = await client.user.create({
data: {
username: data.username,
uri: data.uri,
createdAt: new Date(data.created_at),
endpoints: {
disliked: data.disliked,
featured: data.featured,
liked: data.liked,
followers: data.followers,
following: data.following,
inbox: data.inbox,
outbox: data.outbox,
},
avatar: (data.avatar && data.avatar[0].content) || "",
header: (data.header && data.header[0].content) || "",
displayName: data.display_name ?? "",
note: data.bio?.[0].content ?? "",
publicKey: data.public_key.public_key,
source: {
language: null,
note: "",
privacy: "public",
sensitive: false,
fields: [],
},
},
});
// Add to Meilisearch
await addUserToMeilisearch(user);
const emojis = [];
for (const emoji of userEmojis) {
emojis.push(await addEmojiIfNotExists(emoji));
}
const uriData = new URL(data.uri);
return await client.user.update({
where: {
id: user.id,
},
data: {
emojis: {
connect: emojis.map(emoji => ({
id: emoji.id,
})),
},
instanceId: (await addInstanceIfNotExists(uriData.origin)).id,
},
include: userRelations,
});
};
/**
* Fetches the list of followers associated with the actor and updates the user's followers
*/
export const fetchFollowers = () => {
//
};
/**
* Creates a new LOCAL user.
* @param data The data for the new user.
* @returns The newly created user.
*/
export const createNewLocalUser = async (data: {
username: string;
display_name?: string;
password: string;
email: string;
bio?: string;
avatar?: string;
header?: string;
admin?: boolean;
}) => {
const config = await configManager.getConfig();
const keys = await generateUserKeys();
const user = await client.user.create({
data: {
username: data.username,
displayName: data.display_name ?? data.username,
password: await Bun.password.hash(data.password),
email: data.email,
note: data.bio ?? "",
avatar: data.avatar ?? config.defaults.avatar,
header: data.header ?? config.defaults.avatar,
isAdmin: data.admin ?? false,
uri: "",
publicKey: keys.public_key,
privateKey: keys.private_key,
source: {
language: null,
note: "",
privacy: "public",
sensitive: false,
fields: [],
},
},
});
// Add to Meilisearch
await addUserToMeilisearch(user);
return await client.user.update({
where: {
id: user.id,
},
data: {
uri: `${config.http.base_url}/users/${user.id}`,
endpoints: {
disliked: `${config.http.base_url}/users/${user.id}/disliked`,
featured: `${config.http.base_url}/users/${user.id}/featured`,
liked: `${config.http.base_url}/users/${user.id}/liked`,
followers: `${config.http.base_url}/users/${user.id}/followers`,
following: `${config.http.base_url}/users/${user.id}/following`,
inbox: `${config.http.base_url}/users/${user.id}/inbox`,
outbox: `${config.http.base_url}/users/${user.id}/outbox`,
},
},
include: userRelations,
});
};
/**
* Parses mentions from a list of URIs
*/
export const parseMentionsUris = async (mentions: string[]) => {
return await client.user.findMany({
where: {
uri: {
in: mentions,
},
},
include: userRelations,
});
};
/**
* Retrieves a user from a token.
* @param access_token The access token to retrieve the user from.
* @returns The user associated with the given access token.
*/
export const retrieveUserFromToken = async (access_token: string) => {
if (!access_token) return null;
const token = await client.token.findFirst({
where: {
access_token,
},
include: {
user: {
include: userRelations,
},
},
});
if (!token) return null;
return token.user;
};
/**
* Gets the relationship to another user.
* @param other The other user to get the relationship to.
* @returns The relationship to the other user.
*/
export const getRelationshipToOtherUser = async (
user: UserWithRelations,
other: User
) => {
return await client.relationship.findFirst({
where: {
ownerId: user.id,
subjectId: other.id,
},
});
};
/**
* Generates keys for the user.
*/
export const generateUserKeys = async () => {
const keys = await crypto.subtle.generateKey("Ed25519", true, [
"sign",
"verify",
]);
const privateKey = btoa(
String.fromCharCode.apply(null, [
...new Uint8Array(
// jesus help me what do these letters mean
await crypto.subtle.exportKey("pkcs8", keys.privateKey)
),
])
);
const publicKey = btoa(
String.fromCharCode(
...new Uint8Array(
// why is exporting a key so hard
await crypto.subtle.exportKey("spki", keys.publicKey)
)
)
);
// Add header, footer and newlines later on
// These keys are base64 encrypted
return {
private_key: privateKey,
public_key: publicKey,
};
};
export const userToAPI = (
user: UserWithRelations,
isOwnAccount = false
): APIAccount => {
return {
id: user.id,
username: user.username,
display_name: user.displayName,
note: user.note,
url: user.uri,
avatar: getAvatarUrl(user, config),
header: getHeaderUrl(user, config),
locked: user.isLocked,
created_at: new Date(user.createdAt).toISOString(),
followers_count: user.relationshipSubjects.filter(r => r.following)
.length,
following_count: user.relationships.filter(r => r.following).length,
statuses_count: user._count.statuses,
emojis: user.emojis.map(emoji => emojiToAPI(emoji)),
// TODO: Add fields
fields: [],
bot: user.isBot,
source:
isOwnAccount && user.source
? (user.source as any as APISource)
: undefined,
// TODO: Add static avatar and header
avatar_static: "",
header_static: "",
acct:
user.instance === null
? user.username
: `${user.username}@${user.instance.base_url}`,
// TODO: Add these fields
limited: false,
moved: null,
noindex: false,
suspended: false,
discoverable: undefined,
mute_expires_at: undefined,
group: false,
pleroma: {
is_admin: user.isAdmin,
is_moderator: user.isAdmin,
},
};
};
/**
* Should only return local users
*/
export const userToLysand = (user: UserWithRelations): LysandUser => {
if (user.instanceId !== null) {
throw new Error("Cannot convert remote user to Lysand format");
}
return {
id: user.id,
type: "User",
uri: user.uri,
bio: [
{
content: user.note,
content_type: "text/html",
},
{
content: htmlToText(user.note),
content_type: "text/plain",
},
],
created_at: new Date(user.createdAt).toISOString(),
disliked: `${user.uri}/disliked`,
featured: `${user.uri}/featured`,
liked: `${user.uri}/liked`,
followers: `${user.uri}/followers`,
following: `${user.uri}/following`,
inbox: `${user.uri}/inbox`,
outbox: `${user.uri}/outbox`,
indexable: false,
username: user.username,
avatar: [
{
content: getAvatarUrl(user, config) || "",
content_type: `image/${user.avatar.split(".")[1]}`,
},
],
header: [
{
content: getHeaderUrl(user, config) || "",
content_type: `image/${user.header.split(".")[1]}`,
},
],
display_name: user.displayName,
fields: (user.source as any as APISource).fields.map(field => ({
key: [
{
content: field.name,
content_type: "text/html",
},
{
content: htmlToText(field.name),
content_type: "text/plain",
},
],
value: [
{
content: field.value,
content_type: "text/html",
},
{
content: htmlToText(field.value),
content_type: "text/plain",
},
],
})),
public_key: {
actor: `${config.http.base_url}/users/${user.id}`,
public_key: user.publicKey,
},
extensions: {
"org.lysand:custom_emojis": {
emojis: user.emojis.map(emoji => emojiToLysand(emoji)),
},
},
};
};

View file

@ -1,53 +1,65 @@
---
# Run `docker network create lysand-net` before running docker-compose up
version: "3"
services: services:
lysand: versia:
image: ghcr.io/lysand-org/lysand:main image: ghcr.io/versia-pub/server:main
volumes: volumes:
#- ./logs:/app/logs - ./logs:/app/dist/logs
- ./config:/app/config - ./config:/app/dist/config:ro
- ./.env:/app/.env - ./uploads:/app/dist/uploads
- ./uploads:/app/uploads
restart: unless-stopped restart: unless-stopped
container_name: lysand container_name: versia
tty: true
networks: networks:
- lysand-net - versia-net
depends_on:
- db
- redis
- sonic
worker:
image: ghcr.io/versia-pub/worker:main
volumes:
- ./logs:/app/dist/logs
- ./config:/app/dist/config:ro
restart: unless-stopped
container_name: versia-worker
tty: true
networks:
- versia-net
depends_on:
- db
- redis
db: db:
build: image: postgres:17-alpine
context: . container_name: versia-db
dockerfile: Postgres.Dockerfile
container_name: lysand-db
restart: unless-stopped restart: unless-stopped
environment: environment:
POSTGRES_DB: lysand POSTGRES_DB: versia
POSTGRES_USER: lysand POSTGRES_USER: versia
POSTGRES_PASSWORD: lysand POSTGRES_PASSWORD: versia
networks: networks:
- lysand-net - versia-net
volumes: volumes:
- ./db-data:/var/lib/postgresql/data - ./db-data:/var/lib/postgresql/data
redis: redis:
image: "redis:latest" image: redis:alpine
container_name: lysand-redis container_name: versia-redis
volumes: volumes:
- ./redis-data:/data - ./redis-data:/data
restart: unless-stopped restart: unless-stopped
networks: networks:
- lysand-net - versia-net
meilisearch:
stdin_open: true sonic:
environment:
- MEILI_MASTER_KEY=add_your_key_here
tty: true
networks:
- lysand-net
volumes: volumes:
- ./meili-data:/meili_data - ./config.cfg:/etc/sonic.cfg
image: getmeili/meilisearch:v1.5 - ./store:/var/lib/sonic/store/
container_name: lysand-meilisearch image: valeriansaliou/sonic:v1.4.9
container_name: versia-sonic
restart: unless-stopped restart: unless-stopped
networks:
- versia-net
networks: networks:
lysand-net: versia-net:
external: true

98
docs/.vitepress/config.ts Normal file
View file

@ -0,0 +1,98 @@
import taskLists from "@hackmd/markdown-it-task-lists";
import implicitFigures from "markdown-it-image-figures";
import { defineConfig } from "vitepress";
import { tabsMarkdownPlugin } from "vitepress-plugin-tabs";
// https://vitepress.dev/reference/site-config
export default defineConfig({
title: "Versia Server Docs",
lang: "en-US",
description: "Documentation for Versia Server APIs",
markdown: {
config: (md): void => {
md.use(implicitFigures, {
figcaption: "alt",
copyAttrs: "^class$",
});
md.use(taskLists);
md.use(tabsMarkdownPlugin);
},
math: true,
},
cleanUrls: true,
themeConfig: {
// https://vitepress.dev/reference/default-theme-config
nav: [
{ text: "Home", link: "/" },
{
text: "Versia Protocol",
link: "https://versia.pub",
target: "_blank",
},
],
sidebar: [
{
text: "Installation",
items: [
{
text: "Normal",
link: "/setup/installation",
},
{
text: "Nix",
link: "/setup/nix",
},
],
},
{
text: "CLI",
link: "/cli",
},
{
text: "API",
items: [
{
text: "Reactions",
link: "/api/reactions",
},
{
text: "Challenges",
link: "/api/challenges",
},
{
text: "Mastodon Extensions",
link: "/api/mastodon",
},
],
},
{
text: "Frontend",
items: [
{
text: "Authentication",
link: "/frontend/auth",
},
{
text: "Routes",
link: "/frontend/routes",
},
],
},
],
socialLinks: [
{ icon: "github", link: "https://github.com/versia-pub/server" },
],
search: {
provider: "local",
},
logo: "https://cdn.versia.pub/branding/icon.svg",
},
head: [["link", { rel: "icon", href: "/favicon.png", type: "image/png" }]],
titleTemplate: ":title • Versia Server Docs",
});

View file

@ -0,0 +1,14 @@
import type { Theme } from "vitepress";
import DefaultTheme from "vitepress/theme";
// https://vitepress.dev/guide/custom-theme
import { h, type VNode } from "vue";
import "./style.css";
export default {
extends: DefaultTheme,
Layout: (): VNode => {
return h(DefaultTheme.Layout, null, {
// https://vitepress.dev/guide/extending-default-theme#layout-slots
});
},
} satisfies Theme;

View file

@ -0,0 +1,138 @@
/**
* Customize default theme styling by overriding CSS variables:
* https://github.com/vuejs/vitepress/blob/main/src/client/theme-default/styles/vars.css
*/
/**
* Colors
*
* Each colors have exact same color scale system with 3 levels of solid
* colors with different brightness, and 1 soft color.
*
* - `XXX-1`: The most solid color used mainly for colored text. It must
* satisfy the contrast ratio against when used on top of `XXX-soft`.
*
* - `XXX-2`: The color used mainly for hover state of the button.
*
* - `XXX-3`: The color for solid background, such as bg color of the button.
* It must satisfy the contrast ratio with pure white (#ffffff) text on
* top of it.
*
* - `XXX-soft`: The color used for subtle background such as custom container
* or badges. It must satisfy the contrast ratio when putting `XXX-1` colors
* on top of it.
*
* The soft color must be semi transparent alpha channel. This is crucial
* because it allows adding multiple "soft" colors on top of each other
* to create a accent, such as when having inline code block inside
* custom containers.
*
* - `default`: The color used purely for subtle indication without any
* special meanings attached to it such as bg color for menu hover state.
*
* - `brand`: Used for primary brand colors, such as link text, button with
* brand theme, etc.
*
* - `tip`: Used to indicate useful information. The default theme uses the
* brand color for this by default.
*
* - `warning`: Used to indicate warning to the users. Used in custom
* container, badges, etc.
*
* - `danger`: Used to show error, or dangerous message to the users. Used
* in custom container, badges, etc.
* -------------------------------------------------------------------------- */
:root {
--vp-c-default-1: var(--vp-c-gray-1);
--vp-c-default-2: var(--vp-c-gray-2);
--vp-c-default-3: var(--vp-c-gray-3);
--vp-c-default-soft: var(--vp-c-gray-soft);
--vp-c-brand-1: var(--vp-c-indigo-1);
--vp-c-brand-2: var(--vp-c-indigo-2);
--vp-c-brand-3: var(--vp-c-indigo-3);
--vp-c-brand-soft: var(--vp-c-indigo-soft);
--vp-c-tip-1: var(--vp-c-brand-1);
--vp-c-tip-2: var(--vp-c-brand-2);
--vp-c-tip-3: var(--vp-c-brand-3);
--vp-c-tip-soft: var(--vp-c-brand-soft);
--vp-c-warning-1: var(--vp-c-yellow-1);
--vp-c-warning-2: var(--vp-c-yellow-2);
--vp-c-warning-3: var(--vp-c-yellow-3);
--vp-c-warning-soft: var(--vp-c-yellow-soft);
--vp-c-danger-1: var(--vp-c-red-1);
--vp-c-danger-2: var(--vp-c-red-2);
--vp-c-danger-3: var(--vp-c-red-3);
--vp-c-danger-soft: var(--vp-c-red-soft);
}
/**
* Component: Button
* -------------------------------------------------------------------------- */
:root {
--vp-button-brand-border: transparent;
--vp-button-brand-text: var(--vp-c-white);
--vp-button-brand-bg: var(--vp-c-brand-3);
--vp-button-brand-hover-border: transparent;
--vp-button-brand-hover-text: var(--vp-c-white);
--vp-button-brand-hover-bg: var(--vp-c-brand-2);
--vp-button-brand-active-border: transparent;
--vp-button-brand-active-text: var(--vp-c-white);
--vp-button-brand-active-bg: var(--vp-c-brand-1);
}
/**
* Component: Home
* -------------------------------------------------------------------------- */
:root {
--vp-home-hero-name-color: transparent;
--vp-home-hero-name-background: -webkit-linear-gradient(
120deg,
#e6a9fe 30%,
#bd34fe
);
--vp-home-hero-image-background-image: linear-gradient(
-45deg,
#e6a9fe 50%,
#bd34fe 50%
);
--vp-home-hero-image-filter: blur(44px);
}
@media (min-width: 640px) {
:root {
--vp-home-hero-image-filter: blur(56px);
}
}
@media (min-width: 960px) {
:root {
--vp-home-hero-image-filter: blur(68px);
}
}
/**
* Component: Custom Block
* -------------------------------------------------------------------------- */
:root {
--vp-custom-block-tip-border: transparent;
--vp-custom-block-tip-text: var(--vp-c-text-1);
--vp-custom-block-tip-bg: var(--vp-c-brand-soft);
--vp-custom-block-tip-code-bg: var(--vp-c-brand-soft);
}
/**
* Component: Algolia
* -------------------------------------------------------------------------- */
.DocSearch {
--docsearch-primary-color: var(--vp-c-brand-1) !important;
}

37
docs/api/challenges.md Normal file
View file

@ -0,0 +1,37 @@
# Challenges API
Some API routes may require a cryptographic challenge to be solved before the request can be made. This is to prevent abuse of the API by bots and other malicious actors. The challenge is a simple mathematical problem that can be solved by any client.
This is a form of proof of work CAPTCHA, and should be mostly invisible to users. The challenge is generated by the server and sent to the client, which must solve it and send the solution back to the server.
## Solving a Challenge
Challenges are powered by the [Altcha](https://altcha.org/) library. You may either reimplement their solution code (which is very simple), or use [`altcha-lib`](https://github.com/altcha-org/altcha-lib) to solve the challenges.
## Request Challenge
To request a challenge, you may use the [`POST /api/v1/challenges`](https://vs.cpluspatch.com/docs#tag/challenges/POST/api/v1/challenges) endpoint.
## Sending a Solution
To send a solution with any request, add the following headers:
- `X-Challenge-Solution`: A base64 encoded string of the following JSON object:
```ts
{
number: number; // Solution to the challenge
algorithm: "SHA-256" | "SHA-384" | "SHA-512";
challenge: string;
salt: string,
signature: string,
}
```
Example: `{"number": 42, "algorithm": "SHA-256", "challenge": "xxxx", "salt": "abc", "signature": "def"}` -> `eyJudW1iZXIiOjQyLCJhbGdvcml0aG0iOiJTSEEtMjU2IiwiY2hhbGxlbmdlIjoieHh4eCIsInNhbHQiOiJhYmMiLCJzaWduYXR1cmUiOiJkZWYifQ==`
A challenge solution is valid for 5 minutes (configurable) after the challenge is generated. No solved challenge may be used more than once.
## Routes Requiring Challenges
If challenges are enabled, the following routes will require a challenge to be solved before the request can be made:
- `POST /api/v1/accounts`
Routes requiring challenges may eventually be expanded or made configurable.

420
docs/api/mastodon.md Normal file
View file

@ -0,0 +1,420 @@
# Mastodon API Extensions
Versia Server extends several Mastodon API endpoints to provide additional functionality. These endpoints are not part of the official Mastodon API, but are provided by Versia Server to enhance the user experience.
## Refetch User
```http
POST /api/v1/accounts/:id/refetch
```
Refetches the user's profile information from remote servers. Does not work for local users.
- **Returns**: [`Account`](https://docs.joinmastodon.org/entities/Account/)
- **Authentication**: Required
- **Permissions**: `read:account`
- **Version History**:
- `0.7.0`: Added.
### Request
#### Example
```http
POST /api/v1/accounts/364fd13f-28b5-4e88-badd-ce3e533f0d02/refetch
Authorization: Bearer ...
```
### Response
#### `400 Bad Request`
The user is a local user and cannot be refetched.
#### `200 OK`
New user data.
Example from the [Mastodon API documentation](https://docs.joinmastodon.org/entities/Account/):
```json
{
"id": "23634",
"username": "noiob",
"acct": "noiob@awoo.space",
"display_name": "ikea shark fan account",
"locked": false,
"bot": false,
"created_at": "2017-02-08T02:00:53.274Z",
"note": "<p>:ms_rainbow_flag: :ms_bisexual_flagweb: :ms_nonbinary_flag: <a href=\"https://awoo.space/tags/awoo\" class=\"mention hashtag\" rel=\"nofollow noopener noreferrer\" target=\"_blank\">#<span>awoo</span}.space <a href=\"https://awoo.space/tags/admin\" class=\"mention hashtag\" rel=\"nofollow noopener noreferrer\" target=\"_blank\">#<span>admin</span} ~ <a href=\"https://awoo.space/tags/bi\" class=\"mention hashtag\" rel=\"nofollow noopener noreferrer\" target=\"_blank\">#<span>bi</span} ~ <a href=\"https://awoo.space/tags/nonbinary\" class=\"mention hashtag\" rel=\"nofollow noopener noreferrer\" target=\"_blank\">#<span>nonbinary</span} ~ compsci student ~ likes video <a href=\"https://awoo.space/tags/games\" class=\"mention hashtag\" rel=\"nofollow noopener noreferrer\" target=\"_blank\">#<span>games</span} and weird/ old electronics and will post obsessively about both ~ avatar by <span class=\"h-card\"><a href=\"https://weirder.earth/@dzuk\" class=\"u-url mention\" rel=\"nofollow noopener noreferrer\" target=\"_blank\">@<span>dzuk</span}</span></p>",
"url": "https://awoo.space/@noiob",
"avatar": "https://files.mastodon.social/accounts/avatars/000/023/634/original/6ca8804dc46800ad.png",
"avatar_static": "https://files.mastodon.social/accounts/avatars/000/023/634/original/6ca8804dc46800ad.png",
"header": "https://files.mastodon.social/accounts/headers/000/023/634/original/256eb8d7ac40f49a.png",
"header_static": "https://files.mastodon.social/accounts/headers/000/023/634/original/256eb8d7ac40f49a.png",
"followers_count": 547,
"following_count": 404,
"statuses_count": 28468,
"last_status_at": "2019-11-17",
"emojis": [
{
"shortcode": "ms_rainbow_flag",
"url": "https://files.mastodon.social/custom_emojis/images/000/028/691/original/6de008d6281f4f59.png",
"static_url": "https://files.mastodon.social/custom_emojis/images/000/028/691/static/6de008d6281f4f59.png",
"visible_in_picker": true
},
{
"shortcode": "ms_bisexual_flag",
"url": "https://files.mastodon.social/custom_emojis/images/000/050/744/original/02f94a5fca7eaf78.png",
"static_url": "https://files.mastodon.social/custom_emojis/images/000/050/744/static/02f94a5fca7eaf78.png",
"visible_in_picker": true
},
{
"shortcode": "ms_nonbinary_flag",
"url": "https://files.mastodon.social/custom_emojis/images/000/105/099/original/8106088bd4782072.png",
"static_url": "https://files.mastodon.social/custom_emojis/images/000/105/099/static/8106088bd4782072.png",
"visible_in_picker": true
}
],
"fields": [
{
"name": "Pronouns",
"value": "they/them",
"verified_at": null
},
{
"name": "Alt",
"value": "<span class=\"h-card\"><a href=\"https://cybre.space/@noiob\" class=\"u-url mention\" rel=\"nofollow noopener noreferrer\" target=\"_blank\">@<span>noiob</span}</span>",
"verified_at": null
},
{
"name": "Bots",
"value": "<span class=\"h-card\"><a href=\"https://botsin.space/@darksouls\" class=\"u-url mention\" rel=\"nofollow noopener noreferrer\" target=\"_blank\">@<span>darksouls</span}</span>, <span class=\"h-card\"><a href=\"https://botsin.space/@nierautomata\" class=\"u-url mention\" rel=\"nofollow noopener noreferrer\" target=\"_blank\">@<span>nierautomata</span}</span>, <span class=\"h-card\"><a href=\"https://mastodon.social/@fedi\" class=\"u-url mention\" rel=\"nofollow noopener noreferrer\" target=\"_blank\">@<span>fedi</span}</span>, code for <span class=\"h-card\"><a href=\"https://botsin.space/@awoobot\" class=\"u-url mention\" rel=\"nofollow noopener noreferrer\" target=\"_blank\">@<span>awoobot</span}</span>",
"verified_at": null
},
{
"name": "Website",
"value": "<a href=\"http://shork.xyz\" rel=\"nofollow noopener noreferrer\" target=\"_blank\"><span class=\"invisible\">http://</span><span class=\"\">shork.xyz</span><span class=\"invisible\"></span}",
"verified_at": "2019-11-10T10:31:10.744+00:00"
}
]
}
```
## Get User By Username
```http
GET /api/v1/accounts/id?username=:username
```
Retrieves a user by their username.
- **Returns**: [`Account`](https://docs.joinmastodon.org/entities/Account/)
- **Authentication**: Not required
- **Permissions**: `read:account`
- **Version History**:
- `0.7.0`: Added.
### Request
#### Example
```http
GET /api/v1/accounts/id?username=bobleponge
```
### Response
#### `404 Not Found`
No user with that username was found.
#### `200 OK`
User data.
Example from the [Mastodon API documentation](https://docs.joinmastodon.org/entities/Account/):
```json
{
"id": "23634",
"username": "noiob",
"acct": "noiob@awoo.space",
"display_name": "ikea shark fan account",
"locked": false,
"bot": false,
"created_at": "2017-02-08T02:00:53.274Z",
"note": "<p>:ms_rainbow_flag: :ms_bisexual_flagweb: :ms_nonbinary_flag: <a href=\"https://awoo.space/tags/awoo\" class=\"mention hashtag\" rel=\"nofollow noopener noreferrer\" target=\"_blank\">#<span>awoo</span}.space <a href=\"https://awoo.space/tags/admin\" class=\"mention hashtag\" rel=\"nofollow noopener noreferrer\" target=\"_blank\">#<span>admin</span} ~ <a href=\"https://awoo.space/tags/bi\" class=\"mention hashtag\" rel=\"nofollow noopener noreferrer\" target=\"_blank\">#<span>bi</span} ~ <a href=\"https://awoo.space/tags/nonbinary\" class=\"mention hashtag\" rel=\"nofollow noopener noreferrer\" target=\"_blank\">#<span>nonbinary</span} ~ compsci student ~ likes video <a href=\"https://awoo.space/tags/games\" class=\"mention hashtag\" rel=\"nofollow noopener noreferrer\" target=\"_blank\">#<span>games</span} and weird/ old electronics and will post obsessively about both ~ avatar by <span class=\"h-card\"><a href=\"https://weirder.earth/@dzuk\" class=\"u-url mention\" rel=\"nofollow noopener noreferrer\" target=\"_blank\">@<span>dzuk</span}</span></p>",
"url": "https://awoo.space/@noiob",
"avatar": "https://files.mastodon.social/accounts/avatars/000/023/634/original/6ca8804dc46800ad.png",
"avatar_static": "https://files.mastodon.social/accounts/avatars/000/023/634/original/6ca8804dc46800ad.png",
"header": "https://files.mastodon.social/accounts/headers/000/023/634/original/256eb8d7ac40f49a.png",
"header_static": "https://files.mastodon.social/accounts/headers/000/023/634/original/256eb8d7ac40f49a.png",
"followers_count": 547,
"following_count": 404,
"statuses_count": 28468,
"last_status_at": "2019-11-17",
"emojis": [
{
"shortcode": "ms_rainbow_flag",
"url": "https://files.mastodon.social/custom_emojis/images/000/028/691/original/6de008d6281f4f59.png",
"static_url": "https://files.mastodon.social/custom_emojis/images/000/028/691/static/6de008d6281f4f59.png",
"visible_in_picker": true
},
{
"shortcode": "ms_bisexual_flag",
"url": "https://files.mastodon.social/custom_emojis/images/000/050/744/original/02f94a5fca7eaf78.png",
"static_url": "https://files.mastodon.social/custom_emojis/images/000/050/744/static/02f94a5fca7eaf78.png",
"visible_in_picker": true
},
{
"shortcode": "ms_nonbinary_flag",
"url": "https://files.mastodon.social/custom_emojis/images/000/105/099/original/8106088bd4782072.png",
"static_url": "https://files.mastodon.social/custom_emojis/images/000/105/099/static/8106088bd4782072.png",
"visible_in_picker": true
}
],
"fields": [
{
"name": "Pronouns",
"value": "they/them",
"verified_at": null
},
{
"name": "Alt",
"value": "<span class=\"h-card\"><a href=\"https://cybre.space/@noiob\" class=\"u-url mention\" rel=\"nofollow noopener noreferrer\" target=\"_blank\">@<span>noiob</span}</span>",
"verified_at": null
},
{
"name": "Bots",
"value": "<span class=\"h-card\"><a href=\"https://botsin.space/@darksouls\" class=\"u-url mention\" rel=\"nofollow noopener noreferrer\" target=\"_blank\">@<span>darksouls</span}</span>, <span class=\"h-card\"><a href=\"https://botsin.space/@nierautomata\" class=\"u-url mention\" rel=\"nofollow noopener noreferrer\" target=\"_blank\">@<span>nierautomata</span}</span>, <span class=\"h-card\"><a href=\"https://mastodon.social/@fedi\" class=\"u-url mention\" rel=\"nofollow noopener noreferrer\" target=\"_blank\">@<span>fedi</span}</span>, code for <span class=\"h-card\"><a href=\"https://botsin.space/@awoobot\" class=\"u-url mention\" rel=\"nofollow noopener noreferrer\" target=\"_blank\">@<span>awoobot</span}</span>",
"verified_at": null
},
{
"name": "Website",
"value": "<a href=\"http://shork.xyz\" rel=\"nofollow noopener noreferrer\" target=\"_blank\"><span class=\"invisible\">http://</span><span class=\"\">shork.xyz</span><span class=\"invisible\"></span}",
"verified_at": "2019-11-10T10:31:10.744+00:00"
}
]
}
```
## Get Instance TOS
```http
GET /api/v1/instance/tos
```
Returns the instance's Terms of Service, as configured in the instance settings.
- **Returns**: [`ExtendedDescription`](https://docs.joinmastodon.org/entities/ExtendedDescription/)
- **Authentication**: Not required
- **Permissions**: None
- **Version History**:
- `0.7.0`: Added.
### Request
#### Example
```http
GET /api/v1/instance/tos
```
### Response
#### `200 OK`
Instance's Terms of Service.
```json
{
"updated_at": "2019-11-17T00:00:00.000Z",
"content": "<h1>TOS</h1>\n<p>These are the terms of service for this instance.</p>",
}
```
## Get Instance Privacy Policy
```http
GET /api/v1/instance/privacy_policy
```
Returns the instance's Privacy Policy, as configured in the instance settings.
- **Returns**: [`ExtendedDescription`](https://docs.joinmastodon.org/entities/ExtendedDescription/)
- **Authentication**: Not required
- **Permissions**: None
- **Version History**:
- `0.7.0`: Added.
### Request
#### Example
```http
GET /api/v1/instance/privacy_policy
```
### Response
#### `200 OK`
Instance's Privacy Policy.
```json
{
"updated_at": "2019-11-17T00:00:00.000Z",
"content": "<h1>Privacy Policy</h1>\n<p>This is the privacy policy for this instance.</p>",
}
```
## `/api/v1/instance`
Extra attributes have been added to the `/api/v1/instance` endpoint.
```ts
interface SSOProvider {
id: string;
name: string;
icon?: string;
}
type ExtendedInstance = Instance & {
banner: string | null;
versia_version: string;
sso: {
forced: boolean;
providers: SSOProvider[];
};
}
```
### `banner`
The URL of the instance's banner image.
### `versia_version`
The version of Versia Server running on the instance.
The normal `version` field is always set to `"4.3.0+glitch"` or similar, to not confuse clients that expect a Mastodon instance.
### `sso`
Single Sign-On (SSO) settings for the instance. This object contains two fields:
- `forced`: If this is enabled, normal identifier/password login is disabled and login must be done through SSO.
- `providers`: An array of external OpenID Connect providers that users can link their accounts to. Each provider object contains the following fields:
- `id`: The issuer ID of the OpenID Connect provider.
- `name`: The name of the provider.
- `icon`: The URL of the provider's icon. Optional.
## `/api/v2/instance`
Extra attributes have been added to the `/api/v2/instance` endpoint. These are identical to the `/api/v1/instance` endpoint, except that the `banner` attribute uses the normal Mastodon API attribute.
```ts
type ExtendedInstanceV2 = InstanceV2 & {
versia_version: string;
configuration: Instance["configuration"] & {
emojis: {
// In bytes
emoji_size_limit: number;
max_emoji_shortcode_characters: number;
max_emoji_description_characters: number;
};
};
sso: {
forced: boolean;
providers: SSOProvider[];
};
}
```
### `versia_version`
The version of Versia Server running on the instance.
The normal `version` field is always set to `"4.3.0+glitch"` or similar, to not confuse clients that expect a Mastodon instance.
### `sso`
Single Sign-On (SSO) settings for the instance. This object contains two fields:
- `forced`: If this is enabled, normal identifier/password login is disabled and login must be done through SSO.
- `providers`: An array of external OpenID Connect providers that users can link their accounts to. Each provider object contains the following fields:
- `id`: The issuer ID of the OpenID Connect provider.
- `name`: The name of the provider.
- `icon`: The URL of the provider's icon. Optional.
## `Account`
Two extra attributes have been added to all returned [`Account`](https://docs.joinmastodon.org/entities/Account/) objects.
This object is returned on routes such as `/api/v1/accounts/:id`, `/api/v1/accounts/verify_credentials`, etc.
```ts
type ExtendedAccount = Account & {
roles: Role[];
uri: string;
}
```
### `roles`
An array of `Roles` that the user has.
### `uri`
URI of the account's Versia entity (for federation). Similar to Mastodon's `uri` field on notes.
## `Status`
One attribute has been added to all returned [`Status`](https://docs.joinmastodon.org/entities/Status/) objects.
This object is returned on routes such as `/api/v1/statuses/:id`, `/api/v1/statuses/:id/context`, etc.
```ts
type URL = string;
interface NoteReaction {
name: string;
count: number;
me: boolean;
url: URL;
}
type ExtendedStatus = Status & {
reactions: NoteReaction[];
}
```
```json
{
...
"reactions": [
{
"name": "like",
"count": 3,
"me": true,
},
{
"name": "blobfox",
"count": 1,
"me": false,
}
]
}
```
### `reactions`
An array of all the [`NoteReactions`](./reactions.md#reaction) for the note. Data for the custom emoji (e.g. URL) can be found in the `emojis` field of the [`Status`](https://docs.joinmastodon.org/entities/Status#emojis).
## `/api/v1/accounts/update_credentials`
The `username` parameter can now (optionally) be set to change the user's handle.
> [!WARNING]
> Clients should indicate to users that changing their handle will break existing links to their profile. This is reversible, but the old handle will be available for anyone to claim.

175
docs/api/reactions.md Normal file
View file

@ -0,0 +1,175 @@
# Reactions API
This API is used to send reactions to notes.
## Reaction
```typescript
type UUID = string;
interface NoteReaction {
name: string;
count: number;
me: boolean;
}
type NoteReactionWithAccounts = NoteReaction & {
account_ids: UUID[];
}
```
## Get Reactions
All reactions attached to a [`Status`](https://docs.joinmastodon.org/entities/Status) can be found on the note itself, [in the `reactions` field](./mastodon.md#reactions).
## Get Users Who Reacted
```http
GET /api/v1/statuses/:id/reactions
```
Get a list of all the users who reacted to a note. Only IDs are returned, not full account objects, to improve performance on very popular notes.
- **Returns:** [`NoteReactionWithAccounts[]`](#reaction)
- **Authentication:** Not required
- **Permissions:** `read:reaction`
- **Version History**:
- `0.8.0`: Added.
### Request
#### Example
```http
GET /api/v1/statuses/123/reactions
```
### Response
#### `200 OK`
List of reactions and associated users. The `me` field is `true` if the current user has reacted with that emoji.
Data for the custom emoji (e.g. URL) can be found in the `emojis` field of the [`Status`](https://docs.joinmastodon.org/entities/Status#emojis).
```json
[
{
"name": "like",
"count": 3,
"me": true,
"account_ids": ["1", "2", "3"]
},
{
"name": "blobfox-coffee",
"count": 1,
"me": false,
"account_ids": ["4"]
}
]
```
## Add Reaction
```http
PUT /api/v1/statuses/:id/reactions/:name
```
Add a reaction to a note.
- **Returns:** [`Status`](https://docs.joinmastodon.org/entities/Status)
- **Authentication:** Required
- **Permissions:** `owner:reaction`
- **Version History**:
- `0.8.0`: Added.
### Request
- `name` (string, required): Either a custom emoji shortcode or a Unicode emoji.
#### Example
```http
PUT /api/v1/statuses/123/reactions/blobfox-coffee
Authorization: Bearer ...
```
```http
PUT /api/v1/statuses/123/reactions/👍
Authorization: Bearer ...
```
### Response
#### `201 Created`
Returns the updated note.
```json
{
"id": "123",
...
"reactions": [
{
"name": "👍",
"count": 3,
"me": true
},
{
"name": "blobfox-coffee",
"count": 1,
"me": false
}
]
}
```
## Remove Reaction
```http
DELETE /api/v1/statuses/:id/reactions/:name
```
Remove a reaction from a note.
- **Returns:** [`Status`](https://docs.joinmastodon.org/entities/Status)
- **Authentication:** Required
- **Permissions:** `owner:reaction`
- **Version History**:
- `0.8.0`: Added.
### Request
- `name` (string, required): Either a custom emoji shortcode or a Unicode emoji.
#### Example
```http
DELETE /api/v1/statuses/123/reactions/blobfox-coffee
Authorization: Bearer ...
```
```http
DELETE /api/v1/statuses/123/reactions
Authorization: Bearer ...
```
### Response
#### `200 OK`
Returns the updated note. If the reaction was not found, the note is returned as is.
```json
{
"id": "123",
...
"reactions": [
{
"name": "👍",
"count": 3,
"me": true
}
]
}
```

21
docs/cli/index.md Normal file
View file

@ -0,0 +1,21 @@
# Versia Server CLI
Versia Server includes a built-in, scripting-compatible CLI that can be used to manage the server. This CLI can be used to create and delete users, manage the database and more. It can also output data in JSON or CSV format, making it easy to use in scripts.
## Using the CLI
Versia Server includes a built-in CLI for managing the server. To use it, simply run the following command:
```bash
# Docker
# Replace `versia` with the name of your container
docker compose exec -it versia sh /app/entrypoint.sh cli help
```
You can use the `help` command to see a list of available commands. These include creating users, deleting users and more. Each command also has a `--help,-h` flag that you can use to see more information about the command.
## Scripting with the CLI
Some CLI commands that return data as tables can be used in scripts. To convert them to JSON or CSV, some commands allow you to specify a `--format` flag that can be either `"json"` or `"csv"`. See `cli help` or `cli <command> -h` for more information.
Flags can be used in any order and anywhere in the script (except for the `cli` command itself).

87
docs/frontend/auth.md Normal file
View file

@ -0,0 +1,87 @@
# Frontend Authentication
Multiple API routes are exposed for authentication, to be used by frontend developers.
> [!INFO]
>
> These are different from the Client API routes, which are used by clients to interact with the Mastodon API.
A frontend is a web application that is designed to be the primary user interface for an instance. It is used also used by clients to perform authentication.
## Get Frontend Configuration
```http
GET /api/v1/frontend/config
```
Retrieves the frontend configuration for the instance. This returns whatever the `frontend.settings` object is set to in the Versia Server configuration.
This behaves like the `/api/v1/preferences` endpoint in the Mastodon API, but is specific to the frontend. These values are arbitrary and can be used for anything.
Frontend developers should always namespace their keys to avoid conflicts with other keys.
- **Returns**: Object with arbitrary keys and values.
- **Authentication**: Not required
- **Permissions**: None
- **Version History**:
- `0.7.0`: Added.
### Request
#### Example
```http
GET /api/v1/frontend/config
```
### Response
#### `200 OK`
Frontend configuration.
```json
{
"pub.versia.fe:theme": "dark",
"pub.versia.fe:custom_css": "body { background-color: black; }",
"net.googly.frontend:spoiler_image": "https://example.com/spoiler.png"
}
```
## SSO Sign In
```http
POST /oauth/sso
```
Allows users to sign in to the instance using an external OpenID Connect provider.
- **Returns**: `302 Found` with a `Location` header to redirect the user to the next step.
- **Authentication**: Not required
- **Permissions**: None
- **Version History**:
- `0.7.0`: First documented.
### Request
#### Query Parameters
- `client_id` (string, required): Client ID of the [application](https://docs.joinmastodon.org/entities/Application/) that is making the request.
- `issuer` (string, required): The ID of the OpenID Connect provider, as found in `/api/{v1,v2}/instance`.
#### Example
```http
POST /oauth/sso?client_id=123&issuer=google
```
### Response
#### `302 Found`
Redirects the user to the OpenID Connect provider's login page.
```http
HTTP/2.0 302 Found
Location: https://accounts.google.com/o/oauth2/auth?client_id=123&redirect_uri=https%3A%2F%2Fexample.com%2Fauth&response_type=code&scope=openid%20email&state=123
```

53
docs/frontend/routes.md Normal file
View file

@ -0,0 +1,53 @@
# Frontend Routes
Frontend implementors must implement these routes for correct operation of the instance.
The location of these routes can be configured in the Versia Server configuration at `frontend.routes`:
## Login Form
```http
GET /oauth/authorize
```
This route should display a login form for the user to enter their username and password, as well as a list of OpenID providers to use if available.
The form should submit to the OpenID Connect flow.
Configurable in the Versia Server configuration at `frontend.routes.login`.
## Consent Form
```http
GET /oauth/consent
```
This route should display a consent form for the user to approve the requested application permissions, after logging in.
The form should submit an OpenID Connect authorization request at `POST /oauth/authorize`, with the correct [application](https://docs.joinmastodon.org/entities/Application/) data (client ID, redirect URI, etc.). Do not forget the JWT cookie.
### Submission Example
```http
POST /oauth/authorize
Content-Type: application/json
Cookie: jwt=...
{
"client_id": "client_id",
"response_type": "code",
"redirect_uri": "https://example.com/callback",
"scope": "read write",
"state": "state123",
"code_challenge": "code_challenge",
"code_challenge_method": "S256",
"response_type": "code"
}
```
### Submission Response
```http
HTTP/2.0 302 Found
Location: https://example.com/callback?code=code&state=state123
```

18
docs/index.md Normal file
View file

@ -0,0 +1,18 @@
---
layout: home
hero:
name: Versia Server Docs
features:
- icon: 🛠️
title: Installation
details: Details on how to install Versia Server
link: ./setup/installation
- icon: 🖥
title: API Reference
details: Writing your own client? Check out the API reference
link: ./api/challenges
- icon: 📚
title: Frontend Building
details: Information on developing your own frontend
link: ./frontend/routes
---

BIN
docs/public/favicon.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.8 KiB

View file

@ -0,0 +1,98 @@
# Installation
## Requirements
- A Linux-based operating system. Kernel version `6.1` or later is recommended.
- Basic knowledge of Docker and Docker Compose.
Traditional "from-source" installation is not supported, as this software is designed to be run in a containerized environment. This guide will cover how to run the server using Docker.
## Installation
1. Download the `docker-compose.yml` file from the repository
> [!NOTE]
> You may need to change the image from `ghcr.io/versia-pub/server:latest` to `ghcr.io/versia-pub/server:main` if you want to use the latest changes from the `main` branch.
```bash
# Set this to "main" for the development build
TAG=v0.7.0
curl -o docker-compose.yml https://raw.githubusercontent.com/versia-pub/server/$TAG/docker-compose.yml
```
2. Edit the `docker-compose.yml` file to your liking, e.g removing the `db` service if you want to use an existing database.
3. Download the `config.example.toml` file from the repository
```bash
# This should be the same as the TAG variable above
TAG=v0.7.0
curl -o config.example.toml https://raw.githubusercontent.com/versia-pub/server/$TAG/config/config.example.toml
```
4. Edit the `config.example.toml` to your liking. You will at least need to change the `postgres`, `redis` and `http` sections to match your environment.
> [!WARNING]
> The first time you start the server, it will complain about missing keys in the configuration file.
>
> These will be autogenerated and printed to the console, so you can copy them to your `config.toml` file.
5. Run the following command to start the server:
```bash
docker compose up
```
You may need root privileges to run Docker commands.
To check server logs, run `docker compose logs versia`. The server will likely stop if there is an error, so you can check the logs to see what went wrong.
## Installing the frontend
The frontend is not included in the Docker image, so you will need to install it separately.
To do this, you may copy the static files from our frontend's Docker image:
```bash
# The frontend does not have a stable tag, so we use the main branch
TAG=main
OUTDIR=./frontend
TEMP=$(sudo docker create ghcr.io/versia-pub/frontend:$TAG)
sudo docker cp $TEMP:/app/public $OUTDIR
sudo docker rm $TEMP
```
> [!TIP]
>
> This command can be re-run to update the frontend to the latest version.
Then, set the following bind mount in your `docker-compose.yml` file:
```yaml
services:
versia:
...
volumes:
# If you set OUTDIR to a different directory, change this to match
# e.g. - ./custom-frontend:/frontend
- ./frontend:/frontend
```
Finally, update the config to point to the frontend:
```toml
[frontend]
path = "/frontend"
```
## Running the Server
Database migrations are run automatically on startup.
Please see the [CLI documentation](../cli/index.md) for more information on how to use the CLI.
## Updating the server
Updating the server is as simple as running `docker-compose pull` to update the Docker images, then `docker-compose up` to restart the server.
Sometimes, new configuration options are added to `config.example.toml`. If you see a new option in the example file, you should add it to your `config.toml` file.

87
docs/setup/nix.md Normal file
View file

@ -0,0 +1,87 @@
# Nix Module
This project is packaged as a [Nix Flake](https://nixos.wiki/wiki/Flakes), which can be used to build and run the project in a reproducible environment.
## Installation
### Flake-based NixOS installs
Add the following to your `inputs` in your `flake.nix`:
```nix
inputs = {
# ...
versia-server = {
url = "github:versia-pub/server";
inputs.nixpkgs.follows = "nixpkgs";
};
};
```
Then, add this to your `nixosConfigurations`:
```nix
nixosConfigurations = {
# ...
my-server = {
system = "x86_64-linux"; # arm64-linux is also supported
modules = [
# ...
{
nixpkgs.overlays = [versia-server.overlays.default];
}
versia-server.nixosModules.versia-server
];
};
};
```
You are now ready to use the NixOS module.
## Usage
This module exposes the following configuration option:
```nix
services.versia-server = {
enable = true;
user = "versia-server";
group = "versia-server";
nodes = {
api = {
main = {};
backup = {
configOverrides.http.port = 2734;
};
};
worker = {
one = {};
two = {};
three = {
configOverrides.postgres.port = 5433;
};
};
};
config = {
# ...
http = {
# ...
bind = "0.0.0.0";
port = 8080;
base_url = "https://versia.example";
};
# ...
};
};
```
### Configuration Options
- `enable`: Whether to enable the service. Default: `true`.
- `user`: The user under which the service will run. Default: `versia-server`.
- `group`: The group under which the service will run. Default: `versia-server`.
- `nodes`: A set of nodes to run. Each node can have its own configuration overrides, which will be merged with the default configuration. You must have at least one of each type (`api` and `worker`).
- `config`: Contents of the config file, which is serialized to TOML. Check the Versia Server documentation for information on its contents.

28
drizzle.config.ts Normal file
View file

@ -0,0 +1,28 @@
import { config } from "@versia-server/config";
import type { Config } from "drizzle-kit";
/**
* Drizzle can't properly resolve imports with top-level await, so uncomment
* this line when generating migrations.
*/
export default {
dialect: "postgresql",
out: "./packages/kit/tables/migrations",
schema: "./packages/kit/tables/schema.ts",
dbCredentials: {
/* host: "localhost",
port: 40000,
user: "lysand",
password: "lysand",
database: "lysand", */
host: config.postgres.host,
port: config.postgres.port,
user: config.postgres.username,
password: config.postgres.password,
database: config.postgres.database,
},
// Print all statements
verbose: true,
// Always ask for confirmation
strict: true,
} satisfies Config;

View file

@ -4,34 +4,24 @@
# Commands: # Commands:
# - `start`: Starts the server # - `start`: Starts the server
# - `cli`: Starts the CLI, sends all arguments to it # - `cli`: Starts the CLI, sends all arguments to it
# - `prisma`: Execute a Prisma command, sends
# Exit immediately if a command exits with a non-zero status. # Exit immediately if a command exits with a non-zero status.
set -e set -eu
cd /app/dist
# Parse first argument # Parse first argument
case "$1" in case "$1" in
"start") "start")
# Start the server NODE_ENV=production bun run ./index.js --prod
exec bun run ./dist/index.js --prod
;; ;;
"cli") "cli")
# Start the CLI # Start the CLI
shift 1 shift 1
exec bun run ./dist/cli.js "$@" bun run ./cli/index.js "$@"
;;
"prisma")
# Proxy all Prisma commands
# Use output of dist/prisma.js to get the env variable
shift 1
# Set DATABASE_URL env variable to the output of bun run ./dist/prisma.js
export DATABASE_URL=$(bun run ./dist/prisma.js)
# Execute the Prisma binary
exec bunx prisma "$@"
;; ;;
*) *)
# Run custom commands # Run custom commands
exec "$@" exec "$@"
;; ;;
esac esac
```

61
flake.lock Normal file
View file

@ -0,0 +1,61 @@
{
"nodes": {
"flake-utils": {
"inputs": {
"systems": "systems"
},
"locked": {
"lastModified": 1731533236,
"narHash": "sha256-l0KFg5HjrsfsO/JpG+r7fRrqm12kzFHyUHqHCVpMMbI=",
"owner": "numtide",
"repo": "flake-utils",
"rev": "11707dc2f618dd54ca8739b309ec4fc024de578b",
"type": "github"
},
"original": {
"owner": "numtide",
"repo": "flake-utils",
"type": "github"
}
},
"nixpkgs": {
"locked": {
"lastModified": 1763421233,
"narHash": "sha256-Stk9ZYRkGrnnpyJ4eqt9eQtdFWRRIvMxpNRf4sIegnw=",
"owner": "NixOS",
"repo": "nixpkgs",
"rev": "89c2b2330e733d6cdb5eae7b899326930c2c0648",
"type": "github"
},
"original": {
"owner": "NixOS",
"ref": "nixos-unstable",
"repo": "nixpkgs",
"type": "github"
}
},
"root": {
"inputs": {
"flake-utils": "flake-utils",
"nixpkgs": "nixpkgs"
}
},
"systems": {
"locked": {
"lastModified": 1681028828,
"narHash": "sha256-Vy1rq5AaRuLzOxct8nz4T6wlgyUR7zLU309k9mBC768=",
"owner": "nix-systems",
"repo": "default",
"rev": "da67096a3b9bf56a91d16901293e51ba5b49a27e",
"type": "github"
},
"original": {
"owner": "nix-systems",
"repo": "default",
"type": "github"
}
}
},
"root": "root",
"version": 7
}

Some files were not shown because too many files have changed in this diff Show more