diff --git a/.env.example b/.env.example index 0310196a..4b2539ae 100644 --- a/.env.example +++ b/.env.example @@ -31,4 +31,16 @@ DISABLE_DOWNLOAD_COUNTS=0 # Path where uploaded files are stored on disk (default: ./storage) # The reverse proxy must serve {STORAGE_PATH}/submission_attachments/ at /storage/submission-attachments/ -STORAGE_PATH=./storage \ No newline at end of file +STORAGE_PATH=./storage + +# Used for S3-compatible APIs (R2). Automatically disabled if STORAGE_PROVIDER is not set. +# Currently only supports AWS S3 ('aws') and Cloudflare R2 ('cloudflare'), but providers with an identical API may work too. +STORAGE_PROVIDER= +STORAGE_BUCKET= +STORAGE_PUBLIC_URL= +STORAGE_ACCESS_KEY= +STORAGE_SECRET_KEY= +# only applies to AWS S3 +STORAGE_REGION= +# only applies to Cloudflare R2 +STORAGE_ACCOUNT_ID= diff --git a/.sqlx/query-01959e9a4fdc1c6b0d9dbeff80c79a58e0bae2d79af6c2b9e53ead7d9b6e214d.json b/.sqlx/query-01959e9a4fdc1c6b0d9dbeff80c79a58e0bae2d79af6c2b9e53ead7d9b6e214d.json index 5ff525a7..6c8bf7be 100644 --- a/.sqlx/query-01959e9a4fdc1c6b0d9dbeff80c79a58e0bae2d79af6c2b9e53ead7d9b6e214d.json +++ b/.sqlx/query-01959e9a4fdc1c6b0d9dbeff80c79a58e0bae2d79af6c2b9e53ead7d9b6e214d.json @@ -6,22 +6,46 @@ { "ordinal": 0, "name": "id", - "type_info": "Int4" + "type_info": "Int4", + "origin": { + "Table": { + "table": "mod_tags", + "name": "id" + } + } }, { "ordinal": 1, "name": "name", - "type_info": "Text" + "type_info": "Text", + "origin": { + "Table": { + "table": "mod_tags", + "name": "name" + } + } }, { "ordinal": 2, "name": "display_name", - "type_info": "Text" + "type_info": "Text", + "origin": { + "Table": { + "table": "mod_tags", + "name": "display_name" + } + } }, { "ordinal": 3, "name": "is_readonly", - "type_info": "Bool" + "type_info": "Bool", + "origin": { + "Table": { + "table": "mod_tags", + "name": "is_readonly" + } + } } ], "parameters": { diff --git a/.sqlx/query-0333e917f75fd481ec494abb6e2853cb699faca7c34507e314ae5225b592ed87.json b/.sqlx/query-0333e917f75fd481ec494abb6e2853cb699faca7c34507e314ae5225b592ed87.json index fe65757c..3d12ae85 100644 --- a/.sqlx/query-0333e917f75fd481ec494abb6e2853cb699faca7c34507e314ae5225b592ed87.json +++ b/.sqlx/query-0333e917f75fd481ec494abb6e2853cb699faca7c34507e314ae5225b592ed87.json @@ -6,32 +6,68 @@ { "ordinal": 0, "name": "id", - "type_info": "Int4" + "type_info": "Int4", + "origin": { + "Table": { + "table": "developers", + "name": "id" + } + } }, { "ordinal": 1, "name": "username", - "type_info": "Text" + "type_info": "Text", + "origin": { + "Table": { + "table": "developers", + "name": "username" + } + } }, { "ordinal": 2, "name": "display_name", - "type_info": "Text" + "type_info": "Text", + "origin": { + "Table": { + "table": "developers", + "name": "display_name" + } + } }, { "ordinal": 3, "name": "verified", - "type_info": "Bool" + "type_info": "Bool", + "origin": { + "Table": { + "table": "developers", + "name": "verified" + } + } }, { "ordinal": 4, "name": "admin", - "type_info": "Bool" + "type_info": "Bool", + "origin": { + "Table": { + "table": "developers", + "name": "admin" + } + } }, { "ordinal": 5, "name": "github_id", - "type_info": "Int8" + "type_info": "Int8", + "origin": { + "Table": { + "table": "developers", + "name": "github_user_id" + } + } } ], "parameters": { diff --git a/.sqlx/query-0411ef36ab03892ea4fcf4bb8e7ac1a75139bf9937a76d542e0fc3361fe156d1.json b/.sqlx/query-0411ef36ab03892ea4fcf4bb8e7ac1a75139bf9937a76d542e0fc3361fe156d1.json index 0bb81ef3..9e278c46 100644 --- a/.sqlx/query-0411ef36ab03892ea4fcf4bb8e7ac1a75139bf9937a76d542e0fc3361fe156d1.json +++ b/.sqlx/query-0411ef36ab03892ea4fcf4bb8e7ac1a75139bf9937a76d542e0fc3361fe156d1.json @@ -6,7 +6,8 @@ { "ordinal": 0, "name": "count", - "type_info": "Int8" + "type_info": "Int8", + "origin": "Expression" } ], "parameters": { diff --git a/.sqlx/query-0519d0d7c6d97ffbff763ba2d1c85b2bc796c64f42f15f078a5639f717aa21b9.json b/.sqlx/query-0519d0d7c6d97ffbff763ba2d1c85b2bc796c64f42f15f078a5639f717aa21b9.json index 0ceae2aa..fb10ac6c 100644 --- a/.sqlx/query-0519d0d7c6d97ffbff763ba2d1c85b2bc796c64f42f15f078a5639f717aa21b9.json +++ b/.sqlx/query-0519d0d7c6d97ffbff763ba2d1c85b2bc796c64f42f15f078a5639f717aa21b9.json @@ -6,22 +6,46 @@ { "ordinal": 0, "name": "id", - "type_info": "Int8" + "type_info": "Int8", + "origin": { + "Table": { + "table": "mod_version_submission_comment_attachments", + "name": "id" + } + } }, { "ordinal": 1, "name": "comment_id", - "type_info": "Int8" + "type_info": "Int8", + "origin": { + "Table": { + "table": "mod_version_submission_comment_attachments", + "name": "comment_id" + } + } }, { "ordinal": 2, "name": "filename", - "type_info": "Text" + "type_info": "Text", + "origin": { + "Table": { + "table": "mod_version_submission_comment_attachments", + "name": "filename" + } + } }, { "ordinal": 3, "name": "created_at", - "type_info": "Timestamptz" + "type_info": "Timestamptz", + "origin": { + "Table": { + "table": "mod_version_submission_comment_attachments", + "name": "created_at" + } + } } ], "parameters": { diff --git a/.sqlx/query-0a18d6fc5b51dc801d8e674590b2d609e107196eca233278f827f11c242b6e38.json b/.sqlx/query-0a18d6fc5b51dc801d8e674590b2d609e107196eca233278f827f11c242b6e38.json index c4f65465..09de68c8 100644 --- a/.sqlx/query-0a18d6fc5b51dc801d8e674590b2d609e107196eca233278f827f11c242b6e38.json +++ b/.sqlx/query-0a18d6fc5b51dc801d8e674590b2d609e107196eca233278f827f11c242b6e38.json @@ -6,12 +6,14 @@ { "ordinal": 0, "name": "id_count", - "type_info": "Int8" + "type_info": "Int8", + "origin": "Expression" }, { "ordinal": 1, "name": "download_sum", - "type_info": "Int8" + "type_info": "Int8", + "origin": "Expression" } ], "parameters": { diff --git a/.sqlx/query-0a9a3184f02328c15c2928ab6a39bc6167fe80a2e7eae6c06390b92538347e33.json b/.sqlx/query-0a9a3184f02328c15c2928ab6a39bc6167fe80a2e7eae6c06390b92538347e33.json new file mode 100644 index 00000000..ff38696a --- /dev/null +++ b/.sqlx/query-0a9a3184f02328c15c2928ab6a39bc6167fe80a2e7eae6c06390b92538347e33.json @@ -0,0 +1,15 @@ +{ + "db_name": "PostgreSQL", + "query": "UPDATE mod_versions SET managed_download_link = $1 WHERE id = $2", + "describe": { + "columns": [], + "parameters": { + "Left": [ + "Text", + "Int4" + ] + }, + "nullable": [] + }, + "hash": "0a9a3184f02328c15c2928ab6a39bc6167fe80a2e7eae6c06390b92538347e33" +} diff --git a/.sqlx/query-0eed3c807b61381f067354bf1f573587610f5e01e75b3d205401623af7a94d65.json b/.sqlx/query-0eed3c807b61381f067354bf1f573587610f5e01e75b3d205401623af7a94d65.json index 2cf06ce9..77e7feca 100644 --- a/.sqlx/query-0eed3c807b61381f067354bf1f573587610f5e01e75b3d205401623af7a94d65.json +++ b/.sqlx/query-0eed3c807b61381f067354bf1f573587610f5e01e75b3d205401623af7a94d65.json @@ -6,7 +6,13 @@ { "ordinal": 0, "name": "ip", - "type_info": "Inet" + "type_info": "Inet", + "origin": { + "Table": { + "table": "mod_downloads", + "name": "ip" + } + } } ], "parameters": { diff --git a/.sqlx/query-1303aee56285c1870f8808999c22525567231dc56cb1663c4e41aec26ffa6799.json b/.sqlx/query-1303aee56285c1870f8808999c22525567231dc56cb1663c4e41aec26ffa6799.json deleted file mode 100644 index 31521bf7..00000000 --- a/.sqlx/query-1303aee56285c1870f8808999c22525567231dc56cb1663c4e41aec26ffa6799.json +++ /dev/null @@ -1,144 +0,0 @@ -{ - "db_name": "PostgreSQL", - "query": "SELECT\n mv.id, mv.name, mv.description, mv.version,\n mv.download_link, mv.download_count, mv.hash,\n format_semver(mv.geode_major, mv.geode_minor, mv.geode_patch, mv.geode_meta) as \"geode!: _\",\n mv.early_load, mv.requires_patching, mv.api, mv.mod_id,\n mv.created_at, mv.updated_at,\n mvs.status as \"status: _\", mvs.info\n FROM mod_versions mv\n INNER JOIN mod_version_statuses mvs ON mvs.mod_version_id = mv.id\n WHERE mv.mod_id = $1\n AND ($2::mod_version_status[] IS NULL OR mvs.status = ANY($2))\n ORDER BY mv.id DESC", - "describe": { - "columns": [ - { - "ordinal": 0, - "name": "id", - "type_info": "Int4" - }, - { - "ordinal": 1, - "name": "name", - "type_info": "Text" - }, - { - "ordinal": 2, - "name": "description", - "type_info": "Text" - }, - { - "ordinal": 3, - "name": "version", - "type_info": "Text" - }, - { - "ordinal": 4, - "name": "download_link", - "type_info": "Text" - }, - { - "ordinal": 5, - "name": "download_count", - "type_info": "Int4" - }, - { - "ordinal": 6, - "name": "hash", - "type_info": "Text" - }, - { - "ordinal": 7, - "name": "geode!: _", - "type_info": "Text" - }, - { - "ordinal": 8, - "name": "early_load", - "type_info": "Bool" - }, - { - "ordinal": 9, - "name": "requires_patching", - "type_info": "Bool" - }, - { - "ordinal": 10, - "name": "api", - "type_info": "Bool" - }, - { - "ordinal": 11, - "name": "mod_id", - "type_info": "Text" - }, - { - "ordinal": 12, - "name": "created_at", - "type_info": "Timestamptz" - }, - { - "ordinal": 13, - "name": "updated_at", - "type_info": "Timestamptz" - }, - { - "ordinal": 14, - "name": "status: _", - "type_info": { - "Custom": { - "name": "mod_version_status", - "kind": { - "Enum": [ - "pending", - "rejected", - "accepted", - "unlisted" - ] - } - } - } - }, - { - "ordinal": 15, - "name": "info", - "type_info": "Text" - } - ], - "parameters": { - "Left": [ - "Text", - { - "Custom": { - "name": "mod_version_status[]", - "kind": { - "Array": { - "Custom": { - "name": "mod_version_status", - "kind": { - "Enum": [ - "pending", - "rejected", - "accepted", - "unlisted" - ] - } - } - } - } - } - } - ] - }, - "nullable": [ - false, - false, - true, - false, - false, - false, - false, - null, - false, - false, - false, - false, - true, - true, - false, - true - ] - }, - "hash": "1303aee56285c1870f8808999c22525567231dc56cb1663c4e41aec26ffa6799" -} diff --git a/.sqlx/query-181036cd0f64802504fe5025f18b076dc43adb58d626d76818d73fc3a762ba91.json b/.sqlx/query-181036cd0f64802504fe5025f18b076dc43adb58d626d76818d73fc3a762ba91.json index cbde480a..67e736d0 100644 --- a/.sqlx/query-181036cd0f64802504fe5025f18b076dc43adb58d626d76818d73fc3a762ba91.json +++ b/.sqlx/query-181036cd0f64802504fe5025f18b076dc43adb58d626d76818d73fc3a762ba91.json @@ -6,17 +6,35 @@ { "ordinal": 0, "name": "id", - "type_info": "Int4" + "type_info": "Int4", + "origin": { + "Table": { + "table": "deprecations", + "name": "id" + } + } }, { "ordinal": 1, "name": "mod_id", - "type_info": "Text" + "type_info": "Text", + "origin": { + "Table": { + "table": "deprecations", + "name": "mod_id" + } + } }, { "ordinal": 2, "name": "reason", - "type_info": "Text" + "type_info": "Text", + "origin": { + "Table": { + "table": "deprecations", + "name": "reason" + } + } } ], "parameters": { diff --git a/.sqlx/query-1ed87bd1d14f9c1febbb2a2a2d11eb3d413d28283d97c0b9bfca6f4ca3c80256.json b/.sqlx/query-1ed87bd1d14f9c1febbb2a2a2d11eb3d413d28283d97c0b9bfca6f4ca3c80256.json index 5651f29b..c418db56 100644 --- a/.sqlx/query-1ed87bd1d14f9c1febbb2a2a2d11eb3d413d28283d97c0b9bfca6f4ca3c80256.json +++ b/.sqlx/query-1ed87bd1d14f9c1febbb2a2a2d11eb3d413d28283d97c0b9bfca6f4ca3c80256.json @@ -6,32 +6,68 @@ { "ordinal": 0, "name": "id", - "type_info": "Int4" + "type_info": "Int4", + "origin": { + "Table": { + "table": "developers", + "name": "id" + } + } }, { "ordinal": 1, "name": "username", - "type_info": "Text" + "type_info": "Text", + "origin": { + "Table": { + "table": "developers", + "name": "username" + } + } }, { "ordinal": 2, "name": "display_name", - "type_info": "Text" + "type_info": "Text", + "origin": { + "Table": { + "table": "developers", + "name": "display_name" + } + } }, { "ordinal": 3, "name": "verified", - "type_info": "Bool" + "type_info": "Bool", + "origin": { + "Table": { + "table": "developers", + "name": "verified" + } + } }, { "ordinal": 4, "name": "admin", - "type_info": "Bool" + "type_info": "Bool", + "origin": { + "Table": { + "table": "developers", + "name": "admin" + } + } }, { "ordinal": 5, "name": "github_id", - "type_info": "Int8" + "type_info": "Int8", + "origin": { + "Table": { + "table": "developers", + "name": "github_user_id" + } + } } ], "parameters": { diff --git a/.sqlx/query-1ee95124185a80b20fffcc2ca64084ef1440d4a166a1296bedf9529395272486.json b/.sqlx/query-1ee95124185a80b20fffcc2ca64084ef1440d4a166a1296bedf9529395272486.json index 5b67d135..edb322c8 100644 --- a/.sqlx/query-1ee95124185a80b20fffcc2ca64084ef1440d4a166a1296bedf9529395272486.json +++ b/.sqlx/query-1ee95124185a80b20fffcc2ca64084ef1440d4a166a1296bedf9529395272486.json @@ -6,32 +6,68 @@ { "ordinal": 0, "name": "id", - "type_info": "Int8" + "type_info": "Int8", + "origin": { + "Table": { + "table": "mod_version_submission_comments", + "name": "id" + } + } }, { "ordinal": 1, "name": "submission_id", - "type_info": "Int4" + "type_info": "Int4", + "origin": { + "Table": { + "table": "mod_version_submission_comments", + "name": "submission_id" + } + } }, { "ordinal": 2, "name": "comment", - "type_info": "Text" + "type_info": "Text", + "origin": { + "Table": { + "table": "mod_version_submission_comments", + "name": "comment" + } + } }, { "ordinal": 3, "name": "author_id", - "type_info": "Int4" + "type_info": "Int4", + "origin": { + "Table": { + "table": "mod_version_submission_comments", + "name": "author_id" + } + } }, { "ordinal": 4, "name": "created_at", - "type_info": "Timestamptz" + "type_info": "Timestamptz", + "origin": { + "Table": { + "table": "mod_version_submission_comments", + "name": "created_at" + } + } }, { "ordinal": 5, "name": "updated_at", - "type_info": "Timestamptz" + "type_info": "Timestamptz", + "origin": { + "Table": { + "table": "mod_version_submission_comments", + "name": "updated_at" + } + } } ], "parameters": { diff --git a/.sqlx/query-20cc5dba1dbe11790912ff32e24a757ad86edfe06094087b2654c9428a2469d6.json b/.sqlx/query-20cc5dba1dbe11790912ff32e24a757ad86edfe06094087b2654c9428a2469d6.json index d157eb8a..af0ceae3 100644 --- a/.sqlx/query-20cc5dba1dbe11790912ff32e24a757ad86edfe06094087b2654c9428a2469d6.json +++ b/.sqlx/query-20cc5dba1dbe11790912ff32e24a757ad86edfe06094087b2654c9428a2469d6.json @@ -6,37 +6,79 @@ { "ordinal": 0, "name": "id", - "type_info": "Text" + "type_info": "Text", + "origin": { + "Table": { + "table": "mods", + "name": "id" + } + } }, { "ordinal": 1, "name": "featured", - "type_info": "Bool" + "type_info": "Bool", + "origin": { + "Table": { + "table": "mods", + "name": "featured" + } + } }, { "ordinal": 2, "name": "mod_download_count", - "type_info": "Int4" + "type_info": "Int4", + "origin": { + "Table": { + "table": "mods", + "name": "download_count" + } + } }, { "ordinal": 3, "name": "name", - "type_info": "Text" + "type_info": "Text", + "origin": { + "Table": { + "table": "mod_versions", + "name": "name" + } + } }, { "ordinal": 4, "name": "version", - "type_info": "Text" + "type_info": "Text", + "origin": { + "Table": { + "table": "mod_versions", + "name": "version" + } + } }, { "ordinal": 5, "name": "mod_version_download_count", - "type_info": "Int4" + "type_info": "Int4", + "origin": { + "Table": { + "table": "mod_versions", + "name": "download_count" + } + } }, { "ordinal": 6, "name": "info", - "type_info": "Text" + "type_info": "Text", + "origin": { + "Table": { + "table": "mod_version_statuses", + "name": "info" + } + } }, { "ordinal": 7, @@ -53,12 +95,19 @@ ] } } + }, + "origin": { + "Table": { + "table": "mod_version_statuses", + "name": "status" + } } }, { "ordinal": 8, "name": "validated!: _", - "type_info": "Bool" + "type_info": "Bool", + "origin": "Expression" } ], "parameters": { diff --git a/.sqlx/query-25e42d6a179e920a58a6034b724700f96676190fca5b0a7e11eb036e523e33d5.json b/.sqlx/query-25e42d6a179e920a58a6034b724700f96676190fca5b0a7e11eb036e523e33d5.json index 52af53ec..b474a14d 100644 --- a/.sqlx/query-25e42d6a179e920a58a6034b724700f96676190fca5b0a7e11eb036e523e33d5.json +++ b/.sqlx/query-25e42d6a179e920a58a6034b724700f96676190fca5b0a7e11eb036e523e33d5.json @@ -6,17 +6,35 @@ { "ordinal": 0, "name": "mod_version_id", - "type_info": "Int4" + "type_info": "Int4", + "origin": { + "Table": { + "table": "dependencies", + "name": "dependent_id" + } + } }, { "ordinal": 1, "name": "dependency_id", - "type_info": "Text" + "type_info": "Text", + "origin": { + "Table": { + "table": "dependencies", + "name": "dependency_id" + } + } }, { "ordinal": 2, "name": "version", - "type_info": "Text" + "type_info": "Text", + "origin": { + "Table": { + "table": "dependencies", + "name": "version" + } + } }, { "ordinal": 3, @@ -34,6 +52,12 @@ ] } } + }, + "origin": { + "Table": { + "table": "dependencies", + "name": "compare" + } } }, { @@ -50,6 +74,12 @@ ] } } + }, + "origin": { + "Table": { + "table": "dependencies", + "name": "importance" + } } } ], diff --git a/.sqlx/query-270c2e5479f104bdb52357cedb9813b6e0ebb2708fe344fd8c3914bb5971d914.json b/.sqlx/query-270c2e5479f104bdb52357cedb9813b6e0ebb2708fe344fd8c3914bb5971d914.json new file mode 100644 index 00000000..9b7aaadc --- /dev/null +++ b/.sqlx/query-270c2e5479f104bdb52357cedb9813b6e0ebb2708fe344fd8c3914bb5971d914.json @@ -0,0 +1,93 @@ +{ + "db_name": "PostgreSQL", + "query": "SELECT mv.id, mv.version, mv.managed_download_link, mv.mod_id FROM mod_versions mv\n WHERE managed_download_link IS NOT NULL\n AND mv.id NOT IN (\n SELECT DISTINCT ON (q.mv_id) q.mv_id FROM (\n SELECT DISTINCT ON (m.id, mgv.gd, mv.geode_major) m.id, mv.name, mv.version, mv.download_link, mv.managed_download_link, mv.id as mv_id, mgv.gd\n FROM MODS m\n INNER JOIN mod_versions mv ON m.id = mv.mod_id\n INNER JOIN mod_version_statuses mvs ON mvs.mod_version_id = mv.id\n INNER JOIN mod_gd_versions mgv ON mgv.mod_id = mv.id\n WHERE mvs.status = 'accepted' AND mgv.gd = ANY($1::gd_version[])\n ORDER BY m.id, mgv.gd DESC, mv.geode_major DESC, mv.id DESC\n ) q\n ORDER BY q.mv_id\n )\n ", + "describe": { + "columns": [ + { + "ordinal": 0, + "name": "id", + "type_info": "Int4", + "origin": { + "Table": { + "table": "mod_versions", + "name": "id" + } + } + }, + { + "ordinal": 1, + "name": "version", + "type_info": "Text", + "origin": { + "Table": { + "table": "mod_versions", + "name": "version" + } + } + }, + { + "ordinal": 2, + "name": "managed_download_link", + "type_info": "Text", + "origin": { + "Table": { + "table": "mod_versions", + "name": "managed_download_link" + } + } + }, + { + "ordinal": 3, + "name": "mod_id", + "type_info": "Text", + "origin": { + "Table": { + "table": "mod_versions", + "name": "mod_id" + } + } + } + ], + "parameters": { + "Left": [ + { + "Custom": { + "name": "gd_version[]", + "kind": { + "Array": { + "Custom": { + "name": "gd_version", + "kind": { + "Enum": [ + "*", + "2.113", + "2.200", + "2.204", + "2.205", + "2.206", + "2.207", + "2.2071", + "2.2072", + "2.2073", + "2.2074", + "2.208", + "2.2081", + "2.2082" + ] + } + } + } + } + } + } + ] + }, + "nullable": [ + false, + false, + true, + false + ] + }, + "hash": "270c2e5479f104bdb52357cedb9813b6e0ebb2708fe344fd8c3914bb5971d914" +} diff --git a/.sqlx/query-27c67f136d2f37a916b0bfb8d4966304005a571cd8871cc84b2010315c7d9692.json b/.sqlx/query-27c67f136d2f37a916b0bfb8d4966304005a571cd8871cc84b2010315c7d9692.json index a117b30e..337a1098 100644 --- a/.sqlx/query-27c67f136d2f37a916b0bfb8d4966304005a571cd8871cc84b2010315c7d9692.json +++ b/.sqlx/query-27c67f136d2f37a916b0bfb8d4966304005a571cd8871cc84b2010315c7d9692.json @@ -6,7 +6,13 @@ { "ordinal": 0, "name": "id", - "type_info": "Int4" + "type_info": "Int4", + "origin": { + "Table": { + "table": "mod_versions", + "name": "id" + } + } } ], "parameters": { diff --git a/.sqlx/query-2894a3bf8b4f43496a3a1532ba1e630726cf78d354b586094b1ee8c16a6fe9ee.json b/.sqlx/query-2894a3bf8b4f43496a3a1532ba1e630726cf78d354b586094b1ee8c16a6fe9ee.json new file mode 100644 index 00000000..91dd8c23 --- /dev/null +++ b/.sqlx/query-2894a3bf8b4f43496a3a1532ba1e630726cf78d354b586094b1ee8c16a6fe9ee.json @@ -0,0 +1,324 @@ +{ + "db_name": "PostgreSQL", + "query": "SELECT\n m.id, m.repository, m.about, m.changelog, m.featured, m.download_count as mod_download_count, m.created_at, m.updated_at,\n mv.id as version_id, mv.name, mv.description, mv.version, mv.download_link, mv.managed_download_link,\n mv.download_count as mod_version_download_count, mv.created_at as mod_version_created_at, mv.updated_at as mod_version_updated_at, mv.hash,\n format_semver(mv.geode_major, mv.geode_minor, mv.geode_patch, mv.geode_meta) as \"geode!: _\",\n mv.early_load, mv.requires_patching, mv.api, mv.mod_id, mvs.status as \"status: _\", mvs.info\n FROM mods m\n INNER JOIN mod_versions mv ON m.id = mv.mod_id\n INNER JOIN mod_version_statuses mvs ON mvs.mod_version_id = mv.id\n WHERE m.id = $1\n AND ($2 = false OR mvs.status = 'accepted')\n ORDER BY mv.id DESC", + "describe": { + "columns": [ + { + "ordinal": 0, + "name": "id", + "type_info": "Text", + "origin": { + "Table": { + "table": "mods", + "name": "id" + } + } + }, + { + "ordinal": 1, + "name": "repository", + "type_info": "Text", + "origin": { + "Table": { + "table": "mods", + "name": "repository" + } + } + }, + { + "ordinal": 2, + "name": "about", + "type_info": "Text", + "origin": { + "Table": { + "table": "mods", + "name": "about" + } + } + }, + { + "ordinal": 3, + "name": "changelog", + "type_info": "Text", + "origin": { + "Table": { + "table": "mods", + "name": "changelog" + } + } + }, + { + "ordinal": 4, + "name": "featured", + "type_info": "Bool", + "origin": { + "Table": { + "table": "mods", + "name": "featured" + } + } + }, + { + "ordinal": 5, + "name": "mod_download_count", + "type_info": "Int4", + "origin": { + "Table": { + "table": "mods", + "name": "download_count" + } + } + }, + { + "ordinal": 6, + "name": "created_at", + "type_info": "Timestamptz", + "origin": { + "Table": { + "table": "mods", + "name": "created_at" + } + } + }, + { + "ordinal": 7, + "name": "updated_at", + "type_info": "Timestamptz", + "origin": { + "Table": { + "table": "mods", + "name": "updated_at" + } + } + }, + { + "ordinal": 8, + "name": "version_id", + "type_info": "Int4", + "origin": { + "Table": { + "table": "mod_versions", + "name": "id" + } + } + }, + { + "ordinal": 9, + "name": "name", + "type_info": "Text", + "origin": { + "Table": { + "table": "mod_versions", + "name": "name" + } + } + }, + { + "ordinal": 10, + "name": "description", + "type_info": "Text", + "origin": { + "Table": { + "table": "mod_versions", + "name": "description" + } + } + }, + { + "ordinal": 11, + "name": "version", + "type_info": "Text", + "origin": { + "Table": { + "table": "mod_versions", + "name": "version" + } + } + }, + { + "ordinal": 12, + "name": "download_link", + "type_info": "Text", + "origin": { + "Table": { + "table": "mod_versions", + "name": "download_link" + } + } + }, + { + "ordinal": 13, + "name": "managed_download_link", + "type_info": "Text", + "origin": { + "Table": { + "table": "mod_versions", + "name": "managed_download_link" + } + } + }, + { + "ordinal": 14, + "name": "mod_version_download_count", + "type_info": "Int4", + "origin": { + "Table": { + "table": "mod_versions", + "name": "download_count" + } + } + }, + { + "ordinal": 15, + "name": "mod_version_created_at", + "type_info": "Timestamptz", + "origin": { + "Table": { + "table": "mod_versions", + "name": "created_at" + } + } + }, + { + "ordinal": 16, + "name": "mod_version_updated_at", + "type_info": "Timestamptz", + "origin": { + "Table": { + "table": "mod_versions", + "name": "updated_at" + } + } + }, + { + "ordinal": 17, + "name": "hash", + "type_info": "Text", + "origin": { + "Table": { + "table": "mod_versions", + "name": "hash" + } + } + }, + { + "ordinal": 18, + "name": "geode!: _", + "type_info": "Text", + "origin": "Expression" + }, + { + "ordinal": 19, + "name": "early_load", + "type_info": "Bool", + "origin": { + "Table": { + "table": "mod_versions", + "name": "early_load" + } + } + }, + { + "ordinal": 20, + "name": "requires_patching", + "type_info": "Bool", + "origin": { + "Table": { + "table": "mod_versions", + "name": "requires_patching" + } + } + }, + { + "ordinal": 21, + "name": "api", + "type_info": "Bool", + "origin": { + "Table": { + "table": "mod_versions", + "name": "api" + } + } + }, + { + "ordinal": 22, + "name": "mod_id", + "type_info": "Text", + "origin": { + "Table": { + "table": "mod_versions", + "name": "mod_id" + } + } + }, + { + "ordinal": 23, + "name": "status: _", + "type_info": { + "Custom": { + "name": "mod_version_status", + "kind": { + "Enum": [ + "pending", + "rejected", + "accepted", + "unlisted" + ] + } + } + }, + "origin": { + "Table": { + "table": "mod_version_statuses", + "name": "status" + } + } + }, + { + "ordinal": 24, + "name": "info", + "type_info": "Text", + "origin": { + "Table": { + "table": "mod_version_statuses", + "name": "info" + } + } + } + ], + "parameters": { + "Left": [ + "Text", + "Bool" + ] + }, + "nullable": [ + false, + true, + true, + true, + false, + false, + false, + false, + false, + false, + true, + false, + false, + true, + false, + true, + true, + false, + null, + false, + false, + false, + false, + false, + true + ] + }, + "hash": "2894a3bf8b4f43496a3a1532ba1e630726cf78d354b586094b1ee8c16a6fe9ee" +} diff --git a/.sqlx/query-2b55fed2c473a9b2b249d9afcaff2d290c453d70fb12bf4eb4f099f099f29aa4.json b/.sqlx/query-2b55fed2c473a9b2b249d9afcaff2d290c453d70fb12bf4eb4f099f099f29aa4.json index bb020afe..94d69b88 100644 --- a/.sqlx/query-2b55fed2c473a9b2b249d9afcaff2d290c453d70fb12bf4eb4f099f099f29aa4.json +++ b/.sqlx/query-2b55fed2c473a9b2b249d9afcaff2d290c453d70fb12bf4eb4f099f099f29aa4.json @@ -6,7 +6,13 @@ { "ordinal": 0, "name": "image", - "type_info": "Bytea" + "type_info": "Bytea", + "origin": { + "Table": { + "table": "mods", + "name": "image" + } + } } ], "parameters": { diff --git a/.sqlx/query-343cc93a2b99bed5e20d46ce54eba34475ebf9db478c8c1debeed64552bb6fd7.json b/.sqlx/query-343cc93a2b99bed5e20d46ce54eba34475ebf9db478c8c1debeed64552bb6fd7.json new file mode 100644 index 00000000..f41f7a71 --- /dev/null +++ b/.sqlx/query-343cc93a2b99bed5e20d46ce54eba34475ebf9db478c8c1debeed64552bb6fd7.json @@ -0,0 +1,228 @@ +{ + "db_name": "PostgreSQL", + "query": "SELECT\n mv.id, mv.name, mv.description, mv.version,\n mv.download_link, mv.managed_download_link, mv.download_count, mv.hash,\n format_semver(mv.geode_major, mv.geode_minor, mv.geode_patch, mv.geode_meta) as \"geode!: _\",\n mv.early_load, mv.requires_patching, mv.api, mv.mod_id,\n mv.created_at, mv.updated_at,\n mvs.status as \"status: _\", mvs.info\n FROM mod_versions mv\n INNER JOIN mod_version_statuses mvs ON mvs.mod_version_id = mv.id\n WHERE mv.mod_id = $1\n AND mv.version = $2", + "describe": { + "columns": [ + { + "ordinal": 0, + "name": "id", + "type_info": "Int4", + "origin": { + "Table": { + "table": "mod_versions", + "name": "id" + } + } + }, + { + "ordinal": 1, + "name": "name", + "type_info": "Text", + "origin": { + "Table": { + "table": "mod_versions", + "name": "name" + } + } + }, + { + "ordinal": 2, + "name": "description", + "type_info": "Text", + "origin": { + "Table": { + "table": "mod_versions", + "name": "description" + } + } + }, + { + "ordinal": 3, + "name": "version", + "type_info": "Text", + "origin": { + "Table": { + "table": "mod_versions", + "name": "version" + } + } + }, + { + "ordinal": 4, + "name": "download_link", + "type_info": "Text", + "origin": { + "Table": { + "table": "mod_versions", + "name": "download_link" + } + } + }, + { + "ordinal": 5, + "name": "managed_download_link", + "type_info": "Text", + "origin": { + "Table": { + "table": "mod_versions", + "name": "managed_download_link" + } + } + }, + { + "ordinal": 6, + "name": "download_count", + "type_info": "Int4", + "origin": { + "Table": { + "table": "mod_versions", + "name": "download_count" + } + } + }, + { + "ordinal": 7, + "name": "hash", + "type_info": "Text", + "origin": { + "Table": { + "table": "mod_versions", + "name": "hash" + } + } + }, + { + "ordinal": 8, + "name": "geode!: _", + "type_info": "Text", + "origin": "Expression" + }, + { + "ordinal": 9, + "name": "early_load", + "type_info": "Bool", + "origin": { + "Table": { + "table": "mod_versions", + "name": "early_load" + } + } + }, + { + "ordinal": 10, + "name": "requires_patching", + "type_info": "Bool", + "origin": { + "Table": { + "table": "mod_versions", + "name": "requires_patching" + } + } + }, + { + "ordinal": 11, + "name": "api", + "type_info": "Bool", + "origin": { + "Table": { + "table": "mod_versions", + "name": "api" + } + } + }, + { + "ordinal": 12, + "name": "mod_id", + "type_info": "Text", + "origin": { + "Table": { + "table": "mod_versions", + "name": "mod_id" + } + } + }, + { + "ordinal": 13, + "name": "created_at", + "type_info": "Timestamptz", + "origin": { + "Table": { + "table": "mod_versions", + "name": "created_at" + } + } + }, + { + "ordinal": 14, + "name": "updated_at", + "type_info": "Timestamptz", + "origin": { + "Table": { + "table": "mod_versions", + "name": "updated_at" + } + } + }, + { + "ordinal": 15, + "name": "status: _", + "type_info": { + "Custom": { + "name": "mod_version_status", + "kind": { + "Enum": [ + "pending", + "rejected", + "accepted", + "unlisted" + ] + } + } + }, + "origin": { + "Table": { + "table": "mod_version_statuses", + "name": "status" + } + } + }, + { + "ordinal": 16, + "name": "info", + "type_info": "Text", + "origin": { + "Table": { + "table": "mod_version_statuses", + "name": "info" + } + } + } + ], + "parameters": { + "Left": [ + "Text", + "Text" + ] + }, + "nullable": [ + false, + false, + true, + false, + false, + true, + false, + false, + null, + false, + false, + false, + false, + true, + true, + false, + true + ] + }, + "hash": "343cc93a2b99bed5e20d46ce54eba34475ebf9db478c8c1debeed64552bb6fd7" +} diff --git a/.sqlx/query-358511533c7ab481f97ffdf9bdbdcef430294ba0e874ab1706115541f68828d1.json b/.sqlx/query-358511533c7ab481f97ffdf9bdbdcef430294ba0e874ab1706115541f68828d1.json index b09cd5d2..2b2120e5 100644 --- a/.sqlx/query-358511533c7ab481f97ffdf9bdbdcef430294ba0e874ab1706115541f68828d1.json +++ b/.sqlx/query-358511533c7ab481f97ffdf9bdbdcef430294ba0e874ab1706115541f68828d1.json @@ -6,22 +6,46 @@ { "ordinal": 0, "name": "id", - "type_info": "Int4" + "type_info": "Int4", + "origin": { + "Table": { + "table": "mod_tags", + "name": "id" + } + } }, { "ordinal": 1, "name": "name", - "type_info": "Text" + "type_info": "Text", + "origin": { + "Table": { + "table": "mod_tags", + "name": "name" + } + } }, { "ordinal": 2, "name": "display_name", - "type_info": "Text" + "type_info": "Text", + "origin": { + "Table": { + "table": "mod_tags", + "name": "display_name" + } + } }, { "ordinal": 3, "name": "is_readonly", - "type_info": "Bool" + "type_info": "Bool", + "origin": { + "Table": { + "table": "mod_tags", + "name": "is_readonly" + } + } } ], "parameters": { diff --git a/.sqlx/query-3a9e0f2e4c810e63811251c2da5a387a44c47030bcac9aba859ed5080dcc165e.json b/.sqlx/query-3a9e0f2e4c810e63811251c2da5a387a44c47030bcac9aba859ed5080dcc165e.json index 04a238dd..c2c4b576 100644 --- a/.sqlx/query-3a9e0f2e4c810e63811251c2da5a387a44c47030bcac9aba859ed5080dcc165e.json +++ b/.sqlx/query-3a9e0f2e4c810e63811251c2da5a387a44c47030bcac9aba859ed5080dcc165e.json @@ -6,7 +6,13 @@ { "ordinal": 0, "name": "mod_version_id", - "type_info": "Int4" + "type_info": "Int4", + "origin": { + "Table": { + "table": "mod_version_submissions", + "name": "mod_version_id" + } + } }, { "ordinal": 1, @@ -22,22 +28,46 @@ ] } } + }, + "origin": { + "Table": { + "table": "mod_version_submissions", + "name": "lock" + } } }, { "ordinal": 2, "name": "locked_by", - "type_info": "Int4" + "type_info": "Int4", + "origin": { + "Table": { + "table": "mod_version_submissions", + "name": "locked_by" + } + } }, { "ordinal": 3, "name": "created_at", - "type_info": "Timestamptz" + "type_info": "Timestamptz", + "origin": { + "Table": { + "table": "mod_version_submissions", + "name": "created_at" + } + } }, { "ordinal": 4, "name": "updated_at", - "type_info": "Timestamptz" + "type_info": "Timestamptz", + "origin": { + "Table": { + "table": "mod_version_submissions", + "name": "updated_at" + } + } } ], "parameters": { diff --git a/.sqlx/query-3c81951bc3ef36210fce1b2bc89dc7dd76adc19d954d73ca8c2d031813307aa2.json b/.sqlx/query-3c81951bc3ef36210fce1b2bc89dc7dd76adc19d954d73ca8c2d031813307aa2.json index f383bb42..f195f4f2 100644 --- a/.sqlx/query-3c81951bc3ef36210fce1b2bc89dc7dd76adc19d954d73ca8c2d031813307aa2.json +++ b/.sqlx/query-3c81951bc3ef36210fce1b2bc89dc7dd76adc19d954d73ca8c2d031813307aa2.json @@ -6,12 +6,24 @@ { "ordinal": 0, "name": "deprecation_id", - "type_info": "Int4" + "type_info": "Int4", + "origin": { + "Table": { + "table": "deprecated_by", + "name": "deprecation_id" + } + } }, { "ordinal": 1, "name": "by_mod_id", - "type_info": "Text" + "type_info": "Text", + "origin": { + "Table": { + "table": "deprecated_by", + "name": "by_mod_id" + } + } } ], "parameters": { diff --git a/.sqlx/query-3e911a3e12f4d239c0d1a3185c7f54d36ff0819639c15a2e70d32dce65a39803.json b/.sqlx/query-3e911a3e12f4d239c0d1a3185c7f54d36ff0819639c15a2e70d32dce65a39803.json index 6ea2de4f..94beeb74 100644 --- a/.sqlx/query-3e911a3e12f4d239c0d1a3185c7f54d36ff0819639c15a2e70d32dce65a39803.json +++ b/.sqlx/query-3e911a3e12f4d239c0d1a3185c7f54d36ff0819639c15a2e70d32dce65a39803.json @@ -6,22 +6,46 @@ { "ordinal": 0, "name": "id", - "type_info": "Int8" + "type_info": "Int8", + "origin": { + "Table": { + "table": "mod_version_submission_comment_attachments", + "name": "id" + } + } }, { "ordinal": 1, "name": "comment_id", - "type_info": "Int8" + "type_info": "Int8", + "origin": { + "Table": { + "table": "mod_version_submission_comment_attachments", + "name": "comment_id" + } + } }, { "ordinal": 2, "name": "filename", - "type_info": "Text" + "type_info": "Text", + "origin": { + "Table": { + "table": "mod_version_submission_comment_attachments", + "name": "filename" + } + } }, { "ordinal": 3, "name": "created_at", - "type_info": "Timestamptz" + "type_info": "Timestamptz", + "origin": { + "Table": { + "table": "mod_version_submission_comment_attachments", + "name": "created_at" + } + } } ], "parameters": { diff --git a/.sqlx/query-413daf884b398b94a5c9731618c780ef48dc808cdb2fe71ab1e9ed2c2ffcb3a6.json b/.sqlx/query-413daf884b398b94a5c9731618c780ef48dc808cdb2fe71ab1e9ed2c2ffcb3a6.json index 8afe8fe6..cf9662f4 100644 --- a/.sqlx/query-413daf884b398b94a5c9731618c780ef48dc808cdb2fe71ab1e9ed2c2ffcb3a6.json +++ b/.sqlx/query-413daf884b398b94a5c9731618c780ef48dc808cdb2fe71ab1e9ed2c2ffcb3a6.json @@ -6,32 +6,68 @@ { "ordinal": 0, "name": "id", - "type_info": "Int4" + "type_info": "Int4", + "origin": { + "Table": { + "table": "developers", + "name": "id" + } + } }, { "ordinal": 1, "name": "username", - "type_info": "Text" + "type_info": "Text", + "origin": { + "Table": { + "table": "developers", + "name": "username" + } + } }, { "ordinal": 2, "name": "display_name", - "type_info": "Text" + "type_info": "Text", + "origin": { + "Table": { + "table": "developers", + "name": "display_name" + } + } }, { "ordinal": 3, "name": "verified", - "type_info": "Bool" + "type_info": "Bool", + "origin": { + "Table": { + "table": "developers", + "name": "verified" + } + } }, { "ordinal": 4, "name": "admin", - "type_info": "Bool" + "type_info": "Bool", + "origin": { + "Table": { + "table": "developers", + "name": "admin" + } + } }, { "ordinal": 5, "name": "github_id", - "type_info": "Int8" + "type_info": "Int8", + "origin": { + "Table": { + "table": "developers", + "name": "github_user_id" + } + } } ], "parameters": { diff --git a/.sqlx/query-4250be7721057fee9a8fdbb9ab083bb2398a64b23eed89a0746badb07eb73b1a.json b/.sqlx/query-4250be7721057fee9a8fdbb9ab083bb2398a64b23eed89a0746badb07eb73b1a.json index f0fb3812..1ff60f77 100644 --- a/.sqlx/query-4250be7721057fee9a8fdbb9ab083bb2398a64b23eed89a0746badb07eb73b1a.json +++ b/.sqlx/query-4250be7721057fee9a8fdbb9ab083bb2398a64b23eed89a0746badb07eb73b1a.json @@ -6,22 +6,46 @@ { "ordinal": 0, "name": "mod_id", - "type_info": "Text" + "type_info": "Text", + "origin": { + "Table": { + "table": "mod_links", + "name": "mod_id" + } + } }, { "ordinal": 1, "name": "community", - "type_info": "Text" + "type_info": "Text", + "origin": { + "Table": { + "table": "mod_links", + "name": "community" + } + } }, { "ordinal": 2, "name": "homepage", - "type_info": "Text" + "type_info": "Text", + "origin": { + "Table": { + "table": "mod_links", + "name": "homepage" + } + } }, { "ordinal": 3, "name": "source", - "type_info": "Text" + "type_info": "Text", + "origin": { + "Table": { + "table": "mod_links", + "name": "source" + } + } } ], "parameters": { diff --git a/.sqlx/query-4289772ae34ff1b1fe1c212bd8a8a49bc08edb530ebcb8a967747c881af4b5f5.json b/.sqlx/query-4289772ae34ff1b1fe1c212bd8a8a49bc08edb530ebcb8a967747c881af4b5f5.json index cdc7cb52..2e018caf 100644 --- a/.sqlx/query-4289772ae34ff1b1fe1c212bd8a8a49bc08edb530ebcb8a967747c881af4b5f5.json +++ b/.sqlx/query-4289772ae34ff1b1fe1c212bd8a8a49bc08edb530ebcb8a967747c881af4b5f5.json @@ -6,32 +6,68 @@ { "ordinal": 0, "name": "id", - "type_info": "Int4" + "type_info": "Int4", + "origin": { + "Table": { + "table": "developers", + "name": "id" + } + } }, { "ordinal": 1, "name": "username", - "type_info": "Text" + "type_info": "Text", + "origin": { + "Table": { + "table": "developers", + "name": "username" + } + } }, { "ordinal": 2, "name": "display_name", - "type_info": "Text" + "type_info": "Text", + "origin": { + "Table": { + "table": "developers", + "name": "display_name" + } + } }, { "ordinal": 3, "name": "verified", - "type_info": "Bool" + "type_info": "Bool", + "origin": { + "Table": { + "table": "developers", + "name": "verified" + } + } }, { "ordinal": 4, "name": "admin", - "type_info": "Bool" + "type_info": "Bool", + "origin": { + "Table": { + "table": "developers", + "name": "admin" + } + } }, { "ordinal": 5, "name": "github_id", - "type_info": "Int8" + "type_info": "Int8", + "origin": { + "Table": { + "table": "developers", + "name": "github_user_id" + } + } } ], "parameters": { diff --git a/.sqlx/query-4a624bdb7a8320e4cb18a9e955bfd7ab3f67d6d97529d862ba75dd01e6544f81.json b/.sqlx/query-4a624bdb7a8320e4cb18a9e955bfd7ab3f67d6d97529d862ba75dd01e6544f81.json index bb4e48dd..eb8caad4 100644 --- a/.sqlx/query-4a624bdb7a8320e4cb18a9e955bfd7ab3f67d6d97529d862ba75dd01e6544f81.json +++ b/.sqlx/query-4a624bdb7a8320e4cb18a9e955bfd7ab3f67d6d97529d862ba75dd01e6544f81.json @@ -6,47 +6,101 @@ { "ordinal": 0, "name": "uuid", - "type_info": "Uuid" + "type_info": "Uuid", + "origin": { + "Table": { + "table": "github_login_attempts", + "name": "uid" + } + } }, { "ordinal": 1, "name": "ip", - "type_info": "Inet" + "type_info": "Inet", + "origin": { + "Table": { + "table": "github_login_attempts", + "name": "ip" + } + } }, { "ordinal": 2, "name": "interval", - "type_info": "Int4" + "type_info": "Int4", + "origin": { + "Table": { + "table": "github_login_attempts", + "name": "interval" + } + } }, { "ordinal": 3, "name": "expires_in", - "type_info": "Int4" + "type_info": "Int4", + "origin": { + "Table": { + "table": "github_login_attempts", + "name": "expires_in" + } + } }, { "ordinal": 4, "name": "created_at", - "type_info": "Timestamptz" + "type_info": "Timestamptz", + "origin": { + "Table": { + "table": "github_login_attempts", + "name": "created_at" + } + } }, { "ordinal": 5, "name": "last_poll", - "type_info": "Timestamptz" + "type_info": "Timestamptz", + "origin": { + "Table": { + "table": "github_login_attempts", + "name": "last_poll" + } + } }, { "ordinal": 6, "name": "uri", - "type_info": "Text" + "type_info": "Text", + "origin": { + "Table": { + "table": "github_login_attempts", + "name": "challenge_uri" + } + } }, { "ordinal": 7, "name": "device_code", - "type_info": "Text" + "type_info": "Text", + "origin": { + "Table": { + "table": "github_login_attempts", + "name": "device_code" + } + } }, { "ordinal": 8, "name": "user_code", - "type_info": "Text" + "type_info": "Text", + "origin": { + "Table": { + "table": "github_login_attempts", + "name": "user_code" + } + } } ], "parameters": { diff --git a/.sqlx/query-4ad2b61d2fa7a7edc9ec5ec68eaed41b993407ae32bf0e90fbdd2c8ca3ea9d22.json b/.sqlx/query-4ad2b61d2fa7a7edc9ec5ec68eaed41b993407ae32bf0e90fbdd2c8ca3ea9d22.json index 4d84f0d3..46e9373f 100644 --- a/.sqlx/query-4ad2b61d2fa7a7edc9ec5ec68eaed41b993407ae32bf0e90fbdd2c8ca3ea9d22.json +++ b/.sqlx/query-4ad2b61d2fa7a7edc9ec5ec68eaed41b993407ae32bf0e90fbdd2c8ca3ea9d22.json @@ -6,22 +6,46 @@ { "ordinal": 0, "name": "id", - "type_info": "Int8" + "type_info": "Int8", + "origin": { + "Table": { + "table": "mod_version_submission_comment_attachments", + "name": "id" + } + } }, { "ordinal": 1, "name": "comment_id", - "type_info": "Int8" + "type_info": "Int8", + "origin": { + "Table": { + "table": "mod_version_submission_comment_attachments", + "name": "comment_id" + } + } }, { "ordinal": 2, "name": "filename", - "type_info": "Text" + "type_info": "Text", + "origin": { + "Table": { + "table": "mod_version_submission_comment_attachments", + "name": "filename" + } + } }, { "ordinal": 3, "name": "created_at", - "type_info": "Timestamptz" + "type_info": "Timestamptz", + "origin": { + "Table": { + "table": "mod_version_submission_comment_attachments", + "name": "created_at" + } + } } ], "parameters": { diff --git a/.sqlx/query-5687bf51d606c491a75a05ffed72bd71dcb15053d899b6a8cd6cc75327d52bff.json b/.sqlx/query-5687bf51d606c491a75a05ffed72bd71dcb15053d899b6a8cd6cc75327d52bff.json index 606c83e6..13c40aa6 100644 --- a/.sqlx/query-5687bf51d606c491a75a05ffed72bd71dcb15053d899b6a8cd6cc75327d52bff.json +++ b/.sqlx/query-5687bf51d606c491a75a05ffed72bd71dcb15053d899b6a8cd6cc75327d52bff.json @@ -6,7 +6,13 @@ { "ordinal": 0, "name": "mod_version_id", - "type_info": "Int4" + "type_info": "Int4", + "origin": { + "Table": { + "table": "mod_version_submissions", + "name": "mod_version_id" + } + } }, { "ordinal": 1, @@ -22,22 +28,46 @@ ] } } + }, + "origin": { + "Table": { + "table": "mod_version_submissions", + "name": "lock" + } } }, { "ordinal": 2, "name": "locked_by", - "type_info": "Int4" + "type_info": "Int4", + "origin": { + "Table": { + "table": "mod_version_submissions", + "name": "locked_by" + } + } }, { "ordinal": 3, "name": "created_at", - "type_info": "Timestamptz" + "type_info": "Timestamptz", + "origin": { + "Table": { + "table": "mod_version_submissions", + "name": "created_at" + } + } }, { "ordinal": 4, "name": "updated_at", - "type_info": "Timestamptz" + "type_info": "Timestamptz", + "origin": { + "Table": { + "table": "mod_version_submissions", + "name": "updated_at" + } + } } ], "parameters": { diff --git a/.sqlx/query-58d1a6eafbfe3aaf8836459f8a9d7633e0e322cb3895d7bcf347f35bf30169c7.json b/.sqlx/query-58d1a6eafbfe3aaf8836459f8a9d7633e0e322cb3895d7bcf347f35bf30169c7.json index a7d7c084..64c91c10 100644 --- a/.sqlx/query-58d1a6eafbfe3aaf8836459f8a9d7633e0e322cb3895d7bcf347f35bf30169c7.json +++ b/.sqlx/query-58d1a6eafbfe3aaf8836459f8a9d7633e0e322cb3895d7bcf347f35bf30169c7.json @@ -6,32 +6,68 @@ { "ordinal": 0, "name": "id", - "type_info": "Int4" + "type_info": "Int4", + "origin": { + "Table": { + "table": "developers", + "name": "id" + } + } }, { "ordinal": 1, "name": "username", - "type_info": "Text" + "type_info": "Text", + "origin": { + "Table": { + "table": "developers", + "name": "username" + } + } }, { "ordinal": 2, "name": "display_name", - "type_info": "Text" + "type_info": "Text", + "origin": { + "Table": { + "table": "developers", + "name": "display_name" + } + } }, { "ordinal": 3, "name": "verified", - "type_info": "Bool" + "type_info": "Bool", + "origin": { + "Table": { + "table": "developers", + "name": "verified" + } + } }, { "ordinal": 4, "name": "admin", - "type_info": "Bool" + "type_info": "Bool", + "origin": { + "Table": { + "table": "developers", + "name": "admin" + } + } }, { "ordinal": 5, "name": "github_id", - "type_info": "Int8" + "type_info": "Int8", + "origin": { + "Table": { + "table": "developers", + "name": "github_user_id" + } + } } ], "parameters": { diff --git a/.sqlx/query-5e73a555131f87c514751236ad5ca08ae8f9144fed83971c3b1190ace209a9f5.json b/.sqlx/query-5e73a555131f87c514751236ad5ca08ae8f9144fed83971c3b1190ace209a9f5.json index e86f244d..bbfcfe72 100644 --- a/.sqlx/query-5e73a555131f87c514751236ad5ca08ae8f9144fed83971c3b1190ace209a9f5.json +++ b/.sqlx/query-5e73a555131f87c514751236ad5ca08ae8f9144fed83971c3b1190ace209a9f5.json @@ -6,32 +6,68 @@ { "ordinal": 0, "name": "id", - "type_info": "Int4" + "type_info": "Int4", + "origin": { + "Table": { + "table": "developers", + "name": "id" + } + } }, { "ordinal": 1, "name": "username", - "type_info": "Text" + "type_info": "Text", + "origin": { + "Table": { + "table": "developers", + "name": "username" + } + } }, { "ordinal": 2, "name": "display_name", - "type_info": "Text" + "type_info": "Text", + "origin": { + "Table": { + "table": "developers", + "name": "display_name" + } + } }, { "ordinal": 3, "name": "verified", - "type_info": "Bool" + "type_info": "Bool", + "origin": { + "Table": { + "table": "developers", + "name": "verified" + } + } }, { "ordinal": 4, "name": "admin", - "type_info": "Bool" + "type_info": "Bool", + "origin": { + "Table": { + "table": "developers", + "name": "admin" + } + } }, { "ordinal": 5, "name": "github_id", - "type_info": "Int8" + "type_info": "Int8", + "origin": { + "Table": { + "table": "developers", + "name": "github_user_id" + } + } } ], "parameters": { diff --git a/.sqlx/query-6589899a5fb9ef87d704598a7ab741860b8b7658980ce348fadb9bf03e3cce03.json b/.sqlx/query-6589899a5fb9ef87d704598a7ab741860b8b7658980ce348fadb9bf03e3cce03.json index 24bcc1a2..af1decee 100644 --- a/.sqlx/query-6589899a5fb9ef87d704598a7ab741860b8b7658980ce348fadb9bf03e3cce03.json +++ b/.sqlx/query-6589899a5fb9ef87d704598a7ab741860b8b7658980ce348fadb9bf03e3cce03.json @@ -6,17 +6,35 @@ { "ordinal": 0, "name": "mod_id", - "type_info": "Int4" + "type_info": "Int4", + "origin": { + "Table": { + "table": "incompatibilities", + "name": "mod_id" + } + } }, { "ordinal": 1, "name": "incompatibility_id", - "type_info": "Text" + "type_info": "Text", + "origin": { + "Table": { + "table": "incompatibilities", + "name": "incompatibility_id" + } + } }, { "ordinal": 2, "name": "version", - "type_info": "Text" + "type_info": "Text", + "origin": { + "Table": { + "table": "incompatibilities", + "name": "version" + } + } }, { "ordinal": 3, @@ -34,6 +52,12 @@ ] } } + }, + "origin": { + "Table": { + "table": "incompatibilities", + "name": "compare" + } } }, { @@ -51,6 +75,12 @@ ] } } + }, + "origin": { + "Table": { + "table": "incompatibilities", + "name": "importance" + } } } ], diff --git a/.sqlx/query-6b9a4fc83126ec8a512b825b3183cb5d8e3e4d1fcff129d2fbc897d3cd64c971.json b/.sqlx/query-6b9a4fc83126ec8a512b825b3183cb5d8e3e4d1fcff129d2fbc897d3cd64c971.json index 7023eea1..5178bc80 100644 --- a/.sqlx/query-6b9a4fc83126ec8a512b825b3183cb5d8e3e4d1fcff129d2fbc897d3cd64c971.json +++ b/.sqlx/query-6b9a4fc83126ec8a512b825b3183cb5d8e3e4d1fcff129d2fbc897d3cd64c971.json @@ -6,7 +6,13 @@ { "ordinal": 0, "name": "developer_id", - "type_info": "Int4" + "type_info": "Int4", + "origin": { + "Table": { + "table": "mods_developers", + "name": "developer_id" + } + } } ], "parameters": { diff --git a/.sqlx/query-6bc0d557eeaf39e217f8cb77b446ff825e406eb44887480cb36801b054ed9051.json b/.sqlx/query-6bc0d557eeaf39e217f8cb77b446ff825e406eb44887480cb36801b054ed9051.json index e52f4d46..51bc5c78 100644 --- a/.sqlx/query-6bc0d557eeaf39e217f8cb77b446ff825e406eb44887480cb36801b054ed9051.json +++ b/.sqlx/query-6bc0d557eeaf39e217f8cb77b446ff825e406eb44887480cb36801b054ed9051.json @@ -6,17 +6,35 @@ { "ordinal": 0, "name": "id", - "type_info": "Text" + "type_info": "Text", + "origin": { + "Table": { + "table": "mods", + "name": "id" + } + } }, { "ordinal": 1, "name": "version", - "type_info": "Text" + "type_info": "Text", + "origin": { + "Table": { + "table": "mod_versions", + "name": "version" + } + } }, { "ordinal": 2, "name": "mod_version_id", - "type_info": "Int4" + "type_info": "Int4", + "origin": { + "Table": { + "table": "mod_versions", + "name": "id" + } + } } ], "parameters": { diff --git a/.sqlx/query-6be04be9bbf53814144d17355ba47ba12f948e60e815ad917846d7ff6733245a.json b/.sqlx/query-6be04be9bbf53814144d17355ba47ba12f948e60e815ad917846d7ff6733245a.json index 3df40f25..0a4751c8 100644 --- a/.sqlx/query-6be04be9bbf53814144d17355ba47ba12f948e60e815ad917846d7ff6733245a.json +++ b/.sqlx/query-6be04be9bbf53814144d17355ba47ba12f948e60e815ad917846d7ff6733245a.json @@ -18,22 +18,46 @@ ] } } + }, + "origin": { + "Table": { + "table": "mod_version_submissions_audit", + "name": "action" + } } }, { "ordinal": 1, "name": "details", - "type_info": "Text" + "type_info": "Text", + "origin": { + "Table": { + "table": "mod_version_submissions_audit", + "name": "details" + } + } }, { "ordinal": 2, "name": "performed_by", - "type_info": "Int4" + "type_info": "Int4", + "origin": { + "Table": { + "table": "mod_version_submissions_audit", + "name": "performed_by" + } + } }, { "ordinal": 3, "name": "performed_at", - "type_info": "Timestamptz" + "type_info": "Timestamptz", + "origin": { + "Table": { + "table": "mod_version_submissions_audit", + "name": "performed_at" + } + } } ], "parameters": { diff --git a/.sqlx/query-6c237ee29dee664dabe8175e9d81add4ca9ea87043d8444d6db938a83f400f54.json b/.sqlx/query-6c237ee29dee664dabe8175e9d81add4ca9ea87043d8444d6db938a83f400f54.json index 73e1b99d..c474d101 100644 --- a/.sqlx/query-6c237ee29dee664dabe8175e9d81add4ca9ea87043d8444d6db938a83f400f54.json +++ b/.sqlx/query-6c237ee29dee664dabe8175e9d81add4ca9ea87043d8444d6db938a83f400f54.json @@ -6,12 +6,24 @@ { "ordinal": 0, "name": "id", - "type_info": "Int4" + "type_info": "Int4", + "origin": { + "Table": { + "table": "mod_tags", + "name": "id" + } + } }, { "ordinal": 1, "name": "name", - "type_info": "Text" + "type_info": "Text", + "origin": { + "Table": { + "table": "mod_tags", + "name": "name" + } + } } ], "parameters": { diff --git a/.sqlx/query-74a8ad8da9121d864db3b38a0df52082349b104f6f50382325d4291ab10f3b82.json b/.sqlx/query-74a8ad8da9121d864db3b38a0df52082349b104f6f50382325d4291ab10f3b82.json index e2de9938..edf78f7d 100644 --- a/.sqlx/query-74a8ad8da9121d864db3b38a0df52082349b104f6f50382325d4291ab10f3b82.json +++ b/.sqlx/query-74a8ad8da9121d864db3b38a0df52082349b104f6f50382325d4291ab10f3b82.json @@ -6,12 +6,24 @@ { "ordinal": 0, "name": "name", - "type_info": "Text" + "type_info": "Text", + "origin": { + "Table": { + "table": "mod_tags", + "name": "name" + } + } }, { "ordinal": 1, "name": "mod_id", - "type_info": "Text" + "type_info": "Text", + "origin": { + "Table": { + "table": "mods_mod_tags", + "name": "mod_id" + } + } } ], "parameters": { diff --git a/.sqlx/query-75645a63e093cdaadb0ba84844e6299e3e19eee7b530be498c609e6cd6fc2b33.json b/.sqlx/query-75645a63e093cdaadb0ba84844e6299e3e19eee7b530be498c609e6cd6fc2b33.json index 0b4f3933..9c37b091 100644 --- a/.sqlx/query-75645a63e093cdaadb0ba84844e6299e3e19eee7b530be498c609e6cd6fc2b33.json +++ b/.sqlx/query-75645a63e093cdaadb0ba84844e6299e3e19eee7b530be498c609e6cd6fc2b33.json @@ -6,22 +6,46 @@ { "ordinal": 0, "name": "id", - "type_info": "Int8" + "type_info": "Int8", + "origin": { + "Table": { + "table": "mod_version_submission_comment_attachments", + "name": "id" + } + } }, { "ordinal": 1, "name": "comment_id", - "type_info": "Int8" + "type_info": "Int8", + "origin": { + "Table": { + "table": "mod_version_submission_comment_attachments", + "name": "comment_id" + } + } }, { "ordinal": 2, "name": "filename", - "type_info": "Text" + "type_info": "Text", + "origin": { + "Table": { + "table": "mod_version_submission_comment_attachments", + "name": "filename" + } + } }, { "ordinal": 3, "name": "created_at", - "type_info": "Timestamptz" + "type_info": "Timestamptz", + "origin": { + "Table": { + "table": "mod_version_submission_comment_attachments", + "name": "created_at" + } + } } ], "parameters": { diff --git a/.sqlx/query-79c07336d3e245d46e7e07e0e32e092e6de4a4e3189c0d86735f030bbb0a60b3.json b/.sqlx/query-79c07336d3e245d46e7e07e0e32e092e6de4a4e3189c0d86735f030bbb0a60b3.json index ce3fdde2..f0b6f34a 100644 --- a/.sqlx/query-79c07336d3e245d46e7e07e0e32e092e6de4a4e3189c0d86735f030bbb0a60b3.json +++ b/.sqlx/query-79c07336d3e245d46e7e07e0e32e092e6de4a4e3189c0d86735f030bbb0a60b3.json @@ -6,7 +6,13 @@ { "ordinal": 0, "name": "id", - "type_info": "Text" + "type_info": "Text", + "origin": { + "Table": { + "table": "mods", + "name": "id" + } + } } ], "parameters": { diff --git a/.sqlx/query-7a9ffa7b59f3550e2bd38c756b9cc3566512dc2273dc3b72ba1ba5c2d281aeb9.json b/.sqlx/query-7a9ffa7b59f3550e2bd38c756b9cc3566512dc2273dc3b72ba1ba5c2d281aeb9.json index 568b54b1..d4e9d44a 100644 --- a/.sqlx/query-7a9ffa7b59f3550e2bd38c756b9cc3566512dc2273dc3b72ba1ba5c2d281aeb9.json +++ b/.sqlx/query-7a9ffa7b59f3550e2bd38c756b9cc3566512dc2273dc3b72ba1ba5c2d281aeb9.json @@ -6,7 +6,8 @@ { "ordinal": 0, "name": "count", - "type_info": "Int8" + "type_info": "Int8", + "origin": "Expression" } ], "parameters": { diff --git a/.sqlx/query-7d171a79184b68e491ed200d347d6b412b621e2cc3a5b63481643d7e90d05566.json b/.sqlx/query-7d171a79184b68e491ed200d347d6b412b621e2cc3a5b63481643d7e90d05566.json index 4fb2fb6e..60dc1129 100644 --- a/.sqlx/query-7d171a79184b68e491ed200d347d6b412b621e2cc3a5b63481643d7e90d05566.json +++ b/.sqlx/query-7d171a79184b68e491ed200d347d6b412b621e2cc3a5b63481643d7e90d05566.json @@ -6,12 +6,24 @@ { "ordinal": 0, "name": "id", - "type_info": "Int4" + "type_info": "Int4", + "origin": { + "Table": { + "table": "mod_gd_versions", + "name": "id" + } + } }, { "ordinal": 1, "name": "mod_id", - "type_info": "Int4" + "type_info": "Int4", + "origin": { + "Table": { + "table": "mod_gd_versions", + "name": "mod_id" + } + } }, { "ordinal": 2, @@ -38,6 +50,12 @@ ] } } + }, + "origin": { + "Table": { + "table": "mod_gd_versions", + "name": "gd" + } } }, { @@ -57,6 +75,12 @@ ] } } + }, + "origin": { + "Table": { + "table": "mod_gd_versions", + "name": "platform" + } } } ], diff --git a/.sqlx/query-87c39e971df622c0ae622e37563aab11bb4b6634b7e6d9420097ec25faea4d8c.json b/.sqlx/query-87c39e971df622c0ae622e37563aab11bb4b6634b7e6d9420097ec25faea4d8c.json new file mode 100644 index 00000000..7b5bf4c1 --- /dev/null +++ b/.sqlx/query-87c39e971df622c0ae622e37563aab11bb4b6634b7e6d9420097ec25faea4d8c.json @@ -0,0 +1,217 @@ +{ + "db_name": "PostgreSQL", + "query": "SELECT DISTINCT\n mv.name, mv.id, mv.description, mv.version, mv.download_link, mv.managed_download_link, mv.hash,\n format_semver(mv.geode_major, mv.geode_minor, mv.geode_patch, mv.geode_meta) as \"geode!: _\",\n mv.download_count, mv.early_load, mv.requires_patching, mv.api, mv.mod_id, mv.created_at, mv.updated_at,\n 'pending'::mod_version_status as \"status!: _\", NULL as info\n FROM mod_versions mv\n INNER JOIN mod_version_statuses mvs ON mvs.mod_version_id = mv.id\n WHERE mvs.status = 'pending'\n AND mv.mod_id = ANY($1)\n ORDER BY mv.id DESC", + "describe": { + "columns": [ + { + "ordinal": 0, + "name": "name", + "type_info": "Text", + "origin": { + "Table": { + "table": "mod_versions", + "name": "name" + } + } + }, + { + "ordinal": 1, + "name": "id", + "type_info": "Int4", + "origin": { + "Table": { + "table": "mod_versions", + "name": "id" + } + } + }, + { + "ordinal": 2, + "name": "description", + "type_info": "Text", + "origin": { + "Table": { + "table": "mod_versions", + "name": "description" + } + } + }, + { + "ordinal": 3, + "name": "version", + "type_info": "Text", + "origin": { + "Table": { + "table": "mod_versions", + "name": "version" + } + } + }, + { + "ordinal": 4, + "name": "download_link", + "type_info": "Text", + "origin": { + "Table": { + "table": "mod_versions", + "name": "download_link" + } + } + }, + { + "ordinal": 5, + "name": "managed_download_link", + "type_info": "Text", + "origin": { + "Table": { + "table": "mod_versions", + "name": "managed_download_link" + } + } + }, + { + "ordinal": 6, + "name": "hash", + "type_info": "Text", + "origin": { + "Table": { + "table": "mod_versions", + "name": "hash" + } + } + }, + { + "ordinal": 7, + "name": "geode!: _", + "type_info": "Text", + "origin": "Expression" + }, + { + "ordinal": 8, + "name": "download_count", + "type_info": "Int4", + "origin": { + "Table": { + "table": "mod_versions", + "name": "download_count" + } + } + }, + { + "ordinal": 9, + "name": "early_load", + "type_info": "Bool", + "origin": { + "Table": { + "table": "mod_versions", + "name": "early_load" + } + } + }, + { + "ordinal": 10, + "name": "requires_patching", + "type_info": "Bool", + "origin": { + "Table": { + "table": "mod_versions", + "name": "requires_patching" + } + } + }, + { + "ordinal": 11, + "name": "api", + "type_info": "Bool", + "origin": { + "Table": { + "table": "mod_versions", + "name": "api" + } + } + }, + { + "ordinal": 12, + "name": "mod_id", + "type_info": "Text", + "origin": { + "Table": { + "table": "mod_versions", + "name": "mod_id" + } + } + }, + { + "ordinal": 13, + "name": "created_at", + "type_info": "Timestamptz", + "origin": { + "Table": { + "table": "mod_versions", + "name": "created_at" + } + } + }, + { + "ordinal": 14, + "name": "updated_at", + "type_info": "Timestamptz", + "origin": { + "Table": { + "table": "mod_versions", + "name": "updated_at" + } + } + }, + { + "ordinal": 15, + "name": "status!: _", + "type_info": { + "Custom": { + "name": "mod_version_status", + "kind": { + "Enum": [ + "pending", + "rejected", + "accepted", + "unlisted" + ] + } + } + }, + "origin": "Expression" + }, + { + "ordinal": 16, + "name": "info", + "type_info": "Text", + "origin": "Expression" + } + ], + "parameters": { + "Left": [ + "TextArray" + ] + }, + "nullable": [ + false, + false, + true, + false, + false, + true, + false, + null, + false, + false, + false, + false, + false, + true, + true, + null, + null + ] + }, + "hash": "87c39e971df622c0ae622e37563aab11bb4b6634b7e6d9420097ec25faea4d8c" +} diff --git a/.sqlx/query-880569e638c035da1f99ed07e9d56e16fa96998dc0cc1869ed06c84e567c6ff8.json b/.sqlx/query-880569e638c035da1f99ed07e9d56e16fa96998dc0cc1869ed06c84e567c6ff8.json deleted file mode 100644 index ed52e719..00000000 --- a/.sqlx/query-880569e638c035da1f99ed07e9d56e16fa96998dc0cc1869ed06c84e567c6ff8.json +++ /dev/null @@ -1,124 +0,0 @@ -{ - "db_name": "PostgreSQL", - "query": "SELECT DISTINCT\n mv.name, mv.id, mv.description, mv.version, mv.download_link, mv.hash,\n format_semver(mv.geode_major, mv.geode_minor, mv.geode_patch, mv.geode_meta) as \"geode!: _\",\n mv.download_count, mv.early_load, mv.requires_patching, mv.api, mv.mod_id, mv.created_at, mv.updated_at,\n 'pending'::mod_version_status as \"status!: _\", NULL as info\n FROM mod_versions mv\n INNER JOIN mod_version_statuses mvs ON mvs.mod_version_id = mv.id\n WHERE mvs.status = 'pending'\n AND mv.mod_id = ANY($1)\n ORDER BY mv.id DESC", - "describe": { - "columns": [ - { - "ordinal": 0, - "name": "name", - "type_info": "Text" - }, - { - "ordinal": 1, - "name": "id", - "type_info": "Int4" - }, - { - "ordinal": 2, - "name": "description", - "type_info": "Text" - }, - { - "ordinal": 3, - "name": "version", - "type_info": "Text" - }, - { - "ordinal": 4, - "name": "download_link", - "type_info": "Text" - }, - { - "ordinal": 5, - "name": "hash", - "type_info": "Text" - }, - { - "ordinal": 6, - "name": "geode!: _", - "type_info": "Text" - }, - { - "ordinal": 7, - "name": "download_count", - "type_info": "Int4" - }, - { - "ordinal": 8, - "name": "early_load", - "type_info": "Bool" - }, - { - "ordinal": 9, - "name": "requires_patching", - "type_info": "Bool" - }, - { - "ordinal": 10, - "name": "api", - "type_info": "Bool" - }, - { - "ordinal": 11, - "name": "mod_id", - "type_info": "Text" - }, - { - "ordinal": 12, - "name": "created_at", - "type_info": "Timestamptz" - }, - { - "ordinal": 13, - "name": "updated_at", - "type_info": "Timestamptz" - }, - { - "ordinal": 14, - "name": "status!: _", - "type_info": { - "Custom": { - "name": "mod_version_status", - "kind": { - "Enum": [ - "pending", - "rejected", - "accepted", - "unlisted" - ] - } - } - } - }, - { - "ordinal": 15, - "name": "info", - "type_info": "Text" - } - ], - "parameters": { - "Left": [ - "TextArray" - ] - }, - "nullable": [ - false, - false, - true, - false, - false, - false, - null, - false, - false, - false, - false, - false, - true, - true, - null, - null - ] - }, - "hash": "880569e638c035da1f99ed07e9d56e16fa96998dc0cc1869ed06c84e567c6ff8" -} diff --git a/.sqlx/query-8affc6971c1e33b14f3696d0bd9daf4b82d907eba99837083e21909ea9c195a7.json b/.sqlx/query-8affc6971c1e33b14f3696d0bd9daf4b82d907eba99837083e21909ea9c195a7.json index 2ca4f752..8ee28a5b 100644 --- a/.sqlx/query-8affc6971c1e33b14f3696d0bd9daf4b82d907eba99837083e21909ea9c195a7.json +++ b/.sqlx/query-8affc6971c1e33b14f3696d0bd9daf4b82d907eba99837083e21909ea9c195a7.json @@ -6,32 +6,68 @@ { "ordinal": 0, "name": "id", - "type_info": "Int4" + "type_info": "Int4", + "origin": { + "Table": { + "table": "developers", + "name": "id" + } + } }, { "ordinal": 1, "name": "username", - "type_info": "Text" + "type_info": "Text", + "origin": { + "Table": { + "table": "developers", + "name": "username" + } + } }, { "ordinal": 2, "name": "display_name", - "type_info": "Text" + "type_info": "Text", + "origin": { + "Table": { + "table": "developers", + "name": "display_name" + } + } }, { "ordinal": 3, "name": "verified", - "type_info": "Bool" + "type_info": "Bool", + "origin": { + "Table": { + "table": "developers", + "name": "verified" + } + } }, { "ordinal": 4, "name": "admin", - "type_info": "Bool" + "type_info": "Bool", + "origin": { + "Table": { + "table": "developers", + "name": "admin" + } + } }, { "ordinal": 5, "name": "github_id", - "type_info": "Int8" + "type_info": "Int8", + "origin": { + "Table": { + "table": "developers", + "name": "github_user_id" + } + } } ], "parameters": { diff --git a/.sqlx/query-8c1f2dd19652bb6c393d83c6443bc4cda1f108a749cc953adb9d25a2fffa4072.json b/.sqlx/query-8c1f2dd19652bb6c393d83c6443bc4cda1f108a749cc953adb9d25a2fffa4072.json index 4f049ef8..b531e2d4 100644 --- a/.sqlx/query-8c1f2dd19652bb6c393d83c6443bc4cda1f108a749cc953adb9d25a2fffa4072.json +++ b/.sqlx/query-8c1f2dd19652bb6c393d83c6443bc4cda1f108a749cc953adb9d25a2fffa4072.json @@ -6,32 +6,68 @@ { "ordinal": 0, "name": "id", - "type_info": "Int8" + "type_info": "Int8", + "origin": { + "Table": { + "table": "mod_version_submission_comments", + "name": "id" + } + } }, { "ordinal": 1, "name": "submission_id", - "type_info": "Int4" + "type_info": "Int4", + "origin": { + "Table": { + "table": "mod_version_submission_comments", + "name": "submission_id" + } + } }, { "ordinal": 2, "name": "comment", - "type_info": "Text" + "type_info": "Text", + "origin": { + "Table": { + "table": "mod_version_submission_comments", + "name": "comment" + } + } }, { "ordinal": 3, "name": "author_id", - "type_info": "Int4" + "type_info": "Int4", + "origin": { + "Table": { + "table": "mod_version_submission_comments", + "name": "author_id" + } + } }, { "ordinal": 4, "name": "created_at", - "type_info": "Timestamptz" + "type_info": "Timestamptz", + "origin": { + "Table": { + "table": "mod_version_submission_comments", + "name": "created_at" + } + } }, { "ordinal": 5, "name": "updated_at", - "type_info": "Timestamptz" + "type_info": "Timestamptz", + "origin": { + "Table": { + "table": "mod_version_submission_comments", + "name": "updated_at" + } + } } ], "parameters": { diff --git a/.sqlx/query-8e2101aa5b21d78fe39d03122248fa38da224bae0ad16be16445bf210230e33e.json b/.sqlx/query-8e2101aa5b21d78fe39d03122248fa38da224bae0ad16be16445bf210230e33e.json index e65c4f2e..538ebb0c 100644 --- a/.sqlx/query-8e2101aa5b21d78fe39d03122248fa38da224bae0ad16be16445bf210230e33e.json +++ b/.sqlx/query-8e2101aa5b21d78fe39d03122248fa38da224bae0ad16be16445bf210230e33e.json @@ -6,7 +6,13 @@ { "ordinal": 0, "name": "id", - "type_info": "Text" + "type_info": "Text", + "origin": { + "Table": { + "table": "mods", + "name": "id" + } + } } ], "parameters": { diff --git a/.sqlx/query-905ee0c060aad711f949eef40c3d1c5c88c27e43b9e0f19b8ed13d150bcd67d8.json b/.sqlx/query-905ee0c060aad711f949eef40c3d1c5c88c27e43b9e0f19b8ed13d150bcd67d8.json deleted file mode 100644 index 9ebff9fc..00000000 --- a/.sqlx/query-905ee0c060aad711f949eef40c3d1c5c88c27e43b9e0f19b8ed13d150bcd67d8.json +++ /dev/null @@ -1,173 +0,0 @@ -{ - "db_name": "PostgreSQL", - "query": "SELECT\n m.id, m.repository, m.about, m.changelog, m.featured, m.download_count as mod_download_count, m.created_at, m.updated_at,\n mv.id as version_id, mv.name, mv.description, mv.version, mv.download_link, mv.download_count as mod_version_download_count,\n mv.created_at as mod_version_created_at, mv.updated_at as mod_version_updated_at,\n mv.hash,\n format_semver(mv.geode_major, mv.geode_minor, mv.geode_patch, mv.geode_meta) as \"geode!: _\",\n mv.early_load, mv.requires_patching, mv.api, mv.mod_id, mvs.status as \"status: _\", mvs.info\n FROM mods m\n INNER JOIN mod_versions mv ON m.id = mv.mod_id\n INNER JOIN mod_version_statuses mvs ON mvs.mod_version_id = mv.id\n WHERE m.id = $1\n AND ($2 = false OR mvs.status = 'accepted')\n ORDER BY mv.id DESC", - "describe": { - "columns": [ - { - "ordinal": 0, - "name": "id", - "type_info": "Text" - }, - { - "ordinal": 1, - "name": "repository", - "type_info": "Text" - }, - { - "ordinal": 2, - "name": "about", - "type_info": "Text" - }, - { - "ordinal": 3, - "name": "changelog", - "type_info": "Text" - }, - { - "ordinal": 4, - "name": "featured", - "type_info": "Bool" - }, - { - "ordinal": 5, - "name": "mod_download_count", - "type_info": "Int4" - }, - { - "ordinal": 6, - "name": "created_at", - "type_info": "Timestamptz" - }, - { - "ordinal": 7, - "name": "updated_at", - "type_info": "Timestamptz" - }, - { - "ordinal": 8, - "name": "version_id", - "type_info": "Int4" - }, - { - "ordinal": 9, - "name": "name", - "type_info": "Text" - }, - { - "ordinal": 10, - "name": "description", - "type_info": "Text" - }, - { - "ordinal": 11, - "name": "version", - "type_info": "Text" - }, - { - "ordinal": 12, - "name": "download_link", - "type_info": "Text" - }, - { - "ordinal": 13, - "name": "mod_version_download_count", - "type_info": "Int4" - }, - { - "ordinal": 14, - "name": "mod_version_created_at", - "type_info": "Timestamptz" - }, - { - "ordinal": 15, - "name": "mod_version_updated_at", - "type_info": "Timestamptz" - }, - { - "ordinal": 16, - "name": "hash", - "type_info": "Text" - }, - { - "ordinal": 17, - "name": "geode!: _", - "type_info": "Text" - }, - { - "ordinal": 18, - "name": "early_load", - "type_info": "Bool" - }, - { - "ordinal": 19, - "name": "requires_patching", - "type_info": "Bool" - }, - { - "ordinal": 20, - "name": "api", - "type_info": "Bool" - }, - { - "ordinal": 21, - "name": "mod_id", - "type_info": "Text" - }, - { - "ordinal": 22, - "name": "status: _", - "type_info": { - "Custom": { - "name": "mod_version_status", - "kind": { - "Enum": [ - "pending", - "rejected", - "accepted", - "unlisted" - ] - } - } - } - }, - { - "ordinal": 23, - "name": "info", - "type_info": "Text" - } - ], - "parameters": { - "Left": [ - "Text", - "Bool" - ] - }, - "nullable": [ - false, - true, - true, - true, - false, - false, - false, - false, - false, - false, - true, - false, - false, - false, - true, - true, - false, - null, - false, - false, - false, - false, - false, - true - ] - }, - "hash": "905ee0c060aad711f949eef40c3d1c5c88c27e43b9e0f19b8ed13d150bcd67d8" -} diff --git a/.sqlx/query-91bc425cc6b35915fc00d39b1f127118f0a35841049fc0914add705241d471f6.json b/.sqlx/query-91bc425cc6b35915fc00d39b1f127118f0a35841049fc0914add705241d471f6.json index 4f45f9bb..3b86213f 100644 --- a/.sqlx/query-91bc425cc6b35915fc00d39b1f127118f0a35841049fc0914add705241d471f6.json +++ b/.sqlx/query-91bc425cc6b35915fc00d39b1f127118f0a35841049fc0914add705241d471f6.json @@ -6,7 +6,8 @@ { "ordinal": 0, "name": "count", - "type_info": "Int8" + "type_info": "Int8", + "origin": "Expression" } ], "parameters": { diff --git a/.sqlx/query-91ce04c955fe760ea792a973e258247ea42f0f7c5f68391642480758ddf9b4bc.json b/.sqlx/query-91ce04c955fe760ea792a973e258247ea42f0f7c5f68391642480758ddf9b4bc.json index ba74b44e..1a047e1b 100644 --- a/.sqlx/query-91ce04c955fe760ea792a973e258247ea42f0f7c5f68391642480758ddf9b4bc.json +++ b/.sqlx/query-91ce04c955fe760ea792a973e258247ea42f0f7c5f68391642480758ddf9b4bc.json @@ -6,7 +6,13 @@ { "ordinal": 0, "name": "developer_id", - "type_info": "Int4" + "type_info": "Int4", + "origin": { + "Table": { + "table": "mods_developers", + "name": "developer_id" + } + } } ], "parameters": { diff --git a/.sqlx/query-94a9f2bc14d5a6c21eb7f638e5d70bcdc7112d9ad0d153aaad6bf7b00e27d74a.json b/.sqlx/query-94a9f2bc14d5a6c21eb7f638e5d70bcdc7112d9ad0d153aaad6bf7b00e27d74a.json index e2cb2674..3933afcb 100644 --- a/.sqlx/query-94a9f2bc14d5a6c21eb7f638e5d70bcdc7112d9ad0d153aaad6bf7b00e27d74a.json +++ b/.sqlx/query-94a9f2bc14d5a6c21eb7f638e5d70bcdc7112d9ad0d153aaad6bf7b00e27d74a.json @@ -28,6 +28,12 @@ ] } } + }, + "origin": { + "Table": { + "table": "geode_versions", + "name": "mac" + } } }, { @@ -55,6 +61,12 @@ ] } } + }, + "origin": { + "Table": { + "table": "geode_versions", + "name": "win" + } } }, { @@ -82,6 +94,12 @@ ] } } + }, + "origin": { + "Table": { + "table": "geode_versions", + "name": "android" + } } }, { @@ -109,27 +127,57 @@ ] } } + }, + "origin": { + "Table": { + "table": "geode_versions", + "name": "ios" + } } }, { "ordinal": 4, "name": "tag", - "type_info": "Text" + "type_info": "Text", + "origin": { + "Table": { + "table": "geode_versions", + "name": "tag" + } + } }, { "ordinal": 5, "name": "created_at", - "type_info": "Timestamptz" + "type_info": "Timestamptz", + "origin": { + "Table": { + "table": "geode_versions", + "name": "created_at" + } + } }, { "ordinal": 6, "name": "commit_hash", - "type_info": "Text" + "type_info": "Text", + "origin": { + "Table": { + "table": "geode_versions", + "name": "commit_hash" + } + } }, { "ordinal": 7, "name": "prerelease", - "type_info": "Bool" + "type_info": "Bool", + "origin": { + "Table": { + "table": "geode_versions", + "name": "prerelease" + } + } } ], "parameters": { diff --git a/.sqlx/query-959d6a60bbb47b24bc86963c0063bdd1268c75d03563eaf78eec41752cc1a491.json b/.sqlx/query-959d6a60bbb47b24bc86963c0063bdd1268c75d03563eaf78eec41752cc1a491.json index 5df17d6c..6cf71c0c 100644 --- a/.sqlx/query-959d6a60bbb47b24bc86963c0063bdd1268c75d03563eaf78eec41752cc1a491.json +++ b/.sqlx/query-959d6a60bbb47b24bc86963c0063bdd1268c75d03563eaf78eec41752cc1a491.json @@ -6,42 +6,90 @@ { "ordinal": 0, "name": "id", - "type_info": "Text" + "type_info": "Text", + "origin": { + "Table": { + "table": "mods", + "name": "id" + } + } }, { "ordinal": 1, "name": "repository", - "type_info": "Text" + "type_info": "Text", + "origin": { + "Table": { + "table": "mods", + "name": "repository" + } + } }, { "ordinal": 2, "name": "about", - "type_info": "Text" + "type_info": "Text", + "origin": { + "Table": { + "table": "mods", + "name": "about" + } + } }, { "ordinal": 3, "name": "changelog", - "type_info": "Text" + "type_info": "Text", + "origin": { + "Table": { + "table": "mods", + "name": "changelog" + } + } }, { "ordinal": 4, "name": "featured", - "type_info": "Bool" + "type_info": "Bool", + "origin": { + "Table": { + "table": "mods", + "name": "featured" + } + } }, { "ordinal": 5, "name": "download_count", - "type_info": "Int4" + "type_info": "Int4", + "origin": { + "Table": { + "table": "mods", + "name": "download_count" + } + } }, { "ordinal": 6, "name": "created_at", - "type_info": "Timestamptz" + "type_info": "Timestamptz", + "origin": { + "Table": { + "table": "mods", + "name": "created_at" + } + } }, { "ordinal": 7, "name": "updated_at", - "type_info": "Timestamptz" + "type_info": "Timestamptz", + "origin": { + "Table": { + "table": "mods", + "name": "updated_at" + } + } } ], "parameters": { diff --git a/.sqlx/query-964d894336ec2b5381c454d50a8a4a94573787ab881df61c69818b6c0435951c.json b/.sqlx/query-964d894336ec2b5381c454d50a8a4a94573787ab881df61c69818b6c0435951c.json new file mode 100644 index 00000000..e470cd08 --- /dev/null +++ b/.sqlx/query-964d894336ec2b5381c454d50a8a4a94573787ab881df61c69818b6c0435951c.json @@ -0,0 +1,247 @@ +{ + "db_name": "PostgreSQL", + "query": "SELECT\n mv.id, mv.name, mv.description, mv.version,\n mv.download_link, mv.managed_download_link, mv.download_count, mv.hash,\n format_semver(mv.geode_major, mv.geode_minor, mv.geode_patch, mv.geode_meta) as \"geode!: _\",\n mv.early_load, mv.requires_patching, mv.api, mv.mod_id,\n mv.created_at, mv.updated_at,\n mvs.status as \"status: _\", mvs.info\n FROM mod_versions mv\n INNER JOIN mod_version_statuses mvs ON mvs.mod_version_id = mv.id\n WHERE mv.mod_id = $1\n AND ($2::mod_version_status[] IS NULL OR mvs.status = ANY($2))\n ORDER BY mv.id DESC", + "describe": { + "columns": [ + { + "ordinal": 0, + "name": "id", + "type_info": "Int4", + "origin": { + "Table": { + "table": "mod_versions", + "name": "id" + } + } + }, + { + "ordinal": 1, + "name": "name", + "type_info": "Text", + "origin": { + "Table": { + "table": "mod_versions", + "name": "name" + } + } + }, + { + "ordinal": 2, + "name": "description", + "type_info": "Text", + "origin": { + "Table": { + "table": "mod_versions", + "name": "description" + } + } + }, + { + "ordinal": 3, + "name": "version", + "type_info": "Text", + "origin": { + "Table": { + "table": "mod_versions", + "name": "version" + } + } + }, + { + "ordinal": 4, + "name": "download_link", + "type_info": "Text", + "origin": { + "Table": { + "table": "mod_versions", + "name": "download_link" + } + } + }, + { + "ordinal": 5, + "name": "managed_download_link", + "type_info": "Text", + "origin": { + "Table": { + "table": "mod_versions", + "name": "managed_download_link" + } + } + }, + { + "ordinal": 6, + "name": "download_count", + "type_info": "Int4", + "origin": { + "Table": { + "table": "mod_versions", + "name": "download_count" + } + } + }, + { + "ordinal": 7, + "name": "hash", + "type_info": "Text", + "origin": { + "Table": { + "table": "mod_versions", + "name": "hash" + } + } + }, + { + "ordinal": 8, + "name": "geode!: _", + "type_info": "Text", + "origin": "Expression" + }, + { + "ordinal": 9, + "name": "early_load", + "type_info": "Bool", + "origin": { + "Table": { + "table": "mod_versions", + "name": "early_load" + } + } + }, + { + "ordinal": 10, + "name": "requires_patching", + "type_info": "Bool", + "origin": { + "Table": { + "table": "mod_versions", + "name": "requires_patching" + } + } + }, + { + "ordinal": 11, + "name": "api", + "type_info": "Bool", + "origin": { + "Table": { + "table": "mod_versions", + "name": "api" + } + } + }, + { + "ordinal": 12, + "name": "mod_id", + "type_info": "Text", + "origin": { + "Table": { + "table": "mod_versions", + "name": "mod_id" + } + } + }, + { + "ordinal": 13, + "name": "created_at", + "type_info": "Timestamptz", + "origin": { + "Table": { + "table": "mod_versions", + "name": "created_at" + } + } + }, + { + "ordinal": 14, + "name": "updated_at", + "type_info": "Timestamptz", + "origin": { + "Table": { + "table": "mod_versions", + "name": "updated_at" + } + } + }, + { + "ordinal": 15, + "name": "status: _", + "type_info": { + "Custom": { + "name": "mod_version_status", + "kind": { + "Enum": [ + "pending", + "rejected", + "accepted", + "unlisted" + ] + } + } + }, + "origin": { + "Table": { + "table": "mod_version_statuses", + "name": "status" + } + } + }, + { + "ordinal": 16, + "name": "info", + "type_info": "Text", + "origin": { + "Table": { + "table": "mod_version_statuses", + "name": "info" + } + } + } + ], + "parameters": { + "Left": [ + "Text", + { + "Custom": { + "name": "mod_version_status[]", + "kind": { + "Array": { + "Custom": { + "name": "mod_version_status", + "kind": { + "Enum": [ + "pending", + "rejected", + "accepted", + "unlisted" + ] + } + } + } + } + } + } + ] + }, + "nullable": [ + false, + false, + true, + false, + false, + true, + false, + false, + null, + false, + false, + false, + false, + true, + true, + false, + true + ] + }, + "hash": "964d894336ec2b5381c454d50a8a4a94573787ab881df61c69818b6c0435951c" +} diff --git a/.sqlx/query-96f3e4f9ceffa7f3d9a609252d9f635e70dd70cdafc327486aaa6a6f49e3c5db.json b/.sqlx/query-96f3e4f9ceffa7f3d9a609252d9f635e70dd70cdafc327486aaa6a6f49e3c5db.json new file mode 100644 index 00000000..9a8c102d --- /dev/null +++ b/.sqlx/query-96f3e4f9ceffa7f3d9a609252d9f635e70dd70cdafc327486aaa6a6f49e3c5db.json @@ -0,0 +1,229 @@ +{ + "db_name": "PostgreSQL", + "query": "SELECT mv.id, mv.name, mv.description, mv.version,\n mv.download_link, mv.managed_download_link, mv.download_count,\n mv.hash,\n format_semver(mv.geode_major, mv.geode_minor, mv.geode_patch, mv.geode_meta) as \"geode!: _\",\n mv.early_load, mv.requires_patching, mv.api,\n mv.created_at, mv.updated_at,\n mv.mod_id, mvs.status as \"status: _\", mvs.info\n FROM mod_versions mv\n INNER JOIN mods m ON m.id = mv.mod_id\n INNER JOIN mod_version_statuses mvs ON mvs.mod_version_id = mv.id\n WHERE mv.mod_id = $1 AND mv.version = $2\n AND (mvs.status = 'accepted' OR $3 = false)", + "describe": { + "columns": [ + { + "ordinal": 0, + "name": "id", + "type_info": "Int4", + "origin": { + "Table": { + "table": "mod_versions", + "name": "id" + } + } + }, + { + "ordinal": 1, + "name": "name", + "type_info": "Text", + "origin": { + "Table": { + "table": "mod_versions", + "name": "name" + } + } + }, + { + "ordinal": 2, + "name": "description", + "type_info": "Text", + "origin": { + "Table": { + "table": "mod_versions", + "name": "description" + } + } + }, + { + "ordinal": 3, + "name": "version", + "type_info": "Text", + "origin": { + "Table": { + "table": "mod_versions", + "name": "version" + } + } + }, + { + "ordinal": 4, + "name": "download_link", + "type_info": "Text", + "origin": { + "Table": { + "table": "mod_versions", + "name": "download_link" + } + } + }, + { + "ordinal": 5, + "name": "managed_download_link", + "type_info": "Text", + "origin": { + "Table": { + "table": "mod_versions", + "name": "managed_download_link" + } + } + }, + { + "ordinal": 6, + "name": "download_count", + "type_info": "Int4", + "origin": { + "Table": { + "table": "mod_versions", + "name": "download_count" + } + } + }, + { + "ordinal": 7, + "name": "hash", + "type_info": "Text", + "origin": { + "Table": { + "table": "mod_versions", + "name": "hash" + } + } + }, + { + "ordinal": 8, + "name": "geode!: _", + "type_info": "Text", + "origin": "Expression" + }, + { + "ordinal": 9, + "name": "early_load", + "type_info": "Bool", + "origin": { + "Table": { + "table": "mod_versions", + "name": "early_load" + } + } + }, + { + "ordinal": 10, + "name": "requires_patching", + "type_info": "Bool", + "origin": { + "Table": { + "table": "mod_versions", + "name": "requires_patching" + } + } + }, + { + "ordinal": 11, + "name": "api", + "type_info": "Bool", + "origin": { + "Table": { + "table": "mod_versions", + "name": "api" + } + } + }, + { + "ordinal": 12, + "name": "created_at", + "type_info": "Timestamptz", + "origin": { + "Table": { + "table": "mod_versions", + "name": "created_at" + } + } + }, + { + "ordinal": 13, + "name": "updated_at", + "type_info": "Timestamptz", + "origin": { + "Table": { + "table": "mod_versions", + "name": "updated_at" + } + } + }, + { + "ordinal": 14, + "name": "mod_id", + "type_info": "Text", + "origin": { + "Table": { + "table": "mod_versions", + "name": "mod_id" + } + } + }, + { + "ordinal": 15, + "name": "status: _", + "type_info": { + "Custom": { + "name": "mod_version_status", + "kind": { + "Enum": [ + "pending", + "rejected", + "accepted", + "unlisted" + ] + } + } + }, + "origin": { + "Table": { + "table": "mod_version_statuses", + "name": "status" + } + } + }, + { + "ordinal": 16, + "name": "info", + "type_info": "Text", + "origin": { + "Table": { + "table": "mod_version_statuses", + "name": "info" + } + } + } + ], + "parameters": { + "Left": [ + "Text", + "Text", + "Bool" + ] + }, + "nullable": [ + false, + false, + true, + false, + false, + true, + false, + false, + null, + false, + false, + false, + true, + true, + false, + false, + true + ] + }, + "hash": "96f3e4f9ceffa7f3d9a609252d9f635e70dd70cdafc327486aaa6a6f49e3c5db" +} diff --git a/.sqlx/query-9931bc9f6820c39fdb3c287b4cc76dac05938b5b33b61f2667955ea1b5832d87.json b/.sqlx/query-9931bc9f6820c39fdb3c287b4cc76dac05938b5b33b61f2667955ea1b5832d87.json index 8cfea759..981a89e3 100644 --- a/.sqlx/query-9931bc9f6820c39fdb3c287b4cc76dac05938b5b33b61f2667955ea1b5832d87.json +++ b/.sqlx/query-9931bc9f6820c39fdb3c287b4cc76dac05938b5b33b61f2667955ea1b5832d87.json @@ -6,22 +6,46 @@ { "ordinal": 0, "name": "mod_id", - "type_info": "Text" + "type_info": "Text", + "origin": { + "Table": { + "table": "mod_links", + "name": "mod_id" + } + } }, { "ordinal": 1, "name": "community", - "type_info": "Text" + "type_info": "Text", + "origin": { + "Table": { + "table": "mod_links", + "name": "community" + } + } }, { "ordinal": 2, "name": "homepage", - "type_info": "Text" + "type_info": "Text", + "origin": { + "Table": { + "table": "mod_links", + "name": "homepage" + } + } }, { "ordinal": 3, "name": "source", - "type_info": "Text" + "type_info": "Text", + "origin": { + "Table": { + "table": "mod_links", + "name": "source" + } + } } ], "parameters": { diff --git a/.sqlx/query-9a23bc60988017bdb2d3770f0cbe4e806b378409a148cb0728c03c70470954f5.json b/.sqlx/query-9a23bc60988017bdb2d3770f0cbe4e806b378409a148cb0728c03c70470954f5.json index 05d0e991..c4ad3042 100644 --- a/.sqlx/query-9a23bc60988017bdb2d3770f0cbe4e806b378409a148cb0728c03c70470954f5.json +++ b/.sqlx/query-9a23bc60988017bdb2d3770f0cbe4e806b378409a148cb0728c03c70470954f5.json @@ -6,7 +6,13 @@ { "ordinal": 0, "name": "mod_version_id", - "type_info": "Int4" + "type_info": "Int4", + "origin": { + "Table": { + "table": "mod_version_submissions", + "name": "mod_version_id" + } + } }, { "ordinal": 1, @@ -22,22 +28,46 @@ ] } } + }, + "origin": { + "Table": { + "table": "mod_version_submissions", + "name": "lock" + } } }, { "ordinal": 2, "name": "locked_by", - "type_info": "Int4" + "type_info": "Int4", + "origin": { + "Table": { + "table": "mod_version_submissions", + "name": "locked_by" + } + } }, { "ordinal": 3, "name": "created_at", - "type_info": "Timestamptz" + "type_info": "Timestamptz", + "origin": { + "Table": { + "table": "mod_version_submissions", + "name": "created_at" + } + } }, { "ordinal": 4, "name": "updated_at", - "type_info": "Timestamptz" + "type_info": "Timestamptz", + "origin": { + "Table": { + "table": "mod_version_submissions", + "name": "updated_at" + } + } } ], "parameters": { diff --git a/.sqlx/query-9d56e772c5f6697ab40d0b43581732ccafe10fe556de4659124e59abe8cd7552.json b/.sqlx/query-9d56e772c5f6697ab40d0b43581732ccafe10fe556de4659124e59abe8cd7552.json index db738446..bc01530d 100644 --- a/.sqlx/query-9d56e772c5f6697ab40d0b43581732ccafe10fe556de4659124e59abe8cd7552.json +++ b/.sqlx/query-9d56e772c5f6697ab40d0b43581732ccafe10fe556de4659124e59abe8cd7552.json @@ -6,47 +6,101 @@ { "ordinal": 0, "name": "uuid", - "type_info": "Uuid" + "type_info": "Uuid", + "origin": { + "Table": { + "table": "github_login_attempts", + "name": "uid" + } + } }, { "ordinal": 1, "name": "ip", - "type_info": "Inet" + "type_info": "Inet", + "origin": { + "Table": { + "table": "github_login_attempts", + "name": "ip" + } + } }, { "ordinal": 2, "name": "device_code", - "type_info": "Text" + "type_info": "Text", + "origin": { + "Table": { + "table": "github_login_attempts", + "name": "device_code" + } + } }, { "ordinal": 3, "name": "uri", - "type_info": "Text" + "type_info": "Text", + "origin": { + "Table": { + "table": "github_login_attempts", + "name": "challenge_uri" + } + } }, { "ordinal": 4, "name": "user_code", - "type_info": "Text" + "type_info": "Text", + "origin": { + "Table": { + "table": "github_login_attempts", + "name": "user_code" + } + } }, { "ordinal": 5, "name": "interval", - "type_info": "Int4" + "type_info": "Int4", + "origin": { + "Table": { + "table": "github_login_attempts", + "name": "interval" + } + } }, { "ordinal": 6, "name": "expires_in", - "type_info": "Int4" + "type_info": "Int4", + "origin": { + "Table": { + "table": "github_login_attempts", + "name": "expires_in" + } + } }, { "ordinal": 7, "name": "created_at", - "type_info": "Timestamptz" + "type_info": "Timestamptz", + "origin": { + "Table": { + "table": "github_login_attempts", + "name": "created_at" + } + } }, { "ordinal": 8, "name": "last_poll", - "type_info": "Timestamptz" + "type_info": "Timestamptz", + "origin": { + "Table": { + "table": "github_login_attempts", + "name": "last_poll" + } + } } ], "parameters": { diff --git a/.sqlx/query-a29dd2a2f869ef9fda4b366ee9005fef1f99e69979838e30f908f20244caba1d.json b/.sqlx/query-a29dd2a2f869ef9fda4b366ee9005fef1f99e69979838e30f908f20244caba1d.json deleted file mode 100644 index f7c7128c..00000000 --- a/.sqlx/query-a29dd2a2f869ef9fda4b366ee9005fef1f99e69979838e30f908f20244caba1d.json +++ /dev/null @@ -1,126 +0,0 @@ -{ - "db_name": "PostgreSQL", - "query": "SELECT mv.id, mv.name, mv.description, mv.version,\n mv.download_link, mv.download_count,\n mv.hash,\n format_semver(mv.geode_major, mv.geode_minor, mv.geode_patch, mv.geode_meta) as \"geode!: _\",\n mv.early_load, mv.requires_patching, mv.api,\n mv.created_at, mv.updated_at,\n mv.mod_id, mvs.status as \"status: _\", mvs.info\n FROM mod_versions mv\n INNER JOIN mods m ON m.id = mv.mod_id\n INNER JOIN mod_version_statuses mvs ON mvs.mod_version_id = mv.id\n WHERE mv.mod_id = $1 AND mv.version = $2\n AND (mvs.status = 'accepted' OR $3 = false)", - "describe": { - "columns": [ - { - "ordinal": 0, - "name": "id", - "type_info": "Int4" - }, - { - "ordinal": 1, - "name": "name", - "type_info": "Text" - }, - { - "ordinal": 2, - "name": "description", - "type_info": "Text" - }, - { - "ordinal": 3, - "name": "version", - "type_info": "Text" - }, - { - "ordinal": 4, - "name": "download_link", - "type_info": "Text" - }, - { - "ordinal": 5, - "name": "download_count", - "type_info": "Int4" - }, - { - "ordinal": 6, - "name": "hash", - "type_info": "Text" - }, - { - "ordinal": 7, - "name": "geode!: _", - "type_info": "Text" - }, - { - "ordinal": 8, - "name": "early_load", - "type_info": "Bool" - }, - { - "ordinal": 9, - "name": "requires_patching", - "type_info": "Bool" - }, - { - "ordinal": 10, - "name": "api", - "type_info": "Bool" - }, - { - "ordinal": 11, - "name": "created_at", - "type_info": "Timestamptz" - }, - { - "ordinal": 12, - "name": "updated_at", - "type_info": "Timestamptz" - }, - { - "ordinal": 13, - "name": "mod_id", - "type_info": "Text" - }, - { - "ordinal": 14, - "name": "status: _", - "type_info": { - "Custom": { - "name": "mod_version_status", - "kind": { - "Enum": [ - "pending", - "rejected", - "accepted", - "unlisted" - ] - } - } - } - }, - { - "ordinal": 15, - "name": "info", - "type_info": "Text" - } - ], - "parameters": { - "Left": [ - "Text", - "Text", - "Bool" - ] - }, - "nullable": [ - false, - false, - true, - false, - false, - false, - false, - null, - false, - false, - false, - true, - true, - false, - false, - true - ] - }, - "hash": "a29dd2a2f869ef9fda4b366ee9005fef1f99e69979838e30f908f20244caba1d" -} diff --git a/.sqlx/query-a6c2a86e7f95612a9a2fdcc5168f9ab2485fc07b1b3d47f5327b91c6fcb9a653.json b/.sqlx/query-a6c2a86e7f95612a9a2fdcc5168f9ab2485fc07b1b3d47f5327b91c6fcb9a653.json index 1531665d..bdd73802 100644 --- a/.sqlx/query-a6c2a86e7f95612a9a2fdcc5168f9ab2485fc07b1b3d47f5327b91c6fcb9a653.json +++ b/.sqlx/query-a6c2a86e7f95612a9a2fdcc5168f9ab2485fc07b1b3d47f5327b91c6fcb9a653.json @@ -6,12 +6,24 @@ { "ordinal": 0, "name": "id", - "type_info": "Int4" + "type_info": "Int4", + "origin": { + "Table": { + "table": "mod_gd_versions", + "name": "id" + } + } }, { "ordinal": 1, "name": "mod_id", - "type_info": "Int4" + "type_info": "Int4", + "origin": { + "Table": { + "table": "mod_gd_versions", + "name": "mod_id" + } + } }, { "ordinal": 2, @@ -38,6 +50,12 @@ ] } } + }, + "origin": { + "Table": { + "table": "mod_gd_versions", + "name": "gd" + } } }, { @@ -57,6 +75,12 @@ ] } } + }, + "origin": { + "Table": { + "table": "mod_gd_versions", + "name": "platform" + } } } ], diff --git a/.sqlx/query-a83c43f2bdb4c61f72ae41987a3db540c91edbc36c595ce8c6644bdb36a771c3.json b/.sqlx/query-a83c43f2bdb4c61f72ae41987a3db540c91edbc36c595ce8c6644bdb36a771c3.json index dffd2dc5..5857037b 100644 --- a/.sqlx/query-a83c43f2bdb4c61f72ae41987a3db540c91edbc36c595ce8c6644bdb36a771c3.json +++ b/.sqlx/query-a83c43f2bdb4c61f72ae41987a3db540c91edbc36c595ce8c6644bdb36a771c3.json @@ -6,7 +6,13 @@ { "ordinal": 0, "name": "by_mod_id", - "type_info": "Text" + "type_info": "Text", + "origin": { + "Table": { + "table": "deprecated_by", + "name": "by_mod_id" + } + } } ], "parameters": { diff --git a/.sqlx/query-a9131f0ab03fa27cc7e6531397dc1d9343a95ff30a648d9c9b21120651a1caaa.json b/.sqlx/query-a9131f0ab03fa27cc7e6531397dc1d9343a95ff30a648d9c9b21120651a1caaa.json index 88a33273..e7c25064 100644 --- a/.sqlx/query-a9131f0ab03fa27cc7e6531397dc1d9343a95ff30a648d9c9b21120651a1caaa.json +++ b/.sqlx/query-a9131f0ab03fa27cc7e6531397dc1d9343a95ff30a648d9c9b21120651a1caaa.json @@ -6,42 +6,80 @@ { "ordinal": 0, "name": "id", - "type_info": "Text" + "type_info": "Text", + "origin": { + "Table": { + "table": "mods", + "name": "id" + } + } }, { "ordinal": 1, "name": "repository", - "type_info": "Text" + "type_info": "Text", + "origin": { + "Table": { + "table": "mods", + "name": "repository" + } + } }, { "ordinal": 2, "name": "about", - "type_info": "Text" + "type_info": "Text", + "origin": "Expression" }, { "ordinal": 3, "name": "changelog", - "type_info": "Text" + "type_info": "Text", + "origin": "Expression" }, { "ordinal": 4, "name": "featured", - "type_info": "Bool" + "type_info": "Bool", + "origin": { + "Table": { + "table": "mods", + "name": "featured" + } + } }, { "ordinal": 5, "name": "download_count", - "type_info": "Int4" + "type_info": "Int4", + "origin": { + "Table": { + "table": "mods", + "name": "download_count" + } + } }, { "ordinal": 6, "name": "created_at", - "type_info": "Timestamptz" + "type_info": "Timestamptz", + "origin": { + "Table": { + "table": "mods", + "name": "created_at" + } + } }, { "ordinal": 7, "name": "updated_at", - "type_info": "Timestamptz" + "type_info": "Timestamptz", + "origin": { + "Table": { + "table": "mods", + "name": "updated_at" + } + } } ], "parameters": { diff --git a/.sqlx/query-ae5d56bcbbcbbd970d63fe9a3324bcd78f595e7059cec91429fc0e734456bde1.json b/.sqlx/query-ae5d56bcbbcbbd970d63fe9a3324bcd78f595e7059cec91429fc0e734456bde1.json index c882a626..f3d4ce7d 100644 --- a/.sqlx/query-ae5d56bcbbcbbd970d63fe9a3324bcd78f595e7059cec91429fc0e734456bde1.json +++ b/.sqlx/query-ae5d56bcbbcbbd970d63fe9a3324bcd78f595e7059cec91429fc0e734456bde1.json @@ -6,7 +6,8 @@ { "ordinal": 0, "name": "count", - "type_info": "Int8" + "type_info": "Int8", + "origin": "Expression" } ], "parameters": { diff --git a/.sqlx/query-b13ceba1c001ab7955a7ff8e50853947f6252f641ed3af00a17cb069440e9570.json b/.sqlx/query-b13ceba1c001ab7955a7ff8e50853947f6252f641ed3af00a17cb069440e9570.json index 5944ca3b..d6aed55e 100644 --- a/.sqlx/query-b13ceba1c001ab7955a7ff8e50853947f6252f641ed3af00a17cb069440e9570.json +++ b/.sqlx/query-b13ceba1c001ab7955a7ff8e50853947f6252f641ed3af00a17cb069440e9570.json @@ -6,7 +6,13 @@ { "ordinal": 0, "name": "state", - "type_info": "Uuid" + "type_info": "Uuid", + "origin": { + "Table": { + "table": "github_web_logins", + "name": "state" + } + } } ], "parameters": { diff --git a/.sqlx/query-b248e326b0e2d3c803bedffef28fa22a00f19dca10f573b3f9331a830b0884d7.json b/.sqlx/query-b248e326b0e2d3c803bedffef28fa22a00f19dca10f573b3f9331a830b0884d7.json index ff275ba1..559217ff 100644 --- a/.sqlx/query-b248e326b0e2d3c803bedffef28fa22a00f19dca10f573b3f9331a830b0884d7.json +++ b/.sqlx/query-b248e326b0e2d3c803bedffef28fa22a00f19dca10f573b3f9331a830b0884d7.json @@ -6,12 +6,19 @@ { "ordinal": 0, "name": "filename", - "type_info": "Text" + "type_info": "Text", + "origin": { + "Table": { + "table": "mod_version_submission_comment_attachments", + "name": "filename" + } + } }, { "ordinal": 1, "name": "count", - "type_info": "Int8" + "type_info": "Int8", + "origin": "Expression" } ], "parameters": { diff --git a/.sqlx/query-b520ba987e3979c769e9dab052e42f6ee3f09ca365893cd95ff3821e1bb3a43b.json b/.sqlx/query-b520ba987e3979c769e9dab052e42f6ee3f09ca365893cd95ff3821e1bb3a43b.json deleted file mode 100644 index 93c3f844..00000000 --- a/.sqlx/query-b520ba987e3979c769e9dab052e42f6ee3f09ca365893cd95ff3821e1bb3a43b.json +++ /dev/null @@ -1,125 +0,0 @@ -{ - "db_name": "PostgreSQL", - "query": "SELECT\n mv.id, mv.name, mv.description, mv.version,\n mv.download_link, mv.download_count, mv.hash,\n format_semver(mv.geode_major, mv.geode_minor, mv.geode_patch, mv.geode_meta) as \"geode!: _\",\n mv.early_load, mv.requires_patching, mv.api, mv.mod_id,\n mv.created_at, mv.updated_at,\n mvs.status as \"status: _\", mvs.info\n FROM mod_versions mv\n INNER JOIN mod_version_statuses mvs ON mvs.mod_version_id = mv.id\n WHERE mv.mod_id = $1\n AND mv.version = $2", - "describe": { - "columns": [ - { - "ordinal": 0, - "name": "id", - "type_info": "Int4" - }, - { - "ordinal": 1, - "name": "name", - "type_info": "Text" - }, - { - "ordinal": 2, - "name": "description", - "type_info": "Text" - }, - { - "ordinal": 3, - "name": "version", - "type_info": "Text" - }, - { - "ordinal": 4, - "name": "download_link", - "type_info": "Text" - }, - { - "ordinal": 5, - "name": "download_count", - "type_info": "Int4" - }, - { - "ordinal": 6, - "name": "hash", - "type_info": "Text" - }, - { - "ordinal": 7, - "name": "geode!: _", - "type_info": "Text" - }, - { - "ordinal": 8, - "name": "early_load", - "type_info": "Bool" - }, - { - "ordinal": 9, - "name": "requires_patching", - "type_info": "Bool" - }, - { - "ordinal": 10, - "name": "api", - "type_info": "Bool" - }, - { - "ordinal": 11, - "name": "mod_id", - "type_info": "Text" - }, - { - "ordinal": 12, - "name": "created_at", - "type_info": "Timestamptz" - }, - { - "ordinal": 13, - "name": "updated_at", - "type_info": "Timestamptz" - }, - { - "ordinal": 14, - "name": "status: _", - "type_info": { - "Custom": { - "name": "mod_version_status", - "kind": { - "Enum": [ - "pending", - "rejected", - "accepted", - "unlisted" - ] - } - } - } - }, - { - "ordinal": 15, - "name": "info", - "type_info": "Text" - } - ], - "parameters": { - "Left": [ - "Text", - "Text" - ] - }, - "nullable": [ - false, - false, - true, - false, - false, - false, - false, - null, - false, - false, - false, - false, - true, - true, - false, - true - ] - }, - "hash": "b520ba987e3979c769e9dab052e42f6ee3f09ca365893cd95ff3821e1bb3a43b" -} diff --git a/.sqlx/query-bad99b175dfe2ffccfc71b69175b2593d77d4d24d6e2d9ba052ba4bf1cc6489d.json b/.sqlx/query-bad99b175dfe2ffccfc71b69175b2593d77d4d24d6e2d9ba052ba4bf1cc6489d.json index f983d45f..970dd598 100644 --- a/.sqlx/query-bad99b175dfe2ffccfc71b69175b2593d77d4d24d6e2d9ba052ba4bf1cc6489d.json +++ b/.sqlx/query-bad99b175dfe2ffccfc71b69175b2593d77d4d24d6e2d9ba052ba4bf1cc6489d.json @@ -6,32 +6,68 @@ { "ordinal": 0, "name": "id", - "type_info": "Int8" + "type_info": "Int8", + "origin": { + "Table": { + "table": "mod_version_submission_comments", + "name": "id" + } + } }, { "ordinal": 1, "name": "submission_id", - "type_info": "Int4" + "type_info": "Int4", + "origin": { + "Table": { + "table": "mod_version_submission_comments", + "name": "submission_id" + } + } }, { "ordinal": 2, "name": "comment", - "type_info": "Text" + "type_info": "Text", + "origin": { + "Table": { + "table": "mod_version_submission_comments", + "name": "comment" + } + } }, { "ordinal": 3, "name": "author_id", - "type_info": "Int4" + "type_info": "Int4", + "origin": { + "Table": { + "table": "mod_version_submission_comments", + "name": "author_id" + } + } }, { "ordinal": 4, "name": "created_at", - "type_info": "Timestamptz" + "type_info": "Timestamptz", + "origin": { + "Table": { + "table": "mod_version_submission_comments", + "name": "created_at" + } + } }, { "ordinal": 5, "name": "updated_at", - "type_info": "Timestamptz" + "type_info": "Timestamptz", + "origin": { + "Table": { + "table": "mod_version_submission_comments", + "name": "updated_at" + } + } } ], "parameters": { diff --git a/.sqlx/query-bcf3969b4f9bc4ca27bdca6bff0c5bddac1f2347d7b1f4308478acf731e0145e.json b/.sqlx/query-bcf3969b4f9bc4ca27bdca6bff0c5bddac1f2347d7b1f4308478acf731e0145e.json index 4301f0bb..503bafbc 100644 --- a/.sqlx/query-bcf3969b4f9bc4ca27bdca6bff0c5bddac1f2347d7b1f4308478acf731e0145e.json +++ b/.sqlx/query-bcf3969b4f9bc4ca27bdca6bff0c5bddac1f2347d7b1f4308478acf731e0145e.json @@ -6,7 +6,13 @@ { "ordinal": 0, "name": "featured", - "type_info": "Bool" + "type_info": "Bool", + "origin": { + "Table": { + "table": "mods", + "name": "featured" + } + } } ], "parameters": { diff --git a/.sqlx/query-c376c807583ad0bec9f6abe17ba00ce8d2cf76047bb0d1bb97b6e20c8d527224.json b/.sqlx/query-c376c807583ad0bec9f6abe17ba00ce8d2cf76047bb0d1bb97b6e20c8d527224.json index fce49e27..2788d354 100644 --- a/.sqlx/query-c376c807583ad0bec9f6abe17ba00ce8d2cf76047bb0d1bb97b6e20c8d527224.json +++ b/.sqlx/query-c376c807583ad0bec9f6abe17ba00ce8d2cf76047bb0d1bb97b6e20c8d527224.json @@ -6,7 +6,8 @@ { "ordinal": 0, "name": "count", - "type_info": "Int8" + "type_info": "Int8", + "origin": "Expression" } ], "parameters": { diff --git a/.sqlx/query-c4a5479111161c08985997365f50ecfb1fb6315509f5002a3bfc6fd66c2f83f7.json b/.sqlx/query-c4a5479111161c08985997365f50ecfb1fb6315509f5002a3bfc6fd66c2f83f7.json index d60636b2..50eca5a9 100644 --- a/.sqlx/query-c4a5479111161c08985997365f50ecfb1fb6315509f5002a3bfc6fd66c2f83f7.json +++ b/.sqlx/query-c4a5479111161c08985997365f50ecfb1fb6315509f5002a3bfc6fd66c2f83f7.json @@ -6,72 +6,156 @@ { "ordinal": 0, "name": "id", - "type_info": "Int4" + "type_info": "Int4", + "origin": { + "Table": { + "table": "mod_versions", + "name": "id" + } + } }, { "ordinal": 1, "name": "name", - "type_info": "Text" + "type_info": "Text", + "origin": { + "Table": { + "table": "mod_versions", + "name": "name" + } + } }, { "ordinal": 2, "name": "version", - "type_info": "Text" + "type_info": "Text", + "origin": { + "Table": { + "table": "mod_versions", + "name": "version" + } + } }, { "ordinal": 3, "name": "download_link", - "type_info": "Text" + "type_info": "Text", + "origin": { + "Table": { + "table": "mod_versions", + "name": "download_link" + } + } }, { "ordinal": 4, "name": "download_count", - "type_info": "Int4" + "type_info": "Int4", + "origin": { + "Table": { + "table": "mod_versions", + "name": "download_count" + } + } }, { "ordinal": 5, "name": "hash", - "type_info": "Text" + "type_info": "Text", + "origin": { + "Table": { + "table": "mod_versions", + "name": "hash" + } + } }, { "ordinal": 6, "name": "early_load", - "type_info": "Bool" + "type_info": "Bool", + "origin": { + "Table": { + "table": "mod_versions", + "name": "early_load" + } + } }, { "ordinal": 7, "name": "requires_patching", - "type_info": "Bool" + "type_info": "Bool", + "origin": { + "Table": { + "table": "mod_versions", + "name": "requires_patching" + } + } }, { "ordinal": 8, "name": "api", - "type_info": "Bool" + "type_info": "Bool", + "origin": { + "Table": { + "table": "mod_versions", + "name": "api" + } + } }, { "ordinal": 9, "name": "status_id", - "type_info": "Int4" + "type_info": "Int4", + "origin": { + "Table": { + "table": "mod_versions", + "name": "status_id" + } + } }, { "ordinal": 10, "name": "description", - "type_info": "Text" + "type_info": "Text", + "origin": { + "Table": { + "table": "mod_versions", + "name": "description" + } + } }, { "ordinal": 11, "name": "mod_id", - "type_info": "Text" + "type_info": "Text", + "origin": { + "Table": { + "table": "mod_versions", + "name": "mod_id" + } + } }, { "ordinal": 12, "name": "created_at", - "type_info": "Timestamptz" + "type_info": "Timestamptz", + "origin": { + "Table": { + "table": "mod_versions", + "name": "created_at" + } + } }, { "ordinal": 13, "name": "updated_at", - "type_info": "Timestamptz" + "type_info": "Timestamptz", + "origin": { + "Table": { + "table": "mod_versions", + "name": "updated_at" + } + } } ], "parameters": { diff --git a/.sqlx/query-c8e6b3a10dc50c1b7b24eb55c86b7a945863ec09c57e4165f9cd66888ab5405f.json b/.sqlx/query-c8e6b3a10dc50c1b7b24eb55c86b7a945863ec09c57e4165f9cd66888ab5405f.json index 911b9ed2..95ffcba4 100644 --- a/.sqlx/query-c8e6b3a10dc50c1b7b24eb55c86b7a945863ec09c57e4165f9cd66888ab5405f.json +++ b/.sqlx/query-c8e6b3a10dc50c1b7b24eb55c86b7a945863ec09c57e4165f9cd66888ab5405f.json @@ -6,22 +6,46 @@ { "ordinal": 0, "name": "id", - "type_info": "Int4" + "type_info": "Int4", + "origin": { + "Table": { + "table": "developers", + "name": "id" + } + } }, { "ordinal": 1, "name": "username", - "type_info": "Text" + "type_info": "Text", + "origin": { + "Table": { + "table": "developers", + "name": "username" + } + } }, { "ordinal": 2, "name": "display_name", - "type_info": "Text" + "type_info": "Text", + "origin": { + "Table": { + "table": "developers", + "name": "display_name" + } + } }, { "ordinal": 3, "name": "is_owner", - "type_info": "Bool" + "type_info": "Bool", + "origin": { + "Table": { + "table": "mods_developers", + "name": "is_owner" + } + } } ], "parameters": { diff --git a/.sqlx/query-cc4706434166bf9d5d6c3fde308fb3855ab4c697528a1b4ff8d074595ee82413.json b/.sqlx/query-cc4706434166bf9d5d6c3fde308fb3855ab4c697528a1b4ff8d074595ee82413.json index 1759cc27..12320e30 100644 --- a/.sqlx/query-cc4706434166bf9d5d6c3fde308fb3855ab4c697528a1b4ff8d074595ee82413.json +++ b/.sqlx/query-cc4706434166bf9d5d6c3fde308fb3855ab4c697528a1b4ff8d074595ee82413.json @@ -6,62 +6,134 @@ { "ordinal": 0, "name": "id", - "type_info": "Int4" + "type_info": "Int4", + "origin": { + "Table": { + "table": "mod_versions", + "name": "id" + } + } }, { "ordinal": 1, "name": "name", - "type_info": "Text" + "type_info": "Text", + "origin": { + "Table": { + "table": "mod_versions", + "name": "name" + } + } }, { "ordinal": 2, "name": "version", - "type_info": "Text" + "type_info": "Text", + "origin": { + "Table": { + "table": "mod_versions", + "name": "version" + } + } }, { "ordinal": 3, "name": "description", - "type_info": "Text" + "type_info": "Text", + "origin": { + "Table": { + "table": "mod_versions", + "name": "description" + } + } }, { "ordinal": 4, "name": "download_link", - "type_info": "Text" + "type_info": "Text", + "origin": { + "Table": { + "table": "mod_versions", + "name": "download_link" + } + } }, { "ordinal": 5, "name": "hash", - "type_info": "Text" + "type_info": "Text", + "origin": { + "Table": { + "table": "mod_versions", + "name": "hash" + } + } }, { "ordinal": 6, "name": "early_load", - "type_info": "Bool" + "type_info": "Bool", + "origin": { + "Table": { + "table": "mod_versions", + "name": "early_load" + } + } }, { "ordinal": 7, "name": "requires_patching", - "type_info": "Bool" + "type_info": "Bool", + "origin": { + "Table": { + "table": "mod_versions", + "name": "requires_patching" + } + } }, { "ordinal": 8, "name": "api", - "type_info": "Bool" + "type_info": "Bool", + "origin": { + "Table": { + "table": "mod_versions", + "name": "api" + } + } }, { "ordinal": 9, "name": "mod_id", - "type_info": "Text" + "type_info": "Text", + "origin": { + "Table": { + "table": "mod_versions", + "name": "mod_id" + } + } }, { "ordinal": 10, "name": "created_at", - "type_info": "Timestamptz" + "type_info": "Timestamptz", + "origin": { + "Table": { + "table": "mod_versions", + "name": "created_at" + } + } }, { "ordinal": 11, "name": "updated_at", - "type_info": "Timestamptz" + "type_info": "Timestamptz", + "origin": { + "Table": { + "table": "mod_versions", + "name": "updated_at" + } + } } ], "parameters": { diff --git a/.sqlx/query-d3f5cc5729d842ba8c9a259592cdfa901fbbc2cc4c12fb3268d22aa0f6b76a64.json b/.sqlx/query-d3f5cc5729d842ba8c9a259592cdfa901fbbc2cc4c12fb3268d22aa0f6b76a64.json index ec9b25c8..59935d11 100644 --- a/.sqlx/query-d3f5cc5729d842ba8c9a259592cdfa901fbbc2cc4c12fb3268d22aa0f6b76a64.json +++ b/.sqlx/query-d3f5cc5729d842ba8c9a259592cdfa901fbbc2cc4c12fb3268d22aa0f6b76a64.json @@ -6,7 +6,13 @@ { "ordinal": 0, "name": "name", - "type_info": "Text" + "type_info": "Text", + "origin": { + "Table": { + "table": "mod_tags", + "name": "name" + } + } } ], "parameters": { diff --git a/.sqlx/query-ddcfdb20c8c93a41da225a937478a56617000567bfd04ed8f9be0e501f438937.json b/.sqlx/query-ddcfdb20c8c93a41da225a937478a56617000567bfd04ed8f9be0e501f438937.json index 644bfe33..2d180287 100644 --- a/.sqlx/query-ddcfdb20c8c93a41da225a937478a56617000567bfd04ed8f9be0e501f438937.json +++ b/.sqlx/query-ddcfdb20c8c93a41da225a937478a56617000567bfd04ed8f9be0e501f438937.json @@ -6,32 +6,68 @@ { "ordinal": 0, "name": "id", - "type_info": "Int8" + "type_info": "Int8", + "origin": { + "Table": { + "table": "mod_version_submission_comments", + "name": "id" + } + } }, { "ordinal": 1, "name": "submission_id", - "type_info": "Int4" + "type_info": "Int4", + "origin": { + "Table": { + "table": "mod_version_submission_comments", + "name": "submission_id" + } + } }, { "ordinal": 2, "name": "comment", - "type_info": "Text" + "type_info": "Text", + "origin": { + "Table": { + "table": "mod_version_submission_comments", + "name": "comment" + } + } }, { "ordinal": 3, "name": "author_id", - "type_info": "Int4" + "type_info": "Int4", + "origin": { + "Table": { + "table": "mod_version_submission_comments", + "name": "author_id" + } + } }, { "ordinal": 4, "name": "created_at", - "type_info": "Timestamptz" + "type_info": "Timestamptz", + "origin": { + "Table": { + "table": "mod_version_submission_comments", + "name": "created_at" + } + } }, { "ordinal": 5, "name": "updated_at", - "type_info": "Timestamptz" + "type_info": "Timestamptz", + "origin": { + "Table": { + "table": "mod_version_submission_comments", + "name": "updated_at" + } + } } ], "parameters": { diff --git a/.sqlx/query-ddef8117c5f97a1dbef19f8248b9b90a0b101b5f2abf3e2c3acb2df18cf2d001.json b/.sqlx/query-ddef8117c5f97a1dbef19f8248b9b90a0b101b5f2abf3e2c3acb2df18cf2d001.json index e75188df..86c99733 100644 --- a/.sqlx/query-ddef8117c5f97a1dbef19f8248b9b90a0b101b5f2abf3e2c3acb2df18cf2d001.json +++ b/.sqlx/query-ddef8117c5f97a1dbef19f8248b9b90a0b101b5f2abf3e2c3acb2df18cf2d001.json @@ -19,6 +19,12 @@ ] } } + }, + "origin": { + "Table": { + "table": "incompatibilities", + "name": "compare" + } } }, { @@ -36,22 +42,46 @@ ] } } + }, + "origin": { + "Table": { + "table": "incompatibilities", + "name": "importance" + } } }, { "ordinal": 2, "name": "incompatibility_id", - "type_info": "Text" + "type_info": "Text", + "origin": { + "Table": { + "table": "incompatibilities", + "name": "incompatibility_id" + } + } }, { "ordinal": 3, "name": "mod_id", - "type_info": "Int4" + "type_info": "Int4", + "origin": { + "Table": { + "table": "incompatibilities", + "name": "mod_id" + } + } }, { "ordinal": 4, "name": "version", - "type_info": "Text" + "type_info": "Text", + "origin": { + "Table": { + "table": "incompatibilities", + "name": "version" + } + } } ], "parameters": { diff --git a/.sqlx/query-de581a1dcbd3b435b67aa1e39bd256798593badec03e4a7507b4537ee50f1e6e.json b/.sqlx/query-de581a1dcbd3b435b67aa1e39bd256798593badec03e4a7507b4537ee50f1e6e.json index b09cde70..980ef358 100644 --- a/.sqlx/query-de581a1dcbd3b435b67aa1e39bd256798593badec03e4a7507b4537ee50f1e6e.json +++ b/.sqlx/query-de581a1dcbd3b435b67aa1e39bd256798593badec03e4a7507b4537ee50f1e6e.json @@ -6,17 +6,35 @@ { "ordinal": 0, "name": "id", - "type_info": "Int4" + "type_info": "Int4", + "origin": { + "Table": { + "table": "deprecations", + "name": "id" + } + } }, { "ordinal": 1, "name": "mod_id", - "type_info": "Text" + "type_info": "Text", + "origin": { + "Table": { + "table": "deprecations", + "name": "mod_id" + } + } }, { "ordinal": 2, "name": "reason", - "type_info": "Text" + "type_info": "Text", + "origin": { + "Table": { + "table": "deprecations", + "name": "reason" + } + } } ], "parameters": { diff --git a/.sqlx/query-dfe205a13013db7ee5dbeb0ea3011a909895fdc0e98541bed9816362862968f7.json b/.sqlx/query-dfe205a13013db7ee5dbeb0ea3011a909895fdc0e98541bed9816362862968f7.json index a2e157fb..9d8f1f07 100644 --- a/.sqlx/query-dfe205a13013db7ee5dbeb0ea3011a909895fdc0e98541bed9816362862968f7.json +++ b/.sqlx/query-dfe205a13013db7ee5dbeb0ea3011a909895fdc0e98541bed9816362862968f7.json @@ -18,22 +18,46 @@ ] } } + }, + "origin": { + "Table": { + "table": "mod_version_submission_comment_audit", + "name": "action" + } } }, { "ordinal": 1, "name": "details", - "type_info": "Text" + "type_info": "Text", + "origin": { + "Table": { + "table": "mod_version_submission_comment_audit", + "name": "details" + } + } }, { "ordinal": 2, "name": "performed_by", - "type_info": "Int4" + "type_info": "Int4", + "origin": { + "Table": { + "table": "mod_version_submission_comment_audit", + "name": "performed_by" + } + } }, { "ordinal": 3, "name": "performed_at", - "type_info": "Timestamptz" + "type_info": "Timestamptz", + "origin": { + "Table": { + "table": "mod_version_submission_comment_audit", + "name": "performed_at" + } + } } ], "parameters": { diff --git a/.sqlx/query-e135a61fc8cd6fb39851cf232ed5ba26571d4abff8f13b07b65707985e78ef82.json b/.sqlx/query-e135a61fc8cd6fb39851cf232ed5ba26571d4abff8f13b07b65707985e78ef82.json index 38eff6dd..af1d417f 100644 --- a/.sqlx/query-e135a61fc8cd6fb39851cf232ed5ba26571d4abff8f13b07b65707985e78ef82.json +++ b/.sqlx/query-e135a61fc8cd6fb39851cf232ed5ba26571d4abff8f13b07b65707985e78ef82.json @@ -6,27 +6,57 @@ { "ordinal": 0, "name": "id", - "type_info": "Int4" + "type_info": "Int4", + "origin": { + "Table": { + "table": "developers", + "name": "id" + } + } }, { "ordinal": 1, "name": "username", - "type_info": "Text" + "type_info": "Text", + "origin": { + "Table": { + "table": "developers", + "name": "username" + } + } }, { "ordinal": 2, "name": "display_name", - "type_info": "Text" + "type_info": "Text", + "origin": { + "Table": { + "table": "developers", + "name": "display_name" + } + } }, { "ordinal": 3, "name": "is_owner", - "type_info": "Bool" + "type_info": "Bool", + "origin": { + "Table": { + "table": "mods_developers", + "name": "is_owner" + } + } }, { "ordinal": 4, "name": "mod_id", - "type_info": "Text" + "type_info": "Text", + "origin": { + "Table": { + "table": "mods_developers", + "name": "mod_id" + } + } } ], "parameters": { diff --git a/.sqlx/query-e3b9e16724458e4ac536d3df57ae813fbc3f8d8f22fcaaeefa24cc1f97146bbe.json b/.sqlx/query-e3b9e16724458e4ac536d3df57ae813fbc3f8d8f22fcaaeefa24cc1f97146bbe.json index 0f4d005b..d61b8851 100644 --- a/.sqlx/query-e3b9e16724458e4ac536d3df57ae813fbc3f8d8f22fcaaeefa24cc1f97146bbe.json +++ b/.sqlx/query-e3b9e16724458e4ac536d3df57ae813fbc3f8d8f22fcaaeefa24cc1f97146bbe.json @@ -6,47 +6,101 @@ { "ordinal": 0, "name": "uuid", - "type_info": "Uuid" + "type_info": "Uuid", + "origin": { + "Table": { + "table": "github_login_attempts", + "name": "uid" + } + } }, { "ordinal": 1, "name": "ip", - "type_info": "Inet" + "type_info": "Inet", + "origin": { + "Table": { + "table": "github_login_attempts", + "name": "ip" + } + } }, { "ordinal": 2, "name": "interval", - "type_info": "Int4" + "type_info": "Int4", + "origin": { + "Table": { + "table": "github_login_attempts", + "name": "interval" + } + } }, { "ordinal": 3, "name": "expires_in", - "type_info": "Int4" + "type_info": "Int4", + "origin": { + "Table": { + "table": "github_login_attempts", + "name": "expires_in" + } + } }, { "ordinal": 4, "name": "created_at", - "type_info": "Timestamptz" + "type_info": "Timestamptz", + "origin": { + "Table": { + "table": "github_login_attempts", + "name": "created_at" + } + } }, { "ordinal": 5, "name": "last_poll", - "type_info": "Timestamptz" + "type_info": "Timestamptz", + "origin": { + "Table": { + "table": "github_login_attempts", + "name": "last_poll" + } + } }, { "ordinal": 6, "name": "uri", - "type_info": "Text" + "type_info": "Text", + "origin": { + "Table": { + "table": "github_login_attempts", + "name": "challenge_uri" + } + } }, { "ordinal": 7, "name": "device_code", - "type_info": "Text" + "type_info": "Text", + "origin": { + "Table": { + "table": "github_login_attempts", + "name": "device_code" + } + } }, { "ordinal": 8, "name": "user_code", - "type_info": "Text" + "type_info": "Text", + "origin": { + "Table": { + "table": "github_login_attempts", + "name": "user_code" + } + } } ], "parameters": { diff --git a/.sqlx/query-e6428914db0f351cc0e276729ac6d9a3f8d0504dfdf1c18e9fc653468faa505a.json b/.sqlx/query-e6428914db0f351cc0e276729ac6d9a3f8d0504dfdf1c18e9fc653468faa505a.json index 2f457863..f2000a66 100644 --- a/.sqlx/query-e6428914db0f351cc0e276729ac6d9a3f8d0504dfdf1c18e9fc653468faa505a.json +++ b/.sqlx/query-e6428914db0f351cc0e276729ac6d9a3f8d0504dfdf1c18e9fc653468faa505a.json @@ -6,22 +6,46 @@ { "ordinal": 0, "name": "id", - "type_info": "Int4" + "type_info": "Int4", + "origin": { + "Table": { + "table": "mod_tags", + "name": "id" + } + } }, { "ordinal": 1, "name": "name", - "type_info": "Text" + "type_info": "Text", + "origin": { + "Table": { + "table": "mod_tags", + "name": "name" + } + } }, { "ordinal": 2, "name": "display_name", - "type_info": "Text" + "type_info": "Text", + "origin": { + "Table": { + "table": "mod_tags", + "name": "display_name" + } + } }, { "ordinal": 3, "name": "is_readonly", - "type_info": "Bool" + "type_info": "Bool", + "origin": { + "Table": { + "table": "mod_tags", + "name": "is_readonly" + } + } } ], "parameters": { diff --git a/.sqlx/query-e76119227a3fcb00348279467161b081128d2a2cf67057da0e4b726463ceb40a.json b/.sqlx/query-e76119227a3fcb00348279467161b081128d2a2cf67057da0e4b726463ceb40a.json index 2e186ba6..094f1559 100644 --- a/.sqlx/query-e76119227a3fcb00348279467161b081128d2a2cf67057da0e4b726463ceb40a.json +++ b/.sqlx/query-e76119227a3fcb00348279467161b081128d2a2cf67057da0e4b726463ceb40a.json @@ -6,32 +6,68 @@ { "ordinal": 0, "name": "id", - "type_info": "Int4" + "type_info": "Int4", + "origin": { + "Table": { + "table": "developers", + "name": "id" + } + } }, { "ordinal": 1, "name": "username", - "type_info": "Text" + "type_info": "Text", + "origin": { + "Table": { + "table": "developers", + "name": "username" + } + } }, { "ordinal": 2, "name": "display_name", - "type_info": "Text" + "type_info": "Text", + "origin": { + "Table": { + "table": "developers", + "name": "display_name" + } + } }, { "ordinal": 3, "name": "verified", - "type_info": "Bool" + "type_info": "Bool", + "origin": { + "Table": { + "table": "developers", + "name": "verified" + } + } }, { "ordinal": 4, "name": "admin", - "type_info": "Bool" + "type_info": "Bool", + "origin": { + "Table": { + "table": "developers", + "name": "admin" + } + } }, { "ordinal": 5, "name": "github_id", - "type_info": "Int8" + "type_info": "Int8", + "origin": { + "Table": { + "table": "developers", + "name": "github_user_id" + } + } } ], "parameters": { diff --git a/.sqlx/query-ebf42091af98e77f7e036aa82cf3fc091bfaab8ab9286c04c1bd4f83c91a68cb.json b/.sqlx/query-ebf42091af98e77f7e036aa82cf3fc091bfaab8ab9286c04c1bd4f83c91a68cb.json index d8d8f513..e85b16c0 100644 --- a/.sqlx/query-ebf42091af98e77f7e036aa82cf3fc091bfaab8ab9286c04c1bd4f83c91a68cb.json +++ b/.sqlx/query-ebf42091af98e77f7e036aa82cf3fc091bfaab8ab9286c04c1bd4f83c91a68cb.json @@ -6,32 +6,68 @@ { "ordinal": 0, "name": "id", - "type_info": "Int4" + "type_info": "Int4", + "origin": { + "Table": { + "table": "developers", + "name": "id" + } + } }, { "ordinal": 1, "name": "username", - "type_info": "Text" + "type_info": "Text", + "origin": { + "Table": { + "table": "developers", + "name": "username" + } + } }, { "ordinal": 2, "name": "display_name", - "type_info": "Text" + "type_info": "Text", + "origin": { + "Table": { + "table": "developers", + "name": "display_name" + } + } }, { "ordinal": 3, "name": "verified", - "type_info": "Bool" + "type_info": "Bool", + "origin": { + "Table": { + "table": "developers", + "name": "verified" + } + } }, { "ordinal": 4, "name": "admin", - "type_info": "Bool" + "type_info": "Bool", + "origin": { + "Table": { + "table": "developers", + "name": "admin" + } + } }, { "ordinal": 5, "name": "github_id", - "type_info": "Int8" + "type_info": "Int8", + "origin": { + "Table": { + "table": "developers", + "name": "github_user_id" + } + } } ], "parameters": { diff --git a/.sqlx/query-ef99dae03ba65d4f0cb2c81e1460f4350aa059506c65c84df6445310feae9669.json b/.sqlx/query-ef99dae03ba65d4f0cb2c81e1460f4350aa059506c65c84df6445310feae9669.json index 7f0a43a2..52cc1d0a 100644 --- a/.sqlx/query-ef99dae03ba65d4f0cb2c81e1460f4350aa059506c65c84df6445310feae9669.json +++ b/.sqlx/query-ef99dae03ba65d4f0cb2c81e1460f4350aa059506c65c84df6445310feae9669.json @@ -6,32 +6,68 @@ { "ordinal": 0, "name": "id", - "type_info": "Int4" + "type_info": "Int4", + "origin": { + "Table": { + "table": "developers", + "name": "id" + } + } }, { "ordinal": 1, "name": "username", - "type_info": "Text" + "type_info": "Text", + "origin": { + "Table": { + "table": "developers", + "name": "username" + } + } }, { "ordinal": 2, "name": "display_name", - "type_info": "Text" + "type_info": "Text", + "origin": { + "Table": { + "table": "developers", + "name": "display_name" + } + } }, { "ordinal": 3, "name": "verified", - "type_info": "Bool" + "type_info": "Bool", + "origin": { + "Table": { + "table": "developers", + "name": "verified" + } + } }, { "ordinal": 4, "name": "admin", - "type_info": "Bool" + "type_info": "Bool", + "origin": { + "Table": { + "table": "developers", + "name": "admin" + } + } }, { "ordinal": 5, "name": "github_id", - "type_info": "Int8" + "type_info": "Int8", + "origin": { + "Table": { + "table": "developers", + "name": "github_user_id" + } + } } ], "parameters": { diff --git a/.sqlx/query-f1945f11dce4a240cccbf4e8c2f282dfd1dc2cb69bb9803e0a7a4d648239389f.json b/.sqlx/query-f1945f11dce4a240cccbf4e8c2f282dfd1dc2cb69bb9803e0a7a4d648239389f.json index 30b2af76..8793eeb1 100644 --- a/.sqlx/query-f1945f11dce4a240cccbf4e8c2f282dfd1dc2cb69bb9803e0a7a4d648239389f.json +++ b/.sqlx/query-f1945f11dce4a240cccbf4e8c2f282dfd1dc2cb69bb9803e0a7a4d648239389f.json @@ -6,12 +6,24 @@ { "ordinal": 0, "name": "checked_at", - "type_info": "Timestamptz" + "type_info": "Timestamptz", + "origin": { + "Table": { + "table": "github_loader_release_stats", + "name": "checked_at" + } + } }, { "ordinal": 1, "name": "total_download_count", - "type_info": "Int8" + "type_info": "Int8", + "origin": { + "Table": { + "table": "github_loader_release_stats", + "name": "total_download_count" + } + } } ], "parameters": { diff --git a/.sqlx/query-f2c57d8bc7752c080fc45a6dd5b1fcc9f5ebe72d4948e0403ef5d488a9c8a370.json b/.sqlx/query-f2c57d8bc7752c080fc45a6dd5b1fcc9f5ebe72d4948e0403ef5d488a9c8a370.json index b232b577..8abdd0fc 100644 --- a/.sqlx/query-f2c57d8bc7752c080fc45a6dd5b1fcc9f5ebe72d4948e0403ef5d488a9c8a370.json +++ b/.sqlx/query-f2c57d8bc7752c080fc45a6dd5b1fcc9f5ebe72d4948e0403ef5d488a9c8a370.json @@ -6,7 +6,13 @@ { "ordinal": 0, "name": "id", - "type_info": "Text" + "type_info": "Text", + "origin": { + "Table": { + "table": "mods", + "name": "id" + } + } } ], "parameters": { diff --git a/.sqlx/query-f683c5573877e25f4608a9d8cb97588c3b0cd770f82b53fa2248cdbcbe2c8f49.json b/.sqlx/query-f683c5573877e25f4608a9d8cb97588c3b0cd770f82b53fa2248cdbcbe2c8f49.json index fc35a3c1..0858f05d 100644 --- a/.sqlx/query-f683c5573877e25f4608a9d8cb97588c3b0cd770f82b53fa2248cdbcbe2c8f49.json +++ b/.sqlx/query-f683c5573877e25f4608a9d8cb97588c3b0cd770f82b53fa2248cdbcbe2c8f49.json @@ -6,22 +6,46 @@ { "ordinal": 0, "name": "id", - "type_info": "Int4" + "type_info": "Int4", + "origin": { + "Table": { + "table": "mod_tags", + "name": "id" + } + } }, { "ordinal": 1, "name": "name", - "type_info": "Text" + "type_info": "Text", + "origin": { + "Table": { + "table": "mod_tags", + "name": "name" + } + } }, { "ordinal": 2, "name": "display_name", - "type_info": "Text" + "type_info": "Text", + "origin": { + "Table": { + "table": "mod_tags", + "name": "display_name" + } + } }, { "ordinal": 3, "name": "is_readonly", - "type_info": "Bool" + "type_info": "Bool", + "origin": { + "Table": { + "table": "mod_tags", + "name": "is_readonly" + } + } } ], "parameters": { diff --git a/.sqlx/query-f879d614ff765e840a2cc426e262cd380be6976024923abe0442430d20c8b0bd.json b/.sqlx/query-f879d614ff765e840a2cc426e262cd380be6976024923abe0442430d20c8b0bd.json new file mode 100644 index 00000000..9e9f8b1a --- /dev/null +++ b/.sqlx/query-f879d614ff765e840a2cc426e262cd380be6976024923abe0442430d20c8b0bd.json @@ -0,0 +1,93 @@ +{ + "db_name": "PostgreSQL", + "query": "SELECT final_q.id, final_q.version, final_q.download_link, final_q.mv_id FROM (\n SELECT DISTINCT ON (q.mv_id) q.id, q.version, q.download_link, q.mv_id, q.gd FROM (\n SELECT DISTINCT ON (m.id, mgv.gd, mv.geode_major) m.id, mv.name, mv.version, mv.download_link, mv.managed_download_link, mv.id as mv_id, mgv.gd\n FROM MODS m\n INNER JOIN mod_versions mv ON m.id = mv.mod_id\n INNER JOIN mod_version_statuses mvs ON mvs.mod_version_id = mv.id\n INNER JOIN mod_gd_versions mgv ON mgv.mod_id = mv.id\n WHERE mvs.status = 'accepted' AND mgv.gd = ANY($1::gd_version[])\n ORDER BY m.id, mgv.gd DESC, mv.geode_major DESC, mv.id DESC\n ) q\n WHERE q.managed_download_link IS NULL\n ORDER BY q.mv_id, q.gd DESC\n ) final_q", + "describe": { + "columns": [ + { + "ordinal": 0, + "name": "id", + "type_info": "Text", + "origin": { + "Table": { + "table": "mods", + "name": "id" + } + } + }, + { + "ordinal": 1, + "name": "version", + "type_info": "Text", + "origin": { + "Table": { + "table": "mod_versions", + "name": "version" + } + } + }, + { + "ordinal": 2, + "name": "download_link", + "type_info": "Text", + "origin": { + "Table": { + "table": "mod_versions", + "name": "download_link" + } + } + }, + { + "ordinal": 3, + "name": "mv_id", + "type_info": "Int4", + "origin": { + "Table": { + "table": "mod_versions", + "name": "id" + } + } + } + ], + "parameters": { + "Left": [ + { + "Custom": { + "name": "gd_version[]", + "kind": { + "Array": { + "Custom": { + "name": "gd_version", + "kind": { + "Enum": [ + "*", + "2.113", + "2.200", + "2.204", + "2.205", + "2.206", + "2.207", + "2.2071", + "2.2072", + "2.2073", + "2.2074", + "2.208", + "2.2081", + "2.2082" + ] + } + } + } + } + } + } + ] + }, + "nullable": [ + false, + false, + false, + false + ] + }, + "hash": "f879d614ff765e840a2cc426e262cd380be6976024923abe0442430d20c8b0bd" +} diff --git a/.sqlx/query-f98fe5c88a7a234cc0b68fb39c156a741fbad1d2e4682e1e748037bb08962912.json b/.sqlx/query-f98fe5c88a7a234cc0b68fb39c156a741fbad1d2e4682e1e748037bb08962912.json index a012c0ce..df6a0a84 100644 --- a/.sqlx/query-f98fe5c88a7a234cc0b68fb39c156a741fbad1d2e4682e1e748037bb08962912.json +++ b/.sqlx/query-f98fe5c88a7a234cc0b68fb39c156a741fbad1d2e4682e1e748037bb08962912.json @@ -6,42 +6,90 @@ { "ordinal": 0, "name": "id", - "type_info": "Text" + "type_info": "Text", + "origin": { + "Table": { + "table": "mods", + "name": "id" + } + } }, { "ordinal": 1, "name": "repository", - "type_info": "Text" + "type_info": "Text", + "origin": { + "Table": { + "table": "mods", + "name": "repository" + } + } }, { "ordinal": 2, "name": "about", - "type_info": "Text" + "type_info": "Text", + "origin": { + "Table": { + "table": "mods", + "name": "about" + } + } }, { "ordinal": 3, "name": "changelog", - "type_info": "Text" + "type_info": "Text", + "origin": { + "Table": { + "table": "mods", + "name": "changelog" + } + } }, { "ordinal": 4, "name": "featured", - "type_info": "Bool" + "type_info": "Bool", + "origin": { + "Table": { + "table": "mods", + "name": "featured" + } + } }, { "ordinal": 5, "name": "download_count", - "type_info": "Int4" + "type_info": "Int4", + "origin": { + "Table": { + "table": "mods", + "name": "download_count" + } + } }, { "ordinal": 6, "name": "created_at", - "type_info": "Timestamptz" + "type_info": "Timestamptz", + "origin": { + "Table": { + "table": "mods", + "name": "created_at" + } + } }, { "ordinal": 7, "name": "updated_at", - "type_info": "Timestamptz" + "type_info": "Timestamptz", + "origin": { + "Table": { + "table": "mods", + "name": "updated_at" + } + } } ], "parameters": { diff --git a/.sqlx/query-fca16bbe2790df77b2a7782389c7451a8fc46a5fd1114888b8a5d2ab42db1135.json b/.sqlx/query-fca16bbe2790df77b2a7782389c7451a8fc46a5fd1114888b8a5d2ab42db1135.json index 0e87f90d..54a27ef0 100644 --- a/.sqlx/query-fca16bbe2790df77b2a7782389c7451a8fc46a5fd1114888b8a5d2ab42db1135.json +++ b/.sqlx/query-fca16bbe2790df77b2a7782389c7451a8fc46a5fd1114888b8a5d2ab42db1135.json @@ -6,7 +6,13 @@ { "ordinal": 0, "name": "id", - "type_info": "Int4" + "type_info": "Int4", + "origin": { + "Table": { + "table": "mod_version_statuses", + "name": "id" + } + } } ], "parameters": { diff --git a/.sqlx/query-fced42c56c5c1a4ec5b47254c6ec157560ec9d314947ea11c35f10a736a31684.json b/.sqlx/query-fced42c56c5c1a4ec5b47254c6ec157560ec9d314947ea11c35f10a736a31684.json index 25b4bd5e..57b01a56 100644 --- a/.sqlx/query-fced42c56c5c1a4ec5b47254c6ec157560ec9d314947ea11c35f10a736a31684.json +++ b/.sqlx/query-fced42c56c5c1a4ec5b47254c6ec157560ec9d314947ea11c35f10a736a31684.json @@ -6,32 +6,68 @@ { "ordinal": 0, "name": "id", - "type_info": "Int4" + "type_info": "Int4", + "origin": { + "Table": { + "table": "developers", + "name": "id" + } + } }, { "ordinal": 1, "name": "username", - "type_info": "Text" + "type_info": "Text", + "origin": { + "Table": { + "table": "developers", + "name": "username" + } + } }, { "ordinal": 2, "name": "display_name", - "type_info": "Text" + "type_info": "Text", + "origin": { + "Table": { + "table": "developers", + "name": "display_name" + } + } }, { "ordinal": 3, "name": "admin", - "type_info": "Bool" + "type_info": "Bool", + "origin": { + "Table": { + "table": "developers", + "name": "admin" + } + } }, { "ordinal": 4, "name": "verified", - "type_info": "Bool" + "type_info": "Bool", + "origin": { + "Table": { + "table": "developers", + "name": "verified" + } + } }, { "ordinal": 5, "name": "github_id", - "type_info": "Int8" + "type_info": "Int8", + "origin": { + "Table": { + "table": "developers", + "name": "github_user_id" + } + } } ], "parameters": { diff --git a/.sqlx/query-fdcb055531d7d980dd5447b521a98622b4e452c66855a4be5a749c1576b83c25.json b/.sqlx/query-fdcb055531d7d980dd5447b521a98622b4e452c66855a4be5a749c1576b83c25.json index 67426d74..4fd792d1 100644 --- a/.sqlx/query-fdcb055531d7d980dd5447b521a98622b4e452c66855a4be5a749c1576b83c25.json +++ b/.sqlx/query-fdcb055531d7d980dd5447b521a98622b4e452c66855a4be5a749c1576b83c25.json @@ -6,7 +6,13 @@ { "ordinal": 0, "name": "id", - "type_info": "Int4" + "type_info": "Int4", + "origin": { + "Table": { + "table": "deprecations", + "name": "id" + } + } } ], "parameters": { diff --git a/Cargo.lock b/Cargo.lock index 9005f8f1..e3f6a8ac 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -77,7 +77,7 @@ dependencies = [ "flate2", "foldhash", "futures-core", - "h2", + "h2 0.3.27", "http 0.2.12", "httparse", "httpdate", @@ -487,6 +487,22 @@ version = "1.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1505bd5d3d116872e7271a6d4e16d81d0c8570876c8de68093a09ac269d8aac0" +[[package]] +name = "attohttpc" +version = "0.30.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "16e2cdb6d5ed835199484bb92bb8b3edd526effe995c61732580439c1a67e2e9" +dependencies = [ + "base64", + "http 1.4.2", + "log", + "rustls", + "serde", + "serde_json", + "url", + "webpki-roots", +] + [[package]] name = "autocfg" version = "1.5.1" @@ -536,6 +552,23 @@ dependencies = [ "arrayvec", ] +[[package]] +name = "aws-creds" +version = "0.39.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ca3b85155d265df828f84e53886ed9e427aed979dd8a39f5b8b2162c77e142d7" +dependencies = [ + "attohttpc", + "home", + "log", + "quick-xml", + "rust-ini", + "serde", + "thiserror", + "time", + "url", +] + [[package]] name = "aws-lc-rs" version = "1.17.1" @@ -559,6 +592,15 @@ dependencies = [ "pkg-config", ] +[[package]] +name = "aws-region" +version = "0.28.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "838b36c8dc927b6db1b6c6b8f5d05865f2213550b9e83bf92fa99ed6525472c0" +dependencies = [ + "thiserror", +] + [[package]] name = "base64" version = "0.22.1" @@ -735,7 +777,7 @@ dependencies = [ "num-traits", "serde", "wasm-bindgen", - "windows-link", + "windows-link 0.2.1", ] [[package]] @@ -857,6 +899,26 @@ version = "0.10.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a6ef517f0926dd24a1582492c791b6a4818a4d94e789a334894aa15b0d12f55c" +[[package]] +name = "const-random" +version = "0.1.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "87e00182fe74b066627d63b85fd550ac2998d4b0bd86bfed477a0ae4c7c71359" +dependencies = [ + "const-random-macro", +] + +[[package]] +name = "const-random-macro" +version = "0.1.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f9d839f2a20b0aee515dc581a6172f2321f96cab76c1a38a4c584a194955390e" +dependencies = [ + "getrandom 0.2.17", + "once_cell", + "tiny-keccak", +] + [[package]] name = "constant_time_eq" version = "0.4.2" @@ -1080,6 +1142,9 @@ name = "deranged" version = "0.5.8" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7cd812cc2bc1d69d4764bd80df88b4317eaef9e773c75226407d9bc0876b211c" +dependencies = [ + "serde_core", +] [[package]] name = "derive_arbitrary" @@ -1123,6 +1188,7 @@ checksum = "9ed9a281f7bc9b7576e61468ba615a66a5c8cfdff42420a70aa82701a3b1e292" dependencies = [ "block-buffer 0.10.4", "crypto-common 0.1.7", + "subtle", ] [[package]] @@ -1149,6 +1215,15 @@ dependencies = [ "syn", ] +[[package]] +name = "dlv-list" +version = "0.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "442039f5147480ba31067cb00ada1adae6892028e40e45fc5de7b7df6dcc1b5f" +dependencies = [ + "const-random", +] + [[package]] name = "dotenvy" version = "0.15.7" @@ -1483,7 +1558,8 @@ dependencies = [ "mimalloc", "moka", "regex", - "reqwest", + "reqwest 0.13.4", + "rust-s3", "semver", "serde", "serde_json", @@ -1570,6 +1646,25 @@ dependencies = [ "tracing", ] +[[package]] +name = "h2" +version = "0.4.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6cb093c84e8bd9b188d4c4a8cb6579fc016968d14c99882163cd3ff402a4f155" +dependencies = [ + "atomic-waker", + "bytes", + "fnv", + "futures-core", + "futures-sink", + "http 1.4.2", + "indexmap", + "slab", + "tokio", + "tokio-util", + "tracing", +] + [[package]] name = "half" version = "2.7.1" @@ -1581,6 +1676,12 @@ dependencies = [ "zerocopy", ] +[[package]] +name = "hashbrown" +version = "0.14.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e5274423e17b7c9fc20b6e7e208532f9b19825d82dfd615708b70edd83df41f1" + [[package]] name = "hashbrown" version = "0.16.1" @@ -1625,7 +1726,16 @@ version = "0.13.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4aaa26c720c68b866f2c96ef5c1264b3e6f473fe5d4ce61cd44bbe913e553018" dependencies = [ - "hmac", + "hmac 0.13.0", +] + +[[package]] +name = "hmac" +version = "0.12.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6c49c37c09c17a53d937dfbb742eb3a961d65a994e6bcdcf37e7399d0cc8ab5e" +dependencies = [ + "digest 0.10.7", ] [[package]] @@ -1637,6 +1747,15 @@ dependencies = [ "digest 0.11.3", ] +[[package]] +name = "home" +version = "0.5.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cc627f471c528ff0c4a49e1d5e60450c8f6461dd6d10ba9dcd3a61d3dff7728d" +dependencies = [ + "windows-sys 0.61.2", +] + [[package]] name = "html5ever" version = "0.39.0" @@ -1728,6 +1847,7 @@ dependencies = [ "bytes", "futures-channel", "futures-core", + "h2 0.4.15", "http 1.4.2", "http-body", "httparse", @@ -1751,6 +1871,7 @@ dependencies = [ "tokio", "tokio-rustls", "tower-service", + "webpki-roots", ] [[package]] @@ -1788,7 +1909,7 @@ dependencies = [ "js-sys", "log", "wasm-bindgen", - "windows-core", + "windows-core 0.62.2", ] [[package]] @@ -2034,7 +2155,7 @@ dependencies = [ "simd_cesu8", "thiserror", "walkdir", - "windows-link", + "windows-link 0.2.1", ] [[package]] @@ -2249,6 +2370,17 @@ dependencies = [ "regex-automata", ] +[[package]] +name = "maybe-async" +version = "0.2.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "746873a384ad60adc5db74471dfaba74bd278afbdcfd81db93fafcdfc8b5ca0c" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + [[package]] name = "maybe-rayon" version = "0.1.1" @@ -2269,6 +2401,12 @@ dependencies = [ "digest 0.11.3", ] +[[package]] +name = "md5" +version = "0.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7ebb8d8732c6a6df3d8f032a82911cfc747e00efb95cc46e8d0acd5b5b88570c" + [[package]] name = "memchr" version = "2.8.3" @@ -2388,6 +2526,15 @@ version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0676bb32a98c1a483ce53e500a81ad9c3d5b3f7c920c28c24e9cb0980d0b5bc8" +[[package]] +name = "ntapi" +version = "0.4.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c3b335231dfd352ffb0f8017f3b6027a4917f7df785ea2143d8af2adc66980ae" +dependencies = [ + "winapi", +] + [[package]] name = "nu-ansi-term" version = "0.50.3" @@ -2463,6 +2610,25 @@ dependencies = [ "autocfg", ] +[[package]] +name = "objc2-core-foundation" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2a180dd8642fa45cdb7dd721cd4c11b1cadd4929ce112ebd8b9f5803cc79d536" +dependencies = [ + "bitflags", +] + +[[package]] +name = "objc2-io-kit" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "33fafba39597d6dc1fb709123dfa8289d39406734be322956a69f0931c73bb15" +dependencies = [ + "libc", + "objc2-core-foundation", +] + [[package]] name = "once_cell" version = "1.21.4" @@ -2481,6 +2647,16 @@ version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7c87def4c32ab89d880effc9e097653c8da5d6ef28e6b539d313baaacfbafcbe" +[[package]] +name = "ordered-multimap" +version = "0.7.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "49203cdcae0030493bad186b28da2fa25645fa276a51b6fec8010d281e02ef79" +dependencies = [ + "dlv-list", + "hashbrown 0.14.5", +] + [[package]] name = "parking" version = "2.2.1" @@ -2507,7 +2683,7 @@ dependencies = [ "libc", "redox_syscall", "smallvec", - "windows-link", + "windows-link 0.2.1", ] [[package]] @@ -2529,7 +2705,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "112d82ceb8c5bf524d9af484d4e4970c9fd5a0cc15ba14ad93dccd28873b0629" dependencies = [ "digest 0.11.3", - "hmac", + "hmac 0.13.0", ] [[package]] @@ -2758,6 +2934,16 @@ version = "2.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a993555f31e5a609f617c12db6250dedcac1b0a85076912c436e6fc9b2c8e6a3" +[[package]] +name = "quick-xml" +version = "0.38.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b66c2058c55a409d601666cffe35f04333cf1013010882cec174a7467cd4e21c" +dependencies = [ + "memchr", + "serde", +] + [[package]] name = "quinn" version = "0.11.11" @@ -3020,6 +3206,47 @@ version = "0.8.11" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d6f6ff9a378485b298a5286656da665ba74413d36db0979633275d2e708145d4" +[[package]] +name = "reqwest" +version = "0.12.28" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "eddd3ca559203180a307f12d114c268abf583f59b03cb906fd0b3ff8646c1147" +dependencies = [ + "base64", + "bytes", + "futures-core", + "futures-util", + "http 1.4.2", + "http-body", + "http-body-util", + "hyper", + "hyper-rustls", + "hyper-util", + "js-sys", + "log", + "percent-encoding", + "pin-project-lite", + "quinn", + "rustls", + "rustls-pki-types", + "serde", + "serde_json", + "serde_urlencoded", + "sync_wrapper", + "tokio", + "tokio-rustls", + "tokio-util", + "tower", + "tower-http", + "tower-service", + "url", + "wasm-bindgen", + "wasm-bindgen-futures", + "wasm-streams", + "web-sys", + "webpki-roots", +] + [[package]] name = "reqwest" version = "0.13.4" @@ -3029,6 +3256,7 @@ dependencies = [ "base64", "bytes", "futures-core", + "h2 0.4.15", "http 1.4.2", "http-body", "http-body-util", @@ -3113,6 +3341,49 @@ dependencies = [ "walkdir", ] +[[package]] +name = "rust-ini" +version = "0.21.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "796e8d2b6696392a43bea58116b667fb4c29727dc5abd27d6acf338bb4f688c7" +dependencies = [ + "cfg-if", + "ordered-multimap", +] + +[[package]] +name = "rust-s3" +version = "0.37.2" +source = "git+https://github.com/w4nderlust/rust-s3?rev=2936eb7#2936eb7e856655a4a49a65377e3cdb59e29fea71" +dependencies = [ + "async-trait", + "aws-creds", + "aws-region", + "base64", + "bytes", + "cfg-if", + "futures-util", + "hex", + "hmac 0.12.1", + "http 1.4.2", + "log", + "maybe-async", + "md5", + "percent-encoding", + "quick-xml", + "reqwest 0.12.28", + "serde", + "serde_derive", + "serde_json", + "sha2 0.10.9", + "sysinfo", + "thiserror", + "time", + "tokio", + "tokio-stream", + "url", +] + [[package]] name = "rustc-hash" version = "2.1.3" @@ -3148,7 +3419,9 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6b92b125634d9b795e7beca796cc790df15a7fb38323bf3196fda83292d06b1f" dependencies = [ "aws-lc-rs", + "log", "once_cell", + "ring", "rustls-pki-types", "rustls-webpki", "subtle", @@ -3633,7 +3906,7 @@ dependencies = [ "futures-util", "hex", "hkdf", - "hmac", + "hmac 0.13.0", "ipnetwork", "itoa", "log", @@ -3762,6 +4035,20 @@ dependencies = [ "syn", ] +[[package]] +name = "sysinfo" +version = "0.37.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "16607d5caffd1c07ce073528f9ed972d88db15dd44023fa57142963be3feb11f" +dependencies = [ + "libc", + "memchr", + "ntapi", + "objc2-core-foundation", + "objc2-io-kit", + "windows", +] + [[package]] name = "tagptr" version = "0.2.0" @@ -3864,6 +4151,15 @@ dependencies = [ "time-core", ] +[[package]] +name = "tiny-keccak" +version = "2.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2c9d3793400a45f954c52e73d068316d76b6f4e36977e3fcebb13a2721e80237" +dependencies = [ + "crunchy", +] + [[package]] name = "tinystr" version = "0.8.3" @@ -4397,6 +4693,19 @@ dependencies = [ "unicode-ident", ] +[[package]] +name = "wasm-streams" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "15053d8d85c7eccdbefef60f06769760a563c7f0a9d6902a13d35c7800b0ad65" +dependencies = [ + "futures-util", + "js-sys", + "wasm-bindgen", + "wasm-bindgen-futures", + "web-sys", +] + [[package]] name = "web-sys" version = "0.3.103" @@ -4438,6 +4747,15 @@ dependencies = [ "rustls-pki-types", ] +[[package]] +name = "webpki-roots" +version = "1.0.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7dcd9d09a39985f5344844e66b0c530a33843579125f23e21e9f0f220850f22a" +dependencies = [ + "rustls-pki-types", +] + [[package]] name = "weezl" version = "0.1.12" @@ -4450,6 +4768,22 @@ version = "2.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "998767ef88740d1f5b0682a9c53c24431453923962269c2db68ee43788c5a40d" +[[package]] +name = "winapi" +version = "0.3.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419" +dependencies = [ + "winapi-i686-pc-windows-gnu", + "winapi-x86_64-pc-windows-gnu", +] + +[[package]] +name = "winapi-i686-pc-windows-gnu" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" + [[package]] name = "winapi-util" version = "0.1.11" @@ -4459,6 +4793,47 @@ dependencies = [ "windows-sys 0.61.2", ] +[[package]] +name = "winapi-x86_64-pc-windows-gnu" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" + +[[package]] +name = "windows" +version = "0.61.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9babd3a767a4c1aef6900409f85f5d53ce2544ccdfaa86dad48c91782c6d6893" +dependencies = [ + "windows-collections", + "windows-core 0.61.2", + "windows-future", + "windows-link 0.1.3", + "windows-numerics", +] + +[[package]] +name = "windows-collections" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3beeceb5e5cfd9eb1d76b381630e82c4241ccd0d27f1a39ed41b2760b255c5e8" +dependencies = [ + "windows-core 0.61.2", +] + +[[package]] +name = "windows-core" +version = "0.61.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c0fdd3ddb90610c7638aa2b3a3ab2904fb9e5cdbecc643ddb3647212781c4ae3" +dependencies = [ + "windows-implement", + "windows-interface", + "windows-link 0.1.3", + "windows-result 0.3.4", + "windows-strings 0.4.2", +] + [[package]] name = "windows-core" version = "0.62.2" @@ -4467,9 +4842,20 @@ checksum = "b8e83a14d34d0623b51dce9581199302a221863196a1dde71a7663a4c2be9deb" dependencies = [ "windows-implement", "windows-interface", - "windows-link", - "windows-result", - "windows-strings", + "windows-link 0.2.1", + "windows-result 0.4.1", + "windows-strings 0.5.1", +] + +[[package]] +name = "windows-future" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fc6a41e98427b19fe4b73c550f060b59fa592d7d686537eebf9385621bfbad8e" +dependencies = [ + "windows-core 0.61.2", + "windows-link 0.1.3", + "windows-threading", ] [[package]] @@ -4494,19 +4880,53 @@ dependencies = [ "syn", ] +[[package]] +name = "windows-link" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5e6ad25900d524eaabdbbb96d20b4311e1e7ae1699af4fb28c17ae66c80d798a" + [[package]] name = "windows-link" version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f0805222e57f7521d6a62e36fa9163bc891acd422f971defe97d64e70d0a4fe5" +[[package]] +name = "windows-numerics" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9150af68066c4c5c07ddc0ce30421554771e528bde427614c61038bc2c92c2b1" +dependencies = [ + "windows-core 0.61.2", + "windows-link 0.1.3", +] + +[[package]] +name = "windows-result" +version = "0.3.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "56f42bd332cc6c8eac5af113fc0c1fd6a8fd2aa08a0119358686e5160d0586c6" +dependencies = [ + "windows-link 0.1.3", +] + [[package]] name = "windows-result" version = "0.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7781fa89eaf60850ac3d2da7af8e5242a5ea78d1a11c49bf2910bb5a73853eb5" dependencies = [ - "windows-link", + "windows-link 0.2.1", +] + +[[package]] +name = "windows-strings" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "56e6c93f3a0c3b36176cb1327a4958a0353d5d166c2a35cb268ace15e91d3b57" +dependencies = [ + "windows-link 0.1.3", ] [[package]] @@ -4515,7 +4935,7 @@ version = "0.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7837d08f69c77cf6b07689544538e017c1bfcf57e34b4c0ff58e6c2cd3b37091" dependencies = [ - "windows-link", + "windows-link 0.2.1", ] [[package]] @@ -4533,7 +4953,7 @@ version = "0.61.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ae137229bcbd6cdf0f7b80a31df61766145077ddf49416a728b02cb3921ff3fc" dependencies = [ - "windows-link", + "windows-link 0.2.1", ] [[package]] @@ -4552,6 +4972,15 @@ dependencies = [ "windows_x86_64_msvc", ] +[[package]] +name = "windows-threading" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b66463ad2e0ea3bbf808b7f1d371311c80e115c0b71d60efc142cafbcfb057a6" +dependencies = [ + "windows-link 0.1.3", +] + [[package]] name = "windows_aarch64_gnullvm" version = "0.52.6" @@ -4748,7 +5177,7 @@ dependencies = [ "deflate64", "flate2", "getrandom 0.4.3", - "hmac", + "hmac 0.13.0", "indexmap", "lzma-rust2", "memchr", diff --git a/Cargo.toml b/Cargo.toml index 9f153d6a..84d3c068 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -28,6 +28,7 @@ reqwest = { version = "0.13", default-features = false, features = [ "gzip", "rustls", "query", + "http2" ] } semver = "1.0" serde = { version = "1.0", features = ["derive"] } @@ -55,6 +56,8 @@ utoipa-swagger-ui = { version = "9.0.2", features = ["actix-web"] } uuid = { version = "1.8", features = ["v4", "fast-rng", "macro-diagnostics"] } validator = { version = "0.20.0", features = ["derive"] } zip = "8.6.0" +# have to do this until https://github.com/durch/rust-s3/pull/452 is merged :( +rust-s3 = { git = "https://github.com/w4nderlust/rust-s3", rev = "2936eb7", default-features = false, features = ["tokio-rustls-tls", "fail-on-err"] } [target.'cfg(target_env = "musl")'.dependencies] mimalloc = "0.1.52" diff --git a/migrations/20260718120021_add_managed_download_link.down.sql b/migrations/20260718120021_add_managed_download_link.down.sql new file mode 100644 index 00000000..c2e9517a --- /dev/null +++ b/migrations/20260718120021_add_managed_download_link.down.sql @@ -0,0 +1 @@ +ALTER TABLE mod_versions DROP COLUMN managed_download_link; diff --git a/migrations/20260718120021_add_managed_download_link.up.sql b/migrations/20260718120021_add_managed_download_link.up.sql new file mode 100644 index 00000000..da9db1ee --- /dev/null +++ b/migrations/20260718120021_add_managed_download_link.up.sql @@ -0,0 +1 @@ +ALTER TABLE mod_versions ADD COLUMN managed_download_link TEXT; diff --git a/src/config.rs b/src/config.rs index 18a451d9..76cf5dfd 100644 --- a/src/config.rs +++ b/src/config.rs @@ -1,10 +1,15 @@ -use std::{sync::Arc, time::Duration}; +use std::{ + sync::{Arc, OnceLock}, + time::Duration, +}; use moka::future::Cache; +use tokio::sync::mpsc::Sender; use crate::{ endpoints::mods::IndexQueryParams, - storage::{LocalBackend, PrivateDisk, PublicDisk}, + s3_worker::S3WorkerTask, + storage::{LocalBackend, PrivateDisk, PublicDisk, S3Backend, S3Configuration}, types::{ api::{ApiResponse, PaginatedData}, models::mod_entity::Mod, @@ -22,12 +27,16 @@ pub struct AppData { static_storage: PublicDisk, public_storage: PublicDisk, private_storage: PrivateDisk, + mod_storage: Option, disable_downloads: bool, max_download_mb: u32, port: u16, debug: bool, mods_cache: Cache>>, + http_client: reqwest::Client, + + s3_sender: OnceLock>, } #[derive(Clone)] @@ -68,6 +77,13 @@ pub async fn build_config() -> anyhow::Result { .time_to_live(Duration::from_mins(10)) .build(); + let mod_storage = if let Some(s3_config) = S3Configuration::from_env()? { + let backend = Arc::new(S3Backend::new(&s3_config)?); + Some(PublicDisk::new(backend, s3_config.public_url)) + } else { + None + }; + Ok(AppData { db: pool, app_url: app_url.clone(), @@ -87,11 +103,18 @@ pub async fn build_config() -> anyhow::Result { format!("{app_url}/storage"), ), private_storage: PrivateDisk::new(Arc::new(LocalBackend::new("storage/private"))), + mod_storage, disable_downloads, max_download_mb, port, debug, mods_cache, + http_client: reqwest::Client::builder() + .pool_max_idle_per_host(4) + .connect_timeout(Duration::from_secs(10)) + .read_timeout(Duration::from_secs(30)) + .build()?, + s3_sender: OnceLock::new(), }) } @@ -158,7 +181,29 @@ impl AppData { &self.private_storage } + pub fn mod_storage(&self) -> Option<&PublicDisk> { + self.mod_storage.as_ref() + } + pub fn mods_cache(&self) -> &Cache>> { &self.mods_cache } + + pub fn http_client(&self) -> &reqwest::Client { + &self.http_client + } + + pub fn init_s3_sender(&self, sender: Sender) { + self.s3_sender + .set(sender) + .expect("init_s3_sender must be called only once"); + } + + pub fn send_s3_task(&self, task: S3WorkerTask) -> bool { + if let Some(sender) = self.s3_sender.get() { + sender.try_send(task).is_ok() + } else { + false + } + } } diff --git a/src/database/repository/mod_versions.rs b/src/database/repository/mod_versions.rs index a9a64dcf..abd6a56d 100644 --- a/src/database/repository/mod_versions.rs +++ b/src/database/repository/mod_versions.rs @@ -18,6 +18,7 @@ struct ModVersionRow { description: Option, version: String, download_link: String, + managed_download_link: Option, download_count: i32, hash: String, geode: String, @@ -40,6 +41,7 @@ impl ModVersionRow { description: self.description, version: self.version, download_link: self.download_link, + managed_download_link: self.managed_download_link, hash: self.hash, geode: self.geode, early_load: self.early_load, @@ -71,7 +73,7 @@ pub async fn get_by_version_str( ModVersionRow, r#"SELECT mv.id, mv.name, mv.description, mv.version, - mv.download_link, mv.download_count, mv.hash, + mv.download_link, mv.managed_download_link, mv.download_count, mv.hash, format_semver(mv.geode_major, mv.geode_minor, mv.geode_patch, mv.geode_meta) as "geode!: _", mv.early_load, mv.requires_patching, mv.api, mv.mod_id, mv.created_at, mv.updated_at, @@ -100,7 +102,7 @@ pub async fn get_for_mod( ModVersionRow, r#"SELECT mv.id, mv.name, mv.description, mv.version, - mv.download_link, mv.download_count, mv.hash, + mv.download_link, mv.managed_download_link, mv.download_count, mv.hash, format_semver(mv.geode_major, mv.geode_minor, mv.geode_patch, mv.geode_meta) as "geode!: _", mv.early_load, mv.requires_patching, mv.api, mv.mod_id, mv.created_at, mv.updated_at, @@ -227,6 +229,7 @@ pub async fn create_from_json( description: row.description, version: row.version, download_link: row.download_link, + managed_download_link: None, hash: row.hash, geode: geode.to_string(), download_count: 0.into(), @@ -331,6 +334,7 @@ pub async fn update_pending_version( description: row.description, version: row.version, download_link: row.download_link, + managed_download_link: None, hash: row.hash, geode: geode.to_string(), download_count: row.download_count.into(), @@ -386,3 +390,20 @@ pub async fn update_version_status( Ok(version) } + +#[tracing::instrument(skip_all, fields(id = %id, link = ?link))] +pub async fn update_managed_download_link( + id: i32, + link: Option<&str>, + conn: &mut PgConnection, +) -> Result<(), DatabaseError> { + sqlx::query!( + "UPDATE mod_versions SET managed_download_link = $1 WHERE id = $2", + link, id + ) + .execute(&mut *conn) + .await + .inspect_err(|e| tracing::error!("{:?}", e))?; + + Ok(()) +} diff --git a/src/endpoints/mod_version_submissions.rs b/src/endpoints/mod_version_submissions.rs index 2e49ddcb..9b1954ed 100644 --- a/src/endpoints/mod_version_submissions.rs +++ b/src/endpoints/mod_version_submissions.rs @@ -466,7 +466,7 @@ pub async fn create_comment( username: dev.username.clone(), } .to_discord_webhook() - .send(data.index_admin_webhook_url()); + .send(data.http_client(), data.index_admin_webhook_url()); } Ok(HttpResponse::Created().json(ApiResponse { diff --git a/src/endpoints/mod_versions.rs b/src/endpoints/mod_versions.rs index 93dd2ab6..742a396e 100644 --- a/src/endpoints/mod_versions.rs +++ b/src/endpoints/mod_versions.rs @@ -16,6 +16,7 @@ use crate::events::mod_created::{ NewUnverifiedModVersionCreated, }; use crate::mod_zip::{self, download_mod}; +use crate::s3_worker::S3WorkerTask; use crate::types::models; use crate::types::models::mod_version_submission::ModVersionSubmissionLock; use crate::webhook::discord::DiscordWebhook; @@ -235,7 +236,10 @@ pub async fn download_version( .ok_or(ApiError::NotFound( "Couldn't find valid mod version for given filters".into(), ))?; - let url = mod_version.download_link; + + let url = mod_version + .managed_download_link + .unwrap_or(mod_version.download_link); if data.disable_downloads() || mod_version.status != ModVersionStatusEnum::Accepted { // whatever @@ -346,8 +350,8 @@ pub async fn create_version( .filter(|c| c.is_ascii() && *c != '\0') .collect(); - let bytes = download_mod(&download_link, data.max_download_mb()).await?; - let json = ModJson::from_zip(bytes, &download_link, make_accepted) + let bytes = download_mod(data.http_client(), &download_link, data.max_download_mb()).await?; + let json = ModJson::from_zip(&bytes, &download_link, make_accepted) .inspect_err(|e| tracing::error!("Failed to parse mod.json: {e}"))?; if json.id != the_mod.id { return Err(ApiError::BadRequest(format!( @@ -463,7 +467,14 @@ pub async fn create_version( base_url: data.app_url().to_string(), } .to_discord_webhook() - .send(data.webhook_url()); + .send(data.http_client(), data.webhook_url()); + + data.send_s3_task(S3WorkerTask::UploadMod { + data: bytes, + mod_id: the_mod.id, + version: version.version.clone(), + version_id: version.id, + }); } else { NewUnverifiedModVersionCreated { id: the_mod.id.clone(), @@ -472,7 +483,7 @@ pub async fn create_version( owner: dev.clone(), } .to_discord_webhook() - .send(data.index_admin_webhook_url()); + .send(data.http_client(), data.index_admin_webhook_url()); } version.modify_metadata(data.app_url(), false); @@ -516,6 +527,7 @@ pub async fn update_version( let the_mod = mods::get_one(&path.id, false, &mut pool) .await? .ok_or(ApiError::NotFound(format!("Mod {} not found", path.id)))?; + let mod_id = the_mod.id.clone(); if !dev.admin { return Err(ApiError::Authorization); @@ -560,18 +572,19 @@ pub async fn update_version( } let bytes = mod_zip::download_mod_hash_comp( + data.http_client(), &version.download_link, &version.hash, data.max_download_mb(), ) .await?; - let json = ModJson::from_zip(bytes, &version.download_link, true)?; + let json = ModJson::from_zip(&bytes, &version.download_link, true)?; // Update links with data from mod.json if let Some(links) = json.links.clone() { mod_links::upsert( - the_mod.id.as_str(), + &mod_id, links.community, links.homepage, links.source, @@ -579,7 +592,7 @@ pub async fn update_version( ) .await?; } else { - mod_links::upsert(the_mod.id.as_str(), None, None, None, &mut tx).await?; + mod_links::upsert(&mod_id, None, None, None, &mut tx).await?; } // Update tags with data from mod.json @@ -593,6 +606,13 @@ pub async fn update_version( mods::update_with_json_moved(the_mod, json, &mut tx).await?; + data.send_s3_task(S3WorkerTask::UploadMod { + data: bytes, + mod_id, + version: version.version.clone(), + version_id: version.id, + }); + // Let's also maybe lock the thread if it exists! let thread = mod_version_submissions::get_for_mod_version(version.id, &mut tx).await?; if let Some(thread) = thread @@ -629,7 +649,7 @@ pub async fn update_version( base_url: data.app_url().to_string(), } .to_discord_webhook() - .send(data.webhook_url()); + .send(data.http_client(), data.webhook_url()); } else { NewModVersionAcceptedEvent { id: version.mod_id, @@ -640,7 +660,7 @@ pub async fn update_version( base_url: data.app_url().to_string(), } .to_discord_webhook() - .send(data.webhook_url()); + .send(data.http_client(), data.webhook_url()); } } diff --git a/src/endpoints/mods.rs b/src/endpoints/mods.rs index 195cbd87..2b53f416 100644 --- a/src/endpoints/mods.rs +++ b/src/endpoints/mods.rs @@ -217,8 +217,13 @@ pub async fn create( ) -> Result { let dev = auth.developer()?; let mut pool = data.db().acquire().await?; - let bytes = mod_zip::download_mod(&payload.download_link, data.max_download_mb()).await?; - let json = ModJson::from_zip(bytes, &payload.download_link, false)?; + let bytes = mod_zip::download_mod( + data.http_client(), + &payload.download_link, + data.max_download_mb(), + ) + .await?; + let json = ModJson::from_zip(&bytes, &payload.download_link, false)?; json.validate()?; let existing: Option = mods::get_one(&json.id, false, &mut pool).await?; @@ -302,7 +307,7 @@ pub async fn create( owner: dev.clone(), } .to_discord_webhook() - .send(data.index_admin_webhook_url()); + .send(data.http_client(), data.index_admin_webhook_url()); for i in &mut the_mod.versions { i.modify_metadata(data.app_url(), false); @@ -485,7 +490,7 @@ pub async fn update_mod( featured: payload.featured, } .to_discord_webhook() - .send(data.webhook_url()); + .send(data.http_client(), data.webhook_url()); } } diff --git a/src/main.rs b/src/main.rs index 1b170070..f6746f9c 100644 --- a/src/main.rs +++ b/src/main.rs @@ -20,6 +20,7 @@ mod jobs; mod logging; mod mod_zip; mod openapi; +mod s3_worker; mod storage; mod types; mod webhook; @@ -37,6 +38,9 @@ async fn main() -> anyhow::Result<()> { let app_data = config::build_config().await?; app_data.static_storage().init().await?; app_data.private_storage().init().await?; + if let Some(mod_storage) = app_data.mod_storage() { + mod_storage.init().await?; + } if cli::maybe_cli(&app_data).await? { return Ok(()); @@ -48,12 +52,15 @@ async fn main() -> anyhow::Result<()> { let port = app_data.port(); let debug = app_data.debug(); + let data = web::Data::new(app_data.clone()); + tokio::spawn(s3_worker::run_s3_worker(data.clone())); + tracing::info!("Starting server on 0.0.0.0:{}", port); let server = HttpServer::new(move || { let openapi = ApiDoc::openapi(); let app = App::new() - .app_data(web::Data::new(app_data.clone())) + .app_data(data.clone()) .app_data(QueryConfig::default().error_handler(api::query_error_handler)) .service( SwaggerUi::new("/swagger/{_:.*}").url("/swagger/openapi.json", openapi.clone()), diff --git a/src/mod_zip.rs b/src/mod_zip.rs index 8b089581..6a5b039b 100644 --- a/src/mod_zip.rs +++ b/src/mod_zip.rs @@ -36,7 +36,7 @@ pub enum ModZipError { InvalidBinaries(String), } -pub fn extract_mod_logo(file: &mut ZipFile>) -> Result, ModZipError> { +pub fn extract_mod_logo(file: &mut ZipFile) -> Result, ModZipError> { const FIVE_MEGABYTES: u64 = 5 * 1000 * 1000; if file.size() > FIVE_MEGABYTES { return Err(ModZipError::InvalidLogo( @@ -89,7 +89,7 @@ pub fn extract_mod_logo(file: &mut ZipFile>) -> Result, Mo Ok(bytes) } -pub fn validate_mod_logo(file: &mut ZipFile>) -> Result<(), ModZipError> { +pub fn validate_mod_logo(file: &mut ZipFile) -> Result<(), ModZipError> { const FIVE_MEGABYTES: u64 = 5 * 1000 * 1000; if file.size() > FIVE_MEGABYTES { return Err(ModZipError::InvalidLogo( @@ -119,16 +119,21 @@ pub fn validate_mod_logo(file: &mut ZipFile>) -> Result<(), ModZip } } -pub async fn download_mod(url: &str, limit_mb: u32) -> Result { - download(url, limit_mb).await +pub async fn download_mod( + http_client: &reqwest::Client, + url: &str, + limit_mb: u32, +) -> Result { + download(http_client, url, limit_mb).await } pub async fn download_mod_hash_comp( + http_client: &reqwest::Client, url: &str, hash: &str, limit_mb: u32, ) -> Result { - let bytes = download(url, limit_mb).await?; + let bytes = download(http_client, url, limit_mb).await?; let slice: &[u8] = &bytes; @@ -140,15 +145,21 @@ pub async fn download_mod_hash_comp( Ok(bytes) } -pub fn bytes_to_ziparchive(bytes: Bytes) -> Result>, ModZipError> { +pub fn bytes_to_ziparchive(bytes: &[u8]) -> Result>, ModZipError> { ZipArchive::new(Cursor::new(bytes)) .inspect_err(|e| tracing::error!("Failed to create ZipArchive: {}", e)) .map_err(|e| e.into()) } -async fn download(url: &str, limit_mb: u32) -> Result { +async fn download( + http_client: &reqwest::Client, + url: &str, + limit_mb: u32, +) -> Result { let limit_bytes: u64 = limit_mb as u64 * 1_000_000; - let mut response = reqwest::get(url) + let mut response = http_client + .get(url) + .send() .await .inspect_err(|e| tracing::error!("Failed to fetch .geode file: {e}"))? .error_for_status() diff --git a/src/s3_worker.rs b/src/s3_worker.rs new file mode 100644 index 00000000..f7a5ed87 --- /dev/null +++ b/src/s3_worker.rs @@ -0,0 +1,207 @@ +use std::time::Duration; + +use actix_web::web; +use bytes::Bytes; + +use crate::{ + config::AppData, database::repository::mod_versions::update_managed_download_link, + types::models::mod_gd_version::GDVersionEnum, +}; + +pub enum S3WorkerTask { + UploadMod { + data: Bytes, + mod_id: String, + version: String, + version_id: i32, + }, +} + +fn path_for_mod(mod_id: &str, version: &str) -> String { + format!("mods/{mod_id}/{version}/{mod_id}.geode") +} + +async fn process_task(data: &AppData, task: S3WorkerTask) -> anyhow::Result<()> { + let storage = data.mod_storage().expect("mod storage must be set by now"); + + match task { + S3WorkerTask::UploadMod { + data: bytes, + mod_id, + version, + version_id, + } => { + let path = path_for_mod(&mod_id, &version); + let public_url = storage.asset_url(&path); + + storage.store(&path, &bytes).await?; + + let mut tx = data.db().begin().await?; + update_managed_download_link(version_id, Some(&public_url), &mut tx).await?; + tx.commit().await?; + + tracing::info!( + "Uploaded mod {} {} to S3 at {}", + mod_id, + version, + public_url + ); + } + } + + Ok(()) +} + +async fn cleanup_old_s3_files(data: &AppData) -> anyhow::Result<()> { + let supported_gd = GDVersionEnum::supported_for_storage(); + let storage = data.mod_storage().expect("mod storage must be set by now"); + + let mut db = data.db().acquire().await?; + + let versions = sqlx::query!( + "SELECT mv.id, mv.version, mv.managed_download_link, mv.mod_id FROM mod_versions mv + WHERE managed_download_link IS NOT NULL + AND mv.id NOT IN ( + SELECT DISTINCT ON (q.mv_id) q.mv_id FROM ( + SELECT DISTINCT ON (m.id, mgv.gd, mv.geode_major) m.id, mv.name, mv.version, mv.download_link, mv.managed_download_link, mv.id as mv_id, mgv.gd + FROM MODS m + INNER JOIN mod_versions mv ON m.id = mv.mod_id + INNER JOIN mod_version_statuses mvs ON mvs.mod_version_id = mv.id + INNER JOIN mod_gd_versions mgv ON mgv.mod_id = mv.id + WHERE mvs.status = 'accepted' AND mgv.gd = ANY($1::gd_version[]) + ORDER BY m.id, mgv.gd DESC, mv.geode_major DESC, mv.id DESC + ) q + ORDER BY q.mv_id + ) + ", + supported_gd as &[GDVersionEnum] + ) + .fetch_all(&mut *db) + .await?; + + tracing::info!("Cleaning up {} old S3 files", versions.len()); + + for record in versions { + let path = path_for_mod(&record.mod_id, &record.version); + if let Err(e) = storage.delete(&path).await { + tracing::error!("error deleting old S3 file for mod {} {} at {:?}: {e:?}", record.mod_id, record.version, record.managed_download_link); + continue; + } + + tracing::debug!("Deleted S3 file at path {}", path); + + let mut tx = data.db().begin().await?; + update_managed_download_link(record.id, None, &mut tx).await?; + tx.commit().await?; + } + + Ok(()) +} + +async fn migrate_one( + data: &AppData, + original_url: &str, + mod_id: &str, + version: &str, + version_id: i32, +) -> anyhow::Result<()> { + let resp = data + .http_client() + .get(original_url) + .send() + .await? + .error_for_status()?; + let bytes = resp.bytes().await?; + + process_task( + data, + S3WorkerTask::UploadMod { + data: bytes, + mod_id: mod_id.to_owned(), + version: version.to_owned(), + version_id, + }, + ) + .await +} + +async fn migrate_existing_mods_to_s3(data: &AppData) -> anyhow::Result<()> { + let supported_gd = GDVersionEnum::supported_for_storage(); + + let mut db = data.db().acquire().await?; + + // gets the latest approved version of each mod for each supported GD version + let versions = sqlx::query!( + "SELECT final_q.id, final_q.version, final_q.download_link, final_q.mv_id FROM ( + SELECT DISTINCT ON (q.mv_id) q.id, q.version, q.download_link, q.mv_id, q.gd FROM ( + SELECT DISTINCT ON (m.id, mgv.gd, mv.geode_major) m.id, mv.name, mv.version, mv.download_link, mv.managed_download_link, mv.id as mv_id, mgv.gd + FROM MODS m + INNER JOIN mod_versions mv ON m.id = mv.mod_id + INNER JOIN mod_version_statuses mvs ON mvs.mod_version_id = mv.id + INNER JOIN mod_gd_versions mgv ON mgv.mod_id = mv.id + WHERE mvs.status = 'accepted' AND mgv.gd = ANY($1::gd_version[]) + ORDER BY m.id, mgv.gd DESC, mv.geode_major DESC, mv.id DESC + ) q + WHERE q.managed_download_link IS NULL + ORDER BY q.mv_id, q.gd DESC + ) final_q", + supported_gd as &[GDVersionEnum] + ) + .fetch_all(&mut *db) + .await?; + + tracing::info!("Migrating {} existing mods to S3", versions.len()); + + for record in versions { + if let Err(e) = migrate_one( + data, + &record.download_link, + &record.id, + &record.version, + record.mv_id, + ) + .await + { + tracing::error!( + "error migrating mod {} {} to S3: {e:?}", + record.id, + record.version + ); + } + } + + Ok(()) +} + +pub async fn run_s3_worker(data: web::Data) { + if data.mod_storage().is_none() { + return; + } + + let (tx, mut rx) = tokio::sync::mpsc::channel(64); + data.init_s3_sender(tx); + + let s_data = data.clone(); + tokio::spawn(async move { + if let Err(e) = migrate_existing_mods_to_s3(&s_data).await { + tracing::error!("Error migrating existing mods to S3: {:?}", e); + } + }); + + let mut interval = tokio::time::interval(Duration::from_mins(30)); + + loop { + let result = tokio::select! { + task = rx.recv() => match task { + Some(task) => process_task(&data, task).await, + None => break, + }, + + _ = interval.tick() => cleanup_old_s3_files(&data).await, + }; + + if let Err(e) = result { + tracing::error!("Error processing S3 worker task: {:?}", e); + } + } +} diff --git a/src/storage/local.rs b/src/storage/local.rs new file mode 100644 index 00000000..ffc2eaaf --- /dev/null +++ b/src/storage/local.rs @@ -0,0 +1,62 @@ +use super::*; +use std::path::PathBuf; + +pub struct LocalBackend { + base_path: PathBuf, +} + +impl LocalBackend { + pub fn new(base_path: impl Into) -> LocalBackend { + LocalBackend { + base_path: base_path.into(), + } + } +} + +impl StorageBackend for LocalBackend { + fn store<'a>( + &'a self, + relative_path: &'a str, + data: &'a [u8], + ) -> BoxFuture<'a, StorageResult<()>> { + Box::pin(async move { + let path = self.base_path.join(relative_path); + if let Some(parent) = path.parent() { + tokio::fs::create_dir_all(parent).await?; + } + + tokio::fs::write(path, data).await.map_err(|e| e.into()) + }) + } + + fn read<'a>(&'a self, path: &'a str) -> BoxFuture<'a, StorageResult>> { + Box::pin(async move { + let path = self.base_path.join(path); + match tokio::fs::read(path).await { + Ok(data) => Ok(data), + Err(e) if e.kind() == std::io::ErrorKind::NotFound => Ok(vec![]), + Err(e) => Err(e), + } + .map_err(|e| e.into()) + }) + } + + fn exists<'a>(&'a self, path: &'a str) -> BoxFuture<'a, StorageResult> { + Box::pin(async move { + let path = self.base_path.join(path); + Ok(tokio::fs::metadata(path).await.is_ok()) + }) + } + + fn delete<'a>(&'a self, path: &'a str) -> BoxFuture<'a, StorageResult<()>> { + Box::pin(async move { + let path = self.base_path.join(path); + match tokio::fs::remove_file(path).await { + Ok(()) => Ok(()), + Err(e) if e.kind() == std::io::ErrorKind::NotFound => Ok(()), + Err(e) => Err(e), + } + .map_err(|e| e.into()) + }) + } +} diff --git a/src/storage.rs b/src/storage/mod.rs similarity index 68% rename from src/storage.rs rename to src/storage/mod.rs index 44a0d3a1..dff96428 100644 --- a/src/storage.rs +++ b/src/storage/mod.rs @@ -1,13 +1,23 @@ use std::{path::PathBuf, pin::Pin, sync::Arc}; +pub use local::LocalBackend; +pub use s3::*; + +mod local; +mod s3; + #[derive(thiserror::Error, Debug)] pub enum StorageError { #[error("I/O error: {0}")] Io(#[from] std::io::Error), + #[error("S3 error: {0}")] + S3(#[from] ::s3::error::S3Error), + #[error("{0}")] + Other(String), } pub type StorageResult = Result; -type BoxFuture<'a, T> = Pin + Send + 'a>>; +pub type BoxFuture<'a, T> = Pin + Send + 'a>>; pub trait StorageBackend: Send + Sync { fn init(&self) -> BoxFuture<'_, StorageResult<()>> { @@ -19,66 +29,6 @@ pub trait StorageBackend: Send + Sync { fn delete<'a>(&'a self, path: &'a str) -> BoxFuture<'a, StorageResult<()>>; } -pub struct LocalBackend { - base_path: PathBuf, -} - -impl LocalBackend { - pub fn new(base_path: impl Into) -> LocalBackend { - LocalBackend { - base_path: base_path.into(), - } - } -} - -impl StorageBackend for LocalBackend { - fn store<'a>( - &'a self, - relative_path: &'a str, - data: &'a [u8], - ) -> BoxFuture<'a, StorageResult<()>> { - Box::pin(async move { - let path = self.base_path.join(relative_path); - if let Some(parent) = path.parent() { - tokio::fs::create_dir_all(parent).await?; - } - - tokio::fs::write(path, data).await.map_err(|e| e.into()) - }) - } - - fn read<'a>(&'a self, path: &'a str) -> BoxFuture<'a, StorageResult>> { - Box::pin(async move { - let path = self.base_path.join(path); - match tokio::fs::read(path).await { - Ok(data) => Ok(data), - Err(e) if e.kind() == std::io::ErrorKind::NotFound => Ok(vec![]), - Err(e) => Err(e), - } - .map_err(|e| e.into()) - }) - } - - fn exists<'a>(&'a self, path: &'a str) -> BoxFuture<'a, StorageResult> { - Box::pin(async move { - let path = self.base_path.join(path); - Ok(tokio::fs::metadata(path).await.is_ok()) - }) - } - - fn delete<'a>(&'a self, path: &'a str) -> BoxFuture<'a, StorageResult<()>> { - Box::pin(async move { - let path = self.base_path.join(path); - match tokio::fs::remove_file(path).await { - Ok(()) => Ok(()), - Err(e) if e.kind() == std::io::ErrorKind::NotFound => Ok(()), - Err(e) => Err(e), - } - .map_err(|e| e.into()) - }) - } -} - #[derive(Clone)] struct DiskCore { backend: Arc, diff --git a/src/storage/s3.rs b/src/storage/s3.rs new file mode 100644 index 00000000..a8124cc6 --- /dev/null +++ b/src/storage/s3.rs @@ -0,0 +1,142 @@ +use super::*; +use ::s3::{Bucket, Region, creds::Credentials}; + +pub enum S3Provider { + Aws, + Cloudflare, +} + +impl S3Provider { + pub fn from_str(s: &str) -> Option { + match s.to_lowercase().as_str() { + "aws" => Some(S3Provider::Aws), + "cloudflare" => Some(S3Provider::Cloudflare), + _ => None, + } + } +} + +pub struct S3Configuration { + pub provider: S3Provider, + pub bucket: String, + pub region: Option, + pub access_key: String, + pub secret_key: String, + pub account_id: Option, + pub public_url: String, +} + +impl S3Configuration { + pub fn from_env() -> anyhow::Result> { + let provider = dotenvy::var("STORAGE_PROVIDER").unwrap_or_default(); + if provider.is_empty() { + return Ok(None); + } + + let provider = S3Provider::from_str(&provider).ok_or_else(|| { + anyhow::anyhow!("Invalid STORAGE_PROVIDER value, must be 'aws' or 'cloudflare'") + })?; + + let config = S3Configuration { + provider, + bucket: dotenvy::var("STORAGE_BUCKET")?, + region: dotenvy::var("STORAGE_REGION").ok(), + access_key: dotenvy::var("STORAGE_ACCESS_KEY")?, + secret_key: dotenvy::var("STORAGE_SECRET_KEY")?, + account_id: dotenvy::var("STORAGE_ACCOUNT_ID").ok(), + public_url: dotenvy::var("STORAGE_PUBLIC_URL")?, + }; + + Ok(Some(config)) + } +} + +pub struct S3Backend { + bucket: Box, +} + +impl S3Backend { + pub fn new(config: &S3Configuration) -> anyhow::Result { + match config.provider { + S3Provider::Aws => S3Backend::new_aws(config), + S3Provider::Cloudflare => S3Backend::new_cloudflare(config), + } + } + + fn new_aws(config: &S3Configuration) -> anyhow::Result { + let Some(region) = &config.region else { + return Err(anyhow::anyhow!("STORAGE_REGION is required for AWS S3")); + }; + + let credentials = Credentials::new( + Some(&config.access_key), + Some(&config.secret_key), + None, + None, + None, + )?; + + let bucket = Bucket::new(&config.bucket, region.parse()?, credentials)?; + + Ok(S3Backend { bucket }) + } + + fn new_cloudflare(config: &S3Configuration) -> anyhow::Result { + let Some(account_id) = config.account_id.clone() else { + return Err(anyhow::anyhow!( + "STORAGE_ACCOUNT_ID is required for Cloudflare R2" + )); + }; + + let credentials = Credentials::new( + Some(&config.access_key), + Some(&config.secret_key), + None, + None, + None, + )?; + + let bucket = Bucket::new(&config.bucket, Region::R2 { account_id }, credentials)?; + + Ok(S3Backend { bucket }) + } +} + +impl StorageBackend for S3Backend { + fn store<'a>( + &'a self, + relative_path: &'a str, + data: &'a [u8], + ) -> BoxFuture<'a, StorageResult<()>> { + Box::pin(async move { + let _ = self.bucket.put_object(relative_path, data).await?; + Ok(()) + }) + } + + fn read<'a>(&'a self, path: &'a str) -> BoxFuture<'a, StorageResult>> { + Box::pin(async move { + let data = self.bucket.get_object(path).await?; + + if data.status_code() != 200 { + return Err(StorageError::Other(format!( + "S3 API returned HTTP error {}", + data.status_code() + ))); + } + + Ok(data.to_vec()) + }) + } + + fn exists<'a>(&'a self, path: &'a str) -> BoxFuture<'a, StorageResult> { + Box::pin(async move { Ok(self.bucket.object_exists(path).await?) }) + } + + fn delete<'a>(&'a self, path: &'a str) -> BoxFuture<'a, StorageResult<()>> { + Box::pin(async move { + let _ = self.bucket.delete_object(path).await?; + Ok(()) + }) + } +} diff --git a/src/types/mod_json.rs b/src/types/mod_json.rs index fc994571..c890ab9c 100644 --- a/src/types/mod_json.rs +++ b/src/types/mod_json.rs @@ -180,12 +180,11 @@ pub struct OldModJsonIncompatibility { impl ModJson { pub fn from_zip( - file: Bytes, + file: &[u8], download_url: &str, store_image: bool, ) -> Result { - let slice: &[u8] = &file; - let hash = sha256::digest(slice); + let hash = sha256::digest(file); let mut archive = mod_zip::bytes_to_ziparchive(file)?; // check total size of the zip file @@ -216,7 +215,7 @@ impl ModJson { ))); } - let mut json = serde_json::from_reader::>, ModJson>(json_file) + let mut json = serde_json::from_reader::>, ModJson>(json_file) .inspect_err(|e| tracing::error!("Failed to parse mod.json: {e}"))?; json.version = json.version.trim_start_matches('v').to_string(); @@ -618,7 +617,7 @@ impl ModJson { } } -fn parse_zip_entry_to_str(file: &mut ZipFile>) -> Result { +fn parse_zip_entry_to_str(file: &mut ZipFile) -> Result { let mut string: String = String::from(""); match file.read_to_string(&mut string) { Ok(_) => Ok(string), @@ -660,9 +659,9 @@ fn parse_download_url(url: &str) -> String { String::from(url.trim_end_matches("\\/")) } -fn check_mac_binary(file: &mut ZipFile>) -> Result<(bool, bool), ModZipError> { +fn check_mac_binary(file: &mut ZipFile) -> Result<(bool, bool), ModZipError> { // 12 bytes is all we need - let mut bytes: Vec = vec![0; 12]; + let mut bytes = [0u8; 12]; file.read_exact(&mut bytes).map_err(|e| { tracing::error!("Failed to read MacOS binary: {}", e); ModZipError::InvalidBinaries(format!("Failed to read macOS binary: {e}")) diff --git a/src/types/models/mod_entity.rs b/src/types/models/mod_entity.rs index ee05d08b..6f8bb987 100644 --- a/src/types/models/mod_entity.rs +++ b/src/types/models/mod_entity.rs @@ -86,6 +86,7 @@ struct ModRecordGetOne { description: Option, version: String, download_link: String, + managed_download_link: Option, mod_version_download_count: i32, hash: String, geode: String, @@ -359,7 +360,7 @@ impl Mod { records_builder.push(" LIMIT ").push_bind(limit); records_builder.push(" OFFSET ").push_bind(offset); - // tracing::debug!("sql: {}", records_builder.sql()); + // tracing::info!("sql: {:?}", records_builder.sql()); let records: Vec = records_builder .build_query_as() @@ -586,9 +587,8 @@ impl Mod { ModRecordGetOne, r#"SELECT m.id, m.repository, m.about, m.changelog, m.featured, m.download_count as mod_download_count, m.created_at, m.updated_at, - mv.id as version_id, mv.name, mv.description, mv.version, mv.download_link, mv.download_count as mod_version_download_count, - mv.created_at as mod_version_created_at, mv.updated_at as mod_version_updated_at, - mv.hash, + mv.id as version_id, mv.name, mv.description, mv.version, mv.download_link, mv.managed_download_link, + mv.download_count as mod_version_download_count, mv.created_at as mod_version_created_at, mv.updated_at as mod_version_updated_at, mv.hash, format_semver(mv.geode_major, mv.geode_minor, mv.geode_patch, mv.geode_meta) as "geode!: _", mv.early_load, mv.requires_patching, mv.api, mv.mod_id, mvs.status as "status: _", mvs.info FROM mods m @@ -616,6 +616,7 @@ impl Mod { description: x.description.clone(), version: x.version.clone(), download_link: x.download_link.clone(), + managed_download_link: x.managed_download_link.clone(), download_count: x.mod_version_download_count.into(), hash: x.hash.clone(), geode: x.geode.clone(), diff --git a/src/types/models/mod_gd_version.rs b/src/types/models/mod_gd_version.rs index 67d36e56..6cd34493 100644 --- a/src/types/models/mod_gd_version.rs +++ b/src/types/models/mod_gd_version.rs @@ -53,6 +53,29 @@ pub enum GDVersionEnum { GD22082, } +impl GDVersionEnum { + /// GD versions that are currently actively supported + #[allow(unused)] + pub fn latest_supported() -> &'static [GDVersionEnum] { + &[ + GDVersionEnum::All, + GDVersionEnum::GD22081, + GDVersionEnum::GD22082, + ] + } + + /// GD versions for which we apply auto-migration to S3 storage + /// Generally should include versions that some users might still be using + pub fn supported_for_storage() -> &'static [GDVersionEnum] { + &[ + GDVersionEnum::All, + GDVersionEnum::GD2206, + GDVersionEnum::GD22074, + GDVersionEnum::GD22081, + ] + } +} + impl FromStr for GDVersionEnum { type Err = (); fn from_str(s: &str) -> Result { diff --git a/src/types/models/mod_version.rs b/src/types/models/mod_version.rs index 4bc46608..0abfede5 100644 --- a/src/types/models/mod_version.rs +++ b/src/types/models/mod_version.rs @@ -30,6 +30,8 @@ pub struct ModVersion { pub description: Option, pub version: String, pub download_link: String, + #[serde(skip_serializing)] + pub managed_download_link: Option, pub hash: String, pub geode: String, #[schema(value_type = i32)] @@ -67,6 +69,7 @@ struct ModVersionGetOne { description: Option, version: String, download_link: String, + managed_download_link: Option, download_count: i32, hash: String, geode: String, @@ -99,6 +102,7 @@ impl ModVersionGetOne { description: self.description.clone(), version: self.version.clone(), download_link: self.download_link.clone(), + managed_download_link: self.managed_download_link.clone(), hash: self.hash.clone(), geode: self.geode.clone(), early_load: self.early_load, @@ -318,13 +322,13 @@ impl ModVersion { sqlx::query_as( "SELECT q.name, q.id, q.description, q.version, - q.download_link, q.hash, q.geode, + q.download_link, q.managed_download_link, q.hash, q.geode, q.download_count, q.early_load, q.requires_patching, q.api, q.mod_id, 'accepted'::mod_version_status as status, q.created_at, q.updated_at FROM ( SELECT - mv.name, mv.id, mv.description, mv.version, mv.download_link, mv.hash, + mv.name, mv.id, mv.description, mv.version, mv.download_link, mv.managed_download_link, mv.hash, format_semver(mv.geode_major, mv.geode_minor, mv.geode_patch, mv.geode_meta) as geode, mv.download_count, mv.early_load, mv.requires_patching, mv.api, mv.mod_id, mv.created_at, mv.updated_at, @@ -396,7 +400,7 @@ impl ModVersion { let records = sqlx::query_as!( ModVersionGetOne, r#"SELECT DISTINCT - mv.name, mv.id, mv.description, mv.version, mv.download_link, mv.hash, + mv.name, mv.id, mv.description, mv.version, mv.download_link, mv.managed_download_link, mv.hash, format_semver(mv.geode_major, mv.geode_minor, mv.geode_patch, mv.geode_meta) as "geode!: _", mv.download_count, mv.early_load, mv.requires_patching, mv.api, mv.mod_id, mv.created_at, mv.updated_at, 'pending'::mod_version_status as "status!: _", NULL as info @@ -523,7 +527,7 @@ impl ModVersion { let result = sqlx::query_as!( ModVersionGetOne, r#"SELECT mv.id, mv.name, mv.description, mv.version, - mv.download_link, mv.download_count, + mv.download_link, mv.managed_download_link, mv.download_count, mv.hash, format_semver(mv.geode_major, mv.geode_minor, mv.geode_patch, mv.geode_meta) as "geode!: _", mv.early_load, mv.requires_patching, mv.api, diff --git a/src/webhook/discord.rs b/src/webhook/discord.rs index de3bd160..ba80256d 100644 --- a/src/webhook/discord.rs +++ b/src/webhook/discord.rs @@ -65,7 +65,7 @@ impl DiscordMessage { } } - pub fn send(&self, url: &str) { + pub fn send(&self, http_client: &reqwest::Client, url: &str) { if url.is_empty() { tracing::error!("Not sending webhook since URL is empty"); return; @@ -75,8 +75,9 @@ impl DiscordMessage { let url = String::from(url); let copy = self.clone(); + let client = http_client.clone(); tokio::spawn(async move { - if let Err(e) = reqwest::Client::new().post(&url).json(©).send().await { + if let Err(e) = client.post(&url).json(©).send().await { tracing::error!("Failed to broadcast Discord webhook {}: {}", url, e); } });