From 9bb15f00414e37282f7b51d61899cf4508b7f265 Mon Sep 17 00:00:00 2001
From: Maria Sauer <mcs22@inf.ufpr.br>
Date: Tue, 11 Mar 2025 11:24:26 -0300
Subject: [PATCH] foi

---
 2                                             |  Bin 8877 -> 0 bytes
 docker-compose.yml                            |    4 +-
 package.json                                  |    2 +
 pnpm-lock.yaml                                |  470 +++
 src/db/migrations/0002_wakeful_taskmaster.sql |    9 +
 src/db/migrations/meta/0002_snapshot.json     | 2686 +++++++++++++++++
 src/db/migrations/meta/_journal.json          |    7 +
 src/db/schema/resource.schema.ts              |    2 +-
 src/db/schema/resourceEnum.schema.ts          |    6 +-
 src/db/seeds/resource.seed.ts                 |   13 +-
 src/index.ts                                  |    7 +-
 src/routes/collection-resources.route.ts      |   26 +-
 src/routes/collections.route.ts               |   99 +-
 src/routes/resource.route.ts                  |   36 +-
 src/routes/s3.route.ts                        |    2 +
 15 files changed, 3345 insertions(+), 24 deletions(-)
 delete mode 100644 2
 create mode 100644 src/db/migrations/0002_wakeful_taskmaster.sql
 create mode 100644 src/db/migrations/meta/0002_snapshot.json

diff --git a/2 b/2
deleted file mode 100644
index 34d7c925d56590fca89fde0b2523d7530bef0478..0000000000000000000000000000000000000000
GIT binary patch
literal 0
HcmV?d00001

literal 8877
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
P_HTItPhE(W|9=wzf*=f;

diff --git a/docker-compose.yml b/docker-compose.yml
index bc28cb3..87f5403 100755
--- a/docker-compose.yml
+++ b/docker-compose.yml
@@ -3,11 +3,11 @@ services:
     image: postgres
     restart: always
     environment:
-      POSTGRES_DB: apex_db
+      POSTGRES_DB: hono_db
       POSTGRES_USER: postgres
       POSTGRES_PASSWORD: postgres
     ports:
-      - "5433:5432"
+      - "5432:5432"
     networks:
       - apex_network
     volumes:
diff --git a/package.json b/package.json
index 09493e4..a48e327 100644
--- a/package.json
+++ b/package.json
@@ -13,6 +13,7 @@
     "@hono/swagger-ui": "^0.5.0",
     "@hono/zod-openapi": "^0.18.3",
     "@hono/zod-validator": "^0.2.2",
+    "archiver": "^7.0.1",
     "dotenv": "^16.4.5",
     "dotenv-expand": "^11.0.6",
     "drizzle-orm": "^0.31.2",
@@ -26,6 +27,7 @@
   },
   "devDependencies": {
     "@eslint/js": "^9.5.0",
+    "@types/archiver": "^6.0.3",
     "@types/bun": "latest",
     "cross-env": "^7.0.3",
     "drizzle-kit": "^0.22.7",
diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml
index 44b8d2b..11a763d 100644
--- a/pnpm-lock.yaml
+++ b/pnpm-lock.yaml
@@ -20,6 +20,9 @@ importers:
       '@hono/zod-validator':
         specifier: ^0.2.2
         version: 0.2.2(hono@4.6.1)(zod@3.23.8)
+      archiver:
+        specifier: ^7.0.1
+        version: 7.0.1
       dotenv:
         specifier: ^16.4.5
         version: 16.4.5
@@ -54,6 +57,9 @@ importers:
       '@eslint/js':
         specifier: ^9.5.0
         version: 9.10.0
+      '@types/archiver':
+        specifier: ^6.0.3
+        version: 6.0.3
       '@types/bun':
         specifier: latest
         version: 1.1.9
@@ -577,6 +583,10 @@ packages:
     resolution: {integrity: sha512-d2CGZR2o7fS6sWB7DG/3a95bGKQyHMACZ5aW8qGkkqQpUoZV6C0X7Pc7l4ZNMZkfNBf4VWNe9E1jRsf0G146Ew==}
     engines: {node: '>=18.18'}
 
+  '@isaacs/cliui@8.0.2':
+    resolution: {integrity: sha512-O8jcjabXaleOG9DQ0+ARXWZBTfnP4WNAqzuiJK7ll44AmxGKv/J2M4TPjxjY3znBCfvBXFzucm1twdyFybFqEA==}
+    engines: {node: '>=12'}
+
   '@nodelib/fs.scandir@2.1.5':
     resolution: {integrity: sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==}
     engines: {node: '>= 8'}
@@ -589,6 +599,10 @@ packages:
     resolution: {integrity: sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==}
     engines: {node: '>= 8'}
 
+  '@pkgjs/parseargs@0.11.0':
+    resolution: {integrity: sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg==}
+    engines: {node: '>=14'}
+
   '@smithy/abort-controller@4.0.1':
     resolution: {integrity: sha512-fiUIYgIgRjMWznk6iLJz35K2YxSLHzLBA/RC6lBrKfQ8fHbPfvk7Pk9UvpKoHgJjI18MnbPuEju53zcVy6KF1g==}
     engines: {node: '>=18.0.0'}
@@ -808,12 +822,18 @@ packages:
   '@tokenizer/token@0.3.0':
     resolution: {integrity: sha512-OvjF+z51L3ov0OyAU0duzsYuvO01PH7x4t6DJx+guahgTnBHkhJdG7soQeTSFLWN3efnHyibZ4Z8l2EuWwJN3A==}
 
+  '@types/archiver@6.0.3':
+    resolution: {integrity: sha512-a6wUll6k3zX6qs5KlxIggs1P1JcYJaTCx2gnlr+f0S1yd2DoaEwoIK10HmBaLnZwWneBz+JBm0dwcZu0zECBcQ==}
+
   '@types/bun@1.1.9':
     resolution: {integrity: sha512-SXJRejXpmAc3qxyN/YS4/JGWEzLf4dDBa5fLtRDipQXHqNccuMU4EUYCooXNTsylG0DmwFQsGgEDHxZF+3DqRw==}
 
   '@types/node@20.12.14':
     resolution: {integrity: sha512-scnD59RpYD91xngrQQLGkE+6UrHUPzeKZWhhjBSa3HSkwjbQc38+q3RoIVEwxQGRw3M+j5hpNAM+lgV3cVormg==}
 
+  '@types/readdir-glob@1.1.5':
+    resolution: {integrity: sha512-raiuEPUYqXu+nvtY2Pe8s8FEmZ3x5yAH4VkLdihcPdalvsHltomrRC9BzuStrJ9yk06470hS0Crw0f1pXqD+Hg==}
+
   '@types/ws@8.5.12':
     resolution: {integrity: sha512-3tPRkv1EtkDpzlgyKyI8pGsGZAGPEaXeu0DOj5DI25Ja91bdAYddYHbADRYVrZMRbfW+1l5YwXVDKohDJNQxkQ==}
 
@@ -875,6 +895,10 @@ packages:
     resolution: {integrity: sha512-cDF0/Gf81QpY3xYyJKDV14Zwdmid5+uuENhjH2EqFaF0ni+yAyq/LzMaIJdhNJXZI7uLzwIlA+V7oWoyn6Curg==}
     engines: {node: ^18.18.0 || >=20.0.0}
 
+  abort-controller@3.0.0:
+    resolution: {integrity: sha512-h8lQ8tacZYnR3vNQTgibj+tODHI5/+l06Au2Pcriv/Gmet0eaj4TwWH41sO9wnHDiQsEj19q0drzdWdeAHtweg==}
+    engines: {node: '>=6.5'}
+
   acorn-jsx@5.3.2:
     resolution: {integrity: sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==}
     peerDependencies:
@@ -892,10 +916,26 @@ packages:
     resolution: {integrity: sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==}
     engines: {node: '>=8'}
 
+  ansi-regex@6.1.0:
+    resolution: {integrity: sha512-7HSX4QQb4CspciLpVFwyRe79O3xsIZDDLER21kERQ71oaPodF8jL725AgJMFAYbooIqolJoRLuM81SpeUkpkvA==}
+    engines: {node: '>=12'}
+
   ansi-styles@4.3.0:
     resolution: {integrity: sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==}
     engines: {node: '>=8'}
 
+  ansi-styles@6.2.1:
+    resolution: {integrity: sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug==}
+    engines: {node: '>=12'}
+
+  archiver-utils@5.0.2:
+    resolution: {integrity: sha512-wuLJMmIBQYCsGZgYLTy5FIB2pF6Lfb6cXMSF8Qywwk3t20zWnAi7zLcQFdKQmIB8wyZpY5ER38x08GbwtR2cLA==}
+    engines: {node: '>= 14'}
+
+  archiver@7.0.1:
+    resolution: {integrity: sha512-ZcbTaIqJOfCc03QwD468Unz/5Ir8ATtvAHsK+FdXbDIbGfihqh9mrvdcYunQzqn4HrvWWaFyaxJhGZagaJJpPQ==}
+    engines: {node: '>= 14'}
+
   argparse@2.0.1:
     resolution: {integrity: sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==}
 
@@ -903,9 +943,21 @@ packages:
     resolution: {integrity: sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw==}
     engines: {node: '>=8'}
 
+  async@3.2.6:
+    resolution: {integrity: sha512-htCUDlxyyCLMgaM3xXg0C0LW2xqfuQ6p05pCEIsXuyQ+a1koYKTuBMzRNwmybfLgvJDMd0r1LTn4+E0Ti6C2AA==}
+
+  b4a@1.6.7:
+    resolution: {integrity: sha512-OnAYlL5b7LEkALw87fUVafQw5rVR9RjwGd4KUwNQ6DrrNmaVaUCgLipfVlzrPQ4tWOR9P0IXGNOx50jYCCdSJg==}
+
   balanced-match@1.0.2:
     resolution: {integrity: sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==}
 
+  bare-events@2.5.4:
+    resolution: {integrity: sha512-+gFfDkR8pj4/TrWCGUGWmJIkBwuxPS5F+a5yWjOHQt2hHvNZd5YLzadjmDUtFmMM4y429bnKLa8bYBMHcYdnQA==}
+
+  base64-js@1.5.1:
+    resolution: {integrity: sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==}
+
   bowser@2.11.0:
     resolution: {integrity: sha512-AlcaJBi/pqqJBIQ8U9Mcpc9i8Aqxn88Skv5d+xBX006BY5u8N3mGLHa5Lgppa7L/HfwgwLgZ6NYs+Ag6uUmJRA==}
 
@@ -919,9 +971,16 @@ packages:
     resolution: {integrity: sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==}
     engines: {node: '>=8'}
 
+  buffer-crc32@1.0.0:
+    resolution: {integrity: sha512-Db1SbgBS/fg/392AblrMJk97KggmvYhr4pB5ZIMTWtaivCPMWLkmb7m21cJvpvgK+J3nsU2CmmixNBZx4vFj/w==}
+    engines: {node: '>=8.0.0'}
+
   buffer-from@1.1.2:
     resolution: {integrity: sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==}
 
+  buffer@6.0.3:
+    resolution: {integrity: sha512-FTiCpNxtwiZZHEZbcbTIcZjERVICn9yq/pDFkTl95/AxzD1naBctN7YO68riM/gLSDY7sdrMby8hofADYuuqOA==}
+
   bun-types@1.1.27:
     resolution: {integrity: sha512-rHXAiIDefeMS/fleNM1rRDYqolJGNRdch3+AuCRwcZWaqTa1vjGBNsahH/HVV7Y82frllYhJomCVSEiHzLzkgg==}
 
@@ -940,9 +999,25 @@ packages:
   color-name@1.1.4:
     resolution: {integrity: sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==}
 
+  compress-commons@6.0.2:
+    resolution: {integrity: sha512-6FqVXeETqWPoGcfzrXb37E50NP0LXT8kAMu5ooZayhWWdgEY4lBEEcbQNXtkuKQsGduxiIcI4gOTsxTmuq/bSg==}
+    engines: {node: '>= 14'}
+
   concat-map@0.0.1:
     resolution: {integrity: sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==}
 
+  core-util-is@1.0.3:
+    resolution: {integrity: sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ==}
+
+  crc-32@1.2.2:
+    resolution: {integrity: sha512-ROmzCKrTnOwybPcJApAA6WBWij23HVfGVNKqqrZpuyZOHqK2CwHSvpGuyt/UNNvaIjEd8X5IFGp4Mh+Ie1IHJQ==}
+    engines: {node: '>=0.8'}
+    hasBin: true
+
+  crc32-stream@6.0.0:
+    resolution: {integrity: sha512-piICUB6ei4IlTv1+653yq5+KoqfBYmj9bw6LqXoOneTMDXk5nM1qt12mFW1caG3LlJXEKW1Bp0WggEmIfQB34g==}
+    engines: {node: '>= 14'}
+
   cross-env@7.0.3:
     resolution: {integrity: sha512-+/HKd6EgcQCJGh2PSjZuUitQBQynKor4wrFbRg4DtAgS1aWO+gU52xpH7M9ScGgXSYmAVS9bIJ8EzuaGw0oNAw==}
     engines: {node: '>=10.14', npm: '>=6', yarn: '>=1'}
@@ -952,6 +1027,10 @@ packages:
     resolution: {integrity: sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==}
     engines: {node: '>= 8'}
 
+  cross-spawn@7.0.6:
+    resolution: {integrity: sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==}
+    engines: {node: '>= 8'}
+
   debug@4.3.7:
     resolution: {integrity: sha512-Er2nc/H7RrMXZBFCEim6TCmMk02Z8vLC2Rbi1KEBggpo0fS6l0S1nnapwmIi3yW/+GOJap1Krg4w0Hg80oCqgQ==}
     engines: {node: '>=6.0'}
@@ -1084,6 +1163,15 @@ packages:
       drizzle-orm: '>=0.23.13'
       zod: '*'
 
+  eastasianwidth@0.2.0:
+    resolution: {integrity: sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==}
+
+  emoji-regex@8.0.0:
+    resolution: {integrity: sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==}
+
+  emoji-regex@9.2.2:
+    resolution: {integrity: sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==}
+
   esbuild-register@3.6.0:
     resolution: {integrity: sha512-H2/S7Pm8a9CL1uhp9OvjwrBh5Pvx0H8qVOxNu8Wed9Y7qv56MPtq+GGM8RJpq6glYJn9Wspr8uw7l55uyinNeg==}
     peerDependencies:
@@ -1151,9 +1239,20 @@ packages:
     resolution: {integrity: sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==}
     engines: {node: '>=0.10.0'}
 
+  event-target-shim@5.0.1:
+    resolution: {integrity: sha512-i/2XbnSz/uxRCU6+NdVJgKWDTM427+MqYbkQzD321DuCQJUqOuJKIA0IM2+W2xtYHdKOmZ4dR6fExsd4SXL+WQ==}
+    engines: {node: '>=6'}
+
+  events@3.3.0:
+    resolution: {integrity: sha512-mQw+2fkQbALzQ7V0MY0IqdnXNOeTtP4r0lN9z7AAawCXgqea7bDii20AYrIBrFd/Hx0M2Ocz6S111CaFkUcb0Q==}
+    engines: {node: '>=0.8.x'}
+
   fast-deep-equal@3.1.3:
     resolution: {integrity: sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==}
 
+  fast-fifo@1.3.2:
+    resolution: {integrity: sha512-/d9sfos4yxzpwkDkuN7k2SqFKtYNmCTzgfEpz82x34IM9/zc8KGxQoXg1liNC/izpRM/MBdt44Nmx41ZWqk+FQ==}
+
   fast-glob@3.3.2:
     resolution: {integrity: sha512-oX2ruAFQwf/Orj8m737Y5adxDQO0LAB7/S5MnxCdTNDd4p6BsyIVsv9JQsATbTSq8KHRpLwIHbVlUNatxd+1Ow==}
     engines: {node: '>=8.6.0'}
@@ -1197,6 +1296,10 @@ packages:
   flatted@3.3.1:
     resolution: {integrity: sha512-X8cqMLLie7KsNUDSdzeN8FYK9rEt4Dt67OsG/DNGnYTSDBG4uFAJFBnUeiV+zCVAvwFy56IjM9sH51jVaEhNxw==}
 
+  foreground-child@3.3.1:
+    resolution: {integrity: sha512-gIXjKqtFuWEgzFRJA9WCQeSJLZDjgJUOMCMzxtvFq/37KojM1BFGufqsCy0r4qSQmYLsZYMeyRqzIWOMup03sw==}
+    engines: {node: '>=14'}
+
   get-tsconfig@4.8.1:
     resolution: {integrity: sha512-k9PN+cFBmaLWtVz29SkUoqU5O0slLuHJXt/2P+tMVFT+phsSGXGkp9t3rQIqdz0e+06EHNGs3oM6ZX1s2zHxRg==}
 
@@ -1208,6 +1311,10 @@ packages:
     resolution: {integrity: sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==}
     engines: {node: '>=10.13.0'}
 
+  glob@10.4.5:
+    resolution: {integrity: sha512-7Bv8RF0k6xjo7d4A/PxYLbUCfb6c+Vpd2/mB2yRDlew7Jb5hEXiCD9ibfO7wpk8i4sevK6DFny9h7EYbM3/sHg==}
+    hasBin: true
+
   globals@14.0.0:
     resolution: {integrity: sha512-oahGvuMGQlPw/ivIYBjVSrWAfWLBeku5tpPE2fOPLi+WHffIWbuh2tCjhyQhTBPMf5E9jDEH4FOmTYgYwbKwtQ==}
     engines: {node: '>=18'}
@@ -1220,6 +1327,9 @@ packages:
     resolution: {integrity: sha512-jhIXaOzy1sb8IyocaruWSn1TjmnBVs8Ayhcy83rmxNJ8q2uWKCAj3CnJY+KpGSXCueAPc0i05kVvVKtP1t9S3g==}
     engines: {node: '>=10'}
 
+  graceful-fs@4.2.11:
+    resolution: {integrity: sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==}
+
   graphemer@1.4.0:
     resolution: {integrity: sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag==}
 
@@ -1246,10 +1356,17 @@ packages:
     resolution: {integrity: sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==}
     engines: {node: '>=0.8.19'}
 
+  inherits@2.0.4:
+    resolution: {integrity: sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==}
+
   is-extglob@2.1.1:
     resolution: {integrity: sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==}
     engines: {node: '>=0.10.0'}
 
+  is-fullwidth-code-point@3.0.0:
+    resolution: {integrity: sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==}
+    engines: {node: '>=8'}
+
   is-glob@4.0.3:
     resolution: {integrity: sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==}
     engines: {node: '>=0.10.0'}
@@ -1262,9 +1379,19 @@ packages:
     resolution: {integrity: sha512-Fd4gABb+ycGAmKou8eMftCupSir5lRxqf4aD/vd0cD2qc4HL07OjCeuHMr8Ro4CoMaeCKDB0/ECBOVWjTwUvPQ==}
     engines: {node: '>=8'}
 
+  is-stream@2.0.1:
+    resolution: {integrity: sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg==}
+    engines: {node: '>=8'}
+
+  isarray@1.0.0:
+    resolution: {integrity: sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ==}
+
   isexe@2.0.0:
     resolution: {integrity: sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==}
 
+  jackspeak@3.4.3:
+    resolution: {integrity: sha512-OGlZQpz2yfahA/Rd1Y8Cd9SIEsqvXkLVoSw/cgwhnhFMDbsQFeZYoJJ7bIZBS9BcamUW96asq/npPWugM+RQBw==}
+
   js-yaml@4.1.0:
     resolution: {integrity: sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==}
     hasBin: true
@@ -1281,6 +1408,10 @@ packages:
   keyv@4.5.4:
     resolution: {integrity: sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw==}
 
+  lazystream@1.0.1:
+    resolution: {integrity: sha512-b94GiNHQNy6JNTrt5w6zNyffMrNkXZb3KTkCZJb2V1xaEGCk093vkZ2jk3tpaeP33/OiXC+WvK9AxUebnf5nbw==}
+    engines: {node: '>= 0.6.3'}
+
   levn@0.4.1:
     resolution: {integrity: sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==}
     engines: {node: '>= 0.8.0'}
@@ -1292,6 +1423,12 @@ packages:
   lodash.merge@4.6.2:
     resolution: {integrity: sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==}
 
+  lodash@4.17.21:
+    resolution: {integrity: sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==}
+
+  lru-cache@10.4.3:
+    resolution: {integrity: sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ==}
+
   merge2@1.4.1:
     resolution: {integrity: sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==}
     engines: {node: '>= 8'}
@@ -1303,16 +1440,28 @@ packages:
   minimatch@3.1.2:
     resolution: {integrity: sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==}
 
+  minimatch@5.1.6:
+    resolution: {integrity: sha512-lKwV/1brpG6mBUFHtb7NUmtABCb2WZZmm2wNiOA5hAb8VdCS4B3dtMWyvcoViccwAW/COERjXLt0zP1zXUN26g==}
+    engines: {node: '>=10'}
+
   minimatch@9.0.5:
     resolution: {integrity: sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==}
     engines: {node: '>=16 || 14 >=14.17'}
 
+  minipass@7.1.2:
+    resolution: {integrity: sha512-qOOzS1cBTWYF4BH8fVePDBOO9iptMnGUEZwNc/cMWnTV2nVLZ7VoNWEPHkYczZA0pdoA7dl6e7FL659nX9S2aw==}
+    engines: {node: '>=16 || 14 >=14.17'}
+
   ms@2.1.3:
     resolution: {integrity: sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==}
 
   natural-compare@1.4.0:
     resolution: {integrity: sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==}
 
+  normalize-path@3.0.0:
+    resolution: {integrity: sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==}
+    engines: {node: '>=0.10.0'}
+
   openapi3-ts@4.4.0:
     resolution: {integrity: sha512-9asTNB9IkKEzWMcHmVZE7Ts3kC9G7AFHfs8i7caD8HbI76gEjdkId4z/AkP83xdZsH7PLAnnbl47qZkXuxpArw==}
 
@@ -1328,6 +1477,9 @@ packages:
     resolution: {integrity: sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==}
     engines: {node: '>=10'}
 
+  package-json-from-dist@1.0.1:
+    resolution: {integrity: sha512-UEZIS3/by4OC8vL3P2dTXRETpebLI2NiI5vIrjaD/5UtrkFX/tNbwjTSRAGC/+7CAo2pIcBaRgWmcBBHcsaCIw==}
+
   parent-module@1.0.1:
     resolution: {integrity: sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==}
     engines: {node: '>=6'}
@@ -1340,6 +1492,10 @@ packages:
     resolution: {integrity: sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==}
     engines: {node: '>=8'}
 
+  path-scurry@1.11.1:
+    resolution: {integrity: sha512-Xa4Nw17FS9ApQFJ9umLiJS4orGjm7ZzwUrwamcGQuHSzDyth9boKDaycYdDcZDuqYATXw4HFXgaqWTctW/v1HA==}
+    engines: {node: '>=16 || 14 >=14.18'}
+
   path-type@4.0.0:
     resolution: {integrity: sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==}
     engines: {node: '>=8'}
@@ -1365,6 +1521,13 @@ packages:
     engines: {node: '>=14'}
     hasBin: true
 
+  process-nextick-args@2.0.1:
+    resolution: {integrity: sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==}
+
+  process@0.11.10:
+    resolution: {integrity: sha512-cdGef/drWFoydD1JsMzuFf8100nZl+GT+yacc2bEced5f9Rjk4z+WtFUTBu9PhOi9j/jfmBPu0mMEY4wIdAF8A==}
+    engines: {node: '>= 0.6.0'}
+
   punycode@2.3.1:
     resolution: {integrity: sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==}
     engines: {node: '>=6'}
@@ -1372,6 +1535,16 @@ packages:
   queue-microtask@1.2.3:
     resolution: {integrity: sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==}
 
+  readable-stream@2.3.8:
+    resolution: {integrity: sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA==}
+
+  readable-stream@4.7.0:
+    resolution: {integrity: sha512-oIGGmcpTLwPga8Bn6/Z75SVaH1z5dUut2ibSyAMVhmUggWpmDn2dapB0n7f8nwaSiRtepAsfJyfXIO5DCVAODg==}
+    engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0}
+
+  readdir-glob@1.1.3:
+    resolution: {integrity: sha512-v05I2k7xN8zXvPD9N+z/uhXPaj0sUFCe2rcWZIpBsqxfP7xXFQ0tipAd/wjj1YxWyWtUS5IDJpOG82JKt2EAVA==}
+
   reflect-metadata@0.2.2:
     resolution: {integrity: sha512-urBwgfrvVP/eAyXx4hluJivBKzuEbSQs9rKWCrCkbSxNv8mxPcUZKeuoF3Uy4mJl3Lwprp6yy5/39VWigZ4K6Q==}
 
