Compare commits

..

2 Commits

Author SHA1 Message Date
lbenedar
21abe68858 finish setup insert method, refactor sql migration file 2026-04-17 17:33:21 +03:00
lbenedar
1b7c7e9ae3 add setup insert methods 2026-04-16 18:30:00 +03:00
58 changed files with 2636 additions and 964 deletions

View File

@@ -2,7 +2,6 @@ package main
import ( import (
"context" "context"
"database/sql"
"flag" "flag"
"log" "log"
"log/slog" "log/slog"
@@ -14,6 +13,7 @@ import (
"gitea.local.lab/Lbenedar/foundry_helper_service/internal/foundry/requests" "gitea.local.lab/Lbenedar/foundry_helper_service/internal/foundry/requests"
"gitea.local.lab/Lbenedar/foundry_helper_service/internal/foundry/transport" "gitea.local.lab/Lbenedar/foundry_helper_service/internal/foundry/transport"
"github.com/jmoiron/sqlx"
_ "github.com/mattn/go-sqlite3" _ "github.com/mattn/go-sqlite3"
) )
@@ -47,8 +47,8 @@ type application struct {
var version = "0.1.0" var version = "0.1.0"
func openDB(cfg config) (*sql.DB, error) { func openDB(cfg config) (*sqlx.DB, error) {
db, err := sql.Open("sqlite3", cfg.db.dsn) db, err := sqlx.Open("sqlite3", cfg.db.dsn)
if err != nil { if err != nil {
return nil, err return nil, err
} }

View File

@@ -1,2 +0,0 @@
DROP TABLE IF EXISTS options;
DROP TABLE IF EXISTS foundry_state;

View File

@@ -0,0 +1,38 @@
DROP TABLE IF EXISTS folder;
DROP TABLE IF EXISTS pack;
DROP TABLE IF EXISTS language;
DROP TABLE IF EXISTS style;
DROP TABLE IF EXISTS media;
DROP TABLE IF EXISTS author;
DROP TABLE IF EXISTS es_modules;
DROP TABLE IF EXISTS scripts;
DROP TABLE IF EXISTS tags;
DROP TABLE IF EXISTS relationships;
DROP TABLE IF EXISTS compatibility;
DROP TABLE IF EXISTS world;
DROP TABLE IF EXISTS grid;
DROP TABLE IF EXISTS system;
DROP TABLE IF EXISTS package_warnings_data_error;
DROP TABLE IF EXISTS package_warnings_data_warning;
DROP TABLE IF EXISTS package_warnings_data;
DROP TABLE IF EXISTS package_warnings;
DROP TABLE IF EXISTS news;
DROP TABLE IF EXISTS folder_packs;
DROP TABLE IF EXISTS folder;
DROP TABLE IF EXISTS pack_folder;
DROP TABLE IF EXISTS index_;
DROP TABLE IF EXISTS ownership;
DROP TABLE IF EXISTS relationships_data;
DROP TABLE IF EXISTS document_types_data_html;
DROP TABLE IF EXISTS document_types_data;
DROP TABLE IF EXISTS document_types;
DROP TABLE IF EXISTS module;
DROP TABLE IF EXISTS setup_language_module;
DROP TABLE IF EXISTS setup_language;
DROP TABLE IF EXISTS release_;
DROP TABLE IF EXISTS setup_options;
DROP TABLE IF EXISTS files_storage;
DROP TABLE IF EXISTS files;
DROP TABLE IF EXISTS featured_content;
DROP TABLE IF EXISTS core_update;
DROP TABLE IF EXISTS setup;

View File

@@ -0,0 +1,526 @@
CREATE TABLE IF NOT EXISTS setup (
id INTEGER PRIMARY KEY AUTOINCREMENT,
is_admin BOOLEAN NOT NULL DEFAULT FALSE,
is_setup BOOLEAN NOT NULL DEFAULT TRUE,
created_at DATETIME NOT NULL DEFAULT current_timestamp
);
CREATE TABLE IF NOT EXISTS core_update (
id INTEGER PRIMARY KEY AUTOINCREMENT,
has_update BOOLEAN NOT NULL DEFAULT FALSE,
can_update BOOLEAN NOT NULL DEFAULT FALSE,
could_reach_website BOOLEAN NOT NULL DEFAULT FALSE,
slow_response BOOLEAN NOT NULL DEFAULT FALSE,
will_disable_modules BOOLEAN NOT NULL DEFAULT FALSE,
version VARCHAR(64) NOT NULL,
channel VARCHAR(64) NOT NULL,
setup_id INTEGER UNIQUE,
FOREIGN KEY (setup_id) REFERENCES setup(id) ON DELETE CASCADE
);
CREATE TABLE IF NOT EXISTS featured_content (
id INTEGER PRIMARY KEY AUTOINCREMENT,
title VARCHAR(128) NOT NULL,
caption VARCHAR(128) NOT NULL,
url VARCHAR(128) NOT NULL,
image VARCHAR(128) NOT NULL,
setup_id INTEGER UNIQUE,
FOREIGN KEY (setup_id) REFERENCES setup(id) ON DELETE CASCADE
);
CREATE TABLE IF NOT EXISTS files (
id INTEGER PRIMARY KEY AUTOINCREMENT,
setup_id INTEGER UNIQUE,
FOREIGN KEY (setup_id) REFERENCES setup(id) ON DELETE CASCADE
);
CREATE TABLE IF NOT EXISTS files_storage (
id INTEGER PRIMARY KEY AUTOINCREMENT,
storage TEXT NOT NULL,
files_id INTEGER,
FOREIGN KEY (files_id) REFERENCES files(id) ON DELETE CASCADE
);
CREATE TABLE IF NOT EXISTS setup_options (
id INTEGER PRIMARY KEY AUTOINCREMENT,
css_theme VARCHAR(128) NOT NULL,
data_path VARCHAR(128) NOT NULL,
hostname VARCHAR(128) NOT NULL,
language VARCHAR(128) NOT NULL,
local_hostname VARCHAR(128) NOT NULL,
update_channel VARCHAR(128) NOT NULL,
port INTEGER NOT NULL,
compress_socket BOOLEAN NOT NULL DEFAULT FALSE,
compress_static BOOLEAN NOT NULL DEFAULT FALSE,
fullscreen BOOLEAN NOT NULL DEFAULT FALSE,
hot_reload BOOLEAN NOT NULL DEFAULT FALSE,
proxy_ssl BOOLEAN NOT NULL,
telemetry BOOLEAN NOT NULL,
upnp BOOLEAN NOT NULL,
delete_nedb BOOLEAN NOT NULL,
no_backups BOOLEAN NOT NULL,
setup_id INTEGER UNIQUE,
FOREIGN KEY (setup_id) REFERENCES setup(id) ON DELETE CASCADE
);
CREATE TABLE IF NOT EXISTS release_ (
id INTEGER PRIMARY KEY AUTOINCREMENT,
generation INTEGER NOT NULL,
build INTEGER NOT NULL,
node_version INTEGER NOT NULL,
max_generation INTEGER NOT NULL,
max_stable_generation INTEGER NOT NULL,
time DATETIME NOT NULL,
channel VARCHAR(128) NOT NULL,
suffix VARCHAR(128) NOT NULL,
setup_id INTEGER UNIQUE,
FOREIGN KEY (setup_id) REFERENCES setup(id) ON DELETE CASCADE
);
CREATE TABLE IF NOT EXISTS setup_language (
id INTEGER PRIMARY KEY,
label VARCHAR(128) NOT NULL,
setup_id INTEGER,
FOREIGN KEY (setup_id) REFERENCES setup(id) ON DELETE CASCADE
);
CREATE TABLE IF NOT EXISTS setup_language_module (
id TEXT PRIMARY KEY,
label VARCHAR(128) NOT NULL,
path VARCHAR(128) NOT NULL,
setup_language_id INTEGER,
FOREIGN KEY (setup_language_id) REFERENCES setup_language(id) ON DELETE CASCADE
);
CREATE TABLE IF NOT EXISTS module (
id TEXT PRIMARY KEY,
title VARCHAR(128) NOT NULL,
description VARCHAR(128) NOT NULL,
url VARCHAR(128) NOT NULL,
license VARCHAR(128) NOT NULL,
readme VARCHAR(128) NOT NULL,
bugs VARCHAR(128) NOT NULL,
changelog VARCHAR(128) NOT NULL,
version VARCHAR(128) NOT NULL,
manifest VARCHAR(128) NOT NULL,
download VARCHAR(128) NOT NULL,
socket BOOLEAN NOT NULL DEFAULT FALSE,
protected BOOLEAN NOT NULL DEFAULT FALSE,
exclusive_ BOOLEAN NOT NULL DEFAULT FALSE,
persistent_storage BOOLEAN NOT NULL DEFAULT FALSE,
core_translation BOOLEAN NOT NULL DEFAULT FALSE,
library BOOLEAN NOT NULL DEFAULT FALSE,
locked BOOLEAN NOT NULL DEFAULT FALSE,
owned BOOLEAN NOT NULL DEFAULT FALSE,
has_storage BOOLEAN NOT NULL DEFAULT FALSE,
active BOOLEAN NOT NULL DEFAULT FALSE,
availability INTEGER NOT NULL DEFAULT FALSE,
setup_id INTEGER,
FOREIGN KEY (setup_id) REFERENCES setup(id) ON DELETE CASCADE
);
CREATE TABLE IF NOT EXISTS document_types (
id INTEGER PRIMARY KEY AUTOINCREMENT,
module_id TEXT UNIQUE,
FOREIGN KEY (module_id) REFERENCES module(id) ON DELETE CASCADE
);
CREATE TABLE IF NOT EXISTS document_types_data (
id INTEGER PRIMARY KEY AUTOINCREMENT,
type VARCHAR(64) NOT NULL,
document_types_id INTEGER,
FOREIGN KEY (document_types_id) REFERENCES document_types(id) ON DELETE CASCADE
);
CREATE TABLE IF NOT EXISTS document_types_data_html (
id INTEGER PRIMARY KEY AUTOINCREMENT,
value TEXT NOT NULL,
document_types_data_id INTEGER,
FOREIGN KEY (document_types_data_id) REFERENCES document_types_data(id) ON DELETE CASCADE
);
CREATE TABLE IF NOT EXISTS relationships (
id INTEGER PRIMARY KEY AUTOINCREMENT,
module_id TEXT UNIQUE,
FOREIGN KEY (module_id) REFERENCES module(id) ON DELETE CASCADE
);
CREATE TABLE IF NOT EXISTS relationships_systems (
id TEXT PRIMARY KEY,
relationships_type VARCHAR(32) NOT NULL,
type TEXT NOT NULL,
manifest TEXT NOT NULL,
relationships_id INTEGER,
FOREIGN KEY (relationships_id) REFERENCES relationships(id) ON DELETE CASCADE
);
CREATE TABLE IF NOT EXISTS relationships_requires (
id TEXT PRIMARY KEY,
relationships_type VARCHAR(32) NOT NULL,
type TEXT NOT NULL,
manifest TEXT NOT NULL,
relationships_id INTEGER,
FOREIGN KEY (relationships_id) REFERENCES relationships(id) ON DELETE CASCADE
);
CREATE TABLE IF NOT EXISTS relationships_recommends (
id TEXT PRIMARY KEY,
relationships_type VARCHAR(32) NOT NULL,
type TEXT NOT NULL,
manifest TEXT NOT NULL,
relationships_id INTEGER,
FOREIGN KEY (relationships_id) REFERENCES relationships(id) ON DELETE CASCADE
);
CREATE TABLE IF NOT EXISTS relationships_conflicts (
id TEXT PRIMARY KEY,
relationships_type VARCHAR(32) NOT NULL,
type TEXT NOT NULL,
manifest TEXT NOT NULL,
relationships_id INTEGER,
FOREIGN KEY (relationships_id) REFERENCES relationships(id) ON DELETE CASCADE
);
CREATE TABLE IF NOT EXISTS compatibility (
id INTEGER PRIMARY KEY AUTOINCREMENT,
minimum VARCHAR(64) NOT NULL,
verified VARCHAR(64) NOT NULL,
maximum VARCHAR(64) NOT NULL,
module_id TEXT UNIQUE,
FOREIGN KEY (module_id) REFERENCES module(id) ON DELETE CASCADE,
relationships_systems_id TEXT UNIQUE,
FOREIGN KEY (relationships_systems_id) REFERENCES relationships_systems(id) ON DELETE CASCADE
relationships_requires_id TEXT UNIQUE,
FOREIGN KEY (relationships_requires_id) REFERENCES relationships_requires(id) ON DELETE CASCADE
relationships_recommends_id TEXT UNIQUE,
FOREIGN KEY (relationships_recommends_id) REFERENCES relationships_recommends(id) ON DELETE CASCADE
relationships_conflicts_id TEXT UNIQUE,
FOREIGN KEY (relationships_conflicts_id) REFERENCES relationships_conflicts(id) ON DELETE CASCADE
);
CREATE TABLE IF NOT EXISTS scripts (
id INTEGER PRIMARY KEY AUTOINCREMENT,
value TEXT NOT NULL,
module_id TEXT,
FOREIGN KEY (module_id) REFERENCES module(id) ON DELETE CASCADE
);
CREATE TABLE IF NOT EXISTS es_modules (
id INTEGER PRIMARY KEY AUTOINCREMENT,
value TEXT NOT NULL,
module_id TEXT,
FOREIGN KEY (module_id) REFERENCES module(id) ON DELETE CASCADE
);
CREATE TABLE IF NOT EXISTS tags (
id INTEGER PRIMARY KEY AUTOINCREMENT,
value VARCHAR(128) NOT NULL,
module_id TEXT,
FOREIGN KEY (module_id) REFERENCES module(id) ON DELETE CASCADE
);
CREATE TABLE IF NOT EXISTS author (
id INTEGER PRIMARY KEY AUTOINCREMENT,
name VARCHAR(128) NOT NULL,
url VARCHAR(128) NOT NULL,
email VARCHAR(128) NOT NULL,
discord VARCHAR(128) NOT NULL,
module_id TEXT,
FOREIGN KEY (module_id) REFERENCES module(id) ON DELETE CASCADE
);
CREATE TABLE IF NOT EXISTS media (
id INTEGER PRIMARY KEY AUTOINCREMENT,
type VARCHAR(128) NOT NULL,
url VARCHAR(128) NOT NULL,
caption VARCHAR(128) NOT NULL,
module_id TEXT,
FOREIGN KEY (module_id) REFERENCES module(id) ON DELETE CASCADE
);
CREATE TABLE IF NOT EXISTS style (
id INTEGER PRIMARY KEY AUTOINCREMENT,
src VARCHAR(128) NOT NULL,
module_id TEXT,
FOREIGN KEY (module_id) REFERENCES module(id) ON DELETE CASCADE
);
CREATE TABLE IF NOT EXISTS language (
id INTEGER PRIMARY KEY AUTOINCREMENT,
lang VARCHAR(128) NOT NULL,
name VARCHAR(128) NOT NULL,
path VARCHAR(128) NOT NULL,
module_id TEXT,
FOREIGN KEY (module_id) REFERENCES module(id) ON DELETE CASCADE
);
CREATE TABLE IF NOT EXISTS pack (
id TEXT PRIMARY KEY,
name VARCHAR(128) NOT NULL,
label VARCHAR(128) NOT NULL,
banner VARCHAR(128) NOT NULL,
path VARCHAR(128) NOT NULL,
type VARCHAR(128) NOT NULL,
system VARCHAR(128) NOT NULL,
package_type VARCHAR(128) NOT NULL,
package_name VARCHAR(128) NOT NULL,
module_id TEXT,
FOREIGN KEY (module_id) REFERENCES module(id) ON DELETE CASCADE
);
CREATE TABLE IF NOT EXISTS ownership (
id INTEGER PRIMARY KEY AUTOINCREMENT,
player VARCHAR(128) NOT NULL,
trusted VARCHAR(128) NOT NULL,
assistant VARCHAR(128) NOT NULL,
pack_id TEXT UNIQUE,
FOREIGN KEY (pack_id) REFERENCES pack(id) ON DELETE CASCADE
);
CREATE TABLE IF NOT EXISTS index_ (
id TEXT PRIMARY KEY,
folder VARCHAR(128) NOT NULL,
img VARCHAR(128) NOT NULL,
name VARCHAR(128) NOT NULL,
type VARCHAR(128) NOT NULL,
pack_id TEXT,
FOREIGN KEY (pack_id) REFERENCES pack(id) ON DELETE CASCADE
);
CREATE TABLE IF NOT EXISTS pack_folder (
id TEXT PRIMARY KEY,
description VARCHAR(128) NOT NULL,
name VARCHAR(128) NOT NULL,
sorting VARCHAR(128) NOT NULL,
type VARCHAR(128) NOT NULL,
sort INTEGER NOT NULL,
pack_id TEXT,
FOREIGN KEY (pack_id) REFERENCES pack(id) ON DELETE CASCADE
);
CREATE TABLE IF NOT EXISTS folder (
id INTEGER PRIMARY KEY AUTOINCREMENT,
name VARCHAR(128) NOT NULL,
sorting VARCHAR(128) NOT NULL,
color VARCHAR(128) NOT NULL,
folder_id INTEGER,
FOREIGN KEY (folder_id) REFERENCES folder(id) ON DELETE CASCADE,
module_id TEXT,
FOREIGN KEY (module_id) REFERENCES module(id) ON DELETE CASCADE
);
CREATE TABLE IF NOT EXISTS folder_packs (
id INTEGER PRIMARY KEY AUTOINCREMENT,
packs VARCHAR(128) NOT NULL,
folder_id INTEGER,
FOREIGN KEY (folder_id) REFERENCES folder(id) ON DELETE CASCADE
);
CREATE TABLE IF NOT EXISTS news (
id INTEGER PRIMARY KEY AUTOINCREMENT,
title VARCHAR(64) NOT NULL,
caption VARCHAR(64) NOT NULL,
url VARCHAR(64) NOT NULL,
image VARCHAR(64) NOT NULL,
setup_id INTEGER,
FOREIGN KEY (setup_id) REFERENCES setup(id) ON DELETE CASCADE
);
CREATE TABLE IF NOT EXISTS package_warnings (
id TEXT PRIMARY KEY,
key_ VARCHAR(128) NOT NULL,
setup_id INTEGER,
FOREIGN KEY (setup_id) REFERENCES setup(id) ON DELETE CASCADE
);
CREATE TABLE IF NOT EXISTS package_warnings_data (
id TEXT PRIMARY KEY,
type VARCHAR(128) NOT NULL,
manifest VARCHAR(128) NOT NULL,
reinstallable BOOLEAN NOT NULL,
package_warnings_id TEXT,
FOREIGN KEY (package_warnings_id) REFERENCES package_warnings(id) ON DELETE CASCADE
);
CREATE TABLE IF NOT EXISTS package_warnings_data_warning (
id INTEGER PRIMARY KEY,
value VARCHAR(128) NOT NULL,
package_warnings_data_id TEXT,
FOREIGN KEY (package_warnings_data_id) REFERENCES package_warnings_data(id) ON DELETE CASCADE
);
CREATE TABLE IF NOT EXISTS package_warnings_data_error (
id INTEGER PRIMARY KEY,
value VARCHAR(128) NOT NULL,
package_warnings_data_id TEXT,
FOREIGN KEY (package_warnings_data_id) REFERENCES package_warnings_data(id) ON DELETE CASCADE
);
CREATE TABLE IF NOT EXISTS system (
id TEXT PRIMARY KEY,
title VARCHAR(128) NOT NULL,
description VARCHAR(128) NOT NULL,
url VARCHAR(128) NOT NULL,
license VARCHAR(128) NOT NULL,
bugs VARCHAR(128) NOT NULL,
changelog VARCHAR(128) NOT NULL,
version VARCHAR(128) NOT NULL,
manifest VARCHAR(128) NOT NULL,
download VARCHAR(128) NOT NULL,
background VARCHAR(128) NOT NULL DEFAULT FALSE,
primary_token_attribute VARCHAR(128) NOT NULL DEFAULT FALSE,
availability INTEGER NOT NULL DEFAULT FALSE,
socket BOOLEAN NOT NULL DEFAULT FALSE,
protected BOOLEAN NOT NULL DEFAULT FALSE,
exclusive_ BOOLEAN NOT NULL DEFAULT FALSE,
persistent_storage BOOLEAN NOT NULL DEFAULT FALSE,
locked BOOLEAN NOT NULL DEFAULT FALSE,
owned BOOLEAN NOT NULL DEFAULT FALSE,
has_storage BOOLEAN NOT NULL DEFAULT FALSE,
setup_id INTEGER,
FOREIGN KEY (setup_id) REFERENCES setup(id) ON DELETE CASCADE
);
ALTER TABLE compatibility ADD COLUMN system_id TEXT UNIQUE REFERENCES system(id);
ALTER TABLE relationships ADD COLUMN system_id TEXT UNIQUE REFERENCES system(id);
ALTER TABLE document_types ADD COLUMN system_id TEXT UNIQUE REFERENCES system(id);
CREATE TABLE IF NOT EXISTS grid (
id INTEGER PRIMARY KEY AUTOINCREMENT,
type INTEGER NOT NULL,
size INTEGER NOT NULL,
distance INTEGER NOT NULL,
diagonals INTEGER NOT NULL,
thickness INTEGER NOT NULL,
alpha REAL NOT NULL,
color VARCHAR(128) NOT NULL,
units VARCHAR(128) NOT NULL,
style VARCHAR(128) NOT NULL,
system_id TEXT UNIQUE,
FOREIGN KEY (system_id) REFERENCES system(id) ON DELETE CASCADE
);
ALTER TABLE es_modules ADD COLUMN system_id TEXT REFERENCES system(id);
ALTER TABLE scripts ADD COLUMN system_id TEXT REFERENCES system(id);
ALTER TABLE tags ADD COLUMN system_id TEXT REFERENCES system(id);
ALTER TABLE author ADD COLUMN system_id TEXT REFERENCES system(id);
ALTER TABLE media ADD COLUMN system_id TEXT REFERENCES system(id);
ALTER TABLE pack ADD COLUMN system_id TEXT REFERENCES system(id);
ALTER TABLE style ADD COLUMN system_id TEXT REFERENCES system(id);
ALTER TABLE language ADD COLUMN system_id TEXT REFERENCES system(id);
ALTER TABLE folder ADD COLUMN system_id TEXT REFERENCES system(id);
CREATE TABLE IF NOT EXISTS world (
id TEXT PRIMARY KEY,
title VARCHAR(128) NOT NULL,
description VARCHAR(128) NOT NULL,
version VARCHAR(128) NOT NULL,
system VARCHAR(128) NOT NULL,
background VARCHAR(128) NOT NULL,
join_theme VARCHAR(128) NOT NULL,
core_version VARCHAR(128) NOT NULL,
system_version VARCHAR(128) NOT NULL,
last_played VARCHAR(128) NOT NULL,
playtime INTEGER NOT NULL,
availability INTEGER NOT NULL,
next_session DATETIME NOT NULL,
socket BOOLEAN NOT NULL DEFAULT FALSE,
protected BOOLEAN NOT NULL DEFAULT FALSE,
exclusive_ BOOLEAN NOT NULL DEFAULT FALSE,
persistent_storage BOOLEAN NOT NULL DEFAULT FALSE,
locked BOOLEAN NOT NULL DEFAULT FALSE,
owned BOOLEAN NOT NULL DEFAULT FALSE,
has_storage BOOLEAN NOT NULL DEFAULT FALSE,
setup_id INTEGER,
FOREIGN KEY (setup_id) REFERENCES setup(id) ON DELETE CASCADE
);
ALTER TABLE compatibility ADD COLUMN world_id TEXT UNIQUE REFERENCES world(id);
ALTER TABLE relationships ADD COLUMN world_id TEXT UNIQUE REFERENCES world(id);
ALTER TABLE tags ADD COLUMN world_id TEXT REFERENCES world(id);
ALTER TABLE scripts ADD COLUMN world_id TEXT REFERENCES world(id);
ALTER TABLE es_modules ADD COLUMN world_id TEXT REFERENCES world(id);
ALTER TABLE author ADD COLUMN world_id TEXT REFERENCES world(id);
ALTER TABLE media ADD COLUMN world_id TEXT REFERENCES world(id);
ALTER TABLE style ADD COLUMN world_id TEXT REFERENCES world(id);
ALTER TABLE language ADD COLUMN world_id TEXT REFERENCES world(id);
ALTER TABLE pack ADD COLUMN world_id TEXT REFERENCES world(id);
ALTER TABLE folder ADD COLUMN world_id TEXT REFERENCES world(id);

View File

@@ -1,12 +1,3 @@
CREATE TABLE IF NOT EXISTS setup (
id INTEGER PRIMARY KEY AUTOINCREMENT,
is_admin BOOLEAN NOT NULL DEFAULT FALSE,
is_setup BOOLEAN NOT NULL DEFAULT TRUE,
created_at DATETIME NOT NULL DEFAULT current_timestamp
);
CREATE TABLE IF NOT EXISTS game ( CREATE TABLE IF NOT EXISTS game (
id INTEGER PRIMARY KEY AUTOINCREMENT id INTEGER PRIMARY KEY AUTOINCREMENT
@@ -18,96 +9,6 @@ CREATE TABLE IF NOT EXISTS game (
created_at DATETIME NOT NULL DEFAULT current_timestamp created_at DATETIME NOT NULL DEFAULT current_timestamp
); );
CREATE TABLE IF NOT EXISTS world (
id TEXT PRIMARY KEY,
socket BOOLEAN NOT NULL DEFAULT FALSE,
protected BOOLEAN NOT NULL DEFAULT FALSE,
exclusive_ BOOLEAN NOT NULL DEFAULT FALSE,
persistent_storage BOOLEAN NOT NULL DEFAULT FALSE,
locked BOOLEAN NOT NULL DEFAULT FALSE,
owned BOOLEAN NOT NULL DEFAULT FALSE,
has_storage BOOLEAN NOT NULL DEFAULT FALSE,
playtime INTEGER NOT NULL,
availability INTEGER NOT NULL,
next_session DATETIME NOT NULL,
title VARCHAR(128) NOT NULL,
description VARCHAR(128) NOT NULL,
version VARCHAR(128) NOT NULL,
system VARCHAR(128) NOT NULL,
background VARCHAR(128) NOT NULL,
join_theme VARCHAR(128) NOT NULL,
core_version VARCHAR(128) NOT NULL,
system_version VARCHAR(128) NOT NULL,
last_played VARCHAR(128) NOT NULL,
setup_id INTEGER,
FOREIGN KEY (setup_id) REFERENCES setup(id) ON DELETE CASCADE
game_id INTEGER UNIQUE,
FOREIGN KEY (game_id) REFERENCES game(id) ON DELETE CASCADE
);
CREATE TABLE IF NOT EXISTS system (
id TEXT PRIMARY KEY,
title VARCHAR(128) NOT NULL,
description VARCHAR(128) NOT NULL,
url VARCHAR(128) NOT NULL,
license VARCHAR(128) NOT NULL,
bugs VARCHAR(128) NOT NULL,
changelog VARCHAR(128) NOT NULL,
version VARCHAR(128) NOT NULL,
socket BOOLEAN NOT NULL DEFAULT FALSE,
manifest VARCHAR(128) NOT NULL,
download VARCHAR(128) NOT NULL,
protected BOOLEAN NOT NULL DEFAULT FALSE,
exclusive_ BOOLEAN NOT NULL DEFAULT FALSE,
persistent_storage BOOLEAN NOT NULL DEFAULT FALSE,
background VARCHAR(128) NOT NULL DEFAULT FALSE,
primary_token_attribute VARCHAR(128) NOT NULL DEFAULT FALSE,
availability INTEGER NOT NULL DEFAULT FALSE,
locked BOOLEAN NOT NULL DEFAULT FALSE,
owned BOOLEAN NOT NULL DEFAULT FALSE,
has_storage BOOLEAN NOT NULL DEFAULT FALSE,
setup_id INTEGER,
FOREIGN KEY (setup_id) REFERENCES setup(id) ON DELETE CASCADE
game_id INTEGER UNIQUE,
FOREIGN KEY (game_id) REFERENCES game(id) ON DELETE CASCADE
);
CREATE TABLE IF NOT EXISTS module (
id TEXT PRIMARY KEY,
title VARCHAR(128) NOT NULL,
description VARCHAR(128) NOT NULL,
url VARCHAR(128) NOT NULL,
license VARCHAR(128) NOT NULL,
readme VARCHAR(128) NOT NULL,
bugs VARCHAR(128) NOT NULL,
changelog VARCHAR(128) NOT NULL,
version VARCHAR(128) NOT NULL,
socket BOOLEAN NOT NULL DEFAULT FALSE,
manifest VARCHAR(128) NOT NULL,
download VARCHAR(128) NOT NULL,
protected BOOLEAN NOT NULL DEFAULT FALSE,
exclusive_ BOOLEAN NOT NULL DEFAULT FALSE,
persistent_storage BOOLEAN NOT NULL DEFAULT FALSE,
core_translation BOOLEAN NOT NULL DEFAULT FALSE,
library BOOLEAN NOT NULL DEFAULT FALSE,
availability INTEGER NOT NULL DEFAULT FALSE,
locked BOOLEAN NOT NULL DEFAULT FALSE,
owned BOOLEAN NOT NULL DEFAULT FALSE,
has_storage BOOLEAN NOT NULL DEFAULT FALSE,
active BOOLEAN NOT NULL DEFAULT FALSE,
setup_id INTEGER,
FOREIGN KEY (setup_id) REFERENCES setup(id) ON DELETE CASCADE
game_id INTEGER,
FOREIGN KEY (game_id) REFERENCES game(id) ON DELETE CASCADE
);
CREATE TABLE IF NOT EXISTS addresses ( CREATE TABLE IF NOT EXISTS addresses (
id INTEGER PRIMARY KEY AUTOINCREMENT, id INTEGER PRIMARY KEY AUTOINCREMENT,
@@ -119,29 +20,6 @@ CREATE TABLE IF NOT EXISTS addresses (
FOREIGN KEY (game_id) REFERENCES game(id) ON DELETE CASCADE FOREIGN KEY (game_id) REFERENCES game(id) ON DELETE CASCADE
); );
CREATE TABLE IF NOT EXISTS setup_options (
id INTEGER PRIMARY KEY AUTOINCREMENT,
compress_socket BOOLEAN NOT NULL DEFAULT FALSE,
compress_static BOOLEAN NOT NULL DEFAULT FALSE,
css_theme VARCHAR(128) NOT NULL,
data_path VARCHAR(128) NOT NULL,
fullscreen BOOLEAN NOT NULL DEFAULT FALSE,
hostname VARCHAR(128) NOT NULL,
hot_reload BOOLEAN NOT NULL DEFAULT FALSE,
language VARCHAR(128) NOT NULL,
local_hostname VARCHAR(128) NOT NULL,
port INTEGER NOT NULL,
proxy_ssl BOOLEAN NOT NULL,
telemetry BOOLEAN NOT NULL,
update_channel VARCHAR(128) NOT NULL,
upnp BOOLEAN NOT NULL,
delete_nedb BOOLEAN NOT NULL,
no_backups BOOLEAN NOT NULL,
setup_id INTEGER UNIQUE,
FOREIGN KEY (setup_id) REFERENCES setup(id) ON DELETE CASCADE
);
CREATE TABLE IF NOT EXISTS game_options ( CREATE TABLE IF NOT EXISTS game_options (
id INTEGER PRIMARY KEY, id INTEGER PRIMARY KEY,
@@ -483,51 +361,9 @@ CREATE TABLE IF NOT EXISTS active_users (
FOREIGN KEY (game_id) REFERENCES game(id) ON DELETE CASCADE FOREIGN KEY (game_id) REFERENCES game(id) ON DELETE CASCADE
); );
CREATE TABLE IF NOT EXISTS grid (
id INTEGER PRIMARY KEY AUTOINCREMENT,
type INTEGER NOT NULL,
size INTEGER NOT NULL,
distance INTEGER NOT NULL,
diagonals INTEGER NOT NULL,
thickness INTEGER NOT NULL,
alpha REAL NOT NULL,
color VARCHAR(128) NOT NULL,
units VARCHAR(128) NOT NULL,
style VARCHAR(128) NOT NULL,
system_id TEXT UNIQUE,
FOREIGN KEY (system_id) REFERENCES system(id) ON DELETE CASCADE
);
CREATE TABLE IF NOT EXISTS relationships (
id INTEGER PRIMARY KEY AUTOINCREMENT,
module_id TEXT UNIQUE,
FOREIGN KEY (module_id) REFERENCES module(id) ON DELETE CASCADE,
system_id TEXT UNIQUE,
FOREIGN KEY (system_id) REFERENCES system(id) ON DELETE CASCADE,
world_id TEXT UNIQUE,
FOREIGN KEY (world_id) REFERENCES world(id) ON DELETE CASCADE
);
CREATE TABLE IF NOT EXISTS release_ (
id INTEGER PRIMARY KEY AUTOINCREMENT,
generation INTEGER NOT NULL,
channel VARCHAR(128) NOT NULL,
suffix VARCHAR(128) NOT NULL,
build INTEGER NOT NULL,
node_version INTEGER NOT NULL,
max_generation INTEGER NOT NULL,
max_stable_generation INTEGER NOT NULL,
time INTEGER NOT NULL,
setup_id INTEGER UNIQUE,
FOREIGN KEY (setup_id) REFERENCES setup(id) ON DELETE CASCADE,
game_id INTEGER UNIQUE,
FOREIGN KEY (game_id) REFERENCES game(id) ON DELETE CASCADE
);
CREATE TABLE IF NOT EXISTS item ( CREATE TABLE IF NOT EXISTS item (
id TEXT PRIMARY KEY, id TEXT PRIMARY KEY,
@@ -554,158 +390,6 @@ CREATE TABLE IF NOT EXISTS journal (
FOREIGN KEY (game_id) REFERENCES game(id) ON DELETE CASCADE FOREIGN KEY (game_id) REFERENCES game(id) ON DELETE CASCADE
); );
CREATE TABLE IF NOT EXISTS relationships_data (
id TEXT PRIMARY KEY,
relationships_type VARCHAR(32) NOT NULL,
type TEXT NOT NULL,
manifest TEXT NOT NULL,
relationships_id INTEGER UNIQUE,
FOREIGN KEY (relationships_id) REFERENCES relationships(id) ON DELETE CASCADE
);
CREATE TABLE IF NOT EXISTS compatibility (
id INTEGER PRIMARY KEY AUTOINCREMENT,
minimum VARCHAR(64) NOT NULL,
verified VARCHAR(64) NOT NULL,
maximum VARCHAR(64) NOT NULL,
module_id TEXT UNIQUE,
FOREIGN KEY (module_id) REFERENCES module(id) ON DELETE CASCADE,
system_id TEXT UNIQUE,
FOREIGN KEY (system_id) REFERENCES system(id) ON DELETE CASCADE,
world_id TEXT UNIQUE,
FOREIGN KEY (world_id) REFERENCES world(id) ON DELETE CASCADE,
relationships_data_id TEXT UNIQUE,
FOREIGN KEY (relationships_data_id) REFERENCES relationships_data(id) ON DELETE CASCADE
);
CREATE TABLE IF NOT EXISTS author (
id INTEGER PRIMARY KEY AUTOINCREMENT,
name VARCHAR(128) NOT NULL,
url VARCHAR(128) NOT NULL,
email VARCHAR(128) NOT NULL,
discord VARCHAR(128) NOT NULL,
module_id TEXT,
FOREIGN KEY (module_id) REFERENCES module(id) ON DELETE CASCADE,
system_id TEXT,
FOREIGN KEY (system_id) REFERENCES system(id) ON DELETE CASCADE,
world_id TEXT,
FOREIGN KEY (world_id) REFERENCES world(id) ON DELETE CASCADE
);
CREATE TABLE IF NOT EXISTS media (
id INTEGER PRIMARY KEY AUTOINCREMENT,
type VARCHAR(128) NOT NULL,
url VARCHAR(128) NOT NULL,
caption VARCHAR(128) NOT NULL,
module_id TEXT,
FOREIGN KEY (module_id) REFERENCES module(id) ON DELETE CASCADE,
system_id TEXT,
FOREIGN KEY (system_id) REFERENCES system(id) ON DELETE CASCADE,
world_id TEXT,
FOREIGN KEY (world_id) REFERENCES world(id) ON DELETE CASCADE
);
CREATE TABLE IF NOT EXISTS scripts (
id INTEGER PRIMARY KEY AUTOINCREMENT,
scripts TEXT NOT NULL,
module_id TEXT,
FOREIGN KEY (module_id) REFERENCES module(id) ON DELETE CASCADE,
system_id INTEGER,
FOREIGN KEY (system_id) REFERENCES system(id) ON DELETE CASCADE,
world_id TEXT,
FOREIGN KEY (world_id) REFERENCES world(id) ON DELETE CASCADE
);
CREATE TABLE IF NOT EXISTS es_modules (
id INTEGER PRIMARY KEY AUTOINCREMENT,
es_modules TEXT NOT NULL,
module_id TEXT,
FOREIGN KEY (module_id) REFERENCES module(id) ON DELETE CASCADE,
system_id TEXT,
FOREIGN KEY (system_id) REFERENCES system(id) ON DELETE CASCADE,
world_id TEXT,
FOREIGN KEY (world_id) REFERENCES world(id) ON DELETE CASCADE
);
CREATE TABLE IF NOT EXISTS style (
id INTEGER PRIMARY KEY AUTOINCREMENT,
src VARCHAR(128) NOT NULL,
module_id TEXT,
FOREIGN KEY (module_id) REFERENCES module(id) ON DELETE CASCADE,
system_id TEXT,
FOREIGN KEY (system_id) REFERENCES system(id) ON DELETE CASCADE,
world_id TEXT,
FOREIGN KEY (world_id) REFERENCES world(id) ON DELETE CASCADE
);
CREATE TABLE IF NOT EXISTS language (
id INTEGER PRIMARY KEY AUTOINCREMENT,
lang VARCHAR(128) NOT NULL,
name VARCHAR(128) NOT NULL,
path VARCHAR(128) NOT NULL,
module_id TEXT,
FOREIGN KEY (module_id) REFERENCES module(id) ON DELETE CASCADE,
system_id TEXT,
FOREIGN KEY (system_id) REFERENCES system(id) ON DELETE CASCADE,
world_id TEXT,
FOREIGN KEY (world_id) REFERENCES world(id) ON DELETE CASCADE
);
CREATE TABLE IF NOT EXISTS package_warnings (
id TEXT PRIMARY KEY,
key_ VARCHAR(128) NOT NULL,
setup_id INTEGER,
FOREIGN KEY (setup_id) REFERENCES setup(id) ON DELETE CASCADE,
game_id INTEGER,
FOREIGN KEY (game_id) REFERENCES game(id) ON DELETE CASCADE,
);
CREATE TABLE IF NOT EXISTS package_warnings_data (
id TEXT PRIMARY KEY,
type VARCHAR(128) NOT NULL,
reinstallable VARCHAR(128) NOT NULL,
manifest VARCHAR(128) NOT NULL,
package_warnings_id TEXT,
FOREIGN KEY (package_warnings_id) REFERENCES package_warnings(id) ON DELETE CASCADE
);
CREATE TABLE IF NOT EXISTS package_warnings_data_warning (
id TEXT PRIMARY KEY,
warning VARCHAR(128) NOT NULL,
package_warnings_data_id TEXT,
FOREIGN KEY (package_warnings_data_id) REFERENCES package_warnings_data(id) ON DELETE CASCADE
);
CREATE TABLE IF NOT EXISTS package_warnings_data_error (
id TEXT PRIMARY KEY,
error VARCHAR(128) NOT NULL,
package_warnings_data_id TEXT,
FOREIGN KEY (package_warnings_data_id) REFERENCES package_warnings_data(id) ON DELETE CASCADE
);
CREATE TABLE IF NOT EXISTS world_folder ( CREATE TABLE IF NOT EXISTS world_folder (
id TEXT PRIMARY KEY, id TEXT PRIMARY KEY,
@@ -909,28 +593,6 @@ CREATE TABLE IF NOT EXISTS message_rolls (
FOREIGN KEY (message_id) REFERENCES message(id) ON DELETE CASCADE FOREIGN KEY (message_id) REFERENCES message(id) ON DELETE CASCADE
); );
CREATE TABLE IF NOT EXISTS pack (
id TEXT PRIMARY KEY,
name VARCHAR(128) NOT NULL,
label VARCHAR(128) NOT NULL,
banner VARCHAR(128) NOT NULL,
path VARCHAR(128) NOT NULL,
type VARCHAR(128) NOT NULL,
system VARCHAR(128) NOT NULL,
package_type VARCHAR(128) NOT NULL,
package_name VARCHAR(128) NOT NULL,
game_id INTEGER,
FOREIGN KEY (game_id) REFERENCES game(id) ON DELETE CASCADE,
module_id TEXT,
FOREIGN KEY (module_id) REFERENCES module(id) ON DELETE CASCADE,
system_id TEXT,
FOREIGN KEY (system_id) REFERENCES system(id) ON DELETE CASCADE,
world_id TEXT,
FOREIGN KEY (world_id) REFERENCES world(id) ON DELETE CASCADE
);
CREATE TABLE IF NOT EXISTS journal_page ( CREATE TABLE IF NOT EXISTS journal_page (
id TEXT PRIMARY KEY, id TEXT PRIMARY KEY,
@@ -974,19 +636,6 @@ CREATE TABLE IF NOT EXISTS journal_page_video (
FOREIGN KEY (journal_page_id) REFERENCES journal_page(id) ON DELETE CASCADE FOREIGN KEY (journal_page_id) REFERENCES journal_page(id) ON DELETE CASCADE
); );
CREATE TABLE IF NOT EXISTS ownership (
id INTEGER PRIMARY KEY AUTOINCREMENT,
player VARCHAR(128) NOT NULL,
trusted VARCHAR(128) NOT NULL,
assistant VARCHAR(128) NOT NULL,
pack_id TEXT UNIQUE,
FOREIGN KEY (pack_id) REFERENCES pack(id) ON DELETE CASCADE,
card_deck_id TEXT UNIQUE,
FOREIGN KEY (card_deck_id) REFERENCES card_deck(id) ON DELETE CASCADE
);
CREATE TABLE IF NOT EXISTS ownership_string ( CREATE TABLE IF NOT EXISTS ownership_string (
id INTEGER PRIMARY KEY AUTOINCREMENT, id INTEGER PRIMARY KEY AUTOINCREMENT,
@@ -1006,96 +655,6 @@ CREATE TABLE IF NOT EXISTS ownership_string (
); );
CREATE TABLE IF NOT EXISTS index_ (
id TEXT PRIMARY KEY,
folder VARCHAR(128) NOT NULL,
img VARCHAR(128) NOT NULL,
name VARCHAR(128) NOT NULL,
type VARCHAR(128) NOT NULL,
pack_id TEXT,
FOREIGN KEY (pack_id) REFERENCES pack(id) ON DELETE CASCADE
);
CREATE TABLE IF NOT EXISTS pack_folder (
id TEXT PRIMARY KEY,
description VARCHAR(128) NOT NULL,
name VARCHAR(128) NOT NULL,
sort INTEGER NOT NULL,
sorting VARCHAR(128) NOT NULL,
type VARCHAR(128) NOT NULL,
pack_id TEXT,
FOREIGN KEY (pack_id) REFERENCES pack(id) ON DELETE CASCADE
);
CREATE TABLE IF NOT EXISTS folder (
id INTEGER PRIMARY KEY AUTOINCREMENT,
name VARCHAR(128) NOT NULL,
sorting VARCHAR(128) NOT NULL,
color VARCHAR(128) NOT NULL,
folder_id INTEGER,
FOREIGN KEY (folder_id) REFERENCES folder(id) ON DELETE CASCADE,
module_id TEXT,
FOREIGN KEY (module_id) REFERENCES module(id) ON DELETE CASCADE,
system_id TEXT,
FOREIGN KEY (system_id) REFERENCES system(id) ON DELETE CASCADE,
world_id TEXT,
FOREIGN KEY (world_id) REFERENCES world(id) ON DELETE CASCADE
);
CREATE TABLE IF NOT EXISTS folder_packs (
id INTEGER PRIMARY KEY AUTOINCREMENT,
packs VARCHAR(128) NOT NULL,
folder_id INTEGER,
FOREIGN KEY (folder_id) REFERENCES folder(id) ON DELETE CASCADE
);
CREATE TABLE IF NOT EXISTS tags (
id INTEGER PRIMARY KEY AUTOINCREMENT,
tags VARCHAR(128) NOT NULL,
module_id TEXT,
FOREIGN KEY (module_id) REFERENCES module(id) ON DELETE CASCADE
system_id TEXT,
FOREIGN KEY (system_id) REFERENCES system(id) ON DELETE CASCADE
world_id TEXT,
FOREIGN KEY (world_id) REFERENCES world(id) ON DELETE CASCADE
);
CREATE TABLE IF NOT EXISTS document_types (
id INTEGER PRIMARY KEY AUTOINCREMENT,
module_id TEXT UNIQUE,
FOREIGN KEY (module_id) REFERENCES module(id) ON DELETE CASCADE
system_id TEXT UNIQUE,
FOREIGN KEY (system_id) REFERENCES system(id) ON DELETE CASCADE
);
CREATE TABLE IF NOT EXISTS document_types_data (
id INTEGER PRIMARY KEY AUTOINCREMENT,
type VARCHAR(64) NOT NULL,
document_types_id INTEGER,
FOREIGN KEY (document_types_id) REFERENCES document_types(id) ON DELETE CASCADE
);
CREATE TABLE IF NOT EXISTS document_types_data_html (
id INTEGER PRIMARY KEY AUTOINCREMENT,
html_fields TEXT NOT NULL,
document_types_data_id INTEGER,
FOREIGN KEY (document_types_data_id) REFERENCES document_types_data(id) ON DELETE CASCADE
);
CREATE TABLE IF NOT EXISTS system_update ( CREATE TABLE IF NOT EXISTS system_update (
id INTEGER PRIMARY KEY AUTOINCREMENT, id INTEGER PRIMARY KEY AUTOINCREMENT,
@@ -1106,107 +665,3 @@ CREATE TABLE IF NOT EXISTS system_update (
game_id INTEGER UNIQUE, game_id INTEGER UNIQUE,
FOREIGN KEY (game_id) REFERENCES game(id) ON DELETE CASCADE FOREIGN KEY (game_id) REFERENCES game(id) ON DELETE CASCADE
); );
CREATE TABLE IF NOT EXISTS core_update (
id INTEGER PRIMARY KEY AUTOINCREMENT,
has_update BOOLEAN NOT NULL DEFAULT FALSE,
can_update BOOLEAN NOT NULL DEFAULT FALSE,
could_reach_website BOOLEAN NOT NULL DEFAULT FALSE,
slow_response BOOLEAN NOT NULL DEFAULT FALSE,
version VARCHAR(64) NOT NULL,
channel VARCHAR(64) NOT NULL,
will_disable_modules BOOLEAN NOT NULL DEFAULT FALSE,
setup_id INTEGER UNIQUE,
game_id INTEGER UNIQUE,
FOREIGN KEY (setup_id) REFERENCES setup(id) ON DELETE CASCADE,
FOREIGN KEY (game_id) REFERENCES game(id) ON DELETE CASCADE,
CONSTRAINT one_parent_only CHECK (
(setup_id IS NOT NULL AND game_id IS NULL) OR
(setup_id IS NULL AND game_id IS NOT NULL)
)
);
CREATE TABLE IF NOT EXISTS featured_content (
id INTEGER PRIMARY KEY AUTOINCREMENT,
title VARCHAR(128) NOT NULL,
caption VARCHAR(128) NOT NULL,
url VARCHAR(128) NOT NULL,
image VARCHAR(128) NOT NULL,
setup_id INTEGER UNIQUE,
FOREIGN KEY (setup_id) REFERENCES setup(id) ON DELETE CASCADE
);
CREATE TABLE IF NOT EXISTS news (
id INTEGER PRIMARY KEY AUTOINCREMENT,
title VARCHAR(64) NOT NULL,
caption VARCHAR(64) NOT NULL,
url VARCHAR(64) NOT NULL,
image VARCHAR(64) NOT NULL,
setup_id INTEGER,
FOREIGN KEY (setup_id) REFERENCES setup(id) ON DELETE CASCADE
);
CREATE TABLE IF NOT EXISTS files (
id INTEGER PRIMARY KEY AUTOINCREMENT,
setup_id INTEGER UNIQUE,
game_id INTEGER UNIQUE,
FOREIGN KEY (setup_id) REFERENCES setup(id) ON DELETE CASCADE,
FOREIGN KEY (game_id) REFERENCES game(id) ON DELETE CASCADE,
CONSTRAINT one_parent_only CHECK (
(setup_id IS NOT NULL AND game_id IS NULL) OR
(setup_id IS NULL AND game_id IS NOT NULL)
)
);
CREATE TABLE IF NOT EXISTS files_storage (
id INTEGER PRIMARY KEY AUTOINCREMENT,
storage TEXT NOT NULL,
files_id INTEGER,
FOREIGN KEY (files_id) REFERENCES files(id) ON DELETE CASCADE
);
CREATE TABLE IF NOT EXISTS setup_language (
id TEXT PRIMARY KEY,
label VARCHAR(128) NOT NULL,
setup_id INTEGER,
FOREIGN KEY (setup_id) REFERENCES setup(id) ON DELETE CASCADE
);
CREATE TABLE IF NOT EXISTS setup_language_module (
id TEXT PRIMARY KEY,
label VARCHAR(128) NOT NULL,
path VARCHAR(128) NOT NULL,
setup_language_id TEXT,
FOREIGN KEY (setup_language_id) REFERENCES setup_language(id) ON DELETE CASCADE
);
CREATE TABLE IF NOT EXISTS language (
id INTEGER PRIMARY KEY AUTOINCREMENT,
lang VARCHAR(128) NOT NULL,
name VARCHAR(128) NOT NULL,
path VARCHAR(128) NOT NULL,
module_id TEXT,
FOREIGN KEY (module_id) REFERENCES module(id) ON DELETE CASCADE,
system_id INTEGER,
FOREIGN KEY (system_id) REFERENCES system(id) ON DELETE CASCADE,
world_id INTEGER,
FOREIGN KEY (world_id) REFERENCES world(id) ON DELETE CASCADE
);

View File

@@ -1,32 +0,0 @@
CREATE TABLE IF NOT EXISTS modules (
id INTEGER PRIMARY KEY AUTOINCREMENT,
state_id INTEGER NOT NULL,
text_id VARCHAR(256) NOT NULL,
title VARCHAR(256) NOT NULL,
description TEXT NOT NULL,
url VARCHAR(256) NOT NULL,
version VARCHAR(64) NOT NULL,
availability INTEGER NOT NULL,
created_at DATETIME NOT NULL DEFAULT current_timestamp,
FOREIGN KEY (state_id) REFERENCES foundry_state(id) ON DELETE CASCADE
);
CREATE TABLE IF NOT EXISTS modules_compatibility (
id INTEGER PRIMARY KEY AUTOINCREMENT,
module_id INTEGER UNIQUE,
minimum VARCHAR(64) NOT NULL,
verified VARCHAR(64) NOT NULL,
maximum VARCHAR(64) NOT NULL,
FOREIGN KEY (module_id) REFERENCES modules(id) ON DELETE CASCADE
);
CREATE TABLE IF NOT EXISTS modules_languages (
id INTEGER PRIMARY KEY AUTOINCREMENT,
module_id INTEGER,
language VARCHAR(256) NOT NULL,
name VARCHAR(256) NOT NULL,
path VARCHAR(256) NOT NULL,
FOREIGN KEY (module_id) REFERENCES modules(id) ON DELETE CASCADE
);

View File

@@ -1,2 +0,0 @@
DROP TABLE IF EXISTS systems_compatibility;
DROP TABLE IF EXISTS systems;

View File

@@ -1,21 +0,0 @@
CREATE TABLE IF NOT EXISTS systems (
id INTEGER PRIMARY KEY AUTOINCREMENT,
state_id INTEGER NOT NULL,
text_id VARCHAR(256) NOT NULL,
title VARCHAR(256) NOT NULL,
description TEXT NOT NULL,
url VARCHAR(256) NOT NULL,
download VARCHAR(256) NOT NULL,
created_at DATETIME NOT NULL DEFAULT current_timestamp,
FOREIGN KEY (state_id) REFERENCES foundry_state(id) ON DELETE CASCADE
);
CREATE TABLE IF NOT EXISTS systems_compatibility (
id INTEGER PRIMARY KEY AUTOINCREMENT,
system_id INTEGER UNIQUE,
minimum VARCHAR(64) NOT NULL,
verified VARCHAR(64) NOT NULL,
maximum VARCHAR(64) NOT NULL,
FOREIGN KEY (system_id) REFERENCES systems(id) ON DELETE CASCADE
);

View File

@@ -1,2 +0,0 @@
DROP TABLE IF EXISTS worlds_compatibility;
DROP TABLE IF EXISTS worlds;

View File

@@ -1,24 +0,0 @@
CREATE TABLE IF NOT EXISTS worlds (
id INTEGER PRIMARY KEY AUTOINCREMENT,
state_id INTEGER NOT NULL,
text_id VARCHAR(256) NOT NULL,
title VARCHAR(256) NOT NULL,
description TEXT NOT NULL,
system VARCHAR(256) NOT NULL,
core_version VARCHAR(256) NOT NULL,
system_version VARCHAR(256) NOT NULL,
playtime INTEGER NOT NULL,
next_session DATETIME NOT NULL,
created_at DATETIME NOT NULL DEFAULT current_timestamp,
FOREIGN KEY (state_id) REFERENCES foundry_state(id) ON DELETE CASCADE
);
CREATE TABLE IF NOT EXISTS worlds_compatibility (
id INTEGER PRIMARY KEY AUTOINCREMENT,
world_id INTEGER UNIQUE,
minimum VARCHAR(64) NOT NULL,
verified VARCHAR(64) NOT NULL,
maximum VARCHAR(64) NOT NULL,
FOREIGN KEY (world_id) REFERENCES worlds(id) ON DELETE CASCADE
);

View File

@@ -1,3 +0,0 @@
DROP TABLE IF EXISTS users;
DROP TABLE IF EXISTS users_hotbar;
DROP TABLE IF EXISTS users_stats;

View File

@@ -1,33 +0,0 @@
CREATE TABLE IF NOT EXISTS users (
id INTEGER PRIMARY KEY AUTOINCREMENT,
state_id INTEGER NOT NULL,
name VARCHAR(256) NOT NULL,
role INTEGER NOT NULL,
character VARCHAR(128) NOT NULL,
color VARCHAR(128) NOT NULL,
pronouns VARCHAR(128) NOT NULL,
created_at DATETIME NOT NULL DEFAULT current_timestamp,
FOREIGN KEY (state_id) REFERENCES foundry_state(id) ON DELETE CASCADE
);
CREATE TABLE IF NOT EXISTS users_hotbar (
id INTEGER PRIMARY KEY AUTOINCREMENT,
user_id INTEGER,
key TEXT NOT NULL,
value TEXT NOT NULL,
FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE CASCADE
);
CREATE TABLE IF NOT EXISTS users_stats (
id INTEGER PRIMARY KEY AUTOINCREMENT,
user_id INTEGER UNIQUE,
core_version TEXT NOT NULL,
system_id VARCHAR(64) NOT NULL,
system_version VARCHAR(64) NOT NULL,
created_time INTEGER NOT NULL,
modified_time INTEGER NOT NULL,
last_modified_by VARCHAR(256) NOT NULL,
FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE CASCADE
);

1
go.mod
View File

@@ -54,6 +54,7 @@ require (
github.com/in-toto/in-toto-golang v0.9.0 // indirect github.com/in-toto/in-toto-golang v0.9.0 // indirect
github.com/inconshreveable/mousetrap v1.1.0 // indirect github.com/inconshreveable/mousetrap v1.1.0 // indirect
github.com/inhies/go-bytesize v0.0.0-20220417184213-4913239db9cf // indirect github.com/inhies/go-bytesize v0.0.0-20220417184213-4913239db9cf // indirect
github.com/jmoiron/sqlx v1.4.0 // indirect
github.com/jonboulle/clockwork v0.5.0 // indirect github.com/jonboulle/clockwork v0.5.0 // indirect
github.com/julienschmidt/httprouter v1.3.0 // indirect github.com/julienschmidt/httprouter v1.3.0 // indirect
github.com/klauspost/compress v1.18.3 // indirect github.com/klauspost/compress v1.18.3 // indirect

6
go.sum
View File

@@ -1,5 +1,6 @@
cyphar.com/go-pathrs v0.2.1 h1:9nx1vOgwVvX1mNBWDu93+vaceedpbsDqo+XuBGL40b8= cyphar.com/go-pathrs v0.2.1 h1:9nx1vOgwVvX1mNBWDu93+vaceedpbsDqo+XuBGL40b8=
cyphar.com/go-pathrs v0.2.1/go.mod h1:y8f1EMG7r+hCuFf/rXsKqMJrJAUoADZGNh5/vZPKcGc= cyphar.com/go-pathrs v0.2.1/go.mod h1:y8f1EMG7r+hCuFf/rXsKqMJrJAUoADZGNh5/vZPKcGc=
filippo.io/edwards25519 v1.1.0/go.mod h1:BxyFTGdWcka3PhytdK4V28tE5sGfRvvvRV7EaN4VDT4=
github.com/AdaLogics/go-fuzz-headers v0.0.0-20240806141605-e8a1dd7889d6 h1:He8afgbRMd7mFxO99hRNu+6tazq8nFF9lIwo9JFroBk= github.com/AdaLogics/go-fuzz-headers v0.0.0-20240806141605-e8a1dd7889d6 h1:He8afgbRMd7mFxO99hRNu+6tazq8nFF9lIwo9JFroBk=
github.com/AdaLogics/go-fuzz-headers v0.0.0-20240806141605-e8a1dd7889d6/go.mod h1:8o94RPi1/7XTJvwPpRSzSUedZrtlirdB3r9Z20bi2f8= github.com/AdaLogics/go-fuzz-headers v0.0.0-20240806141605-e8a1dd7889d6/go.mod h1:8o94RPi1/7XTJvwPpRSzSUedZrtlirdB3r9Z20bi2f8=
github.com/Azure/go-ansiterm v0.0.0-20250102033503-faa5f7b0171c h1:udKWzYgxTojEKWjV8V+WSxDXJ4NFATAsZjh8iIbsQIg= github.com/Azure/go-ansiterm v0.0.0-20250102033503-faa5f7b0171c h1:udKWzYgxTojEKWjV8V+WSxDXJ4NFATAsZjh8iIbsQIg=
@@ -152,6 +153,7 @@ github.com/go-openapi/swag/yamlutils v0.25.3 h1:LKTJjCn/W1ZfMec0XDL4Vxh8kyAnv1or
github.com/go-openapi/swag/yamlutils v0.25.3/go.mod h1:Y7QN6Wc5DOBXK14/xeo1cQlq0EA0wvLoSv13gDQoCao= github.com/go-openapi/swag/yamlutils v0.25.3/go.mod h1:Y7QN6Wc5DOBXK14/xeo1cQlq0EA0wvLoSv13gDQoCao=
github.com/go-openapi/validate v0.25.1 h1:sSACUI6Jcnbo5IWqbYHgjibrhhmt3vR6lCzKZnmAgBw= github.com/go-openapi/validate v0.25.1 h1:sSACUI6Jcnbo5IWqbYHgjibrhhmt3vR6lCzKZnmAgBw=
github.com/go-openapi/validate v0.25.1/go.mod h1:RMVyVFYte0gbSTaZ0N4KmTn6u/kClvAFp+mAVfS/DQc= github.com/go-openapi/validate v0.25.1/go.mod h1:RMVyVFYte0gbSTaZ0N4KmTn6u/kClvAFp+mAVfS/DQc=
github.com/go-sql-driver/mysql v1.8.1/go.mod h1:wEBSXgmK//2ZFJyE+qWnIsVGmvmEKlqwuVSjsCm7DZg=
github.com/go-viper/mapstructure/v2 v2.5.0 h1:vM5IJoUAy3d7zRSVtIwQgBj7BiWtMPfmPEgAXnvj1Ro= github.com/go-viper/mapstructure/v2 v2.5.0 h1:vM5IJoUAy3d7zRSVtIwQgBj7BiWtMPfmPEgAXnvj1Ro=
github.com/go-viper/mapstructure/v2 v2.5.0/go.mod h1:oJDH3BJKyqBA2TXFhDsKDGDTlndYOZ6rGS0BRZIxGhM= github.com/go-viper/mapstructure/v2 v2.5.0/go.mod h1:oJDH3BJKyqBA2TXFhDsKDGDTlndYOZ6rGS0BRZIxGhM=
github.com/gofrs/flock v0.13.0 h1:95JolYOvGMqeH31+FC7D2+uULf6mG61mEZ/A8dRYMzw= github.com/gofrs/flock v0.13.0 h1:95JolYOvGMqeH31+FC7D2+uULf6mG61mEZ/A8dRYMzw=
@@ -195,6 +197,8 @@ github.com/inconshreveable/mousetrap v1.1.0 h1:wN+x4NVGpMsO7ErUn/mUI3vEoE6Jt13X2
github.com/inconshreveable/mousetrap v1.1.0/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw= github.com/inconshreveable/mousetrap v1.1.0/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw=
github.com/inhies/go-bytesize v0.0.0-20220417184213-4913239db9cf h1:FtEj8sfIcaaBfAKrE1Cwb61YDtYq9JxChK1c7AKce7s= github.com/inhies/go-bytesize v0.0.0-20220417184213-4913239db9cf h1:FtEj8sfIcaaBfAKrE1Cwb61YDtYq9JxChK1c7AKce7s=
github.com/inhies/go-bytesize v0.0.0-20220417184213-4913239db9cf/go.mod h1:yrqSXGoD/4EKfF26AOGzscPOgTTJcyAwM2rpixWT+t4= github.com/inhies/go-bytesize v0.0.0-20220417184213-4913239db9cf/go.mod h1:yrqSXGoD/4EKfF26AOGzscPOgTTJcyAwM2rpixWT+t4=
github.com/jmoiron/sqlx v1.4.0 h1:1PLqN7S1UYp5t4SrVVnt4nUVNemrDAtxlulVe+Qgm3o=
github.com/jmoiron/sqlx v1.4.0/go.mod h1:ZrZ7UsYB/weZdl2Bxg6jCRO9c3YHl8r3ahlKmRT4JLY=
github.com/jonboulle/clockwork v0.5.0 h1:Hyh9A8u51kptdkR+cqRpT1EebBwTn1oK9YfGYbdFz6I= github.com/jonboulle/clockwork v0.5.0 h1:Hyh9A8u51kptdkR+cqRpT1EebBwTn1oK9YfGYbdFz6I=
github.com/jonboulle/clockwork v0.5.0/go.mod h1:3mZlmanh0g2NDKO5TWZVJAfofYk64M7XN3SzBPjZF60= github.com/jonboulle/clockwork v0.5.0/go.mod h1:3mZlmanh0g2NDKO5TWZVJAfofYk64M7XN3SzBPjZF60=
github.com/julienschmidt/httprouter v1.3.0 h1:U0609e9tgbseu3rBINet9P48AI/D3oJs4dN7jwJOQ1U= github.com/julienschmidt/httprouter v1.3.0 h1:U0609e9tgbseu3rBINet9P48AI/D3oJs4dN7jwJOQ1U=
@@ -207,10 +211,12 @@ github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE=
github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk= github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk=
github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE=
github.com/lib/pq v1.10.9/go.mod h1:AlVN5x4E4T544tWzH6hKfbfQvm3HdbOxrmggDNAPY9o=
github.com/mattn/go-runewidth v0.0.16 h1:E5ScNMtiwvlvB5paMFdw9p4kSQzbXFikJ5SQO6TULQc= github.com/mattn/go-runewidth v0.0.16 h1:E5ScNMtiwvlvB5paMFdw9p4kSQzbXFikJ5SQO6TULQc=
github.com/mattn/go-runewidth v0.0.16/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w= github.com/mattn/go-runewidth v0.0.16/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w=
github.com/mattn/go-shellwords v1.0.12 h1:M2zGm7EW6UQJvDeQxo4T51eKPurbeFbe8WtebGE2xrk= github.com/mattn/go-shellwords v1.0.12 h1:M2zGm7EW6UQJvDeQxo4T51eKPurbeFbe8WtebGE2xrk=
github.com/mattn/go-shellwords v1.0.12/go.mod h1:EZzvwXDESEeg03EKmM+RmDnNOPKG4lLtQsUlTZDWQ8Y= github.com/mattn/go-shellwords v1.0.12/go.mod h1:EZzvwXDESEeg03EKmM+RmDnNOPKG4lLtQsUlTZDWQ8Y=
github.com/mattn/go-sqlite3 v1.14.22/go.mod h1:Uh1q+B4BYcTPb+yiD3kU8Ct7aC0hY9fxUwlHK0RXw+Y=
github.com/mattn/go-sqlite3 v1.14.39 h1:sIwSjlJGOaRJjw44/HXaeTblZMjseqr6OOio1tz/+JI= github.com/mattn/go-sqlite3 v1.14.39 h1:sIwSjlJGOaRJjw44/HXaeTblZMjseqr6OOio1tz/+JI=
github.com/mattn/go-sqlite3 v1.14.39/go.mod h1:Uh1q+B4BYcTPb+yiD3kU8Ct7aC0hY9fxUwlHK0RXw+Y= github.com/mattn/go-sqlite3 v1.14.39/go.mod h1:Uh1q+B4BYcTPb+yiD3kU8Ct7aC0hY9fxUwlHK0RXw+Y=
github.com/mitchellh/hashstructure/v2 v2.0.2 h1:vGKWl0YJqUNxE8d+h8f6NJLcCJrgbhC4NcD46KavDd4= github.com/mitchellh/hashstructure/v2 v2.0.2 h1:vGKWl0YJqUNxE8d+h8f6NJLcCJrgbhC4NcD46KavDd4=

View File

@@ -5,6 +5,8 @@ import (
"database/sql" "database/sql"
"errors" "errors"
"time" "time"
"github.com/jmoiron/sqlx"
) )
type StateType int type StateType int
@@ -44,7 +46,7 @@ type Options struct {
} }
type FoundryStateModel struct { type FoundryStateModel struct {
DB *sql.DB DB *sqlx.DB
} }
func (m FoundryStateModel) Insert(state *FoundryState) error { func (m FoundryStateModel) Insert(state *FoundryState) error {

View File

@@ -1,6 +1,6 @@
package db package db
import "database/sql" import "github.com/jmoiron/sqlx"
// var ( // var (
// ErrRecordNotFound = errors.New("record not found") // ErrRecordNotFound = errors.New("record not found")
@@ -21,7 +21,7 @@ type Models struct {
// } // }
// } // }
func NewModels(db *sql.DB) *Models { func NewModels(db *sqlx.DB) *Models {
return &Models{ return &Models{
FoundryState: FoundryStateModel{DB: db}, FoundryState: FoundryStateModel{DB: db},
} }

View File

@@ -1,5 +1,12 @@
package db package db
import (
"context"
"fmt"
"github.com/jmoiron/sqlx"
)
type Author struct { type Author struct {
ID uint ID uint
@@ -9,3 +16,40 @@ type Author struct {
Discord string Discord string
// SystemAuthorsFlags SystemAuthorsFlags `json:"flags"` // SystemAuthorsFlags SystemAuthorsFlags `json:"flags"`
} }
func (a *Author) Query(data *InsertId[string]) {
data.query = fmt.Sprintf(`
INSERT INTO author (%s, name, url, email, discord)
VALUES ($1, $2, $3, $4, $5)
RETURNING id`, data.fieldName)
}
func (a *Author) Insert(tx *sqlx.Tx, data *InsertId[string]) error {
if data.query == "" {
return ErrNoQuery
}
args := []any{data.id, a.Name, a.URL, a.Email, a.Discord}
err := tx.QueryRow(data.query, args...).Scan(&a.ID)
if err != nil {
return err
}
return nil
}
func (a *Author) InsertCtx(ctx context.Context, tx *sqlx.Tx, data *InsertId[string]) error {
if data.query == "" {
return ErrNoQuery
}
args := []any{data.id, a.Name, a.URL, a.Email, a.Discord}
err := tx.QueryRowContext(ctx, data.query, args...).Scan(&a.ID)
if err != nil {
return err
}
return nil
}

View File

@@ -1,5 +1,12 @@
package db package db
import (
"context"
"fmt"
"github.com/jmoiron/sqlx"
)
type Compatibility struct { type Compatibility struct {
ID uint ID uint
@@ -7,3 +14,40 @@ type Compatibility struct {
Verified string Verified string
Maximum string Maximum string
} }
func (c Compatibility) Query(data *InsertId[string]) {
data.query = fmt.Sprintf(`
INSERT INTO compatibility (%s, minimum, verified, maximum)
VALUES ($1, $2, $3, $4)
RETURNING id`, data.fieldName)
}
func (c Compatibility) Insert(tx *sqlx.Tx, data *InsertId[string]) error {
if data.query == "" {
return ErrNoQuery
}
args := []any{data.id, c.Minimum, c.Verified, c.Maximum}
err := tx.QueryRow(data.query, args...).Scan(&c.ID)
if err != nil {
return err
}
return nil
}
func (c Compatibility) InsertCtx(ctx context.Context, tx *sqlx.Tx, data *InsertId[string]) error {
if data.query == "" {
return ErrNoQuery
}
args := []any{data.id, c.Minimum, c.Verified, c.Maximum}
err := tx.QueryRowContext(ctx, data.query, args...).Scan(&c.ID)
if err != nil {
return err
}
return nil
}

View File

@@ -1,9 +1,60 @@
package db package db
import (
"context"
"github.com/jmoiron/sqlx"
)
type DocumentTypes struct { type DocumentTypes struct {
ID uint ID uint
Data []DocumentTypeData Data []*DocumentTypeData
}
func (d DocumentTypes) Query(data *InsertId[string]) {
data.query = `
INSERT INTO document_types (module_id)
VALUES ($1)
RETURNING id`
}
func (d DocumentTypes) Insert(tx *sqlx.Tx, data *InsertId[string]) error {
if data.query == "" {
return ErrNoQuery
}
args := []any{data.id}
err := tx.QueryRow(data.query, args...).Scan(&d.ID)
if err != nil {
return err
}
syncDB := NewSyncDB()
defer close(syncDB.errChan)
InsertSliceParallel(syncDB, tx, d.Data, &InsertId[uint]{id: d.ID})
return syncDB.Wait()
}
func (d DocumentTypes) InsertCtx(ctx context.Context, tx *sqlx.Tx, data *InsertId[string]) error {
if data.query == "" {
return ErrNoQuery
}
args := []any{data.id}
err := tx.QueryRowContext(ctx, data.query, args...).Scan(&d.ID)
if err != nil {
return err
}
syncDB := NewSyncDB()
defer close(syncDB.errChan)
InsertSliceParallel(syncDB, tx, d.Data, &InsertId[uint]{id: d.ID})
return syncDB.Wait()
} }
type DocumentTypeData struct { type DocumentTypeData struct {
@@ -12,3 +63,50 @@ type DocumentTypeData struct {
Type string Type string
HtmlFields []string HtmlFields []string
} }
func (d *DocumentTypeData) Query(data *InsertId[uint]) {
data.query = `
INSERT INTO document_types_data (document_types_id, type)
VALUES ($1, $2)
RETURNING id`
}
func (d *DocumentTypeData) Insert(tx *sqlx.Tx, data *InsertId[uint]) error {
if data.query == "" {
return ErrNoQuery
}
args := []any{data.id, d.Type}
err := tx.QueryRow(data.query, args...).Scan(&d.ID)
if err != nil {
return err
}
syncDB := NewSyncDB()
defer close(syncDB.errChan)
relData := &InsertId[uint]{id: d.ID, fieldName: "document_types_data_id", tableName: "document_types_data_html"}
InsertSimpleSliceParallel(syncDB, tx, d.HtmlFields, relData)
return syncDB.Wait()
}
func (d *DocumentTypeData) InsertCtx(ctx context.Context, tx *sqlx.Tx, data *InsertId[uint]) error {
if data.query == "" {
return ErrNoQuery
}
args := []any{data.id, d.Type}
err := tx.QueryRowContext(ctx, data.query, args...).Scan(&d.ID)
if err != nil {
return err
}
syncDB := NewSyncDB()
defer close(syncDB.errChan)
relData := &InsertId[uint]{id: d.ID, fieldName: "document_types_data_id", tableName: "document_types_data_html"}
InsertSimpleSliceParallel(syncDB, tx, d.HtmlFields, relData)
return syncDB.Wait()
}

View File

@@ -1,7 +1,104 @@
package db package db
import (
"context"
"fmt"
"github.com/jmoiron/sqlx"
)
type Files struct { type Files struct {
ID uint ID uint
Storages []string Storages []FilesStorage
}
func (f *Files) Query(data *InsertId[uint]) {
data.query = fmt.Sprintf(`
INSERT INTO files (%s)
VALUES ($1)
RETURNING id`, data.fieldName)
}
func (f *Files) Insert(tx *sqlx.Tx, data *InsertId[uint]) error {
if data.query == "" {
return ErrNoQuery
}
args := []any{data.id}
err := tx.QueryRowx(data.query, args...).Scan(&f.ID)
if err != nil {
return err
}
syncDB := NewSyncDB()
defer close(syncDB.errChan)
InsertSliceParallel(syncDB, tx, f.Storages, &InsertId[uint]{id: f.ID})
return syncDB.Wait()
}
func (f *Files) InsertCtx(ctx context.Context, tx *sqlx.Tx, data *InsertId[uint]) error {
if data.query == "" {
return ErrNoQuery
}
args := []any{data.id}
err := tx.QueryRowxContext(ctx, data.query, args...).Scan(&f.ID)
if err != nil {
return err
}
syncDB := NewSyncDB()
defer close(syncDB.errChan)
InsertSliceParallel(syncDB, tx, f.Storages, &InsertId[uint]{id: f.ID})
return syncDB.Wait()
}
type FilesStorage struct {
ID uint
Storage string
}
func (f FilesStorage) Query(data *InsertId[uint]) {
data.query = `
INSERT INTO files_storage (files_id, storage)
VALUES ($1, $2)
RETURNING id`
}
func (f FilesStorage) Insert(tx *sqlx.Tx, data *InsertId[uint]) error {
if data.query == "" {
return ErrNoQuery
}
args := []any{data.id, f.Storage}
err := tx.QueryRowx(data.query, args...).Scan(&f.ID)
if err != nil {
return err
}
return nil
}
func (f FilesStorage) InsertCtx(ctx context.Context, tx *sqlx.Tx, data *InsertId[uint]) error {
if data.query == "" {
return ErrNoQuery
}
args := []any{data.id, f.Storage}
err := tx.QueryRowxContext(ctx, data.query, args...).Scan(&f.ID)
if err != nil {
return err
}
return nil
} }

View File

@@ -1,5 +1,13 @@
package db package db
import (
"context"
"fmt"
"strconv"
"github.com/jmoiron/sqlx"
)
type Folder struct { type Folder struct {
ID uint ID uint
@@ -7,7 +15,59 @@ type Folder struct {
Sorting string Sorting string
Color string Color string
Packs []string Packs []string
Folders []Folder Folders []*Folder
}
func (f *Folder) Query(data *InsertId[string]) {
data.query = fmt.Sprintf(`
INSERT INTO folder (%s, name, sorting, color)
VALUES ($1, $2, $3, $4)
RETURNING id`, data.fieldName)
}
func (f *Folder) InsertObjects(tx *sqlx.Tx) error {
relId := &InsertId[string]{
id: strconv.FormatUint(uint64(f.ID), 10),
fieldName: "folder_id",
tableName: "folder_packs",
}
syncDB := NewSyncDB()
defer close(syncDB.errChan)
InsertSimpleSliceParallel(syncDB, tx, f.Packs, relId)
InsertSliceParallel(syncDB, tx, f.Folders, relId)
return syncDB.Wait()
}
func (f *Folder) Insert(tx *sqlx.Tx, data *InsertId[string]) error {
if data.query == "" {
return ErrNoQuery
}
args := []any{data.id, f.Name, f.Sorting, f.Color}
err := tx.QueryRow(data.query, args...).Scan(&f.ID)
if err != nil {
return err
}
return f.InsertObjects(tx)
}
func (f *Folder) InsertCtx(ctx context.Context, tx *sqlx.Tx, data *InsertId[string]) error {
if data.query == "" {
return ErrNoQuery
}
args := []any{data.id, f.Name, f.Sorting, f.Color}
err := tx.QueryRowContext(ctx, data.query, args...).Scan(&f.ID)
if err != nil {
return err
}
return f.InsertObjects(tx)
} }
type WorldFolder struct { type WorldFolder struct {

View File

@@ -1,6 +1,9 @@
package db package db
import "time" import (
"database/sql"
"time"
)
type FoundryDataType string type FoundryDataType string
@@ -17,3 +20,7 @@ type FoundryData struct {
Game *Game Game *Game
CreatedAt time.Time CreatedAt time.Time
} }
type FoundryDataModel struct {
DB *sql.DB
}

View File

@@ -11,14 +11,14 @@ type Game struct {
Files Files Files Files
Options GameOptions Options GameOptions
Release Release Release Release
World World World *World
System System System *System
CoreUpdate CoreUpdate CoreUpdate CoreUpdate
SystemUpdate SystemUpdate SystemUpdate SystemUpdate
ActiveUsers []string ActiveUsers []string
Modules []Module Modules []*Module
PackageWarnings []PackageWarning PackageWarnings []*PackageWarning
Packs []Pack Packs []*Pack
Messages []Message Messages []Message
Combats []Combat Combats []Combat
CardDeck []CardDeck CardDeck []CardDeck

View File

@@ -1,5 +1,11 @@
package db package db
import (
"context"
"github.com/jmoiron/sqlx"
)
type Grid struct { type Grid struct {
ID uint ID uint
@@ -13,3 +19,43 @@ type Grid struct {
Units string Units string
Style string Style string
} }
func (g *Grid) Query(data *InsertId[string]) {
data.query = `
INSERT INTO grid (system_id, type, size, distance, diagonals, thickness
alpha, color, units, style)
VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10)
RETURNING id`
}
func (g *Grid) Insert(tx *sqlx.Tx, data *InsertId[string]) error {
if data.query == "" {
return ErrNoQuery
}
args := []any{data.id, g.Type, g.Size, g.Distance, g.Diagonals, g.Thickness,
g.Alpha, g.Color, g.Units, g.Style}
err := tx.QueryRowx(data.query, args...).Scan(&g.ID)
if err != nil {
return err
}
return nil
}
func (g *Grid) InsertCtx(ctx context.Context, tx *sqlx.Tx, data *InsertId[string]) error {
if data.query == "" {
return ErrNoQuery
}
args := []any{data.id, g.Type, g.Size, g.Distance, g.Diagonals, g.Thickness,
g.Alpha, g.Color, g.Units, g.Style}
err := tx.QueryRowxContext(ctx, data.query, args...).Scan(&g.ID)
if err != nil {
return err
}
return nil
}

View File

@@ -1,5 +1,11 @@
package db package db
import (
"context"
"github.com/jmoiron/sqlx"
)
type Index struct { type Index struct {
ID string ID string
@@ -8,3 +14,40 @@ type Index struct {
Name string Name string
Type string Type string
} }
func (i *Index) Query(data *InsertId[string]) {
data.query = `
INSERT INTO index_ (pack_id, id, folder, img, name, type)
VALUES ($1, $2, $3, $4, $5, $6)
RETURNING id`
}
func (i *Index) Insert(tx *sqlx.Tx, data *InsertId[string]) error {
if data.query == "" {
return ErrNoQuery
}
args := []any{data.id, i.ID, i.Folder, i.Img, i.Name, i.Type}
_, err := tx.Exec(data.query, args...)
if err != nil {
return err
}
return nil
}
func (i *Index) InsertCtx(ctx context.Context, tx *sqlx.Tx, data *InsertId[string]) error {
if data.query == "" {
return ErrNoQuery
}
args := []any{data.id, i.ID, i.Folder, i.Img, i.Name, i.Type}
_, err := tx.ExecContext(ctx, data.query, args...)
if err != nil {
return err
}
return nil
}

View File

@@ -1,5 +1,108 @@
package db package db
import (
"context"
"fmt"
"github.com/jmoiron/sqlx"
)
type SetupLanguage struct {
ID string
Label string
Modules []SetupLanguageModule
}
func (l *SetupLanguage) Query(data *InsertId[uint]) {
data.query = `
INSERT INTO setup_language (setup_id, label)
VALUES ($1, $2)
RETURNING id`
}
func (l *SetupLanguage) Insert(tx *sqlx.Tx, data *InsertId[uint]) error {
if data.query == "" {
return ErrNoQuery
}
args := []any{data.id, l.Label}
err := tx.QueryRowx(data.query, args...).Scan(&l.ID)
if err != nil {
return err
}
syncDB := NewSyncDB()
defer close(syncDB.errChan)
InsertSliceParallel(syncDB, tx, l.Modules, &InsertId[string]{id: l.ID})
return nil
}
func (l *SetupLanguage) InsertCtx(ctx context.Context, tx *sqlx.Tx, data *InsertId[uint]) error {
if data.query == "" {
return ErrNoQuery
}
args := []any{data.id, l.Label}
err := tx.QueryRowxContext(ctx, data.query, args...).Scan(&l.ID)
if err != nil {
return err
}
syncDB := NewSyncDB()
defer close(syncDB.errChan)
InsertSliceParallel(syncDB, tx, l.Modules, &InsertId[string]{id: l.ID})
return nil
}
type SetupLanguageModule struct {
ID string
Label string
Path string
}
func (l SetupLanguageModule) Query(data *InsertId[string]) {
data.query = `
INSERT INTO setup_language_module (setup_language_id, id, label, path)
VALUES ($1, $2, $3, $4)
RETURNING id`
}
func (l SetupLanguageModule) Insert(tx *sqlx.Tx, data *InsertId[string]) error {
if data.query == "" {
return ErrNoQuery
}
args := []any{data.id, l.ID, l.Label, l.Path}
_, err := tx.Exec(data.query, args...)
if err != nil {
return err
}
return nil
}
func (l SetupLanguageModule) InsertCtx(ctx context.Context, tx *sqlx.Tx, data *InsertId[string]) error {
if data.query == "" {
return ErrNoQuery
}
args := []any{data.id, l.ID, l.Label, l.Path}
_, err := tx.ExecContext(ctx, data.query, args...)
if err != nil {
return err
}
return nil
}
type Language struct { type Language struct {
ID uint ID uint
@@ -8,16 +111,39 @@ type Language struct {
Path string Path string
} }
type SetupLanguage struct { func (l *Language) Query(data *InsertId[string]) {
ID string data.query = fmt.Sprintf(`
INSERT INTO language (%s, lang, name, path)
Label string VALUES ($1, $2, $3, $4)
Modules []SetupLanguageModule RETURNING id`, data.fieldName)
} }
type SetupLanguageModule struct { func (l *Language) Insert(tx *sqlx.Tx, data *InsertId[string]) error {
ID string if data.query == "" {
return ErrNoQuery
}
Label string args := []any{data.id, l.Lang, l.Name, l.Path}
Path string
err := tx.QueryRow(data.query, args...).Scan(&l.ID)
if err != nil {
return err
}
return nil
}
func (l *Language) InsertCtx(ctx context.Context, tx *sqlx.Tx, data *InsertId[string]) error {
if data.query == "" {
return ErrNoQuery
}
args := []any{data.id, l.Lang, l.Name, l.Path}
err := tx.QueryRowContext(ctx, data.query, args...).Scan(&l.ID)
if err != nil {
return err
}
return nil
} }

View File

@@ -1,5 +1,12 @@
package db package db
import (
"context"
"fmt"
"github.com/jmoiron/sqlx"
)
type Media struct { type Media struct {
ID uint ID uint
@@ -7,3 +14,40 @@ type Media struct {
URL string URL string
Caption string Caption string
} }
func (m *Media) Query(data *InsertId[string]) {
data.query = fmt.Sprintf(`
INSERT INTO media (%s, type, url, caption)
VALUES ($1, $2, $3, $4)
RETURNING id`, data.fieldName)
}
func (m *Media) Insert(tx *sqlx.Tx, data *InsertId[string]) error {
if data.query == "" {
return ErrNoQuery
}
args := []any{data.id, m.Type, m.URL, m.Caption}
err := tx.QueryRow(data.query, args...).Scan(&m.ID)
if err != nil {
return err
}
return nil
}
func (m *Media) InsertCtx(ctx context.Context, tx *sqlx.Tx, data *InsertId[string]) error {
if data.query == "" {
return ErrNoQuery
}
args := []any{data.id, m.Type, m.URL, m.Caption}
err := tx.QueryRowContext(ctx, data.query, args...).Scan(&m.ID)
if err != nil {
return err
}
return nil
}

View File

@@ -1,5 +1,12 @@
package db package db
import (
"context"
"fmt"
"github.com/jmoiron/sqlx"
)
type Module struct { type Module struct {
ID string ID string
@@ -11,30 +18,98 @@ type Module struct {
Bugs string Bugs string
Changelog string Changelog string
Version string Version string
Socket bool
Manifest string
Download string Download string
Manifest string
Socket bool
Protected bool Protected bool
Exclusive bool Exclusive bool
PersistentStorage bool PersistentStorage bool
CoreTranslation bool CoreTranslation bool
Library bool Library bool
Availability int
Locked bool Locked bool
Owned bool Owned bool
HasStorage bool HasStorage bool
Active bool Active bool
Availability int
DocumentTypes DocumentTypes DocumentTypes DocumentTypes
Relationships Relationships Relationships Relationships
Compatibility Compatibility Compatibility Compatibility
Authors []Author
Media []Media
Scripts []string Scripts []string
Esmodules []string Esmodules []string
Styles []Style
Languages []Language
Packs []Pack
PackFolders []Folder
Tags []string Tags []string
// ModulesFlags ModulesFlags `json:"flags,omitempty"` Authors []*Author
Media []*Media
Styles []*Style
Languages []*Language
Packs []*Pack
PackFolders []*Folder
}
func (m *Module) Query(data *InsertId[uint]) {
data.query = fmt.Sprintf(`
INSERT INTO module (%s, id, title, description, url, license, readme, bugs,
changelog, version, manifest, download, socket, protected, exclusive_, persistent_storage,
core_translation, library, locked, owned, has_storage, active, availability)
VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11, $12, $13, $14, $15, $16, $17,
$18, $19, $20, $21, $22, $23)`, data.fieldName)
}
func (m *Module) InsertObjects(tx *sqlx.Tx) error {
relId := &InsertId[string]{id: m.ID, fieldName: "module_id"}
syncDB := NewSyncDB()
defer close(syncDB.errChan)
go InsertWithCtxParallel(syncDB, tx, m.DocumentTypes, relId)
go InsertWithCtxParallel(syncDB, tx, m.Relationships, relId)
go InsertWithCtxParallel(syncDB, tx, m.Compatibility, relId)
scriptRelId := &InsertId[string]{id: m.ID, fieldName: "module_id", tableName: "scripts"}
go InsertSimpleSliceParallel(syncDB, tx, m.Scripts, scriptRelId)
esModulesRelId := &InsertId[string]{id: m.ID, fieldName: "module_id", tableName: "es_modules"}
go InsertSimpleSliceParallel(syncDB, tx, m.Esmodules, esModulesRelId)
tagsRelId := &InsertId[string]{id: m.ID, fieldName: "module_id", tableName: "tags"}
go InsertSimpleSliceParallel(syncDB, tx, m.Tags, tagsRelId)
go InsertSliceParallel(syncDB, tx, m.Authors, relId)
go InsertSliceParallel(syncDB, tx, m.Media, relId)
go InsertSliceParallel(syncDB, tx, m.Styles, relId)
go InsertSliceParallel(syncDB, tx, m.Languages, relId)
go InsertSliceParallel(syncDB, tx, m.Packs, relId)
go InsertSliceParallel(syncDB, tx, m.PackFolders, relId)
return syncDB.Wait()
}
func (m *Module) Insert(tx *sqlx.Tx, data *InsertId[uint]) error {
if data.query == "" {
return ErrNoQuery
}
args := []any{data.id, m.ID, m.Title, m.Description, m.URL, m.License, m.Readme, m.Bugs,
m.Changelog, m.Version, m.Manifest, m.Download, m.Socket, m.Protected, m.Exclusive, m.PersistentStorage,
m.CoreTranslation, m.Library, m.Locked, m.Owned, m.HasStorage, m.Active, m.Availability}
_, err := tx.Exec(data.query, args...)
if err != nil {
return err
}
return m.InsertObjects(tx)
}
func (m *Module) InsertCtx(ctx context.Context, tx *sqlx.Tx, data *InsertId[uint]) error {
if data.query == "" {
return ErrNoQuery
}
args := []any{data.id, m.ID, m.Title, m.Description, m.URL, m.License, m.Readme, m.Bugs,
m.Changelog, m.Version, m.Manifest, m.Download, m.Socket, m.Protected, m.Exclusive, m.PersistentStorage,
m.CoreTranslation, m.Library, m.Locked, m.Owned, m.HasStorage, m.Active, m.Availability}
_, err := tx.ExecContext(ctx, data.query, args...)
if err != nil {
return err
}
return m.InsertObjects(tx)
} }

View File

@@ -1,5 +1,11 @@
package db package db
import (
"context"
"github.com/jmoiron/sqlx"
)
type GameOptions struct { type GameOptions struct {
ID uint ID uint
@@ -8,23 +14,98 @@ type GameOptions struct {
Port int Port int
} }
func (g *GameOptions) Insert(tx *sqlx.Tx, gameId *InsertId[uint]) error {
query := `
INSERT INTO featured_content (game_id, language, update_channel, port)
VALUES ($1, $2, $3, $4)
RETURNING id`
args := []any{gameId.id, g.Language, g.UpdateChannel, g.Port}
err := tx.QueryRowx(query, args...).Scan(&g.ID)
if err != nil {
return err
}
return nil
}
func (g *GameOptions) InsertCtx(ctx context.Context, tx *sqlx.Tx, gameId *InsertId[uint]) error {
query := `
INSERT INTO featured_content (game_id, language, update_channel, port)
VALUES ($1, $2, $3, $4)
RETURNING id`
args := []any{gameId.id, g.Language, g.UpdateChannel, g.Port}
err := tx.QueryRowxContext(ctx, query, args...).Scan(&g.ID)
if err != nil {
return err
}
return nil
}
type SetupOptions struct { type SetupOptions struct {
ID uint ID uint
CompressSocket bool
CompressStatic bool
CSSTheme string CSSTheme string
DataPath string DataPath string
Fullscreen bool
Hostname string Hostname string
HotReload bool
Language string Language string
LocalHostname string LocalHostname string
UpdateChannel string
Port int Port int
CompressSocket bool
CompressStatic bool
Fullscreen bool
HotReload bool
ProxySSL bool ProxySSL bool
Telemetry bool Telemetry bool
UpdateChannel string
Upnp bool Upnp bool
DeleteNEDB bool DeleteNEDB bool
NoBackups bool NoBackups bool
} }
func (s *SetupOptions) Query(data *InsertId[uint]) {
data.query = `
INSERT INTO setup_options (setup_id, css_theme, data_path, hostname, language, local_hostname,
update_channel, port, compress_socket, compress_static, fullscreen, hot_reload, proxy_ssl,
telemetry, upnp, delete_nedb, no_backups,)
VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11, $12, $13, $14, $15, $16, $17)
RETURNING id`
}
func (s *SetupOptions) Insert(tx *sqlx.Tx, data *InsertId[uint]) error {
if data.query == "" {
return ErrNoQuery
}
args := []any{data.id, s.CSSTheme, s.DataPath, s.Hostname, s.Language, s.LocalHostname,
s.UpdateChannel, s.Port, s.CompressSocket, s.CompressStatic, s.Fullscreen, s.HotReload,
s.ProxySSL, s.Telemetry, s.Upnp, s.DeleteNEDB, s.NoBackups}
err := tx.QueryRowx(data.query, args...).Scan(&s.ID)
if err != nil {
return err
}
return nil
}
func (s *SetupOptions) InsertCtx(ctx context.Context, tx *sqlx.Tx, data *InsertId[uint]) error {
if data.query == "" {
return ErrNoQuery
}
args := []any{data.id, s.CSSTheme, s.DataPath, s.Hostname, s.Language, s.LocalHostname,
s.UpdateChannel, s.Port, s.CompressSocket, s.CompressStatic, s.Fullscreen, s.HotReload,
s.ProxySSL, s.Telemetry, s.Upnp, s.DeleteNEDB, s.NoBackups}
err := tx.QueryRowxContext(ctx, data.query, args...).Scan(&s.ID)
if err != nil {
return err
}
return nil
}

View File

@@ -1,5 +1,11 @@
package db package db
import (
"context"
"github.com/jmoiron/sqlx"
)
type Ownership struct { type Ownership struct {
ID uint ID uint
@@ -8,6 +14,43 @@ type Ownership struct {
Assistant string Assistant string
} }
func (o Ownership) Query(data *InsertId[string]) {
data.query = `
INSERT INTO ownership (%s, player, trusted, assistant)
VALUES ($1, $2, $3, $4)
RETURNING id`
}
func (o Ownership) Insert(tx *sqlx.Tx, data *InsertId[string]) error {
if data.query == "" {
return ErrNoQuery
}
args := []any{data.id, o.Player, o.Trusted, o.Assistant}
err := tx.QueryRow(data.query, args...).Scan(&o.ID)
if err != nil {
return err
}
return nil
}
func (o Ownership) InsertCtx(ctx context.Context, tx *sqlx.Tx, data *InsertId[string]) error {
if data.query == "" {
return ErrNoQuery
}
args := []any{data.id, o.Player, o.Trusted, o.Assistant}
err := tx.QueryRowContext(ctx, data.query, args...).Scan(&o.ID)
if err != nil {
return err
}
return nil
}
type OwnershipString struct { type OwnershipString struct {
ID uint ID uint

View File

@@ -1,5 +1,12 @@
package db package db
import (
"context"
"fmt"
"github.com/jmoiron/sqlx"
)
type Pack struct { type Pack struct {
ID string ID string
@@ -12,8 +19,57 @@ type Pack struct {
PackageType string PackageType string
PackageName string PackageName string
Ownership Ownership Ownership Ownership
Index []Index Index []*Index
Folders []PackFolder Folders []*PackFolder
}
func (p *Pack) Query(data *InsertId[string]) {
data.query = fmt.Sprintf(`
INSERT INTO pack (%s, id, name, label, banner, path, type, system, package_type, package_name)
VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10)
RETURNING id`, data.fieldName)
}
func (p *Pack) InsertObjects(tx *sqlx.Tx) error {
relId := &InsertId[string]{id: p.ID, fieldName: "pack_id"}
syncDB := NewSyncDB()
defer close(syncDB.errChan)
InsertWithCtxParallel(syncDB, tx, p.Ownership, relId)
InsertSliceParallel(syncDB, tx, p.Index, relId)
InsertSliceParallel(syncDB, tx, p.Folders, relId)
return syncDB.Wait()
}
func (p *Pack) Insert(tx *sqlx.Tx, data *InsertId[string]) error {
if data.query == "" {
return ErrNoQuery
}
args := []any{data.id, p.ID, p.Name, p.Label, p.Banner, p.Path, p.Type, p.System, p.PackageType, p.PackageName}
_, err := tx.Exec(data.query, args...)
if err != nil {
return err
}
return p.InsertObjects(tx)
}
func (p *Pack) InsertCtx(ctx context.Context, tx *sqlx.Tx, data *InsertId[string]) error {
if data.query == "" {
return ErrNoQuery
}
args := []any{data.id, p.ID, p.Name, p.Label, p.Banner, p.Path, p.Type, p.System, p.PackageType, p.PackageName}
_, err := tx.ExecContext(ctx, data.query, args...)
if err != nil {
return err
}
return p.InsertObjects(tx)
} }
type PackFolder struct { type PackFolder struct {
@@ -21,7 +77,43 @@ type PackFolder struct {
Description string Description string
Name string Name string
Sort int
Sorting string Sorting string
Type string Type string
Sort int
}
func (p *PackFolder) Query(data *InsertId[string]) {
data.query = fmt.Sprintf(`
INSERT INTO pack_folder (%s, id, description, name, sorting, type, sort)
VALUES ($1, $2, $3, $4, $5, $6, $7)`, data.fieldName)
}
func (p *PackFolder) Insert(tx *sqlx.Tx, data *InsertId[string]) error {
if data.query == "" {
return ErrNoQuery
}
args := []any{data.id, p.ID, p.Description, p.Name, p.Sorting, p.Type, p.Sort}
_, err := tx.Exec(data.query, args...)
if err != nil {
return err
}
return nil
}
func (p *PackFolder) InsertCtx(ctx context.Context, tx *sqlx.Tx, data *InsertId[string]) error {
if data.query == "" {
return ErrNoQuery
}
args := []any{data.id, p.ID, p.Description, p.Name, p.Sorting, p.Type, p.Sort}
_, err := tx.ExecContext(ctx, data.query, args...)
if err != nil {
return err
}
return nil
} }

View File

@@ -1,18 +1,112 @@
package db package db
type PackageWarningsData struct { import (
ID string "context"
"fmt"
Type string "github.com/jmoiron/sqlx"
Warning []string )
Error []string
Reinstallable bool
Manifest string
}
type PackageWarning struct { type PackageWarning struct {
ID string ID string
Key string Key string
Value PackageWarningsData Value *PackageWarningsData
}
func (p *PackageWarning) Query(data *InsertId[uint]) {
data.query = fmt.Sprintf(`
INSERT INTO package_warnings (%s, id)
VALUES ($1, $2)`, data.fieldName)
}
func (p *PackageWarning) Insert(tx *sqlx.Tx, data *InsertId[uint]) error {
if data.query == "" {
return ErrNoQuery
}
args := []any{data.id, p.ID}
_, err := tx.Exec(data.query, args...)
if err != nil {
return err
}
InsertWithCtx(tx, p.Value, &InsertId[string]{id: p.ID})
return nil
}
func (p *PackageWarning) InsertCtx(ctx context.Context, tx *sqlx.Tx, data *InsertId[uint]) error {
if data.query == "" {
return ErrNoQuery
}
args := []any{data.id, p.ID}
_, err := tx.Exec(data.query, args...)
if err != nil {
return err
}
InsertWithCtx(tx, p.Value, &InsertId[string]{id: p.ID})
return nil
}
type PackageWarningsData struct {
ID string
Type string
Manifest string
Reinstallable bool
Warning []string
Error []string
}
func (p *PackageWarningsData) InsertObjects(tx *sqlx.Tx) error {
syncDB := NewSyncDB()
defer close(syncDB.errChan)
warningData := &InsertId[string]{id: p.ID, fieldName: "package_warnings_data_id", tableName: "package_warnings_data_warning"}
InsertSimpleSliceParallel(syncDB, tx, p.Warning, warningData)
errorData := &InsertId[string]{id: p.ID, fieldName: "package_warnings_data_id", tableName: "package_warnings_data_error"}
InsertSimpleSliceParallel(syncDB, tx, p.Warning, errorData)
return syncDB.Wait()
}
func (p *PackageWarningsData) Query(data *InsertId[string]) {
data.query = fmt.Sprintf(`
INSERT INTO package_warnings_data (%s, id, type, reinstallable, manifest)
VALUES ($1, $2, $3, $4, $5)`, data.fieldName)
}
func (p *PackageWarningsData) Insert(tx *sqlx.Tx, data *InsertId[string]) error {
if data.query == "" {
return ErrNoQuery
}
args := []any{data.id, p.ID, p.Type, p.Reinstallable, p.Manifest}
_, err := tx.Exec(data.query, args...)
if err != nil {
return err
}
return p.InsertObjects(tx)
}
func (p *PackageWarningsData) InsertCtx(ctx context.Context, tx *sqlx.Tx, data *InsertId[string]) error {
if data.query == "" {
return ErrNoQuery
}
args := []any{data.id, p.ID, p.Type, p.Reinstallable, p.Manifest}
_, err := tx.ExecContext(ctx, data.query, args...)
if err != nil {
return err
}
return p.InsertObjects(tx)
} }

View File

@@ -1,16 +1,122 @@
package db package db
import (
"context"
"fmt"
"github.com/jmoiron/sqlx"
)
type Relationships struct { type Relationships struct {
ID uint ID uint
Data []RelationshipsData Systems []RelationshipsData
Requires []RelationshipsData
Recommends []RelationshipsData
Conflicts []RelationshipsData
}
func (r Relationships) Query(data *InsertId[string]) {
data.query = fmt.Sprintf(`
INSERT INTO relationships (%s)
VALUES ($1)
RETURNING id`, data.fieldName)
}
func (r Relationships) Insert(tx *sqlx.Tx, data *InsertId[string]) error {
if data.query == "" {
return ErrNoQuery
}
args := []any{data.id}
err := tx.QueryRowx(data.query, args...).Scan(&r.ID)
if err != nil {
return err
}
syncDB := NewSyncDB()
defer close(syncDB.errChan)
InsertSliceParallel(syncDB, tx, r.Systems, &InsertId[uint]{id: r.ID, tableName: "relationships_systems"})
InsertSliceParallel(syncDB, tx, r.Requires, &InsertId[uint]{id: r.ID, tableName: "relationships_requires"})
InsertSliceParallel(syncDB, tx, r.Recommends, &InsertId[uint]{id: r.ID, tableName: "relationships_recommends"})
InsertSliceParallel(syncDB, tx, r.Conflicts, &InsertId[uint]{id: r.ID, tableName: "relationships_conflicts"})
return syncDB.Wait()
}
func (r Relationships) InsertCtx(ctx context.Context, tx *sqlx.Tx, data *InsertId[string]) error {
if data.query == "" {
return ErrNoQuery
}
args := []any{data.id}
err := tx.QueryRowxContext(ctx, data.query, args...).Scan(&r.ID)
if err != nil {
return err
}
syncDB := NewSyncDB()
defer close(syncDB.errChan)
InsertSliceParallel(syncDB, tx, r.Systems, &InsertId[uint]{id: r.ID, tableName: "relationships_systems"})
InsertSliceParallel(syncDB, tx, r.Requires, &InsertId[uint]{id: r.ID, tableName: "relationships_requires"})
InsertSliceParallel(syncDB, tx, r.Recommends, &InsertId[uint]{id: r.ID, tableName: "relationships_recommends"})
InsertSliceParallel(syncDB, tx, r.Conflicts, &InsertId[uint]{id: r.ID, tableName: "relationships_conflicts"})
return syncDB.Wait()
} }
type RelationshipsData struct { type RelationshipsData struct {
ID string ID string
RelationshipsType string Type string
Type string Manifest string
Manifest string Compatibility Compatibility
Compatibility Compatibility }
func (r RelationshipsData) Query(data *InsertId[uint]) {
data.query = fmt.Sprintf(`
INSERT INTO %s (relationships_id, id, type, manifest)
VALUES ($1, $2, $3, $4, $5)`, data.tableName)
}
func (r RelationshipsData) Insert(tx *sqlx.Tx, data *InsertId[uint]) error {
if data.query == "" {
return ErrNoQuery
}
args := []any{data.id, r.ID, r.Type, r.Manifest}
_, err := tx.Exec(data.query, args...)
if err != nil {
return err
}
syncDB := NewSyncDB()
defer close(syncDB.errChan)
InsertWithCtxParallel(syncDB, tx, r.Compatibility, &InsertId[string]{id: r.ID, fieldName: fmt.Sprintf("%s_id", data.tableName)})
return nil
}
func (r RelationshipsData) InsertCtx(ctx context.Context, tx *sqlx.Tx, data *InsertId[uint]) error {
if data.query == "" {
return ErrNoQuery
}
args := []any{data.id, r.ID, r.Type, r.Manifest}
_, err := tx.ExecContext(ctx, data.query, args...)
if err != nil {
return err
}
syncDB := NewSyncDB()
defer close(syncDB.errChan)
InsertWithCtxParallel(syncDB, tx, r.Compatibility, &InsertId[string]{id: r.ID, fieldName: fmt.Sprintf("%s_id", data.tableName)})
return nil
} }

View File

@@ -1,14 +1,61 @@
package db package db
import (
"context"
"fmt"
"github.com/jmoiron/sqlx"
)
type Release struct { type Release struct {
ID uint ID uint
Generation int Generation int
Channel string
Suffix string
Build int Build int
NodeVersion int NodeVersion int
MaxGeneration int MaxGeneration int
MaxStableGeneration int MaxStableGeneration int
Time int64 Time int64
Channel string
Suffix string
}
func (r *Release) Query(data *InsertId[uint]) {
data.query = fmt.Sprintf(`
INSERT INTO release_ (%s, generaion, build, node_version, max_generation, max_stable_generation,
time, channel, suffix)
VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9)
RETURNING id`, data.fieldName)
}
func (r *Release) Insert(tx *sqlx.Tx, data *InsertId[uint]) error {
if data.query == "" {
return ErrNoQuery
}
args := []any{data.id, r.Generation, r.Build, r.NodeVersion, r.MaxGeneration, r.MaxStableGeneration,
r.Time, r.Channel, r.Suffix}
err := tx.QueryRowx(data.query, args...).Scan(&r.ID)
if err != nil {
return err
}
return nil
}
func (r *Release) InsertCtx(ctx context.Context, tx *sqlx.Tx, data *InsertId[uint]) error {
if data.query == "" {
return ErrNoQuery
}
args := []any{data.id, r.Generation, r.Build, r.NodeVersion, r.MaxGeneration, r.MaxStableGeneration,
r.Time, r.Channel, r.Suffix}
err := tx.QueryRowxContext(ctx, data.query, args...).Scan(&r.ID)
if err != nil {
return err
}
return nil
} }

View File

@@ -1,21 +1,83 @@
package db package db
import (
"context"
"strconv"
"time"
"github.com/jmoiron/sqlx"
)
type Setup struct { type Setup struct {
ID uint ID uint
CreatedAt time.Time
IsAdmin bool IsAdmin bool
IsSetup bool IsSetup bool
CoreUpdate CoreUpdate CoreUpdate CoreUpdate
FeaturedContent FeaturedContent FeaturedContent FeaturedContent
Files Files Files Files
Options SetupOptions Options *SetupOptions
Release Release Release Release
Languages []SetupLanguage Languages []*SetupLanguage
Modules []Module Modules []*Module
News []News News []*News
PackageWarnings []PackageWarning PackageWarnings []*PackageWarning
Systems []System Systems []*System
Worlds []World Worlds []*World
}
func (s *Setup) InsertObjects(tx *sqlx.Tx) error {
relData := &InsertId[uint]{id: s.ID, fieldName: "setup_id"}
syncDB := NewSyncDB()
defer close(syncDB.errChan)
InsertWithCtxParallel(syncDB, tx, &s.CoreUpdate, relData)
InsertWithCtxParallel(syncDB, tx, &s.FeaturedContent, relData)
InsertWithCtxParallel(syncDB, tx, &s.Files, relData)
InsertWithCtxParallel(syncDB, tx, s.Options, relData)
InsertWithCtxParallel(syncDB, tx, &s.Release, relData)
InsertSliceParallel(syncDB, tx, s.Languages, relData)
InsertSliceParallel(syncDB, tx, s.Modules, relData)
InsertSliceParallel(syncDB, tx, s.News, relData)
InsertSliceParallel(syncDB, tx, s.PackageWarnings, relData)
relDataString := &InsertId[string]{
id: strconv.FormatUint(uint64(s.ID), 10),
fieldName: "setup_id",
}
InsertSliceParallel(syncDB, tx, s.Systems, relDataString)
InsertSliceParallel(syncDB, tx, s.Worlds, relDataString)
return syncDB.Wait()
}
func (s *Setup) Insert(db *sqlx.DB) error {
tx := db.MustBegin()
defer tx.Rollback()
const query = `
INSERT INTO setup (is_admin, is_setup)
VALUES ($1, $2)
RETURNING id, created_at`
args := []any{s.IsAdmin, s.IsSetup}
ctx, cancel := context.WithTimeout(context.Background(), 3*time.Second)
defer cancel()
err := tx.QueryRowContext(ctx, query, args...).Scan(&s.ID, &s.CreatedAt)
if err != nil {
return err
}
err = s.InsertObjects(tx)
if err != nil {
return err
}
return tx.Commit()
} }
type FeaturedContent struct { type FeaturedContent struct {
@@ -27,6 +89,43 @@ type FeaturedContent struct {
Image string Image string
} }
func (f *FeaturedContent) Query(data *InsertId[uint]) {
data.query = `
INSERT INTO featured_content (setup_id, title, caption, url, image)
VALUES ($1, $2, $3, $4, $5)
RETURNING id`
}
func (f *FeaturedContent) Insert(tx *sqlx.Tx, data *InsertId[uint]) error {
if data.query == "" {
return ErrNoQuery
}
args := []any{data.id, f.Title, f.Caption, f.URL, f.Image}
err := tx.QueryRowx(data.query, args...).Scan(&f.ID)
if err != nil {
return err
}
return nil
}
func (f *FeaturedContent) InsertCtx(ctx context.Context, tx *sqlx.Tx, data *InsertId[uint]) error {
if data.query == "" {
return ErrNoQuery
}
args := []any{data.id, f.Title, f.Caption, f.URL, f.Image}
err := tx.QueryRowxContext(ctx, data.query, args...).Scan(&f.ID)
if err != nil {
return err
}
return nil
}
type News struct { type News struct {
ID uint ID uint
@@ -35,3 +134,40 @@ type News struct {
URL string URL string
Image string Image string
} }
func (n *News) Query(data *InsertId[uint]) {
data.query = `
INSERT INTO news (setup_id, title, caption, url, image)
VALUES ($1, $2, $3, $4, $5)
RETURNING id`
}
func (n *News) Insert(tx *sqlx.Tx, data *InsertId[uint]) error {
if data.query == "" {
return ErrNoQuery
}
args := []any{data.id, n.Title, n.Caption, n.URL, n.Image}
err := tx.QueryRow(data.query, args...).Scan(&n.ID)
if err != nil {
return err
}
return nil
}
func (n *News) InsertCtx(ctx context.Context, tx *sqlx.Tx, data *InsertId[uint]) error {
if data.query == "" {
return ErrNoQuery
}
args := []any{data.id, n.Title, n.Caption, n.URL, n.Image}
err := tx.QueryRowContext(ctx, data.query, args...).Scan(&n.ID)
if err != nil {
return err
}
return nil
}

View File

@@ -1,7 +1,51 @@
package db package db
import (
"context"
"fmt"
"github.com/jmoiron/sqlx"
)
type Style struct { type Style struct {
ID uint ID uint
Src string Src string
} }
func (s *Style) Query(data *InsertId[string]) {
data.query = fmt.Sprintf(`
INSERT INTO style (%s, src)
VALUES ($1, $2)
RETURNING id`, data.fieldName)
}
func (s *Style) Insert(tx *sqlx.Tx, data *InsertId[string]) error {
if data.query == "" {
return ErrNoQuery
}
args := []any{data.id, s.Src}
err := tx.QueryRow(data.query, args...).Scan(&s.ID)
if err != nil {
return err
}
return nil
}
func (s *Style) InsertCtx(ctx context.Context, tx *sqlx.Tx, data *InsertId[string]) error {
if data.query == "" {
return ErrNoQuery
}
args := []any{data.id, s.Src}
err := tx.QueryRowContext(ctx, data.query, args...).Scan(&s.ID)
if err != nil {
return err
}
return nil
}

View File

@@ -1,5 +1,12 @@
package db package db
import (
"context"
"fmt"
"github.com/jmoiron/sqlx"
)
type System struct { type System struct {
ID string ID string
@@ -10,29 +17,101 @@ type System struct {
Bugs string Bugs string
Changelog string Changelog string
Version string Version string
Socket bool
Manifest string Manifest string
Download string Download string
Protected bool
Exclusive bool
PersistentStorage bool
Background string Background string
PrimaryTokenAttribute string PrimaryTokenAttribute string
Availability int Availability int
Socket bool
Protected bool
Exclusive bool
PersistentStorage bool
Locked bool Locked bool
Owned bool Owned bool
HasStorage bool HasStorage bool
Esmodules []string
Scripts []string
Tags []string
Compatibility Compatibility Compatibility Compatibility
Relationships Relationships Relationships Relationships
DocumentTypes DocumentTypes DocumentTypes DocumentTypes
Grid Grid Grid *Grid
Authors []Author Esmodules []string
Media []Media Scripts []string
Packs []Pack Tags []string
Styles []Style Authors []*Author
Languages []Language Media []*Media
PackFolders []Folder Packs []*Pack
Styles []*Style
Languages []*Language
PackFolders []*Folder
}
func (s *System) Query(data *InsertId[string]) {
data.query = fmt.Sprintf(`
INSERT INTO system (%s, id, title, description, url, license, bugs, changelog, version, manifest,
download, background, primary_token_attribute, availability, socket, protected, exclusive_,
persistent_storage, locked, owned, has_storage)
VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11, $12, $13, $14, $15, $16, $17, $18, $19, $20, $21)`,
data.fieldName)
}
func (s *System) InsertObjects(tx *sqlx.Tx) error {
relId := &InsertId[string]{id: s.ID, fieldName: "system_id"}
syncDB := NewSyncDB()
defer close(syncDB.errChan)
InsertWithCtxParallel(syncDB, tx, s.Compatibility, relId)
InsertWithCtxParallel(syncDB, tx, s.Relationships, relId)
InsertWithCtxParallel(syncDB, tx, s.DocumentTypes, relId)
InsertWithCtxParallel(syncDB, tx, s.Grid, relId)
esModulesRelId := &InsertId[string]{id: s.ID, fieldName: "system_id", tableName: "es_modules"}
InsertSimpleSliceParallel(syncDB, tx, s.Esmodules, esModulesRelId)
scriptRelId := &InsertId[string]{id: s.ID, fieldName: "system_id", tableName: "scripts"}
InsertSimpleSliceParallel(syncDB, tx, s.Scripts, scriptRelId)
tagsRelId := &InsertId[string]{id: s.ID, fieldName: "system_id", tableName: "tags"}
InsertSimpleSliceParallel(syncDB, tx, s.Tags, tagsRelId)
InsertSliceParallel(syncDB, tx, s.Authors, relId)
InsertSliceParallel(syncDB, tx, s.Media, relId)
InsertSliceParallel(syncDB, tx, s.Styles, relId)
InsertSliceParallel(syncDB, tx, s.Languages, relId)
InsertSliceParallel(syncDB, tx, s.Packs, relId)
InsertSliceParallel(syncDB, tx, s.PackFolders, relId)
return syncDB.Wait()
}
func (s *System) Insert(tx *sqlx.Tx, data *InsertId[string]) error {
if data.query == "" {
return ErrNoQuery
}
args := []any{data.id, s.ID, s.Title, s.Description, s.URL, s.License, s.Bugs,
s.Changelog, s.Version, s.Manifest, s.Download, s.Background,
s.PrimaryTokenAttribute, s.Availability, s.Socket, s.Protected, s.Exclusive,
s.PersistentStorage, s.Locked, s.Owned, s.HasStorage}
_, err := tx.Exec(data.query, args...)
if err != nil {
return err
}
return s.InsertObjects(tx)
}
func (s *System) InsertCtx(ctx context.Context, tx *sqlx.Tx, data *InsertId[string]) error {
if data.query == "" {
return ErrNoQuery
}
args := []any{data.id, s.ID, s.Title, s.Description, s.URL, s.License, s.Bugs,
s.Changelog, s.Version, s.Manifest, s.Download, s.Background,
s.PrimaryTokenAttribute, s.Availability, s.Socket, s.Protected, s.Exclusive,
s.PersistentStorage, s.Locked, s.Owned, s.HasStorage}
_, err := tx.ExecContext(ctx, data.query, args...)
if err != nil {
return err
}
return s.InsertObjects(tx)
} }

View File

@@ -1,5 +1,12 @@
package db package db
import (
"context"
"fmt"
"github.com/jmoiron/sqlx"
)
type CoreUpdate struct { type CoreUpdate struct {
ID uint ID uint
@@ -7,9 +14,46 @@ type CoreUpdate struct {
CanUpdate bool CanUpdate bool
CouldReachWebsite bool CouldReachWebsite bool
SlowResponse bool SlowResponse bool
WillDisableModules bool
Version string Version string
Channel string Channel string
WillDisableModules bool }
func (c *CoreUpdate) Query(data *InsertId[uint]) {
data.query = fmt.Sprintf(`
INSERT INTO core_update (%s, has_update, can_update, could_reach_website, slow_response, will_disable_modules, version, channel)
VALUES ($1, $2, $3, $4, $5, $6, $7, $8)
RETURNING id`, data.fieldName)
}
func (c *CoreUpdate) Insert(tx *sqlx.Tx, data *InsertId[uint]) error {
if data.query == "" {
return ErrNoQuery
}
args := []any{data.id, c.HasUpdate, c.CanUpdate, c.CouldReachWebsite, c.SlowResponse, c.WillDisableModules, c.Version, c.Channel}
err := tx.QueryRowx(data.query, args...).Scan(&c.ID)
if err != nil {
return err
}
return nil
}
func (c *CoreUpdate) InsertCtx(ctx context.Context, tx *sqlx.Tx, data *InsertId[uint]) error {
if data.query == "" {
return ErrNoQuery
}
args := []any{data.id, c.HasUpdate, c.CanUpdate, c.CouldReachWebsite, c.SlowResponse, c.WillDisableModules, c.Version, c.Channel}
err := tx.QueryRowxContext(ctx, data.query, args...).Scan(&c.ID)
if err != nil {
return err
}
return nil
} }
type SystemUpdate struct { type SystemUpdate struct {

View File

@@ -0,0 +1,176 @@
package db
import (
"context"
"errors"
"fmt"
"sync"
"time"
"github.com/jmoiron/sqlx"
)
var (
ErrNoQuery = errors.New("Query has not been set")
)
type AllowedIds interface {
~uint | ~string
}
type InsertId[T AllowedIds] struct {
id T
fieldName string
tableName string
query string
}
type SyncDB struct {
errChan chan error
wg sync.WaitGroup
}
func NewSyncDB() *SyncDB {
return &SyncDB{
wg: sync.WaitGroup{},
errChan: make(chan error),
}
}
func (s *SyncDB) Wait() error {
return WaitSync(&s.wg, s.errChan)
}
func WaitSync(wg *sync.WaitGroup, errChan chan error) error {
wgDone := make(chan struct{})
go func() {
wg.Wait()
close(wgDone)
}()
select {
case <-wgDone:
return nil
case err := <-errChan:
close(wgDone)
return err
}
}
type Insertable[T AllowedIds] interface {
Query(data *InsertId[T])
Insert(tx *sqlx.Tx, relId *InsertId[T]) error
InsertCtx(ctx context.Context, tx *sqlx.Tx, relId *InsertId[T]) error
}
func InsertWithCtx[T AllowedIds, I Insertable[T]](tx *sqlx.Tx, data I, relId *InsertId[T]) error {
ctx, cancel := context.WithTimeout(context.Background(), 3*time.Second)
defer cancel()
data.Query(relId)
return data.InsertCtx(ctx, tx, relId)
}
func InsertWithCtxParallel[T AllowedIds, I Insertable[T]](syncDb *SyncDB, tx *sqlx.Tx, data I, relId *InsertId[T]) {
syncDb.wg.Go(func() {
ctx, cancel := context.WithTimeout(context.Background(), 3*time.Second)
defer cancel()
data.Query(relId)
err := data.InsertCtx(ctx, tx, relId)
if err != nil {
syncDb.errChan <- err
}
})
}
func InsertSlice[T AllowedIds, I Insertable[T]](tx *sqlx.Tx, data []I, relId *InsertId[T]) error {
ctx, cancel := context.WithTimeout(context.Background(), 20*time.Second)
defer cancel()
if len(data) > 0 {
data[0].Query(relId)
}
for i := range data {
err := data[i].InsertCtx(ctx, tx, relId)
if err != nil {
return err
}
}
return nil
}
func InsertSliceParallel[T AllowedIds, I Insertable[T]](syncDb *SyncDB, tx *sqlx.Tx, data []I, relId *InsertId[T]) {
syncDb.wg.Go(func() {
wg := sync.WaitGroup{}
errChan := make(chan error)
defer close(errChan)
var err error
if len(data) > 0 {
data[0].Query(relId)
}
for i := range data {
wg.Go(func() {
ctx, cancel := context.WithTimeout(context.Background(), 3*time.Second)
defer cancel()
err = data[i].InsertCtx(ctx, tx, relId)
if err != nil {
errChan <- err
}
})
}
err = WaitSync(&wg, errChan)
if err != nil {
syncDb.errChan <- err
}
})
}
func InsertSimpleSlice[T AllowedIds, I any](tx *sqlx.Tx, data []I, relId *InsertId[T]) error {
ctx, cancel := context.WithTimeout(context.Background(), 3*time.Second)
defer cancel()
query := fmt.Sprintf(`
INSERT INTO %s (%s, value)
VALUES ($1, $2)`, relId.tableName, relId.fieldName)
for i := range data {
_, err := tx.ExecContext(ctx, query, relId.id, data[i])
if err != nil {
return err
}
}
return nil
}
func InsertSimpleSliceParallel[T AllowedIds, I any](syncDb *SyncDB, tx *sqlx.Tx, data []I, relId *InsertId[T]) {
syncDb.wg.Go(func() {
wg := sync.WaitGroup{}
errChan := make(chan error)
defer close(errChan)
query := fmt.Sprintf(`
INSERT INTO %s (%s, value)
VALUES ($1, $2)`, relId.tableName, relId.fieldName)
for i := range data {
wg.Go(func() {
ctx, cancel := context.WithTimeout(context.Background(), 3*time.Second)
defer cancel()
_, err := tx.ExecContext(ctx, query, relId.id, data[i])
if err != nil {
errChan <- err
}
})
}
err := WaitSync(&wg, errChan)
if err != nil {
syncDb.errChan <- err
}
})
}

View File

@@ -1,20 +1,16 @@
package db package db
import "time" import (
"context"
"fmt"
"time"
"github.com/jmoiron/sqlx"
)
type World struct { type World struct {
ID string ID string
Socket bool
Protected bool
Exclusive bool
PersistentStorage bool
Locked bool
Owned bool
HasStorage bool
Playtime int
Availability int
NextSession time.Time
Title string Title string
Description string Description string
Version string Version string
@@ -24,15 +20,93 @@ type World struct {
CoreVersion string CoreVersion string
SystemVersion string SystemVersion string
LastPlayed string LastPlayed string
Playtime int
Availability int
NextSession time.Time
Socket bool
Protected bool
Exclusive bool
PersistentStorage bool
Locked bool
Owned bool
HasStorage bool
Compatibility Compatibility
Relationships Relationships
Tags []string Tags []string
Scripts []string Scripts []string
Esmodules []string Esmodules []string
Compatibility Compatibility Authors []*Author
Relationships Relationships Media []*Media
Authors []Author Styles []*Style
Media []Media Languages []*Language
Styles []Style Packs []*Pack
Languages []Language PackFolders []*Folder
Packs []Pack }
PackFolders []Folder
func (w *World) Query(data *InsertId[string]) {
data.query = fmt.Sprintf(`
INSERT INTO world (%s, id, title, description, version, system, background, join_theme,
core_version, system_version, last_played, playtime, availability, next_session, socket,
protected, exclusive_, persistent_storage, locked, owned, has_storage)
VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11, $12, $13, $14, $15, $16, $17, $18, $19, $20, $21)`,
data.fieldName)
}
func (w *World) InsertObjects(tx *sqlx.Tx) error {
relId := &InsertId[string]{id: w.ID, fieldName: "world_id"}
syncDB := NewSyncDB()
defer close(syncDB.errChan)
InsertWithCtxParallel(syncDB, tx, w.Compatibility, relId)
InsertWithCtxParallel(syncDB, tx, w.Relationships, relId)
esModulesRelId := &InsertId[string]{id: w.ID, fieldName: "world_id", tableName: "es_modules"}
InsertSimpleSliceParallel(syncDB, tx, w.Esmodules, esModulesRelId)
scriptRelId := &InsertId[string]{id: w.ID, fieldName: "world_id", tableName: "scripts"}
InsertSimpleSliceParallel(syncDB, tx, w.Scripts, scriptRelId)
tagsRelId := &InsertId[string]{id: w.ID, fieldName: "world_id", tableName: "tags"}
InsertSimpleSliceParallel(syncDB, tx, w.Tags, tagsRelId)
InsertSliceParallel(syncDB, tx, w.Authors, relId)
InsertSliceParallel(syncDB, tx, w.Media, relId)
InsertSliceParallel(syncDB, tx, w.Styles, relId)
InsertSliceParallel(syncDB, tx, w.Languages, relId)
InsertSliceParallel(syncDB, tx, w.Packs, relId)
InsertSliceParallel(syncDB, tx, w.PackFolders, relId)
return syncDB.Wait()
}
func (w *World) Insert(tx *sqlx.Tx, data *InsertId[string]) error {
if data.query == "" {
return ErrNoQuery
}
args := []any{data.id, w.ID, w.Title, w.Description, w.Version, w.System, w.Background, w.JoinTheme,
w.CoreVersion, w.SystemVersion, w.LastPlayed, w.Playtime, w.Availability, w.NextSession, w.Socket,
w.Protected, w.Exclusive, w.PersistentStorage, w.Locked, w.Owned, w.HasStorage}
_, err := tx.Exec(data.query, args...)
if err != nil {
return err
}
return w.InsertObjects(tx)
}
func (w *World) InsertCtx(ctx context.Context, tx *sqlx.Tx, data *InsertId[string]) error {
if data.query == "" {
return ErrNoQuery
}
args := []any{data.id, w.ID, w.Title, w.Description, w.Version, w.System, w.Background, w.JoinTheme,
w.CoreVersion, w.SystemVersion, w.LastPlayed, w.Playtime, w.Availability, w.NextSession, w.Socket,
w.Protected, w.Exclusive, w.PersistentStorage, w.Locked, w.Owned, w.HasStorage}
_, err := tx.ExecContext(ctx, data.query, args...)
if err != nil {
return err
}
return w.InsertObjects(tx)
} }

View File

@@ -10,15 +10,19 @@ type Author struct {
// SystemAuthorsFlags SystemAuthorsFlags `json:"flags"` // SystemAuthorsFlags SystemAuthorsFlags `json:"flags"`
} }
func (a *Author) ToDB(dest *db.Author) bool { func (a *Author) ToDB(dest **db.Author) bool {
if dest == nil { if dest == nil {
return false return false
} }
dest.Name = a.Name author := &db.Author{
dest.URL = a.URL Name: a.Name,
dest.Email = a.Email URL: a.URL,
dest.Discord = a.Discord Email: a.Email,
Discord: a.Discord,
}
*dest = author
return true return true
} }

View File

@@ -13,12 +13,12 @@ func (d *DocumentTypes) ToDB(dest *db.DocumentTypes) bool {
return false return false
} }
dest.Data = make([]db.DocumentTypeData, 2) dest.Data = make([]*db.DocumentTypeData, 2)
d.Actor.ToDB(&dest.Data[0]) d.Actor.ToDB(dest.Data[0])
dest.Data[0].Type = "Actor" dest.Data[0].Type = "Actor"
d.Item.ToDB(&dest.Data[1]) d.Item.ToDB(dest.Data[1])
dest.Data[1].Type = "Item" dest.Data[1].Type = "Item"
return true return true

View File

@@ -12,7 +12,10 @@ func (f *Files) ToDB(dest *db.Files) bool {
return false return false
} }
copy(dest.Storages, f.Storages) dest.Storages = make([]db.FilesStorage, len(f.Storages))
for i := range f.Storages {
dest.Storages[i].Storage = f.Storages[i]
}
return true return true
} }

View File

@@ -10,17 +10,20 @@ type Folder struct {
Folders []*Folder `json:"folders,omitempty"` Folders []*Folder `json:"folders,omitempty"`
} }
func (f *Folder) ToDB(dest *db.Folder) bool { func (f *Folder) ToDB(dest **db.Folder) bool {
if dest == nil { if dest == nil {
return false return false
} }
dest.Name = f.Name folder := &db.Folder{
dest.Sorting = f.Sorting Name: f.Name,
dest.Color = f.Color Sorting: f.Sorting,
copy(dest.Packs, f.Packs) Color: f.Color,
}
copy(folder.Packs, f.Packs)
CopySliceToDB(&folder.Folders, f.Folders)
CopySliceToDB(&dest.Folders, f.Folders) *dest = folder
return true return true
} }

View File

@@ -14,20 +14,24 @@ type Grid struct {
Thickness int `json:"thickness,omitempty"` Thickness int `json:"thickness,omitempty"`
} }
func (g *Grid) ToDB(dest *db.Grid) bool { func (g *Grid) ToDB(dest **db.Grid) bool {
if dest == nil { if dest == nil {
return false return false
} }
dest.Type = g.Type grid := &db.Grid{
dest.Size = g.Size Type: g.Type,
dest.Color = g.Color Size: g.Size,
dest.Alpha = g.Alpha Color: g.Color,
dest.Distance = g.Distance Alpha: g.Alpha,
dest.Units = g.Units Distance: g.Distance,
dest.Diagonals = g.Diagonals Units: g.Units,
dest.Style = g.Style Diagonals: g.Diagonals,
dest.Thickness = g.Thickness Style: g.Style,
Thickness: g.Thickness,
}
*dest = grid
return true return true
} }

View File

@@ -10,16 +10,20 @@ type Index struct {
Type string `json:"type"` Type string `json:"type"`
} }
func (i *Index) ToDB(dest *db.Index) bool { func (i *Index) ToDB(dest **db.Index) bool {
if dest == nil { if dest == nil {
return false return false
} }
dest.ID = i.Id index := &db.Index{
dest.Folder = i.Folder ID: i.Id,
dest.Img = i.Img Folder: i.Folder,
dest.Name = i.Name Img: i.Img,
dest.Type = i.Type Name: i.Name,
Type: i.Type,
}
*dest = index
return true return true
} }

View File

@@ -9,14 +9,18 @@ type Language struct {
// SystemLanguagesFlags SystemLanguagesFlags `json:"flags"` // SystemLanguagesFlags SystemLanguagesFlags `json:"flags"`
} }
func (l *Language) ToDB(dest *db.Language) bool { func (l *Language) ToDB(dest **db.Language) bool {
if dest == nil { if dest == nil {
return false return false
} }
dest.Lang = l.Lang lang := &db.Language{
dest.Name = l.Name Lang: l.Lang,
dest.Path = l.Path Name: l.Name,
Path: l.Path,
}
*dest = lang
return true return true
} }
@@ -27,15 +31,19 @@ type SetupLanguage struct {
Modules []*SetupLanguageModule `json:"modules"` Modules []*SetupLanguageModule `json:"modules"`
} }
func (s *SetupLanguage) ToDB(dest *db.SetupLanguage) bool { func (s *SetupLanguage) ToDB(dest **db.SetupLanguage) bool {
if dest == nil { if dest == nil {
return false return false
} }
dest.ID = s.ID lang := &db.SetupLanguage{
dest.Label = s.Label ID: s.ID,
Label: s.Label,
}
CopySliceToDB(&dest.Modules, s.Modules) CopySliceToDB(&lang.Modules, s.Modules)
*dest = lang
return true return true
} }

View File

@@ -8,14 +8,18 @@ type Media struct {
Caption string `json:"caption"` Caption string `json:"caption"`
} }
func (m *Media) ToDB(dest *db.Media) bool { func (m *Media) ToDB(dest **db.Media) bool {
if dest == nil { if dest == nil {
return false return false
} }
dest.Type = m.Type media := &db.Media{
dest.URL = m.URL Type: m.Type,
dest.Caption = m.Caption URL: m.URL,
Caption: m.Caption,
}
*dest = media
return true return true
} }

View File

@@ -44,50 +44,54 @@ type Module struct {
// ModulesFlags ModulesFlags `json:"flags,omitempty"` // ModulesFlags ModulesFlags `json:"flags,omitempty"`
} }
func (m *Module) ToDB(dest *db.Module) bool { func (m *Module) ToDB(dest **db.Module) bool {
if dest == nil { if dest == nil {
return false return false
} }
dest.ID = m.ID module := &db.Module{
dest.Title = m.Title ID: m.ID,
dest.Description = m.Description Title: m.Title,
dest.URL = m.URL Description: m.Description,
dest.License = m.License URL: m.URL,
dest.Readme = m.Readme License: m.License,
dest.Bugs = m.Bugs Readme: m.Readme,
dest.Changelog = m.Changelog Bugs: m.Bugs,
dest.Version = m.Version Changelog: m.Changelog,
dest.Socket = m.Socket Version: m.Version,
dest.Manifest = m.Manifest Socket: m.Socket,
dest.Download = m.Download Manifest: m.Manifest,
dest.Protected = m.Protected Download: m.Download,
dest.Exclusive = m.Exclusive Protected: m.Protected,
dest.PersistentStorage = m.PersistentStorage Exclusive: m.Exclusive,
dest.CoreTranslation = m.CoreTranslation PersistentStorage: m.PersistentStorage,
dest.Library = m.Library CoreTranslation: m.CoreTranslation,
dest.Availability = m.Availability Library: m.Library,
dest.Locked = m.Locked Availability: m.Availability,
dest.Owned = m.Owned Locked: m.Locked,
dest.HasStorage = m.HasStorage Owned: m.Owned,
dest.Active = m.Active HasStorage: m.HasStorage,
Active: m.Active,
}
copy(dest.Scripts, m.Scripts) copy(module.Scripts, m.Scripts)
copy(dest.Esmodules, m.Esmodules) copy(module.Esmodules, m.Esmodules)
copy(dest.Tags, m.Tags) copy(module.Tags, m.Tags)
m.Compatibility.ToDB(&dest.Compatibility) m.Compatibility.ToDB(&module.Compatibility)
m.Relationships.ToDB(&dest.Relationships) m.Relationships.ToDB(&module.Relationships)
m.DocumentTypes.ToDB(&dest.DocumentTypes) m.DocumentTypes.ToDB(&module.DocumentTypes)
wg := sync.WaitGroup{} wg := sync.WaitGroup{}
go CopySliceToDBParallel(&wg, &dest.Authors, m.Authors) go CopySliceToDBParallel(&wg, &module.Authors, m.Authors)
go CopySliceToDBParallel(&wg, &dest.Media, m.Media) go CopySliceToDBParallel(&wg, &module.Media, m.Media)
go CopySliceToDBParallel(&wg, &dest.Styles, m.Styles) go CopySliceToDBParallel(&wg, &module.Styles, m.Styles)
go CopySliceToDBParallel(&wg, &dest.Languages, m.Languages) go CopySliceToDBParallel(&wg, &module.Languages, m.Languages)
go CopySliceToDBParallel(&wg, &dest.Packs, m.Packs) go CopySliceToDBParallel(&wg, &module.Packs, m.Packs)
go CopySliceToDBParallel(&wg, &dest.PackFolders, m.PackFolders) go CopySliceToDBParallel(&wg, &module.PackFolders, m.PackFolders)
wg.Wait() wg.Wait()
*dest = module
return true return true
} }

View File

@@ -32,45 +32,49 @@ type SetupOptions struct {
HotReload bool `json:"hotReload"` HotReload bool `json:"hotReload"`
Language string `json:"language"` Language string `json:"language"`
LocalHostname string `json:"localHostname"` LocalHostname string `json:"localHostname"`
Port int `json:"port"`
ProxySSL bool `json:"proxySSL"`
Telemetry bool `json:"telemetry"`
UpdateChannel string `json:"updateChannel"`
Upnp bool `json:"upnp"`
DeleteNEDB bool `json:"deleteNEDB"`
NoBackups bool `json:"noBackups"`
// PasswordSalt any `json:"passwordSalt"` // PasswordSalt any `json:"passwordSalt"`
Port int `json:"port"`
// Protocol any `json:"protocol"` // Protocol any `json:"protocol"`
// ProxyPort any `json:"proxyPort"` // ProxyPort any `json:"proxyPort"`
ProxySSL bool `json:"proxySSL"`
// RoutePrefix any `json:"routePrefix"` // RoutePrefix any `json:"routePrefix"`
// SslCert any `json:"sslCert"` // SslCert any `json:"sslCert"`
// SslKey any `json:"sslKey"` // SslKey any `json:"sslKey"`
Telemetry bool `json:"telemetry"`
UpdateChannel string `json:"updateChannel"`
Upnp bool `json:"upnp"`
// UpnpLeaseDuration any `json:"upnpLeaseDuration"` // UpnpLeaseDuration any `json:"upnpLeaseDuration"`
// World any `json:"world"` // World any `json:"world"`
DeleteNEDB bool `json:"deleteNEDB"`
// AdminPassword string `json:"adminPassword"` // AdminPassword string `json:"adminPassword"`
NoBackups bool `json:"noBackups"`
} }
func (s *SetupOptions) ToDB(dest *db.SetupOptions) bool { func (s *SetupOptions) ToDB(dest **db.SetupOptions) bool {
if dest == nil { if dest == nil {
return false return false
} }
dest.CompressSocket = s.CompressSocket options := &db.SetupOptions{
dest.CompressStatic = s.CompressStatic CompressSocket: s.CompressSocket,
dest.CSSTheme = s.CSSTheme CompressStatic: s.CompressStatic,
dest.DataPath = s.DataPath CSSTheme: s.CSSTheme,
dest.Fullscreen = s.Fullscreen DataPath: s.DataPath,
dest.Hostname = s.Hostname Fullscreen: s.Fullscreen,
dest.HotReload = s.HotReload Hostname: s.Hostname,
dest.Language = s.Language HotReload: s.HotReload,
dest.LocalHostname = s.LocalHostname Language: s.Language,
dest.Port = s.Port LocalHostname: s.LocalHostname,
dest.ProxySSL = s.ProxySSL Port: s.Port,
dest.Telemetry = s.Telemetry ProxySSL: s.ProxySSL,
dest.UpdateChannel = s.UpdateChannel Telemetry: s.Telemetry,
dest.Upnp = s.Upnp UpdateChannel: s.UpdateChannel,
dest.DeleteNEDB = s.DeleteNEDB Upnp: s.Upnp,
dest.NoBackups = s.NoBackups DeleteNEDB: s.DeleteNEDB,
NoBackups: s.NoBackups,
}
*dest = options
return true return true
} }

View File

@@ -22,27 +22,32 @@ type Pack struct {
// SystemPacksFlags SystemPacksFlags `json:"flags"` // SystemPacksFlags SystemPacksFlags `json:"flags"`
} }
func (p *Pack) ToDB(dest *db.Pack) bool { func (p *Pack) ToDB(dest **db.Pack) bool {
if dest == nil { if dest == nil {
return false return false
} }
dest.Name = p.Name pack := &db.Pack{
dest.Label = p.Label Name: p.Name,
dest.Banner = p.Banner Label: p.Label,
dest.Path = p.Path Banner: p.Banner,
dest.Type = p.Type Path: p.Path,
dest.System = p.System Type: p.Type,
p.Ownership.ToDB(&dest.Ownership) System: p.System,
dest.PackageType = p.PackageType PackageType: p.PackageType,
dest.PackageName = p.PackageName PackageName: p.PackageName,
dest.ID = p.Id ID: p.Id,
}
p.Ownership.ToDB(&pack.Ownership)
wg := sync.WaitGroup{} wg := sync.WaitGroup{}
go CopySliceToDBParallel(&wg, &dest.Index, p.Index) go CopySliceToDBParallel(&wg, &pack.Index, p.Index)
go CopySliceToDBParallel(&wg, &dest.Folders, p.Folders) go CopySliceToDBParallel(&wg, &pack.Folders, p.Folders)
wg.Wait() wg.Wait()
*dest = pack
return true return true
} }
@@ -58,17 +63,21 @@ type PackFolder struct {
// Packs0FoldersFlags any `json:"flags"` // Packs0FoldersFlags any `json:"flags"`
} }
func (p *PackFolder) ToDB(dest *db.PackFolder) bool { func (p *PackFolder) ToDB(dest **db.PackFolder) bool {
if dest == nil { if dest == nil {
return false return false
} }
dest.ID = p.ID packFolder := &db.PackFolder{
dest.Description = p.Description ID: p.ID,
dest.Name = p.Name Description: p.Description,
dest.Sort = p.Sort Name: p.Name,
dest.Sorting = p.Sorting Sort: p.Sort,
dest.Type = p.Type Sorting: p.Sorting,
Type: p.Type,
}
*dest = packFolder
return true return true
} }

View File

@@ -76,15 +76,19 @@ type News struct {
Image string `json:"image"` Image string `json:"image"`
} }
func (n *News) ToDB(dest *db.News) bool { func (n *News) ToDB(dest **db.News) bool {
if dest == nil { if dest == nil {
return false return false
} }
dest.Title = n.Title news := &db.News{
dest.Caption = n.Caption Title: n.Title,
dest.URL = n.Caption Caption: n.Caption,
dest.Image = n.Image URL: n.Caption,
Image: n.Image,
}
*dest = news
return true return true
} }

View File

@@ -6,12 +6,16 @@ type Style struct {
Src string `json:"src"` Src string `json:"src"`
} }
func (s *Style) ToDB(dest *db.Style) bool { func (s *Style) ToDB(dest **db.Style) bool {
if dest == nil { if dest == nil {
return false return false
} }
dest.Src = s.Src style := &db.Style{
Src: s.Src,
}
*dest = style
return true return true
} }

View File

@@ -43,49 +43,53 @@ type System struct {
// SystemFlags SystemFlags `json:"flags"` // SystemFlags SystemFlags `json:"flags"`
} }
func (s *System) ToDB(dest *db.System) bool { func (s *System) ToDB(dest **db.System) bool {
if dest == nil { if dest == nil {
return false return false
} }
dest.ID = s.ID system := &db.System{
dest.Title = s.Title ID: s.ID,
dest.Description = s.Description Title: s.Title,
dest.URL = s.URL Description: s.Description,
dest.License = s.License URL: s.URL,
dest.Bugs = s.Bugs License: s.License,
dest.Changelog = s.Changelog Bugs: s.Bugs,
dest.Version = s.Version Changelog: s.Changelog,
dest.Socket = s.Socket Version: s.Version,
dest.Manifest = s.Manifest Socket: s.Socket,
dest.Download = s.Download Manifest: s.Manifest,
dest.Protected = s.Protected Download: s.Download,
dest.Exclusive = s.Exclusive Protected: s.Protected,
dest.PersistentStorage = s.PersistentStorage Exclusive: s.Exclusive,
dest.Background = s.Background PersistentStorage: s.PersistentStorage,
dest.PrimaryTokenAttribute = s.PrimaryTokenAttribute Background: s.Background,
dest.Availability = s.Availability PrimaryTokenAttribute: s.PrimaryTokenAttribute,
dest.Locked = s.Locked Availability: s.Availability,
dest.Owned = s.Owned Locked: s.Locked,
dest.HasStorage = s.HasStorage Owned: s.Owned,
HasStorage: s.HasStorage,
}
copy(dest.Scripts, s.Scripts) copy(system.Scripts, s.Scripts)
copy(dest.Esmodules, s.Esmodules) copy(system.Esmodules, s.Esmodules)
copy(dest.Tags, s.Tags) copy(system.Tags, s.Tags)
s.Compatibility.ToDB(&dest.Compatibility) s.Compatibility.ToDB(&system.Compatibility)
s.Relationships.ToDB(&dest.Relationships) s.Relationships.ToDB(&system.Relationships)
s.DocumentTypes.ToDB(&dest.DocumentTypes) s.DocumentTypes.ToDB(&system.DocumentTypes)
s.Grid.ToDB(&dest.Grid) s.Grid.ToDB(&system.Grid)
wg := sync.WaitGroup{} wg := sync.WaitGroup{}
go CopySliceToDBParallel(&wg, &dest.Authors, s.Authors) go CopySliceToDBParallel(&wg, &system.Authors, s.Authors)
go CopySliceToDBParallel(&wg, &dest.Media, s.Media) go CopySliceToDBParallel(&wg, &system.Media, s.Media)
go CopySliceToDBParallel(&wg, &dest.Styles, s.Styles) go CopySliceToDBParallel(&wg, &system.Styles, s.Styles)
go CopySliceToDBParallel(&wg, &dest.Languages, s.Languages) go CopySliceToDBParallel(&wg, &system.Languages, s.Languages)
go CopySliceToDBParallel(&wg, &dest.Packs, s.Packs) go CopySliceToDBParallel(&wg, &system.Packs, s.Packs)
go CopySliceToDBParallel(&wg, &dest.PackFolders, s.PackFolders) go CopySliceToDBParallel(&wg, &system.PackFolders, s.PackFolders)
wg.Wait() wg.Wait()
*dest = system
return true return true
} }

View File

@@ -28,13 +28,13 @@ func HotbarToDB(dest *[]db.UserHotbar, src map[int]string) {
} }
} }
func PackageWarningsToDB(dest *[]db.PackageWarning, src map[string]PackageWarningsData) { func PackageWarningsToDB(dest *[]*db.PackageWarning, src map[string]PackageWarningsData) {
*dest = make([]db.PackageWarning, len(src)) *dest = make([]*db.PackageWarning, len(src))
i := 0 i := 0
for k, v := range src { for k, v := range src {
(*dest)[i].Key = k (*dest)[i].Key = k
v.ToDB(&(*dest)[i].Value) v.ToDB((*dest)[i].Value)
i++ i++
} }
} }

View File

@@ -43,48 +43,52 @@ type World struct {
// Flags any `json:"flags"` // Flags any `json:"flags"`
} }
func (w *World) ToDB(dest *db.World) bool { func (w *World) ToDB(dest **db.World) bool {
if dest == nil { if dest == nil {
return false return false
} }
dest.ID = w.ID world := &db.World{
dest.Title = w.Title ID: w.ID,
dest.Description = w.Description Title: w.Title,
dest.Version = w.Version Description: w.Description,
dest.Socket = w.Socket Version: w.Version,
dest.Protected = w.Protected Socket: w.Socket,
dest.Exclusive = w.Exclusive Protected: w.Protected,
dest.PersistentStorage = w.PersistentStorage Exclusive: w.Exclusive,
dest.System = w.System PersistentStorage: w.PersistentStorage,
dest.Background = w.Background System: w.System,
dest.JoinTheme = w.JoinTheme Background: w.Background,
dest.CoreVersion = w.CoreVersion JoinTheme: w.JoinTheme,
dest.SystemVersion = w.SystemVersion CoreVersion: w.CoreVersion,
dest.LastPlayed = w.LastPlayed SystemVersion: w.SystemVersion,
dest.Playtime = w.Playtime LastPlayed: w.LastPlayed,
dest.NextSession = w.NextSession Playtime: w.Playtime,
dest.Availability = w.Availability NextSession: w.NextSession,
dest.Locked = w.Locked Availability: w.Availability,
dest.Owned = w.Owned Locked: w.Locked,
dest.HasStorage = w.HasStorage Owned: w.Owned,
HasStorage: w.HasStorage,
}
copy(dest.Scripts, w.Scripts) copy(world.Scripts, w.Scripts)
copy(dest.Esmodules, w.Esmodules) copy(world.Esmodules, w.Esmodules)
copy(dest.Tags, w.Tags) copy(world.Tags, w.Tags)
w.Compatibility.ToDB(&dest.Compatibility) w.Compatibility.ToDB(&world.Compatibility)
w.Relationships.ToDB(&dest.Relationships) w.Relationships.ToDB(&world.Relationships)
wg := sync.WaitGroup{} wg := sync.WaitGroup{}
go CopySliceToDBParallel(&wg, &dest.Authors, w.Authors) go CopySliceToDBParallel(&wg, &world.Authors, w.Authors)
go CopySliceToDBParallel(&wg, &dest.Media, w.Media) go CopySliceToDBParallel(&wg, &world.Media, w.Media)
go CopySliceToDBParallel(&wg, &dest.Styles, w.Styles) go CopySliceToDBParallel(&wg, &world.Styles, w.Styles)
go CopySliceToDBParallel(&wg, &dest.Languages, w.Languages) go CopySliceToDBParallel(&wg, &world.Languages, w.Languages)
go CopySliceToDBParallel(&wg, &dest.Packs, w.Packs) go CopySliceToDBParallel(&wg, &world.Packs, w.Packs)
go CopySliceToDBParallel(&wg, &dest.PackFolders, w.PackFolders) go CopySliceToDBParallel(&wg, &world.PackFolders, w.PackFolders)
wg.Wait() wg.Wait()
*dest = world
return true return true
} }

View File

@@ -1,7 +1,6 @@
package transport package transport
import ( import (
"database/sql"
"log/slog" "log/slog"
"sync" "sync"
"time" "time"
@@ -10,6 +9,7 @@ import (
"gitea.local.lab/Lbenedar/foundry_helper_service/internal/foundry/requests" "gitea.local.lab/Lbenedar/foundry_helper_service/internal/foundry/requests"
"gitea.local.lab/Lbenedar/foundry_helper_service/internal/foundry/types" "gitea.local.lab/Lbenedar/foundry_helper_service/internal/foundry/types"
"github.com/gorilla/websocket" "github.com/gorilla/websocket"
"github.com/jmoiron/sqlx"
) )
type FoundryTransport struct { type FoundryTransport struct {
@@ -32,7 +32,7 @@ type FoundryTransport struct {
Logger *slog.Logger Logger *slog.Logger
} }
func NewFoundryTransport(dbConn *sql.DB, logger *slog.Logger, httpConfig *requests.FoundryHttpRequest) *FoundryTransport { func NewFoundryTransport(dbConn *sqlx.DB, logger *slog.Logger, httpConfig *requests.FoundryHttpRequest) *FoundryTransport {
return &FoundryTransport{ return &FoundryTransport{
CurrWsId: 0, CurrWsId: 0,
ExchangeChan: types.ExchangeChannels{ ExchangeChan: types.ExchangeChannels{