commit b719cd5c618c34c5081095831f3f2a75e81d4098
parent c3ca613d0131185e4a661a388323cf5ce045e050
Author: mtmn <miro@haravara.org>
Date: Mon, 13 Apr 2026 01:08:18 +0200
chore: run biome on src/ and test/
Diffstat:
6 files changed, 115 insertions(+), 107 deletions(-)
diff --git a/src/Client.js b/src/Client.js
@@ -1,8 +1,8 @@
export const extractParam = (key) => (search) => {
- const params = new URLSearchParams(search);
- return params.get(key);
+ const params = new URLSearchParams(search);
+ return params.get(key);
};
export const formatRFC3339 = (instant) => {
- return new Date(instant).toISOString();
+ return new Date(instant).toISOString();
};
diff --git a/src/Db.js b/src/Db.js
@@ -1,40 +1,40 @@
-import duckdb from 'duckdb';
+import duckdb from "duckdb";
export const connectImpl = (path) => (cb) => () => {
- const db = new duckdb.Database(path, (err) => {
- if (err) {
- cb(err)(null)();
- } else {
- try {
- const conn = db.connect();
- cb(null)(conn)();
- } catch (e) {
- cb(e)(null)();
- }
- }
- });
+ const db = new duckdb.Database(path, (err) => {
+ if (err) {
+ cb(err)(null)();
+ } else {
+ try {
+ const conn = db.connect();
+ cb(null)(conn)();
+ } catch (e) {
+ cb(e)(null)();
+ }
+ }
+ });
};
export const runImpl = (conn) => (sql) => (params) => (cb) => () => {
- conn.run(sql, ...params, (err) => {
- cb(err)();
- });
+ conn.run(sql, ...params, (err) => {
+ cb(err)();
+ });
};
export const allImpl = (conn) => (sql) => (params) => (cb) => () => {
- conn.all(sql, ...params, (err, rows) => {
- if (rows) {
- // DuckDB returns BIGINT as BigInt, which JSON.stringify doesn't support.
- // We convert them to Numbers here.
- for (let i = 0; i < rows.length; i++) {
- const row = rows[i];
- for (const key in row) {
- if (typeof row[key] === 'bigint') {
- row[key] = Number(row[key]);
- }
- }
- }
- }
- cb(err)(rows)();
- });
+ conn.all(sql, ...params, (err, rows) => {
+ if (rows) {
+ // DuckDB returns BIGINT as BigInt, which JSON.stringify doesn't support.
+ // We convert them to Numbers here.
+ for (let i = 0; i < rows.length; i++) {
+ const row = rows[i];
+ for (const key in row) {
+ if (typeof row[key] === "bigint") {
+ row[key] = Number(row[key]);
+ }
+ }
+ }
+ }
+ cb(err)(rows)();
+ });
};
diff --git a/src/Main.js b/src/Main.js
@@ -1,5 +1,5 @@
-import { config } from 'dotenv';
+import { config } from "dotenv";
export const dotenvConfig = () => {
- config();
+ config();
};
diff --git a/src/Main.purs b/src/Main.purs
@@ -190,12 +190,12 @@ indexHtml =
background: #50447f;
color: #ffffff;
}
-
+
.container {
max-width: 800px;
margin: 0 auto;
}
-
+
h1 {
color: #ffffff;
margin-bottom: 20px;
@@ -204,13 +204,13 @@ indexHtml =
display: inline-block;
padding-bottom: 5px;
}
-
+
ul {
list-style: none;
padding: 0;
margin: 0 0 20px 0;
}
-
+
li {
background: #521e40;
border: 1px solid #50447f;
@@ -222,28 +222,28 @@ indexHtml =
align-items: center;
box-shadow: 4px 4px 0px #50447f;
}
-
+
li.success {
background: #521e40;
border-color: #50447f;
}
-
+
.track-info {
flex: 1;
}
-
+
.track-name {
font-weight: bold;
font-size: 16px;
color: #ffffff;
}
-
+
.track-artist {
font-size: 14px;
color: #a0c0d0;
margin-top: 1px;
}
-
+
.track-time {
font-size: 12px;
color: #9fbfe7;
@@ -258,7 +258,7 @@ indexHtml =
.album-link:hover {
color: #ffffff;
}
-
+
.status {
color: #b9d0aa;
font-weight: bold;
@@ -273,42 +273,42 @@ indexHtml =
transition: transform 0.2s ease-in-out;
cursor: pointer;
}
-
+
.track-cover.zoomed {
transform: scale(5.0);
z-index: 10;
position: relative;
box-shadow: 0 8px 16px rgba(0, 0, 0, 0.5);
}
-
+
.loading {
padding: 20px;
color: #9fbfe7;
text-align: center;
}
-
+
.error {
padding: 20px;
color: #eca28f;
text-align: center;
}
-
+
.small {
font-size: 12px;
color: #9fbfe7;
margin-top: 20px;
}
-
+
.small a {
color: #a0c0d0;
text-decoration: none;
}
-
+
.small a:hover {
color: #ffffff;
text-decoration: underline;
}
-
+
.refresh-btn {
background: none;
border: none;
@@ -317,11 +317,11 @@ indexHtml =
font-size: 12px;
text-decoration: underline;
}
-
+
.refresh-btn:hover {
color: #ffffff;
}
-
+
.playing-indicator {
display: inline-block;
width: 8px;
@@ -331,7 +331,7 @@ indexHtml =
margin-right: 8px;
animation: pulse 2s infinite;
}
-
+
@keyframes pulse {
0% { opacity: 1; }
50% { opacity: 0.3; }
diff --git a/src/S3.js b/src/S3.js
@@ -1,59 +1,67 @@
-import { S3Client, PutObjectCommand, HeadObjectCommand } from "@aws-sdk/client-s3";
+import {
+ S3Client,
+ PutObjectCommand,
+ HeadObjectCommand,
+} from "@aws-sdk/client-s3";
-const getClient = () => new S3Client({
- region: process.env.S3_REGION || "us-east-1",
- endpoint: process.env.AWS_ENDPOINT_URL,
- forcePathStyle: process.env.AWS_S3_ADDRESSING_STYLE === "path",
- credentials: {
- accessKeyId: process.env.AWS_ACCESS_KEY_ID,
- secretAccessKey: process.env.AWS_SECRET_ACCESS_KEY
- }
-});
+const getClient = () =>
+ new S3Client({
+ region: process.env.S3_REGION || "us-east-1",
+ endpoint: process.env.AWS_ENDPOINT_URL,
+ forcePathStyle: process.env.AWS_S3_ADDRESSING_STYLE === "path",
+ credentials: {
+ accessKeyId: process.env.AWS_ACCESS_KEY_ID,
+ secretAccessKey: process.env.AWS_SECRET_ACCESS_KEY,
+ },
+ });
-export const uploadToS3Impl = (key) => (body) => (contentType) => (cb) => () => {
- const client = getClient();
- const command = new PutObjectCommand({
- Bucket: process.env.S3_BUCKET,
- Key: key,
- Body: body,
- ContentType: contentType
- });
+export const uploadToS3Impl =
+ (key) => (body) => (contentType) => (cb) => () => {
+ const client = getClient();
+ const command = new PutObjectCommand({
+ Bucket: process.env.S3_BUCKET,
+ Key: key,
+ Body: body,
+ ContentType: contentType,
+ });
- client.send(command)
- .then(() => {
- cb(null)();
- })
- .catch((err) => {
- console.error(`S3: Upload failed for ${key}`, err);
- cb(err)();
- });
-};
+ client
+ .send(command)
+ .then(() => {
+ cb(null)();
+ })
+ .catch((err) => {
+ console.error(`S3: Upload failed for ${key}`, err);
+ cb(err)();
+ });
+ };
export const existsInS3Impl = (key) => (cb) => () => {
- const client = getClient();
- const command = new HeadObjectCommand({
- Bucket: process.env.S3_BUCKET,
- Key: key
- });
+ const client = getClient();
+ const command = new HeadObjectCommand({
+ Bucket: process.env.S3_BUCKET,
+ Key: key,
+ });
- client.send(command)
- .then(() => cb(true)())
- .catch((err) => {
- if (err.name === "NotFound" || err.$metadata?.httpStatusCode === 404) {
- cb(false)();
- } else {
- console.error(`S3: exists check failed for ${key}`, err);
- cb(false)();
- }
- });
+ client
+ .send(command)
+ .then(() => cb(true)())
+ .catch((err) => {
+ if (err.name === "NotFound" || err.$metadata?.httpStatusCode === 404) {
+ cb(false)();
+ } else {
+ console.error(`S3: exists check failed for ${key}`, err);
+ cb(false)();
+ }
+ });
};
export const getS3UrlImpl = (key) => {
- const endpoint = process.env.AWS_ENDPOINT_URL || "";
- const bucket = process.env.S3_BUCKET || "";
- if (process.env.AWS_S3_ADDRESSING_STYLE === "path") {
- return `${endpoint}/${bucket}/${key}`;
- } else {
- return `${endpoint.replace("://", `://${bucket}.`)}/${key}`;
- }
+ const endpoint = process.env.AWS_ENDPOINT_URL || "";
+ const bucket = process.env.S3_BUCKET || "";
+ if (process.env.AWS_S3_ADDRESSING_STYLE === "path") {
+ return `${endpoint}/${bucket}/${key}`;
+ } else {
+ return `${endpoint.replace("://", `://${bucket}.`)}/${key}`;
+ }
};
diff --git a/test/Main.purs b/test/Main.purs
@@ -22,7 +22,7 @@ main :: Effect Unit
main = do
Process.setEnv "AWS_ENDPOINT_URL" "https://s3.example.com"
Process.setEnv "S3_BUCKET" "my-bucket"
-
+
runSpecAndExitProcess [consoleReporter] do
describe "Scorpus Main Utils" do
it "should build ListenBrainz URLs correctly" do
@@ -149,7 +149,7 @@ main = do
-- Test Filtering (as mentioned in architecture.md)
listensFiltered <- getScrobbles conn 10 0 (Just { field: "genre", value: "Rock" })
length listensFiltered `shouldEqual` 1
-
+
listensEmpty <- getScrobbles conn 10 0 (Just { field: "genre", value: "Jazz" })
length listensEmpty `shouldEqual` 0