@@ -1389,6 +1562,12 @@ packages:
   run-parallel@1.2.0:
     resolution: {integrity: sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==}
 
+  safe-buffer@5.1.2:
+    resolution: {integrity: sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==}
+
+  safe-buffer@5.2.1:
+    resolution: {integrity: sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==}
+
   semver@7.6.3:
     resolution: {integrity: sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A==}
     engines: {node: '>=10'}
@@ -1402,6 +1581,10 @@ packages:
     resolution: {integrity: sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==}
     engines: {node: '>=8'}
 
+  signal-exit@4.1.0:
+    resolution: {integrity: sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==}
+    engines: {node: '>=14'}
+
   slash@3.0.0:
     resolution: {integrity: sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==}
     engines: {node: '>=8'}
@@ -1413,10 +1596,31 @@ packages:
     resolution: {integrity: sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==}
     engines: {node: '>=0.10.0'}
 
+  streamx@2.22.0:
+    resolution: {integrity: sha512-sLh1evHOzBy/iWRiR6d1zRcLao4gGZr3C1kzNz4fopCOKJb6xD9ub8Mpi9Mr1R6id5o43S+d93fI48UC5uM9aw==}
+
+  string-width@4.2.3:
+    resolution: {integrity: sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==}
+    engines: {node: '>=8'}
+
+  string-width@5.1.2:
+    resolution: {integrity: sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA==}
+    engines: {node: '>=12'}
+
+  string_decoder@1.1.1:
+    resolution: {integrity: sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==}
+
+  string_decoder@1.3.0:
+    resolution: {integrity: sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==}
+
   strip-ansi@6.0.1:
     resolution: {integrity: sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==}
     engines: {node: '>=8'}
 
+  strip-ansi@7.1.0:
+    resolution: {integrity: sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==}
+    engines: {node: '>=12'}
+
   strip-json-comments@3.1.1:
     resolution: {integrity: sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==}
     engines: {node: '>=8'}
@@ -1432,6 +1636,12 @@ packages:
     resolution: {integrity: sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==}
     engines: {node: '>=8'}
 
+  tar-stream@3.1.7:
+    resolution: {integrity: sha512-qJj60CXt7IU1Ffyc3NJMjh6EkuCFej46zUqJ4J7pqYlThyd9bO0XBTmcOIhSzZJVWfsLks0+nle/j538YAW9RQ==}
+
+  text-decoder@1.2.3:
+    resolution: {integrity: sha512-3/o9z3X0X0fTupwsYvR03pJ/DjWuqqrfwBgTQzdWDiQSm9KitAyz/9WqsT2JQW7KV2m+bC2ol/zqpW37NHxLaA==}
+
   text-table@0.2.0:
     resolution: {integrity: sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw==}
 
@@ -1484,6 +1694,9 @@ packages:
   uri-js@4.4.1:
     resolution: {integrity: sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==}
 
+  util-deprecate@1.0.2:
+    resolution: {integrity: sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==}
+
   uuid@9.0.1:
     resolution: {integrity: sha512-b+1eJOlsR9K8HJpow9Ok3fiWOWSIcIzXodvv0rQjVoOVNpWMpxf1wZNpt4y9h10odCNrqnYp1OBzRktckBe3sA==}
     hasBin: true
@@ -1497,6 +1710,14 @@ packages:
     resolution: {integrity: sha512-BN22B5eaMMI9UMtjrGd5g5eCYPpCPDUy0FJXbYsaT5zYxjFOckS53SQDE3pWkVoWpHXVb3BrYcEN4Twa55B5cA==}
     engines: {node: '>=0.10.0'}
 
+  wrap-ansi@7.0.0:
+    resolution: {integrity: sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==}
+    engines: {node: '>=10'}
+
+  wrap-ansi@8.1.0:
+    resolution: {integrity: sha512-si7QWI6zUMq56bESFvagtmzMdGOtoxfR+Sez11Mobfc7tm+VkUckk9bW2UeffTGVUbOksxmSw0AA2gs8g71NCQ==}
+    engines: {node: '>=12'}
+
   yaml@2.7.0:
     resolution: {integrity: sha512-+hSoy/QHluxmC9kCIJyL/uyFmLmc+e5CFR5Wa+bpIhIj85LVb9ZH2nVnqrHoSvKogwODv0ClqZkmiSSaIH5LTA==}
     engines: {node: '>= 14'}
@@ -1506,6 +1727,10 @@ packages:
     resolution: {integrity: sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==}
     engines: {node: '>=10'}
 
+  zip-stream@6.0.1:
+    resolution: {integrity: sha512-zK7YHHz4ZXpW89AHXUPbQVGKI7uvkd3hzusTdotCg1UxyaVtg0zFJSTfW/Dq5f7OBBVnq6cZIaC8Ti4hb6dtCA==}
+    engines: {node: '>= 14'}
+
   zod@3.23.8:
     resolution: {integrity: sha512-XBx9AXhXktjUqnepgTiE5flcKIYWi/rme0Eaj+5Y0lftuGBq+jyRu/md4WnuxqgP1ubdpNCsYEYPxrzVHD8d6g==}
 
@@ -2181,6 +2406,15 @@ snapshots:
 
   '@humanwhocodes/retry@0.3.0': {}
 
+  '@isaacs/cliui@8.0.2':
+    dependencies:
+      string-width: 5.1.2
+      string-width-cjs: string-width@4.2.3
+      strip-ansi: 7.1.0
+      strip-ansi-cjs: strip-ansi@6.0.1
+      wrap-ansi: 8.1.0
+      wrap-ansi-cjs: wrap-ansi@7.0.0
+
   '@nodelib/fs.scandir@2.1.5':
     dependencies:
       '@nodelib/fs.stat': 2.0.5
@@ -2193,6 +2427,9 @@ snapshots:
       '@nodelib/fs.scandir': 2.1.5
       fastq: 1.17.1
 
+  '@pkgjs/parseargs@0.11.0':
+    optional: true
+
   '@smithy/abort-controller@4.0.1':
     dependencies:
       '@smithy/types': 4.1.0
@@ -2534,6 +2771,10 @@ snapshots:
 
   '@tokenizer/token@0.3.0': {}
 
+  '@types/archiver@6.0.3':
+    dependencies:
+      '@types/readdir-glob': 1.1.5
+
   '@types/bun@1.1.9':
     dependencies:
       bun-types: 1.1.27
