feat:移除了弹窗,服务器添加sls
This commit is contained in:
158
packages/app-lib/migrations/20240711194701_init.sql
Normal file
158
packages/app-lib/migrations/20240711194701_init.sql
Normal file
@ -0,0 +1,158 @@
|
||||
CREATE TABLE settings (
|
||||
id INTEGER NOT NULL CHECK (id = 0),
|
||||
|
||||
max_concurrent_downloads INTEGER NOT NULL DEFAULT 10,
|
||||
max_concurrent_writes INTEGER NOT NULL DEFAULT 10,
|
||||
|
||||
theme TEXT NOT NULL DEFAULT 'dark',
|
||||
default_page TEXT NOT NULL DEFAULT 'home',
|
||||
collapsed_navigation INTEGER NOT NULL DEFAULT TRUE,
|
||||
advanced_rendering INTEGER NOT NULL DEFAULT TRUE,
|
||||
native_decorations INTEGER NOT NULL DEFAULT FALSE,
|
||||
|
||||
telemetry INTEGER NOT NULL DEFAULT FALSE,
|
||||
discord_rpc INTEGER NOT NULL DEFAULT TRUE,
|
||||
developer_mode INTEGER NOT NULL DEFAULT FALSE,
|
||||
|
||||
onboarded INTEGER NOT NULL DEFAULT FALSE,
|
||||
|
||||
-- array of strings
|
||||
extra_launch_args JSONB NOT NULL,
|
||||
-- array of (string, string)
|
||||
custom_env_vars JSONB NOT NULL,
|
||||
mc_memory_max INTEGER NOT NULL DEFAULT 2048,
|
||||
mc_force_fullscreen INTEGER NOT NULL DEFAULT FALSE,
|
||||
mc_game_resolution_x INTEGER NOT NULL DEFAULT 854,
|
||||
mc_game_resolution_y INTEGER NOT NULL DEFAULT 480,
|
||||
|
||||
hide_on_process_start INTEGER NOT NULL DEFAULT FALSE,
|
||||
|
||||
hook_pre_launch TEXT NULL,
|
||||
hook_wrapper TEXT NULL,
|
||||
hook_post_exit TEXT NULL,
|
||||
|
||||
custom_dir TEXT NULL,
|
||||
prev_custom_dir TEXT NULL,
|
||||
migrated INTEGER NOT NULL DEFAULT FALSE,
|
||||
|
||||
PRIMARY KEY (id)
|
||||
);
|
||||
|
||||
INSERT INTO settings (id, extra_launch_args, custom_env_vars) VALUES (0, jsonb_array(), jsonb_array());
|
||||
|
||||
CREATE TABLE java_versions (
|
||||
major_version INTEGER NOT NULL,
|
||||
full_version TEXT NOT NULL,
|
||||
architecture TEXT NOT NULL,
|
||||
path TEXT NOT NULL,
|
||||
|
||||
PRIMARY KEY (major_version)
|
||||
);
|
||||
|
||||
CREATE TABLE minecraft_users (
|
||||
uuid TEXT NOT NULL,
|
||||
active INTEGER NOT NULL DEFAULT FALSE,
|
||||
username TEXT NOT NULL,
|
||||
access_token TEXT NOT NULL,
|
||||
refresh_token TEXT NOT NULL,
|
||||
expires INTEGER NOT NULL,
|
||||
|
||||
PRIMARY KEY (uuid)
|
||||
);
|
||||
CREATE UNIQUE INDEX minecraft_users_active ON minecraft_users(active);
|
||||
|
||||
CREATE TABLE minecraft_device_tokens (
|
||||
id INTEGER NOT NULL CHECK (id = 0),
|
||||
|
||||
uuid TEXT NOT NULL,
|
||||
private_key TEXT NOT NULL,
|
||||
x TEXT NOT NULL,
|
||||
y TEXT NOT NULL,
|
||||
issue_instant INTEGER NOT NULL,
|
||||
not_after INTEGER NOT NULL,
|
||||
token TEXT NOT NULL,
|
||||
display_claims JSONB NOT NULL,
|
||||
|
||||
PRIMARY KEY (id)
|
||||
);
|
||||
|
||||
CREATE TABLE modrinth_users (
|
||||
id TEXT NOT NULL,
|
||||
active INTEGER NOT NULL DEFAULT FALSE,
|
||||
session_id TEXT NOT NULL,
|
||||
expires INTEGER NOT NULL,
|
||||
|
||||
PRIMARY KEY (id)
|
||||
);
|
||||
CREATE UNIQUE INDEX modrinth_users_active ON modrinth_users(active);
|
||||
|
||||
CREATE TABLE cache (
|
||||
id TEXT NOT NULL,
|
||||
data_type TEXT NOT NULL,
|
||||
alias TEXT NULL,
|
||||
|
||||
data JSONB NULL,
|
||||
expires INTEGER NOT NULL,
|
||||
|
||||
UNIQUE (data_type, alias),
|
||||
PRIMARY KEY (id, data_type)
|
||||
);
|
||||
|
||||
CREATE TABLE profiles (
|
||||
path TEXT NOT NULL,
|
||||
install_stage TEXT NOT NULL,
|
||||
|
||||
name TEXT NOT NULL,
|
||||
icon_path TEXT NULL,
|
||||
|
||||
game_version TEXT NOT NULL,
|
||||
mod_loader TEXT NOT NULL,
|
||||
mod_loader_version TEXT NULL,
|
||||
|
||||
-- array of strings
|
||||
groups JSONB NOT NULL,
|
||||
|
||||
linked_project_id TEXT NULL,
|
||||
linked_version_id TEXT NULL,
|
||||
locked INTEGER NULL,
|
||||
|
||||
created INTEGER NOT NULL,
|
||||
modified INTEGER NOT NULL,
|
||||
last_played INTEGER NULL,
|
||||
|
||||
submitted_time_played INTEGER NOT NULL DEFAULT 0,
|
||||
recent_time_played INTEGER NOT NULL DEFAULT 0,
|
||||
|
||||
override_java_path TEXT NULL,
|
||||
|
||||
-- array of strings
|
||||
override_extra_launch_args JSONB NOT NULL,
|
||||
-- array of (string, string)
|
||||
override_custom_env_vars JSONB NOT NULL,
|
||||
|
||||
override_mc_memory_max INTEGER NULL,
|
||||
override_mc_force_fullscreen INTEGER NULL,
|
||||
override_mc_game_resolution_x INTEGER NULL,
|
||||
override_mc_game_resolution_y INTEGER NULL,
|
||||
|
||||
override_hook_pre_launch TEXT NULL,
|
||||
override_hook_wrapper TEXT NULL,
|
||||
override_hook_post_exit TEXT NULL,
|
||||
|
||||
|
||||
PRIMARY KEY (path)
|
||||
);
|
||||
|
||||
CREATE TABLE processes (
|
||||
pid INTEGER NOT NULL,
|
||||
start_time INTEGER NOT NULL,
|
||||
name TEXT NOT NULL,
|
||||
executable TEXT NOT NULL,
|
||||
profile_path TEXT NOT NULL,
|
||||
post_exit_command TEXT NULL,
|
||||
|
||||
UNIQUE (pid),
|
||||
PRIMARY KEY (pid),
|
||||
FOREIGN KEY (profile_path) REFERENCES profiles(path)
|
||||
);
|
||||
CREATE INDEX processes_profile_path ON processes(profile_path);
|
||||
@ -0,0 +1,2 @@
|
||||
DROP INDEX modrinth_users_active;
|
||||
DROP INDEX minecraft_users_active;
|
||||
@ -0,0 +1 @@
|
||||
ALTER TABLE settings ADD COLUMN personalized_ads INTEGER NOT NULL DEFAULT TRUE;
|
||||
@ -0,0 +1,2 @@
|
||||
ALTER TABLE settings ADD COLUMN toggle_sidebar INTEGER NOT NULL DEFAULT FALSE;
|
||||
ALTER TABLE settings ADD COLUMN feature_flags JSONB NOT NULL default '{}';
|
||||
@ -0,0 +1 @@
|
||||
ALTER TABLE profiles ADD COLUMN protocol_version INTEGER NULL
|
||||
10
packages/app-lib/migrations/20250408181656_add-join-log.sql
Normal file
10
packages/app-lib/migrations/20250408181656_add-join-log.sql
Normal file
@ -0,0 +1,10 @@
|
||||
CREATE TABLE join_log (
|
||||
profile_path TEXT NOT NULL,
|
||||
host TEXT NOT NULL,
|
||||
port INTEGER NOT NULL,
|
||||
join_time INTEGER NOT NULL,
|
||||
|
||||
PRIMARY KEY (profile_path, host, port),
|
||||
FOREIGN KEY (profile_path) REFERENCES profiles(path) ON DELETE CASCADE
|
||||
);
|
||||
CREATE INDEX join_log_profile_path ON join_log(profile_path);
|
||||
80
packages/app-lib/migrations/20250413162050_skin-selector.sql
Normal file
80
packages/app-lib/migrations/20250413162050_skin-selector.sql
Normal file
@ -0,0 +1,80 @@
|
||||
CREATE TABLE default_minecraft_capes (
|
||||
minecraft_user_uuid TEXT NOT NULL,
|
||||
id TEXT NOT NULL,
|
||||
|
||||
PRIMARY KEY (minecraft_user_uuid, id)
|
||||
);
|
||||
|
||||
-- Emulate a ON UPDATE CASCADE foreign key constraint for the user UUID on the default_minecraft_capes table,
|
||||
-- but allowing deletion of the user UUID in the minecraft_users table. This allows the application to temporarily
|
||||
-- keep skin state around for logged-out users, allowing them to retain their skins under the right conditions
|
||||
CREATE TRIGGER default_minecraft_capes_user_uuid_insert_check
|
||||
BEFORE INSERT ON default_minecraft_capes FOR EACH ROW
|
||||
BEGIN
|
||||
SELECT CASE WHEN NOT EXISTS (
|
||||
SELECT 1 FROM minecraft_users WHERE uuid = NEW.minecraft_user_uuid
|
||||
) THEN RAISE(ABORT, 'Cannot add a default cape for an unknown Minecraft user UUID') END;
|
||||
END;
|
||||
|
||||
CREATE TRIGGER default_minecraft_capes_user_uuid_update_check
|
||||
BEFORE UPDATE ON default_minecraft_capes FOR EACH ROW
|
||||
BEGIN
|
||||
SELECT CASE WHEN NOT EXISTS (
|
||||
SELECT 1 FROM minecraft_users WHERE uuid = NEW.minecraft_user_uuid
|
||||
) THEN RAISE(ABORT, 'Cannot change a default cape to refer to an unknown Minecraft user UUID') END;
|
||||
END;
|
||||
|
||||
CREATE TRIGGER default_minecraft_capes_user_uuid_update_cascade
|
||||
AFTER UPDATE OF uuid ON minecraft_users FOR EACH ROW
|
||||
BEGIN
|
||||
UPDATE default_minecraft_capes SET minecraft_user_uuid = NEW.uuid WHERE minecraft_user_uuid = OLD.uuid;
|
||||
END;
|
||||
|
||||
CREATE TABLE custom_minecraft_skins (
|
||||
minecraft_user_uuid TEXT NOT NULL,
|
||||
texture_key TEXT NOT NULL,
|
||||
variant TEXT NOT NULL CHECK (variant IN ('CLASSIC', 'SLIM', 'UNKNOWN')),
|
||||
cape_id TEXT,
|
||||
|
||||
PRIMARY KEY (minecraft_user_uuid, texture_key, variant, cape_id),
|
||||
FOREIGN KEY (texture_key) REFERENCES custom_minecraft_skin_textures(texture_key)
|
||||
ON DELETE CASCADE ON UPDATE CASCADE
|
||||
);
|
||||
|
||||
-- Similar partial foreign key emulation as above
|
||||
CREATE TRIGGER custom_minecraft_skins_user_uuid_insert_check
|
||||
BEFORE INSERT ON custom_minecraft_skins FOR EACH ROW
|
||||
BEGIN
|
||||
SELECT CASE WHEN NOT EXISTS (
|
||||
SELECT 1 FROM minecraft_users WHERE uuid = NEW.minecraft_user_uuid
|
||||
) THEN RAISE(ABORT, 'Cannot add a custom skin for an unknown Minecraft user UUID') END;
|
||||
END;
|
||||
|
||||
CREATE TRIGGER custom_minecraft_skins_user_uuid_update_check
|
||||
BEFORE UPDATE ON custom_minecraft_skins FOR EACH ROW
|
||||
BEGIN
|
||||
SELECT CASE WHEN NOT EXISTS (
|
||||
SELECT 1 FROM minecraft_users WHERE uuid = NEW.minecraft_user_uuid
|
||||
) THEN RAISE(ABORT, 'Cannot change a custom skin to refer to an unknown Minecraft user UUID') END;
|
||||
END;
|
||||
|
||||
CREATE TRIGGER custom_minecraft_skins_user_uuid_update_cascade
|
||||
AFTER UPDATE OF uuid ON minecraft_users FOR EACH ROW
|
||||
BEGIN
|
||||
UPDATE custom_minecraft_skins SET minecraft_user_uuid = NEW.uuid WHERE minecraft_user_uuid = OLD.uuid;
|
||||
END;
|
||||
|
||||
CREATE TABLE custom_minecraft_skin_textures (
|
||||
texture_key TEXT NOT NULL,
|
||||
texture PNG BLOB NOT NULL,
|
||||
|
||||
PRIMARY KEY (texture_key)
|
||||
);
|
||||
|
||||
CREATE TRIGGER custom_minecraft_skin_texture_delete_cleanup
|
||||
AFTER DELETE ON custom_minecraft_skins FOR EACH ROW
|
||||
BEGIN
|
||||
DELETE FROM custom_minecraft_skin_textures WHERE texture_key NOT IN (
|
||||
SELECT texture_key FROM custom_minecraft_skins
|
||||
);
|
||||
END;
|
||||
@ -0,0 +1 @@
|
||||
ALTER TABLE profiles ADD COLUMN launcher_feature_version TEXT NOT NULL DEFAULT 'none'
|
||||
@ -0,0 +1,10 @@
|
||||
CREATE TABLE attached_world_data (
|
||||
profile_path TEXT NOT NULL,
|
||||
world_type TEXT CHECK ( world_type in ('singleplayer', 'server') ) NOT NULL,
|
||||
world_id TEXT NOT NULL,
|
||||
display_status TEXT NOT NULL DEFAULT 'normal',
|
||||
|
||||
PRIMARY KEY (profile_path, world_type, world_id),
|
||||
FOREIGN KEY (profile_path) REFERENCES profiles(path) ON DELETE CASCADE
|
||||
);
|
||||
CREATE INDEX attached_world_data_profile_path ON attached_world_data(profile_path);
|
||||
@ -0,0 +1 @@
|
||||
ALTER TABLE settings ADD COLUMN hide_nametag_skins_page INTEGER NOT NULL DEFAULT 0 CHECK (hide_nametag_skins_page IN (0, 1));
|
||||
@ -0,0 +1,6 @@
|
||||
ALTER TABLE settings
|
||||
ADD COLUMN skipped_update TEXT NULL;
|
||||
ALTER TABLE settings
|
||||
ADD COLUMN pending_update_toast_for_version TEXT NULL;
|
||||
ALTER TABLE settings
|
||||
ADD COLUMN auto_download_updates INT NULL;
|
||||
@ -0,0 +1 @@
|
||||
ALTER TABLE settings ADD COLUMN version INTEGER NOT NULL DEFAULT 1;
|
||||
@ -0,0 +1,2 @@
|
||||
-- Add migration script here
|
||||
ALTER TABLE settings ADD COLUMN locale TEXT NOT NULL DEFAULT '';
|
||||
@ -0,0 +1,2 @@
|
||||
ALTER TABLE attached_world_data ADD COLUMN project_id TEXT;
|
||||
ALTER TABLE attached_world_data ADD COLUMN content_kind TEXT;
|
||||
@ -0,0 +1,13 @@
|
||||
DROP TABLE IF EXISTS default_minecraft_capes;
|
||||
|
||||
-- Keep only one saved skin per Minecraft account and texture.
|
||||
-- variant and cape_id are settings on that saved skin, not part of the skin identity.
|
||||
DELETE FROM custom_minecraft_skins
|
||||
WHERE rowid NOT IN (
|
||||
SELECT MAX(rowid)
|
||||
FROM custom_minecraft_skins
|
||||
GROUP BY minecraft_user_uuid, texture_key
|
||||
);
|
||||
|
||||
CREATE UNIQUE INDEX custom_minecraft_skins_one_per_texture
|
||||
ON custom_minecraft_skins (minecraft_user_uuid, texture_key);
|
||||
@ -0,0 +1,3 @@
|
||||
DROP TRIGGER IF EXISTS default_minecraft_capes_user_uuid_insert_check;
|
||||
DROP TRIGGER IF EXISTS default_minecraft_capes_user_uuid_update_check;
|
||||
DROP TRIGGER IF EXISTS default_minecraft_capes_user_uuid_update_cascade;
|
||||
@ -0,0 +1,2 @@
|
||||
ALTER TABLE profiles
|
||||
ADD COLUMN preferred_update_channel TEXT NOT NULL DEFAULT 'release';
|
||||
@ -0,0 +1,13 @@
|
||||
ALTER TABLE custom_minecraft_skins
|
||||
ADD COLUMN display_order INTEGER NOT NULL DEFAULT 0;
|
||||
|
||||
UPDATE custom_minecraft_skins
|
||||
SET display_order = (
|
||||
SELECT COUNT(*)
|
||||
FROM custom_minecraft_skins AS previous
|
||||
WHERE previous.minecraft_user_uuid = custom_minecraft_skins.minecraft_user_uuid
|
||||
AND previous.rowid <= custom_minecraft_skins.rowid
|
||||
) - 1;
|
||||
|
||||
CREATE INDEX custom_minecraft_skins_user_display_order
|
||||
ON custom_minecraft_skins (minecraft_user_uuid, display_order);
|
||||
@ -0,0 +1,376 @@
|
||||
CREATE TABLE instances (
|
||||
id TEXT NOT NULL,
|
||||
path TEXT NOT NULL,
|
||||
applied_content_set_id TEXT NULL,
|
||||
|
||||
install_stage TEXT NOT NULL,
|
||||
launcher_feature_version TEXT NOT NULL,
|
||||
update_channel TEXT NOT NULL DEFAULT 'release',
|
||||
|
||||
name TEXT NOT NULL,
|
||||
icon_path TEXT NULL,
|
||||
|
||||
created INTEGER NOT NULL,
|
||||
modified INTEGER NOT NULL,
|
||||
last_played INTEGER NULL,
|
||||
|
||||
submitted_time_played INTEGER NOT NULL DEFAULT 0,
|
||||
recent_time_played INTEGER NOT NULL DEFAULT 0,
|
||||
|
||||
PRIMARY KEY (id),
|
||||
UNIQUE (path)
|
||||
);
|
||||
|
||||
CREATE INDEX instances_path ON instances(path);
|
||||
CREATE INDEX instances_applied_content_set_id
|
||||
ON instances(applied_content_set_id);
|
||||
|
||||
CREATE TABLE instance_links (
|
||||
instance_id TEXT NOT NULL,
|
||||
link_kind TEXT NOT NULL,
|
||||
|
||||
modrinth_project_id TEXT NULL,
|
||||
modrinth_version_id TEXT NULL,
|
||||
|
||||
server_project_id TEXT NULL,
|
||||
|
||||
content_project_id TEXT NULL,
|
||||
content_version_id TEXT NULL,
|
||||
|
||||
hosting_server_id TEXT NULL,
|
||||
hosting_instance_ids JSONB NULL,
|
||||
hosting_active_instance_id TEXT NULL,
|
||||
|
||||
shared_instance_id TEXT NULL,
|
||||
|
||||
PRIMARY KEY (instance_id),
|
||||
FOREIGN KEY (instance_id) REFERENCES instances(id) ON DELETE CASCADE
|
||||
);
|
||||
|
||||
CREATE INDEX instance_links_link_kind ON instance_links(link_kind);
|
||||
CREATE INDEX instance_links_modrinth_project_id
|
||||
ON instance_links(modrinth_project_id);
|
||||
CREATE INDEX instance_links_server_project_id
|
||||
ON instance_links(server_project_id);
|
||||
CREATE INDEX instance_links_hosting_server_id
|
||||
ON instance_links(hosting_server_id);
|
||||
CREATE INDEX instance_links_hosting_active_instance_id
|
||||
ON instance_links(hosting_active_instance_id);
|
||||
CREATE INDEX instance_links_shared_instance_id
|
||||
ON instance_links(shared_instance_id);
|
||||
|
||||
CREATE TABLE instance_groups (
|
||||
instance_id TEXT NOT NULL,
|
||||
group_name TEXT NOT NULL,
|
||||
|
||||
PRIMARY KEY (instance_id, group_name),
|
||||
FOREIGN KEY (instance_id) REFERENCES instances(id) ON DELETE CASCADE
|
||||
);
|
||||
|
||||
CREATE INDEX instance_groups_group_name ON instance_groups(group_name);
|
||||
|
||||
CREATE TABLE instance_launch_overrides (
|
||||
instance_id TEXT NOT NULL,
|
||||
overrides JSONB NOT NULL,
|
||||
|
||||
PRIMARY KEY (instance_id),
|
||||
FOREIGN KEY (instance_id) REFERENCES instances(id) ON DELETE CASCADE
|
||||
);
|
||||
|
||||
CREATE TABLE instance_content_sets (
|
||||
id TEXT NOT NULL,
|
||||
instance_id TEXT NOT NULL,
|
||||
|
||||
name TEXT NOT NULL,
|
||||
source_kind TEXT NOT NULL,
|
||||
status TEXT NOT NULL,
|
||||
|
||||
game_version TEXT NOT NULL,
|
||||
protocol_version INTEGER NULL,
|
||||
loader TEXT NOT NULL,
|
||||
loader_version TEXT NULL,
|
||||
|
||||
created INTEGER NOT NULL,
|
||||
modified INTEGER NOT NULL,
|
||||
|
||||
PRIMARY KEY (id),
|
||||
FOREIGN KEY (instance_id) REFERENCES instances(id) ON DELETE CASCADE
|
||||
);
|
||||
|
||||
CREATE INDEX instance_content_sets_instance_id
|
||||
ON instance_content_sets(instance_id);
|
||||
|
||||
CREATE TABLE instance_content_set_remote_refs (
|
||||
content_set_id TEXT NOT NULL,
|
||||
ref_type TEXT NOT NULL,
|
||||
ref_id TEXT NOT NULL,
|
||||
|
||||
PRIMARY KEY (content_set_id, ref_type),
|
||||
FOREIGN KEY (content_set_id)
|
||||
REFERENCES instance_content_sets(id)
|
||||
ON DELETE CASCADE
|
||||
);
|
||||
|
||||
CREATE INDEX instance_content_set_remote_refs_ref
|
||||
ON instance_content_set_remote_refs(ref_type, ref_id);
|
||||
|
||||
CREATE TABLE instance_content_set_sync_state (
|
||||
content_set_id TEXT NOT NULL,
|
||||
provider TEXT NOT NULL,
|
||||
|
||||
applied_update_id TEXT NULL,
|
||||
latest_available_update_id TEXT NULL,
|
||||
checked_at INTEGER NULL,
|
||||
status TEXT NOT NULL,
|
||||
|
||||
PRIMARY KEY (content_set_id),
|
||||
FOREIGN KEY (content_set_id)
|
||||
REFERENCES instance_content_sets(id)
|
||||
ON DELETE CASCADE
|
||||
);
|
||||
|
||||
CREATE INDEX instance_content_set_sync_state_provider
|
||||
ON instance_content_set_sync_state(provider);
|
||||
|
||||
CREATE INDEX instance_content_set_sync_state_latest_available_update_id
|
||||
ON instance_content_set_sync_state(latest_available_update_id);
|
||||
|
||||
CREATE TABLE instance_files (
|
||||
id TEXT NOT NULL,
|
||||
instance_id TEXT NOT NULL,
|
||||
|
||||
relative_path TEXT NOT NULL,
|
||||
file_name TEXT NOT NULL,
|
||||
enabled INTEGER NOT NULL,
|
||||
|
||||
sha1 TEXT NOT NULL,
|
||||
size INTEGER NOT NULL,
|
||||
missing INTEGER NOT NULL DEFAULT 0,
|
||||
|
||||
added_at INTEGER NOT NULL,
|
||||
modified_at INTEGER NOT NULL,
|
||||
|
||||
PRIMARY KEY (id),
|
||||
UNIQUE (instance_id, relative_path),
|
||||
FOREIGN KEY (instance_id) REFERENCES instances(id) ON DELETE CASCADE
|
||||
);
|
||||
|
||||
CREATE INDEX instance_files_instance_id ON instance_files(instance_id);
|
||||
CREATE INDEX instance_files_sha1 ON instance_files(sha1);
|
||||
CREATE INDEX instance_files_missing ON instance_files(missing);
|
||||
|
||||
CREATE TABLE instance_content_entries (
|
||||
id TEXT NOT NULL,
|
||||
instance_id TEXT NOT NULL,
|
||||
content_set_id TEXT NOT NULL,
|
||||
file_id TEXT NULL,
|
||||
|
||||
project_type TEXT NOT NULL,
|
||||
project_id TEXT NULL,
|
||||
version_id TEXT NULL,
|
||||
|
||||
source_kind TEXT NOT NULL,
|
||||
server_requirement TEXT NOT NULL,
|
||||
client_requirement TEXT NOT NULL,
|
||||
enabled INTEGER NOT NULL DEFAULT 1,
|
||||
|
||||
added_at INTEGER NOT NULL,
|
||||
modified_at INTEGER NOT NULL,
|
||||
|
||||
PRIMARY KEY (id),
|
||||
FOREIGN KEY (instance_id) REFERENCES instances(id) ON DELETE CASCADE,
|
||||
FOREIGN KEY (content_set_id)
|
||||
REFERENCES instance_content_sets(id)
|
||||
ON DELETE CASCADE,
|
||||
FOREIGN KEY (file_id) REFERENCES instance_files(id) ON DELETE SET NULL
|
||||
);
|
||||
|
||||
CREATE INDEX instance_content_entries_instance_id
|
||||
ON instance_content_entries(instance_id);
|
||||
CREATE INDEX instance_content_entries_content_set_id
|
||||
ON instance_content_entries(content_set_id);
|
||||
CREATE INDEX instance_content_entries_file_id
|
||||
ON instance_content_entries(file_id);
|
||||
CREATE INDEX instance_content_entries_project_id
|
||||
ON instance_content_entries(project_id);
|
||||
CREATE INDEX instance_content_entries_version_id
|
||||
ON instance_content_entries(version_id);
|
||||
CREATE INDEX instance_content_entries_source_kind
|
||||
ON instance_content_entries(source_kind);
|
||||
|
||||
CREATE TABLE instance_content_update_checks (
|
||||
content_entry_id TEXT NOT NULL,
|
||||
|
||||
update_channel TEXT NOT NULL,
|
||||
update_version_id TEXT NULL,
|
||||
checked_at INTEGER NOT NULL,
|
||||
|
||||
PRIMARY KEY (content_entry_id),
|
||||
FOREIGN KEY (content_entry_id)
|
||||
REFERENCES instance_content_entries(id)
|
||||
ON DELETE CASCADE
|
||||
);
|
||||
|
||||
CREATE INDEX instance_content_update_checks_update_version_id
|
||||
ON instance_content_update_checks(update_version_id);
|
||||
|
||||
INSERT INTO instances (
|
||||
id,
|
||||
path,
|
||||
applied_content_set_id,
|
||||
install_stage,
|
||||
launcher_feature_version,
|
||||
update_channel,
|
||||
name,
|
||||
icon_path,
|
||||
created,
|
||||
modified,
|
||||
last_played,
|
||||
submitted_time_played,
|
||||
recent_time_played
|
||||
)
|
||||
SELECT
|
||||
'legacy:' || path,
|
||||
path,
|
||||
'legacy:' || path || ':default',
|
||||
install_stage,
|
||||
launcher_feature_version,
|
||||
preferred_update_channel,
|
||||
name,
|
||||
icon_path,
|
||||
created,
|
||||
modified,
|
||||
last_played,
|
||||
submitted_time_played,
|
||||
recent_time_played
|
||||
FROM profiles;
|
||||
|
||||
INSERT INTO instance_content_sets (
|
||||
id,
|
||||
instance_id,
|
||||
name,
|
||||
source_kind,
|
||||
status,
|
||||
game_version,
|
||||
protocol_version,
|
||||
loader,
|
||||
loader_version,
|
||||
created,
|
||||
modified
|
||||
)
|
||||
SELECT
|
||||
'legacy:' || path || ':default',
|
||||
'legacy:' || path,
|
||||
'Default',
|
||||
CASE
|
||||
WHEN linked_project_id IS NOT NULL
|
||||
AND linked_version_id IS NOT NULL
|
||||
AND linked_version_id != ''
|
||||
THEN 'modrinth_modpack'
|
||||
WHEN linked_project_id IS NOT NULL
|
||||
AND (linked_version_id IS NULL OR linked_version_id = '')
|
||||
THEN 'server_project'
|
||||
ELSE 'local'
|
||||
END,
|
||||
'available',
|
||||
game_version,
|
||||
protocol_version,
|
||||
mod_loader,
|
||||
mod_loader_version,
|
||||
created,
|
||||
modified
|
||||
FROM profiles;
|
||||
|
||||
INSERT INTO instance_links (
|
||||
instance_id,
|
||||
link_kind,
|
||||
modrinth_project_id,
|
||||
modrinth_version_id,
|
||||
server_project_id,
|
||||
content_project_id,
|
||||
content_version_id,
|
||||
hosting_server_id,
|
||||
hosting_instance_ids,
|
||||
hosting_active_instance_id,
|
||||
shared_instance_id
|
||||
)
|
||||
SELECT
|
||||
'legacy:' || path,
|
||||
CASE
|
||||
WHEN linked_project_id IS NULL
|
||||
THEN 'unmanaged'
|
||||
WHEN linked_version_id IS NULL OR linked_version_id = ''
|
||||
THEN 'server_project'
|
||||
ELSE 'modrinth_modpack'
|
||||
END,
|
||||
CASE
|
||||
WHEN linked_version_id IS NOT NULL AND linked_version_id != ''
|
||||
THEN linked_project_id
|
||||
ELSE NULL
|
||||
END,
|
||||
CASE
|
||||
WHEN linked_version_id IS NOT NULL AND linked_version_id != ''
|
||||
THEN linked_version_id
|
||||
ELSE NULL
|
||||
END,
|
||||
CASE
|
||||
WHEN linked_project_id IS NOT NULL
|
||||
AND (linked_version_id IS NULL OR linked_version_id = '')
|
||||
THEN linked_project_id
|
||||
ELSE NULL
|
||||
END,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL
|
||||
FROM profiles;
|
||||
|
||||
INSERT OR IGNORE INTO instance_groups (instance_id, group_name)
|
||||
SELECT
|
||||
'legacy:' || profiles.path,
|
||||
json_each.value
|
||||
FROM profiles, json_each(profiles.groups);
|
||||
|
||||
INSERT INTO instance_launch_overrides (
|
||||
instance_id,
|
||||
overrides
|
||||
)
|
||||
SELECT
|
||||
'legacy:' || path,
|
||||
jsonb(json_object(
|
||||
'java_path', override_java_path,
|
||||
'extra_launch_args', json(CASE
|
||||
WHEN json_type(override_extra_launch_args) = 'null' THEN 'null'
|
||||
ELSE json(override_extra_launch_args)
|
||||
END),
|
||||
'custom_env_vars', json(CASE
|
||||
WHEN json_type(override_custom_env_vars) = 'null' THEN 'null'
|
||||
ELSE json(override_custom_env_vars)
|
||||
END),
|
||||
'memory', json(CASE
|
||||
WHEN override_mc_memory_max IS NULL THEN 'null'
|
||||
ELSE json_object('maximum', override_mc_memory_max)
|
||||
END),
|
||||
'force_fullscreen', json(CASE
|
||||
WHEN override_mc_force_fullscreen IS NULL THEN 'null'
|
||||
WHEN override_mc_force_fullscreen = 0 THEN 'false'
|
||||
ELSE 'true'
|
||||
END),
|
||||
'game_resolution', json(CASE
|
||||
WHEN override_mc_game_resolution_x IS NULL
|
||||
OR override_mc_game_resolution_y IS NULL
|
||||
THEN 'null'
|
||||
ELSE json_array(
|
||||
override_mc_game_resolution_x,
|
||||
override_mc_game_resolution_y
|
||||
)
|
||||
END),
|
||||
'hooks', json_object(
|
||||
'pre_launch', COALESCE(override_hook_pre_launch, ''),
|
||||
'wrapper', COALESCE(override_hook_wrapper, ''),
|
||||
'post_exit', COALESCE(override_hook_post_exit, '')
|
||||
)
|
||||
))
|
||||
FROM profiles;
|
||||
@ -0,0 +1,129 @@
|
||||
CREATE TEMP TABLE finish_instance_profile_migration_validation (
|
||||
error_count INTEGER NOT NULL CHECK (error_count = 0)
|
||||
);
|
||||
|
||||
INSERT INTO finish_instance_profile_migration_validation (error_count)
|
||||
SELECT COUNT(*)
|
||||
FROM profiles
|
||||
LEFT JOIN instances ON instances.path = profiles.path
|
||||
WHERE instances.id IS NULL;
|
||||
|
||||
INSERT INTO finish_instance_profile_migration_validation (error_count)
|
||||
SELECT COUNT(*)
|
||||
FROM instances
|
||||
LEFT JOIN instance_content_sets
|
||||
ON instance_content_sets.id = instances.applied_content_set_id
|
||||
AND instance_content_sets.instance_id = instances.id
|
||||
WHERE instances.applied_content_set_id IS NULL
|
||||
OR instance_content_sets.id IS NULL;
|
||||
|
||||
DROP TABLE finish_instance_profile_migration_validation;
|
||||
|
||||
DROP INDEX processes_profile_path;
|
||||
ALTER TABLE processes RENAME TO processes_old;
|
||||
|
||||
CREATE TABLE processes (
|
||||
pid INTEGER NOT NULL,
|
||||
start_time INTEGER NOT NULL,
|
||||
name TEXT NOT NULL,
|
||||
executable TEXT NOT NULL,
|
||||
instance_id TEXT NOT NULL,
|
||||
post_exit_command TEXT NULL,
|
||||
|
||||
UNIQUE (pid),
|
||||
PRIMARY KEY (pid),
|
||||
FOREIGN KEY (instance_id) REFERENCES instances(id) ON DELETE CASCADE
|
||||
);
|
||||
|
||||
INSERT INTO processes (
|
||||
pid,
|
||||
start_time,
|
||||
name,
|
||||
executable,
|
||||
instance_id,
|
||||
post_exit_command
|
||||
)
|
||||
SELECT
|
||||
processes_old.pid,
|
||||
processes_old.start_time,
|
||||
processes_old.name,
|
||||
processes_old.executable,
|
||||
instances.id,
|
||||
processes_old.post_exit_command
|
||||
FROM processes_old
|
||||
JOIN instances ON instances.path = processes_old.profile_path;
|
||||
|
||||
DROP TABLE processes_old;
|
||||
|
||||
CREATE INDEX processes_instance_id ON processes(instance_id);
|
||||
|
||||
DROP INDEX join_log_profile_path;
|
||||
ALTER TABLE join_log RENAME TO join_log_old;
|
||||
|
||||
CREATE TABLE join_log (
|
||||
instance_id TEXT NOT NULL,
|
||||
host TEXT NOT NULL,
|
||||
port INTEGER NOT NULL,
|
||||
join_time INTEGER NOT NULL,
|
||||
|
||||
PRIMARY KEY (instance_id, host, port),
|
||||
FOREIGN KEY (instance_id) REFERENCES instances(id) ON DELETE CASCADE
|
||||
);
|
||||
|
||||
INSERT INTO join_log (
|
||||
instance_id,
|
||||
host,
|
||||
port,
|
||||
join_time
|
||||
)
|
||||
SELECT
|
||||
instances.id,
|
||||
join_log_old.host,
|
||||
join_log_old.port,
|
||||
join_log_old.join_time
|
||||
FROM join_log_old
|
||||
JOIN instances ON instances.path = join_log_old.profile_path;
|
||||
|
||||
DROP TABLE join_log_old;
|
||||
|
||||
CREATE INDEX join_log_instance_id ON join_log(instance_id);
|
||||
|
||||
DROP INDEX attached_world_data_profile_path;
|
||||
ALTER TABLE attached_world_data RENAME TO attached_world_data_old;
|
||||
|
||||
CREATE TABLE attached_world_data (
|
||||
instance_id TEXT NOT NULL,
|
||||
world_type TEXT CHECK ( world_type in ('singleplayer', 'server') ) NOT NULL,
|
||||
world_id TEXT NOT NULL,
|
||||
display_status TEXT NOT NULL DEFAULT 'normal',
|
||||
project_id TEXT NULL,
|
||||
content_kind TEXT NULL,
|
||||
|
||||
PRIMARY KEY (instance_id, world_type, world_id),
|
||||
FOREIGN KEY (instance_id) REFERENCES instances(id) ON DELETE CASCADE
|
||||
);
|
||||
|
||||
INSERT INTO attached_world_data (
|
||||
instance_id,
|
||||
world_type,
|
||||
world_id,
|
||||
display_status,
|
||||
project_id,
|
||||
content_kind
|
||||
)
|
||||
SELECT
|
||||
instances.id,
|
||||
attached_world_data_old.world_type,
|
||||
attached_world_data_old.world_id,
|
||||
attached_world_data_old.display_status,
|
||||
attached_world_data_old.project_id,
|
||||
attached_world_data_old.content_kind
|
||||
FROM attached_world_data_old
|
||||
JOIN instances ON instances.path = attached_world_data_old.profile_path;
|
||||
|
||||
DROP TABLE attached_world_data_old;
|
||||
|
||||
CREATE INDEX attached_world_data_instance_id
|
||||
ON attached_world_data(instance_id);
|
||||
|
||||
DROP TABLE profiles;
|
||||
@ -0,0 +1,7 @@
|
||||
CREATE TABLE app_metadata (
|
||||
key TEXT NOT NULL,
|
||||
value TEXT NOT NULL,
|
||||
updated_at INTEGER NOT NULL DEFAULT (unixepoch()),
|
||||
|
||||
PRIMARY KEY (key)
|
||||
);
|
||||
19
packages/app-lib/migrations/20260624120000_install-jobs.sql
Normal file
19
packages/app-lib/migrations/20260624120000_install-jobs.sql
Normal file
@ -0,0 +1,19 @@
|
||||
CREATE TABLE install_jobs (
|
||||
id TEXT NOT NULL PRIMARY KEY,
|
||||
instance_id TEXT NULL,
|
||||
kind TEXT NOT NULL,
|
||||
|
||||
status TEXT NOT NULL,
|
||||
state JSONB NOT NULL,
|
||||
|
||||
created INTEGER NOT NULL,
|
||||
modified INTEGER NOT NULL,
|
||||
finished INTEGER NULL,
|
||||
|
||||
dismissed INTEGER NOT NULL DEFAULT 0,
|
||||
FOREIGN KEY (instance_id) REFERENCES instances(id) ON DELETE SET NULL
|
||||
);
|
||||
|
||||
CREATE INDEX install_jobs_instance_id ON install_jobs(instance_id);
|
||||
CREATE INDEX install_jobs_status ON install_jobs(status);
|
||||
CREATE INDEX install_jobs_finished ON install_jobs(finished);
|
||||
@ -0,0 +1,21 @@
|
||||
ALTER TABLE instance_links ADD COLUMN imported_name TEXT NULL;
|
||||
ALTER TABLE instance_links ADD COLUMN imported_version_number TEXT NULL;
|
||||
ALTER TABLE instance_links ADD COLUMN imported_filename TEXT NULL;
|
||||
|
||||
UPDATE instance_links
|
||||
SET
|
||||
link_kind = 'imported_modpack',
|
||||
imported_name = (
|
||||
SELECT instances.name
|
||||
FROM instances
|
||||
WHERE instances.id = instance_links.instance_id
|
||||
)
|
||||
WHERE
|
||||
link_kind = 'unmanaged'
|
||||
AND EXISTS (
|
||||
SELECT 1
|
||||
FROM instance_content_entries
|
||||
WHERE
|
||||
instance_content_entries.instance_id = instance_links.instance_id
|
||||
AND instance_content_entries.source_kind = 'imported_modpack'
|
||||
);
|
||||
@ -0,0 +1,12 @@
|
||||
UPDATE instances
|
||||
SET
|
||||
submitted_time_played = CASE
|
||||
WHEN submitted_time_played < 0 THEN 0
|
||||
ELSE submitted_time_played
|
||||
END,
|
||||
recent_time_played = CASE
|
||||
WHEN recent_time_played < 0 THEN 0
|
||||
ELSE recent_time_played
|
||||
END
|
||||
WHERE submitted_time_played < 0
|
||||
OR recent_time_played < 0;
|
||||
@ -0,0 +1,3 @@
|
||||
UPDATE settings
|
||||
SET telemetry = FALSE,
|
||||
personalized_ads = FALSE;
|
||||
@ -0,0 +1 @@
|
||||
ALTER TABLE settings ADD COLUMN accent_color TEXT NOT NULL DEFAULT 'pink';
|
||||
@ -0,0 +1,3 @@
|
||||
ALTER TABLE minecraft_users
|
||||
ADD COLUMN account_type TEXT NOT NULL DEFAULT 'microsoft'
|
||||
CHECK (account_type IN ('microsoft', 'offline'));
|
||||
@ -0,0 +1,33 @@
|
||||
CREATE TABLE offline_minecraft_skins (
|
||||
minecraft_user_uuid TEXT NOT NULL,
|
||||
texture_key TEXT NOT NULL,
|
||||
variant TEXT NOT NULL CHECK (variant IN ('CLASSIC', 'SLIM', 'UNKNOWN')),
|
||||
|
||||
PRIMARY KEY (minecraft_user_uuid)
|
||||
);
|
||||
|
||||
-- Keep offline skin selections when an account is temporarily removed, matching
|
||||
-- the saved-skin tables, while still rejecting selections for unknown users.
|
||||
CREATE TRIGGER offline_minecraft_skins_user_uuid_insert_check
|
||||
BEFORE INSERT ON offline_minecraft_skins FOR EACH ROW
|
||||
BEGIN
|
||||
SELECT CASE WHEN NOT EXISTS (
|
||||
SELECT 1 FROM minecraft_users WHERE uuid = NEW.minecraft_user_uuid
|
||||
) THEN RAISE(ABORT, 'Cannot add an offline skin for an unknown Minecraft user UUID') END;
|
||||
END;
|
||||
|
||||
CREATE TRIGGER offline_minecraft_skins_user_uuid_update_check
|
||||
BEFORE UPDATE ON offline_minecraft_skins FOR EACH ROW
|
||||
BEGIN
|
||||
SELECT CASE WHEN NOT EXISTS (
|
||||
SELECT 1 FROM minecraft_users WHERE uuid = NEW.minecraft_user_uuid
|
||||
) THEN RAISE(ABORT, 'Cannot change an offline skin to refer to an unknown Minecraft user UUID') END;
|
||||
END;
|
||||
|
||||
CREATE TRIGGER offline_minecraft_skins_user_uuid_update_cascade
|
||||
AFTER UPDATE OF uuid ON minecraft_users FOR EACH ROW
|
||||
BEGIN
|
||||
UPDATE offline_minecraft_skins
|
||||
SET minecraft_user_uuid = NEW.uuid
|
||||
WHERE minecraft_user_uuid = OLD.uuid;
|
||||
END;
|
||||
@ -0,0 +1,3 @@
|
||||
ALTER TABLE settings ADD COLUMN custom_background_path TEXT NULL;
|
||||
ALTER TABLE settings ADD COLUMN custom_background_blur INTEGER NOT NULL DEFAULT 12 CHECK (custom_background_blur BETWEEN 0 AND 40);
|
||||
ALTER TABLE settings ADD COLUMN custom_background_opacity INTEGER NOT NULL DEFAULT 65 CHECK (custom_background_opacity BETWEEN 10 AND 100);
|
||||
24
packages/app-lib/migrations/20260714120000_translation.sql
Normal file
24
packages/app-lib/migrations/20260714120000_translation.sql
Normal file
@ -0,0 +1,24 @@
|
||||
CREATE TABLE translation_settings (
|
||||
id INTEGER NOT NULL CHECK (id = 0),
|
||||
provider TEXT NOT NULL DEFAULT 'microsoft',
|
||||
target_language TEXT NOT NULL DEFAULT '',
|
||||
mode TEXT NOT NULL DEFAULT 'bilingual',
|
||||
auto_translate INTEGER NOT NULL DEFAULT FALSE,
|
||||
style TEXT NOT NULL DEFAULT 'weakened',
|
||||
openai_base_url TEXT NOT NULL DEFAULT 'https://api.openai.com/v1',
|
||||
openai_model TEXT NOT NULL DEFAULT 'gpt-4o-mini',
|
||||
openai_api_key TEXT NULL,
|
||||
deeplx_base_url TEXT NOT NULL DEFAULT 'https://api.deeplx.org/{{apiKey}}/translate',
|
||||
deeplx_api_key TEXT NULL,
|
||||
PRIMARY KEY (id)
|
||||
);
|
||||
|
||||
INSERT INTO translation_settings (id) VALUES (0);
|
||||
|
||||
CREATE TABLE translation_cache (
|
||||
key TEXT NOT NULL PRIMARY KEY,
|
||||
translation TEXT NOT NULL,
|
||||
created_at INTEGER NOT NULL
|
||||
);
|
||||
|
||||
CREATE INDEX translation_cache_created_at ON translation_cache(created_at);
|
||||
@ -0,0 +1,49 @@
|
||||
ALTER TABLE instance_links
|
||||
ADD COLUMN curseforge_project_id INTEGER NULL;
|
||||
|
||||
ALTER TABLE instance_links
|
||||
ADD COLUMN curseforge_file_id INTEGER NULL;
|
||||
|
||||
CREATE INDEX instance_links_curseforge_project_id
|
||||
ON instance_links(curseforge_project_id);
|
||||
|
||||
CREATE TABLE instance_content_provider_refs (
|
||||
content_entry_id TEXT NOT NULL,
|
||||
provider TEXT NOT NULL,
|
||||
project_id TEXT NOT NULL,
|
||||
version_id TEXT NULL,
|
||||
primary_ref INTEGER NOT NULL DEFAULT 0,
|
||||
|
||||
PRIMARY KEY (content_entry_id, provider),
|
||||
FOREIGN KEY (content_entry_id)
|
||||
REFERENCES instance_content_entries(id)
|
||||
ON DELETE CASCADE,
|
||||
CHECK (provider IN ('modrinth', 'curseforge')),
|
||||
CHECK (primary_ref IN (0, 1))
|
||||
);
|
||||
|
||||
CREATE INDEX instance_content_provider_refs_project
|
||||
ON instance_content_provider_refs(provider, project_id);
|
||||
|
||||
CREATE INDEX instance_content_provider_refs_version
|
||||
ON instance_content_provider_refs(provider, version_id);
|
||||
|
||||
CREATE UNIQUE INDEX instance_content_provider_refs_primary
|
||||
ON instance_content_provider_refs(content_entry_id)
|
||||
WHERE primary_ref = 1;
|
||||
|
||||
INSERT OR IGNORE INTO instance_content_provider_refs (
|
||||
content_entry_id,
|
||||
provider,
|
||||
project_id,
|
||||
version_id,
|
||||
primary_ref
|
||||
)
|
||||
SELECT
|
||||
id,
|
||||
'modrinth',
|
||||
project_id,
|
||||
version_id,
|
||||
1
|
||||
FROM instance_content_entries
|
||||
WHERE project_id IS NOT NULL;
|
||||
@ -0,0 +1,30 @@
|
||||
ALTER TABLE install_jobs ADD COLUMN provider TEXT NULL;
|
||||
ALTER TABLE install_jobs ADD COLUMN retry_of TEXT NULL;
|
||||
ALTER TABLE install_jobs ADD COLUMN files_total INTEGER NULL;
|
||||
ALTER TABLE install_jobs ADD COLUMN files_completed INTEGER NOT NULL DEFAULT 0;
|
||||
ALTER TABLE install_jobs ADD COLUMN bytes_total INTEGER NULL;
|
||||
ALTER TABLE install_jobs ADD COLUMN bytes_downloaded INTEGER NOT NULL DEFAULT 0;
|
||||
|
||||
CREATE TABLE install_job_items (
|
||||
id TEXT NOT NULL,
|
||||
job_id TEXT NOT NULL,
|
||||
name TEXT NOT NULL,
|
||||
project_id TEXT NULL,
|
||||
version_id TEXT NULL,
|
||||
item_type TEXT NULL,
|
||||
status TEXT NOT NULL,
|
||||
url TEXT NULL,
|
||||
bytes_total INTEGER NULL,
|
||||
bytes_downloaded INTEGER NOT NULL DEFAULT 0,
|
||||
error TEXT NULL,
|
||||
manual_url TEXT NULL,
|
||||
created INTEGER NOT NULL,
|
||||
modified INTEGER NOT NULL,
|
||||
finished INTEGER NULL,
|
||||
PRIMARY KEY (job_id, id),
|
||||
FOREIGN KEY (job_id) REFERENCES install_jobs(id) ON DELETE CASCADE
|
||||
);
|
||||
|
||||
CREATE INDEX install_jobs_provider ON install_jobs(provider);
|
||||
CREATE INDEX install_job_items_job_id ON install_job_items(job_id);
|
||||
CREATE INDEX install_job_items_status ON install_job_items(status);
|
||||
@ -0,0 +1,81 @@
|
||||
DROP TRIGGER custom_minecraft_skins_user_uuid_insert_check;
|
||||
DROP TRIGGER custom_minecraft_skins_user_uuid_update_check;
|
||||
DROP TRIGGER custom_minecraft_skins_user_uuid_update_cascade;
|
||||
DROP TRIGGER offline_minecraft_skins_user_uuid_insert_check;
|
||||
DROP TRIGGER offline_minecraft_skins_user_uuid_update_check;
|
||||
DROP TRIGGER offline_minecraft_skins_user_uuid_update_cascade;
|
||||
|
||||
CREATE TABLE minecraft_users_yggdrasil (
|
||||
uuid TEXT NOT NULL,
|
||||
active INTEGER NOT NULL DEFAULT FALSE,
|
||||
username TEXT NOT NULL,
|
||||
access_token TEXT NOT NULL,
|
||||
refresh_token TEXT NOT NULL,
|
||||
expires INTEGER NOT NULL,
|
||||
account_type TEXT NOT NULL DEFAULT 'microsoft'
|
||||
CHECK (account_type IN ('microsoft', 'offline', 'yggdrasil')),
|
||||
yggdrasil_api_root TEXT NOT NULL DEFAULT '',
|
||||
yggdrasil_server_name TEXT NOT NULL DEFAULT '',
|
||||
yggdrasil_login TEXT NOT NULL DEFAULT '',
|
||||
yggdrasil_client_token TEXT NOT NULL DEFAULT '',
|
||||
|
||||
PRIMARY KEY (uuid)
|
||||
);
|
||||
|
||||
INSERT INTO minecraft_users_yggdrasil (
|
||||
uuid, active, username, access_token, refresh_token, expires, account_type
|
||||
)
|
||||
SELECT
|
||||
uuid, active, username, access_token, refresh_token, expires, account_type
|
||||
FROM minecraft_users;
|
||||
|
||||
DROP TABLE minecraft_users;
|
||||
ALTER TABLE minecraft_users_yggdrasil RENAME TO minecraft_users;
|
||||
|
||||
CREATE TRIGGER custom_minecraft_skins_user_uuid_insert_check
|
||||
BEFORE INSERT ON custom_minecraft_skins FOR EACH ROW
|
||||
BEGIN
|
||||
SELECT CASE WHEN NOT EXISTS (
|
||||
SELECT 1 FROM minecraft_users WHERE uuid = NEW.minecraft_user_uuid
|
||||
) THEN RAISE(ABORT, 'Cannot add a custom skin for an unknown Minecraft user UUID') END;
|
||||
END;
|
||||
|
||||
CREATE TRIGGER custom_minecraft_skins_user_uuid_update_check
|
||||
BEFORE UPDATE ON custom_minecraft_skins FOR EACH ROW
|
||||
BEGIN
|
||||
SELECT CASE WHEN NOT EXISTS (
|
||||
SELECT 1 FROM minecraft_users WHERE uuid = NEW.minecraft_user_uuid
|
||||
) THEN RAISE(ABORT, 'Cannot change a custom skin to refer to an unknown Minecraft user UUID') END;
|
||||
END;
|
||||
|
||||
CREATE TRIGGER custom_minecraft_skins_user_uuid_update_cascade
|
||||
AFTER UPDATE OF uuid ON minecraft_users FOR EACH ROW
|
||||
BEGIN
|
||||
UPDATE custom_minecraft_skins
|
||||
SET minecraft_user_uuid = NEW.uuid
|
||||
WHERE minecraft_user_uuid = OLD.uuid;
|
||||
END;
|
||||
|
||||
CREATE TRIGGER offline_minecraft_skins_user_uuid_insert_check
|
||||
BEFORE INSERT ON offline_minecraft_skins FOR EACH ROW
|
||||
BEGIN
|
||||
SELECT CASE WHEN NOT EXISTS (
|
||||
SELECT 1 FROM minecraft_users WHERE uuid = NEW.minecraft_user_uuid
|
||||
) THEN RAISE(ABORT, 'Cannot add an offline skin for an unknown Minecraft user UUID') END;
|
||||
END;
|
||||
|
||||
CREATE TRIGGER offline_minecraft_skins_user_uuid_update_check
|
||||
BEFORE UPDATE ON offline_minecraft_skins FOR EACH ROW
|
||||
BEGIN
|
||||
SELECT CASE WHEN NOT EXISTS (
|
||||
SELECT 1 FROM minecraft_users WHERE uuid = NEW.minecraft_user_uuid
|
||||
) THEN RAISE(ABORT, 'Cannot change an offline skin to refer to an unknown Minecraft user UUID') END;
|
||||
END;
|
||||
|
||||
CREATE TRIGGER offline_minecraft_skins_user_uuid_update_cascade
|
||||
AFTER UPDATE OF uuid ON minecraft_users FOR EACH ROW
|
||||
BEGIN
|
||||
UPDATE offline_minecraft_skins
|
||||
SET minecraft_user_uuid = NEW.uuid
|
||||
WHERE minecraft_user_uuid = OLD.uuid;
|
||||
END;
|
||||
@ -0,0 +1,3 @@
|
||||
ALTER TABLE settings ADD COLUMN use_minecraft_mirror INTEGER NOT NULL DEFAULT FALSE;
|
||||
ALTER TABLE settings ADD COLUMN use_modrinth_mirror INTEGER NOT NULL DEFAULT FALSE;
|
||||
ALTER TABLE settings ADD COLUMN use_curseforge_mirror INTEGER NOT NULL DEFAULT TRUE;
|
||||
@ -0,0 +1,3 @@
|
||||
UPDATE settings
|
||||
SET use_modrinth_mirror = TRUE
|
||||
WHERE use_modrinth_mirror = FALSE;
|
||||
@ -0,0 +1,50 @@
|
||||
ALTER TABLE settings ADD COLUMN auto_concurrent_downloads INTEGER NOT NULL DEFAULT TRUE;
|
||||
ALTER TABLE settings
|
||||
ADD COLUMN minecraft_metadata_source TEXT NOT NULL DEFAULT 'auto' CHECK (
|
||||
minecraft_metadata_source IN ('auto', 'official_only', 'mirror_preferred')
|
||||
);
|
||||
ALTER TABLE settings
|
||||
ADD COLUMN minecraft_file_source TEXT NOT NULL DEFAULT 'auto' CHECK (
|
||||
minecraft_file_source IN ('auto', 'official_only', 'mirror_preferred')
|
||||
);
|
||||
ALTER TABLE settings
|
||||
ADD COLUMN modrinth_source TEXT NOT NULL DEFAULT 'auto' CHECK (
|
||||
modrinth_source IN ('auto', 'official_only', 'mirror_preferred')
|
||||
);
|
||||
ALTER TABLE settings
|
||||
ADD COLUMN curseforge_source TEXT NOT NULL DEFAULT 'auto' CHECK (
|
||||
curseforge_source IN ('auto', 'official_only', 'mirror_preferred')
|
||||
);
|
||||
|
||||
UPDATE settings
|
||||
SET
|
||||
auto_concurrent_downloads = TRUE,
|
||||
max_concurrent_downloads = MIN(MAX(max_concurrent_downloads, 1), 64),
|
||||
minecraft_metadata_source = CASE
|
||||
WHEN use_minecraft_mirror = FALSE
|
||||
AND use_modrinth_mirror = TRUE
|
||||
AND use_curseforge_mirror = TRUE THEN 'auto'
|
||||
WHEN use_minecraft_mirror = TRUE THEN 'mirror_preferred'
|
||||
ELSE 'official_only'
|
||||
END,
|
||||
minecraft_file_source = CASE
|
||||
WHEN use_minecraft_mirror = FALSE
|
||||
AND use_modrinth_mirror = TRUE
|
||||
AND use_curseforge_mirror = TRUE THEN 'auto'
|
||||
WHEN use_minecraft_mirror = TRUE THEN 'mirror_preferred'
|
||||
ELSE 'official_only'
|
||||
END,
|
||||
modrinth_source = CASE
|
||||
WHEN use_minecraft_mirror = FALSE
|
||||
AND use_modrinth_mirror = TRUE
|
||||
AND use_curseforge_mirror = TRUE THEN 'auto'
|
||||
WHEN use_modrinth_mirror = TRUE THEN 'mirror_preferred'
|
||||
ELSE 'official_only'
|
||||
END,
|
||||
curseforge_source = CASE
|
||||
WHEN use_minecraft_mirror = FALSE
|
||||
AND use_modrinth_mirror = TRUE
|
||||
AND use_curseforge_mirror = TRUE THEN 'auto'
|
||||
WHEN use_curseforge_mirror = TRUE THEN 'mirror_preferred'
|
||||
ELSE 'official_only'
|
||||
END;
|
||||
@ -0,0 +1,2 @@
|
||||
ALTER TABLE install_job_items ADD COLUMN attempt INTEGER NULL;
|
||||
ALTER TABLE install_job_items ADD COLUMN max_attempts INTEGER NULL;
|
||||
@ -0,0 +1,6 @@
|
||||
UPDATE settings
|
||||
SET
|
||||
minecraft_metadata_source = 'auto',
|
||||
minecraft_file_source = 'auto',
|
||||
modrinth_source = 'auto',
|
||||
curseforge_source = 'auto';
|
||||
@ -0,0 +1,2 @@
|
||||
UPDATE settings
|
||||
SET max_concurrent_downloads = MIN(MAX(max_concurrent_downloads, 1), 256);
|
||||
@ -0,0 +1,5 @@
|
||||
ALTER TABLE settings ADD COLUMN onboarding_version INTEGER NOT NULL DEFAULT 0;
|
||||
ALTER TABLE settings ADD COLUMN onboarding_instance_tour_completed INTEGER NOT NULL DEFAULT TRUE;
|
||||
|
||||
UPDATE settings
|
||||
SET onboarding_instance_tour_completed = CASE WHEN onboarded = 1 THEN TRUE ELSE FALSE END;
|
||||
@ -0,0 +1,10 @@
|
||||
CREATE TABLE discovered_javas (
|
||||
path TEXT NOT NULL PRIMARY KEY,
|
||||
major_version INTEGER NOT NULL,
|
||||
full_version TEXT NOT NULL,
|
||||
architecture TEXT NOT NULL,
|
||||
file_size INTEGER NOT NULL,
|
||||
file_mtime_ms INTEGER NOT NULL
|
||||
);
|
||||
|
||||
CREATE INDEX discovered_javas_major_version ON discovered_javas (major_version);
|
||||
@ -0,0 +1,2 @@
|
||||
ALTER TABLE instances
|
||||
ADD COLUMN symlink_target TEXT;
|
||||
@ -0,0 +1 @@
|
||||
ALTER TABLE settings ADD COLUMN sidebar_instance_count INTEGER NOT NULL DEFAULT 0;
|
||||
@ -0,0 +1,6 @@
|
||||
-- Add local_mod_data column to instance_files for storing manually
|
||||
-- extracted mod metadata (fabric.mod.json / quilt.mod.json / mods.toml
|
||||
-- / neoforge.mods.toml / mcmod.info) when Modrinth hash lookup fails.
|
||||
|
||||
ALTER TABLE instance_files
|
||||
ADD COLUMN local_mod_data TEXT NULL;
|
||||
@ -0,0 +1 @@
|
||||
ALTER TABLE settings ADD COLUMN mc_memory_auto INTEGER NOT NULL DEFAULT FALSE;
|
||||
@ -0,0 +1 @@
|
||||
ALTER TABLE settings ADD COLUMN mc_memory_optimize INTEGER NOT NULL DEFAULT FALSE;
|
||||
@ -0,0 +1 @@
|
||||
ALTER TABLE translation_settings ADD COLUMN openai_system_prompt TEXT NOT NULL DEFAULT '';
|
||||
@ -0,0 +1 @@
|
||||
ALTER TABLE settings ADD COLUMN auto_set_java_high_performance_mode INTEGER NOT NULL DEFAULT TRUE;
|
||||
@ -0,0 +1,2 @@
|
||||
ALTER TABLE settings ADD COLUMN transparent_background INTEGER NOT NULL DEFAULT FALSE;
|
||||
ALTER TABLE settings ADD COLUMN transparent_background_opacity INTEGER NOT NULL DEFAULT 55;
|
||||
@ -0,0 +1 @@
|
||||
ALTER TABLE settings ADD COLUMN transparent_background_blur INTEGER NOT NULL DEFAULT FALSE;
|
||||
@ -0,0 +1,16 @@
|
||||
CREATE TABLE IF NOT EXISTS java_versions_new (
|
||||
major_version INTEGER NOT NULL,
|
||||
full_version TEXT NOT NULL,
|
||||
architecture TEXT NOT NULL,
|
||||
path TEXT NOT NULL PRIMARY KEY,
|
||||
distribution TEXT
|
||||
);
|
||||
|
||||
INSERT OR REPLACE INTO java_versions_new (major_version, full_version, architecture, path, distribution)
|
||||
SELECT major_version, full_version, architecture, path, NULL FROM java_versions
|
||||
GROUP BY path;
|
||||
|
||||
DROP TABLE IF EXISTS java_versions;
|
||||
ALTER TABLE java_versions_new RENAME TO java_versions;
|
||||
|
||||
CREATE INDEX IF NOT EXISTS idx_java_versions_major_version ON java_versions(major_version);
|
||||
@ -0,0 +1 @@
|
||||
ALTER TABLE discovered_javas ADD COLUMN distribution TEXT;
|
||||
@ -0,0 +1,15 @@
|
||||
ALTER TABLE instances
|
||||
ADD COLUMN pinned_at INTEGER NULL;
|
||||
|
||||
CREATE TABLE instance_daily_playtime (
|
||||
played_on TEXT NOT NULL,
|
||||
instance_id TEXT NOT NULL,
|
||||
instance_name TEXT NOT NULL,
|
||||
played_seconds INTEGER NOT NULL DEFAULT 0,
|
||||
session_count INTEGER NOT NULL DEFAULT 0,
|
||||
|
||||
PRIMARY KEY (played_on, instance_id)
|
||||
);
|
||||
|
||||
CREATE INDEX instance_daily_playtime_played_on
|
||||
ON instance_daily_playtime(played_on);
|
||||
@ -0,0 +1,7 @@
|
||||
ALTER TABLE settings
|
||||
ADD COLUMN home_layout TEXT NOT NULL DEFAULT 'standard'
|
||||
CHECK (home_layout IN ('standard', 'minimal'));
|
||||
|
||||
ALTER TABLE settings
|
||||
ADD COLUMN minimal_home_instance_id TEXT NULL
|
||||
REFERENCES instances(id) ON DELETE SET NULL;
|
||||
@ -0,0 +1 @@
|
||||
ALTER TABLE settings ADD COLUMN auto_hide_downloads_button INTEGER NOT NULL DEFAULT FALSE;
|
||||
@ -0,0 +1,242 @@
|
||||
ALTER TABLE instance_content_provider_refs
|
||||
RENAME TO instance_content_provider_refs_legacy;
|
||||
|
||||
ALTER TABLE instance_content_update_checks
|
||||
RENAME TO instance_content_update_checks_legacy;
|
||||
|
||||
ALTER TABLE instance_content_entries
|
||||
RENAME TO instance_content_entries_legacy;
|
||||
|
||||
-- SQLite keeps index names unchanged when a table is renamed. Drop the
|
||||
-- legacy indexes before creating their provider-qualified replacements;
|
||||
-- otherwise the new CREATE INDEX statements fail with "already exists".
|
||||
DROP INDEX IF EXISTS instance_content_entries_instance_id;
|
||||
DROP INDEX IF EXISTS instance_content_entries_content_set_id;
|
||||
DROP INDEX IF EXISTS instance_content_entries_file_id;
|
||||
DROP INDEX IF EXISTS instance_content_entries_project_id;
|
||||
DROP INDEX IF EXISTS instance_content_entries_version_id;
|
||||
DROP INDEX IF EXISTS instance_content_entries_source_kind;
|
||||
DROP INDEX IF EXISTS instance_content_update_checks_update_version_id;
|
||||
DROP INDEX IF EXISTS instance_content_provider_refs_project;
|
||||
DROP INDEX IF EXISTS instance_content_provider_refs_version;
|
||||
DROP INDEX IF EXISTS instance_content_provider_refs_primary;
|
||||
|
||||
CREATE TABLE instance_content_entries (
|
||||
id TEXT NOT NULL,
|
||||
instance_id TEXT NOT NULL,
|
||||
content_set_id TEXT NOT NULL,
|
||||
file_id TEXT NULL,
|
||||
|
||||
project_type TEXT NOT NULL,
|
||||
source_kind TEXT NOT NULL,
|
||||
server_requirement TEXT NOT NULL,
|
||||
client_requirement TEXT NOT NULL,
|
||||
enabled INTEGER NOT NULL DEFAULT 1,
|
||||
|
||||
added_at INTEGER NOT NULL,
|
||||
modified_at INTEGER NOT NULL,
|
||||
|
||||
PRIMARY KEY (id),
|
||||
FOREIGN KEY (instance_id) REFERENCES instances(id) ON DELETE CASCADE,
|
||||
FOREIGN KEY (content_set_id)
|
||||
REFERENCES instance_content_sets(id)
|
||||
ON DELETE CASCADE,
|
||||
FOREIGN KEY (file_id) REFERENCES instance_files(id) ON DELETE SET NULL
|
||||
);
|
||||
|
||||
CREATE INDEX IF NOT EXISTS instance_content_entries_instance_id
|
||||
ON instance_content_entries(instance_id);
|
||||
CREATE INDEX IF NOT EXISTS instance_content_entries_content_set_id
|
||||
ON instance_content_entries(content_set_id);
|
||||
CREATE INDEX IF NOT EXISTS instance_content_entries_file_id
|
||||
ON instance_content_entries(file_id);
|
||||
CREATE INDEX IF NOT EXISTS instance_content_entries_source_kind
|
||||
ON instance_content_entries(source_kind);
|
||||
|
||||
INSERT INTO instance_content_entries (
|
||||
id,
|
||||
instance_id,
|
||||
content_set_id,
|
||||
file_id,
|
||||
project_type,
|
||||
source_kind,
|
||||
server_requirement,
|
||||
client_requirement,
|
||||
enabled,
|
||||
added_at,
|
||||
modified_at
|
||||
)
|
||||
SELECT
|
||||
id,
|
||||
instance_id,
|
||||
content_set_id,
|
||||
file_id,
|
||||
project_type,
|
||||
source_kind,
|
||||
server_requirement,
|
||||
client_requirement,
|
||||
enabled,
|
||||
added_at,
|
||||
modified_at
|
||||
FROM instance_content_entries_legacy;
|
||||
|
||||
CREATE TABLE instance_content_provider_refs (
|
||||
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||
content_entry_id TEXT NOT NULL,
|
||||
provider TEXT NOT NULL,
|
||||
provider_project_id TEXT NOT NULL,
|
||||
provider_release_id TEXT NULL,
|
||||
is_origin INTEGER NOT NULL DEFAULT 0,
|
||||
|
||||
FOREIGN KEY (content_entry_id)
|
||||
REFERENCES instance_content_entries(id)
|
||||
ON DELETE CASCADE,
|
||||
CHECK (provider IN ('modrinth', 'curseforge')),
|
||||
CHECK (is_origin IN (0, 1))
|
||||
);
|
||||
|
||||
CREATE INDEX IF NOT EXISTS instance_content_provider_refs_project
|
||||
ON instance_content_provider_refs(provider, provider_project_id);
|
||||
|
||||
CREATE INDEX IF NOT EXISTS instance_content_provider_refs_release
|
||||
ON instance_content_provider_refs(provider, provider_release_id);
|
||||
|
||||
CREATE UNIQUE INDEX IF NOT EXISTS instance_content_provider_refs_identity
|
||||
ON instance_content_provider_refs(
|
||||
content_entry_id,
|
||||
provider,
|
||||
provider_project_id,
|
||||
COALESCE(provider_release_id, '')
|
||||
);
|
||||
|
||||
CREATE UNIQUE INDEX IF NOT EXISTS instance_content_provider_refs_origin
|
||||
ON instance_content_provider_refs(content_entry_id)
|
||||
WHERE is_origin = 1;
|
||||
|
||||
INSERT OR IGNORE INTO instance_content_provider_refs (
|
||||
content_entry_id,
|
||||
provider,
|
||||
provider_project_id,
|
||||
provider_release_id,
|
||||
is_origin
|
||||
)
|
||||
SELECT
|
||||
content_entry_id,
|
||||
provider,
|
||||
project_id,
|
||||
version_id,
|
||||
primary_ref
|
||||
FROM instance_content_provider_refs_legacy
|
||||
WHERE length(trim(project_id)) > 0
|
||||
AND (
|
||||
provider = 'modrinth'
|
||||
OR (
|
||||
provider = 'curseforge'
|
||||
AND project_id NOT GLOB '*[^0-9]*'
|
||||
AND CAST(project_id AS INTEGER) > 0
|
||||
AND (
|
||||
version_id IS NULL
|
||||
OR (
|
||||
version_id NOT GLOB '*[^0-9]*'
|
||||
AND CAST(version_id AS INTEGER) > 0
|
||||
)
|
||||
)
|
||||
)
|
||||
);
|
||||
|
||||
INSERT OR IGNORE INTO instance_content_provider_refs (
|
||||
content_entry_id,
|
||||
provider,
|
||||
provider_project_id,
|
||||
provider_release_id,
|
||||
is_origin
|
||||
)
|
||||
SELECT
|
||||
legacy.id,
|
||||
'curseforge',
|
||||
legacy.project_id,
|
||||
legacy.version_id,
|
||||
1
|
||||
FROM instance_content_entries_legacy legacy
|
||||
WHERE legacy.source_kind = 'curseforge'
|
||||
AND legacy.project_id IS NOT NULL
|
||||
AND legacy.project_id NOT GLOB '*[^0-9]*'
|
||||
AND CAST(legacy.project_id AS INTEGER) > 0
|
||||
AND NOT EXISTS (
|
||||
SELECT 1
|
||||
FROM instance_content_provider_refs ref
|
||||
WHERE ref.content_entry_id = legacy.id
|
||||
AND ref.provider = 'curseforge'
|
||||
);
|
||||
|
||||
INSERT OR IGNORE INTO instance_content_provider_refs (
|
||||
content_entry_id,
|
||||
provider,
|
||||
provider_project_id,
|
||||
provider_release_id,
|
||||
is_origin
|
||||
)
|
||||
SELECT
|
||||
legacy.id,
|
||||
'modrinth',
|
||||
json_extract(cache.data, '$.project_id'),
|
||||
json_extract(cache.data, '$.version_id'),
|
||||
CASE
|
||||
WHEN legacy.source_kind IN ('modrinth_modpack', 'modrinth_hosting')
|
||||
THEN 1
|
||||
ELSE 0
|
||||
END
|
||||
FROM instance_content_entries_legacy legacy
|
||||
INNER JOIN instance_files file ON file.id = legacy.file_id
|
||||
INNER JOIN cache
|
||||
ON cache.data_type = 'file_hash'
|
||||
AND json_extract(cache.data, '$.path') =
|
||||
legacy.instance_id || '/' || file.relative_path
|
||||
WHERE json_extract(cache.data, '$.project_id') IS NOT NULL
|
||||
AND json_extract(cache.data, '$.version_id') IS NOT NULL;
|
||||
|
||||
CREATE TABLE instance_content_update_checks (
|
||||
content_entry_id TEXT NOT NULL,
|
||||
update_channel TEXT NOT NULL,
|
||||
provider TEXT NULL,
|
||||
provider_project_id TEXT NULL,
|
||||
provider_release_id TEXT NULL,
|
||||
checked_at INTEGER NOT NULL,
|
||||
|
||||
PRIMARY KEY (content_entry_id),
|
||||
FOREIGN KEY (content_entry_id)
|
||||
REFERENCES instance_content_entries(id)
|
||||
ON DELETE CASCADE,
|
||||
CHECK (provider IS NULL OR provider IN ('modrinth', 'curseforge'))
|
||||
);
|
||||
|
||||
CREATE INDEX IF NOT EXISTS instance_content_update_checks_release
|
||||
ON instance_content_update_checks(provider, provider_release_id);
|
||||
|
||||
INSERT INTO instance_content_update_checks (
|
||||
content_entry_id,
|
||||
update_channel,
|
||||
provider,
|
||||
provider_project_id,
|
||||
provider_release_id,
|
||||
checked_at
|
||||
)
|
||||
SELECT
|
||||
legacy.content_entry_id,
|
||||
legacy.update_channel,
|
||||
ref.provider,
|
||||
ref.provider_project_id,
|
||||
CASE
|
||||
WHEN legacy.update_version_id IS NULL THEN NULL
|
||||
ELSE legacy.update_version_id
|
||||
END,
|
||||
legacy.checked_at
|
||||
FROM instance_content_update_checks_legacy legacy
|
||||
LEFT JOIN instance_content_provider_refs ref
|
||||
ON ref.content_entry_id = legacy.content_entry_id
|
||||
AND ref.is_origin = 1
|
||||
WHERE ref.provider = 'modrinth';
|
||||
|
||||
DROP TABLE instance_content_provider_refs_legacy;
|
||||
DROP TABLE instance_content_update_checks_legacy;
|
||||
DROP TABLE instance_content_entries_legacy;
|
||||
@ -0,0 +1,187 @@
|
||||
ALTER TABLE instance_content_provider_refs
|
||||
RENAME TO instance_content_provider_refs_single_legacy;
|
||||
|
||||
DROP INDEX IF EXISTS instance_content_provider_refs_project;
|
||||
DROP INDEX IF EXISTS instance_content_provider_refs_release;
|
||||
DROP INDEX IF EXISTS instance_content_provider_refs_origin;
|
||||
DROP INDEX IF EXISTS instance_content_provider_refs_identity;
|
||||
|
||||
CREATE TABLE instance_content_provider_refs (
|
||||
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||
content_entry_id TEXT NOT NULL,
|
||||
provider TEXT NOT NULL,
|
||||
provider_project_id TEXT NOT NULL,
|
||||
provider_release_id TEXT NULL,
|
||||
is_origin INTEGER NOT NULL DEFAULT 0,
|
||||
|
||||
FOREIGN KEY (content_entry_id)
|
||||
REFERENCES instance_content_entries(id)
|
||||
ON DELETE CASCADE,
|
||||
CHECK (provider IN ('modrinth', 'curseforge')),
|
||||
CHECK (is_origin IN (0, 1))
|
||||
);
|
||||
|
||||
CREATE INDEX instance_content_provider_refs_project
|
||||
ON instance_content_provider_refs(provider, provider_project_id);
|
||||
|
||||
CREATE INDEX instance_content_provider_refs_release
|
||||
ON instance_content_provider_refs(provider, provider_release_id);
|
||||
|
||||
CREATE UNIQUE INDEX instance_content_provider_refs_identity
|
||||
ON instance_content_provider_refs(
|
||||
content_entry_id,
|
||||
provider,
|
||||
provider_project_id,
|
||||
COALESCE(provider_release_id, '')
|
||||
);
|
||||
|
||||
CREATE UNIQUE INDEX instance_content_provider_refs_origin
|
||||
ON instance_content_provider_refs(content_entry_id)
|
||||
WHERE is_origin = 1;
|
||||
|
||||
INSERT OR IGNORE INTO instance_content_provider_refs (
|
||||
content_entry_id,
|
||||
provider,
|
||||
provider_project_id,
|
||||
provider_release_id,
|
||||
is_origin
|
||||
)
|
||||
SELECT
|
||||
content_entry_id,
|
||||
provider,
|
||||
provider_project_id,
|
||||
provider_release_id,
|
||||
is_origin
|
||||
FROM instance_content_provider_refs_single_legacy
|
||||
WHERE length(trim(provider_project_id)) > 0
|
||||
AND (
|
||||
(
|
||||
provider = 'modrinth'
|
||||
AND (
|
||||
provider_release_id IS NULL
|
||||
OR length(trim(provider_release_id)) > 0
|
||||
)
|
||||
)
|
||||
OR (
|
||||
provider = 'curseforge'
|
||||
AND provider_project_id NOT GLOB '*[^0-9]*'
|
||||
AND CAST(provider_project_id AS INTEGER) > 0
|
||||
AND (
|
||||
provider_release_id IS NULL
|
||||
OR (
|
||||
provider_release_id NOT GLOB '*[^0-9]*'
|
||||
AND CAST(provider_release_id AS INTEGER) > 0
|
||||
)
|
||||
)
|
||||
)
|
||||
);
|
||||
|
||||
UPDATE instance_content_provider_refs
|
||||
SET is_origin = 0
|
||||
WHERE content_entry_id IN (
|
||||
SELECT id
|
||||
FROM instance_content_entries
|
||||
WHERE source_kind = 'curseforge'
|
||||
);
|
||||
|
||||
INSERT OR IGNORE INTO instance_content_provider_refs (
|
||||
content_entry_id,
|
||||
provider,
|
||||
provider_project_id,
|
||||
provider_release_id,
|
||||
is_origin
|
||||
)
|
||||
SELECT
|
||||
ref.content_entry_id,
|
||||
'curseforge',
|
||||
ref.provider_project_id,
|
||||
ref.provider_release_id,
|
||||
0
|
||||
FROM instance_content_provider_refs ref
|
||||
INNER JOIN instance_content_entries entry
|
||||
ON entry.id = ref.content_entry_id
|
||||
WHERE entry.source_kind = 'curseforge'
|
||||
AND ref.provider = 'modrinth'
|
||||
AND ref.provider_project_id NOT GLOB '*[^0-9]*'
|
||||
AND CAST(ref.provider_project_id AS INTEGER) > 0
|
||||
AND (
|
||||
ref.provider_release_id IS NULL
|
||||
OR (
|
||||
ref.provider_release_id NOT GLOB '*[^0-9]*'
|
||||
AND CAST(ref.provider_release_id AS INTEGER) > 0
|
||||
)
|
||||
)
|
||||
AND NOT EXISTS (
|
||||
SELECT 1
|
||||
FROM instance_content_provider_refs existing
|
||||
WHERE existing.content_entry_id = ref.content_entry_id
|
||||
AND existing.provider = 'curseforge'
|
||||
)
|
||||
AND ref.id = (
|
||||
SELECT MIN(candidate.id)
|
||||
FROM instance_content_provider_refs candidate
|
||||
WHERE candidate.content_entry_id = ref.content_entry_id
|
||||
AND candidate.provider = 'modrinth'
|
||||
AND candidate.provider_project_id NOT GLOB '*[^0-9]*'
|
||||
AND CAST(candidate.provider_project_id AS INTEGER) > 0
|
||||
AND (
|
||||
candidate.provider_release_id IS NULL
|
||||
OR (
|
||||
candidate.provider_release_id NOT GLOB '*[^0-9]*'
|
||||
AND CAST(candidate.provider_release_id AS INTEGER) > 0
|
||||
)
|
||||
)
|
||||
);
|
||||
|
||||
UPDATE instance_content_provider_refs
|
||||
SET is_origin = 1
|
||||
WHERE id IN (
|
||||
SELECT MIN(ref.id)
|
||||
FROM instance_content_provider_refs ref
|
||||
INNER JOIN instance_content_entries entry
|
||||
ON entry.id = ref.content_entry_id
|
||||
WHERE entry.source_kind = 'curseforge'
|
||||
AND ref.provider = 'curseforge'
|
||||
GROUP BY ref.content_entry_id
|
||||
);
|
||||
|
||||
DELETE FROM instance_content_provider_refs
|
||||
WHERE provider = 'modrinth'
|
||||
AND content_entry_id IN (
|
||||
SELECT id
|
||||
FROM instance_content_entries
|
||||
WHERE source_kind = 'curseforge'
|
||||
)
|
||||
AND NOT EXISTS (
|
||||
SELECT 1
|
||||
FROM instance_content_entries entry
|
||||
INNER JOIN instance_files file ON file.id = entry.file_id
|
||||
INNER JOIN cache
|
||||
ON cache.data_type = 'file_hash'
|
||||
AND json_extract(
|
||||
CASE WHEN json_valid(cache.data) THEN cache.data ELSE '{}' END,
|
||||
'$.path'
|
||||
) =
|
||||
entry.instance_id || '/' || file.relative_path
|
||||
WHERE entry.id = instance_content_provider_refs.content_entry_id
|
||||
AND json_extract(
|
||||
CASE WHEN json_valid(cache.data) THEN cache.data ELSE '{}' END,
|
||||
'$.project_id'
|
||||
) =
|
||||
instance_content_provider_refs.provider_project_id
|
||||
AND json_extract(
|
||||
CASE WHEN json_valid(cache.data) THEN cache.data ELSE '{}' END,
|
||||
'$.version_id'
|
||||
) IS
|
||||
instance_content_provider_refs.provider_release_id
|
||||
);
|
||||
|
||||
DELETE FROM instance_content_update_checks
|
||||
WHERE provider = 'modrinth'
|
||||
AND content_entry_id IN (
|
||||
SELECT id
|
||||
FROM instance_content_entries
|
||||
WHERE source_kind = 'curseforge'
|
||||
);
|
||||
|
||||
DROP TABLE instance_content_provider_refs_single_legacy;
|
||||
@ -0,0 +1,16 @@
|
||||
CREATE UNIQUE INDEX java_versions_major_version_path
|
||||
ON java_versions(major_version, path);
|
||||
|
||||
CREATE TABLE java_default_versions (
|
||||
major_version INTEGER NOT NULL PRIMARY KEY,
|
||||
path TEXT NOT NULL,
|
||||
FOREIGN KEY (major_version, path)
|
||||
REFERENCES java_versions(major_version, path)
|
||||
ON DELETE CASCADE
|
||||
ON UPDATE CASCADE
|
||||
);
|
||||
|
||||
INSERT INTO java_default_versions (major_version, path)
|
||||
SELECT major_version, MIN(path)
|
||||
FROM java_versions
|
||||
GROUP BY major_version;
|
||||
@ -0,0 +1,5 @@
|
||||
-- Cache extracted icons for unmatched Mod / ResourcePack files so the
|
||||
-- content list can show real artwork without reopening archives on every
|
||||
-- render. NULL = not attempted yet, '' = attempted with no icon found.
|
||||
ALTER TABLE instance_files
|
||||
ADD COLUMN icon_path TEXT NULL;
|
||||
@ -0,0 +1,75 @@
|
||||
CREATE TABLE settings_with_official_preferred (
|
||||
id INTEGER NOT NULL CHECK (id = 0),
|
||||
max_concurrent_downloads INTEGER NOT NULL DEFAULT 10,
|
||||
max_concurrent_writes INTEGER NOT NULL DEFAULT 10,
|
||||
theme TEXT NOT NULL DEFAULT 'dark',
|
||||
default_page TEXT NOT NULL DEFAULT 'home',
|
||||
collapsed_navigation INTEGER NOT NULL DEFAULT TRUE,
|
||||
advanced_rendering INTEGER NOT NULL DEFAULT TRUE,
|
||||
native_decorations INTEGER NOT NULL DEFAULT FALSE,
|
||||
telemetry INTEGER NOT NULL DEFAULT FALSE,
|
||||
discord_rpc INTEGER NOT NULL DEFAULT TRUE,
|
||||
developer_mode INTEGER NOT NULL DEFAULT FALSE,
|
||||
onboarded INTEGER NOT NULL DEFAULT FALSE,
|
||||
extra_launch_args JSONB NOT NULL,
|
||||
custom_env_vars JSONB NOT NULL,
|
||||
mc_memory_max INTEGER NOT NULL DEFAULT 2048,
|
||||
mc_force_fullscreen INTEGER NOT NULL DEFAULT FALSE,
|
||||
mc_game_resolution_x INTEGER NOT NULL DEFAULT 854,
|
||||
mc_game_resolution_y INTEGER NOT NULL DEFAULT 480,
|
||||
hide_on_process_start INTEGER NOT NULL DEFAULT FALSE,
|
||||
hook_pre_launch TEXT NULL,
|
||||
hook_wrapper TEXT NULL,
|
||||
hook_post_exit TEXT NULL,
|
||||
custom_dir TEXT NULL,
|
||||
prev_custom_dir TEXT NULL,
|
||||
migrated INTEGER NOT NULL DEFAULT FALSE,
|
||||
personalized_ads INTEGER NOT NULL DEFAULT TRUE,
|
||||
toggle_sidebar INTEGER NOT NULL DEFAULT FALSE,
|
||||
feature_flags JSONB NOT NULL DEFAULT '{}',
|
||||
hide_nametag_skins_page INTEGER NOT NULL DEFAULT 0 CHECK (hide_nametag_skins_page IN (0, 1)),
|
||||
skipped_update TEXT NULL,
|
||||
pending_update_toast_for_version TEXT NULL,
|
||||
auto_download_updates INT NULL,
|
||||
version INTEGER NOT NULL DEFAULT 1,
|
||||
locale TEXT NOT NULL DEFAULT '',
|
||||
accent_color TEXT NOT NULL DEFAULT 'pink',
|
||||
custom_background_path TEXT NULL,
|
||||
custom_background_blur INTEGER NOT NULL DEFAULT 12 CHECK (custom_background_blur BETWEEN 0 AND 40),
|
||||
custom_background_opacity INTEGER NOT NULL DEFAULT 65 CHECK (custom_background_opacity BETWEEN 10 AND 100),
|
||||
use_minecraft_mirror INTEGER NOT NULL DEFAULT FALSE,
|
||||
use_modrinth_mirror INTEGER NOT NULL DEFAULT FALSE,
|
||||
use_curseforge_mirror INTEGER NOT NULL DEFAULT TRUE,
|
||||
auto_concurrent_downloads INTEGER NOT NULL DEFAULT TRUE,
|
||||
minecraft_metadata_source TEXT NOT NULL DEFAULT 'auto' CHECK (
|
||||
minecraft_metadata_source IN ('auto', 'official_only', 'mirror_preferred', 'official_preferred')
|
||||
),
|
||||
minecraft_file_source TEXT NOT NULL DEFAULT 'auto' CHECK (
|
||||
minecraft_file_source IN ('auto', 'official_only', 'mirror_preferred', 'official_preferred')
|
||||
),
|
||||
modrinth_source TEXT NOT NULL DEFAULT 'auto' CHECK (
|
||||
modrinth_source IN ('auto', 'official_only', 'mirror_preferred', 'official_preferred')
|
||||
),
|
||||
curseforge_source TEXT NOT NULL DEFAULT 'auto' CHECK (
|
||||
curseforge_source IN ('auto', 'official_only', 'mirror_preferred', 'official_preferred')
|
||||
),
|
||||
onboarding_version INTEGER NOT NULL DEFAULT 0,
|
||||
onboarding_instance_tour_completed INTEGER NOT NULL DEFAULT TRUE,
|
||||
sidebar_instance_count INTEGER NOT NULL DEFAULT 0,
|
||||
mc_memory_auto INTEGER NOT NULL DEFAULT FALSE,
|
||||
mc_memory_optimize INTEGER NOT NULL DEFAULT FALSE,
|
||||
auto_set_java_high_performance_mode INTEGER NOT NULL DEFAULT TRUE,
|
||||
transparent_background INTEGER NOT NULL DEFAULT FALSE,
|
||||
transparent_background_opacity INTEGER NOT NULL DEFAULT 55,
|
||||
transparent_background_blur INTEGER NOT NULL DEFAULT FALSE,
|
||||
home_layout TEXT NOT NULL DEFAULT 'standard' CHECK (home_layout IN ('standard', 'minimal')),
|
||||
minimal_home_instance_id TEXT NULL REFERENCES instances(id) ON DELETE SET NULL,
|
||||
auto_hide_downloads_button INTEGER NOT NULL DEFAULT FALSE,
|
||||
PRIMARY KEY (id)
|
||||
);
|
||||
|
||||
INSERT INTO settings_with_official_preferred
|
||||
SELECT * FROM settings;
|
||||
|
||||
DROP TABLE settings;
|
||||
ALTER TABLE settings_with_official_preferred RENAME TO settings;
|
||||
@ -0,0 +1,3 @@
|
||||
ALTER TABLE settings
|
||||
ADD COLUMN use_system_proxy INTEGER NOT NULL DEFAULT FALSE
|
||||
CHECK (use_system_proxy IN (0, 1));
|
||||
@ -0,0 +1,192 @@
|
||||
ALTER TABLE instance_content_sets
|
||||
ADD COLUMN revision INTEGER NOT NULL DEFAULT 0;
|
||||
|
||||
ALTER TABLE instance_content_entries
|
||||
ADD COLUMN ownership_kind TEXT NOT NULL DEFAULT 'user_added'
|
||||
CHECK (ownership_kind IN ('pack_managed', 'user_added'));
|
||||
|
||||
UPDATE instance_content_entries AS entry
|
||||
SET ownership_kind = 'pack_managed'
|
||||
WHERE EXISTS (
|
||||
SELECT 1
|
||||
FROM instance_links link
|
||||
WHERE link.instance_id = entry.instance_id
|
||||
AND (
|
||||
(link.link_kind IN ('modrinth_modpack', 'server_project_modpack')
|
||||
AND entry.source_kind = 'modrinth_modpack')
|
||||
OR (link.link_kind = 'curseforge_modpack'
|
||||
AND entry.source_kind = 'curseforge')
|
||||
OR (link.link_kind = 'imported_modpack'
|
||||
AND entry.source_kind IN (
|
||||
'imported_modpack',
|
||||
'modrinth_modpack',
|
||||
'curseforge'
|
||||
))
|
||||
)
|
||||
);
|
||||
|
||||
CREATE INDEX instance_content_entries_ownership_kind
|
||||
ON instance_content_entries(content_set_id, ownership_kind);
|
||||
|
||||
CREATE TABLE instance_pack_members (
|
||||
id TEXT NOT NULL,
|
||||
content_set_id TEXT NOT NULL,
|
||||
content_entry_id TEXT NULL,
|
||||
member_key TEXT NOT NULL,
|
||||
project_type TEXT NOT NULL,
|
||||
expected_relative_path TEXT NOT NULL,
|
||||
provider TEXT NULL,
|
||||
provider_project_id TEXT NULL,
|
||||
provider_release_id TEXT NULL,
|
||||
required INTEGER NOT NULL DEFAULT 1,
|
||||
expected_sha1 TEXT NULL,
|
||||
expected_size INTEGER NULL,
|
||||
expected_fingerprint INTEGER NULL,
|
||||
materialization_state TEXT NOT NULL DEFAULT 'present',
|
||||
override_kind TEXT NOT NULL DEFAULT 'none',
|
||||
reconciled INTEGER NOT NULL DEFAULT 1,
|
||||
created_at INTEGER NOT NULL,
|
||||
modified_at INTEGER NOT NULL,
|
||||
|
||||
PRIMARY KEY (id),
|
||||
UNIQUE (content_set_id, member_key),
|
||||
FOREIGN KEY (content_set_id)
|
||||
REFERENCES instance_content_sets(id)
|
||||
ON DELETE CASCADE,
|
||||
FOREIGN KEY (content_entry_id)
|
||||
REFERENCES instance_content_entries(id)
|
||||
ON DELETE SET NULL,
|
||||
CHECK (provider IS NULL OR provider IN ('modrinth', 'curseforge')),
|
||||
CHECK (required IN (0, 1)),
|
||||
CHECK (materialization_state IN (
|
||||
'present',
|
||||
'pending_manual',
|
||||
'missing',
|
||||
'removed'
|
||||
)),
|
||||
CHECK (override_kind IN ('none', 'disabled', 'removed', 'version')),
|
||||
CHECK (reconciled IN (0, 1))
|
||||
);
|
||||
|
||||
CREATE INDEX instance_pack_members_content_set
|
||||
ON instance_pack_members(content_set_id);
|
||||
CREATE INDEX instance_pack_members_content_entry
|
||||
ON instance_pack_members(content_entry_id);
|
||||
CREATE INDEX instance_pack_members_provider
|
||||
ON instance_pack_members(provider, provider_project_id, provider_release_id);
|
||||
CREATE INDEX instance_pack_members_state
|
||||
ON instance_pack_members(content_set_id, materialization_state);
|
||||
|
||||
INSERT INTO instance_pack_members (
|
||||
id,
|
||||
content_set_id,
|
||||
content_entry_id,
|
||||
member_key,
|
||||
project_type,
|
||||
expected_relative_path,
|
||||
provider,
|
||||
provider_project_id,
|
||||
provider_release_id,
|
||||
required,
|
||||
expected_sha1,
|
||||
expected_size,
|
||||
expected_fingerprint,
|
||||
materialization_state,
|
||||
override_kind,
|
||||
reconciled,
|
||||
created_at,
|
||||
modified_at
|
||||
)
|
||||
SELECT
|
||||
'pack-member:' || entry.id,
|
||||
entry.content_set_id,
|
||||
entry.id,
|
||||
CASE
|
||||
WHEN origin.provider IS NOT NULL THEN
|
||||
origin.provider || ':' || origin.provider_project_id || ':' || entry.project_type
|
||||
ELSE 'path:' || lower(replace(file.relative_path, '\\', '/'))
|
||||
END,
|
||||
entry.project_type,
|
||||
file.relative_path,
|
||||
origin.provider,
|
||||
origin.provider_project_id,
|
||||
origin.provider_release_id,
|
||||
CASE
|
||||
WHEN entry.server_requirement = 'optional'
|
||||
AND entry.client_requirement = 'optional'
|
||||
THEN 0
|
||||
ELSE 1
|
||||
END,
|
||||
file.sha1,
|
||||
file.size,
|
||||
NULL,
|
||||
CASE WHEN file.missing = 1 THEN 'missing' ELSE 'present' END,
|
||||
CASE
|
||||
WHEN entry.enabled = 0 OR file.enabled = 0 THEN 'disabled'
|
||||
ELSE 'none'
|
||||
END,
|
||||
CASE
|
||||
WHEN link.link_kind = 'curseforge_modpack' THEN 0
|
||||
ELSE 1
|
||||
END,
|
||||
entry.added_at,
|
||||
entry.modified_at
|
||||
FROM instance_content_entries entry
|
||||
INNER JOIN instance_files file ON file.id = entry.file_id
|
||||
INNER JOIN instance_links link ON link.instance_id = entry.instance_id
|
||||
LEFT JOIN instance_content_provider_refs origin
|
||||
ON origin.content_entry_id = entry.id
|
||||
AND origin.is_origin = 1
|
||||
WHERE entry.ownership_kind = 'pack_managed';
|
||||
|
||||
CREATE TABLE instance_pending_manual_downloads (
|
||||
id TEXT NOT NULL,
|
||||
instance_id TEXT NOT NULL,
|
||||
pack_member_id TEXT NULL,
|
||||
content_entry_id TEXT NULL,
|
||||
operation_kind TEXT NOT NULL,
|
||||
operation_target_id TEXT NULL,
|
||||
project_type TEXT NOT NULL,
|
||||
provider TEXT NOT NULL,
|
||||
provider_project_id TEXT NOT NULL,
|
||||
provider_release_id TEXT NOT NULL,
|
||||
file_name TEXT NOT NULL,
|
||||
website_url TEXT NULL,
|
||||
target_relative_path TEXT NOT NULL,
|
||||
expected_sha1 TEXT NULL,
|
||||
expected_size INTEGER NULL,
|
||||
expected_fingerprint INTEGER NULL,
|
||||
state TEXT NOT NULL DEFAULT 'waiting',
|
||||
context JSONB NOT NULL DEFAULT '{}',
|
||||
created_at INTEGER NOT NULL,
|
||||
modified_at INTEGER NOT NULL,
|
||||
|
||||
PRIMARY KEY (id),
|
||||
FOREIGN KEY (instance_id) REFERENCES instances(id) ON DELETE CASCADE,
|
||||
FOREIGN KEY (pack_member_id)
|
||||
REFERENCES instance_pack_members(id)
|
||||
ON DELETE CASCADE,
|
||||
FOREIGN KEY (content_entry_id)
|
||||
REFERENCES instance_content_entries(id)
|
||||
ON DELETE SET NULL,
|
||||
CHECK (provider IN ('modrinth', 'curseforge')),
|
||||
CHECK (operation_kind IN (
|
||||
'pack_install',
|
||||
'pack_update',
|
||||
'content_install',
|
||||
'content_update'
|
||||
)),
|
||||
CHECK (state IN ('waiting', 'matched', 'imported', 'error', 'cancelled'))
|
||||
);
|
||||
|
||||
CREATE UNIQUE INDEX instance_pending_manual_download_identity
|
||||
ON instance_pending_manual_downloads(
|
||||
instance_id,
|
||||
operation_kind,
|
||||
provider,
|
||||
provider_project_id,
|
||||
provider_release_id
|
||||
)
|
||||
WHERE state IN ('waiting', 'matched');
|
||||
CREATE INDEX instance_pending_manual_downloads_instance_state
|
||||
ON instance_pending_manual_downloads(instance_id, state);
|
||||
@ -0,0 +1 @@
|
||||
ALTER TABLE settings DROP COLUMN use_system_proxy;
|
||||
@ -0,0 +1,2 @@
|
||||
ALTER TABLE settings
|
||||
ADD COLUMN home_widgets JSONB NULL;
|
||||
93
packages/app-lib/migrations/20260805120000_ai-providers.sql
Normal file
93
packages/app-lib/migrations/20260805120000_ai-providers.sql
Normal file
@ -0,0 +1,93 @@
|
||||
CREATE TABLE ai_settings (
|
||||
id INTEGER NOT NULL CHECK (id = 0),
|
||||
enabled INTEGER NOT NULL DEFAULT TRUE,
|
||||
PRIMARY KEY (id)
|
||||
);
|
||||
|
||||
INSERT INTO ai_settings (id) VALUES (0);
|
||||
|
||||
CREATE TABLE ai_provider_configs (
|
||||
provider_id TEXT NOT NULL PRIMARY KEY,
|
||||
custom_name TEXT NULL,
|
||||
protocol TEXT NOT NULL DEFAULT 'openai',
|
||||
enabled INTEGER NOT NULL DEFAULT FALSE,
|
||||
endpoint TEXT NOT NULL DEFAULT '',
|
||||
settings TEXT NOT NULL DEFAULT '{}'
|
||||
);
|
||||
|
||||
CREATE TABLE ai_provider_models (
|
||||
provider_id TEXT NOT NULL,
|
||||
model_id TEXT NOT NULL,
|
||||
display_name TEXT NOT NULL DEFAULT '',
|
||||
enabled INTEGER NOT NULL DEFAULT TRUE,
|
||||
source TEXT NOT NULL DEFAULT 'custom',
|
||||
PRIMARY KEY (provider_id, model_id)
|
||||
);
|
||||
|
||||
ALTER TABLE translation_settings ADD COLUMN ai_provider_id TEXT NOT NULL DEFAULT '';
|
||||
ALTER TABLE translation_settings ADD COLUMN ai_model_id TEXT NOT NULL DEFAULT '';
|
||||
|
||||
INSERT INTO ai_provider_configs (
|
||||
provider_id,
|
||||
custom_name,
|
||||
protocol,
|
||||
enabled,
|
||||
endpoint
|
||||
)
|
||||
SELECT
|
||||
'openai',
|
||||
'OpenAI Compatible',
|
||||
'openai',
|
||||
TRUE,
|
||||
openai_base_url
|
||||
FROM translation_settings
|
||||
WHERE id = 0
|
||||
AND trim(openai_model) != ''
|
||||
AND (
|
||||
lower(trim(openai_base_url)) LIKE 'http://%'
|
||||
OR lower(trim(openai_base_url)) LIKE 'https://%'
|
||||
)
|
||||
AND (
|
||||
provider = 'openai-compatible'
|
||||
OR openai_api_key IS NOT NULL
|
||||
OR openai_base_url != 'https://api.openai.com/v1'
|
||||
OR openai_model != 'gpt-4o-mini'
|
||||
OR openai_system_prompt != ''
|
||||
);
|
||||
|
||||
INSERT INTO ai_provider_models (
|
||||
provider_id,
|
||||
model_id,
|
||||
display_name,
|
||||
enabled,
|
||||
source
|
||||
)
|
||||
SELECT
|
||||
'openai',
|
||||
openai_model,
|
||||
openai_model,
|
||||
TRUE,
|
||||
'custom'
|
||||
FROM translation_settings
|
||||
WHERE id = 0
|
||||
AND EXISTS (
|
||||
SELECT 1
|
||||
FROM ai_provider_configs
|
||||
WHERE provider_id = 'openai'
|
||||
);
|
||||
|
||||
UPDATE translation_settings
|
||||
SET provider = 'ai',
|
||||
ai_provider_id = 'openai',
|
||||
ai_model_id = openai_model
|
||||
WHERE id = 0
|
||||
AND provider = 'openai-compatible'
|
||||
AND trim(openai_model) != ''
|
||||
AND (
|
||||
lower(trim(openai_base_url)) LIKE 'http://%'
|
||||
OR lower(trim(openai_base_url)) LIKE 'https://%'
|
||||
);
|
||||
|
||||
UPDATE translation_settings
|
||||
SET provider = 'microsoft'
|
||||
WHERE id = 0 AND provider = 'openai-compatible';
|
||||
@ -0,0 +1,111 @@
|
||||
ALTER TABLE ai_settings
|
||||
ADD COLUMN legacy_openai_credential_cleanup INTEGER NOT NULL DEFAULT FALSE;
|
||||
|
||||
CREATE TEMP TABLE legacy_openai_ai_config (
|
||||
provider_id TEXT NOT NULL PRIMARY KEY,
|
||||
model_id TEXT NOT NULL
|
||||
);
|
||||
|
||||
INSERT INTO legacy_openai_ai_config (provider_id, model_id)
|
||||
SELECT
|
||||
config.provider_id,
|
||||
translation.openai_model
|
||||
FROM translation_settings AS translation
|
||||
INNER JOIN ai_provider_configs AS config
|
||||
ON config.provider_id = 'openai'
|
||||
AND config.custom_name = 'OpenAI Compatible'
|
||||
AND config.protocol = 'openai'
|
||||
AND config.enabled = TRUE
|
||||
AND config.endpoint = translation.openai_base_url
|
||||
AND json(config.settings) = json('{}')
|
||||
INNER JOIN ai_provider_models AS model
|
||||
ON model.provider_id = config.provider_id
|
||||
AND model.model_id = translation.openai_model
|
||||
AND model.display_name = translation.openai_model
|
||||
AND model.enabled = TRUE
|
||||
AND model.source = 'custom'
|
||||
WHERE translation.id = 0;
|
||||
|
||||
UPDATE ai_settings
|
||||
SET legacy_openai_credential_cleanup = TRUE
|
||||
WHERE id = 0
|
||||
AND (
|
||||
EXISTS (SELECT 1 FROM legacy_openai_ai_config)
|
||||
OR EXISTS (
|
||||
SELECT 1
|
||||
FROM translation_settings
|
||||
WHERE id = 0 AND openai_api_key IS NOT NULL
|
||||
)
|
||||
);
|
||||
|
||||
DELETE FROM ai_provider_models
|
||||
WHERE EXISTS (
|
||||
SELECT 1
|
||||
FROM legacy_openai_ai_config
|
||||
WHERE legacy_openai_ai_config.provider_id = ai_provider_models.provider_id
|
||||
AND legacy_openai_ai_config.model_id = ai_provider_models.model_id
|
||||
);
|
||||
|
||||
DELETE FROM ai_provider_configs
|
||||
WHERE EXISTS (
|
||||
SELECT 1
|
||||
FROM legacy_openai_ai_config
|
||||
WHERE legacy_openai_ai_config.provider_id = ai_provider_configs.provider_id
|
||||
)
|
||||
AND NOT EXISTS (
|
||||
SELECT 1
|
||||
FROM ai_provider_models
|
||||
WHERE ai_provider_models.provider_id = ai_provider_configs.provider_id
|
||||
);
|
||||
|
||||
UPDATE translation_settings
|
||||
SET provider = CASE
|
||||
WHEN provider = 'ai'
|
||||
AND ai_provider_id = 'openai'
|
||||
AND EXISTS (
|
||||
SELECT 1
|
||||
FROM legacy_openai_ai_config
|
||||
WHERE model_id = ai_model_id
|
||||
)
|
||||
THEN 'microsoft'
|
||||
ELSE provider
|
||||
END,
|
||||
ai_provider_id = CASE
|
||||
WHEN provider = 'ai'
|
||||
AND ai_provider_id = 'openai'
|
||||
AND EXISTS (
|
||||
SELECT 1
|
||||
FROM legacy_openai_ai_config
|
||||
WHERE model_id = ai_model_id
|
||||
)
|
||||
THEN ''
|
||||
ELSE ai_provider_id
|
||||
END,
|
||||
ai_model_id = CASE
|
||||
WHEN provider = 'ai'
|
||||
AND ai_provider_id = 'openai'
|
||||
AND EXISTS (
|
||||
SELECT 1
|
||||
FROM legacy_openai_ai_config
|
||||
WHERE model_id = ai_model_id
|
||||
)
|
||||
THEN ''
|
||||
ELSE ai_model_id
|
||||
END,
|
||||
openai_base_url = 'https://api.openai.com/v1',
|
||||
openai_model = 'gpt-4o-mini',
|
||||
openai_api_key = NULL,
|
||||
openai_system_prompt = CASE
|
||||
WHEN provider = 'ai'
|
||||
AND NOT EXISTS (
|
||||
SELECT 1
|
||||
FROM legacy_openai_ai_config
|
||||
WHERE provider_id = ai_provider_id
|
||||
AND model_id = ai_model_id
|
||||
)
|
||||
THEN openai_system_prompt
|
||||
ELSE ''
|
||||
END
|
||||
WHERE id = 0;
|
||||
|
||||
DROP TABLE legacy_openai_ai_config;
|
||||
@ -0,0 +1,3 @@
|
||||
ALTER TABLE settings ADD COLUMN mojang_auth_source TEXT NOT NULL DEFAULT 'auto' CHECK (
|
||||
mojang_auth_source IN ('auto', 'official_only', 'mirror_preferred', 'official_preferred')
|
||||
);
|
||||
@ -0,0 +1,6 @@
|
||||
CREATE TABLE instance_config_sync_state (
|
||||
instance_id TEXT NOT NULL PRIMARY KEY,
|
||||
config_updated_at INTEGER NOT NULL,
|
||||
generated_at INTEGER NULL,
|
||||
FOREIGN KEY (instance_id) REFERENCES instances(id) ON DELETE CASCADE
|
||||
);
|
||||
@ -0,0 +1,2 @@
|
||||
ALTER TABLE settings
|
||||
ADD COLUMN terracotta_public_nodes JSONB NOT NULL DEFAULT '["wss://center.node.1tmc.top"]';
|
||||
@ -0,0 +1,2 @@
|
||||
UPDATE translation_settings SET provider = 'google'
|
||||
WHERE id = 0 AND provider = 'microsoft';
|
||||
@ -0,0 +1,5 @@
|
||||
CREATE TABLE IF NOT EXISTS google_translate_ip_cache (
|
||||
ip TEXT NOT NULL PRIMARY KEY,
|
||||
latency_ms INTEGER NOT NULL,
|
||||
created_at INTEGER NOT NULL
|
||||
);
|
||||
32
packages/app-lib/migrations/20260814120000_telemetry.sql
Normal file
32
packages/app-lib/migrations/20260814120000_telemetry.sql
Normal file
@ -0,0 +1,32 @@
|
||||
ALTER TABLE settings
|
||||
ADD COLUMN telemetry_consent_version INTEGER NOT NULL DEFAULT 0;
|
||||
|
||||
CREATE TABLE telemetry_identity (
|
||||
id INTEGER NOT NULL CHECK (id = 0),
|
||||
installation_id TEXT NOT NULL,
|
||||
last_heartbeat_day TEXT NULL,
|
||||
PRIMARY KEY (id)
|
||||
);
|
||||
|
||||
CREATE TABLE telemetry_outbox (
|
||||
event_id TEXT NOT NULL,
|
||||
event_type TEXT NOT NULL CHECK (event_type IN ('heartbeat', 'error')),
|
||||
payload JSONB NOT NULL,
|
||||
created_at INTEGER NOT NULL,
|
||||
next_attempt_at INTEGER NOT NULL,
|
||||
attempts INTEGER NOT NULL DEFAULT 0,
|
||||
size_bytes INTEGER NOT NULL,
|
||||
dedupe_key TEXT NOT NULL,
|
||||
occurrence_count INTEGER NOT NULL DEFAULT 1,
|
||||
PRIMARY KEY (event_id),
|
||||
UNIQUE (dedupe_key)
|
||||
);
|
||||
|
||||
CREATE INDEX telemetry_outbox_retry
|
||||
ON telemetry_outbox (next_attempt_at, created_at);
|
||||
|
||||
CREATE TABLE telemetry_error_daily (
|
||||
day TEXT NOT NULL,
|
||||
fingerprint TEXT NOT NULL,
|
||||
PRIMARY KEY (day, fingerprint)
|
||||
);
|
||||
@ -0,0 +1,47 @@
|
||||
ALTER TABLE instance_content_entries
|
||||
ADD COLUMN auto_dependency INTEGER NOT NULL DEFAULT 0
|
||||
CHECK (auto_dependency IN (0, 1));
|
||||
|
||||
CREATE INDEX instance_content_entries_auto_dependency
|
||||
ON instance_content_entries(content_set_id, auto_dependency);
|
||||
|
||||
CREATE TABLE instance_content_dependencies (
|
||||
id TEXT NOT NULL,
|
||||
content_set_id TEXT NOT NULL,
|
||||
parent_entry_id TEXT NOT NULL,
|
||||
child_entry_id TEXT NOT NULL,
|
||||
provider TEXT NOT NULL,
|
||||
dependency_kind TEXT NOT NULL,
|
||||
parent_project_id TEXT NOT NULL,
|
||||
parent_release_id TEXT NOT NULL,
|
||||
child_project_id TEXT NOT NULL,
|
||||
child_release_id TEXT NOT NULL,
|
||||
created_at INTEGER NOT NULL,
|
||||
modified_at INTEGER NOT NULL,
|
||||
|
||||
PRIMARY KEY (id),
|
||||
UNIQUE (
|
||||
content_set_id,
|
||||
parent_entry_id,
|
||||
child_entry_id,
|
||||
dependency_kind
|
||||
),
|
||||
FOREIGN KEY (content_set_id)
|
||||
REFERENCES instance_content_sets(id)
|
||||
ON DELETE CASCADE,
|
||||
FOREIGN KEY (parent_entry_id)
|
||||
REFERENCES instance_content_entries(id)
|
||||
ON DELETE CASCADE,
|
||||
FOREIGN KEY (child_entry_id)
|
||||
REFERENCES instance_content_entries(id)
|
||||
ON DELETE CASCADE,
|
||||
CHECK (provider IN ('modrinth', 'curseforge')),
|
||||
CHECK (dependency_kind IN ('required', 'include'))
|
||||
);
|
||||
|
||||
CREATE INDEX instance_content_dependencies_child
|
||||
ON instance_content_dependencies(content_set_id, child_entry_id);
|
||||
CREATE INDEX instance_content_dependencies_parent
|
||||
ON instance_content_dependencies(content_set_id, parent_entry_id);
|
||||
CREATE INDEX instance_content_dependencies_child_project
|
||||
ON instance_content_dependencies(provider, child_project_id);
|
||||
@ -0,0 +1,56 @@
|
||||
-- Allow dependency edges between locally identified files. SQLite cannot
|
||||
-- alter a CHECK constraint, so the table is rebuilt with the widened
|
||||
-- provider constraint. Index names are recreated after the old table (and
|
||||
-- its indexes) are dropped.
|
||||
|
||||
CREATE TABLE instance_content_dependencies_local_provider (
|
||||
id TEXT NOT NULL,
|
||||
content_set_id TEXT NOT NULL,
|
||||
parent_entry_id TEXT NOT NULL,
|
||||
child_entry_id TEXT NOT NULL,
|
||||
provider TEXT NOT NULL,
|
||||
dependency_kind TEXT NOT NULL,
|
||||
parent_project_id TEXT NOT NULL,
|
||||
parent_release_id TEXT NOT NULL,
|
||||
child_project_id TEXT NOT NULL,
|
||||
child_release_id TEXT NOT NULL,
|
||||
created_at INTEGER NOT NULL,
|
||||
modified_at INTEGER NOT NULL,
|
||||
|
||||
PRIMARY KEY (id),
|
||||
UNIQUE (
|
||||
content_set_id,
|
||||
parent_entry_id,
|
||||
child_entry_id,
|
||||
dependency_kind
|
||||
),
|
||||
FOREIGN KEY (content_set_id)
|
||||
REFERENCES instance_content_sets(id)
|
||||
ON DELETE CASCADE,
|
||||
FOREIGN KEY (parent_entry_id)
|
||||
REFERENCES instance_content_entries(id)
|
||||
ON DELETE CASCADE,
|
||||
FOREIGN KEY (child_entry_id)
|
||||
REFERENCES instance_content_entries(id)
|
||||
ON DELETE CASCADE,
|
||||
CHECK (provider IN ('modrinth', 'curseforge', 'local')),
|
||||
CHECK (dependency_kind IN ('required', 'include'))
|
||||
);
|
||||
|
||||
INSERT INTO instance_content_dependencies_local_provider
|
||||
SELECT id, content_set_id, parent_entry_id, child_entry_id, provider,
|
||||
dependency_kind, parent_project_id, parent_release_id,
|
||||
child_project_id, child_release_id, created_at, modified_at
|
||||
FROM instance_content_dependencies;
|
||||
|
||||
DROP TABLE instance_content_dependencies;
|
||||
|
||||
ALTER TABLE instance_content_dependencies_local_provider
|
||||
RENAME TO instance_content_dependencies;
|
||||
|
||||
CREATE INDEX instance_content_dependencies_child
|
||||
ON instance_content_dependencies(content_set_id, child_entry_id);
|
||||
CREATE INDEX instance_content_dependencies_parent
|
||||
ON instance_content_dependencies(content_set_id, parent_entry_id);
|
||||
CREATE INDEX instance_content_dependencies_child_project
|
||||
ON instance_content_dependencies(provider, child_project_id);
|
||||
@ -0,0 +1,10 @@
|
||||
-- Track which content entries already had their CurseForge dependency
|
||||
-- relations resolved during backfill, so entries without any relations are
|
||||
-- not refetched from the API on every snapshot.
|
||||
|
||||
ALTER TABLE instance_content_entries
|
||||
ADD COLUMN dependency_backfilled INTEGER NOT NULL DEFAULT 0
|
||||
CHECK (dependency_backfilled IN (0, 1));
|
||||
|
||||
CREATE INDEX instance_content_entries_dependency_backfilled
|
||||
ON instance_content_entries(content_set_id, dependency_backfilled);
|
||||
@ -0,0 +1,8 @@
|
||||
ALTER TABLE settings
|
||||
ADD COLUMN download_engine TEXT NOT NULL DEFAULT 'xmcl';
|
||||
|
||||
UPDATE settings
|
||||
SET download_engine = CASE
|
||||
WHEN json_extract(feature_flags, '$.xmcl_download_engine') = 0 THEN 'legacy'
|
||||
ELSE 'xmcl'
|
||||
END;
|
||||
@ -0,0 +1,2 @@
|
||||
ALTER TABLE settings
|
||||
ADD COLUMN bypass_curseforge_download_restrictions INTEGER NOT NULL DEFAULT TRUE;
|
||||
@ -0,0 +1,59 @@
|
||||
-- A dependency edge can be proven by one provider while each endpoint belongs
|
||||
-- to a different provider. Rebuild because SQLite cannot tighten the existing
|
||||
-- provider CHECK constraint in place.
|
||||
CREATE TABLE instance_content_dependencies_endpoint_providers (
|
||||
id TEXT NOT NULL,
|
||||
content_set_id TEXT NOT NULL,
|
||||
parent_entry_id TEXT NOT NULL,
|
||||
child_entry_id TEXT NOT NULL,
|
||||
evidence_provider TEXT NOT NULL,
|
||||
parent_provider TEXT NOT NULL,
|
||||
child_provider TEXT NOT NULL,
|
||||
dependency_kind TEXT NOT NULL,
|
||||
parent_project_id TEXT NOT NULL,
|
||||
parent_release_id TEXT NOT NULL,
|
||||
child_project_id TEXT NOT NULL,
|
||||
child_release_id TEXT NOT NULL,
|
||||
created_at INTEGER NOT NULL,
|
||||
modified_at INTEGER NOT NULL,
|
||||
|
||||
PRIMARY KEY (id),
|
||||
UNIQUE (
|
||||
content_set_id,
|
||||
parent_entry_id,
|
||||
child_entry_id,
|
||||
dependency_kind
|
||||
),
|
||||
FOREIGN KEY (content_set_id)
|
||||
REFERENCES instance_content_sets(id)
|
||||
ON DELETE CASCADE,
|
||||
FOREIGN KEY (parent_entry_id)
|
||||
REFERENCES instance_content_entries(id)
|
||||
ON DELETE CASCADE,
|
||||
FOREIGN KEY (child_entry_id)
|
||||
REFERENCES instance_content_entries(id)
|
||||
ON DELETE CASCADE,
|
||||
CHECK (evidence_provider IN ('modrinth', 'curseforge', 'local')),
|
||||
CHECK (parent_provider IN ('modrinth', 'curseforge', 'local')),
|
||||
CHECK (child_provider IN ('modrinth', 'curseforge', 'local')),
|
||||
CHECK (dependency_kind IN ('required', 'include'))
|
||||
);
|
||||
|
||||
INSERT INTO instance_content_dependencies_endpoint_providers
|
||||
SELECT id, content_set_id, parent_entry_id, child_entry_id,
|
||||
provider, provider, provider, dependency_kind,
|
||||
parent_project_id, parent_release_id,
|
||||
child_project_id, child_release_id, created_at, modified_at
|
||||
FROM instance_content_dependencies;
|
||||
|
||||
DROP TABLE instance_content_dependencies;
|
||||
|
||||
ALTER TABLE instance_content_dependencies_endpoint_providers
|
||||
RENAME TO instance_content_dependencies;
|
||||
|
||||
CREATE INDEX instance_content_dependencies_child
|
||||
ON instance_content_dependencies(content_set_id, child_entry_id);
|
||||
CREATE INDEX instance_content_dependencies_parent
|
||||
ON instance_content_dependencies(content_set_id, parent_entry_id);
|
||||
CREATE INDEX instance_content_dependencies_child_project
|
||||
ON instance_content_dependencies(child_provider, child_project_id);
|
||||
@ -0,0 +1,3 @@
|
||||
UPDATE settings
|
||||
SET download_engine = 'legacy'
|
||||
WHERE id = 0;
|
||||
@ -0,0 +1,2 @@
|
||||
UPDATE settings
|
||||
SET mc_memory_auto = 1;
|
||||
@ -0,0 +1,3 @@
|
||||
UPDATE settings
|
||||
SET download_engine = 'xmcl'
|
||||
WHERE id = 0;
|
||||
@ -0,0 +1,84 @@
|
||||
CREATE TABLE instance_loader_components (
|
||||
instance_id TEXT NOT NULL,
|
||||
kind TEXT NOT NULL CHECK(kind IN (
|
||||
'vanilla',
|
||||
'forge',
|
||||
'neoforge',
|
||||
'fabric',
|
||||
'quilt',
|
||||
'cleanroom',
|
||||
'legacy_fabric',
|
||||
'optifine',
|
||||
'lite_loader',
|
||||
'optifabric'
|
||||
)),
|
||||
version TEXT NULL,
|
||||
role TEXT NOT NULL CHECK(role IN ('primary', 'adjunct')),
|
||||
provider_metadata TEXT NULL
|
||||
CHECK(provider_metadata IS NULL OR json_valid(provider_metadata)),
|
||||
|
||||
PRIMARY KEY (instance_id, kind),
|
||||
FOREIGN KEY (instance_id) REFERENCES instances(id) ON DELETE CASCADE
|
||||
);
|
||||
|
||||
CREATE UNIQUE INDEX instance_loader_components_primary
|
||||
ON instance_loader_components(instance_id)
|
||||
WHERE role = 'primary';
|
||||
|
||||
CREATE INDEX instance_loader_components_kind
|
||||
ON instance_loader_components(kind);
|
||||
|
||||
INSERT INTO instance_loader_components (
|
||||
instance_id,
|
||||
kind,
|
||||
version,
|
||||
role,
|
||||
provider_metadata
|
||||
)
|
||||
SELECT
|
||||
i.id,
|
||||
CASE cs.loader
|
||||
WHEN 'optifine' THEN 'vanilla'
|
||||
WHEN 'lite_loader' THEN 'vanilla'
|
||||
ELSE cs.loader
|
||||
END,
|
||||
CASE
|
||||
WHEN cs.loader IN ('optifine', 'lite_loader') THEN NULL
|
||||
ELSE cs.loader_version
|
||||
END,
|
||||
'primary',
|
||||
NULL
|
||||
FROM instances i
|
||||
INNER JOIN instance_content_sets cs
|
||||
ON cs.id = i.applied_content_set_id
|
||||
AND cs.instance_id = i.id
|
||||
WHERE cs.loader IN (
|
||||
'vanilla',
|
||||
'forge',
|
||||
'neoforge',
|
||||
'fabric',
|
||||
'quilt',
|
||||
'cleanroom',
|
||||
'legacy_fabric',
|
||||
'optifine',
|
||||
'lite_loader'
|
||||
);
|
||||
|
||||
INSERT INTO instance_loader_components (
|
||||
instance_id,
|
||||
kind,
|
||||
version,
|
||||
role,
|
||||
provider_metadata
|
||||
)
|
||||
SELECT
|
||||
i.id,
|
||||
cs.loader,
|
||||
cs.loader_version,
|
||||
'adjunct',
|
||||
NULL
|
||||
FROM instances i
|
||||
INNER JOIN instance_content_sets cs
|
||||
ON cs.id = i.applied_content_set_id
|
||||
AND cs.instance_id = i.id
|
||||
WHERE cs.loader IN ('optifine', 'lite_loader');
|
||||
@ -0,0 +1,5 @@
|
||||
ALTER TABLE settings ADD COLUMN proxy_mode TEXT NOT NULL DEFAULT 'system'
|
||||
CHECK (proxy_mode IN ('none', 'system', 'custom'));
|
||||
ALTER TABLE settings ADD COLUMN proxy_url TEXT NOT NULL DEFAULT '';
|
||||
ALTER TABLE settings ADD COLUMN proxy_username TEXT NOT NULL DEFAULT '';
|
||||
ALTER TABLE settings ADD COLUMN proxy_password TEXT NOT NULL DEFAULT '';
|
||||
@ -0,0 +1,10 @@
|
||||
CREATE TABLE content_favorites (
|
||||
provider TEXT NOT NULL CHECK (provider IN ('modrinth', 'curseforge')),
|
||||
project_id TEXT NOT NULL CHECK (length(project_id) > 0),
|
||||
content_type TEXT NOT NULL CHECK (content_type IN ('mod', 'resourcepack', 'datapack', 'shader')),
|
||||
saved_at INTEGER NOT NULL,
|
||||
|
||||
PRIMARY KEY (provider, project_id)
|
||||
);
|
||||
|
||||
CREATE INDEX content_favorites_saved_at_idx ON content_favorites (saved_at DESC);
|
||||
@ -0,0 +1,2 @@
|
||||
ALTER TABLE translation_settings ADD COLUMN deepl_api_endpoint TEXT NOT NULL DEFAULT 'https://api-free.deepl.com/v2/translate';
|
||||
ALTER TABLE translation_settings ADD COLUMN deepl_api_key TEXT NULL;
|
||||
@ -0,0 +1 @@
|
||||
ALTER TABLE settings ADD COLUMN enter_lightweight_mode_on_game_launch INTEGER NOT NULL DEFAULT FALSE;
|
||||
@ -0,0 +1,2 @@
|
||||
UPDATE settings
|
||||
SET download_engine = 'legacy';
|
||||
@ -0,0 +1,43 @@
|
||||
DROP INDEX instance_loader_components_primary;
|
||||
DROP INDEX instance_loader_components_kind;
|
||||
|
||||
ALTER TABLE instance_loader_components RENAME TO instance_loader_components_old;
|
||||
|
||||
CREATE TABLE instance_loader_components (
|
||||
instance_id TEXT NOT NULL,
|
||||
kind TEXT NOT NULL CHECK(kind IN (
|
||||
'vanilla',
|
||||
'forge',
|
||||
'neoforge',
|
||||
'fabric',
|
||||
'quilt',
|
||||
'cleanroom',
|
||||
'legacy_fabric',
|
||||
'babric',
|
||||
'optifine',
|
||||
'lite_loader',
|
||||
'optifabric'
|
||||
)),
|
||||
version TEXT NULL,
|
||||
role TEXT NOT NULL CHECK(role IN ('primary', 'adjunct')),
|
||||
provider_metadata TEXT NULL
|
||||
CHECK(provider_metadata IS NULL OR json_valid(provider_metadata)),
|
||||
|
||||
PRIMARY KEY (instance_id, kind),
|
||||
FOREIGN KEY (instance_id) REFERENCES instances(id) ON DELETE CASCADE
|
||||
);
|
||||
|
||||
INSERT INTO instance_loader_components (
|
||||
instance_id, kind, version, role, provider_metadata
|
||||
)
|
||||
SELECT instance_id, kind, version, role, provider_metadata
|
||||
FROM instance_loader_components_old;
|
||||
|
||||
DROP TABLE instance_loader_components_old;
|
||||
|
||||
CREATE UNIQUE INDEX instance_loader_components_primary
|
||||
ON instance_loader_components(instance_id)
|
||||
WHERE role = 'primary';
|
||||
|
||||
CREATE INDEX instance_loader_components_kind
|
||||
ON instance_loader_components(kind);
|
||||
@ -0,0 +1,272 @@
|
||||
DROP INDEX IF EXISTS instance_content_provider_refs_project;
|
||||
DROP INDEX IF EXISTS instance_content_provider_refs_release;
|
||||
DROP INDEX IF EXISTS instance_content_provider_refs_identity;
|
||||
DROP INDEX IF EXISTS instance_content_provider_refs_origin;
|
||||
DROP INDEX IF EXISTS instance_content_update_checks_release;
|
||||
DROP INDEX IF EXISTS instance_pack_members_content_set;
|
||||
DROP INDEX IF EXISTS instance_pack_members_content_entry;
|
||||
DROP INDEX IF EXISTS instance_pack_members_provider;
|
||||
DROP INDEX IF EXISTS instance_pack_members_state;
|
||||
DROP INDEX IF EXISTS instance_pending_manual_download_identity;
|
||||
DROP INDEX IF EXISTS instance_pending_manual_downloads_instance_state;
|
||||
DROP INDEX IF EXISTS instance_content_dependencies_child;
|
||||
DROP INDEX IF EXISTS instance_content_dependencies_parent;
|
||||
DROP INDEX IF EXISTS instance_content_dependencies_child_project;
|
||||
DROP INDEX IF EXISTS content_favorites_saved_at_idx;
|
||||
|
||||
ALTER TABLE instance_content_provider_refs RENAME TO instance_content_provider_refs_old;
|
||||
ALTER TABLE instance_content_update_checks RENAME TO instance_content_update_checks_old;
|
||||
ALTER TABLE instance_pack_members RENAME TO instance_pack_members_old;
|
||||
ALTER TABLE instance_pending_manual_downloads RENAME TO instance_pending_manual_downloads_old;
|
||||
ALTER TABLE instance_content_dependencies RENAME TO instance_content_dependencies_old;
|
||||
ALTER TABLE content_favorites RENAME TO content_favorites_old;
|
||||
|
||||
CREATE TABLE instance_content_provider_refs (
|
||||
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||
content_entry_id TEXT NOT NULL,
|
||||
provider TEXT NOT NULL,
|
||||
provider_project_id TEXT NOT NULL,
|
||||
provider_release_id TEXT NULL,
|
||||
is_origin INTEGER NOT NULL DEFAULT 0,
|
||||
|
||||
FOREIGN KEY (content_entry_id)
|
||||
REFERENCES instance_content_entries(id)
|
||||
ON DELETE CASCADE,
|
||||
CHECK (provider IN ('modrinth', 'curseforge', 'mcarchive')),
|
||||
CHECK (is_origin IN (0, 1))
|
||||
);
|
||||
|
||||
CREATE INDEX instance_content_provider_refs_project
|
||||
ON instance_content_provider_refs(provider, provider_project_id);
|
||||
CREATE INDEX instance_content_provider_refs_release
|
||||
ON instance_content_provider_refs(provider, provider_release_id);
|
||||
CREATE UNIQUE INDEX instance_content_provider_refs_identity
|
||||
ON instance_content_provider_refs(
|
||||
content_entry_id,
|
||||
provider,
|
||||
provider_project_id,
|
||||
COALESCE(provider_release_id, '')
|
||||
);
|
||||
CREATE UNIQUE INDEX instance_content_provider_refs_origin
|
||||
ON instance_content_provider_refs(content_entry_id)
|
||||
WHERE is_origin = 1;
|
||||
|
||||
INSERT INTO instance_content_provider_refs (
|
||||
id, content_entry_id, provider, provider_project_id,
|
||||
provider_release_id, is_origin
|
||||
)
|
||||
SELECT id, content_entry_id, provider, provider_project_id,
|
||||
provider_release_id, is_origin
|
||||
FROM instance_content_provider_refs_old;
|
||||
|
||||
CREATE TABLE instance_content_update_checks (
|
||||
content_entry_id TEXT NOT NULL,
|
||||
update_channel TEXT NOT NULL,
|
||||
provider TEXT NULL,
|
||||
provider_project_id TEXT NULL,
|
||||
provider_release_id TEXT NULL,
|
||||
checked_at INTEGER NOT NULL,
|
||||
|
||||
PRIMARY KEY (content_entry_id),
|
||||
FOREIGN KEY (content_entry_id)
|
||||
REFERENCES instance_content_entries(id)
|
||||
ON DELETE CASCADE,
|
||||
CHECK (provider IS NULL OR provider IN ('modrinth', 'curseforge', 'mcarchive'))
|
||||
);
|
||||
|
||||
CREATE INDEX instance_content_update_checks_release
|
||||
ON instance_content_update_checks(provider, provider_release_id);
|
||||
|
||||
INSERT INTO instance_content_update_checks (
|
||||
content_entry_id, update_channel, provider, provider_project_id,
|
||||
provider_release_id, checked_at
|
||||
)
|
||||
SELECT content_entry_id, update_channel, provider, provider_project_id,
|
||||
provider_release_id, checked_at
|
||||
FROM instance_content_update_checks_old;
|
||||
|
||||
CREATE TABLE instance_pack_members (
|
||||
id TEXT NOT NULL,
|
||||
content_set_id TEXT NOT NULL,
|
||||
content_entry_id TEXT NULL,
|
||||
member_key TEXT NOT NULL,
|
||||
project_type TEXT NOT NULL,
|
||||
expected_relative_path TEXT NOT NULL,
|
||||
provider TEXT NULL,
|
||||
provider_project_id TEXT NULL,
|
||||
provider_release_id TEXT NULL,
|
||||
required INTEGER NOT NULL DEFAULT 1,
|
||||
expected_sha1 TEXT NULL,
|
||||
expected_size INTEGER NULL,
|
||||
expected_fingerprint INTEGER NULL,
|
||||
materialization_state TEXT NOT NULL DEFAULT 'present',
|
||||
override_kind TEXT NOT NULL DEFAULT 'none',
|
||||
reconciled INTEGER NOT NULL DEFAULT 1,
|
||||
created_at INTEGER NOT NULL,
|
||||
modified_at INTEGER NOT NULL,
|
||||
|
||||
PRIMARY KEY (id),
|
||||
UNIQUE (content_set_id, member_key),
|
||||
FOREIGN KEY (content_set_id)
|
||||
REFERENCES instance_content_sets(id)
|
||||
ON DELETE CASCADE,
|
||||
FOREIGN KEY (content_entry_id)
|
||||
REFERENCES instance_content_entries(id)
|
||||
ON DELETE SET NULL,
|
||||
CHECK (provider IS NULL OR provider IN ('modrinth', 'curseforge', 'mcarchive')),
|
||||
CHECK (required IN (0, 1)),
|
||||
CHECK (materialization_state IN ('present', 'pending_manual', 'missing', 'removed')),
|
||||
CHECK (override_kind IN ('none', 'disabled', 'removed', 'version')),
|
||||
CHECK (reconciled IN (0, 1))
|
||||
);
|
||||
|
||||
CREATE INDEX instance_pack_members_content_set
|
||||
ON instance_pack_members(content_set_id);
|
||||
CREATE INDEX instance_pack_members_content_entry
|
||||
ON instance_pack_members(content_entry_id);
|
||||
CREATE INDEX instance_pack_members_provider
|
||||
ON instance_pack_members(provider, provider_project_id, provider_release_id);
|
||||
CREATE INDEX instance_pack_members_state
|
||||
ON instance_pack_members(content_set_id, materialization_state);
|
||||
|
||||
INSERT INTO instance_pack_members (
|
||||
id, content_set_id, content_entry_id, member_key, project_type,
|
||||
expected_relative_path, provider, provider_project_id, provider_release_id,
|
||||
required, expected_sha1, expected_size, expected_fingerprint,
|
||||
materialization_state, override_kind, reconciled, created_at, modified_at
|
||||
)
|
||||
SELECT id, content_set_id, content_entry_id, member_key, project_type,
|
||||
expected_relative_path, provider, provider_project_id, provider_release_id,
|
||||
required, expected_sha1, expected_size, expected_fingerprint,
|
||||
materialization_state, override_kind, reconciled, created_at, modified_at
|
||||
FROM instance_pack_members_old;
|
||||
|
||||
CREATE TABLE instance_pending_manual_downloads (
|
||||
id TEXT NOT NULL,
|
||||
instance_id TEXT NOT NULL,
|
||||
pack_member_id TEXT NULL,
|
||||
content_entry_id TEXT NULL,
|
||||
operation_kind TEXT NOT NULL,
|
||||
operation_target_id TEXT NULL,
|
||||
project_type TEXT NOT NULL,
|
||||
provider TEXT NOT NULL,
|
||||
provider_project_id TEXT NOT NULL,
|
||||
provider_release_id TEXT NOT NULL,
|
||||
file_name TEXT NOT NULL,
|
||||
website_url TEXT NULL,
|
||||
target_relative_path TEXT NOT NULL,
|
||||
expected_sha1 TEXT NULL,
|
||||
expected_size INTEGER NULL,
|
||||
expected_fingerprint INTEGER NULL,
|
||||
state TEXT NOT NULL DEFAULT 'waiting',
|
||||
context JSONB NOT NULL DEFAULT '{}',
|
||||
created_at INTEGER NOT NULL,
|
||||
modified_at INTEGER NOT NULL,
|
||||
|
||||
PRIMARY KEY (id),
|
||||
FOREIGN KEY (instance_id) REFERENCES instances(id) ON DELETE CASCADE,
|
||||
FOREIGN KEY (pack_member_id)
|
||||
REFERENCES instance_pack_members(id)
|
||||
ON DELETE CASCADE,
|
||||
FOREIGN KEY (content_entry_id)
|
||||
REFERENCES instance_content_entries(id)
|
||||
ON DELETE SET NULL,
|
||||
CHECK (provider IN ('modrinth', 'curseforge', 'mcarchive')),
|
||||
CHECK (operation_kind IN ('pack_install', 'pack_update', 'content_install', 'content_update')),
|
||||
CHECK (state IN ('waiting', 'matched', 'imported', 'error', 'cancelled'))
|
||||
);
|
||||
|
||||
CREATE UNIQUE INDEX instance_pending_manual_download_identity
|
||||
ON instance_pending_manual_downloads(
|
||||
instance_id, operation_kind, provider, provider_project_id,
|
||||
provider_release_id
|
||||
)
|
||||
WHERE state IN ('waiting', 'matched');
|
||||
CREATE INDEX instance_pending_manual_downloads_instance_state
|
||||
ON instance_pending_manual_downloads(instance_id, state);
|
||||
|
||||
INSERT INTO instance_pending_manual_downloads (
|
||||
id, instance_id, pack_member_id, content_entry_id, operation_kind,
|
||||
operation_target_id, project_type, provider, provider_project_id,
|
||||
provider_release_id, file_name, website_url, target_relative_path,
|
||||
expected_sha1, expected_size, expected_fingerprint, state, context,
|
||||
created_at, modified_at
|
||||
)
|
||||
SELECT id, instance_id, pack_member_id, content_entry_id, operation_kind,
|
||||
operation_target_id, project_type, provider, provider_project_id,
|
||||
provider_release_id, file_name, website_url, target_relative_path,
|
||||
expected_sha1, expected_size, expected_fingerprint, state, context,
|
||||
created_at, modified_at
|
||||
FROM instance_pending_manual_downloads_old;
|
||||
|
||||
CREATE TABLE instance_content_dependencies (
|
||||
id TEXT NOT NULL,
|
||||
content_set_id TEXT NOT NULL,
|
||||
parent_entry_id TEXT NOT NULL,
|
||||
child_entry_id TEXT NOT NULL,
|
||||
evidence_provider TEXT NOT NULL,
|
||||
parent_provider TEXT NOT NULL,
|
||||
child_provider TEXT NOT NULL,
|
||||
dependency_kind TEXT NOT NULL,
|
||||
parent_project_id TEXT NOT NULL,
|
||||
parent_release_id TEXT NOT NULL,
|
||||
child_project_id TEXT NOT NULL,
|
||||
child_release_id TEXT NOT NULL,
|
||||
created_at INTEGER NOT NULL,
|
||||
modified_at INTEGER NOT NULL,
|
||||
|
||||
PRIMARY KEY (id),
|
||||
UNIQUE (content_set_id, parent_entry_id, child_entry_id, dependency_kind),
|
||||
FOREIGN KEY (content_set_id)
|
||||
REFERENCES instance_content_sets(id)
|
||||
ON DELETE CASCADE,
|
||||
FOREIGN KEY (parent_entry_id)
|
||||
REFERENCES instance_content_entries(id)
|
||||
ON DELETE CASCADE,
|
||||
FOREIGN KEY (child_entry_id)
|
||||
REFERENCES instance_content_entries(id)
|
||||
ON DELETE CASCADE,
|
||||
CHECK (evidence_provider IN ('modrinth', 'curseforge', 'mcarchive', 'local')),
|
||||
CHECK (parent_provider IN ('modrinth', 'curseforge', 'mcarchive', 'local')),
|
||||
CHECK (child_provider IN ('modrinth', 'curseforge', 'mcarchive', 'local')),
|
||||
CHECK (dependency_kind IN ('required', 'include'))
|
||||
);
|
||||
|
||||
CREATE INDEX instance_content_dependencies_child
|
||||
ON instance_content_dependencies(content_set_id, child_entry_id);
|
||||
CREATE INDEX instance_content_dependencies_parent
|
||||
ON instance_content_dependencies(content_set_id, parent_entry_id);
|
||||
CREATE INDEX instance_content_dependencies_child_project
|
||||
ON instance_content_dependencies(child_provider, child_project_id);
|
||||
|
||||
INSERT INTO instance_content_dependencies (
|
||||
id, content_set_id, parent_entry_id, child_entry_id, evidence_provider,
|
||||
parent_provider, child_provider, dependency_kind, parent_project_id,
|
||||
parent_release_id, child_project_id, child_release_id, created_at, modified_at
|
||||
)
|
||||
SELECT id, content_set_id, parent_entry_id, child_entry_id, evidence_provider,
|
||||
parent_provider, child_provider, dependency_kind, parent_project_id,
|
||||
parent_release_id, child_project_id, child_release_id, created_at, modified_at
|
||||
FROM instance_content_dependencies_old;
|
||||
|
||||
CREATE TABLE content_favorites (
|
||||
provider TEXT NOT NULL CHECK (provider IN ('modrinth', 'curseforge', 'mcarchive')),
|
||||
project_id TEXT NOT NULL CHECK (length(project_id) > 0),
|
||||
content_type TEXT NOT NULL CHECK (content_type IN ('mod', 'resourcepack', 'datapack', 'shader')),
|
||||
saved_at INTEGER NOT NULL,
|
||||
|
||||
PRIMARY KEY (provider, project_id)
|
||||
);
|
||||
|
||||
CREATE INDEX content_favorites_saved_at_idx ON content_favorites (saved_at DESC);
|
||||
|
||||
INSERT INTO content_favorites (provider, project_id, content_type, saved_at)
|
||||
SELECT provider, project_id, content_type, saved_at
|
||||
FROM content_favorites_old;
|
||||
|
||||
DROP TABLE instance_pending_manual_downloads_old;
|
||||
DROP TABLE instance_pack_members_old;
|
||||
DROP TABLE instance_content_update_checks_old;
|
||||
DROP TABLE instance_content_provider_refs_old;
|
||||
DROP TABLE instance_content_dependencies_old;
|
||||
DROP TABLE content_favorites_old;
|
||||
@ -0,0 +1,56 @@
|
||||
DROP INDEX IF EXISTS instance_content_provider_refs_project;
|
||||
DROP INDEX IF EXISTS instance_content_provider_refs_release;
|
||||
DROP INDEX IF EXISTS instance_content_provider_refs_identity;
|
||||
DROP INDEX IF EXISTS instance_content_provider_refs_origin;
|
||||
|
||||
ALTER TABLE instance_content_provider_refs RENAME TO instance_content_provider_refs_old;
|
||||
|
||||
CREATE TABLE instance_content_provider_refs (
|
||||
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||
content_entry_id TEXT NOT NULL,
|
||||
provider TEXT NOT NULL,
|
||||
provider_project_id TEXT NOT NULL,
|
||||
provider_release_id TEXT NULL,
|
||||
provider_file_id TEXT NULL,
|
||||
is_origin INTEGER NOT NULL DEFAULT 0,
|
||||
|
||||
FOREIGN KEY (content_entry_id)
|
||||
REFERENCES instance_content_entries(id)
|
||||
ON DELETE CASCADE,
|
||||
CHECK (provider IN ('modrinth', 'curseforge', 'mcarchive')),
|
||||
CHECK (is_origin IN (0, 1))
|
||||
);
|
||||
|
||||
CREATE INDEX instance_content_provider_refs_project
|
||||
ON instance_content_provider_refs(provider, provider_project_id);
|
||||
CREATE INDEX instance_content_provider_refs_release
|
||||
ON instance_content_provider_refs(provider, provider_release_id);
|
||||
CREATE INDEX instance_content_provider_refs_file
|
||||
ON instance_content_provider_refs(provider, provider_file_id);
|
||||
CREATE UNIQUE INDEX instance_content_provider_refs_identity
|
||||
ON instance_content_provider_refs(
|
||||
content_entry_id,
|
||||
provider,
|
||||
provider_project_id,
|
||||
COALESCE(provider_release_id, ''),
|
||||
COALESCE(provider_file_id, '')
|
||||
);
|
||||
CREATE UNIQUE INDEX instance_content_provider_refs_origin
|
||||
ON instance_content_provider_refs(content_entry_id)
|
||||
WHERE is_origin = 1;
|
||||
|
||||
INSERT INTO instance_content_provider_refs (
|
||||
id, content_entry_id, provider, provider_project_id,
|
||||
provider_release_id, provider_file_id, is_origin
|
||||
)
|
||||
SELECT
|
||||
id,
|
||||
content_entry_id,
|
||||
provider,
|
||||
provider_project_id,
|
||||
provider_release_id,
|
||||
CASE WHEN provider = 'curseforge' THEN provider_release_id ELSE NULL END,
|
||||
is_origin
|
||||
FROM instance_content_provider_refs_old;
|
||||
|
||||
DROP TABLE instance_content_provider_refs_old;
|
||||
@ -0,0 +1,9 @@
|
||||
CREATE TABLE crash_analysis_ai_settings (
|
||||
id INTEGER NOT NULL CHECK (id = 0),
|
||||
enabled INTEGER NOT NULL DEFAULT FALSE,
|
||||
provider_id TEXT NOT NULL DEFAULT '',
|
||||
model_id TEXT NOT NULL DEFAULT '',
|
||||
PRIMARY KEY (id)
|
||||
);
|
||||
|
||||
INSERT INTO crash_analysis_ai_settings (id) VALUES (0);
|
||||
@ -0,0 +1,7 @@
|
||||
CREATE TABLE crash_analysis_mod_snapshots (
|
||||
instance_id TEXT NOT NULL,
|
||||
filename TEXT NOT NULL,
|
||||
size INTEGER NOT NULL,
|
||||
sha256 TEXT NOT NULL,
|
||||
PRIMARY KEY (instance_id, filename)
|
||||
);
|
||||
@ -0,0 +1,5 @@
|
||||
ALTER TABLE crash_analysis_mod_snapshots ADD COLUMN project_id TEXT;
|
||||
ALTER TABLE crash_analysis_mod_snapshots ADD COLUMN project_title TEXT;
|
||||
ALTER TABLE crash_analysis_mod_snapshots ADD COLUMN icon_url TEXT;
|
||||
ALTER TABLE crash_analysis_mod_snapshots ADD COLUMN version_id TEXT;
|
||||
ALTER TABLE crash_analysis_mod_snapshots ADD COLUMN version_number TEXT;
|
||||
@ -0,0 +1,9 @@
|
||||
CREATE TABLE instance_post_upgrade_notices (
|
||||
instance_id TEXT PRIMARY KEY NOT NULL REFERENCES instances(id) ON DELETE CASCADE,
|
||||
upgrade_job_id TEXT NOT NULL,
|
||||
target_game_version TEXT NOT NULL,
|
||||
consecutive_clean_launches INTEGER NOT NULL DEFAULT 0,
|
||||
warnings_json TEXT NOT NULL,
|
||||
created TEXT NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
modified TEXT NOT NULL DEFAULT CURRENT_TIMESTAMP
|
||||
);
|
||||
@ -0,0 +1,2 @@
|
||||
ALTER TABLE instances
|
||||
ADD COLUMN game_dir_override TEXT;
|
||||
@ -0,0 +1,3 @@
|
||||
ALTER TABLE settings ADD COLUMN close_behavior TEXT NOT NULL DEFAULT 'ask' CHECK (
|
||||
close_behavior IN ('ask', 'close', 'lightweight')
|
||||
);
|
||||
@ -0,0 +1,8 @@
|
||||
-- Direct association ("直接关联") instances point at an externally managed
|
||||
-- traditional .minecraft layout without copying, symlinking, or reinstalling
|
||||
-- anything. All columns are NULL for ordinary and pre-migration instances.
|
||||
ALTER TABLE instances ADD COLUMN linked_launcher TEXT NULL;
|
||||
ALTER TABLE instances ADD COLUMN linked_launcher_root TEXT NULL;
|
||||
ALTER TABLE instances ADD COLUMN linked_dot_minecraft TEXT NULL;
|
||||
ALTER TABLE instances ADD COLUMN linked_version_id TEXT NULL;
|
||||
ALTER TABLE instances ADD COLUMN linked_version_json_path TEXT NULL;
|
||||
@ -0,0 +1,5 @@
|
||||
-- Error telemetry is no longer collected or uploaded. Remove legacy local
|
||||
-- samples and queued error payloads while retaining the tables for upgrades
|
||||
-- from older installations.
|
||||
DELETE FROM telemetry_outbox WHERE event_type <> 'heartbeat';
|
||||
DELETE FROM telemetry_error_daily;
|
||||
@ -0,0 +1 @@
|
||||
ALTER TABLE settings ADD COLUMN mc_maximize_window INTEGER NOT NULL DEFAULT FALSE;
|
||||
@ -0,0 +1,4 @@
|
||||
-- The selected external-root layout is recorded per linked instance so it
|
||||
-- remains stable after Settings closes and across application restarts.
|
||||
-- NULL keeps the legacy launcher-specific automatic behavior.
|
||||
ALTER TABLE instances ADD COLUMN linked_game_dir_mode TEXT NULL;
|
||||
Reference in New Issue
Block a user