4d1a53fc69
- Created backend directory structure - Added .env configuration for PocketBase - Added initial migration with users, groups, games, teamSessions, invitations collections - Added docker-compose.yml for containerized deployment - Added README.md with setup instructions Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
782 lines
17 KiB
JavaScript
782 lines
17 KiB
JavaScript
/// <reference path="../pb_data/types.d.ts" />
|
|
|
|
migrate((app) => {
|
|
// Users collection
|
|
app.deleteCollection("users");
|
|
app.createCollection("users", {
|
|
id: "users",
|
|
name: "users",
|
|
type: "auth",
|
|
fields: [
|
|
{
|
|
id: "new_aQr3td8dJl",
|
|
name: "username",
|
|
type: "text",
|
|
system: false,
|
|
required: true,
|
|
unique: true,
|
|
options: {
|
|
min: 3,
|
|
max: 20,
|
|
pattern: "^[a-zA-Z0-9_]+$",
|
|
}
|
|
},
|
|
{
|
|
id: "new_Jx4zWq9kLm",
|
|
name: "displayName",
|
|
type: "text",
|
|
system: false,
|
|
required: true,
|
|
unique: false,
|
|
options: {
|
|
min: null,
|
|
max: 50,
|
|
pattern: "",
|
|
}
|
|
},
|
|
{
|
|
id: "new_Xp7vR2sT4u",
|
|
name: "avatar",
|
|
type: "url",
|
|
system: false,
|
|
required: false,
|
|
unique: false,
|
|
options: {
|
|
exceptDomains: null,
|
|
onlyDomains: null,
|
|
}
|
|
},
|
|
{
|
|
id: "new_Nh8gD3fF6g",
|
|
name: "bio",
|
|
type: "text",
|
|
system: false,
|
|
required: false,
|
|
unique: false,
|
|
options: {
|
|
min: null,
|
|
max: 500,
|
|
pattern: "",
|
|
}
|
|
},
|
|
{
|
|
id: "new_Vc5bH8kJ7o",
|
|
name: "region",
|
|
type: "select",
|
|
system: false,
|
|
required: true,
|
|
unique: false,
|
|
options: {
|
|
maxSelect: 1,
|
|
values: [
|
|
"cn",
|
|
"us",
|
|
"eu",
|
|
"asia",
|
|
"other"
|
|
],
|
|
}
|
|
},
|
|
{
|
|
id: "new_Tf6rK9mP8q",
|
|
name: "preferences",
|
|
type: "json",
|
|
system: false,
|
|
required: false,
|
|
unique: false,
|
|
options: {
|
|
maxSize: 10000,
|
|
}
|
|
},
|
|
{
|
|
id: "new_Dg7hL0nR9s",
|
|
name: "stats",
|
|
type: "json",
|
|
system: false,
|
|
required: false,
|
|
unique: false,
|
|
options: {
|
|
maxSize: 10000,
|
|
}
|
|
},
|
|
{
|
|
id: "new_Wm8jO1pS0t",
|
|
name: "isActive",
|
|
type: "bool",
|
|
system: false,
|
|
required: false,
|
|
unique: false,
|
|
options: {}
|
|
},
|
|
{
|
|
id: "new_Yn9kQ2qT1u",
|
|
name: "lastSeen",
|
|
type: "date",
|
|
system: false,
|
|
required: false,
|
|
unique: false,
|
|
options: {
|
|
min: "",
|
|
max: "",
|
|
}
|
|
},
|
|
],
|
|
indexes: [
|
|
"create index users_username_idx on users (username)",
|
|
"create index users_region_idx on users (region)",
|
|
"create index users_isActive_idx on users (isActive)",
|
|
],
|
|
listRule: "id = @request.auth.id",
|
|
viewRule: "id = @request.auth.id",
|
|
createRule: null,
|
|
updateRule: "id = @request.auth.id",
|
|
deleteRule: "id = @request.auth.id",
|
|
options: {
|
|
allowEmailAuth: true,
|
|
allowOAuth2Auth: false,
|
|
allowUsernameAuth: false,
|
|
exceptEmailDomains: null,
|
|
manageRule: null,
|
|
minPasswordLength: 8,
|
|
onlyEmailDomains: null,
|
|
requireEmail: false,
|
|
}
|
|
});
|
|
|
|
// Games collection
|
|
app.deleteCollection("games");
|
|
app.createCollection("games", {
|
|
id: "games",
|
|
name: "games",
|
|
type: "base",
|
|
fields: [
|
|
{
|
|
id: "new_Zp3wT8sV5x",
|
|
name: "name",
|
|
type: "text",
|
|
system: false,
|
|
required: true,
|
|
unique: true,
|
|
options: {
|
|
min: 1,
|
|
max: 100,
|
|
pattern: "",
|
|
}
|
|
},
|
|
{
|
|
id: "new_Bq4xU9tW6y",
|
|
name: "nameEn",
|
|
type: "text",
|
|
system: false,
|
|
required: false,
|
|
unique: false,
|
|
options: {
|
|
min: null,
|
|
max: 100,
|
|
pattern: "",
|
|
}
|
|
},
|
|
{
|
|
id: "new_Cr5yV0uX7z",
|
|
name: "cover",
|
|
type: "url",
|
|
system: false,
|
|
required: false,
|
|
unique: false,
|
|
options: {
|
|
exceptDomains: null,
|
|
onlyDomains: null,
|
|
}
|
|
},
|
|
{
|
|
id: "new_Ds6zW1vY8a",
|
|
name: "description",
|
|
type: "editor",
|
|
system: false,
|
|
required: false,
|
|
unique: false,
|
|
options: {
|
|
convertUrls: false,
|
|
}
|
|
},
|
|
{
|
|
id: "new_Et7aX2wZ9b",
|
|
name: "type",
|
|
type: "select",
|
|
system: false,
|
|
required: true,
|
|
unique: false,
|
|
options: {
|
|
maxSelect: 1,
|
|
values: [
|
|
"fps",
|
|
"moba",
|
|
"rpg",
|
|
"strategy",
|
|
"racing",
|
|
"sports",
|
|
"casual",
|
|
"other"
|
|
],
|
|
}
|
|
},
|
|
{
|
|
id: "new_Fu8bY3xA0c",
|
|
name: "platform",
|
|
type: "select",
|
|
system: false,
|
|
required: true,
|
|
unique: false,
|
|
options: {
|
|
maxSelect: 1,
|
|
values: [
|
|
"pc",
|
|
"mobile",
|
|
"console",
|
|
"crossplay"
|
|
],
|
|
}
|
|
},
|
|
{
|
|
id: "new_Gv9cZ4yB1d",
|
|
name: "maxTeamSize",
|
|
type: "number",
|
|
system: false,
|
|
required: true,
|
|
unique: false,
|
|
options: {
|
|
min: 2,
|
|
max: 100,
|
|
noDecimal: true,
|
|
}
|
|
},
|
|
{
|
|
id: "new_Hw0dA5zC2e",
|
|
name: "tags",
|
|
type: "json",
|
|
system: false,
|
|
required: false,
|
|
unique: false,
|
|
options: {
|
|
maxSize: 5000,
|
|
}
|
|
},
|
|
{
|
|
id: "new_Ix1eB6aD3f",
|
|
name: "isActive",
|
|
type: "bool",
|
|
system: false,
|
|
required: false,
|
|
unique: false,
|
|
options: {}
|
|
},
|
|
],
|
|
indexes: [
|
|
"create index games_name_idx on games (name)",
|
|
"create index games_type_idx on games (type)",
|
|
"create index games_platform_idx on games (platform)",
|
|
"create index games_isActive_idx on games (isActive)",
|
|
],
|
|
listRule: "",
|
|
viewRule: "",
|
|
createRule: null,
|
|
updateRule: null,
|
|
deleteRule: null,
|
|
options: {
|
|
allowEmailAuth: false,
|
|
allowOAuth2Auth: false,
|
|
allowUsernameAuth: false,
|
|
exceptEmailDomains: null,
|
|
manageRule: null,
|
|
onlyEmailDomains: null,
|
|
requireEmail: false,
|
|
}
|
|
});
|
|
|
|
// Groups collection
|
|
app.deleteCollection("groups");
|
|
app.createCollection("groups", {
|
|
id: "groups",
|
|
name: "groups",
|
|
type: "base",
|
|
fields: [
|
|
{
|
|
id: "new_Jy2fC7bE4g",
|
|
name: "name",
|
|
type: "text",
|
|
system: false,
|
|
required: true,
|
|
unique: false,
|
|
options: {
|
|
min: 3,
|
|
max: 50,
|
|
pattern: "",
|
|
}
|
|
},
|
|
{
|
|
id: "new_Kz3gD8cF5h",
|
|
name: "description",
|
|
type: "text",
|
|
system: false,
|
|
required: false,
|
|
unique: false,
|
|
options: {
|
|
min: null,
|
|
max: 500,
|
|
pattern: "",
|
|
}
|
|
},
|
|
{
|
|
id: "new_La4hE9dG6i",
|
|
name: "avatar",
|
|
type: "url",
|
|
system: false,
|
|
required: false,
|
|
unique: false,
|
|
options: {
|
|
exceptDomains: null,
|
|
onlyDomains: null,
|
|
}
|
|
},
|
|
{
|
|
id: "new_Mb5iF0eH7j",
|
|
name: "owner",
|
|
type: "relation",
|
|
system: false,
|
|
required: true,
|
|
unique: false,
|
|
options: {
|
|
collectionId: "users",
|
|
cascadeDelete: true,
|
|
minSelect: null,
|
|
maxSelect: 1,
|
|
displayFields: [
|
|
"username",
|
|
"displayName"
|
|
],
|
|
}
|
|
},
|
|
{
|
|
id: "new_Nc6jG1fI8k",
|
|
name: "game",
|
|
type: "relation",
|
|
system: false,
|
|
required: true,
|
|
unique: false,
|
|
options: {
|
|
collectionId: "games",
|
|
cascadeDelete: false,
|
|
minSelect: null,
|
|
maxSelect: 1,
|
|
displayFields: [
|
|
"name"
|
|
],
|
|
}
|
|
},
|
|
{
|
|
id: "new_Od7kH2gJ9l",
|
|
name: "members",
|
|
type: "relation",
|
|
system: false,
|
|
required: false,
|
|
unique: false,
|
|
options: {
|
|
collectionId: "users",
|
|
cascadeDelete: false,
|
|
minSelect: null,
|
|
maxSelect: null,
|
|
displayFields: [
|
|
"username",
|
|
"displayName"
|
|
],
|
|
}
|
|
},
|
|
{
|
|
id: "new_Pe8lI3hK0m",
|
|
name: "maxMembers",
|
|
type: "number",
|
|
system: false,
|
|
required: true,
|
|
unique: false,
|
|
options: {
|
|
min: 2,
|
|
max: 100,
|
|
noDecimal: true,
|
|
}
|
|
},
|
|
{
|
|
id: "new_Qf9mJ4iL1n",
|
|
name: "status",
|
|
type: "select",
|
|
system: false,
|
|
required: true,
|
|
unique: false,
|
|
options: {
|
|
maxSelect: 1,
|
|
values: [
|
|
"recruiting",
|
|
"full",
|
|
"inactive"
|
|
],
|
|
}
|
|
},
|
|
{
|
|
id: "new_Rg0nK5jM2o",
|
|
name: "tags",
|
|
type: "json",
|
|
system: false,
|
|
required: false,
|
|
unique: false,
|
|
options: {
|
|
maxSize: 5000,
|
|
}
|
|
},
|
|
{
|
|
id: "new_Sh1oL6kN3p",
|
|
name: "requirements",
|
|
type: "json",
|
|
system: false,
|
|
required: false,
|
|
unique: false,
|
|
options: {
|
|
maxSize: 10000,
|
|
}
|
|
},
|
|
{
|
|
id: "new_Ti2pM7lO4q",
|
|
name: "stats",
|
|
type: "json",
|
|
system: false,
|
|
required: false,
|
|
unique: false,
|
|
options: {
|
|
maxSize: 10000,
|
|
}
|
|
},
|
|
],
|
|
indexes: [
|
|
"create index groups_name_idx on groups (name)",
|
|
"create index groups_owner_idx on groups (owner)",
|
|
"create index groups_game_idx on groups (game)",
|
|
"create index groups_status_idx on groups (status)",
|
|
],
|
|
listRule: "",
|
|
viewRule: "",
|
|
createRule: "@request.auth.id != \"\"",
|
|
updateRule: "owner = @request.auth.id",
|
|
deleteRule: "owner = @request.auth.id",
|
|
options: {
|
|
allowEmailAuth: false,
|
|
allowOAuth2Auth: false,
|
|
allowUsernameAuth: false,
|
|
exceptEmailDomains: null,
|
|
manageRule: null,
|
|
onlyEmailDomains: null,
|
|
requireEmail: false,
|
|
}
|
|
});
|
|
|
|
// Team Sessions collection
|
|
app.deleteCollection("teamSessions");
|
|
app.createCollection("teamSessions", {
|
|
id: "teamSessions",
|
|
name: "teamSessions",
|
|
type: "base",
|
|
fields: [
|
|
{
|
|
id: "new_Uj3qN8mP5r",
|
|
name: "group",
|
|
type: "relation",
|
|
system: false,
|
|
required: true,
|
|
unique: false,
|
|
options: {
|
|
collectionId: "groups",
|
|
cascadeDelete: true,
|
|
minSelect: null,
|
|
maxSelect: 1,
|
|
displayFields: [
|
|
"name"
|
|
],
|
|
}
|
|
},
|
|
{
|
|
id: "new_Vk4rO9nQ6s",
|
|
name: "host",
|
|
type: "relation",
|
|
system: false,
|
|
required: true,
|
|
unique: false,
|
|
options: {
|
|
collectionId: "users",
|
|
cascadeDelete: false,
|
|
minSelect: null,
|
|
maxSelect: 1,
|
|
displayFields: [
|
|
"username",
|
|
"displayName"
|
|
],
|
|
}
|
|
},
|
|
{
|
|
id: "new_Wl5sP0oR7t",
|
|
name: "participants",
|
|
type: "relation",
|
|
system: false,
|
|
required: false,
|
|
unique: false,
|
|
options: {
|
|
collectionId: "users",
|
|
cascadeDelete: false,
|
|
minSelect: null,
|
|
maxSelect: null,
|
|
displayFields: [
|
|
"username",
|
|
"displayName"
|
|
],
|
|
}
|
|
},
|
|
{
|
|
id: "new_Xm6tQ1pS8u",
|
|
name: "status",
|
|
type: "select",
|
|
system: false,
|
|
required: true,
|
|
unique: false,
|
|
options: {
|
|
maxSelect: 1,
|
|
values: [
|
|
"waiting",
|
|
"playing",
|
|
"completed",
|
|
"cancelled"
|
|
],
|
|
}
|
|
},
|
|
{
|
|
id: "new_Yn7uR2qT9v",
|
|
name: "voiceChat",
|
|
type: "bool",
|
|
system: false,
|
|
required: false,
|
|
unique: false,
|
|
options: {}
|
|
},
|
|
{
|
|
id: "new_Zo8vS3rU0w",
|
|
name: "roomInfo",
|
|
type: "json",
|
|
system: false,
|
|
required: false,
|
|
unique: false,
|
|
options: {
|
|
maxSize: 10000,
|
|
}
|
|
},
|
|
{
|
|
id: "new_Ap9wT4sV1x",
|
|
name: "notes",
|
|
type: "text",
|
|
system: false,
|
|
required: false,
|
|
unique: false,
|
|
options: {
|
|
min: null,
|
|
max: 1000,
|
|
pattern: "",
|
|
}
|
|
},
|
|
{
|
|
id: "new_Bq0xU5tW2y",
|
|
name: "scheduledAt",
|
|
type: "date",
|
|
system: false,
|
|
required: false,
|
|
unique: false,
|
|
options: {
|
|
min: "",
|
|
max: "",
|
|
}
|
|
},
|
|
{
|
|
id: "new_Cr1yV6uX3z",
|
|
name: "startedAt",
|
|
type: "date",
|
|
system: false,
|
|
required: false,
|
|
unique: false,
|
|
options: {
|
|
min: "",
|
|
max: "",
|
|
}
|
|
},
|
|
{
|
|
id: "new_Ds2zW7vY4a",
|
|
name: "endedAt",
|
|
type: "date",
|
|
system: false,
|
|
required: false,
|
|
unique: false,
|
|
options: {
|
|
min: "",
|
|
max: "",
|
|
}
|
|
},
|
|
],
|
|
indexes: [
|
|
"create index teamSessions_group_idx on teamSessions (group)",
|
|
"create index teamSessions_host_idx on teamSessions (host)",
|
|
"create index teamSessions_status_idx on teamSessions (status)",
|
|
"create index teamSessions_scheduledAt_idx on teamSessions (scheduledAt)",
|
|
],
|
|
listRule: "group.owner = @request.auth.id || group.members.id = @request.auth.id",
|
|
viewRule: "group.owner = @request.auth.id || group.members.id = @request.auth.id",
|
|
createRule: "@request.auth.id != \"\"",
|
|
updateRule: "group.owner = @request.auth.id",
|
|
deleteRule: "group.owner = @request.auth.id",
|
|
options: {
|
|
allowEmailAuth: false,
|
|
allowOAuth2Auth: false,
|
|
allowUsernameAuth: false,
|
|
exceptEmailDomains: null,
|
|
manageRule: null,
|
|
onlyEmailDomains: null,
|
|
requireEmail: false,
|
|
}
|
|
});
|
|
|
|
// Invitations collection
|
|
app.deleteCollection("invitations");
|
|
app.createCollection("invitations", {
|
|
id: "invitations",
|
|
name: "invitations",
|
|
type: "base",
|
|
fields: [
|
|
{
|
|
id: "new_Et3yZ8wB5c",
|
|
name: "group",
|
|
type: "relation",
|
|
system: false,
|
|
required: true,
|
|
unique: false,
|
|
options: {
|
|
collectionId: "groups",
|
|
cascadeDelete: true,
|
|
minSelect: null,
|
|
maxSelect: 1,
|
|
displayFields: [
|
|
"name"
|
|
],
|
|
}
|
|
},
|
|
{
|
|
id: "new_Fu4zA9xC6d",
|
|
name: "sender",
|
|
type: "relation",
|
|
system: false,
|
|
required: true,
|
|
unique: false,
|
|
options: {
|
|
collectionId: "users",
|
|
cascadeDelete: false,
|
|
minSelect: null,
|
|
maxSelect: 1,
|
|
displayFields: [
|
|
"username",
|
|
"displayName"
|
|
],
|
|
}
|
|
},
|
|
{
|
|
id: "new_Gv5aB0yD7e",
|
|
name: "recipient",
|
|
type: "relation",
|
|
system: false,
|
|
required: true,
|
|
unique: false,
|
|
options: {
|
|
collectionId: "users",
|
|
cascadeDelete: false,
|
|
minSelect: null,
|
|
maxSelect: 1,
|
|
displayFields: [
|
|
"username",
|
|
"displayName"
|
|
],
|
|
}
|
|
},
|
|
{
|
|
id: "new_Hw6bC1zE8f",
|
|
name: "status",
|
|
type: "select",
|
|
system: false,
|
|
required: true,
|
|
unique: false,
|
|
options: {
|
|
maxSelect: 1,
|
|
values: [
|
|
"pending",
|
|
"accepted",
|
|
"rejected",
|
|
"cancelled"
|
|
],
|
|
}
|
|
},
|
|
{
|
|
id: "new_Ix7cD2aF9g",
|
|
name: "message",
|
|
type: "text",
|
|
system: false,
|
|
required: false,
|
|
unique: false,
|
|
options: {
|
|
min: null,
|
|
max: 500,
|
|
pattern: "",
|
|
}
|
|
},
|
|
{
|
|
id: "new_Jy8dE3bG0h",
|
|
name: "respondedAt",
|
|
type: "date",
|
|
system: false,
|
|
required: false,
|
|
unique: false,
|
|
options: {
|
|
min: "",
|
|
max: "",
|
|
}
|
|
},
|
|
],
|
|
indexes: [
|
|
"create index invitations_group_idx on invitations (group)",
|
|
"create index invitations_sender_idx on invitations (sender)",
|
|
"create index invitations_recipient_idx on invitations (recipient)",
|
|
"create index invitations_status_idx on invitations (status)",
|
|
"create unique index invitations_unique_pending on invitations (group, recipient) where status = 'pending'",
|
|
],
|
|
listRule: "sender = @request.auth.id || recipient = @request.auth.id || group.owner = @request.auth.id",
|
|
viewRule: "sender = @request.auth.id || recipient = @request.auth.id || group.owner = @request.auth.id",
|
|
createRule: "group.owner = @request.auth.id",
|
|
updateRule: "recipient = @request.auth.id",
|
|
deleteRule: "sender = @request.auth.id || group.owner = @request.auth.id",
|
|
options: {
|
|
allowEmailAuth: false,
|
|
allowOAuth2Auth: false,
|
|
allowUsernameAuth: false,
|
|
exceptEmailDomains: null,
|
|
manageRule: null,
|
|
onlyEmailDomains: null,
|
|
requireEmail: false,
|
|
}
|
|
});
|
|
|
|
}, (app) => {
|
|
// Rollback
|
|
app.deleteCollection("invitations");
|
|
app.deleteCollection("teamSessions");
|
|
app.deleteCollection("groups");
|
|
app.deleteCollection("games");
|
|
app.deleteCollection("users");
|
|
});
|