@@ -2542,6 +2783,10 @@ snapshots:
     dependencies:
       undici-types: 5.26.5
 
+  '@types/readdir-glob@1.1.5':
+    dependencies:
+      '@types/node': 20.12.14
+
   '@types/ws@8.5.12':
     dependencies:
       '@types/node': 20.12.14
@@ -2627,6 +2872,10 @@ snapshots:
       '@typescript-eslint/types': 7.18.0
       eslint-visitor-keys: 3.4.3
 
+  abort-controller@3.0.0:
+    dependencies:
+      event-target-shim: 5.0.1
+
   acorn-jsx@5.3.2(acorn@8.12.1):
     dependencies:
       acorn: 8.12.1
@@ -2642,16 +2891,49 @@ snapshots:
 
   ansi-regex@5.0.1: {}
 
+  ansi-regex@6.1.0: {}
+
   ansi-styles@4.3.0:
     dependencies:
       color-convert: 2.0.1
 
+  ansi-styles@6.2.1: {}
+
+  archiver-utils@5.0.2:
+    dependencies:
+      glob: 10.4.5
+      graceful-fs: 4.2.11
+      is-stream: 2.0.1
+      lazystream: 1.0.1
+      lodash: 4.17.21
+      normalize-path: 3.0.0
+      readable-stream: 4.7.0
+
+  archiver@7.0.1:
+    dependencies:
+      archiver-utils: 5.0.2
+      async: 3.2.6
+      buffer-crc32: 1.0.0
+      readable-stream: 4.7.0
+      readdir-glob: 1.1.3
+      tar-stream: 3.1.7
+      zip-stream: 6.0.1
+
   argparse@2.0.1: {}
 
   array-union@2.1.0: {}
 
+  async@3.2.6: {}
+
+  b4a@1.6.7: {}
+
   balanced-match@1.0.2: {}
 
+  bare-events@2.5.4:
+    optional: true
+
+  base64-js@1.5.1: {}
+
   bowser@2.11.0: {}
 
   brace-expansion@1.1.11:
@@ -2667,8 +2949,15 @@ snapshots:
     dependencies:
       fill-range: 7.1.1
 
+  buffer-crc32@1.0.0: {}
+
   buffer-from@1.1.2: {}
 
+  buffer@6.0.3:
+    dependencies:
+      base64-js: 1.5.1
+      ieee754: 1.2.1
+
   bun-types@1.1.27:
     dependencies:
       '@types/node': 20.12.14
@@ -2687,8 +2976,25 @@ snapshots:
 
   color-name@1.1.4: {}
 
+  compress-commons@6.0.2:
+    dependencies:
+      crc-32: 1.2.2
+      crc32-stream: 6.0.0
+      is-stream: 2.0.1
+      normalize-path: 3.0.0
+      readable-stream: 4.7.0
+
   concat-map@0.0.1: {}
 
+  core-util-is@1.0.3: {}
+
+  crc-32@1.2.2: {}
+
+  crc32-stream@6.0.0:
+    dependencies:
+      crc-32: 1.2.2
+      readable-stream: 4.7.0
+
   cross-env@7.0.3:
     dependencies:
       cross-spawn: 7.0.3
@@ -2699,6 +3005,12 @@ snapshots:
       shebang-command: 2.0.0
       which: 2.0.2
 
+  cross-spawn@7.0.6:
+    dependencies:
+      path-key: 3.1.1
+      shebang-command: 2.0.0
+      which: 2.0.2
+
   debug@4.3.7:
     dependencies:
       ms: 2.1.3
@@ -2737,6 +3049,12 @@ snapshots:
       drizzle-orm: 0.31.4(bun-types@1.1.27)(postgres@3.4.4)
       zod: 3.23.8
 
+  eastasianwidth@0.2.0: {}
+
+  emoji-regex@8.0.0: {}
+
+  emoji-regex@9.2.2: {}
+
   esbuild-register@3.6.0(esbuild@0.19.12):
     dependencies:
       debug: 4.3.7
@@ -2867,8 +3185,14 @@ snapshots:
 
   esutils@2.0.3: {}
 
+  event-target-shim@5.0.1: {}
+
+  events@3.3.0: {}
+
   fast-deep-equal@3.1.3: {}
 
+  fast-fifo@1.3.2: {}
+
   fast-glob@3.3.2:
     dependencies:
       '@nodelib/fs.stat': 2.0.5
@@ -2920,6 +3244,11 @@ snapshots:
 
   flatted@3.3.1: {}
 
+  foreground-child@3.3.1:
+    dependencies:
+      cross-spawn: 7.0.6
+      signal-exit: 4.1.0
+
   get-tsconfig@4.8.1:
     dependencies:
       resolve-pkg-maps: 1.0.0
@@ -2932,6 +3261,15 @@ snapshots:
     dependencies:
       is-glob: 4.0.3
 
+  glob@10.4.5:
+    dependencies:
+      foreground-child: 3.3.1
+      jackspeak: 3.4.3
+      minimatch: 9.0.5
+      minipass: 7.1.2
+      package-json-from-dist: 1.0.1
+      path-scurry: 1.11.1
+
   globals@14.0.0: {}
 
   globals@15.9.0: {}
@@ -2945,6 +3283,8 @@ snapshots:
       merge2: 1.4.1
       slash: 3.0.0
 
+  graceful-fs@4.2.11: {}
+
   graphemer@1.4.0: {}
 
   has-flag@4.0.0: {}
@@ -2962,8 +3302,12 @@ snapshots:
 
   imurmurhash@0.1.4: {}
 
+  inherits@2.0.4: {}
+
   is-extglob@2.1.1: {}
 
+  is-fullwidth-code-point@3.0.0: {}
+
   is-glob@4.0.3:
     dependencies:
       is-extglob: 2.1.1
@@ -2972,8 +3316,18 @@ snapshots:
 
   is-path-inside@3.0.3: {}
 
+  is-stream@2.0.1: {}
+
+  isarray@1.0.0: {}
+
   isexe@2.0.0: {}
 
+  jackspeak@3.4.3:
+    dependencies:
+      '@isaacs/cliui': 8.0.2
+    optionalDependencies:
+      '@pkgjs/parseargs': 0.11.0
+
   js-yaml@4.1.0:
     dependencies:
       argparse: 2.0.1
@@ -2988,6 +3342,10 @@ snapshots:
     dependencies:
       json-buffer: 3.0.1
 
+  lazystream@1.0.1:
+    dependencies:
+      readable-stream: 2.3.8
+
   levn@0.4.1:
     dependencies:
       prelude-ls: 1.2.1
@@ -2999,6 +3357,10 @@ snapshots:
 
   lodash.merge@4.6.2: {}
 
+  lodash@4.17.21: {}
+
+  lru-cache@10.4.3: {}
+
   merge2@1.4.1: {}
 
   micromatch@4.0.8:
@@ -3010,14 +3372,22 @@ snapshots:
     dependencies:
       brace-expansion: 1.1.11
 
+  minimatch@5.1.6:
+    dependencies:
+      brace-expansion: 2.0.1
+
   minimatch@9.0.5:
     dependencies:
       brace-expansion: 2.0.1
 
+  minipass@7.1.2: {}
+
   ms@2.1.3: {}
 
   natural-compare@1.4.0: {}
 
+  normalize-path@3.0.0: {}
+
   openapi3-ts@4.4.0:
     dependencies:
       yaml: 2.7.0
@@ -3039,6 +3409,8 @@ snapshots:
     dependencies:
       p-limit: 3.1.0
 
+  package-json-from-dist@1.0.1: {}
+
   parent-module@1.0.1:
     dependencies:
       callsites: 3.1.0
@@ -3047,6 +3419,11 @@ snapshots:
 
   path-key@3.1.1: {}
 
+  path-scurry@1.11.1:
+    dependencies:
+      lru-cache: 10.4.3
+      minipass: 7.1.2
+
   path-type@4.0.0: {}
 
   peek-readable@6.1.1: {}
@@ -3059,10 +3436,36 @@ snapshots:
 
   prettier@3.3.3: {}
 
+  process-nextick-args@2.0.1: {}
+
+  process@0.11.10: {}
+
   punycode@2.3.1: {}
 
   queue-microtask@1.2.3: {}
 
+  readable-stream@2.3.8:
+    dependencies:
+      core-util-is: 1.0.3
+      inherits: 2.0.4
+      isarray: 1.0.0
+      process-nextick-args: 2.0.1
+      safe-buffer: 5.1.2
+      string_decoder: 1.1.1
+      util-deprecate: 1.0.2
+
+  readable-stream@4.7.0:
+    dependencies:
+      abort-controller: 3.0.0
+      buffer: 6.0.3
+      events: 3.3.0
+      process: 0.11.10
+      string_decoder: 1.3.0
+
+  readdir-glob@1.1.3:
+    dependencies:
+      minimatch: 5.1.6
+
   reflect-metadata@0.2.2: {}
 
   resolve-from@4.0.0: {}
@@ -3075,6 +3478,10 @@ snapshots:
     dependencies:
       queue-microtask: 1.2.3
 
+  safe-buffer@5.1.2: {}
+
+  safe-buffer@5.2.1: {}
+
   semver@7.6.3: {}
 
   shebang-command@2.0.0:
@@ -3083,6 +3490,8 @@ snapshots:
 
   shebang-regex@3.0.0: {}
 
+  signal-exit@4.1.0: {}
+
   slash@3.0.0: {}
 
   source-map-support@0.5.21:
@@ -3092,10 +3501,41 @@ snapshots:
 
   source-map@0.6.1: {}
 
+  streamx@2.22.0:
+    dependencies:
+      fast-fifo: 1.3.2
+      text-decoder: 1.2.3
+    optionalDependencies:
+      bare-events: 2.5.4
+
+  string-width@4.2.3:
+    dependencies:
+      emoji-regex: 8.0.0
+      is-fullwidth-code-point: 3.0.0
+      strip-ansi: 6.0.1
+
+  string-width@5.1.2:
+    dependencies:
+      eastasianwidth: 0.2.0
+      emoji-regex: 9.2.2
+      strip-ansi: 7.1.0
+
+  string_decoder@1.1.1:
+    dependencies:
+      safe-buffer: 5.1.2
+
+  string_decoder@1.3.0:
+    dependencies:
+      safe-buffer: 5.2.1
+
   strip-ansi@6.0.1:
     dependencies:
       ansi-regex: 5.0.1
 
+  strip-ansi@7.1.0:
+    dependencies:
+      ansi-regex: 6.1.0
+
   strip-json-comments@3.1.1: {}
 
   strnum@1.0.5: {}
@@ -3109,6 +3549,16 @@ snapshots:
     dependencies:
       has-flag: 4.0.0
 
+  tar-stream@3.1.7:
+    dependencies:
+      b4a: 1.6.7
+      fast-fifo: 1.3.2
+      streamx: 2.22.0
+
+  text-decoder@1.2.3:
+    dependencies:
+      b4a: 1.6.7
+
   text-table@0.2.0: {}
 
   to-regex-range@5.0.1:
@@ -3153,6 +3603,8 @@ snapshots:
     dependencies:
       punycode: 2.3.1
 
+  util-deprecate@1.0.2: {}
+
   uuid@9.0.1: {}
 
   which@2.0.2:
@@ -3161,8 +3613,26 @@ snapshots:
 
   word-wrap@1.2.5: {}
 
+  wrap-ansi@7.0.0:
+    dependencies:
+      ansi-styles: 4.3.0
+      string-width: 4.2.3
+      strip-ansi: 6.0.1
+
+  wrap-ansi@8.1.0:
+    dependencies:
+      ansi-styles: 6.2.1
+      string-width: 5.1.2
+      strip-ansi: 7.1.0
+
   yaml@2.7.0: {}
 
   yocto-queue@0.1.0: {}
 
+  zip-stream@6.0.1:
+    dependencies:
+      archiver-utils: 5.0.2
+      compress-commons: 6.0.2
+      readable-stream: 4.7.0
+
   zod@3.23.8: {}
