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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
F{tJR244D7`

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