chore: reconcile performance layer after stack rebase

This commit is contained in:
ajnart committed 2026-08-13 20:01:46 +02:00
1 parent 1088f058e3
commit c92ca2af5f
235 files changed
+18492 -15756

No files matched your search

@@ -1,172 +0,0 @@
/// <reference path="../pb_data/types.d.ts" />
migrate(
(app) => {
const users = app.findCollectionByNameOrId("users");
const githubClientId = $os.getenv("GITHUB_CLIENT_ID");
const githubClientSecret = $os.getenv("GITHUB_CLIENT_SECRET");
if (githubClientId && githubClientSecret) {
users.oauth2.enabled = true;
users.oauth2.providers = [
{
name: "github",
clientId: githubClientId,
clientSecret: githubClientSecret,
},
];
}
app.save(users);
let submissions;
try {
submissions = app.findCollectionByNameOrId("submissions");
} catch {
submissions = new Collection({
type: "base",
name: "submissions",
listRule: "",
viewRule: "",
createRule: "@request.auth.id != ''",
updateRule: "author = @request.auth.id",
deleteRule: "author = @request.auth.id",
fields: [
{ name: "type", type: "select", required: true, maxSelect: 1, values: ["css", "widget"] },
{ name: "title", type: "text", required: true, min: 3, max: 100 },
{ name: "description", type: "text", max: 2000 },
{ name: "schemaVersion", type: "text", required: true, max: 100 },
{ name: "content", type: "text", required: true, max: 1000000 },
{
name: "screenshots",
type: "file",
maxSelect: 5,
maxSize: 5242880,
mimeTypes: ["image/png", "image/jpeg", "image/webp", "image/gif"],
},
{
name: "author",
type: "relation",
required: true,
maxSelect: 1,
collectionId: users.id,
cascadeDelete: true,
},
{ name: "upvotes", type: "number", onlyInt: true },
{ name: "downvotes", type: "number", onlyInt: true },
{ name: "version", type: "number", onlyInt: true },
{ name: "changelog", type: "text", max: 2000 },
{ name: "created", type: "autodate", onCreate: true },
{ name: "updated", type: "autodate", onCreate: true, onUpdate: true },
],
});
app.save(submissions);
}
let votes;
try {
votes = app.findCollectionByNameOrId("votes");
} catch {
votes = new Collection({
type: "base",
name: "votes",
listRule: "user = @request.auth.id",
viewRule: "user = @request.auth.id",
createRule: "@request.auth.id != ''",
updateRule: "user = @request.auth.id",
deleteRule: "user = @request.auth.id",
fields: [
{
name: "submission",
type: "relation",
required: true,
maxSelect: 1,
collectionId: submissions.id,
cascadeDelete: true,
},
{ name: "user", type: "relation", required: true, maxSelect: 1, collectionId: users.id, cascadeDelete: true },
{ name: "value", type: "number", required: true, onlyInt: true, min: -1, max: 1 },
{ name: "created", type: "autodate", onCreate: true },
{ name: "updated", type: "autodate", onCreate: true, onUpdate: true },
],
});
votes.addIndex("idx_votes_unique_user_submission", true, "submission, user", "");
app.save(votes);
}
let reports;
try {
reports = app.findCollectionByNameOrId("reports");
} catch {
reports = new Collection({
type: "base",
name: "reports",
listRule: null,
viewRule: null,
createRule: "@request.auth.id != ''",
updateRule: null,
deleteRule: null,
fields: [
{
name: "submission",
type: "relation",
required: true,
maxSelect: 1,
collectionId: submissions.id,
cascadeDelete: true,
},
{ name: "user", type: "relation", required: true, maxSelect: 1, collectionId: users.id, cascadeDelete: true },
{ name: "reason", type: "text", required: true, min: 3, max: 1000 },
{ name: "created", type: "autodate", onCreate: true },
],
});
app.save(reports);
}
let comments;
try {
comments = app.findCollectionByNameOrId("comments");
} catch {
comments = new Collection({
type: "base",
name: "comments",
listRule: "",
viewRule: "",
createRule: "@request.auth.id != ''",
updateRule: "author = @request.auth.id",
deleteRule: "author = @request.auth.id",
fields: [
{
name: "submission",
type: "relation",
required: true,
maxSelect: 1,
collectionId: submissions.id,
cascadeDelete: true,
},
{
name: "author",
type: "relation",
required: true,
maxSelect: 1,
collectionId: users.id,
cascadeDelete: true,
},
{ name: "content", type: "text", required: true, min: 1, max: 2000 },
{ name: "created", type: "autodate", onCreate: true },
{ name: "updated", type: "autodate", onCreate: true, onUpdate: true },
],
});
comments.addIndex("idx_comments_submission", false, "submission", "");
app.save(comments);
}
},
(app) => {
for (const name of ["comments", "reports", "votes", "submissions"]) {
try {
app.delete(app.findCollectionByNameOrId(name));
} catch {
// already gone
}
}
},
);
@@ -1,49 +0,0 @@
/// <reference path="../pb_data/types.d.ts" />
migrate(
(app) => {
// Keep databases created by the original prototype valid after the
// migration file was renamed with the feature.
try {
app.findCollectionByNameOrId("marketplace");
return;
} catch {
// Fresh database; create the public view below.
}
const collection = new Collection({
name: "marketplace",
type: "view",
listRule: "",
viewRule: "",
viewQuery: `
SELECT
s.id,
s.type,
s.title,
s.description,
s.schemaVersion,
s.content,
s.screenshots,
s.version,
s.changelog,
s.author,
s.created,
s.updated,
COALESCE(NULLIF(u.name, ''), 'unknown') as authorName,
COALESCE(SUM(CASE WHEN v.value = 1 THEN 1 ELSE 0 END), 0) as upvotes,
COALESCE(SUM(CASE WHEN v.value = -1 THEN 1 ELSE 0 END), 0) as downvotes,
(SELECT COUNT(*) FROM comments c WHERE c.submission = s.id) as commentCount
FROM submissions s
LEFT JOIN users u ON u.id = s.author
LEFT JOIN votes v ON v.submission = s.id
GROUP BY s.id
`,
});
app.save(collection);
},
(app) => {
const collection = app.findCollectionByNameOrId("marketplace");
app.delete(collection);
},
);
-30
View File
@@ -1,30 +0,0 @@
#!/bin/sh
set -eu
image="${1:-homarr/workshop:ci}"
container="homarr-workshop-smoke-${$}"
port="${WORKSHOP_SMOKE_PORT:-18090}"
cleanup() {
docker rm --force "$container" >/dev/null 2>&1 || true
}
trap cleanup EXIT INT TERM
docker run --detach --name "$container" --publish "127.0.0.1:${port}:8090" "$image" >/dev/null
attempt=0
until curl --fail --silent "http://127.0.0.1:${port}/api/health" >/dev/null; do
attempt=$((attempt + 1))
if [ "$attempt" -ge 30 ]; then
docker logs "$container"
exit 1
fi
sleep 1
done
curl --fail --silent "http://127.0.0.1:${port}/" | grep --quiet "Homarr"
curl --fail --silent "http://127.0.0.1:${port}/workshop/" | grep --quiet "Workshop"
curl --fail --silent "http://127.0.0.1:${port}/api/collections/marketplace/records?page=1&perPage=1" >/dev/null
curl --fail --silent "http://127.0.0.1:${port}/api/health" | grep --quiet '"code":200'
echo "Workshop image serves Docusaurus and PocketBase successfully"