diff --git a/src/db/migrations/0002_wakeful_taskmaster.sql b/src/db/migrations/0002_wakeful_taskmaster.sql
new file mode 100644
index 0000000..05daccf
--- /dev/null
+++ b/src/db/migrations/0002_wakeful_taskmaster.sql
@@ -0,0 +1,9 @@
+DO $$ BEGIN
+ CREATE TYPE "public"."resource_state" AS ENUM('draft', 'submitted', 'accepted');
+EXCEPTION
+ WHEN duplicate_object THEN null;
+END $$;
+--> statement-breakpoint
+ALTER TABLE "resources" DROP CONSTRAINT "resources_bucket_key_unique";--> statement-breakpoint
+ALTER TABLE "resources" ADD COLUMN "resource_state" "resource_state" DEFAULT 'draft' NOT NULL;--> statement-breakpoint
+ALTER TABLE "resources" DROP COLUMN IF EXISTS "bucket_key";
\ No newline at end of file
diff --git a/src/db/migrations/meta/0002_snapshot.json b/src/db/migrations/meta/0002_snapshot.json
new file mode 100644
index 0000000..b9f4b8a
--- /dev/null
+++ b/src/db/migrations/meta/0002_snapshot.json
@@ -0,0 +1,2686 @@
+{
+  "id": "a2249c37-5786-4d0f-ba5e-1c3b465aa103",
+  "prevId": "8bb70cc6-4e1b-4435-baaa-8d1a6917165f",
+  "version": "7",
+  "dialect": "postgresql",
+  "tables": {
+    "public.achievements": {
+      "name": "achievements",
+      "schema": "",
+      "columns": {
+        "id": {
+          "name": "id",
+          "type": "serial",
+          "primaryKey": true,
+          "notNull": true
+        },
+        "name": {
+          "name": "name",
+          "type": "varchar(255)",
+          "primaryKey": false,
+          "notNull": true
+        },
+        "description": {
+          "name": "description",
+          "type": "text",
+          "primaryKey": false,
+          "notNull": false
+        },
+        "reward_experience": {
+          "name": "reward_experience",
+          "type": "numeric",
+          "primaryKey": false,
+          "notNull": false
+        },
+        "reward_points": {
+          "name": "reward_points",
+          "type": "numeric",
+          "primaryKey": false,
+          "notNull": false
+        },
+        "state": {
+          "name": "state",
+          "type": "state",
+          "typeSchema": "public",
+          "primaryKey": false,
+          "notNull": true,
+          "default": "'inactive'"
+        },
+        "repeatable": {
+          "name": "repeatable",
+          "type": "integer",
+          "primaryKey": false,
+          "notNull": true
+        },
+        "is_resettable": {
+          "name": "is_resettable",
+          "type": "boolean",
+          "primaryKey": false,
+          "notNull": true
+        },
+        "created_at": {
+          "name": "created_at",
+          "type": "timestamp",
+          "primaryKey": false,
+          "notNull": true,
+          "default": "now()"
+        },
+        "updated_at": {
+          "name": "updated_at",
+          "type": "timestamp",
+          "primaryKey": false,
+          "notNull": true,
+          "default": "now()"
+        }
+      },
+      "indexes": {},
+      "foreignKeys": {},
+      "compositePrimaryKeys": {},
+      "uniqueConstraints": {
+        "achievements_id_unique": {
+          "name": "achievements_id_unique",
+          "nullsNotDistinct": false,
+          "columns": [
+            "id"
+          ]
+        }
+      }
+    },
+    "public.actions": {
+      "name": "actions",
+      "schema": "",
+      "columns": {
+        "id": {
+          "name": "id",
+          "type": "serial",
+          "primaryKey": true,
+          "notNull": true
+        },
+        "name": {
+          "name": "name",
+          "type": "varchar(255)",
+          "primaryKey": false,
+          "notNull": true
+        },
+        "created_at": {
+          "name": "created_at",
+          "type": "timestamp",
+          "primaryKey": false,
+          "notNull": true,
+          "default": "now()"
+        },
+        "updated_at": {
+          "name": "updated_at",
+          "type": "timestamp",
+          "primaryKey": false,
+          "notNull": true,
+          "default": "now()"
+        }
+      },
+      "indexes": {},
+      "foreignKeys": {},
+      "compositePrimaryKeys": {},
+      "uniqueConstraints": {
+        "actions_id_unique": {
+          "name": "actions_id_unique",
+          "nullsNotDistinct": false,
+          "columns": [
+            "id"
+          ]
+        }
+      }
+    },
+    "public.collection_likes": {
+      "name": "collection_likes",
+      "schema": "",
+      "columns": {
+        "id": {
+          "name": "id",
+          "type": "serial",
+          "primaryKey": true,
+          "notNull": true
+        },
+        "user_id": {
+          "name": "user_id",
+          "type": "integer",
+          "primaryKey": false,
+          "notNull": true
+        },
+        "collection": {
+          "name": "collection",
+          "type": "integer",
+          "primaryKey": false,
+          "notNull": true
+        }
+      },
+      "indexes": {},
+      "foreignKeys": {
+        "collection_likes_user_id_users_id_fk": {
+          "name": "collection_likes_user_id_users_id_fk",
+          "tableFrom": "collection_likes",
+          "tableTo": "users",
+          "columnsFrom": [
+            "user_id"
+          ],
+          "columnsTo": [
+            "id"
+          ],
+          "onDelete": "cascade",
+          "onUpdate": "no action"
+        },
+        "collection_likes_collection_collections_id_fk": {
+          "name": "collection_likes_collection_collections_id_fk",
+          "tableFrom": "collection_likes",
+          "tableTo": "collections",
+          "columnsFrom": [
+            "collection"
+          ],
+          "columnsTo": [
+            "id"
+          ],
+          "onDelete": "cascade",
+          "onUpdate": "no action"
+        }
+      },
+      "compositePrimaryKeys": {},
+      "uniqueConstraints": {
+        "collection_likes_id_unique": {
+          "name": "collection_likes_id_unique",
+          "nullsNotDistinct": false,
+          "columns": [
+            "id"
+          ]
+        }
+      }
+    },
+    "public.collection_resources": {
+      "name": "collection_resources",
+      "schema": "",
+      "columns": {
+        "id": {
+          "name": "id",
+          "type": "serial",
+          "primaryKey": true,
+          "notNull": true
+        },
+        "collection_id": {
+          "name": "collection_id",
+          "type": "integer",
+          "primaryKey": false,
+          "notNull": true
+        },
+        "resource_id": {
+          "name": "resource_id",
+          "type": "integer",
+          "primaryKey": false,
+          "notNull": true
+        }
+      },
+      "indexes": {},
+      "foreignKeys": {
+        "collection_resources_collection_id_collections_id_fk": {
+          "name": "collection_resources_collection_id_collections_id_fk",
+          "tableFrom": "collection_resources",
+          "tableTo": "collections",
+          "columnsFrom": [
+            "collection_id"
+          ],
+          "columnsTo": [
+            "id"
+          ],
+          "onDelete": "cascade",
+          "onUpdate": "no action"
+        },
+        "collection_resources_resource_id_resources_id_fk": {
+          "name": "collection_resources_resource_id_resources_id_fk",
+          "tableFrom": "collection_resources",
+          "tableTo": "resources",
+          "columnsFrom": [
+            "resource_id"
+          ],
+          "columnsTo": [
+            "id"
+          ],
+          "onDelete": "cascade",
+          "onUpdate": "no action"
+        }
+      },
+      "compositePrimaryKeys": {},
+      "uniqueConstraints": {
+        "collection_resources_id_unique": {
+          "name": "collection_resources_id_unique",
+          "nullsNotDistinct": false,
+          "columns": [
+            "id"
+          ]
+        }
+      }
+    },
+    "public.collection_stats": {
+      "name": "collection_stats",
+      "schema": "",
+      "columns": {
+        "id": {
+          "name": "id",
+          "type": "serial",
+          "primaryKey": true,
+          "notNull": true
+        },
+        "views": {
+          "name": "views",
+          "type": "integer",
+          "primaryKey": false,
+          "notNull": true,
+          "default": 0
+        },
+        "downloads": {
+          "name": "downloads",
+          "type": "integer",
+          "primaryKey": false,
+          "notNull": true,
+          "default": 0
+        },
+        "likes": {
+          "name": "likes",
+          "type": "integer",
+          "primaryKey": false,
+          "notNull": true,
+          "default": 0
+        },
+        "shares": {
+          "name": "shares",
+          "type": "integer",
+          "primaryKey": false,
+          "notNull": true,
+          "default": 0
+        },
+        "score": {
+          "name": "score",
+          "type": "numeric",
+          "primaryKey": false,
+          "notNull": true,
+          "default": "'0.0'"
+        },
+        "follows": {
+          "name": "follows",
+          "type": "integer",
+          "primaryKey": false,
+          "notNull": true,
+          "default": 0
+        }
+      },
+      "indexes": {},
+      "foreignKeys": {},
+      "compositePrimaryKeys": {},
+      "uniqueConstraints": {
+        "collection_stats_id_unique": {
+          "name": "collection_stats_id_unique",
+          "nullsNotDistinct": false,
+          "columns": [
+            "id"
+          ]
+        }
+      }
+    },
+    "public.collections": {
+      "name": "collections",
+      "schema": "",
+      "columns": {
+        "id": {
+          "name": "id",
+          "type": "serial",
+          "primaryKey": true,
+          "notNull": true
+        },
+        "name": {
+          "name": "name",
+          "type": "varchar(255)",
+          "primaryKey": false,
+          "notNull": false
+        },
+        "description": {
+          "name": "description",
+          "type": "text",
+          "primaryKey": false,
+          "notNull": false
+        },
+        "is_private": {
+          "name": "is_private",
+          "type": "boolean",
+          "primaryKey": false,
+          "notNull": false,
+          "default": false
+        },
+        "is_active": {
+          "name": "is_active",
+          "type": "boolean",
+          "primaryKey": false,
+          "notNull": false,
+          "default": true
+        },
+        "created_at": {
+          "name": "created_at",
+          "type": "timestamp",
+          "primaryKey": false,
+          "notNull": true,
+          "default": "now()"
+        },
+        "updated_at": {
+          "name": "updated_at",
+          "type": "timestamp",
+          "primaryKey": false,
+          "notNull": true,
+          "default": "now()"
+        },
+        "deleted_at": {
+          "name": "deleted_at",
+          "type": "timestamp",
+          "primaryKey": false,
+          "notNull": false
+        },
+        "thumbnail": {
+          "name": "thumbnail",
+          "type": "varchar(255)",
+          "primaryKey": false,
+          "notNull": false
+        },
+        "user_id": {
+          "name": "user_id",
+          "type": "integer",
+          "primaryKey": false,
+          "notNull": true
+        },
+        "collection_stats_id": {
+          "name": "collection_stats_id",
+          "type": "integer",
+          "primaryKey": false,
+          "notNull": true
+        }
+      },
+      "indexes": {},
+      "foreignKeys": {
+        "collections_user_id_users_id_fk": {
+          "name": "collections_user_id_users_id_fk",
+          "tableFrom": "collections",
+          "tableTo": "users",
+          "columnsFrom": [
+            "user_id"
+          ],
+          "columnsTo": [
+            "id"
+          ],
+          "onDelete": "cascade",
+          "onUpdate": "no action"
+        },
+        "collections_collection_stats_id_collection_stats_id_fk": {
+          "name": "collections_collection_stats_id_collection_stats_id_fk",
+          "tableFrom": "collections",
+          "tableTo": "collection_stats",
+          "columnsFrom": [
+            "collection_stats_id"
+          ],
+          "columnsTo": [
+            "id"
+          ],
+          "onDelete": "cascade",
+          "onUpdate": "no action"
+        }
+      },
+      "compositePrimaryKeys": {},
+      "uniqueConstraints": {
+        "collections_id_unique": {
+          "name": "collections_id_unique",
+          "nullsNotDistinct": false,
+          "columns": [
+            "id"
+          ]
+        }
+      }
+    },
+    "public.commentReply": {
+      "name": "commentReply",
+      "schema": "",
+      "columns": {
+        "id": {
+          "name": "id",
+          "type": "serial",
+          "primaryKey": true,
+          "notNull": true
+        },
+        "user_id": {
+          "name": "user_id",
+          "type": "integer",
+          "primaryKey": false,
+          "notNull": true
+        },
+        "comment_id": {
+          "name": "comment_id",
+          "type": "integer",
+          "primaryKey": false,
+          "notNull": true
+        },
+        "text": {
+          "name": "text",
+          "type": "text",
+          "primaryKey": false,
+          "notNull": true
+        },
+        "created_at": {
+          "name": "created_at",
+          "type": "timestamp",
+          "primaryKey": false,
+          "notNull": true,
+          "default": "now()"
+        },
+        "deleted_at": {
+          "name": "deleted_at",
+          "type": "timestamp",
+          "primaryKey": false,
+          "notNull": false
+        },
+        "update_at": {
+          "name": "update_at",
+          "type": "timestamp",
+          "primaryKey": false,
+          "notNull": true,
+          "default": "now()"
+        }
+      },
+      "indexes": {},
+      "foreignKeys": {
+        "commentReply_user_id_users_id_fk": {
+          "name": "commentReply_user_id_users_id_fk",
+          "tableFrom": "commentReply",
+          "tableTo": "users",
+          "columnsFrom": [
+            "user_id"
+          ],
+          "columnsTo": [
+            "id"
+          ],
+          "onDelete": "cascade",
+          "onUpdate": "no action"
+        },
+        "commentReply_comment_id_comments_id_fk": {
+          "name": "commentReply_comment_id_comments_id_fk",
+          "tableFrom": "commentReply",
+          "tableTo": "comments",
+          "columnsFrom": [
+            "comment_id"
+          ],
+          "columnsTo": [
+            "id"
+          ],
+          "onDelete": "cascade",
+          "onUpdate": "no action"
+        }
+      },
+      "compositePrimaryKeys": {},
+      "uniqueConstraints": {
+        "commentReply_id_unique": {
+          "name": "commentReply_id_unique",
+          "nullsNotDistinct": false,
+          "columns": [
+            "id"
+          ]
+        }
+      }
+    },
+    "public.comments": {
+      "name": "comments",
+      "schema": "",
+      "columns": {
+        "id": {
+          "name": "id",
+          "type": "serial",
+          "primaryKey": true,
+          "notNull": true
+        },
+        "user_id": {
+          "name": "user_id",
+          "type": "integer",
+          "primaryKey": false,
+          "notNull": true
+        },
+        "resource_id": {
+          "name": "resource_id",
+          "type": "integer",
+          "primaryKey": false,
+          "notNull": true
+        },
+        "text": {
+          "name": "text",
+          "type": "text",
+          "primaryKey": false,
+          "notNull": true
+        },
+        "created_at": {
+          "name": "created_at",
+          "type": "timestamp",
+          "primaryKey": false,
+          "notNull": true,
+          "default": "now()"
+        },
+        "deleted_at": {
+          "name": "deleted_at",
+          "type": "timestamp",
+          "primaryKey": false,
+          "notNull": false
+        },
+        "update_at": {
+          "name": "update_at",
+          "type": "timestamp",
+          "primaryKey": false,
+          "notNull": true,
+          "default": "now()"
+        }
+      },
+      "indexes": {},
+      "foreignKeys": {
+        "comments_user_id_users_id_fk": {
+          "name": "comments_user_id_users_id_fk",
+          "tableFrom": "comments",
+          "tableTo": "users",
+          "columnsFrom": [
+            "user_id"
+          ],
+          "columnsTo": [
+            "id"
+          ],
+          "onDelete": "cascade",
+          "onUpdate": "no action"
+        },
+        "comments_resource_id_resources_id_fk": {
+          "name": "comments_resource_id_resources_id_fk",
+          "tableFrom": "comments",
+          "tableTo": "resources",
+          "columnsFrom": [
+            "resource_id"
+          ],
+          "columnsTo": [
+            "id"
+          ],
+          "onDelete": "cascade",
+          "onUpdate": "no action"
+        }
+      },
+      "compositePrimaryKeys": {},
+      "uniqueConstraints": {
+        "comments_id_unique": {
+          "name": "comments_id_unique",
+          "nullsNotDistinct": false,
+          "columns": [
+            "id"
+          ]
+        }
+      }
+    },
+    "public.complaints": {
+      "name": "complaints",
+      "schema": "",
+      "columns": {
+        "id": {
+          "name": "id",
+          "type": "serial",
+          "primaryKey": true,
+          "notNull": true
+        },
+        "state": {
+          "name": "state",
+          "type": "state",
+          "typeSchema": "public",
+          "primaryKey": false,
+          "notNull": true,
+          "default": "'under_review'"
+        },
+        "description": {
+          "name": "description",
+          "type": "text",
+          "primaryKey": false,
+          "notNull": true
+        },
+        "denouncer_id": {
+          "name": "denouncer_id",
+          "type": "integer",
+          "primaryKey": false,
+          "notNull": true
+        },
+        "resource_id": {
+          "name": "resource_id",
+          "type": "integer",
+          "primaryKey": false,
+          "notNull": true
+        },
+        "collection_id": {
+          "name": "collection_id",
+          "type": "integer",
+          "primaryKey": false,
+          "notNull": false
+        },
+        "user_id": {
+          "name": "user_id",
+          "type": "integer",
+          "primaryKey": false,
+          "notNull": false
+        },
+        "evaluated_at": {
+          "name": "evaluated_at",
+          "type": "timestamp",
+          "primaryKey": false,
+          "notNull": false
+        },
+        "created_at": {
+          "name": "created_at",
+          "type": "timestamp",
+          "primaryKey": false,
+          "notNull": true,
+          "default": "now()"
+        },
+        "q1": {
+          "name": "q1",
+          "type": "boolean",
+          "primaryKey": false,
+          "notNull": false
+        },
+        "q2": {
+          "name": "q2",
+          "type": "boolean",
+          "primaryKey": false,
+          "notNull": false
+        },
+        "q3": {
+          "name": "q3",
+          "type": "boolean",
+          "primaryKey": false,
+          "notNull": false
+        },
+        "q4": {
+          "name": "q4",
+          "type": "boolean",
+          "primaryKey": false,
+          "notNull": false
+        }
+      },
+      "indexes": {},
+      "foreignKeys": {
+        "complaints_denouncer_id_users_id_fk": {
+          "name": "complaints_denouncer_id_users_id_fk",
+          "tableFrom": "complaints",
+          "tableTo": "users",
+          "columnsFrom": [
+            "denouncer_id"
+          ],
+          "columnsTo": [
+            "id"
+          ],
+          "onDelete": "cascade",
+          "onUpdate": "no action"
+        },
+        "complaints_resource_id_resources_id_fk": {
+          "name": "complaints_resource_id_resources_id_fk",
+          "tableFrom": "complaints",
+          "tableTo": "resources",
+          "columnsFrom": [
+            "resource_id"
+          ],
+          "columnsTo": [
+            "id"
+          ],
+          "onDelete": "cascade",
+          "onUpdate": "no action"
+        },
+        "complaints_collection_id_collections_id_fk": {
+          "name": "complaints_collection_id_collections_id_fk",
+          "tableFrom": "complaints",
+          "tableTo": "collections",
+          "columnsFrom": [
+            "collection_id"
+          ],
+          "columnsTo": [
+            "id"
+          ],
+          "onDelete": "cascade",
+          "onUpdate": "no action"
+        },
+        "complaints_user_id_users_id_fk": {
+          "name": "complaints_user_id_users_id_fk",
+          "tableFrom": "complaints",
+          "tableTo": "users",
+          "columnsFrom": [
+            "user_id"
+          ],
+          "columnsTo": [
+            "id"
+          ],
+          "onDelete": "cascade",
+          "onUpdate": "no action"
+        }
+      },
+      "compositePrimaryKeys": {},
+      "uniqueConstraints": {
+        "complaints_id_unique": {
+          "name": "complaints_id_unique",
+          "nullsNotDistinct": false,
+          "columns": [
+            "id"
+          ]
+        }
+      }
+    },
+    "public.educational_stages": {
+      "name": "educational_stages",
+      "schema": "",
+      "columns": {
+        "id": {
+          "name": "id",
+          "type": "serial",
+          "primaryKey": true,
+          "notNull": true
+        },
+        "name": {
+          "name": "name",
+          "type": "varchar(255)",
+          "primaryKey": false,
+          "notNull": true
+        }
+      },
+      "indexes": {},
+      "foreignKeys": {},
+      "compositePrimaryKeys": {},
+      "uniqueConstraints": {
+        "educational_stages_id_unique": {
+          "name": "educational_stages_id_unique",
+          "nullsNotDistinct": false,
+          "columns": [
+            "id"
+          ]
+        }
+      }
+    },
+    "public.followers": {
+      "name": "followers",
+      "schema": "",
+      "columns": {
+        "id": {
+          "name": "id",
+          "type": "serial",
+          "primaryKey": true,
+          "notNull": true
+        },
+        "user_id": {
+          "name": "user_id",
+          "type": "integer",
+          "primaryKey": false,
+          "notNull": true
+        },
+        "follower_id": {
+          "name": "follower_id",
+          "type": "integer",
+          "primaryKey": false,
+          "notNull": true
+        }
+      },
+      "indexes": {},
+      "foreignKeys": {
+        "followers_user_id_users_id_fk": {
+          "name": "followers_user_id_users_id_fk",
+          "tableFrom": "followers",
+          "tableTo": "users",
+          "columnsFrom": [
+            "user_id"
+          ],
+          "columnsTo": [
+            "id"
+          ],
+          "onDelete": "cascade",
+          "onUpdate": "no action"
+        },
+        "followers_follower_id_users_id_fk": {
+          "name": "followers_follower_id_users_id_fk",
+          "tableFrom": "followers",
+          "tableTo": "users",
+          "columnsFrom": [
+            "follower_id"
+          ],
+          "columnsTo": [
+            "id"
+          ],
+          "onDelete": "cascade",
+          "onUpdate": "no action"
+        }
+      },
+      "compositePrimaryKeys": {},
+      "uniqueConstraints": {
+        "followers_id_unique": {
+          "name": "followers_id_unique",
+          "nullsNotDistinct": false,
+          "columns": [
+            "id"
+          ]
+        }
+      }
+    },
+    "public.institutions": {
+      "name": "institutions",
+      "schema": "",
+      "columns": {
+        "id": {
+          "name": "id",
+          "type": "serial",
+          "primaryKey": true,
+          "notNull": true
+        },
+        "name": {
+          "name": "name",
+          "type": "varchar(255)",
+          "primaryKey": false,
+          "notNull": true
+        },
+        "uf": {
+          "name": "uf",
+          "type": "varchar(2)",
+          "primaryKey": false,
+          "notNull": false
+        },
+        "city": {
+          "name": "city",
+          "type": "varchar(255)",
+          "primaryKey": false,
+          "notNull": false
+        },
+        "cep": {
+          "name": "cep",
+          "type": "varchar(10)",
+          "primaryKey": false,
+          "notNull": false
+        },
+        "created_at": {
+          "name": "created_at",
+          "type": "timestamp",
+          "primaryKey": false,
+          "notNull": true,
+          "default": "now()"
+        },
+        "updated_at": {
+          "name": "updated_at",
+          "type": "timestamp",
+          "primaryKey": false,
+          "notNull": true,
+          "default": "now()"
+        }
+      },
+      "indexes": {},
+      "foreignKeys": {},
+      "compositePrimaryKeys": {},
+      "uniqueConstraints": {
+        "institutions_id_unique": {
+          "name": "institutions_id_unique",
+          "nullsNotDistinct": false,
+          "columns": [
+            "id"
+          ]
+        }
+      }
+    },
+    "public.items": {
+      "name": "items",
+      "schema": "",
+      "columns": {
+        "id": {
+          "name": "id",
+          "type": "serial",
+          "primaryKey": true,
+          "notNull": true
+        },
+        "name": {
+          "name": "name",
+          "type": "varchar(255)",
+          "primaryKey": false,
+          "notNull": true
+        },
+        "price": {
+          "name": "price",
+          "type": "numeric",
+          "primaryKey": false,
+          "notNull": false
+        },
+        "discount": {
+          "name": "discount",
+          "type": "numeric",
+          "primaryKey": false,
+          "notNull": false
+        },
+        "description": {
+          "name": "description",
+          "type": "text",
+          "primaryKey": false,
+          "notNull": false
+        },
+        "is_active": {
+          "name": "is_active",
+          "type": "boolean",
+          "primaryKey": false,
+          "notNull": false,
+          "default": false
+        },
+        "created_at": {
+          "name": "created_at",
+          "type": "timestamp",
+          "primaryKey": false,
+          "notNull": true,
+          "default": "now()"
+        },
+        "updated_at": {
+          "name": "updated_at",
+          "type": "timestamp",
+          "primaryKey": false,
+          "notNull": true,
+          "default": "now()"
+        },
+        "achievement_id": {
+          "name": "achievement_id",
+          "type": "integer",
+          "primaryKey": false,
+          "notNull": false
+        }
+      },
+      "indexes": {},
+      "foreignKeys": {
+        "items_achievement_id_achievements_id_fk": {
+          "name": "items_achievement_id_achievements_id_fk",
+          "tableFrom": "items",
+          "tableTo": "achievements",
+          "columnsFrom": [
+            "achievement_id"
+          ],
+          "columnsTo": [
+            "id"
+          ],
+          "onDelete": "no action",
+          "onUpdate": "no action"
+        }
+      },
+      "compositePrimaryKeys": {},
+      "uniqueConstraints": {
+        "items_id_unique": {
+          "name": "items_id_unique",
+          "nullsNotDistinct": false,
+          "columns": [
+            "id"
+          ]
+        }
+      }
+    },
+    "public.languages": {
+      "name": "languages",
+      "schema": "",
+      "columns": {
+        "id": {
+          "name": "id",
+          "type": "serial",
+          "primaryKey": true,
+          "notNull": true
+        },
+        "name": {
+          "name": "name",
+          "type": "varchar(255)",
+          "primaryKey": false,
+          "notNull": true
+        },
+        "code": {
+          "name": "code",
+          "type": "varchar(10)",
+          "primaryKey": false,
+          "notNull": true
+        }
+      },
+      "indexes": {},
+      "foreignKeys": {},
+      "compositePrimaryKeys": {},
+      "uniqueConstraints": {
+        "languages_id_unique": {
+          "name": "languages_id_unique",
+          "nullsNotDistinct": false,
+          "columns": [
+            "id"
+          ]
+        },
+        "languages_code_unique": {
+          "name": "languages_code_unique",
+          "nullsNotDistinct": false,
+          "columns": [
+            "code"
+          ]
+        }
+      }
+    },
+    "public.licenses": {
+      "name": "licenses",
+      "schema": "",
+      "columns": {
+        "id": {
+          "name": "id",
+          "type": "serial",
+          "primaryKey": true,
+          "notNull": true
+        },
+        "name": {
+          "name": "name",
+          "type": "varchar(255)",
+          "primaryKey": false,
+          "notNull": true
+        },
+        "description": {
+          "name": "description",
+          "type": "text",
+          "primaryKey": false,
+          "notNull": true
+        },
+        "url": {
+          "name": "url",
+          "type": "varchar(255)",
+          "primaryKey": false,
+          "notNull": true
+        }
+      },
+      "indexes": {},
+      "foreignKeys": {},
+      "compositePrimaryKeys": {},
+      "uniqueConstraints": {
+        "licenses_id_unique": {
+          "name": "licenses_id_unique",
+          "nullsNotDistinct": false,
+          "columns": [
+            "id"
+          ]
+        }
+      }
+    },
+    "public.notifications": {
+      "name": "notifications",
+      "schema": "",
+      "columns": {
+        "id": {
+          "name": "id",
+          "type": "serial",
+          "primaryKey": true,
+          "notNull": true
+        },
+        "action_id": {
+          "name": "action_id",
+          "type": "integer",
+          "primaryKey": false,
+          "notNull": true
+        },
+        "actor_user_id": {
+          "name": "actor_user_id",
+          "type": "integer",
+          "primaryKey": false,
+          "notNull": true
+        },
+        "target_user_id": {
+          "name": "target_user_id",
+          "type": "integer",
+          "primaryKey": false,
+          "notNull": true
+        },
+        "target_resource_id": {
+          "name": "target_resource_id",
+          "type": "integer",
+          "primaryKey": false,
+          "notNull": false
+        },
+        "target_collection_id": {
+          "name": "target_collection_id",
+          "type": "integer",
+          "primaryKey": false,
+          "notNull": false
+        },
+        "created_at": {
+          "name": "created_at",
+          "type": "timestamp",
+          "primaryKey": false,
+          "notNull": true,
+          "default": "now()"
+        },
+        "updated_at": {
+          "name": "updated_at",
+          "type": "timestamp",
+          "primaryKey": false,
+          "notNull": true,
+          "default": "now()"
+        }
+      },
+      "indexes": {},
+      "foreignKeys": {
+        "notifications_action_id_actions_id_fk": {
+          "name": "notifications_action_id_actions_id_fk",
+          "tableFrom": "notifications",
+          "tableTo": "actions",
+          "columnsFrom": [
+            "action_id"
+          ],
+          "columnsTo": [
+            "id"
+          ],
+          "onDelete": "cascade",
+          "onUpdate": "no action"
+        },
+        "notifications_actor_user_id_users_id_fk": {
+          "name": "notifications_actor_user_id_users_id_fk",
+          "tableFrom": "notifications",
+          "tableTo": "users",
+          "columnsFrom": [
+            "actor_user_id"
+          ],
+          "columnsTo": [
+            "id"
+          ],
+          "onDelete": "cascade",
+          "onUpdate": "no action"
+        },
+        "notifications_target_user_id_users_id_fk": {
+          "name": "notifications_target_user_id_users_id_fk",
+          "tableFrom": "notifications",
+          "tableTo": "users",
+          "columnsFrom": [
+            "target_user_id"
+          ],
+          "columnsTo": [
+            "id"
+          ],
+          "onDelete": "cascade",
+          "onUpdate": "no action"
+        },
+        "notifications_target_resource_id_resources_id_fk": {
+          "name": "notifications_target_resource_id_resources_id_fk",
+          "tableFrom": "notifications",
+          "tableTo": "resources",
+          "columnsFrom": [
+            "target_resource_id"
+          ],
+          "columnsTo": [
+            "id"
+          ],
+          "onDelete": "cascade",
+          "onUpdate": "no action"
+        },
+        "notifications_target_collection_id_collections_id_fk": {
+          "name": "notifications_target_collection_id_collections_id_fk",
+          "tableFrom": "notifications",
+          "tableTo": "collections",
+          "columnsFrom": [
+            "target_collection_id"
+          ],
+          "columnsTo": [
+            "id"
+          ],
+          "onDelete": "cascade",
+          "onUpdate": "no action"
+        }
+      },
+      "compositePrimaryKeys": {},
+      "uniqueConstraints": {
+        "notifications_id_unique": {
+          "name": "notifications_id_unique",
+          "nullsNotDistinct": false,
+          "columns": [
+            "id"
+          ]
+        }
+      }
+    },
+    "public.object_types": {
+      "name": "object_types",
+      "schema": "",
+      "columns": {
+        "id": {
+          "name": "id",
+          "type": "serial",
+          "primaryKey": true,
+          "notNull": true
+        },
+        "name": {
+          "name": "name",
+          "type": "varchar(255)",
+          "primaryKey": false,
+          "notNull": true
+        }
+      },
+      "indexes": {},
+      "foreignKeys": {},
+      "compositePrimaryKeys": {},
+      "uniqueConstraints": {
+        "object_types_id_unique": {
+          "name": "object_types_id_unique",
+          "nullsNotDistinct": false,
+          "columns": [
+            "id"
+          ]
+        }
+      }
+    },
+    "public.reset_tickets": {
+      "name": "reset_tickets",
+      "schema": "",
+      "columns": {
+        "id": {
+          "name": "id",
+          "type": "serial",
+          "primaryKey": true,
+          "notNull": true
+        },
+        "user_id": {
+          "name": "user_id",
+          "type": "integer",
+          "primaryKey": false,
+          "notNull": true
+        },
+        "token_hash": {
+          "name": "token_hash",
+          "type": "varchar(255)",
+          "primaryKey": false,
+          "notNull": true
+        },
+        "expiration_date": {
+          "name": "expiration_date",
+          "type": "timestamp",
+          "primaryKey": false,
+          "notNull": true
+        },
+        "token_used": {
+          "name": "token_used",
+          "type": "boolean",
+          "primaryKey": false,
+          "notNull": true,
+          "default": false
+        },
+        "valid_token": {
+          "name": "valid_token",
+          "type": "boolean",
+          "primaryKey": false,
+          "notNull": true,
+          "default": true
+        },
+        "created_at": {
+          "name": "created_at",
+          "type": "timestamp",
+          "primaryKey": false,
+          "notNull": true,
+          "default": "now()"
+        },
+        "updated_at": {
+          "name": "updated_at",
+          "type": "timestamp",
+          "primaryKey": false,
+          "notNull": true,
+          "default": "now()"
+        }
+      },
+      "indexes": {},
+      "foreignKeys": {
+        "reset_tickets_user_id_users_id_fk": {
+          "name": "reset_tickets_user_id_users_id_fk",
+          "tableFrom": "reset_tickets",
+          "tableTo": "users",
+          "columnsFrom": [
+            "user_id"
+          ],
+          "columnsTo": [
+            "id"
+          ],
+          "onDelete": "cascade",
+          "onUpdate": "no action"
+        }
+      },
+      "compositePrimaryKeys": {},
+      "uniqueConstraints": {
+        "reset_tickets_id_unique": {
+          "name": "reset_tickets_id_unique",
+          "nullsNotDistinct": false,
+          "columns": [
+            "id"
+          ]
+        }
+      }
+    },
+    "public.resource_educational_stages": {
+      "name": "resource_educational_stages",
+      "schema": "",
+      "columns": {
+        "id": {
+          "name": "id",
+          "type": "serial",
+          "primaryKey": true,
+          "notNull": true
+        },
+        "resource_id": {
+          "name": "resource_id",
+          "type": "integer",
+          "primaryKey": false,
+          "notNull": true
+        },
+        "educational_stage_id": {
+          "name": "educational_stage_id",
+          "type": "integer",
+          "primaryKey": false,
+          "notNull": true
+        }
+      },
+      "indexes": {},
+      "foreignKeys": {
+        "resource_educational_stages_resource_id_resources_id_fk": {
+          "name": "resource_educational_stages_resource_id_resources_id_fk",
+          "tableFrom": "resource_educational_stages",
+          "tableTo": "resources",
+          "columnsFrom": [
+            "resource_id"
+          ],
+          "columnsTo": [
+            "id"
+          ],
+          "onDelete": "cascade",
+          "onUpdate": "no action"
+        },
+        "resource_educational_stages_educational_stage_id_educational_stages_id_fk": {
+          "name": "resource_educational_stages_educational_stage_id_educational_stages_id_fk",
+          "tableFrom": "resource_educational_stages",
+          "tableTo": "educational_stages",
+          "columnsFrom": [
+            "educational_stage_id"
+          ],
+          "columnsTo": [
+            "id"
+          ],
+          "onDelete": "cascade",
+          "onUpdate": "no action"
+        }
+      },
+      "compositePrimaryKeys": {},
+      "uniqueConstraints": {
+        "resource_educational_stages_id_unique": {
+          "name": "resource_educational_stages_id_unique",
+          "nullsNotDistinct": false,
+          "columns": [
+            "id"
+          ]
+        }
+      }
+    },
+    "public.resource_languages": {
+      "name": "resource_languages",
+      "schema": "",
+      "columns": {
+        "id": {
+          "name": "id",
+          "type": "serial",
+          "primaryKey": true,
+          "notNull": true
+        },
+        "resource_id": {
+          "name": "resource_id",
+          "type": "integer",
+          "primaryKey": false,
+          "notNull": true
+        },
+        "language_id": {
+          "name": "language_id",
+          "type": "integer",
+          "primaryKey": false,
+          "notNull": true
+        }
+      },
+      "indexes": {},
+      "foreignKeys": {
+        "resource_languages_resource_id_resources_id_fk": {
+          "name": "resource_languages_resource_id_resources_id_fk",
+          "tableFrom": "resource_languages",
+          "tableTo": "resources",
+          "columnsFrom": [
+            "resource_id"
+          ],
+          "columnsTo": [
+            "id"
+          ],
+          "onDelete": "cascade",
+          "onUpdate": "no action"
+        },
+        "resource_languages_language_id_languages_id_fk": {
+          "name": "resource_languages_language_id_languages_id_fk",
+          "tableFrom": "resource_languages",
+          "tableTo": "languages",
+          "columnsFrom": [
+            "language_id"
+          ],
+          "columnsTo": [
+            "id"
+          ],
+          "onDelete": "cascade",
+          "onUpdate": "no action"
+        }
+      },
+      "compositePrimaryKeys": {},
+      "uniqueConstraints": {
+        "resource_languages_id_unique": {
+          "name": "resource_languages_id_unique",
+          "nullsNotDistinct": false,
+          "columns": [
+            "id"
+          ]
+        }
+      }
+    },
+    "public.resource_likes": {
+      "name": "resource_likes",
+      "schema": "",
+      "columns": {
+        "id": {
+          "name": "id",
+          "type": "serial",
+          "primaryKey": true,
+          "notNull": true
+        },
+        "user_id": {
+          "name": "user_id",
+          "type": "integer",
+          "primaryKey": false,
+          "notNull": true
+        },
+        "resource_id": {
+          "name": "resource_id",
+          "type": "integer",
+          "primaryKey": false,
+          "notNull": true
+        }
+      },
+      "indexes": {},
+      "foreignKeys": {
+        "resource_likes_user_id_users_id_fk": {
+          "name": "resource_likes_user_id_users_id_fk",
+          "tableFrom": "resource_likes",
+          "tableTo": "users",
+          "columnsFrom": [
+            "user_id"
+          ],
+          "columnsTo": [
+            "id"
+          ],
+          "onDelete": "cascade",
+          "onUpdate": "no action"
+        },
+        "resource_likes_resource_id_resources_id_fk": {
+          "name": "resource_likes_resource_id_resources_id_fk",
+          "tableFrom": "resource_likes",
+          "tableTo": "resources",
+          "columnsFrom": [
+            "resource_id"
+          ],
+          "columnsTo": [
+            "id"
+          ],
+          "onDelete": "cascade",
+          "onUpdate": "no action"
+        }
+      },
+      "compositePrimaryKeys": {},
+      "uniqueConstraints": {
+        "resource_likes_id_unique": {
+          "name": "resource_likes_id_unique",
+          "nullsNotDistinct": false,
+          "columns": [
+            "id"
+          ]
+        }
+      }
+    },
+    "public.resource_stats": {
+      "name": "resource_stats",
+      "schema": "",
+      "columns": {
+        "id": {
+          "name": "id",
+          "type": "serial",
+          "primaryKey": true,
+          "notNull": true
+        },
+        "views": {
+          "name": "views",
+          "type": "integer",
+          "primaryKey": false,
+          "notNull": true,
+          "default": 0
+        },
+        "downloads": {
+          "name": "downloads",
+          "type": "integer",
+          "primaryKey": false,
+          "notNull": true,
+          "default": 0
+        },
+        "likes": {
+          "name": "likes",
+          "type": "integer",
+          "primaryKey": false,
+          "notNull": true,
+          "default": 0
+        },
+        "shares": {
+          "name": "shares",
+          "type": "integer",
+          "primaryKey": false,
+          "notNull": true,
+          "default": 0
+        },
+        "score": {
+          "name": "score",
+          "type": "numeric",
+          "primaryKey": false,
+          "notNull": true,
+          "default": "'0.0'"
+        },
+        "follows": {
+          "name": "follows",
+          "type": "integer",
+          "primaryKey": false,
+          "notNull": true,
+          "default": 0
+        },
+        "comments": {
+          "name": "comments",
+          "type": "integer",
+          "primaryKey": false,
+          "notNull": true,
+          "default": 0
+        }
+      },
+      "indexes": {},
+      "foreignKeys": {},
+      "compositePrimaryKeys": {},
+      "uniqueConstraints": {
+        "resource_stats_id_unique": {
+          "name": "resource_stats_id_unique",
+          "nullsNotDistinct": false,
+          "columns": [
+            "id"
+          ]
+        }
+      }
+    },
+    "public.resource_subjects": {
+      "name": "resource_subjects",
+      "schema": "",
+      "columns": {
+        "id": {
+          "name": "id",
+          "type": "serial",
+          "primaryKey": true,
+          "notNull": true
+        },
+        "resource_id": {
+          "name": "resource_id",
+          "type": "integer",
+          "primaryKey": false,
+          "notNull": true
+        },
+        "subject_id": {
+          "name": "subject_id",
+          "type": "integer",
+          "primaryKey": false,
+          "notNull": true
+        }
+      },
+      "indexes": {},
+      "foreignKeys": {
+        "resource_subjects_resource_id_resources_id_fk": {
+          "name": "resource_subjects_resource_id_resources_id_fk",
+          "tableFrom": "resource_subjects",
+          "tableTo": "resources",
+          "columnsFrom": [
+            "resource_id"
+          ],
+          "columnsTo": [
+            "id"
+          ],
+          "onDelete": "cascade",
+          "onUpdate": "no action"
+        },
+        "resource_subjects_subject_id_subjects_id_fk": {
+          "name": "resource_subjects_subject_id_subjects_id_fk",
+          "tableFrom": "resource_subjects",
+          "tableTo": "subjects",
+          "columnsFrom": [
+            "subject_id"
+          ],
+          "columnsTo": [
+            "id"
+          ],
+          "onDelete": "cascade",
+          "onUpdate": "no action"
+        }
+      },
+      "compositePrimaryKeys": {},
+      "uniqueConstraints": {
+        "resource_subjects_id_unique": {
+          "name": "resource_subjects_id_unique",
+          "nullsNotDistinct": false,
+          "columns": [
+            "id"
+          ]
+        }
+      }
+    },
+    "public.resources": {
+      "name": "resources",
+      "schema": "",
+      "columns": {
+        "id": {
+          "name": "id",
+          "type": "serial",
+          "primaryKey": true,
+          "notNull": true
+        },
+        "resource_state": {
+          "name": "resource_state",
+          "type": "resource_state",
+          "typeSchema": "public",
+          "primaryKey": false,
+          "notNull": true,
+          "default": "'draft'"
+        },
+        "name": {
+          "name": "name",
+          "type": "varchar(255)",
+          "primaryKey": false,
+          "notNull": true
+        },
+        "author": {
+          "name": "author",
+          "type": "varchar(255)",
+          "primaryKey": false,
+          "notNull": true
+        },
+        "link": {
+          "name": "link",
+          "type": "varchar(255)",
+          "primaryKey": false,
+          "notNull": false
+        },
+        "thumbnail": {
+          "name": "thumbnail",
+          "type": "varchar(255)",
+          "primaryKey": false,
+          "notNull": true
+        },
+        "description": {
+          "name": "description",
+          "type": "text",
+          "primaryKey": false,
+          "notNull": false
+        },
+        "active": {
+          "name": "active",
+          "type": "boolean",
+          "primaryKey": false,
+          "notNull": true,
+          "default": false
+        },
+        "created_at": {
+          "name": "created_at",
+          "type": "timestamp",
+          "primaryKey": false,
+          "notNull": true,
+          "default": "now()"
+        },
+        "updated_at": {
+          "name": "updated_at",
+          "type": "timestamp",
+          "primaryKey": false,
+          "notNull": true,
+          "default": "now()"
+        },
+        "published_at": {
+          "name": "published_at",
+          "type": "timestamp",
+          "primaryKey": false,
+          "notNull": false
+        },
+        "submitted_at": {
+          "name": "submitted_at",
+          "type": "timestamp",
+          "primaryKey": false,
+          "notNull": false
+        },
+        "deleted_at": {
+          "name": "deleted_at",
+          "type": "timestamp",
+          "primaryKey": false,
+          "notNull": false
+        },
+        "user_id": {
+          "name": "user_id",
+          "type": "integer",
+          "primaryKey": false,
+          "notNull": true
+        },
+        "resource_stats_id": {
+          "name": "resource_stats_id",
+          "type": "integer",
+          "primaryKey": false,
+          "notNull": true
+        },
+        "object_type_id": {
+          "name": "object_type_id",
+          "type": "integer",
+          "primaryKey": false,
+          "notNull": true
+        },
+        "license_id": {
+          "name": "license_id",
+          "type": "integer",
+          "primaryKey": false,
+          "notNull": true
+        }
+      },
+      "indexes": {},
+      "foreignKeys": {
+        "resources_user_id_users_id_fk": {
+          "name": "resources_user_id_users_id_fk",
+          "tableFrom": "resources",
+          "tableTo": "users",
+          "columnsFrom": [
+            "user_id"
+          ],
+          "columnsTo": [
+            "id"
+          ],
+          "onDelete": "cascade",
+          "onUpdate": "no action"
+        },
+        "resources_resource_stats_id_resource_stats_id_fk": {
+          "name": "resources_resource_stats_id_resource_stats_id_fk",
+          "tableFrom": "resources",
+          "tableTo": "resource_stats",
+          "columnsFrom": [
+            "resource_stats_id"
+          ],
+          "columnsTo": [
+            "id"
+          ],
+          "onDelete": "cascade",
+          "onUpdate": "no action"
+        },
+        "resources_object_type_id_object_types_id_fk": {
+          "name": "resources_object_type_id_object_types_id_fk",
+          "tableFrom": "resources",
+          "tableTo": "object_types",
+          "columnsFrom": [
+            "object_type_id"
+          ],
+          "columnsTo": [
+            "id"
+          ],
+          "onDelete": "cascade",
+          "onUpdate": "no action"
+        },
+        "resources_license_id_licenses_id_fk": {
+          "name": "resources_license_id_licenses_id_fk",
+          "tableFrom": "resources",
+          "tableTo": "licenses",
+          "columnsFrom": [
+            "license_id"
+          ],
+          "columnsTo": [
+            "id"
+          ],
+          "onDelete": "cascade",
+          "onUpdate": "no action"
+        }
+      },
+      "compositePrimaryKeys": {},
+      "uniqueConstraints": {
+        "resources_id_unique": {
+          "name": "resources_id_unique",
+          "nullsNotDistinct": false,
+          "columns": [
+            "id"
+          ]
+        },
+        "resources_resource_stats_id_unique": {
+          "name": "resources_resource_stats_id_unique",
+          "nullsNotDistinct": false,
+          "columns": [
+            "resource_stats_id"
+          ]
+        }
+      }
+    },
+    "public.roles": {
+      "name": "roles",
+      "schema": "",
+      "columns": {
+        "id": {
+          "name": "id",
+          "type": "serial",
+          "primaryKey": true,
+          "notNull": true
+        },
+        "name": {
+          "name": "name",
+          "type": "varchar(255)",
+          "primaryKey": false,
+          "notNull": true
+        },
+        "description": {
+          "name": "description",
+          "type": "text",
+          "primaryKey": false,
+          "notNull": false
+        },
+        "created_at": {
+          "name": "created_at",
+          "type": "timestamp",
+          "primaryKey": false,
+          "notNull": true,
+          "default": "now()"
+        },
+        "updated_at": {
+          "name": "updated_at",
+          "type": "timestamp",
+          "primaryKey": false,
+          "notNull": true,
+          "default": "now()"
+        }
+      },
+      "indexes": {},
+      "foreignKeys": {},
+      "compositePrimaryKeys": {},
+      "uniqueConstraints": {
+        "roles_id_unique": {
+          "name": "roles_id_unique",
+          "nullsNotDistinct": false,
+          "columns": [
+            "id"
+          ]
+        },
+        "roles_name_unique": {
+          "name": "roles_name_unique",
+          "nullsNotDistinct": false,
+          "columns": [
+            "name"
+          ]
+        }
+      }
+    },
+    "public.subjects": {
+      "name": "subjects",
+      "schema": "",
+      "columns": {
+        "id": {
+          "name": "id",
+          "type": "serial",
+          "primaryKey": true,
+          "notNull": true
+        },
+        "name": {
+          "name": "name",
+          "type": "varchar(255)",
+          "primaryKey": false,
+          "notNull": true
+        }
+      },
+      "indexes": {},
+      "foreignKeys": {},
+      "compositePrimaryKeys": {},
+      "uniqueConstraints": {
+        "subjects_id_unique": {
+          "name": "subjects_id_unique",
+          "nullsNotDistinct": false,
+          "columns": [
+            "id"
+          ]
+        }
+      }
+    },
+    "public.submissions": {
+      "name": "submissions",
+      "schema": "",
+      "columns": {
+        "id": {
+          "name": "id",
+          "type": "serial",
+          "primaryKey": true,
+          "notNull": true
+        },
+        "is_accepted": {
+          "name": "is_accepted",
+          "type": "boolean",
+          "primaryKey": false,
+          "notNull": true,
+          "default": false
+        },
+        "justification": {
+          "name": "justification",
+          "type": "text",
+          "primaryKey": false,
+          "notNull": false
+        },
+        "resource_id": {
+          "name": "resource_id",
+          "type": "integer",
+          "primaryKey": false,
+          "notNull": true
+        },
+        "submitter_id": {
+          "name": "submitter_id",
+          "type": "integer",
+          "primaryKey": false,
+          "notNull": true
+        },
+        "curator_id": {
+          "name": "curator_id",
+          "type": "integer",
+          "primaryKey": false,
+          "notNull": false
+        },
+        "created_at": {
+          "name": "created_at",
+          "type": "timestamp",
+          "primaryKey": false,
+          "notNull": true,
+          "default": "now()"
+        },
+        "updated_at": {
+          "name": "updated_at",
+          "type": "timestamp",
+          "primaryKey": false,
+          "notNull": true,
+          "default": "now()"
+        },
+        "answered_at": {
+          "name": "answered_at",
+          "type": "timestamp",
+          "primaryKey": false,
+          "notNull": false
+        },
+        "q1": {
+          "name": "q1",
+          "type": "boolean",
+          "primaryKey": false,
+          "notNull": false
+        },
+        "q2": {
+          "name": "q2",
+          "type": "boolean",
+          "primaryKey": false,
+          "notNull": false
+        },
+        "q3": {
+          "name": "q3",
+          "type": "boolean",
+          "primaryKey": false,
+          "notNull": false
+        },
+        "q4": {
+          "name": "q4",
+          "type": "boolean",
+          "primaryKey": false,
+          "notNull": false
+        }
+      },
+      "indexes": {},
+      "foreignKeys": {
+        "submissions_resource_id_resources_id_fk": {
+          "name": "submissions_resource_id_resources_id_fk",
+          "tableFrom": "submissions",
+          "tableTo": "resources",
+          "columnsFrom": [
+            "resource_id"
+          ],
+          "columnsTo": [
+            "id"
+          ],
+          "onDelete": "cascade",
+          "onUpdate": "no action"
+        },
+        "submissions_submitter_id_users_id_fk": {
+          "name": "submissions_submitter_id_users_id_fk",
+          "tableFrom": "submissions",
+          "tableTo": "users",
+          "columnsFrom": [
+            "submitter_id"
+          ],
+          "columnsTo": [
+            "id"
+          ],
+          "onDelete": "cascade",
+          "onUpdate": "no action"
+        },
+        "submissions_curator_id_users_id_fk": {
+          "name": "submissions_curator_id_users_id_fk",
+          "tableFrom": "submissions",
+          "tableTo": "users",
+          "columnsFrom": [
+            "curator_id"
+          ],
+          "columnsTo": [
+            "id"
+          ],
+          "onDelete": "cascade",
+          "onUpdate": "no action"
+        }
+      },
+      "compositePrimaryKeys": {},
+      "uniqueConstraints": {
+        "submissions_id_unique": {
+          "name": "submissions_id_unique",
+          "nullsNotDistinct": false,
+          "columns": [
+            "id"
+          ]
+        }
+      }
+    },
+    "public.user_achievements": {
+      "name": "user_achievements",
+      "schema": "",
+      "columns": {
+        "id": {
+          "name": "id",
+          "type": "serial",
+          "primaryKey": true,
+          "notNull": true
+        },
+        "user_id": {
+          "name": "user_id",
+          "type": "integer",
+          "primaryKey": false,
+          "notNull": true
+        },
+        "achievement_id": {
+          "name": "achievement_id",
+          "type": "integer",
+          "primaryKey": false,
+          "notNull": true
+        }
+      },
+      "indexes": {},
+      "foreignKeys": {
+        "user_achievements_user_id_users_id_fk": {
+          "name": "user_achievements_user_id_users_id_fk",
+          "tableFrom": "user_achievements",
+          "tableTo": "users",
+          "columnsFrom": [
+            "user_id"
+          ],
+          "columnsTo": [
+            "id"
+          ],
+          "onDelete": "cascade",
+          "onUpdate": "no action"
+        },
+        "user_achievements_achievement_id_users_id_fk": {
+          "name": "user_achievements_achievement_id_users_id_fk",
+          "tableFrom": "user_achievements",
+          "tableTo": "users",
+          "columnsFrom": [
+            "achievement_id"
+          ],
+          "columnsTo": [
+            "id"
+          ],
+          "onDelete": "cascade",
+          "onUpdate": "no action"
+        }
+      },
+      "compositePrimaryKeys": {},
+      "uniqueConstraints": {
+        "user_achievements_id_unique": {
+          "name": "user_achievements_id_unique",
+          "nullsNotDistinct": false,
+          "columns": [
+            "id"
+          ]
+        }
+      }
+    },
+    "public.userCollections": {
+      "name": "userCollections",
+      "schema": "",
+      "columns": {
+        "id": {
+          "name": "id",
+          "type": "serial",
+          "primaryKey": true,
+          "notNull": true
+        },
+        "user_id": {
+          "name": "user_id",
+          "type": "integer",
+          "primaryKey": false,
+          "notNull": true
+        },
+        "collection_id": {
+          "name": "collection_id",
+          "type": "integer",
+          "primaryKey": false,
+          "notNull": true
+        }
+      },
+      "indexes": {},
+      "foreignKeys": {
+        "userCollections_user_id_users_id_fk": {
+          "name": "userCollections_user_id_users_id_fk",
+          "tableFrom": "userCollections",
+          "tableTo": "users",
+          "columnsFrom": [
+            "user_id"
+          ],
+          "columnsTo": [
+            "id"
+          ],
+          "onDelete": "cascade",
+          "onUpdate": "no action"
+        },
+        "userCollections_collection_id_collections_id_fk": {
+          "name": "userCollections_collection_id_collections_id_fk",
+          "tableFrom": "userCollections",
+          "tableTo": "collections",
+          "columnsFrom": [
+            "collection_id"
+          ],
+          "columnsTo": [
+            "id"
+          ],
+          "onDelete": "cascade",
+          "onUpdate": "no action"
+        }
+      },
+      "compositePrimaryKeys": {},
+      "uniqueConstraints": {
+        "userCollections_id_unique": {
+          "name": "userCollections_id_unique",
+          "nullsNotDistinct": false,
+          "columns": [
+            "id"
+          ]
+        }
+      }
+    },
+    "public.user_institutions": {
+      "name": "user_institutions",
+      "schema": "",
+      "columns": {
+        "id": {
+          "name": "id",
+          "type": "serial",
+          "primaryKey": true,
+          "notNull": true
+        },
+        "user_id": {
+          "name": "user_id",
+          "type": "integer",
+          "primaryKey": false,
+          "notNull": true
+        },
+        "institution_id": {
+          "name": "institution_id",
+          "type": "integer",
+          "primaryKey": false,
+          "notNull": true
+        }
+      },
+      "indexes": {},
+      "foreignKeys": {
+        "user_institutions_user_id_users_id_fk": {
+          "name": "user_institutions_user_id_users_id_fk",
+          "tableFrom": "user_institutions",
+          "tableTo": "users",
+          "columnsFrom": [
+            "user_id"
+          ],
+          "columnsTo": [
+            "id"
+          ],
+          "onDelete": "cascade",
+          "onUpdate": "no action"
+        },
+        "user_institutions_institution_id_institutions_id_fk": {
+          "name": "user_institutions_institution_id_institutions_id_fk",
+          "tableFrom": "user_institutions",
+          "tableTo": "institutions",
+          "columnsFrom": [
+            "institution_id"
+          ],
+          "columnsTo": [
+            "id"
+          ],
+          "onDelete": "cascade",
+          "onUpdate": "no action"
+        }
+      },
+      "compositePrimaryKeys": {},
+      "uniqueConstraints": {
+        "user_institutions_id_unique": {
+          "name": "user_institutions_id_unique",
+          "nullsNotDistinct": false,
+          "columns": [
+            "id"
+          ]
+        }
+      }
+    },
+    "public.user_items": {
+      "name": "user_items",
+      "schema": "",
+      "columns": {
+        "id": {
+          "name": "id",
+          "type": "serial",
+          "primaryKey": true,
+          "notNull": true
+        },
+        "user_id": {
+          "name": "user_id",
+          "type": "integer",
+          "primaryKey": false,
+          "notNull": true
+        },
+        "item_id": {
+          "name": "item_id",
+          "type": "integer",
+          "primaryKey": false,
+          "notNull": true
+        }
+      },
+      "indexes": {},
+      "foreignKeys": {
+        "user_items_user_id_users_id_fk": {
+          "name": "user_items_user_id_users_id_fk",
+          "tableFrom": "user_items",
+          "tableTo": "users",
+          "columnsFrom": [
+            "user_id"
+          ],
+          "columnsTo": [
+            "id"
+          ],
+          "onDelete": "cascade",
+          "onUpdate": "no action"
+        },
+        "user_items_item_id_items_id_fk": {
+          "name": "user_items_item_id_items_id_fk",
+          "tableFrom": "user_items",
+          "tableTo": "items",
+          "columnsFrom": [
+            "item_id"
+          ],
+          "columnsTo": [
+            "id"
+          ],
+          "onDelete": "cascade",
+          "onUpdate": "no action"
+        }
+      },
+      "compositePrimaryKeys": {},
+      "uniqueConstraints": {
+        "user_items_id_unique": {
+          "name": "user_items_id_unique",
+          "nullsNotDistinct": false,
+          "columns": [
+            "id"
+          ]
+        }
+      }
+    },
+    "public.user_roles": {
+      "name": "user_roles",
+      "schema": "",
+      "columns": {
+        "id": {
+          "name": "id",
+          "type": "serial",
+          "primaryKey": true,
+          "notNull": true
+        },
+        "user_id": {
+          "name": "user_id",
+          "type": "integer",
+          "primaryKey": false,
+          "notNull": true
+        },
+        "role_id": {
+          "name": "role_id",
+          "type": "integer",
+          "primaryKey": false,
+          "notNull": true
+        }
+      },
+      "indexes": {},
+      "foreignKeys": {
+        "user_roles_user_id_users_id_fk": {
+          "name": "user_roles_user_id_users_id_fk",
+          "tableFrom": "user_roles",
+          "tableTo": "users",
+          "columnsFrom": [
+            "user_id"
+          ],
+          "columnsTo": [
+            "id"
+          ],
+          "onDelete": "cascade",
+          "onUpdate": "no action"
+        },
+        "user_roles_role_id_roles_id_fk": {
+          "name": "user_roles_role_id_roles_id_fk",
+          "tableFrom": "user_roles",
+          "tableTo": "roles",
+          "columnsFrom": [
+            "role_id"
+          ],
+          "columnsTo": [
+            "id"
+          ],
+          "onDelete": "cascade",
+          "onUpdate": "no action"
+        }
+      },
+      "compositePrimaryKeys": {},
+      "uniqueConstraints": {
+        "user_roles_id_unique": {
+          "name": "user_roles_id_unique",
+          "nullsNotDistinct": false,
+          "columns": [
+            "id"
+          ]
+        }
+      }
+    },
+    "public.user_stats": {
+      "name": "user_stats",
+      "schema": "",
+      "columns": {
+        "id": {
+          "name": "id",
+          "type": "serial",
+          "primaryKey": true,
+          "notNull": true
+        },
+        "score": {
+          "name": "score",
+          "type": "numeric",
+          "primaryKey": false,
+          "notNull": true,
+          "default": "'0.0'"
+        },
+        "likes": {
+          "name": "likes",
+          "type": "integer",
+          "primaryKey": false,
+          "notNull": true,
+          "default": 0
+        },
+        "likes_received": {
+          "name": "likes_received",
+          "type": "integer",
+          "primaryKey": false,
+          "notNull": true,
+          "default": 0
+        },
+        "follows": {
+          "name": "follows",
+          "type": "integer",
+          "primaryKey": false,
+          "notNull": true,
+          "default": 0
+        },
+        "followers": {
+          "name": "followers",
+          "type": "integer",
+          "primaryKey": false,
+          "notNull": true,
+          "default": 0
+        },
+        "collections": {
+          "name": "collections",
+          "type": "integer",
+          "primaryKey": false,
+          "notNull": true,
+          "default": 0
+        },
+        "submitted_resources": {
+          "name": "submitted_resources",
+          "type": "integer",
+          "primaryKey": false,
+          "notNull": true,
+          "default": 0
+        },
+        "approved_resources": {
+          "name": "approved_resources",
+          "type": "integer",
+          "primaryKey": false,
+          "notNull": true,
+          "default": 0
+        },
+        "reviewed_resources": {
+          "name": "reviewed_resources",
+          "type": "integer",
+          "primaryKey": false,
+          "notNull": true,
+          "default": 0
+        },
+        "comments": {
+          "name": "comments",
+          "type": "integer",
+          "primaryKey": false,
+          "notNull": true,
+          "default": 0
+        }
+      },
+      "indexes": {},
+      "foreignKeys": {},
+      "compositePrimaryKeys": {},
+      "uniqueConstraints": {
+        "user_stats_id_unique": {
+          "name": "user_stats_id_unique",
+          "nullsNotDistinct": false,
+          "columns": [
+            "id"
+          ]
+        }
+      }
+    },
+    "public.users": {
+      "name": "users",
+      "schema": "",
+      "columns": {
+        "id": {
+          "name": "id",
+          "type": "serial",
+          "primaryKey": true,
+          "notNull": true
+        },
+        "name": {
+          "name": "name",
+          "type": "varchar(255)",
+          "primaryKey": false,
+          "notNull": true
+        },
+        "username": {
+          "name": "username",
+          "type": "varchar(255)",
+          "primaryKey": false,
+          "notNull": true
+        },
+        "password": {
+          "name": "password",
+          "type": "varchar(255)",
+          "primaryKey": false,
+          "notNull": true
+        },
+        "email": {
+          "name": "email",
+          "type": "varchar(255)",
+          "primaryKey": false,
+          "notNull": true
+        },
+        "description": {
+          "name": "description",
+          "type": "text",
+          "primaryKey": false,
+          "notNull": false,
+          "default": "'sem descrição'"
+        },
+        "institution": {
+          "name": "institution",
+          "type": "text",
+          "primaryKey": false,
+          "notNull": false,
+          "default": "'sem instituição'"
+        },
+        "birthday": {
+          "name": "birthday",
+          "type": "timestamp",
+          "primaryKey": false,
+          "notNull": true
+        },
+        "cpf": {
+          "name": "cpf",
+          "type": "varchar(11)",
+          "primaryKey": false,
+          "notNull": true
+        },
+        "created_at": {
+          "name": "created_at",
+          "type": "timestamp",
+          "primaryKey": false,
+          "notNull": true,
+          "default": "now()"
+        },
+        "updated_at": {
+          "name": "updated_at",
+          "type": "timestamp",
+          "primaryKey": false,
+          "notNull": true,
+          "default": "now()"
+        },
+        "confirmed_at": {
+          "name": "confirmed_at",
+          "type": "timestamp",
+          "primaryKey": false,
+          "notNull": false
+        },
+        "confirmation_sent_at": {
+          "name": "confirmation_sent_at",
+          "type": "timestamp",
+          "primaryKey": false,
+          "notNull": false
+        },
+        "deleted_at": {
+          "name": "deleted_at",
+          "type": "timestamp",
+          "primaryKey": false,
+          "notNull": false
+        },
+        "reactivated_at": {
+          "name": "reactivated_at",
+          "type": "timestamp",
+          "primaryKey": false,
+          "notNull": false
+        },
+        "active": {
+          "name": "active",
+          "type": "boolean",
+          "primaryKey": false,
+          "notNull": false,
+          "default": true
+        },
+        "user_stats_id": {
+          "name": "user_stats_id",
+          "type": "integer",
+          "primaryKey": false,
+          "notNull": true
+        }
+      },
+      "indexes": {},
+      "foreignKeys": {
+        "users_user_stats_id_user_stats_id_fk": {
+          "name": "users_user_stats_id_user_stats_id_fk",
+          "tableFrom": "users",
+          "tableTo": "user_stats",
+          "columnsFrom": [
+            "user_stats_id"
+          ],
+          "columnsTo": [
+            "id"
+          ],
+          "onDelete": "no action",
+          "onUpdate": "no action"
+        }
+      },
+      "compositePrimaryKeys": {},
+      "uniqueConstraints": {
+        "users_id_unique": {
+          "name": "users_id_unique",
+          "nullsNotDistinct": false,
+          "columns": [
+            "id"
+          ]
+        },
+        "users_username_unique": {
+          "name": "users_username_unique",
+          "nullsNotDistinct": false,
+          "columns": [
+            "username"
+          ]
+        },
+        "users_email_unique": {
+          "name": "users_email_unique",
+          "nullsNotDistinct": false,
+          "columns": [
+            "email"
+          ]
+        },
+        "users_cpf_unique": {
+          "name": "users_cpf_unique",
+          "nullsNotDistinct": false,
+          "columns": [
+            "cpf"
+          ]
+        },
+        "users_user_stats_id_unique": {
+          "name": "users_user_stats_id_unique",
+          "nullsNotDistinct": false,
+          "columns": [
+            "user_stats_id"
+          ]
+        }
+      }
+    }
+  },
+  "enums": {
+    "public.resource_state": {
+      "name": "resource_state",
+      "schema": "public",
+      "values": [
+        "draft",
+        "submitted",
+        "accepted"
+      ]
+    },
+    "public.state": {
+      "name": "state",
+      "schema": "public",
+      "values": [
+        "active",
+        "inactive",
+        "under_review"
+      ]
+    }
+  },
+  "schemas": {},
+  "_meta": {
+    "columns": {},
+    "schemas": {},
+    "tables": {}
+  }
+}
\ No newline at end of file
diff --git a/src/db/migrations/meta/_journal.json b/src/db/migrations/meta/_journal.json
index fd42dad..d2fd8ec 100644
--- a/src/db/migrations/meta/_journal.json
+++ b/src/db/migrations/meta/_journal.json
@@ -15,6 +15,13 @@
       "when": 1740406482014,
       "tag": "0001_odd_valkyrie",
       "breakpoints": true
+    },
+    {
+      "idx": 2,
+      "version": "7",
+      "when": 1741614026669,
+      "tag": "0002_wakeful_taskmaster",
+      "breakpoints": true
     }
   ]
 }
\ No newline at end of file
diff --git a/src/db/schema/resource.schema.ts b/src/db/schema/resource.schema.ts
index dc86b4e..7e8a99c 100644
--- a/src/db/schema/resource.schema.ts
+++ b/src/db/schema/resource.schema.ts
@@ -24,7 +24,7 @@ const resourceTable = pgTable('resources', {
   id: serial('id').primaryKey()
     .notNull()
     .unique(),
-  state: resourceEnum('state').notNull().default('draft'),
+  resource_state: resourceEnum('resource_state').notNull().default('draft'),
   name: varchar('name', { length: 255 })
     .notNull(),
   author: varchar('author', { length: 255 })
diff --git a/src/db/schema/resourceEnum.schema.ts b/src/db/schema/resourceEnum.schema.ts
index df77bc6..cd49481 100644
--- a/src/db/schema/resourceEnum.schema.ts
+++ b/src/db/schema/resourceEnum.schema.ts
@@ -1,7 +1,11 @@
 import { pgEnum } from "drizzle-orm/pg-core";
 import { z } from "zod";
 
-const resourceEnum = pgEnum('state',['draft', 'submitted', 'accepted'])
+
+
+const resourceEnum = pgEnum('resource_state',
+    ['draft', 'submitted', 'accepted']
+)
 const resourceEnumSchema = z.enum(resourceEnum.enumValues)
 
 export default resourceEnum
diff --git a/src/db/seeds/resource.seed.ts b/src/db/seeds/resource.seed.ts
index c51975c..98cf82a 100644
--- a/src/db/seeds/resource.seed.ts
+++ b/src/db/seeds/resource.seed.ts
@@ -11,7 +11,6 @@ const resourceData: ResourceInput[] = [
         name: 'recurso 1',
         description: 'recurso 1 description',
         author: 'author 1',
-        bucket_key: 'bucket_key 1',
         link: 'link 1',
         thumbnail: 'thumbnail 1',
         user_id: 1,
@@ -23,7 +22,17 @@ const resourceData: ResourceInput[] = [
         name: 'recurso 2',
         description: 'recurso 2 description',
         author: 'author 2',
-        bucket_key: 'bucket_key 2',
+        link: 'link 2',
+        thumbnail: 'thumbnail 2',
+        user_id: 1,
+        resource_stats_id: 2,
+        object_type_id: 1,
+        license_id: 1
+    },
+    {
+        name: 'recurso 3',
+        description: 'recurso 2 description',
+        author: 'author 2',
         link: 'link 2',
         thumbnail: 'thumbnail 2',
         user_id: 1,
diff --git a/src/index.ts b/src/index.ts
index aa4fb29..97b4c89 100644
--- a/src/index.ts
+++ b/src/index.ts
@@ -43,7 +43,7 @@ import { OpenAPIHono } from "@hono/zod-openapi";
 import { commentsRouter, publicCommentsRoute } from './routes/comments.route'
 import { publicCommentsReplyRoute, commentReplyRouter } from './routes/comment-reply.route'
 import { publicUserCollectionsRoutes, userCollectionsRoute } from './routes/user-collection.route'
-import { s3Routes } from './routes/s3.route'
+import { publicS3, s3Routes } from './routes/s3.route'
 
 
 
@@ -102,8 +102,8 @@ app
   .route('/resource', publicResourceRouter)
   .route('/statsResource', publicResourceStatsRouter)
   .route('/subjects', publicSubjectsRouter)
-  .route('/get-collections', getCollections)
-  .route('/get-collection-stats', getCollectionsStats)
+  .route('/collections', getCollections)
+  .route('/collectionStats', getCollectionsStats)
   .route('/license', publicLicenseRouter)
   .route('/language', publicLanguageRouter)
   .route('/educationalStage', publicEducationalStageRouter)
@@ -120,6 +120,7 @@ app
   .route('/comments', publicCommentsRoute)
   .route('/replyComment', publicCommentsReplyRoute)
   .route('/userCollections', publicUserCollectionsRoutes)
+  .route('/s3', publicS3)
 //rotas que precisam de token
 app
   .basePath('/api')
diff --git a/src/routes/collection-resources.route.ts b/src/routes/collection-resources.route.ts
index dcf0372..83b3494 100644
--- a/src/routes/collection-resources.route.ts
+++ b/src/routes/collection-resources.route.ts
@@ -6,15 +6,16 @@ import { zValidator } from "@hono/zod-validator";
 import { createApexError, HttpStatus } from "@/services/error.service";
 import { Hono } from "hono";
 
+
 const associateSchema = z.object({
-    collectionId: z.number(),
-    resourceIds: z.array(z.number()),
+  collectionId: z.number(),
+  resourceIds: z.array(z.number()),
 })
 
 const service = Container.get(CollectionResourcesService);
 
 export const collectionResourcesRoutes = honoWithJwt()
-// associate resources with collection
+  // associate resources with collection
   .post('/associate', zValidator('json', associateSchema),
     async (c) => {
       try {
@@ -35,7 +36,7 @@ export const collectionResourcesRoutes = honoWithJwt()
       }
     }
   )
-  .post('/:collectionId/delete/:resourceId', 
+  .post('/:collectionId/delete/:resourceId',
     async (c) => {
       try {
         const collectionId = +c.req.param('collectionId');
@@ -56,16 +57,16 @@ export const collectionResourcesRoutes = honoWithJwt()
       }
     }
   )
-  
+
 
 export const publicCollectionResourcesRoutes = new Hono()
-// get all resources of a collection
-.get('/:collectionId/resources',
+  // get all resources of a collection
+  .get('/:collectionId/resources',
     async (c) => {
       try {
         const collectionId = +c.req.param('collectionId');
         const resources = await service.getResourcesbyCollection(collectionId);
-        return c.json(resources, HttpStatus.OK);
+        return c.json(resources);
       } catch (e) {
         return c.json(
           createApexError({
@@ -79,12 +80,12 @@ export const publicCollectionResourcesRoutes = new Hono()
         )
       }
     }
-  )  
+  )
   // check if resource is associated with collection
   .get('/:collectionId/resources/:resourceId/exists',
     async (c) => {
       try {
-        const collectionId  = +c.req.param('collectionId');
+        const collectionId = +c.req.param('collectionId');
         const resourceId = +c.req.param('resourceId');
         const exists = await service.isAssociationExists(collectionId, resourceId);
         return c.json({ exists }, HttpStatus.OK);
@@ -101,7 +102,7 @@ export const publicCollectionResourcesRoutes = new Hono()
         );
       }
     }
-  )  
+  )
   // get collections of a resource
   .get('/resource/:resourceId/collections',
     async (c) => {
@@ -122,4 +123,5 @@ export const publicCollectionResourcesRoutes = new Hono()
         );
       }
     }
-  )
\ No newline at end of file
+  )
+  ;
diff --git a/src/routes/collections.route.ts b/src/routes/collections.route.ts
index e63c53f..1aacb15 100644
--- a/src/routes/collections.route.ts
+++ b/src/routes/collections.route.ts
@@ -7,9 +7,14 @@ import { createApexError, HttpStatus } from "@/services/error.service";
 import { Hono } from "hono";
 import { collectionStatsSchemas } from "@/db/schema/collection-stats.schema";
 import { CollectionStatsService } from "@/services/collection-stats.service";
+import { getFile } from "@/services/s3.service";
+import archiver from "archiver"; // Biblioteca para criar ZIPs
+import { CollectionResourcesService } from "@/services/collection-resources.service";
+
 
 const service = Container.get(CollectionsService);
 const serviceStats = Container.get(CollectionStatsService);
+const serviceResourceCollection = Container.get(CollectionResourcesService) ;
 
 export const collectionsRouter = honoWithJwt()
   .post(
@@ -275,4 +280,96 @@ export const getCollections = new Hono()
         HttpStatus.NOT_FOUND
       )
     }
-  })
\ No newline at end of file
+  })
+  
+  .get("/:collectionId/download", async (c) => {
+    try {
+      const collectionId = +c.req.param("collectionId");
+
+      // Buscar os recursos da coleção
+      const resources = await serviceResourceCollection.getResourcesbyCollection(collectionId);
+
+      if (!resources.length) {
+        return c.json({ message: "Nenhum recurso encontrado para essa coleção" }, 404);
+      }
+
+      // Criar um arquivo ZIP via streaming (economizando memória)
+      //ReadableStream: os arquivos são processados e enviados aos poucos, sem precisar carregar tudo na memória local
+      const zipStream = new ReadableStream({
+        start(controller) {
+          const archive = archiver("zip", { zlib: { level: 3 } }); // Usa minizlib internamente, selecionando o nivel 3 de compressão
+
+
+          // .on sao event listeners, que reagem a eventos especificos durante a criação do zip
+
+          //sempre que um pedaço é gerado (chunk) ele é enviado (enqueue) para o usuario
+          archive.on("data", (chunk: Buffer) => controller.enqueue(chunk));
+          // Finaliza o stream quando o processo de zipagem for concluído
+          archive.on("end", () => {
+            console.log("ZIP finalizado e stream encerrado.");
+            controller.close()
+          });
+          // Se ocorrer um erro, o stream é encerrado com erro
+
+          archive.on("error", (err: NodeJS.ErrnoException) => {
+            console.error("Erro ao criar o ZIP:", err);
+            controller.error(err)
+          });
+
+          // Monitora o evento de 'warning', caso algum problema não crítico aconteça
+          archive.on("warning", (err: NodeJS.ErrnoException) => {
+            if (err.code === "ENOENT") {
+              console.warn("Aviso: arquivo não encontrado:", err);
+            } else {
+              throw err;
+            }
+          });
+
+
+          (async () => {
+            //busca os arquivos e adiciona ao zip
+            for (const resource of resources) {
+              try {
+                //pega o arquivo do s3
+                const response = await getFile(`resource/${resource.id}`);
+
+                if (response && response.Body) {
+                  //converte para o tipo buffer
+                  const buffer = Buffer.from(await response.Body.transformToByteArray());
+                  // Coloca o nome do arquivo e adiciona ao archive (ZIP)
+                  archive.append(buffer, { name: resource.name || `${resource.id}` });
+                } else {
+                  console.warn(`Arquivo ${resource.id} não encontrado.`);
+                }
+              } catch (error) {
+                console.error(`Erro ao buscar ${resource.id}:`, error);
+              }
+            }
+
+            archive.finalize(); // Finalserviceiza o zip
+          })();
+        },
+      });
+
+      //retorna o zip para o cliente
+      return new Response(zipStream, {
+        status: 200,
+        headers: {
+          "Content-Type": "application/zip",
+          "Content-Disposition": `attachment; filename="collection-${collectionId}.zip"`,
+        },
+      });
+
+    } catch (error) {
+      console.error("Erro ao gerar ZIP:", error);
+      return c.json(
+        {
+          status: "error",
+          message: "Erro interno ao gerar o ZIP",
+          code: 500,
+          path: c.req.routePath,
+        },
+        500
+      );
+    }
+  });
\ No newline at end of file
diff --git a/src/routes/resource.route.ts b/src/routes/resource.route.ts
index 318f099..610e7f5 100644
--- a/src/routes/resource.route.ts
+++ b/src/routes/resource.route.ts
@@ -7,6 +7,7 @@ import { createApexError, HttpStatus } from "@/services/error.service";
 import { Hono } from "hono";
 import { resourceStatsSchema } from "@/db/schema/resource-stats.schema";
 import { ResourceStatsService } from "@/services/resource-stats.service";
+import { getFile } from "@/services/s3.service";
 
 const service = Container.get(ResourceService);
 const serviceStats = Container.get(ResourceStatsService);
@@ -22,7 +23,7 @@ export const resourceRouter = honoWithJwt()
         async (c) => {
             try {
                 const input = await c.req.valid('json')
-              
+
                 //cria o stats do recurso correspondente
                 const stats = resourceStatsSchema.dto.parse(
                     await serviceStats.create()
@@ -170,7 +171,7 @@ export const publicResourceRouter = new Hono()
     .get('/allResourceByUser/:user_id', async (c) => {
         try {
             const user_id = +c.req.param('user_id')
-            const resources =resourceSchema.dto.array().parse( await service.allResourceByUser(user_id));
+            const resources = resourceSchema.dto.array().parse(await service.allResourceByUser(user_id));
 
             return c.json(resources);
         } catch (e) {
@@ -233,3 +234,34 @@ export const publicResourceRouter = new Hono()
             }
         }
     )
+
+    .get("/download/resource/:id", async (ctx) => {
+        const id = ctx.req.param("id");
+
+        try {
+            // Busca o arquivo no S3 com a chave "resource/id"
+            const response = await getFile(`resource/${id}`);
+
+            if (!response || !response.Body) {
+                return ctx.json({ message: "Arquivo não encontrado" }, 404);
+            }
+
+            // Converte o conteúdo do corpo para ArrayBuffer
+            const fileData = await response.Body.transformToByteArray();
+
+            return new Response(fileData, {
+                status: 200,
+                headers: {
+                    "Content-Type": response.ContentType || "application/octet-stream",
+                    "Content-Disposition": `attachment; filename="${id}"`,
+                }
+            });
+
+        } catch (error) {
+            console.error("Erro ao buscar arquivo do S3:", error);
+            return ctx.json(
+                { message: "Erro interno ao buscar o arquivo" },
+                500
+            );
+        }
+    });
diff --git a/src/routes/s3.route.ts b/src/routes/s3.route.ts
index 9c6e25c..9fe2708 100644
--- a/src/routes/s3.route.ts
+++ b/src/routes/s3.route.ts
@@ -224,6 +224,8 @@ export const s3Routes = new Hono()
         }
     })
 
+    export const publicS3 = new Hono()
+
 
 
     .get("get/resource/:id",
-- 
GitLab