mirror of
https://github.com/zoriya/Kyoo.git
synced 2025-12-06 06:36:25 +00:00
Compare commits
1682 Commits
fix/downlo
...
11c300ecf7
| Author | SHA1 | Date | |
|---|---|---|---|
| 11c300ecf7 | |||
| 1e975ce238 | |||
| b39fa4262d | |||
| d7699389bc | |||
|
|
1036e9f3f3 | ||
|
|
b4749f3ed3 | ||
|
|
a20c61206f | ||
|
|
0644a43cb1 | ||
| af4742ae0b | |||
|
|
e401ca98c0 | ||
|
|
a756c875fd | ||
|
|
2ef26e5d02 | ||
|
|
e7d9002156 | ||
|
|
28d2e193aa | ||
| ce5bee11c0 | |||
| 60d59d7f7b | |||
| 464d720ef9 | |||
| 8fc279d2ed | |||
| a45e992339 | |||
| 5f8ddd435a | |||
| d822463fe0 | |||
|
|
3a0cbf786d | ||
|
|
dfb4777a5d | ||
|
|
eea32c47e9 | ||
|
|
6bcd03b18e | ||
|
|
87a3df6897 | ||
|
|
7f7a16e9b5 | ||
|
|
b95dd9056b | ||
|
|
5044f941b1 | ||
| c56f9ea791 | |||
| eb56dd70d6 | |||
| a4f5ef33ff | |||
| 20ab1dae6c | |||
| 7ebc0fe504 | |||
| 019aceb8d9 | |||
| f59cb5d671 | |||
| d4deafe1dc | |||
| 7b2f1c7a82 | |||
| c5fa3ecb01 | |||
| 3602905e86 | |||
| 1f7844b8a5 | |||
|
|
3b76fb2647 | ||
|
|
9a00d5036f | ||
|
|
7c315602cd | ||
|
|
19e0e402da | ||
|
|
ef38468178 | ||
| 2cbbb450c2 | |||
| 9f466ff702 | |||
| 05f7fabb3c | |||
| 5bc6a06b91 | |||
| f7e801e574 | |||
|
|
c663189df1 | ||
| 37ec32b52d | |||
| 188ce3f67d | |||
| 18b2ae2c5f | |||
| a115c83cba | |||
| 27d25f4829 | |||
|
|
d1d6fa9556 | ||
|
|
7878673d8d | ||
| 34761b43ae | |||
|
|
536b03b1ef | ||
|
|
6f37c128ef | ||
|
|
8e3a582f75 | ||
|
|
b5720dca06 | ||
|
|
df26dbca63 | ||
|
|
851ae9eb9d | ||
|
|
8aaf786400 | ||
| 3e40842c84 | |||
| 8ab4146241 | |||
| 0fa25eaeca | |||
| 2194831d86 | |||
| 7124a3d3c6 | |||
| 55a22f1c9e | |||
| 6d58164a6d | |||
| fea9c16515 | |||
| 01883d08cc | |||
|
|
03792487c3 | ||
|
|
87a0fa39f7 | ||
|
|
64dae6ddce | ||
|
|
efec489c96 | ||
|
|
5837b9875d | ||
| 1e1a6a1159 | |||
| 5e63b57440 | |||
|
|
befc0fc84f | ||
|
|
9bbdb3d7f0 | ||
|
|
58690eb428 | ||
|
|
7d47b7642c | ||
|
|
2f3682c226 | ||
|
|
d952444919 | ||
|
|
86cb391425 | ||
|
|
ed6623293b | ||
|
|
7a756dd67c | ||
|
|
e71640a636 | ||
|
|
f4b1ab5fa0 | ||
|
|
90475e47b1 | ||
|
|
c32b58e974 | ||
|
|
211f75f71a | ||
|
|
f0b9f3afdc | ||
|
|
6bc041723e | ||
|
|
82ea4fbe0b | ||
|
|
1749dc814b | ||
|
|
dfc886127a | ||
|
|
4943c94182 | ||
|
|
238702f81c | ||
|
|
c60abb26f9 | ||
|
|
2fb393bb45 | ||
|
|
6bab124331 | ||
|
|
9c57e01426 | ||
|
|
66dedaee29 | ||
|
|
eb31c0d8e6 | ||
|
|
cd65632527 | ||
|
|
a563d8f8ba | ||
|
|
60082ee799 | ||
|
|
6065b73d13 | ||
|
|
32a9dfc11c | ||
|
|
57c135c86b | ||
|
|
5064111a93 | ||
|
|
de718b6a46 | ||
|
|
d7748eb83e | ||
|
|
d730b5f3f4 | ||
|
|
5d17f8f0f9 | ||
|
|
864ee3efa2 | ||
|
|
a14a0145a9 | ||
|
|
a86c361825 | ||
|
|
e17e969bfe | ||
|
|
4708186f5c | ||
|
|
6238c8d9a0 | ||
|
|
7a34bbedae | ||
|
|
e59477eddd | ||
|
|
7368af7266 | ||
|
|
9c03f99524 | ||
|
|
54d4965a9a | ||
|
|
dc7d6919da | ||
|
|
aa180bfcea | ||
|
|
5ab28622d9 | ||
|
|
7f97ea6e90 | ||
|
|
869b0206b8 | ||
|
|
159a4cc77a | ||
|
|
571590a40d | ||
|
|
0943401d03 | ||
|
|
ababb67b1a | ||
|
|
5bf4d70623 | ||
|
|
c495589927 | ||
|
|
5e20257202 | ||
|
|
e8154c31ce | ||
|
|
b1d8d00a9b | ||
|
|
c5c0de5493 | ||
|
|
cfafe12c82 | ||
|
|
594e0233ca | ||
|
|
63c5b40123 | ||
| 1caff13adc | |||
| b4c85f3f28 | |||
| a95bbcb6eb | |||
| 61b38d5b03 | |||
| 563ae85db1 | |||
| 8f0fb42b47 | |||
| 40c13e7ddf | |||
| 0a862c3782 | |||
| b1723c2f2c | |||
|
|
84fcbbbb42 | ||
|
|
93b5b50ba1 | ||
| 4f9d340ef4 | |||
| 5142e2bc25 | |||
| 8f7f388403 | |||
| 5a37327e63 | |||
| d42062679a | |||
| 6bb905b388 | |||
| 39cfd501ac | |||
| 079cc6b4f9 | |||
| 951ae955ed | |||
| 61708857af | |||
| d3c69876d4 | |||
| ebaf6d2177 | |||
| 9bc30ab62d | |||
|
|
f71a65d134 | ||
|
|
ca0722b55c | ||
|
|
22cf24fd8c | ||
|
|
19e3619a42 | ||
| 1db4dea56f | |||
| 03bb51661a | |||
| 01177c2489 | |||
| a86cd969a3 | |||
| bc6c93c9c7 | |||
| 572ddc69ad | |||
| c1b243df9c | |||
| 31500dc3c5 | |||
| 509e7c08cd | |||
| 165d9e8f31 | |||
| 04171af3e3 | |||
| f1ddc7e7b9 | |||
| 5827cc32e8 | |||
| 4dc34641ec | |||
|
|
14c8f25499 | ||
|
|
d98ac3b452 | ||
| 3e7b27342c | |||
| dd9e611bef | |||
|
|
0905e4424e | ||
|
|
64c43a7833 | ||
| 648a03e3ea | |||
|
|
eb6887d189 | ||
|
|
c6133d85ff | ||
|
|
8a1b90f035 | ||
|
|
8348e185fc | ||
|
|
1d78b26a37 | ||
| a8b2e575d5 | |||
| c132afe163 | |||
| ebad8f32a4 | |||
| fb74ed30f8 | |||
| a0be0555e0 | |||
| 002b9e4b35 | |||
| 996ad52159 | |||
| 3b8c21c20f | |||
| b3b58f7a1e | |||
| 7739908a19 | |||
| a3f29c73ec | |||
| 5fdc96db64 | |||
| 9206a30182 | |||
| 1d81981c3f | |||
| a15f28e541 | |||
| 23832929e9 | |||
| 3590963206 | |||
| 5ca1ae938f | |||
| dfdeca35f3 | |||
| 70ff2285d5 | |||
| c5f237771c | |||
| 8fea8b1fe7 | |||
| 816ee8de14 | |||
| a7d5f94dfb | |||
| b7c6ba1e85 | |||
| e348464261 | |||
| 5031cc7163 | |||
| ebfb486363 | |||
| 6cb1ae5fa1 | |||
| ad41c09055 | |||
| 5b320974df | |||
| e01c67b1ef | |||
| da5823deb2 | |||
| 7085a68733 | |||
| 84a855602e | |||
| 57779f02b1 | |||
| becc550add | |||
| 9343bb524c | |||
| fc9695a2dc | |||
| a310ceaed5 | |||
| 4d8806fc7f | |||
| d70b45d1fd | |||
| 5eb067639b | |||
| c364d3a67e | |||
| 666ad9279f | |||
| 02c77d2f32 | |||
| ebbed77650 | |||
| 578dc4bbc9 | |||
| e3ae961b68 | |||
| c33ba01e54 | |||
| 787bfc1151 | |||
| f12718d67f | |||
| df3e0d1ed7 | |||
| 8ffed25580 | |||
| a0739e57f2 | |||
|
|
da79d235be | ||
|
|
ae20682c92 | ||
|
|
99d4a21c12 | ||
|
|
17040e9775 | ||
|
|
f92f93f960 | ||
|
|
1eb832f00d | ||
|
|
b14ada8f48 | ||
|
|
f5f7a187c4 | ||
|
|
938f7ca047 | ||
|
|
b0c1df2827 | ||
|
|
be0b5d1523 | ||
|
|
fbee956876 | ||
|
|
db1c1a5e92 | ||
|
|
b4f9552048 | ||
|
|
1a5b93e5aa | ||
|
|
216a58af24 | ||
|
|
eff7a32b09 | ||
|
|
bd041c1a4e | ||
|
|
48876494f7 | ||
|
|
e4d92ff364 | ||
|
|
d35ab8c894 | ||
| 64f38517e2 | |||
|
|
6b82053aec | ||
|
|
5e91766d15 | ||
|
|
65dc31c88a | ||
|
|
7ad78bd759 | ||
|
|
0befab278e | ||
|
|
8ea88f4301 | ||
|
|
07fdf5e0b9 | ||
|
|
de9559d1a2 | ||
|
|
640bcad39f | ||
|
|
19edd54e37 | ||
|
|
e9a9ecb157 | ||
|
|
36605a9b85 | ||
|
|
432b6681c7 | ||
|
|
34525168bb | ||
|
|
336a925591 | ||
|
|
2f6b946e71 | ||
|
|
47218e289b | ||
|
|
8f1813168b | ||
|
|
7ececfaf6a | ||
|
|
3f994ddd6f | ||
|
|
4e051e7ead | ||
|
|
b48a0fc0e0 | ||
|
|
3fbfc3c289 | ||
|
|
0baaed5973 | ||
|
|
7f2c1fa5af | ||
|
|
89d44078f3 | ||
|
|
ba0311ca29 | ||
|
|
c249397b23 | ||
|
|
52022c1660 | ||
|
|
df2b5a0b1d | ||
|
|
b062222238 | ||
|
|
0432fb59d4 | ||
|
|
7da6b7c488 | ||
|
|
f7701986bd | ||
|
|
9af26df40e | ||
|
|
a4ee343101 | ||
|
|
a11eae6094 | ||
|
|
84941ceb63 | ||
|
|
4a889890e3 | ||
|
|
794c10e590 | ||
|
|
897564337c | ||
|
|
e49e202677 | ||
|
|
b85febeaa4 | ||
|
|
c0bbb973c4 | ||
|
|
a57b2696de | ||
|
|
952a0dbc2f | ||
|
|
6919a310b8 | ||
|
|
76ea0ce2ce | ||
|
|
611490e786 | ||
|
|
725c1dc2e6 | ||
|
|
d77156e5d0 | ||
|
|
8f9190c176 | ||
|
|
90780eae4b | ||
|
|
691d63e15f | ||
|
|
6054e8cb18 | ||
|
|
385130aa05 | ||
|
|
b0daddca17 | ||
|
|
fb049d4c05 | ||
|
|
774ff21b6b | ||
|
|
f899445e13 | ||
|
|
ecb4dae801 | ||
|
|
03d3a1b386 | ||
|
|
bfff409142 | ||
|
|
e9a34967f1 | ||
|
|
fc726f96fe | ||
|
|
dcb551afbe | ||
|
|
1cdf765fec | ||
| d5a747f40d | |||
| 335b003b7c | |||
| e0d5754519 | |||
| 28702b9cdb | |||
| f99a144bc4 | |||
| dc0c412eda | |||
| fcac650322 | |||
| 5379536db2 | |||
| 8c8a974054 | |||
| 616c7140d3 | |||
| 7939cc1c79 | |||
| ec204d04e1 | |||
| 460e4596f7 | |||
| c340a9b559 | |||
| 5d414bea16 | |||
| 46f313d735 | |||
| 30dd1e0b96 | |||
| 61b6eb0c6e | |||
| 8caff21114 | |||
| c90d0e7ffc | |||
| 4188e7bcd3 | |||
|
|
fbfe9dda8a | ||
|
|
2ef8f07a72 | ||
| 8a9cf9fa1a | |||
| ff4155de5e | |||
| 5ed43c85de | |||
| 666e4e2e6b | |||
| 8513cc057b | |||
| 42cce837e4 | |||
| d5c7ee40bc | |||
| dbf63e1b22 | |||
| 4b6f56a293 | |||
|
|
f5cc3e0717 | ||
|
|
5c05531449 | ||
|
|
74a2f50012 | ||
| f6a41fdd63 | |||
|
|
46736b9100 | ||
|
|
cb16a51b38 | ||
| aea2535cc6 | |||
| 287b5350ff | |||
| 015b909a91 | |||
|
|
d5197f563c | ||
|
|
b82ebc90e8 | ||
|
|
c924e330b8 | ||
| 1ea83848f3 | |||
| 4c1ad4da5b | |||
| 7b3f3cc1c1 | |||
| bbe1ad4ef1 | |||
| 4a98b5ff27 | |||
| 8f80d6c96d | |||
| e1059aceed | |||
| 9d8e2e25e2 | |||
| 69838493bc | |||
| 512b378702 | |||
|
|
6986b54d98 | ||
|
|
c8b3c0d806 | ||
|
|
5f94bd144d | ||
|
|
2aadfb1319 | ||
| 3f1c027019 | |||
| 0d4e8d5a62 | |||
| bf1997facd | |||
| 977398c851 | |||
| a697ffb524 | |||
| aa342cfbd3 | |||
| c7103410dc | |||
|
|
549b44ad89 | ||
| 26410734fc | |||
| 985a13c1e4 | |||
| dfe0d52b1e | |||
| 552926d2cb | |||
| 0ad9c86756 | |||
| 1673da0004 | |||
| 4d96ab5451 | |||
| aa5ba7f2a9 | |||
| 16f6399c4f | |||
| 4ff0a1fe09 | |||
| e63e3605c6 | |||
| 886b33d5a7 | |||
| 2f0e077fa1 | |||
| 713f3ca96f | |||
| 69c4e4e6d8 | |||
| 9498dea3fd | |||
| 6823642e33 | |||
| 6c243b8961 | |||
| 43cf343841 | |||
| 3a9cb262f8 | |||
| 36abadc2cc | |||
|
|
5d7cdfdad8 | ||
|
|
ecfb063bc7 | ||
|
|
d100018291 | ||
|
|
405fbb49a0 | ||
|
|
9b015da29c | ||
|
|
4d57278062 | ||
|
|
2b832ab05c | ||
|
|
5454665337 | ||
|
|
76564736bd | ||
|
|
f8adc3cf0c | ||
|
|
3317f6a3b8 | ||
|
|
a83ea2f370 | ||
| 8de7f20ac9 | |||
| 9fbddd7b58 | |||
| 651475876b | |||
| 9d2edc8d06 | |||
| 50b6af78f4 | |||
| d6c5e5281d | |||
|
|
4029f4bb43 | ||
|
|
64f7e7c8be | ||
|
|
f37f95e6f4 | ||
|
|
ab49263b0c | ||
|
|
01002f2975 | ||
|
|
df9622f57b | ||
|
|
09ec19626e | ||
|
|
c56192244e | ||
|
|
e78c4cbf5f | ||
| 5e37a946ac | |||
| f0a0b40b3e | |||
| 1fdabaa63a | |||
| f8aae2f701 | |||
| bb62a2844f | |||
| 317e795d6f | |||
| 3f82f04f65 | |||
| 829497300e | |||
| 14cf634815 | |||
| 96a38e0c65 | |||
| 1685800ce8 | |||
| 9ba853f52c | |||
| c172767843 | |||
| f41be77632 | |||
| 16d6c65eba | |||
| b1f6fdc30f | |||
| 474a0a546b | |||
| e3bde0cd57 | |||
| 11712d3e4e | |||
| be54eb11fe | |||
| 31c183ecf1 | |||
| 23f42f247d | |||
| 8c40e2230d | |||
| 6584983535 | |||
| 071b365a9b | |||
| 4b239db229 | |||
| f2bc916483 | |||
| 6cfeba6c62 | |||
| b4144e61d3 | |||
| b4f303e0fb | |||
| 176d76b246 | |||
| 7ee6c2e666 | |||
| ea7cb8b4d1 | |||
| 0a8553653c | |||
| f76b2732a1 | |||
| 7211699e87 | |||
| 5d6bb63ba2 | |||
| c1e3a67a4e | |||
| 4a3d033562 | |||
| cbc00729cc | |||
| 7a4e203cdd | |||
| 32ecf25321 | |||
| d53d4a26e9 | |||
| c84985766e | |||
| 6a229a090a | |||
| 25e9cec3c3 | |||
| b9354537e1 | |||
| 0e01b7c564 | |||
| 9b89b00b9f | |||
| 32c826e65d | |||
| b22e89423a | |||
| b602185237 | |||
| 2f6943cd6f | |||
| 489336c77a | |||
| 6e2743a4be | |||
| 3e69ea9c8b | |||
| d9d411b377 | |||
| be4b4f016b | |||
| 107e581801 | |||
| 9b68110cf6 | |||
| 505427f0ff | |||
| 9e3a9af0ef | |||
| af97c52e48 | |||
| 953ac5ffa8 | |||
| 791bbf275a | |||
| d1bf1f3339 | |||
| 62e0a123aa | |||
| 55d1551cd3 | |||
| a22edc11ce | |||
| af566150f5 | |||
| 4828fa08cf | |||
| e5b1842432 | |||
| 7857b14a14 | |||
| 12d9ad3183 | |||
| df23cf54d7 | |||
| 9c451a865e | |||
| 5b2ccba175 | |||
| ae0f55ae9b | |||
| c9fcbc8e8f | |||
| 1747454845 | |||
| 095d309bb6 | |||
| 10e200ea5a | |||
| af75985a14 | |||
| 34c891128e | |||
| cafc40d5f2 | |||
| d13fa1bdf1 | |||
| 90b6e2264d | |||
| a9b7d18a6e | |||
| 2fc696dde9 | |||
| f3310e23f3 | |||
| ebda81db97 | |||
| d6d71421fd | |||
| d873c74545 | |||
| 07972b0773 | |||
| e2f02a279d | |||
| 444249dfc4 | |||
| 6d70870ef3 | |||
| 0839f5afb7 | |||
| 9eae11d3b5 | |||
| cd874e382f | |||
| 0cafe1ef40 | |||
| d666cda744 | |||
| 19f346ffb6 | |||
| a29dff1014 | |||
| 45a1198f30 | |||
| 1e65053c37 | |||
| b0dad090ae | |||
| 53867792f3 | |||
| 21435da93f | |||
| 2bf9464c18 | |||
| f5f4ad439c | |||
| d1e38c9e1c | |||
| 249019d6f5 | |||
| 608e0cf12e | |||
| f1f7dde507 | |||
| 058f7a67a1 | |||
| 38d4b20092 | |||
| 37271cc855 | |||
| 481af6bfd3 | |||
| e4e7caf738 | |||
| fa8f43c9bb | |||
| 3537722d44 | |||
| d8906cfe06 | |||
| d32711845b | |||
| cb7edde64c | |||
| 4353b5e911 | |||
| b6ed8f0684 | |||
| b28f00aa22 | |||
| 70be095131 | |||
| fb2a9cf9f1 | |||
| 7beff1eeaf | |||
| f8612fed96 | |||
| 9c98e284f0 | |||
| b3a13882c1 | |||
| e3a04c0e0f | |||
| 4eed03a566 | |||
| ed7e9cd159 | |||
| 11d0461d55 | |||
| 8dd43653cc | |||
| 2d7ff3bc58 | |||
| f740448229 | |||
| d92482d0b7 | |||
| ab5d2ad4e8 | |||
| 7ff794742d | |||
| 4480757df5 | |||
| 87fa87298e | |||
| 51f583965a | |||
| 60d1105280 | |||
| aba86601cd | |||
| 9f330f6683 | |||
| eb2b2a95a0 | |||
| 943d2ac10b | |||
| 6324901d3b | |||
| b3d8ffc89d | |||
| ae9bfcfd41 | |||
|
|
37e0fc3f0e | ||
|
|
533ca0aed0 | ||
|
|
5897899d71 | ||
|
|
3f96da2c7c | ||
|
|
c31c82a3e4 | ||
|
|
1c3314d8a5 | ||
|
|
63df1baead | ||
|
|
4f63f09566 | ||
|
|
bd9f51d260 | ||
|
|
17181cec0e | ||
|
|
7455e79f61 | ||
|
|
67cd8bea9c | ||
|
|
05c2118f1f | ||
|
|
21b7a5cec6 | ||
|
|
6e5b9852c7 | ||
|
|
1d70864e89 | ||
|
|
dfce460153 | ||
|
|
7d31de50c3 | ||
|
|
77ffc2e061 | ||
|
|
1b3f6d41ba | ||
|
|
fa0bb985a7 | ||
|
|
d9a6d052bc | ||
|
|
18b0c34165 | ||
|
|
1f573a2553 | ||
|
|
ce63da1448 | ||
|
|
f6a67341b6 | ||
|
|
4a0e1aa72c | ||
|
|
27a4fc328e | ||
|
|
e45883230b | ||
|
|
8f121d20e3 | ||
|
|
665d614921 | ||
|
|
aa42d807b2 | ||
|
|
4c0f20a33e | ||
|
|
f729ef06a7 | ||
|
|
ebec864187 | ||
|
|
d9e0ca1edd | ||
|
|
d23a24943e | ||
| ebd95c7b0c | |||
| a96813fe30 | |||
| 4df171386b | |||
| 46d98e038d | |||
| 205dda652a | |||
| e26bc931f5 | |||
| 45e769828b | |||
| 466b67afe5 | |||
| 379765b28f | |||
| 71b3ee61af | |||
| 7203155747 | |||
| 9cb9301a35 | |||
| 6a5862ddd2 | |||
| 060c4d74b4 | |||
| 07a41bb175 | |||
| d2bb37b3a7 | |||
| ce66dba0c8 | |||
| 6194d806cc | |||
| 1fca8957a2 | |||
| 39dcfb4418 | |||
| 1369da1845 | |||
| 621c9cec82 | |||
| c504cbbff5 | |||
| 0aa2c9c086 | |||
|
|
099032c165 | ||
|
|
a16d09d692 | ||
|
|
949a367d0d | ||
|
|
0b3d46cc67 | ||
|
|
7d04da2eae | ||
|
|
454855b299 | ||
|
|
265386f289 | ||
|
|
cf7bc456e8 | ||
|
|
0493265b1d | ||
|
|
58cc688a02 | ||
|
|
1a61b18b2d | ||
|
|
0fe423869a | ||
|
|
7193b5a2a2 | ||
|
|
79ee70a1a2 | ||
|
|
73e2eaaf70 | ||
|
|
02c2a2db52 | ||
|
|
a39baa1b50 | ||
|
|
5ebbd2b565 | ||
|
|
35437500ed | ||
|
|
94fe79bcd1 | ||
|
|
5ced62aab3 | ||
| f2294ac97e | |||
|
|
1c8cbab989 | ||
|
|
f2caf1a975 | ||
| b1509f4001 | |||
|
|
4475964eb2 | ||
| 092128add1 | |||
| e68217dbce | |||
|
|
9945d49be9 | ||
| fb908c95ef | |||
| 667249bc81 | |||
| dcbbb6352a | |||
|
|
d0a1ee848f | ||
| e8acb31834 | |||
| a72ecdb21b | |||
| 85186a74c8 | |||
| 822a7029ef | |||
|
|
634c8808a1 | ||
|
|
099d893da9 | ||
| 1d1ea295c0 | |||
|
|
b38adc558d | ||
|
|
893d2b7081 | ||
|
|
e962887569 | ||
|
|
5af6078e67 | ||
|
|
5e3c8c5f6f | ||
|
|
91e08dd5a9 | ||
| cf8814a5fd | |||
|
|
a7760f4e41 | ||
| 8785d5af4d | |||
|
|
0d6219aca7 | ||
| cad5dee882 | |||
|
|
cb831888ee | ||
| c6ad4266ec | |||
|
|
1b1e49f089 | ||
| b6fafa6d68 | |||
|
|
111d216dcd | ||
| 3b9d9f592e | |||
|
|
4b79ec7fae | ||
| d7388d3504 | |||
| 3c681fca65 | |||
| 29f38e42ae | |||
| c0596eb3ab | |||
|
|
5941fc3ee7 | ||
|
|
f121b718a9 | ||
|
|
eaa09aba3b | ||
|
|
31a38d0861 | ||
|
|
9416c06a0d | ||
|
|
60410481c1 | ||
|
|
4be2812780 | ||
|
|
26b839fc4a | ||
|
|
bc7920fad3 | ||
|
|
50e18ee99d | ||
|
|
6b751e11f3 | ||
|
|
28fe8bd9bc | ||
|
|
7c0424fcda | ||
|
|
b96ce5d46f | ||
|
|
e73aa83c83 | ||
|
|
e403c35741 | ||
|
|
a23293c0b7 | ||
|
|
6fa4bd889f | ||
|
|
81cc6d752b | ||
|
|
88fff8ff24 | ||
|
|
8f2b487fb4 | ||
|
|
196f5678df | ||
|
|
db15a5649a | ||
|
|
beb0946802 | ||
|
|
a1cd3ba752 | ||
|
|
7de11919ad | ||
| 60764f6c06 | |||
| 7bd1de3df6 | |||
| 20f8640790 | |||
| e1b428e8ce | |||
| 144e08a99c | |||
| d6d3540b16 | |||
| 09dd78b272 | |||
| 67d7643261 | |||
| d8566355bb | |||
| 68270c1343 | |||
| c8742605ff | |||
| 9991da4fe1 | |||
| 4cf67c3247 | |||
| 69006478cb | |||
| c0e00c0fd4 | |||
| e32fc229f8 | |||
| c48815a71a | |||
| e2fa3af1e8 | |||
| fef9e844a1 | |||
| 4ba7750012 | |||
| df7d109c34 | |||
| 880a85ff8d | |||
| 572e763a61 | |||
| 080da9bc27 | |||
| db0b244286 | |||
| 59533e5f0c | |||
| b3edf31afc | |||
| bf361a79d1 | |||
| 83d8462003 | |||
| 3f5af4b7fa | |||
| 18eb1b02a3 | |||
| 4b0100c52d | |||
| a7f355531d | |||
| aa9476680c | |||
| b4e8fbdd26 | |||
|
|
d7dc92a8ca | ||
| 148fd6b2e5 | |||
|
|
c9f93c5ab3 | ||
| a83fa90482 | |||
|
|
427376524f | ||
|
|
d38d2b7006 | ||
|
|
008dcc6e64 | ||
| 341322d625 | |||
| 5994b8bc02 | |||
| 5a6e29e57a | |||
| 74ee45244b | |||
| c3abd7c61b | |||
| 11e1c59698 | |||
| 22754442ad | |||
| 54131b6762 | |||
| 1943eca52b | |||
| be35a4f0d9 | |||
| 32cc6e7910 | |||
| e489d0c445 | |||
| 31a749b5ed | |||
| be2e5e5ccf | |||
| 6ecaec2dee | |||
| 781a6a8196 | |||
| e9db7b6285 | |||
| 29704e2f26 | |||
| 026ad817bc | |||
| dcbe817d60 | |||
| 0aab4cd84c | |||
| 49f700ca6e | |||
| 8110f7de66 | |||
| 31d545530b | |||
| dbe8e319c8 | |||
| a903d88a66 | |||
| d4fbba8aeb | |||
| d88160218b | |||
| 6d8697cd9d | |||
| c5a676b2a5 | |||
| 431055ec49 | |||
| 8ef4fe5e55 | |||
| 92753b72d3 | |||
| 411f6dcfba | |||
| 076d5a0dbd | |||
| b81c94f2da | |||
| f53e71afff | |||
| 8fe50ad00b | |||
| 65a7f62fd1 | |||
| d0d12cc5f6 | |||
| 4dbb41f008 | |||
|
|
a84ecfcae0 | ||
| 2f85253ae4 | |||
|
|
f522ee6481 | ||
| f14301f9ac | |||
|
|
10e5700904 | ||
| 6d09c3354c | |||
| 0e81c11f75 | |||
| 1f8652e06c | |||
| bcded031e2 | |||
| 161e4943a1 | |||
| 9dc1087273 | |||
| 6391a99bb9 | |||
| 068b19c936 | |||
| 50549f20de | |||
| 825619b11d | |||
| e6e2f8ce91 | |||
| 61151478e4 | |||
| 4cf5adda9a | |||
| 204344955e | |||
| 92b0076bef | |||
| 7ec940a8dc | |||
| b94a6a652e | |||
| 23adc6033e | |||
| 631967567f | |||
| 808ee3a8c2 | |||
|
|
aec2b0d9bf | ||
|
|
c08e233bfd | ||
|
|
b8986d17e4 | ||
| 02ad247468 | |||
|
|
8214deaeb2 | ||
| ecee7255ed | |||
|
|
0ce178595e | ||
| 792e8d5974 | |||
|
|
c61ca4021c | ||
| 15019152d3 | |||
|
|
7cd53ca867 | ||
|
|
b3bfc97469 | ||
| d34ab4f0f0 | |||
|
|
3777908d57 | ||
|
|
1e0618e4be | ||
|
|
f0cabb4f5d | ||
| b77aa39770 | |||
| 4ce8ce7f6d | |||
| 27c5b34c5a | |||
| 6ff00a1133 | |||
| 7d3413a3d5 | |||
| 9905587c83 | |||
| 47554590a9 | |||
| c114af0856 | |||
| 5da13f8f41 | |||
| 51558db1b2 | |||
| 0a729ccf75 | |||
| f11e1b56db | |||
| 71b57c50e7 | |||
| 6e642db7db | |||
| 9ef114b91a | |||
| 71b8cbca4a | |||
| 67511a3aa8 | |||
| 1a11bc3492 | |||
| 82d8a00eb4 | |||
|
|
7deb31aea5 | ||
| e75321879c | |||
|
|
8f98e75534 | ||
| 8ecb036ec3 | |||
|
|
5431d50005 | ||
| 7fcae39567 | |||
|
|
f2e05e21eb | ||
|
|
998cdcb80a | ||
|
|
58951b1a20 | ||
|
|
f7ee8a0a15 | ||
|
|
f894a5db21 | ||
|
|
26c3b093b3 | ||
| 31bfd58160 | |||
|
|
53ecb31470 | ||
| d08febf803 | |||
|
|
aface8f326 | ||
|
|
9983f0c48a | ||
| 27aff3cf8f | |||
|
|
6b4bab7905 | ||
| 5ae04c6dac | |||
| 458eb2c387 | |||
| f6b10738da | |||
| 2cebdcd63e | |||
| 6dec212a2c | |||
| 621d4752ba | |||
| 878d72f3a4 | |||
| 8687cf8de0 | |||
| dfaf5480ad | |||
| e3a537896a | |||
| 25f042fbd7 | |||
| 43a128ebe8 | |||
| 46833ac06f | |||
| 039880d812 | |||
| 18532b80b1 | |||
| cba47ca346 | |||
| 7e6592fa2e | |||
| 8d7d5f3e7e | |||
| bcec4c31d1 | |||
| 06458adc31 | |||
| b093df96ec | |||
| e0ad458d73 | |||
| 4b46963eff | |||
| 34926dab51 | |||
| d61573668b | |||
| aab38f6a89 | |||
| f9ff6c00d7 | |||
| fc60fcc7c4 | |||
| c161d680e3 | |||
| 3f77a1bda5 | |||
| fd57f506c1 | |||
| cca0da4bf6 | |||
| 16fb638231 | |||
| ac7b589d76 | |||
| 3f188e27a1 | |||
| 74f2229dcd | |||
| 67dc251489 | |||
| b69cb05088 | |||
| 6b0e3e7577 | |||
| 74a509ec03 | |||
| 0e4f678e2c | |||
| 269003c25d | |||
| bbbf7b32e0 | |||
| 54ee704ab9 | |||
| c58cb3ef78 | |||
| 194428ecfe | |||
| dcf26b94cd | |||
| d9e3b3a94b | |||
| e8ffe31330 | |||
| fd2f3be663 | |||
| e86ab9c081 | |||
| 66fadb2b20 | |||
| 70d0d480f6 | |||
| 477fb24036 | |||
| 0558222150 | |||
|
|
a430819d22 | ||
|
|
4e24d01b3f | ||
|
|
85a5fd0846 | ||
|
|
6781428791 | ||
| 250c9c8ff9 | |||
| cdf4ab4941 | |||
| 750434465d | |||
| 6cf8947c80 | |||
| 2aada33a6a | |||
| bf16231350 | |||
| 44658ce6b0 | |||
| 03d071acb4 | |||
| 7492bff7c8 | |||
| ff5fc69d41 | |||
| 4d9547952e | |||
| 6d2c9958f9 | |||
| 97a9a406bb | |||
| adaa892a26 | |||
| 2301e48321 | |||
| 710675180c | |||
| 1cc26c5985 | |||
| 31d95d7fd7 | |||
| 12faca5fb5 | |||
| e32c83180e | |||
| 73250f2bba | |||
| 648fb6825a | |||
| 4f73e76a34 | |||
| 68d4958e3a | |||
| 9ff62ef050 | |||
| 9f974de245 | |||
| d53947265f | |||
| 662400da13 | |||
| f143511e14 | |||
| cc221c560d | |||
| 24f44de7c0 | |||
| 9b1bd69eae | |||
| 019be569dd | |||
| 98c6263036 | |||
| 4538d9ce98 | |||
| e8c9dfce56 | |||
| fc9afa5ede | |||
| dbfe836ce3 | |||
| 5535507469 | |||
| 01183df4e9 | |||
| 43465834c3 | |||
| 0a1ca61dfb | |||
| 6402b3cae6 | |||
| c96365fe0a | |||
| 84d9ccb8bb | |||
| 655f677e91 | |||
| 5483e34c5e | |||
| b5460682c9 | |||
| 6a30173628 | |||
| 9aa7815f57 | |||
| 4ee6493eb8 | |||
| fb7635ef56 | |||
| 5e0ba7f630 | |||
| caeef0417c | |||
| b70f66960d | |||
| 89914f6c95 | |||
| 1476505262 | |||
| 29696c378a | |||
| a5483b4ca1 | |||
| c70e11d36a | |||
| c730d47cd9 | |||
|
|
200ea580f0 | ||
|
|
a90af3be49 | ||
|
|
bcdf99576c | ||
| 9b526461c6 | |||
| 1bca9f47dd | |||
| 3f09ca93a3 | |||
| a370048a12 | |||
| b18ab07e3e | |||
| 7fb23bb490 | |||
|
|
1c8571e406 | ||
|
|
40949e1edb | ||
|
|
0f0fac26db | ||
|
|
d6e2d34710 | ||
|
|
c9f854c562 | ||
|
|
f5edea5c30 | ||
|
|
0a137e06f9 | ||
|
|
1398b3112c | ||
|
|
17c4aee408 | ||
|
|
0874c019a2 | ||
|
|
208149963c | ||
|
|
3fec5a1a71 | ||
|
|
e5ccfba4f1 | ||
|
|
fd1e841150 | ||
|
|
bc98bb2d60 | ||
|
|
284db713b3 | ||
|
|
319c65a859 | ||
|
|
d374108b37 | ||
|
|
bd89f4ac32 | ||
| 1b94d783d9 | |||
| b6dff90ccd | |||
| b16c2374c4 | |||
| 30bf2d9207 | |||
| 4424e9b40a | |||
| 32a1e89b27 | |||
| 5d8d5721af | |||
| f9554bd128 | |||
| b1df97f767 | |||
| cf59695e09 | |||
| 1a2ab48c73 | |||
| 015f58226a | |||
| 740bf7adaa | |||
| 7906374553 | |||
| e9c7cfe832 | |||
| b0637aeb6a | |||
| b262aeed5d | |||
| f2c1982afa | |||
| e5bb462e36 | |||
| fabf6b6863 | |||
| 2588eef23b | |||
| a216fd0d67 | |||
| 8d6121d8b0 | |||
| 2510420cea | |||
| 0939289e2c | |||
| 5ca0ef08d4 | |||
| 962672e4ed | |||
| 470a8deae9 | |||
| ec3d48ac79 | |||
| b9c022f614 | |||
| d4257c1d02 | |||
|
|
b3b9ec17a7 | ||
|
|
b9ab977253 | ||
| 404855b637 | |||
| e2d34a993b | |||
| 7868731922 | |||
| bb2630431a | |||
| a6ac5dfb75 | |||
| 9f929eeb7a | |||
| 9f06353f60 | |||
| 9abe7f191a | |||
| 5bf30af564 | |||
| 1634624701 | |||
| 1e2fd919ff | |||
| ce81caaf14 | |||
| 426665c9d9 | |||
| 1c0fdf6f89 | |||
| eaec881594 | |||
| 59aca6d520 | |||
| 988b705a30 | |||
| a51de86c95 | |||
| 23dc0a2f88 | |||
| 26470136af | |||
| f756c001e5 | |||
| e80440d413 | |||
| 6800c90ebf | |||
| f522a42560 | |||
| 401f1b5bc4 | |||
|
|
346264f49a | ||
|
|
c721e2918f | ||
|
|
8ed850469d | ||
|
|
451642c107 | ||
|
|
e937f44ba6 | ||
|
|
5c00c2b0c8 | ||
|
|
7d468eb64d | ||
|
|
ce03f39c25 | ||
|
|
11d0601ae7 | ||
|
|
1e44112444 | ||
|
|
fb36a62104 | ||
|
|
66f2c523cf | ||
|
|
36877596ed | ||
|
|
360ee3e5a2 | ||
| 87314a0e96 | |||
| ce242bf1b4 | |||
| a8fb84daf0 | |||
| 02d1197f6b | |||
| 956ab51e1b | |||
| 02ddd1401b | |||
| a734a40668 | |||
| a558f47558 | |||
| 7047304ae5 | |||
| 9fc5f8a706 | |||
| 7fcaf6490d | |||
| f3f69a0def | |||
| 5ca1b19148 | |||
| 7cc6e7e2d4 | |||
| 4d0a6e5223 | |||
| d1609ddfbf | |||
| 1cdb372079 | |||
| b6f996139f | |||
| 46570410ea | |||
| b9da57fd88 | |||
| 9a54266967 | |||
| 8b7e109be3 | |||
| 86d37514dc | |||
|
|
f490faa796 | ||
|
|
67ea86a955 | ||
|
|
2afccaa813 | ||
|
|
0e230114a7 | ||
|
|
57ae120d4d | ||
|
|
420d5238b2 | ||
|
|
8f60a97043 | ||
| 3aee4bd3e2 | |||
| fe6f4fd43b | |||
| 3547799079 | |||
| c71650d386 | |||
| e78f28ea71 | |||
| 0555fcb9a5 | |||
| 81958f6c3b | |||
| 6e293efc2b | |||
| 371d9148f4 | |||
| 1389abb946 | |||
| 641ce4237e | |||
| 879d2959d5 | |||
| 50002907e3 | |||
| 482ad0dda2 | |||
| 0499be4194 | |||
| 3d6912b60d | |||
| efbec85b67 | |||
| c14d4e0911 | |||
| c71da66bb6 | |||
| 8531049716 | |||
| e960307172 | |||
| e20e327286 | |||
| 81b7d5558e | |||
| df41694811 | |||
| 05d5ac5a75 | |||
| 2fd6b85d7e | |||
| 587dc4f970 | |||
| a4853cb186 | |||
| 3a7a12bfd3 | |||
| 43ae26679a | |||
| eea0f688a0 | |||
| 9e1afca9ec | |||
| c263dd770e | |||
| 0b77072b04 | |||
| 0c0628529c | |||
| cdceb1a734 | |||
| c8c6cccf6a | |||
| caa394e0da | |||
| 5e1e2fb6e2 | |||
| 24035c15bf | |||
| 5d24dcafd5 | |||
| cfe2cabfa4 | |||
| 55b3f1cc8c | |||
| 3d20f063e9 | |||
| c20aa862a9 | |||
| 92ee0b2e7f | |||
| 8253554304 | |||
| 31b7c0e035 | |||
| 30d5d65755 | |||
| 1309749e46 | |||
| b63391d744 | |||
| b47c38ca76 | |||
| 361c07ce53 | |||
| b8b536632d | |||
| 0edf216618 | |||
| 887431a335 | |||
| 7ca441aaae | |||
| c5972bd15f | |||
| b0dac24eea | |||
| cfe6ce9c7e | |||
| 97d9abca62 | |||
| 02ebb6b3f6 | |||
| d6cae5ace1 | |||
| 47729d8373 | |||
| 2a9ea5ecbf | |||
| 4a9a768488 | |||
| 0b0ae9abd3 | |||
| ed19413576 | |||
| 34e145ab23 | |||
| ffa42de4f3 | |||
| 84ce544f4d | |||
| 29d11720a5 | |||
| 7071e07ef4 | |||
| eb2d2009f7 | |||
| c5a502ec32 | |||
| 89952185a9 | |||
| 039c19f61c | |||
| 372c1f6875 | |||
| 3f97ba729d | |||
| 143ac6c721 | |||
| 0759d6c2c4 | |||
| e2e04b88f4 | |||
| d3fc3894bc | |||
| 8d01a87b6c | |||
| a37c4fe723 | |||
| 78e84cf960 | |||
| 4f74ffc5ce | |||
| f53e8e3611 | |||
| 00774230af | |||
| 6f71b98209 | |||
| e7ed36caff | |||
| 6d13f0610b | |||
| 6327e911ad | |||
| 4c7a02b443 | |||
| ed5d677ae1 | |||
| 908e06c88f | |||
| 4c91462b05 | |||
| c40f086244 | |||
| da3a5181df | |||
| 8acb1750b6 | |||
| 96a8ae3de7 | |||
| e0704458ee | |||
| bbc52e58b4 | |||
| 7eaf1e1729 | |||
| ad8673a46f | |||
| 9e4076e1ea | |||
| f59dd37825 | |||
| dcd7e8fad8 | |||
| 72f821f9f2 | |||
|
|
eef868d407 | ||
| 303178b220 | |||
|
|
3fddc0eae5 | ||
|
|
b88e40802e | ||
|
|
e26c830b35 | ||
| b1ebbfe7af | |||
|
|
92b0cc3ef1 | ||
|
|
f918a3bc4b | ||
| 147e0eef36 | |||
| 45698e1d18 | |||
|
|
727f548a80 | ||
|
|
8b4a4f6dde | ||
|
|
874c825706 | ||
| dd24b4258e | |||
| 3182cc8d07 | |||
| 9be48de1fd | |||
|
|
1c3519730b | ||
|
|
2ee313d5f6 | ||
| cd89e757c1 | |||
|
|
aadf300e5e | ||
|
|
2d982b7539 | ||
| c427d080c7 | |||
| c86c838b93 | |||
| 778f9fd9eb | |||
| 257ef354c6 | |||
| 0e12ccd6bb | |||
|
|
b2255651af | ||
|
|
7cd0f07432 | ||
|
|
fbe15f413f | ||
| f27e2344e5 | |||
|
|
b140e091bc | ||
|
|
d075610195 | ||
| f8b587a7b1 | |||
| e4f7c1215b | |||
| 4db01dd910 | |||
| 46543d1f74 | |||
|
|
6992de5e2f | ||
|
|
8f4aecb236 | ||
|
|
d39694ae24 | ||
|
|
04a628e195 | ||
|
|
35a78264b8 | ||
|
|
352013c260 | ||
|
|
c93aa2438b | ||
|
|
b4e22538fc | ||
|
|
34255444bf | ||
|
|
3bb3a508f0 | ||
|
|
b1fb2a0038 | ||
|
|
6151a61c68 | ||
|
|
d142189be2 | ||
|
|
8655c2c0a5 | ||
|
|
b8faaaf4eb | ||
|
|
d90f4f3526 | ||
|
|
d418e0ffb3 | ||
|
|
ae5c41c35b | ||
|
|
52f5989b5a | ||
|
|
1a2b922c16 | ||
|
|
fbb0d7b581 | ||
|
|
9b00782e10 | ||
|
|
64f67e7ef7 | ||
|
|
296305f8f6 | ||
|
|
cf728739b3 | ||
|
|
8dcd4df750 | ||
|
|
124e45261a | ||
|
|
d22a1ad5f0 | ||
|
|
81ef228c7f | ||
|
|
32e71c14b1 | ||
|
|
694dff0f97 | ||
|
|
0b95ca2173 | ||
|
|
58c6b71e33 | ||
|
|
98e3c111b6 | ||
|
|
03992e1b2b | ||
|
|
6ee047695a | ||
|
|
c4ed84f52a | ||
| 6e3086097b | |||
| c54be64769 | |||
|
|
0e0f77ccbf | ||
|
|
750b7d294d | ||
|
|
92b6072584 | ||
|
|
b80b5aa241 | ||
|
|
9d43a39b98 | ||
|
|
c610edc819 | ||
|
|
9034d60565 | ||
|
|
d69567df7b | ||
|
|
2e266a2ad7 | ||
|
|
663190425d | ||
| 02a5733cbf | |||
| 85378091ce | |||
|
|
aabc8fcac9 | ||
| 124eb90fa0 | |||
| 7e2dfea5e7 | |||
|
|
ddc8c2014a | ||
|
|
7d1f227531 | ||
|
|
b79ab3cf4e | ||
|
|
64ee06bac3 | ||
|
|
924a1169d4 | ||
|
|
7e9f7fff56 | ||
|
|
aa47be34de | ||
|
|
3af4308dcf | ||
|
|
3165f9310e | ||
|
|
c90fe218cb | ||
|
|
447c047b42 | ||
|
|
8312c66e07 | ||
|
|
049f4b0c7c | ||
|
|
22b541ca48 | ||
|
|
51c1d7b4d8 | ||
| e2c9a90fa8 | |||
|
|
d0ea0994c1 | ||
|
|
23cb8a3b49 | ||
|
|
cee6993ed0 | ||
| 4acd2be626 | |||
|
|
4681a141e2 | ||
|
|
c3677b7689 | ||
|
|
e29822b57c | ||
|
|
0cf10aec8d | ||
|
|
c95ddbce78 | ||
|
|
b51d478f35 | ||
|
|
1ff5c25d63 | ||
|
|
0c7c9ba2a6 | ||
|
|
b7d6e9406a | ||
|
|
02e29210d3 | ||
|
|
87e45b68ce | ||
| 899e90deaf | |||
|
|
c9de1263d7 | ||
| 5c91f8a637 | |||
|
|
adf534b58e | ||
|
|
d308ac575f | ||
| 55515ccc52 | |||
|
|
2f3e636501 | ||
|
|
492631034f | ||
|
|
4cb1c43f65 | ||
| 3b438e1f91 | |||
| eb27f7a2ce | |||
|
|
8efbff3eae | ||
|
|
a9a8ab38a8 | ||
|
|
74456d9915 | ||
|
|
fa375f4d48 | ||
| 1b5216072d | |||
| c3b4f64941 | |||
| 8fd57da294 | |||
| 719d1609a8 | |||
| 0d82a1349f | |||
| e706f8974f | |||
| 49fc88667a | |||
| 79b685ea8a | |||
| a2df0ae305 | |||
| 200087f2f6 | |||
| 2b493e6d16 | |||
| 662457d0f1 | |||
| 8b1cf61209 | |||
| 10d8c121b3 | |||
| 9b2f6eadc7 | |||
| 1b192c7d05 | |||
| 3c73196f87 | |||
| caa4cf4c8d | |||
| e197062f64 | |||
| 95da0184a0 | |||
| 7b08afde06 | |||
| b340958348 | |||
| 4685f76cad | |||
| dd1580b819 | |||
| dc41880ca7 | |||
| 0c64d9b15d | |||
| cf1e7497e2 | |||
| 8a2fb36cb0 | |||
| 306dbbd024 | |||
| dfc411e5f6 | |||
| d285603716 | |||
| db08bb12c8 | |||
| b20c6c30ff | |||
| d820a1b149 | |||
| 6b55ae6395 | |||
| 606332ba6f | |||
| 629660bb79 | |||
| 73e3c6c64b | |||
|
|
362b4105c8 | ||
| 6f57c4427b | |||
| 7eed5ca957 | |||
|
|
a33fbe5896 | ||
| 3c22637f06 | |||
|
|
426e29c9a7 | ||
| 368c9af655 | |||
|
|
87fecc14cb | ||
|
|
c6c4be0431 | ||
| 24b8e09801 | |||
|
|
97d5312bb5 | ||
| 209e61f490 | |||
|
|
9758639d2f | ||
| 0831c1eb07 | |||
|
|
a30ce584fe | ||
|
|
8ef02ac7e4 | ||
|
|
fcbd9c2601 | ||
|
|
d36d7f06ac | ||
| 1a28103e7b | |||
|
|
ebb87ef2bb | ||
|
|
7c61ba39bc | ||
|
|
6c9f544500 | ||
|
|
88f997011e | ||
| 1902ab0d81 | |||
|
|
1f822413ef | ||
|
|
9ed4e7570d | ||
|
|
861bea46f7 | ||
|
|
9fab7b4df4 | ||
|
|
77794fa6f6 | ||
|
|
37fe57fdf4 | ||
|
|
5ea78f0817 | ||
|
|
df07e75737 | ||
| 42b9e07dbf | |||
| 633a02af06 | |||
| 92100c7c43 | |||
| c78e2ed9e8 | |||
| c7d70e1eec | |||
|
|
c065aa8572 | ||
| 925331383d | |||
|
|
e260414dab | ||
| 76dcdee761 | |||
|
|
c15a849bc6 | ||
| 4b06a46356 | |||
| a62cc600dc | |||
| d11030326b | |||
| b50501907c | |||
| 45d17fdd2c | |||
| 16f01257e3 | |||
|
|
5c8260bcbd | ||
| 4176bd0f0a | |||
| da29d9753d | |||
| ae2cdab9f1 | |||
| 6d702e3786 | |||
| 63e7aac754 | |||
| e7c9eca524 | |||
| b49eb3bffa | |||
| 22dd3c65d2 | |||
| 809bfc49cd | |||
|
|
da21984290 | ||
|
|
7441a3a3b1 | ||
|
|
7bba4fc0d8 | ||
|
|
8e61244e7b | ||
|
|
839548cb44 | ||
|
|
b6c5261499 | ||
|
|
9c98f9e03f | ||
|
|
464bdf201e | ||
|
|
db7c77383d | ||
|
|
cdd2c3c457 | ||
|
|
f9a0063f8d | ||
| a5094e9656 | |||
|
|
ad8dbc3c1a | ||
|
|
c2bb307a25 | ||
|
|
5f5de45be6 | ||
|
|
3e864999b9 | ||
|
|
dc4aa237fb | ||
|
|
e96a592173 | ||
|
|
9657648e0d | ||
| 0bc103386a | |||
|
|
35003b16f8 | ||
| 195ed11c62 | |||
| d9685acbbf | |||
| 18a473b987 | |||
| 2f835acd2d | |||
| 660175f4ed | |||
| e6f4f51aea | |||
| 5108649bf0 | |||
| 58c6815dc3 | |||
| 37b1ffe0ca | |||
| c5024eb79d | |||
| 1612019c7f | |||
| b0f1dc7721 | |||
| fda0fc9dc1 | |||
| 0b3ed7faaa | |||
| 27d769cd07 | |||
|
|
7a827139b7 | ||
| 848819c8cd | |||
| ab86cfca3a | |||
| 4e79f38d1e | |||
| 2618650d27 | |||
| 6aac9d1f26 | |||
|
|
f9623089a2 | ||
|
|
d187c63704 | ||
|
|
4f8a316da3 | ||
|
|
d526c23974 | ||
| fdf9163d7d | |||
| e623818585 | |||
| 70147e4fe8 | |||
| eeaf919121 | |||
| 26314265c9 | |||
| 231f63c1b7 | |||
| aba3b68eea | |||
| 475813c42c | |||
| 8d0e362951 | |||
| ca6b581c85 | |||
| c3ef7bc0e1 | |||
| 286f9f7ea8 | |||
| fa6609eea9 | |||
| 67f6ce308b | |||
| b14ac6ec02 | |||
| fa03d835ed | |||
| 7d3c73a1e9 | |||
| c0f8f22e6a | |||
| 8c038b42df | |||
| 5874e86185 | |||
| 7d617a5d28 | |||
| c84afc8e4c | |||
| 14ec227266 | |||
| 6a431a5bb4 | |||
| 6208fd2b8d | |||
| 37f866456c | |||
| 6ab12b48b0 | |||
| 7f30c187b7 | |||
| 4e4f93bf28 | |||
| a112ecb8e9 | |||
| cc3b6f268a | |||
| 59010797a8 | |||
| e3fdf0af45 | |||
| cc45bb4656 | |||
| 5991916227 | |||
| a75bd48ccf | |||
| 3ea2004267 | |||
| e91e0151ba | |||
| 5e026449cc | |||
| 5047364ad3 | |||
| c5047babca | |||
| f16fa9686c | |||
| 0f091618b7 | |||
| 9f7607cb87 | |||
| 5854c731a3 | |||
|
|
605756a794 | ||
|
|
ddc3e8f61a | ||
|
|
7bc07baf47 | ||
|
|
7f144e8cc3 | ||
|
|
67e1dadfab | ||
| def4aa38d6 | |||
|
|
dadb463042 | ||
| 80a978de5b | |||
|
|
a00b5bf432 | ||
|
|
8592a7a0a3 | ||
|
|
43a189e5ff | ||
|
|
8d2bf0a3a2 | ||
| 1897b1cb51 | |||
| d43549816e | |||
| 99411e0ce3 | |||
|
|
671c3006f4 | ||
| 948c862a70 | |||
| aa3a48f69e | |||
|
|
f11511940c | ||
|
|
990a16cfda | ||
| ba41c40f81 | |||
|
|
84dd2550a1 | ||
|
|
e7df151f14 | ||
|
|
c39260e926 | ||
|
|
79d586dfca | ||
| 7209b7d0a6 | |||
|
|
1f7443336e | ||
|
|
3657493073 | ||
|
|
d983199969 | ||
|
|
b13affb84b | ||
|
|
31ee4bfd55 | ||
| ff4edf7694 | |||
|
|
bfd9c79de8 | ||
|
|
dcb2b8b2ee | ||
|
|
e58b356378 | ||
|
|
1f7050ea6e | ||
|
|
923b1b92cc | ||
|
|
3a1cfcaea3 | ||
| 9e373a3444 | |||
|
|
8e4bf1e1cd | ||
|
|
3cfd3ef3b0 | ||
|
|
4a3a5bfa8d | ||
|
|
79c7dc0ad0 | ||
|
|
ccdd6a8709 | ||
|
|
dfa9d9d233 | ||
|
|
c8fa35b0c4 | ||
|
|
2fd50585ac | ||
| dd34425ee4 | |||
|
|
e9403a8572 | ||
| a15649b9df | |||
|
|
f4135df502 | ||
|
|
28b130540b | ||
|
|
f58c997870 | ||
|
|
141e683d02 | ||
|
|
427c0fbce5 | ||
|
|
11a3e71705 | ||
|
|
d06abca25d | ||
|
|
47774351a3 | ||
|
|
3a4c07dd1e | ||
|
|
53321ee53c | ||
|
|
4b6bc0014a | ||
|
|
ac3438a96d | ||
|
|
777984a1fb | ||
|
|
8b90ae4398 | ||
|
|
257679a19c | ||
|
|
6c9f4c7ec4 | ||
|
|
6c76b772b0 | ||
|
|
07e500e6e2 | ||
|
|
4cac395d9f | ||
|
|
085f2c27a0 | ||
|
|
2b144174a8 | ||
| df8b5658a7 |
104
.env.example
104
.env.example
@@ -1,6 +1,7 @@
|
||||
# vi: ft=sh
|
||||
# shellcheck disable=SC2034
|
||||
|
||||
# THIS IS V5 .ENV ; IF YOU ARE ON V4 PLEASE LOOK AT THE .ENV HERE: https://github.com/zoriya/Kyoo/blob/v4.7.1/.env.example
|
||||
|
||||
# Useful config options
|
||||
|
||||
@@ -9,22 +10,11 @@ LIBRARY_ROOT=./video
|
||||
# You should set this to a path where kyoo can write large amount of data, this is used as a cache by the transcoder.
|
||||
# It will automatically be cleaned up on kyoo's startup/shutdown/runtime.
|
||||
CACHE_ROOT=/tmp/kyoo_cache
|
||||
LIBRARY_LANGUAGES=en
|
||||
# A pattern (regex) to ignore video files.
|
||||
# Where to store downloaded images of the shows
|
||||
IMAGES_PATH="./images";
|
||||
# A pattern (regex) to ignore files.
|
||||
LIBRARY_IGNORE_PATTERN=".*/[dD]ownloads?/.*"
|
||||
|
||||
# If this is true, new accounts wont have any permissions before you approve them in your admin dashboard.
|
||||
REQUIRE_ACCOUNT_VERIFICATION=true
|
||||
# Specify permissions of guest accounts, default is no permissions.
|
||||
UNLOGGED_PERMISSIONS=
|
||||
# but you can allow anyone to use your instance without account by doing:
|
||||
# UNLOGGED_PERMISSIONS=overall.read,overall.play
|
||||
# You can specify this to allow guests users to see your collection without behing able to play videos for example:
|
||||
# UNLOGGED_PERMISSIONS=overall.read
|
||||
|
||||
# Specify permissions of new accounts.
|
||||
DEFAULT_PERMISSIONS=overall.read,overall.play
|
||||
|
||||
# Hardware transcoding (equivalent of --profile docker compose option).
|
||||
COMPOSE_PROFILES=cpu # cpu (no hardware acceleration) or vaapi or qsv or nvidia
|
||||
# the preset used during transcode. faster means worst quality, you can probably use a slower preset with hwaccels
|
||||
@@ -32,14 +22,9 @@ COMPOSE_PROFILES=cpu # cpu (no hardware acceleration) or vaapi or qsv or nvidia
|
||||
GOCODER_PRESET=fast
|
||||
|
||||
|
||||
# The following value should be set to a random sequence of characters.
|
||||
# You MUST change it when installing kyoo (for security)
|
||||
# You can input multiple api keys separated by a ,
|
||||
KYOO_APIKEYS=t7H5!@4iMNsAaSJQ49pat4jprJgTcF656if#J3
|
||||
|
||||
# Keep those empty to use kyoo's default api key. You can also specify a custom API key if you want.
|
||||
# go to https://www.themoviedb.org/settings/api and copy the api key (not the read access token, the api key)
|
||||
THEMOVIEDB_APIKEY=
|
||||
# go to https://www.themoviedb.org/settings/api and copy the read access token (not the api key)
|
||||
THEMOVIEDB_API_ACCESS_TOKEN=""
|
||||
# go to https://thetvdb.com/api-information/signup and copy the api key
|
||||
TVDB_APIKEY=
|
||||
# you can also input your subscriber's pin to support TVDB
|
||||
@@ -47,49 +32,50 @@ TVDB_PIN=
|
||||
|
||||
|
||||
# The url you can use to reach your kyoo instance. This is used during oidc to redirect users to your instance.
|
||||
PUBLIC_URL=http://localhost:5000
|
||||
PUBLIC_URL=http://localhost:8901
|
||||
|
||||
# Use a builtin oidc service (google, discord, trakt, or simkl):
|
||||
# When you create a client_id, secret combo you may be asked for a redirect url. You need to specify https://YOUR-PUBLIC-URL/api/auth/logged/YOUR-SERVICE-NAME
|
||||
OIDC_DISCORD_CLIENTID=
|
||||
OIDC_DISCORD_SECRET=
|
||||
# Or add your custom one:
|
||||
OIDC_SERVICE_NAME=YourPrettyName
|
||||
OIDC_SERVICE_LOGO=https://url-of-your-logo.com
|
||||
OIDC_SERVICE_CLIENTID=
|
||||
OIDC_SERVICE_SECRET=
|
||||
OIDC_SERVICE_AUTHORIZATION=https://url-of-the-authorization-endpoint-of-the-oidc-service.com/auth
|
||||
OIDC_SERVICE_TOKEN=https://url-of-the-token-endpoint-of-the-oidc-service.com/token
|
||||
OIDC_SERVICE_PROFILE=https://url-of-the-profile-endpoint-of-the-oidc-service.com/userinfo
|
||||
OIDC_SERVICE_SCOPE="the list of scopes space separeted like email identity"
|
||||
# Token authentication method as seen in https://openid.net/specs/openid-connect-core-1_0.html#ClientAuthentication
|
||||
# Supported values: ClientSecretBasic (default) or ClientSecretPost
|
||||
# If in doubt, leave this empty.
|
||||
OIDC_SERVICE_AUTHMETHOD=ClientSecretBasic
|
||||
# on the previous list, service is the internal name of your service, you can add as many as you want.
|
||||
# Default permissions of new users. They are able to browse & play videos.
|
||||
# Set `verified` to true if you don't wanna manually verify users.
|
||||
EXTRA_CLAIMS='{"permissions": ["core.read", "core.play"], "verified": false}'
|
||||
# This is the permissions of the first user (aka the first user is admin)
|
||||
FIRST_USER_CLAIMS='{"permissions": ["users.read", "users.write", "users.delete", "apikeys.read", "apikeys.write", "core.read", "core.write", "core.play", "scanner.trigger"], "verified": true}'
|
||||
|
||||
# Guest (meaning unlogged in users) can be:
|
||||
# unauthorized (they need to connect before doing anything)
|
||||
# GUEST_CLAIMS=""
|
||||
# able to browse & see what you have but not able to play
|
||||
GUEST_CLAIMS='{"permissions": ["core.read"], "verified": true}'
|
||||
# or have browse & play permissions
|
||||
GUEST_CLAIMS='{"permissions": ["core.read", "core.play"], "verified": true}'
|
||||
|
||||
# DO NOT change this.
|
||||
PROTECTED_CLAIMS="permissions,verified"
|
||||
|
||||
|
||||
# Following options are optional and only useful for debugging.
|
||||
# You can create apikeys at runtime via POST /keys but you can also have some defined in the env.
|
||||
# Replace $YOURNAME with the name of the key you want (only alpha are valid)
|
||||
# The value will be the apikey (max 128 bytes)
|
||||
KEIBI_APIKEY_SCANNER=EJqUB8robwKwLNt37SuHqdcsNGrtwpfYxeExfiAbokpxZVd4WctWr7gnSZ
|
||||
KEIBI_APIKEY_SCANNER_CLAIMS='{"permissions": ["core.read", "core.write"]}'
|
||||
|
||||
# To debug the front end, you can set the following to an external backend
|
||||
KYOO_URL=
|
||||
|
||||
# Database things
|
||||
POSTGRES_USER=KyooUser
|
||||
POSTGRES_PASSWORD=KyooPassword
|
||||
POSTGRES_DB=kyooDB
|
||||
POSTGRES_SERVER=postgres
|
||||
POSTGRES_PORT=5432
|
||||
OTEL_EXPORTER_OTLP_ENDPOINT="http://localhost:4317"
|
||||
OTEL_EXPORTER_OTLP_PROTOCOL="http/protobuf"
|
||||
|
||||
# Read by the api container to know if it should run meilisearch's migrations/sync
|
||||
# and download missing images. This is a good idea to only have one instance with this on
|
||||
# Note: it does not run postgres migrations, use the migration container for that.
|
||||
RUN_MIGRATIONS=true
|
||||
|
||||
MEILI_HOST="http://meilisearch:7700"
|
||||
MEILI_MASTER_KEY="ghvjkgisbgkbgskegblfqbgjkebbhgwkjfb"
|
||||
|
||||
RABBITMQ_HOST=rabbitmq
|
||||
RABBITMQ_PORT=5672
|
||||
RABBITMQ_DEFAULT_USER=kyoo
|
||||
RABBITMQ_DEFAULT_PASS=aohohunuhouhuhhoahothonseuhaoensuthoaentsuhha
|
||||
# It is recommended to use the below PG environment variables when possible.
|
||||
# POSTGRES_URL=postgres://user:password@hostname:port/dbname?sslmode=verify-full&sslrootcert=/path/to/server.crt&sslcert=/path/to/client.crt&sslkey=/path/to/client.key
|
||||
# The behavior of the below variables match what is documented here:
|
||||
# https://www.postgresql.org/docs/current/libpq-envars.html
|
||||
PGUSER=kyoo
|
||||
PGPASSWORD=password
|
||||
PGDATABASE=kyoo
|
||||
PGHOST=postgres
|
||||
PGPORT=5432
|
||||
# PGOPTIONS=-c search_path=kyoo,public
|
||||
# PGPASSFILE=/my/password # Takes precedence over PGPASSWORD. New line characters are not trimmed.
|
||||
# PGSSLMODE=verify-full
|
||||
# PGSSLROOTCERT=/my/serving.crt
|
||||
# PGSSLCERT=/my/client.crt
|
||||
# PGSSLKEY=/my/client.key=password
|
||||
|
||||
@@ -1,3 +0,0 @@
|
||||
7e6e56a366babe17e7891a5897180efbf93c00c5
|
||||
a5638203a6ecb9f372a5a61e1c8fd443bf3a17fe
|
||||
18e301f26acd7f2e97eac26c5f48377fa13956f5
|
||||
1
.gitattributes
vendored
1
.gitattributes
vendored
@@ -1 +0,0 @@
|
||||
*.Designer.cs linguist-generated=true
|
||||
1
.github/CODEOWNERS
vendored
Normal file
1
.github/CODEOWNERS
vendored
Normal file
@@ -0,0 +1 @@
|
||||
chart/ @acelinkio
|
||||
41
.github/workflows/api-test.yml
vendored
Normal file
41
.github/workflows/api-test.yml
vendored
Normal file
@@ -0,0 +1,41 @@
|
||||
name: Tests
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- master
|
||||
- next
|
||||
pull_request:
|
||||
workflow_dispatch:
|
||||
|
||||
jobs:
|
||||
test:
|
||||
name: Test api
|
||||
runs-on: ubuntu-latest
|
||||
services:
|
||||
postgres:
|
||||
image: postgres:15
|
||||
ports:
|
||||
- "5432:5432"
|
||||
env:
|
||||
POSTGRES_USER: kyoo
|
||||
POSTGRES_PASSWORD: password
|
||||
POSTGRES_DB: kyoo_test
|
||||
options: >-
|
||||
--health-cmd pg_isready
|
||||
--health-interval 10s
|
||||
--health-timeout 5s
|
||||
--health-retries 5
|
||||
steps:
|
||||
- uses: actions/checkout@v6
|
||||
- uses: oven-sh/setup-bun@v2
|
||||
|
||||
- name: Install dependencies
|
||||
working-directory: ./api
|
||||
run: bun install --frozen-lockfile
|
||||
|
||||
- name: Test
|
||||
working-directory: ./api
|
||||
run: bun test
|
||||
env:
|
||||
PGHOST: localhost
|
||||
IMAGES_PATH: ./images
|
||||
64
.github/workflows/auth-hurl.yml
vendored
Normal file
64
.github/workflows/auth-hurl.yml
vendored
Normal file
@@ -0,0 +1,64 @@
|
||||
name: HurlTests
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- master
|
||||
- next
|
||||
pull_request:
|
||||
|
||||
|
||||
jobs:
|
||||
test:
|
||||
name: Hurl tests Auth
|
||||
runs-on: ubuntu-latest
|
||||
services:
|
||||
postgres:
|
||||
image: postgres:15
|
||||
ports:
|
||||
- "5432:5432"
|
||||
env:
|
||||
POSTGRES_USER: kyoo
|
||||
POSTGRES_PASSWORD: password
|
||||
options: >-
|
||||
--health-cmd pg_isready
|
||||
--health-interval 10s
|
||||
--health-timeout 5s
|
||||
--health-retries 5
|
||||
steps:
|
||||
- uses: actions/checkout@v6
|
||||
|
||||
- uses: gacts/install-hurl@v1
|
||||
|
||||
- uses: actions/setup-go@v6
|
||||
with:
|
||||
go-version: '^1.22.5'
|
||||
cache-dependency-path: ./auth/go.sum
|
||||
|
||||
- name: Install dependencies
|
||||
working-directory: ./auth
|
||||
run: |
|
||||
go mod download
|
||||
|
||||
- name: Build
|
||||
working-directory: ./auth
|
||||
run: |
|
||||
go build -o ./keibi
|
||||
|
||||
- name: Run hurl tests
|
||||
working-directory: ./auth
|
||||
run: |
|
||||
./keibi > logs &
|
||||
wget --retry-connrefused --retry-on-http-error=502 http://localhost:4568/auth/health
|
||||
hurl --error-format long --variable host=http://localhost:4568/auth tests/*
|
||||
env:
|
||||
PGHOST: localhost
|
||||
FIRST_USER_CLAIMS: '{"permissions": ["users.read"]}'
|
||||
KEIBI_APIKEY_HURL: 1234apikey
|
||||
KEIBI_APIKEY_HURL_CLAIMS: '{"permissions": ["apikeys.write", "apikeys.read"]}'
|
||||
|
||||
|
||||
- name: Show logs
|
||||
if: failure()
|
||||
working-directory: ./auth
|
||||
run: cat logs
|
||||
|
||||
37
.github/workflows/coding-style.yml
vendored
37
.github/workflows/coding-style.yml
vendored
@@ -2,19 +2,22 @@ name: Coding Style
|
||||
on: [pull_request, workflow_dispatch]
|
||||
|
||||
jobs:
|
||||
back:
|
||||
name: "Lint Back"
|
||||
api:
|
||||
name: "Lint api"
|
||||
runs-on: ubuntu-latest
|
||||
defaults:
|
||||
run:
|
||||
working-directory: ./back
|
||||
working-directory: ./api
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: actions/checkout@v6
|
||||
|
||||
- name: Check coding style
|
||||
run: |
|
||||
dotnet tool restore
|
||||
dotnet csharpier . --check
|
||||
- name: Setup Biome
|
||||
uses: biomejs/setup-biome@v2
|
||||
with:
|
||||
version: latest
|
||||
|
||||
- name: Run Biome
|
||||
run: biome ci .
|
||||
|
||||
front:
|
||||
name: "Lint Front"
|
||||
@@ -23,7 +26,7 @@ jobs:
|
||||
run:
|
||||
working-directory: ./front
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: actions/checkout@v6
|
||||
|
||||
- name: Setup Biome
|
||||
uses: biomejs/setup-biome@v2
|
||||
@@ -37,7 +40,7 @@ jobs:
|
||||
name: "Lint scanner/autosync"
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: actions/checkout@v6
|
||||
|
||||
- uses: chartboost/ruff-action@v1
|
||||
with:
|
||||
@@ -50,7 +53,19 @@ jobs:
|
||||
run:
|
||||
working-directory: ./transcoder
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: actions/checkout@v6
|
||||
|
||||
- name: Run go fmt
|
||||
run: if [ "$(gofmt -s -l . | wc -l)" -gt 0 ]; then exit 1; fi
|
||||
|
||||
auth:
|
||||
name: "Lint auth"
|
||||
runs-on: ubuntu-latest
|
||||
defaults:
|
||||
run:
|
||||
working-directory: ./auth
|
||||
steps:
|
||||
- uses: actions/checkout@v6
|
||||
|
||||
- name: Run go fmt
|
||||
run: if [ "$(gofmt -s -l . | wc -l)" -gt 0 ]; then exit 1; fi
|
||||
|
||||
34
.github/workflows/docker.yml
vendored
34
.github/workflows/docker.yml
vendored
@@ -19,38 +19,40 @@ jobs:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
include:
|
||||
- context: ./back
|
||||
- context: ./api
|
||||
dockerfile: Dockerfile
|
||||
label: back
|
||||
image: zoriya/kyoo_back
|
||||
|
||||
- context: ./back
|
||||
dockerfile: Dockerfile.migrations
|
||||
label: migrations
|
||||
image: zoriya/kyoo_migrations
|
||||
label: api
|
||||
image: ${{ github.repository_owner }}/kyoo_api
|
||||
|
||||
- context: ./front
|
||||
dockerfile: Dockerfile
|
||||
label: front
|
||||
image: zoriya/kyoo_front
|
||||
image: ${{ github.repository_owner }}/kyoo_front
|
||||
|
||||
- context: ./scanner
|
||||
dockerfile: Dockerfile
|
||||
label: scanner
|
||||
image: zoriya/kyoo_scanner
|
||||
image: ${{ github.repository_owner }}/kyoo_scanner
|
||||
|
||||
- context: ./autosync
|
||||
dockerfile: Dockerfile
|
||||
label: autosync
|
||||
image: zoriya/kyoo_autosync
|
||||
image: ${{ github.repository_owner }}/kyoo_autosync
|
||||
|
||||
- context: ./transcoder
|
||||
dockerfile: Dockerfile
|
||||
label: transcoder
|
||||
image: zoriya/kyoo_transcoder
|
||||
image: ${{ github.repository_owner }}/kyoo_transcoder
|
||||
|
||||
- context: ./auth
|
||||
dockerfile: Dockerfile
|
||||
label: auth
|
||||
image: ${{ github.repository_owner }}/kyoo_auth
|
||||
env:
|
||||
DOCKERHUB_ENABLED: ${{ secrets.DOCKER_USERNAME && secrets.DOCKER_PASSWORD && 'true' || 'false' }}
|
||||
name: Build ${{matrix.label}}
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: actions/checkout@v6
|
||||
|
||||
- uses: dorny/paths-filter@v3
|
||||
id: filter
|
||||
@@ -64,7 +66,7 @@ jobs:
|
||||
uses: docker/metadata-action@v5
|
||||
with:
|
||||
images: |
|
||||
docker.io/${{matrix.image}}
|
||||
docker.io/${{matrix.image}},enable=${{ env.DOCKERHUB_ENABLED }}
|
||||
ghcr.io/${{matrix.image}}
|
||||
tags: |
|
||||
type=edge
|
||||
@@ -84,7 +86,7 @@ jobs:
|
||||
uses: docker/setup-buildx-action@v3
|
||||
|
||||
- name: Login to DockerHub
|
||||
if: env.SHOULD_PUSH == 'true'
|
||||
if: env.SHOULD_PUSH == 'true' && env.DOCKERHUB_ENABLED == 'true'
|
||||
uses: docker/login-action@v3
|
||||
with:
|
||||
username: ${{ secrets.DOCKER_USERNAME }}
|
||||
@@ -114,7 +116,7 @@ jobs:
|
||||
cache-to: type=gha,mode=max
|
||||
|
||||
- name: Sync README.MD
|
||||
if: env.SHOULD_PUSH == 'true'
|
||||
if: env.SHOULD_PUSH == 'true' && env.DOCKERHUB_ENABLED == 'true'
|
||||
uses: ms-jpq/sync-dockerhub-readme@v1
|
||||
with:
|
||||
username: ${{ secrets.DOCKER_USERNAME }}
|
||||
|
||||
54
.github/workflows/helm-release-chart.yml
vendored
Normal file
54
.github/workflows/helm-release-chart.yml
vendored
Normal file
@@ -0,0 +1,54 @@
|
||||
name: Release Helm Chart
|
||||
on:
|
||||
push:
|
||||
tags:
|
||||
- v*
|
||||
workflow_dispatch:
|
||||
inputs:
|
||||
channel:
|
||||
description: 'Release channel (master, edge, or leave blank for tag-based)'
|
||||
required: false
|
||||
default: 'master'
|
||||
|
||||
jobs:
|
||||
release:
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@1af3b93b6815bc44a9784bd300feb67ff0d1eeb3 # v6.0.0
|
||||
|
||||
- name: Set up Helm
|
||||
uses: azure/setup-helm@1a275c3b69536ee54be43f2070a358922e12c8d4 # v4.3.1
|
||||
|
||||
- name: Log in to GHCR
|
||||
uses: docker/login-action@5e57cd118135c172c3672efd75eb46360885c0ef # v3.6.0
|
||||
with:
|
||||
registry: ghcr.io
|
||||
username: ${{ github.actor }}
|
||||
password: ${{ secrets.GITHUB_TOKEN }}
|
||||
|
||||
- name: Update Helm Dependencies
|
||||
run: helm dependency update ./chart
|
||||
|
||||
- name: Determine Chart Version
|
||||
id: version
|
||||
run: |
|
||||
if [ "${{ github.event_name }}" = "workflow_dispatch" ]; then
|
||||
TAG="${{ github.event.inputs.channel }}"
|
||||
else
|
||||
TAG=$(echo ${GITHUB_REF#refs/tags/} | sed 's/^v//')
|
||||
fi
|
||||
echo "TAG=$TAG" >> "${GITHUB_ENV}"
|
||||
echo "Using chart version: $TAG"
|
||||
|
||||
- name: Package Helm Chart
|
||||
run: helm package ./chart --version $TAG --app-version $TAG
|
||||
|
||||
- name: Build Helm-safe repo name
|
||||
run: |
|
||||
REPO_NAME="$(echo "oci://ghcr.io/${GITHUB_REPOSITORY_OWNER}/helm-charts" | tr '[:upper:]' '[:lower:]')"
|
||||
echo "REPO_NAME=${REPO_NAME}" >> "${GITHUB_ENV}"
|
||||
|
||||
- name: Push Helm Chart to GHCR
|
||||
run: helm push kyoo-*.tgz "${REPO_NAME}"
|
||||
45
.github/workflows/helm-test-chart.yml
vendored
Normal file
45
.github/workflows/helm-test-chart.yml
vendored
Normal file
@@ -0,0 +1,45 @@
|
||||
name: Test Helm Chart
|
||||
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- master
|
||||
- next
|
||||
pull_request:
|
||||
workflow_dispatch:
|
||||
|
||||
jobs:
|
||||
test-helm-chart:
|
||||
name: Test Helm Chart
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@v6
|
||||
|
||||
- name: Set up Helm
|
||||
uses: azure/setup-helm@v4
|
||||
|
||||
- name: Lint the Helm chart
|
||||
run: |
|
||||
helm lint ./chart
|
||||
|
||||
- name: Create Kind cluster
|
||||
uses: helm/kind-action@v1
|
||||
|
||||
- name: Install Helm chart in Kind cluster (Dry Run)
|
||||
run: |
|
||||
helm dependency update ./chart
|
||||
helm install test-release ./chart --dry-run --debug
|
||||
|
||||
- name: Deploy Helm chart to Kind cluster
|
||||
run: |
|
||||
helm install test-release ./chart
|
||||
|
||||
- name: Verify Helm release
|
||||
run: |
|
||||
kubectl get all
|
||||
|
||||
- name: Cleanup Kind cluster
|
||||
run: |
|
||||
kind delete cluster
|
||||
31
.github/workflows/native-build.yml
vendored
31
.github/workflows/native-build.yml
vendored
@@ -13,52 +13,63 @@ jobs:
|
||||
working-directory: ./front
|
||||
steps:
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@v4
|
||||
uses: actions/checkout@v6
|
||||
|
||||
- name: Check for EXPO_TOKEN
|
||||
# This is required because GHA doesn't support secrets in the `if` condition
|
||||
- name: Check if Expo build is enabled
|
||||
env:
|
||||
IS_SECRET_SET: ${{ env.IS_EXPO_ENABLED == 'true' && 'true' || 'false' }}
|
||||
run: echo "IS_EXPO_ENABLED=${IS_SECRET_SET}" >> "${GITHUB_ENV}"
|
||||
|
||||
- name: Log if Expo build is disabled due to fork
|
||||
if: env.IS_EXPO_ENABLED != 'true'
|
||||
run: |
|
||||
if [ -z "${{ secrets.EXPO_TOKEN }}" ]; then
|
||||
echo "You must provide an EXPO_TOKEN secret linked to this project's Expo account in this repo's secrets. Learn more: https://docs.expo.dev/eas-update/github-actions"
|
||||
exit 1
|
||||
fi
|
||||
echo "Expo build is disabled for forks. To enable it, add an EXPO_TOKEN secret to this repository. See https://docs.expo.dev/eas-update/github-actions/ for more information."
|
||||
|
||||
- name: Setup Node
|
||||
uses: actions/setup-node@v4
|
||||
uses: actions/setup-node@v6
|
||||
if: env.IS_EXPO_ENABLED == 'true'
|
||||
with:
|
||||
node-version: 18.x
|
||||
node-version: 24.x
|
||||
cache: yarn
|
||||
cache-dependency-path: front/yarn.lock
|
||||
|
||||
- name: Setup Expo
|
||||
uses: expo/expo-github-action@v8
|
||||
if: env.IS_EXPO_ENABLED == 'true'
|
||||
with:
|
||||
expo-version: latest
|
||||
eas-version: latest
|
||||
token: ${{ secrets.EXPO_TOKEN }}
|
||||
|
||||
- name: Install dependencies
|
||||
if: env.IS_EXPO_ENABLED == 'true'
|
||||
run: yarn install --immutable
|
||||
|
||||
- name: Build Mobile Release
|
||||
if: env.IS_EXPO_ENABLED == 'true'
|
||||
run: yarn build:mobile:apk | tee log.txt
|
||||
|
||||
- name: Parse Asset URL
|
||||
id: url
|
||||
if: env.IS_EXPO_ENABLED == 'true'
|
||||
run: |
|
||||
ASSET_URL=$(cat log.txt | jq '.[0].artifacts.buildUrl' -r)
|
||||
echo The android url is $ASSET_URL
|
||||
echo "assetUrl=$ASSET_URL" >> $GITHUB_OUTPUT
|
||||
|
||||
- name: Download APK Asset
|
||||
if: env.IS_EXPO_ENABLED == 'true'
|
||||
run: wget -O kyoo.apk ${{ steps.url.outputs.assetUrl }}
|
||||
|
||||
- uses: actions/upload-artifact@v4
|
||||
- uses: actions/upload-artifact@v5
|
||||
if: env.IS_EXPO_ENABLED == 'true'
|
||||
with:
|
||||
name: kyoo.apk
|
||||
path: ./front/kyoo.apk
|
||||
|
||||
- name: Upload release artifacts
|
||||
uses: softprops/action-gh-release@v2
|
||||
if: startsWith(github.ref, 'refs/tags/')
|
||||
if: env.IS_EXPO_ENABLED == 'true' && startsWith(github.ref, 'refs/tags/')
|
||||
with:
|
||||
files: ./front/kyoo.apk
|
||||
|
||||
24
.github/workflows/native-update.yml
vendored
24
.github/workflows/native-update.yml
vendored
@@ -13,31 +13,39 @@ jobs:
|
||||
working-directory: ./front
|
||||
steps:
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@v4
|
||||
uses: actions/checkout@v6
|
||||
|
||||
- name: Check for EXPO_TOKEN
|
||||
# This is required because GHA doesn't support secrets in the `if` condition
|
||||
- name: Check if Expo build is enabled
|
||||
env:
|
||||
IS_SECRET_SET: ${{ env.IS_EXPO_ENABLED == 'true' && 'true' || 'false' }}
|
||||
run: echo "IS_EXPO_ENABLED=${IS_SECRET_SET}" >> "${GITHUB_ENV}"
|
||||
|
||||
- name: Log if Expo build is disabled due to fork
|
||||
if: env.IS_EXPO_ENABLED != 'true'
|
||||
run: |
|
||||
if [ -z "${{ secrets.EXPO_TOKEN }}" ]; then
|
||||
echo "You must provide an EXPO_TOKEN secret linked to this project's Expo account in this repo's secrets. Learn more: https://docs.expo.dev/eas-update/github-actions"
|
||||
exit 1
|
||||
fi
|
||||
echo "Expo build is disabled for forks. To enable it, add an EXPO_TOKEN secret to this repository. See https://docs.expo.dev/eas-update/github-actions/ for more information."
|
||||
|
||||
- name: Setup Node
|
||||
uses: actions/setup-node@v4
|
||||
uses: actions/setup-node@v6
|
||||
if: env.IS_EXPO_ENABLED == 'true'
|
||||
with:
|
||||
node-version: 18.x
|
||||
node-version: 24.x
|
||||
cache: yarn
|
||||
cache-dependency-path: front/yarn.lock
|
||||
|
||||
- name: Setup Expo
|
||||
uses: expo/expo-github-action@v8
|
||||
if: env.IS_EXPO_ENABLED == 'true'
|
||||
with:
|
||||
expo-version: latest
|
||||
eas-version: latest
|
||||
token: ${{ secrets.EXPO_TOKEN }}
|
||||
|
||||
- name: Install dependencies
|
||||
if: env.IS_EXPO_ENABLED == 'true'
|
||||
run: yarn install --immutable
|
||||
|
||||
- name: Publish update
|
||||
if: env.IS_EXPO_ENABLED == 'true'
|
||||
run: yarn update
|
||||
|
||||
11
.github/workflows/release.yml
vendored
11
.github/workflows/release.yml
vendored
@@ -10,7 +10,7 @@ jobs:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@v4
|
||||
uses: actions/checkout@v6
|
||||
|
||||
- name: Set correct versions
|
||||
run: |
|
||||
@@ -19,12 +19,9 @@ jobs:
|
||||
VERSION=${VERSION%.*} # Remove minor version
|
||||
sed "s/edge/$VERSION/" -i docker-compose.yml
|
||||
|
||||
- uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: docker-compose.yml
|
||||
path: ./docker-compose.yml
|
||||
|
||||
- name: Upload release artifacts
|
||||
uses: softprops/action-gh-release@v2
|
||||
with:
|
||||
files: ./docker-compose.yml
|
||||
files: |
|
||||
./docker-compose.yml
|
||||
./.env.example
|
||||
|
||||
50
.github/workflows/robot.yml
vendored
50
.github/workflows/robot.yml
vendored
@@ -1,50 +0,0 @@
|
||||
name: RobotTests
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- master
|
||||
- next
|
||||
pull_request:
|
||||
|
||||
|
||||
jobs:
|
||||
test:
|
||||
name: Run Robot Tests
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
|
||||
- name: Pull images
|
||||
run: |
|
||||
cp .env.example .env
|
||||
docker compose version
|
||||
docker compose pull
|
||||
|
||||
- name: Docker cache
|
||||
uses: satackey/action-docker-layer-caching@v0.0.11
|
||||
continue-on-error: true
|
||||
|
||||
- name: Start the service
|
||||
run: |
|
||||
docker compose up -d back postgres traefik meilisearch --wait
|
||||
|
||||
- name: Perform healthchecks
|
||||
run: |
|
||||
docker compose ps -a
|
||||
docker compose logs
|
||||
wget --retry-connrefused --retry-on-http-error=502 http://localhost:8901/api/health || (docker compose logs && exit 1)
|
||||
|
||||
- name: Run robot tests
|
||||
run: |
|
||||
pip install -r back/tests/robot/requirements.txt
|
||||
robot -d out back/tests/robot/
|
||||
|
||||
- name: Show logs
|
||||
if: failure()
|
||||
run: docker compose logs
|
||||
|
||||
- uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: results
|
||||
path: out
|
||||
|
||||
4
.gitignore
vendored
4
.gitignore
vendored
@@ -1,4 +1,5 @@
|
||||
/video
|
||||
.devspace/
|
||||
.env
|
||||
.venv
|
||||
.idea
|
||||
@@ -6,3 +7,6 @@
|
||||
log.html
|
||||
output.xml
|
||||
report.html
|
||||
chart/charts
|
||||
chart/Chart.lock
|
||||
tmp
|
||||
|
||||
@@ -3,3 +3,5 @@ function-case=1 #lowercase
|
||||
keyword-case=1
|
||||
type-case=1
|
||||
no-space-function=1
|
||||
keep-newline=1
|
||||
nogrouping=1
|
||||
|
||||
@@ -1,4 +0,0 @@
|
||||
# Authors
|
||||
Ordered by the date of the first commit.
|
||||
|
||||
* Zoe Roux ([@zoriya](http://github.com/zoriya))
|
||||
249
DIAGRAMS.md
Normal file
249
DIAGRAMS.md
Normal file
@@ -0,0 +1,249 @@
|
||||
# Diagrams
|
||||
These diagrams are created with Mermaid and rendered locally. For the best experience, please use a browser.
|
||||
|
||||
# Project Structure
|
||||
Kyoo is a monorepo that consists of several projects each in their own directory. Diagram below shows an outline of kyoo, projects, and artifacts.
|
||||
|
||||
```mermaid
|
||||
block
|
||||
columns 1
|
||||
block:proj1:1
|
||||
proj_name["Kyoo"]:1
|
||||
end
|
||||
block:proj2:1
|
||||
dir_1["api/"]
|
||||
dir_2["auth/"]
|
||||
dir_3["front/"]
|
||||
dir_4["transcoder/"]
|
||||
dir_5["scanner/"]
|
||||
end
|
||||
block:proj3:1
|
||||
%% columns auto (default)
|
||||
block:api_b:1
|
||||
autosync_i1("kyoo_api")
|
||||
end
|
||||
block:auth_b:1
|
||||
columns 1
|
||||
back_i1("kyoo_auth")
|
||||
end
|
||||
block:front_b:1
|
||||
front_i1("kyoo_front")
|
||||
end
|
||||
block:transcoder_b:1
|
||||
transcoder_i1("kyoo_transcoder")
|
||||
end
|
||||
block:scanner_b:1
|
||||
columns 1
|
||||
scanner_i1("kyoo_scanner")
|
||||
end
|
||||
end
|
||||
|
||||
style proj_name fill:transparent,stroke-width:0px
|
||||
style proj1 fill:#1168bd,stroke-width:0px
|
||||
style proj2 fill:#1168bd,stroke-width:0px
|
||||
style proj3 fill:#1168bd,stroke-width:0px
|
||||
|
||||
style dir_1 fill:#438dd5,stroke-width:0px
|
||||
style dir_2 fill:#438dd5,stroke-width:0px
|
||||
style dir_3 fill:#438dd5,stroke-width:0px
|
||||
style dir_4 fill:#438dd5,stroke-width:0px
|
||||
style dir_5 fill:#438dd5,stroke-width:0px
|
||||
|
||||
style api_b fill:#438dd5,stroke-width:0px
|
||||
style auth_b fill:#438dd5,stroke-width:0px
|
||||
style front_b fill:#438dd5,stroke-width:0px
|
||||
style transcoder_b fill:#438dd5,stroke-width:0px
|
||||
style scanner_b fill:#438dd5,stroke-width:0px
|
||||
|
||||
style autosync_i1 fill:#85bbf0,stroke-width:0px
|
||||
style back_i1 fill:#85bbf0,stroke-width:0px
|
||||
style front_i1 fill:#85bbf0,stroke-width:0px
|
||||
style transcoder_i1 fill:#85bbf0,stroke-width:0px
|
||||
style scanner_i1 fill:#85bbf0,stroke-width:0px
|
||||
```
|
||||
|
||||
# C4 Diagrams
|
||||
Diagrams that focus on capturing project from a high level point of view. Context, Container, Component, Code
|
||||
|
||||
## Context
|
||||
```mermaid
|
||||
C4Context
|
||||
UpdateLayoutConfig($c4ShapeInRow="2", $c4BoundaryInRow="2")
|
||||
|
||||
title Context Diagram for Kyoo
|
||||
|
||||
Person(user, "User")
|
||||
System(kyoo, "Kyoo", "")
|
||||
System_Ext(media, "MediaLibrary", "")
|
||||
System_Ext(content, "ContentDatabase", "")
|
||||
System_Ext(tracker, "ActivityTracker", "")
|
||||
|
||||
Rel(user, kyoo, "")
|
||||
Rel(kyoo, content, "")
|
||||
Rel(kyoo, media, "")
|
||||
Rel(kyoo, tracker, "")
|
||||
```
|
||||
|
||||
## Container
|
||||
Kyoo leverages the [API Gateway](https://learn.microsoft.com/en-us/azure/architecture/microservices/design/gateway) approach to microservices and [offloads](https://learn.microsoft.com/en-us/azure/architecture/patterns/gateway-offloading) authentication at the gateway.
|
||||
|
||||
```mermaid
|
||||
C4Container
|
||||
UpdateLayoutConfig($c4ShapeInRow="3", $c4BoundaryInRow="1")
|
||||
|
||||
title Container diagram for Kyoo System
|
||||
|
||||
Person(user, "User")
|
||||
Container(apigateway, "API Gateway")
|
||||
Container(auth, "auth")
|
||||
Container(transcoder, "transcoder")
|
||||
Container(scanner, "scanner")
|
||||
Container(frontend, "front")
|
||||
System_Ext(media, "MediaLibrary", "")
|
||||
System_Ext(content, "ContentDatabase", "")
|
||||
Container(api, "api")
|
||||
System_Ext(tracker, "ActivityTracker", "")
|
||||
|
||||
|
||||
Rel(user, apigateway, "")
|
||||
Rel(apigateway, frontend, "")
|
||||
Rel(apigateway, scanner, "")
|
||||
Rel(apigateway, transcoder, "")
|
||||
Rel(apigateway, api, "")
|
||||
Rel(apigateway, auth, "")
|
||||
Rel(frontend, api, "")
|
||||
Rel(api, tracker, "")
|
||||
Rel(api, content, "")
|
||||
Rel(scanner, api, "")
|
||||
Rel(scanner, media, "")
|
||||
Rel(scanner, content, "")
|
||||
Rel(transcoder, media, "")
|
||||
```
|
||||
## Component
|
||||
#### Auth
|
||||
Auth microservice is implicitly used by each other microservice for both end user authentication and microservice to microservice communications. Auth microservice will not be directly represented in the other component diagrams. Instead in their relationsihp will specify "auth via middleware".
|
||||
|
||||
```mermaid
|
||||
C4Component
|
||||
UpdateLayoutConfig($c4ShapeInRow="5", $c4BoundaryInRow="2")
|
||||
|
||||
title Auth Component Diagram
|
||||
|
||||
Container_Boundary(auth, "auth") {
|
||||
Component(auth_c1, "kyoo_auth", "Go", "")
|
||||
ComponentDb(auth_db1, "kelbi", "Postgres", "")
|
||||
}
|
||||
Rel(auth_c1, auth_db1, "")
|
||||
```
|
||||
|
||||
#### Api
|
||||
```mermaid
|
||||
C4Component
|
||||
UpdateLayoutConfig($c4ShapeInRow="2", $c4BoundaryInRow="2")
|
||||
|
||||
title Api Component Diagram
|
||||
|
||||
Person(user, "User")
|
||||
Container_Boundary(api, "api") {
|
||||
ComponentDb(api_db1, "kyoo", "Postgres", "")
|
||||
Component(api_c1, "kyoo_api", "TypeScript", "")
|
||||
Component(api_c2, "ApiMetadata", "S3/Volume", "Persistent. Distributed Metadata")
|
||||
}
|
||||
Container_Boundary(scanner, "scanner") {
|
||||
Component(scanner_c1, "kyoo_scanner", "Python", "")
|
||||
}
|
||||
|
||||
System_Boundary(external, "") {
|
||||
System_Ext(tracker, "ActivityTracker", "")
|
||||
System_Ext(content, "ContentDatabase", "")
|
||||
}
|
||||
|
||||
Container_Boundary(front, "front") {
|
||||
Component(front_c1, "kyoo_front", "TypeScript", "")
|
||||
}
|
||||
|
||||
Rel(user, api_c1, "auth via middleware")
|
||||
Rel(api_c1, api_db1, "")
|
||||
Rel(api_c1, api_c2, "")
|
||||
Rel(api_c1, content, "http(s) <br/> retries media images")
|
||||
Rel(api_c1, tracker, "")
|
||||
Rel(scanner_c1, api_c1, "auth via middleware")
|
||||
Rel(front_c1, api_c1, "http(s) SSR <br/> auth via middleware")
|
||||
```
|
||||
|
||||
#### Front
|
||||
```mermaid
|
||||
C4Component
|
||||
UpdateLayoutConfig($c4ShapeInRow="5", $c4BoundaryInRow="2")
|
||||
|
||||
title Front Component Diagram
|
||||
|
||||
Person(user, "User")
|
||||
Container_Boundary(front, "front") {
|
||||
Component(front_c1, "kyoo_front", "TypeScript", "")
|
||||
}
|
||||
|
||||
Container_Boundary(api, "api") {
|
||||
Component(api_c1, "kyoo_api", "TypeScript", "")
|
||||
}
|
||||
Rel(user, front_c1, "")
|
||||
Rel(front_c1, api_c1, "http(s) SSR <br/> auth via middleware")
|
||||
```
|
||||
|
||||
|
||||
#### Transcoder
|
||||
```mermaid
|
||||
C4Component
|
||||
UpdateLayoutConfig($c4ShapeInRow="2", $c4BoundaryInRow="1")
|
||||
|
||||
title Transcoder Component Diagram
|
||||
|
||||
Person(user, "User")
|
||||
|
||||
Container_Boundary(transcoder, "transcoder") {
|
||||
ComponentDb(transcoder_db1, "gocoder", "Postgres", "")
|
||||
Component(transcoder_c1, "kyoo_transcoder", "Go", "")
|
||||
Component(transcoder_c2, "TranscodeMetadata", "S3/Volume", "Persistent. Distributed Metadata")
|
||||
Component(transcoder_c3, "TranscodeCache", "Volume", "Volatile. Local cache")
|
||||
}
|
||||
|
||||
System_Boundary(external, "") {
|
||||
System_Ext(media, "MediaLibrary", "")
|
||||
}
|
||||
|
||||
Rel(user, transcoder_c1, "auth via middleware")
|
||||
Rel(transcoder_c1, media, "mounted to filesystem <br/> reads")
|
||||
Rel(transcoder_c1, transcoder_db1, "")
|
||||
Rel(transcoder_c1, transcoder_c2, "")
|
||||
Rel(transcoder_c1, transcoder_c3, "")
|
||||
```
|
||||
|
||||
|
||||
#### Scanner
|
||||
```mermaid
|
||||
C4Component
|
||||
UpdateLayoutConfig($c4ShapeInRow="5", $c4BoundaryInRow="2")
|
||||
|
||||
title Scanner Component Diagram
|
||||
|
||||
Person(user, "User")
|
||||
|
||||
Container_Boundary(api, "api") {
|
||||
Component(api_c1, "kyoo_api", "TypeScript", "")
|
||||
}
|
||||
|
||||
Container_Boundary(scanner, "scanner") {
|
||||
Component(scanner_c1, "kyoo_scanner", "Python", "")
|
||||
ComponentDb(scanner_db1, "scanner", "Postgres", "")
|
||||
}
|
||||
System_Boundary(external, "") {
|
||||
System_Ext(content, "ContentDatabase", "")
|
||||
System_Ext(media, "MediaLibrary", "")
|
||||
}
|
||||
|
||||
Rel(user, scanner_c1, "http(s) <br/> auth via middleware")
|
||||
Rel(scanner_c1, api_c1, "http(s) <br/> auth via middleware")
|
||||
Rel(scanner_c1, scanner_db1, "")
|
||||
Rel(scanner_c1, content, "http(s) <br/> gathers media metadata")
|
||||
Rel(scanner_c1, media, "mounted to filesystem <br/> watches")
|
||||
```
|
||||
@@ -3,10 +3,10 @@
|
||||
1. Install docker & docker-compose
|
||||
2. Download the
|
||||
[`docker-compose.yml`](https://github.com/zoriya/kyoo/releases/latest/download/docker-compose.yml) and
|
||||
[`.env`](https://raw.githubusercontent.com/zoriya/Kyoo/master/.env.example) files
|
||||
3. Fill the `.env` file with your configuration options
|
||||
[`.env`](https://github.com/zoriya/kyoo/releases/latest/download/env.example) files
|
||||
3. Fill the `.env` file with your configuration options. Ensure it's named `.env` (nothing before the dot)
|
||||
4. Look at [Hardware Acceleration section](#Hardware-Acceleration) if you need it
|
||||
5. Look at [Custom Volumes](#Custom-Volumes) if you need it,
|
||||
5. Look at [FAQ](#FAQ) if you need it,
|
||||
6. Run `docker compose up -d` and see kyoo at `http://localhost:8901`
|
||||
|
||||
# Installing
|
||||
@@ -23,7 +23,7 @@ Those files can be put in any directory of your choice.
|
||||
Those files are:
|
||||
|
||||
- A `docker-compose.yml` (simply download docker-compose.yml from [the latest release](https://github.com/zoriya/kyoo/releases/latest/download/docker-compose.yml)).
|
||||
- A `.env` file that you will need to **fill**. Look at the example [.env.example](https://raw.githubusercontent.com/zoriya/Kyoo/master/.env.example)
|
||||
- A `.env` file that you will need to **fill**. Look at the example [.env.example](https://github.com/zoriya/kyoo/releases/latest/download/env.example). It's name NEEDS to be `.env` (nothing before the dot)
|
||||
|
||||
> If you want an explanation of what are those files, you can read the following:
|
||||
> The `docker-compose.yml` file describes the different services of Kyoo, where they should be downloaded and their start order. \
|
||||
@@ -33,7 +33,7 @@ If you need hardware acceleration, look at [Hardware Acceleration section](#Hard
|
||||
If you need custom volumes (because video directories are on different disks and you can't use raid, because you use network drives or another custom volume type), look at [Custom Volumes](#Custom-Volumes).
|
||||
|
||||
The next and last step is actually starting Kyoo. To do that, open a terminal in the same directory as the 3 configurations files
|
||||
and run `docker-compose up -d`.
|
||||
and run `docker compose up -d`.
|
||||
|
||||
Congratulation, everything is now ready to use Kyoo. You can navigate to `http://localhost:8901` on a web browser to see your instance of Kyoo.
|
||||
|
||||
@@ -43,11 +43,11 @@ Updating Kyoo is exactly the same as installing it. Get an updated version of th
|
||||
unsure that your `.env` contains all the options specified in the updated `.env.example` file.
|
||||
|
||||
After that, you will need to update Kyoo's services. For that, open a terminal in the configuration's directory and run
|
||||
the command `docker-compose pull`. You are now ready to restart Kyoo, you can run `docker-compose up -d`.
|
||||
the command `docker compose pull`. You are now ready to restart Kyoo, you can run `docker compose up -d`.
|
||||
|
||||
# Uninstalling
|
||||
|
||||
To uninstall Kyoo, you need to open a terminal in the configuration's directory and run `docker-compose down`. This will
|
||||
To uninstall Kyoo, you need to open a terminal in the configuration's directory and run `docker compose down`. This will
|
||||
stop Kyoo's services. You can then remove the configuration files.
|
||||
|
||||
# Hardware Acceleration
|
||||
@@ -91,7 +91,9 @@ You can also add `COMPOSE_PROFILES=nvidia` to your `.env` instead of adding the
|
||||
Note that most nvidia cards have an artificial limit on the number of encodes. You can confirm your card limit [here](https://developer.nvidia.com/video-encode-and-decode-gpu-support-matrix-new).
|
||||
This limit can also be removed by applying an [unofficial patch](https://github.com/keylase/nvidia-patch) to you driver.
|
||||
|
||||
# Custom volumes
|
||||
# FAQ
|
||||
|
||||
## Custom volumes
|
||||
|
||||
To customize volumes, you can edit the `docker-compose.yml` manually.
|
||||
|
||||
@@ -107,8 +109,6 @@ For example, if your library is split into multiples paths you can edit the `vol
|
||||
restart: unless-stopped
|
||||
env_file:
|
||||
- ./.env
|
||||
environment:
|
||||
- GOCODER_PREFIX=/video
|
||||
volumes:
|
||||
- - ${LIBRARY_ROOT}:/video:ro
|
||||
+ - /my_path/number1:/video/1:ro
|
||||
@@ -119,3 +119,19 @@ For example, if your library is split into multiples paths you can edit the `vol
|
||||
You can also edit the volume definition to use advanced volume drivers if you need to access smb or network drives. Mounting a drive into your filesystem and binding it in this volume section is also a valid choice (especially for fuse filesystems like cloud drives for example).
|
||||
|
||||
Don't forget to **also edit the scanner's volumes** if you edit the transcoder's volume.
|
||||
|
||||
## Ignoring Directories
|
||||
Kyoo supports excluding specific directories from scanning and monitoring by detecting the presence of a `.ignore` file. When a directory contains a `.ignore` file, Kyoo will recursively exclude that directory and all its contents from processing.
|
||||
|
||||
Example:
|
||||
To exclude `/media/extras/**`, add a `.ignore` file:
|
||||
```bash
|
||||
touch /media/extras/.ignore
|
||||
```
|
||||
Kyoo will skip `/media/extras` and its contents in all future scans and monitoring events.
|
||||
|
||||
# OpenID Connect
|
||||
|
||||
Kyoo supports OpenID Connect (OIDC) for authentication. Please refer to the [OIDC.md](OIDC.md) file for more information.
|
||||
|
||||
<!-- vim: set wrap: -->
|
||||
|
||||
64
OIDC.md
Normal file
64
OIDC.md
Normal file
@@ -0,0 +1,64 @@
|
||||
# OpenID Connect
|
||||
|
||||
Kyoo supports OpenID Connect (OIDC) for authentication. This allows you to use your existing identity provider to authenticate users in Kyoo.
|
||||
|
||||
## Configuration
|
||||
|
||||
To enable OIDC, you need to fill the following environment variables in your `.env` file:
|
||||
|
||||
```env
|
||||
PUBLIC_URL=https://your-kyoo-instance.com
|
||||
OIDC_<name>_NAME=<name>
|
||||
OIDC_<name>_LOGO=https://url-of-your-logo.com
|
||||
OIDC_<name>_CLIENTID=
|
||||
OIDC_<name>_SECRET=
|
||||
OIDC_<name>_AUTHORIZATION=https://url-of-the-authorization-endpoint-of-the-oidc-service.com/auth
|
||||
OIDC_<name>_TOKEN=https://url-of-the-token-endpoint-of-the-oidc-service.com/token
|
||||
OIDC_<name>_PROFILE=https://url-of-the-profile-endpoint-of-the-oidc-service.com/userinfo
|
||||
OIDC_<name>_SCOPE="email openid profile"
|
||||
OIDC_<name>_AUTHMETHOD=ClientSecretBasic
|
||||
```
|
||||
|
||||
- `PUBLIC_URL` is the URL of your Kyoo instance. This is required for OIDC to work.
|
||||
- `<name>` is the name of the OIDC provider. It can be anything you want. This will be the display name of the OIDC provider on the login page.
|
||||
- `OIDC_<name>_LOGO` is the URL of the logo of the OIDC provider. It will be displayed on the login page.
|
||||
- `OIDC_<name>_CLIENTID` is the client ID of the OIDC provider.
|
||||
- `OIDC_<name>_SECRET` is the client secret of the OIDC provider.
|
||||
- `OIDC_<name>_AUTHORIZATION` is the URL of the authorization endpoint of the OIDC provider.
|
||||
- `OIDC_<name>_TOKEN` is the URL of the token endpoint of the OIDC provider.
|
||||
- `OIDC_<name>_PROFILE` is the URL of the profile endpoint of the OIDC provider.
|
||||
- `OIDC_<name>_SCOPE` is the scope of the OIDC provider. This is a space-separated list of scopes.
|
||||
- `OIDC_<name>_AUTHMETHOD` is the authentication method of the OIDC provider. This can be `ClientSecretBasic` or `ClientSecretPost`.
|
||||
|
||||
## Example
|
||||
|
||||
### Google OIDC
|
||||
|
||||
To enable Google OIDC, please follow the instructions from the [Google Developers](https://developers.google.com/identity/gsi/web/guides/get-google-api-clientid) to create a new project and get the client ID and secret.
|
||||
|
||||
When creating the Oauth 2.0 Client ID, make sure to add the following redirect URI: `https://your-kyoo-instance.com/api/auth/logged/google`.
|
||||
|
||||
For the authorized JavaScript origins, add `https://your-kyoo-instance.com`.
|
||||
|
||||
Then, fill the following environment variables in your `.env` file:
|
||||
|
||||
```env
|
||||
PUBLIC_URL=https://your-kyoo-instance.com
|
||||
OIDC_GOOGLE_NAME=Google
|
||||
OIDC_GOOGLE_LOGO=https://www.gstatic.com/marketing-cms/assets/images/d5/dc/cfe9ce8b4425b410b49b7f2dd3f3/g.webp=s200
|
||||
OIDC_GOOGLE_CLIENTID=<client-id> # the client ID you got from Google
|
||||
OIDC_GOOGLE_SECRET=<client-secret> # the client secret you got from Google
|
||||
OIDC_GOOGLE_AUTHORIZATION=https://accounts.google.com/o/oauth2/auth
|
||||
OIDC_GOOGLE_TOKEN=https://oauth2.googleapis.com/token
|
||||
OIDC_GOOGLE_PROFILE=https://www.googleapis.com/oauth2/v2/userinfo
|
||||
OIDC_GOOGLE_SCOPE="email openid profile"
|
||||
OIDC_GOOGLE_AUTHMETHOD=ClientSecretPost
|
||||
```
|
||||
|
||||
### Another OIDC providers
|
||||
|
||||
To enable another OIDC provider, just fill the environment variables with the information you got from the provider.
|
||||
|
||||
Remember that when `<name>` is `XYZ`, the environment variables should start with `OIDC_XYZ_`.
|
||||
|
||||
In that case, the callback URL will be `https://your-kyoo-instance.com/api/auth/logged/xyz`.
|
||||
19
README.md
19
README.md
@@ -12,7 +12,7 @@ Kyoo does not have a plugin system and aim to have every features built-in (see
|
||||
|
||||
- **[Installation](./INSTALLING.md):** Basic installation guidelines, how to start Kyoo, enable OIDC or hardware transcoding.
|
||||
- **[Join the discord](https://discord.gg/E6Apw3aFaA):** Ask questions, talk about the development, feature you might want or bugs you might encounter.
|
||||
- **[API Documentation](https://kyoo.zoriya.dev/api/doc):** The API to integrate Kyoo with other services, if you have any questions, please ask on github or discord!
|
||||
- **[API Documentation](https://kyoo.zoriya.dev/api/doc):** The API to integrate Kyoo with other services, if you have any questions, please ask on GitHub or Discord!
|
||||
- **[Contributing](./CONTRIBUTING.md):** Feel free to open issues, submit pull requests, and contribute to making Kyoo even better. We need you!
|
||||
|
||||
[](https://discord.gg/zpA74Qpvj5)
|
||||
@@ -29,24 +29,21 @@ Kyoo does not have a plugin system and aim to have every features built-in (see
|
||||
|
||||
- **Watch List Scrubbing Support:** Your watch list is automatically synced to connected services (SIMKL and soon others [#351](https://github.com/zoriya/Kyoo/issues/351), [#352](https://github.com/zoriya/Kyoo/issues/352)). No need to manually mark episodes as watched.
|
||||
|
||||
- **Download and Offline Support:** Download videos to watch them without internet access, you progress will automatically be synced next time your devices goes online.
|
||||
- **Download and Offline Support:** Download videos to watch them without internet access, your progress will automatically be synced next time your devices goes online.
|
||||
|
||||
- **Enhanced Subtitle Support:** Subtitles are important, Kyoo supports SSA/ASS and uses the video's embedded fonts when available.
|
||||
|
||||
- **Anime Name Parsing**: While there are still some issues (see [#466](https://github.com/zoriya/Kyoo/issues/466), Kyoo will match weird anime names (like `[Some-Stuffs] Jojo's Bizarre Adventure Stone Ocean 24 (1920x1080 Blu-Ray Opus) [2750810F].mkv`) without issue.
|
||||
|
||||
- **Cloud Native:** Still an ongoing effort (see [#357](https://github.com/zoriya/Kyoo/issues/357)) but Kyoo is made with the idea that it could run distributed or standalone, on an RPI or on huge home-datacenters.
|
||||
- **Helm Chart:** Deploy Kyoo to your Kubernetes cluster today! There is an official Helm chart. Multiple replicas is a WIP!
|
||||
|
||||
## 📺 Clients
|
||||
|
||||
Clients is a bit part of media servers but for now, Kyoo's focus is on features. Only a web version and an android apps are available for now. The front is written with react-native (expo) so adapting for others platform is possible. Here is a rough roadmap of clients supports:
|
||||
- Today: Web & Android
|
||||
- End of 2024: Chromecast support
|
||||
- Summer 2025: Android TV app
|
||||
Kyoo currently supports Web and Android clients, with additional platforms being thought about.
|
||||
|
||||
Apple devices are not planned for now because I do not own any of their device, and it requires $100/year.
|
||||
Don't see your client? Kyoo is focused on adding features, but welcomes contributors! The frontend is built with React-Native and Expo. Come hang and develop with us on Discord.
|
||||
|
||||
If you would like to have a client sooner or on devices not listed on the roadmap, come hang on the discord and consider contributing to Kyoo.
|
||||
Support for Apple devices (iOS, tvOS) is not currently planned due to buying hardware and yearly developer fee (~$100).
|
||||
|
||||
## 📖 Translations
|
||||
|
||||
@@ -58,9 +55,9 @@ If Kyoo is not available on your language, you can use [weblate](https://hosted.
|
||||
|
||||
From a technical standpoint, both Jellyfin and Plex lean on SQLite and confine everything within a single container, Kyoo takes a different route. We're not afraid to bring in additional containers when it makes sense – whether for specialized features like Meilisearch powering our search system or for scalability, as seen with our transcoder.
|
||||
|
||||
Kyoo embraces the "setup once, forget about it" philosophy. Unlike Plex and Jellyfin, we don't burden you with manual file renaming or specific folder structures. Kyoo seamlessly works with files straight from your download directory, minimizing the maintenance headache for server admins.
|
||||
Kyoo embraces the “setup once, forget about it” philosophy. Unlike Plex and Jellyfin, we don't burden you with manual file renaming or specific folder structures. Kyoo seamlessly works with files straight from your download directory, minimizing the maintenance headache for server admins.
|
||||
|
||||
Kyoo narrows its focus to movies, TV shows, and anime streaming. No music, ebooks, or games – just pure cinematic delight.
|
||||
Kyoo narrows its focus to movies, TV shows, and anime streaming. No music, e-books, or games – just pure cinematic delight.
|
||||
|
||||
## 🔗 Live Demo
|
||||
|
||||
|
||||
7
api/.dockerignore
Normal file
7
api/.dockerignore
Normal file
@@ -0,0 +1,7 @@
|
||||
**
|
||||
!/package.json
|
||||
!/bun.lock
|
||||
!/tsconfig.json
|
||||
!/patches
|
||||
!/src
|
||||
!/drizzle
|
||||
31
api/.env.example
Normal file
31
api/.env.example
Normal file
@@ -0,0 +1,31 @@
|
||||
# vi: ft=sh
|
||||
# shellcheck disable=SC2034
|
||||
|
||||
# either an hard-coded secret to decode jwts or empty to use keibi's public secret.
|
||||
# this should only be used in tests
|
||||
JWT_SECRET=
|
||||
# used to verify who's making the jwt
|
||||
JWT_ISSUER=$PUBLIC_URL
|
||||
# keibi's server to retrieve the public jwt secret
|
||||
AUTH_SERVER=http://auth:4568
|
||||
|
||||
IMAGES_PATH=./images
|
||||
|
||||
OTEL_EXPORTER_OTLP_PROTOCOL="http/protobuf"
|
||||
OTEL_EXPORTER_OTLP_ENDPOINT="http://localhost:4317"
|
||||
|
||||
# It is recommended to use the below PG environment variables when possible.
|
||||
# POSTGRES_URL=postgres://user:password@hostname:port/dbname?sslmode=verify-full&sslrootcert=/path/to/server.crt&sslcert=/path/to/client.crt&sslkey=/path/to/client.key
|
||||
# The behavior of the below variables match what is documented here:
|
||||
# https://www.postgresql.org/docs/current/libpq-envars.html
|
||||
PGUSER=kyoo
|
||||
PGPASSWORD=password
|
||||
PGDATABASE=kyoo
|
||||
PGHOST=postgres
|
||||
PGPORT=5432
|
||||
# PGOPTIONS=-c search_path=kyoo,public
|
||||
# PGPASSFILE=/my/password # Takes precedence over PGPASSWORD. New line characters are not trimmed.
|
||||
# PGSSLMODE=verify-full
|
||||
# PGSSLROOTCERT=/my/serving.crt
|
||||
# PGSSLCERT=/my/client.crt
|
||||
# PGSSLKEY=/my/client.key
|
||||
3
api/.gitignore
vendored
Normal file
3
api/.gitignore
vendored
Normal file
@@ -0,0 +1,3 @@
|
||||
/node_modules
|
||||
**/*.bun
|
||||
images
|
||||
30
api/Dockerfile
Normal file
30
api/Dockerfile
Normal file
@@ -0,0 +1,30 @@
|
||||
FROM oven/bun:debian AS builder
|
||||
WORKDIR /app
|
||||
|
||||
COPY package.json bun.lock .
|
||||
COPY patches patches
|
||||
RUN bun install --production
|
||||
|
||||
COPY src src
|
||||
COPY drizzle drizzle
|
||||
COPY tsconfig.json .
|
||||
|
||||
ENV NODE_ENV=production
|
||||
RUN bun build \
|
||||
--compile \
|
||||
--minify-whitespace \
|
||||
--minify-syntax \
|
||||
--target bun \
|
||||
--outfile server \
|
||||
./src/index.ts
|
||||
|
||||
FROM debian
|
||||
WORKDIR /app
|
||||
|
||||
COPY --from=builder /app/server server
|
||||
COPY --from=builder /app/node_modules/@img /app/node_modules/@img
|
||||
COPY ./drizzle ./drizzle
|
||||
|
||||
ENV NODE_ENV=production
|
||||
EXPOSE 3567
|
||||
CMD ["/app/server"]
|
||||
12
api/Dockerfile.dev
Normal file
12
api/Dockerfile.dev
Normal file
@@ -0,0 +1,12 @@
|
||||
FROM oven/bun AS builder
|
||||
WORKDIR /app
|
||||
|
||||
COPY package.json bun.lock .
|
||||
COPY patches patches
|
||||
RUN bun install --production
|
||||
|
||||
COPY . .
|
||||
|
||||
EXPOSE 3567
|
||||
CMD ["bun", "dev"]
|
||||
|
||||
164
api/README.md
Normal file
164
api/README.md
Normal file
@@ -0,0 +1,164 @@
|
||||
# Kyoo API
|
||||
|
||||
## Database schema
|
||||
|
||||
The many-to-many relation between entries (episodes/movies) & videos is NOT a mistake. Some video files can contain multiples episodes (like `MyShow 2&3.mvk`). One video file can also contain only a portion of an episode (like `MyShow 2 Part 1.mkv`)
|
||||
|
||||
```mermaid
|
||||
erDiagram
|
||||
shows {
|
||||
guid id PK
|
||||
kind kind "serie|movie|collection"
|
||||
string(128) slug UK
|
||||
genre[] genres
|
||||
int rating "From 0 to 100"
|
||||
status status "NN"
|
||||
datetime added_date
|
||||
date start_air
|
||||
date end_air "null for movies"
|
||||
datetime next_refresh
|
||||
jsonb external_id
|
||||
guid studio_id FK
|
||||
string original_language
|
||||
guid collection_id FK
|
||||
}
|
||||
show_translations {
|
||||
guid id PK, FK
|
||||
string language PK
|
||||
string name "NN"
|
||||
string tagline
|
||||
string[] aliases
|
||||
string description
|
||||
string[] tags
|
||||
string trailerUrl
|
||||
jsonb poster
|
||||
jsonb banner
|
||||
jsonb logo
|
||||
jsonb thumbnail
|
||||
}
|
||||
shows ||--|{ show_translations : has
|
||||
shows |o--|| entries : has
|
||||
shows |o--|| shows : has_collection
|
||||
|
||||
entries {
|
||||
guid id PK
|
||||
string(256) slug UK
|
||||
guid show_id FK, UK
|
||||
%% Order is absolute number.
|
||||
uint order "NN"
|
||||
uint season_number UK
|
||||
uint episode_number UK "NN"
|
||||
type type "episode|movie|special|extra"
|
||||
date air_date
|
||||
uint runtime
|
||||
jsonb thumbnail
|
||||
datetime next_refresh
|
||||
jsonb external_id
|
||||
}
|
||||
entry_translations {
|
||||
guid id PK, FK
|
||||
string language PK
|
||||
string name
|
||||
string description
|
||||
}
|
||||
entries ||--|{ entry_translations : has
|
||||
|
||||
videos {
|
||||
guid id PK
|
||||
string path "NN"
|
||||
uint rendering "dedup for duplicates part1/2"
|
||||
uint part
|
||||
uint version "max version is preferred rendering"
|
||||
}
|
||||
videos }|--|{ entries : for
|
||||
|
||||
seasons {
|
||||
guid id PK
|
||||
string(256) slug UK
|
||||
guid show_id FK
|
||||
uint season_number "NN"
|
||||
datetime added_date
|
||||
date start_air
|
||||
date end_air
|
||||
datetime next_refresh
|
||||
jsonb external_id
|
||||
}
|
||||
|
||||
season_translations {
|
||||
guid id PK,FK
|
||||
string language PK
|
||||
string name
|
||||
string description
|
||||
jsonb poster
|
||||
jsonb banner
|
||||
jsonb logo
|
||||
jsonb thumbnail
|
||||
}
|
||||
seasons ||--|{ season_translations : has
|
||||
seasons ||--o{ entries : has
|
||||
shows ||--|{ seasons : has
|
||||
|
||||
users {
|
||||
guid id PK
|
||||
}
|
||||
|
||||
watchlist {
|
||||
guid show_id PK, FK
|
||||
guid user_id PK, FK
|
||||
status status "completed|watching|rewatching|dropped|planned"
|
||||
uint seen_entry_count "NN"
|
||||
guid next_entry FK
|
||||
}
|
||||
shows ||--|{ watchlist : has
|
||||
users ||--|{ watchlist : has
|
||||
watchlist ||--|o entries : next_entry
|
||||
|
||||
history {
|
||||
int id PK
|
||||
guid entry_id FK
|
||||
guid profile_id FK
|
||||
guid video_id FK
|
||||
jsonb progress "{ percent, time }"
|
||||
datetime played_date
|
||||
}
|
||||
entries ||--|{ history : part_of
|
||||
users ||--|{ history : has
|
||||
videos o|--o{ history : has
|
||||
|
||||
roles {
|
||||
guid show_id PK, FK
|
||||
guid staff_id PK, FK
|
||||
uint order
|
||||
type type "actor|director|writer|producer|music|other"
|
||||
string character_name
|
||||
string character_latin_name
|
||||
jsonb character_image
|
||||
}
|
||||
staff {
|
||||
guid id PK
|
||||
string(256) slug UK
|
||||
string name "NN"
|
||||
string latin_name
|
||||
jsonb image
|
||||
datetime next_refresh
|
||||
jsonb external_id
|
||||
}
|
||||
staff ||--|{ roles : has
|
||||
shows ||--|{ roles : has
|
||||
|
||||
studios {
|
||||
guid id PK
|
||||
string(128) slug UK
|
||||
jsonb logo
|
||||
datetime next_refresh
|
||||
jsonb external_id
|
||||
}
|
||||
|
||||
studio_translations {
|
||||
guid id PK,FK
|
||||
string language PK
|
||||
string name
|
||||
}
|
||||
studios ||--|{ studio_translations : has
|
||||
shows }|--|{ studios : has
|
||||
```
|
||||
3
api/biome.json
Normal file
3
api/biome.json
Normal file
@@ -0,0 +1,3 @@
|
||||
{
|
||||
"extends": "//"
|
||||
}
|
||||
492
api/bun.lock
Normal file
492
api/bun.lock
Normal file
@@ -0,0 +1,492 @@
|
||||
{
|
||||
"lockfileVersion": 1,
|
||||
"configVersion": 0,
|
||||
"workspaces": {
|
||||
"": {
|
||||
"name": "api",
|
||||
"dependencies": {
|
||||
"@elysiajs/opentelemetry": "^1.4.8",
|
||||
"@elysiajs/swagger": "zoriya/elysia-swagger#build",
|
||||
"@kubiks/otel-drizzle": "zoriya/drizzle-otel#build",
|
||||
"@types/bun": "^1.3.1",
|
||||
"blurhash": "^2.0.5",
|
||||
"drizzle-kit": "^0.31.5",
|
||||
"drizzle-orm": "0.44.7",
|
||||
"elysia": "^1.4.13",
|
||||
"jose": "^6.1.0",
|
||||
"node-addon-api": "^8.5.0",
|
||||
"parjs": "^1.3.9",
|
||||
"pg": "^8.16.3",
|
||||
"sharp": "^0.34.4",
|
||||
},
|
||||
"devDependencies": {
|
||||
"@biomejs/biome": "2.3.7",
|
||||
"@types/pg": "^8.15.5",
|
||||
},
|
||||
},
|
||||
},
|
||||
"patchedDependencies": {
|
||||
"drizzle-orm@0.44.7": "patches/drizzle-orm@0.44.7.patch",
|
||||
},
|
||||
"packages": {
|
||||
"@biomejs/biome": ["@biomejs/biome@2.3.7", "", { "optionalDependencies": { "@biomejs/cli-darwin-arm64": "2.3.7", "@biomejs/cli-darwin-x64": "2.3.7", "@biomejs/cli-linux-arm64": "2.3.7", "@biomejs/cli-linux-arm64-musl": "2.3.7", "@biomejs/cli-linux-x64": "2.3.7", "@biomejs/cli-linux-x64-musl": "2.3.7", "@biomejs/cli-win32-arm64": "2.3.7", "@biomejs/cli-win32-x64": "2.3.7" }, "bin": { "biome": "bin/biome" } }, "sha512-CTbAS/jNAiUc6rcq94BrTB8z83O9+BsgWj2sBCQg9rD6Wkh2gjfR87usjx0Ncx0zGXP1NKgT7JNglay5Zfs9jw=="],
|
||||
|
||||
"@biomejs/cli-darwin-arm64": ["@biomejs/cli-darwin-arm64@2.3.7", "", { "os": "darwin", "cpu": "arm64" }, "sha512-LirkamEwzIUULhXcf2D5b+NatXKeqhOwilM+5eRkbrnr6daKz9rsBL0kNZ16Hcy4b8RFq22SG4tcLwM+yx/wFA=="],
|
||||
|
||||
"@biomejs/cli-darwin-x64": ["@biomejs/cli-darwin-x64@2.3.7", "", { "os": "darwin", "cpu": "x64" }, "sha512-Q4TO633kvrMQkKIV7wmf8HXwF0dhdTD9S458LGE24TYgBjSRbuhvio4D5eOQzirEYg6eqxfs53ga/rbdd8nBKg=="],
|
||||
|
||||
"@biomejs/cli-linux-arm64": ["@biomejs/cli-linux-arm64@2.3.7", "", { "os": "linux", "cpu": "arm64" }, "sha512-inHOTdlstUBzgjDcx0ge71U4SVTbwAljmkfi3MC5WzsYCRhancqfeL+sa4Ke6v2ND53WIwCFD5hGsYExoI3EZQ=="],
|
||||
|
||||
"@biomejs/cli-linux-arm64-musl": ["@biomejs/cli-linux-arm64-musl@2.3.7", "", { "os": "linux", "cpu": "arm64" }, "sha512-/afy8lto4CB8scWfMdt+NoCZtatBUF62Tk3ilWH2w8ENd5spLhM77zKlFZEvsKJv9AFNHknMl03zO67CiklL2Q=="],
|
||||
|
||||
"@biomejs/cli-linux-x64": ["@biomejs/cli-linux-x64@2.3.7", "", { "os": "linux", "cpu": "x64" }, "sha512-fJMc3ZEuo/NaMYo5rvoWjdSS5/uVSW+HPRQujucpZqm2ZCq71b8MKJ9U4th9yrv2L5+5NjPF0nqqILCl8HY/fg=="],
|
||||
|
||||
"@biomejs/cli-linux-x64-musl": ["@biomejs/cli-linux-x64-musl@2.3.7", "", { "os": "linux", "cpu": "x64" }, "sha512-CQUtgH1tIN6e5wiYSJqzSwJumHYolNtaj1dwZGCnZXm2PZU1jOJof9TsyiP3bXNDb+VOR7oo7ZvY01If0W3iFQ=="],
|
||||
|
||||
"@biomejs/cli-win32-arm64": ["@biomejs/cli-win32-arm64@2.3.7", "", { "os": "win32", "cpu": "arm64" }, "sha512-aJAE8eCNyRpcfx2JJAtsPtISnELJ0H4xVVSwnxm13bzI8RwbXMyVtxy2r5DV1xT3WiSP+7LxORcApWw0LM8HiA=="],
|
||||
|
||||
"@biomejs/cli-win32-x64": ["@biomejs/cli-win32-x64@2.3.7", "", { "os": "win32", "cpu": "x64" }, "sha512-pulzUshqv9Ed//MiE8MOUeeEkbkSHVDVY5Cz5wVAnH1DUqliCQG3j6s1POaITTFqFfo7AVIx2sWdKpx/GS+Nqw=="],
|
||||
|
||||
"@drizzle-team/brocli": ["@drizzle-team/brocli@0.10.2", "", {}, "sha512-z33Il7l5dKjUgGULTqBsQBQwckHh5AbIuxhdsIxDDiZAzBOrZO6q9ogcWC65kU382AfynTfgNumVcNIjuIua6w=="],
|
||||
|
||||
"@elysiajs/opentelemetry": ["@elysiajs/opentelemetry@1.4.8", "", { "dependencies": { "@opentelemetry/api": "^1.9.0", "@opentelemetry/instrumentation": "^0.200.0", "@opentelemetry/sdk-node": "^0.200.0" }, "peerDependencies": { "elysia": ">= 1.4.0" } }, "sha512-c9unbcdXfehExCv1GsiTCfos5SyIAyDwP7apcMeXmUMBaJZiAYMfiEH8RFFFIfIHJHC/xlNJzUPodkcUaaoJJQ=="],
|
||||
|
||||
"@elysiajs/swagger": ["@elysiajs/swagger@github:zoriya/elysia-swagger#f88fbc7", { "dependencies": { "@scalar/themes": "^0.9.81", "@scalar/types": "^0.1.3", "openapi-types": "^12.1.3", "pathe": "^1.1.2" }, "peerDependencies": { "elysia": ">= 1.3.0" } }, "zoriya-elysia-swagger-f88fbc7"],
|
||||
|
||||
"@emnapi/runtime": ["@emnapi/runtime@1.6.0", "", { "dependencies": { "tslib": "^2.4.0" } }, "sha512-obtUmAHTMjll499P+D9A3axeJFlhdjOWdKUNs/U6QIGT7V5RjcUW1xToAzjvmgTSQhDbYn/NwfTRoJcQ2rNBxA=="],
|
||||
|
||||
"@esbuild-kit/core-utils": ["@esbuild-kit/core-utils@3.3.2", "", { "dependencies": { "esbuild": "~0.18.20", "source-map-support": "^0.5.21" } }, "sha512-sPRAnw9CdSsRmEtnsl2WXWdyquogVpB3yZ3dgwJfe8zrOzTsV7cJvmwrKVa+0ma5BoiGJ+BoqkMvawbayKUsqQ=="],
|
||||
|
||||
"@esbuild-kit/esm-loader": ["@esbuild-kit/esm-loader@2.6.5", "", { "dependencies": { "@esbuild-kit/core-utils": "^3.3.2", "get-tsconfig": "^4.7.0" } }, "sha512-FxEMIkJKnodyA1OaCUoEvbYRkoZlLZ4d/eXFu9Fh8CbBBgP5EmZxrfTRyN0qpXZ4vOvqnE5YdRdcrmUUXuU+dA=="],
|
||||
|
||||
"@esbuild/aix-ppc64": ["@esbuild/aix-ppc64@0.25.11", "", { "os": "aix", "cpu": "ppc64" }, "sha512-Xt1dOL13m8u0WE8iplx9Ibbm+hFAO0GsU2P34UNoDGvZYkY8ifSiy6Zuc1lYxfG7svWE2fzqCUmFp5HCn51gJg=="],
|
||||
|
||||
"@esbuild/android-arm": ["@esbuild/android-arm@0.25.11", "", { "os": "android", "cpu": "arm" }, "sha512-uoa7dU+Dt3HYsethkJ1k6Z9YdcHjTrSb5NUy66ZfZaSV8hEYGD5ZHbEMXnqLFlbBflLsl89Zke7CAdDJ4JI+Gg=="],
|
||||
|
||||
"@esbuild/android-arm64": ["@esbuild/android-arm64@0.25.11", "", { "os": "android", "cpu": "arm64" }, "sha512-9slpyFBc4FPPz48+f6jyiXOx/Y4v34TUeDDXJpZqAWQn/08lKGeD8aDp9TMn9jDz2CiEuHwfhRmGBvpnd/PWIQ=="],
|
||||
|
||||
"@esbuild/android-x64": ["@esbuild/android-x64@0.25.11", "", { "os": "android", "cpu": "x64" }, "sha512-Sgiab4xBjPU1QoPEIqS3Xx+R2lezu0LKIEcYe6pftr56PqPygbB7+szVnzoShbx64MUupqoE0KyRlN7gezbl8g=="],
|
||||
|
||||
"@esbuild/darwin-arm64": ["@esbuild/darwin-arm64@0.25.11", "", { "os": "darwin", "cpu": "arm64" }, "sha512-VekY0PBCukppoQrycFxUqkCojnTQhdec0vevUL/EDOCnXd9LKWqD/bHwMPzigIJXPhC59Vd1WFIL57SKs2mg4w=="],
|
||||
|
||||
"@esbuild/darwin-x64": ["@esbuild/darwin-x64@0.25.11", "", { "os": "darwin", "cpu": "x64" }, "sha512-+hfp3yfBalNEpTGp9loYgbknjR695HkqtY3d3/JjSRUyPg/xd6q+mQqIb5qdywnDxRZykIHs3axEqU6l1+oWEQ=="],
|
||||
|
||||
"@esbuild/freebsd-arm64": ["@esbuild/freebsd-arm64@0.25.11", "", { "os": "freebsd", "cpu": "arm64" }, "sha512-CmKjrnayyTJF2eVuO//uSjl/K3KsMIeYeyN7FyDBjsR3lnSJHaXlVoAK8DZa7lXWChbuOk7NjAc7ygAwrnPBhA=="],
|
||||
|
||||
"@esbuild/freebsd-x64": ["@esbuild/freebsd-x64@0.25.11", "", { "os": "freebsd", "cpu": "x64" }, "sha512-Dyq+5oscTJvMaYPvW3x3FLpi2+gSZTCE/1ffdwuM6G1ARang/mb3jvjxs0mw6n3Lsw84ocfo9CrNMqc5lTfGOw=="],
|
||||
|
||||
"@esbuild/linux-arm": ["@esbuild/linux-arm@0.25.11", "", { "os": "linux", "cpu": "arm" }, "sha512-TBMv6B4kCfrGJ8cUPo7vd6NECZH/8hPpBHHlYI3qzoYFvWu2AdTvZNuU/7hsbKWqu/COU7NIK12dHAAqBLLXgw=="],
|
||||
|
||||
"@esbuild/linux-arm64": ["@esbuild/linux-arm64@0.25.11", "", { "os": "linux", "cpu": "arm64" }, "sha512-Qr8AzcplUhGvdyUF08A1kHU3Vr2O88xxP0Tm8GcdVOUm25XYcMPp2YqSVHbLuXzYQMf9Bh/iKx7YPqECs6ffLA=="],
|
||||
|
||||
"@esbuild/linux-ia32": ["@esbuild/linux-ia32@0.25.11", "", { "os": "linux", "cpu": "ia32" }, "sha512-TmnJg8BMGPehs5JKrCLqyWTVAvielc615jbkOirATQvWWB1NMXY77oLMzsUjRLa0+ngecEmDGqt5jiDC6bfvOw=="],
|
||||
|
||||
"@esbuild/linux-loong64": ["@esbuild/linux-loong64@0.25.11", "", { "os": "linux", "cpu": "none" }, "sha512-DIGXL2+gvDaXlaq8xruNXUJdT5tF+SBbJQKbWy/0J7OhU8gOHOzKmGIlfTTl6nHaCOoipxQbuJi7O++ldrxgMw=="],
|
||||
|
||||
"@esbuild/linux-mips64el": ["@esbuild/linux-mips64el@0.25.11", "", { "os": "linux", "cpu": "none" }, "sha512-Osx1nALUJu4pU43o9OyjSCXokFkFbyzjXb6VhGIJZQ5JZi8ylCQ9/LFagolPsHtgw6himDSyb5ETSfmp4rpiKQ=="],
|
||||
|
||||
"@esbuild/linux-ppc64": ["@esbuild/linux-ppc64@0.25.11", "", { "os": "linux", "cpu": "ppc64" }, "sha512-nbLFgsQQEsBa8XSgSTSlrnBSrpoWh7ioFDUmwo158gIm5NNP+17IYmNWzaIzWmgCxq56vfr34xGkOcZ7jX6CPw=="],
|
||||
|
||||
"@esbuild/linux-riscv64": ["@esbuild/linux-riscv64@0.25.11", "", { "os": "linux", "cpu": "none" }, "sha512-HfyAmqZi9uBAbgKYP1yGuI7tSREXwIb438q0nqvlpxAOs3XnZ8RsisRfmVsgV486NdjD7Mw2UrFSw51lzUk1ww=="],
|
||||
|
||||
"@esbuild/linux-s390x": ["@esbuild/linux-s390x@0.25.11", "", { "os": "linux", "cpu": "s390x" }, "sha512-HjLqVgSSYnVXRisyfmzsH6mXqyvj0SA7pG5g+9W7ESgwA70AXYNpfKBqh1KbTxmQVaYxpzA/SvlB9oclGPbApw=="],
|
||||
|
||||
"@esbuild/linux-x64": ["@esbuild/linux-x64@0.25.11", "", { "os": "linux", "cpu": "x64" }, "sha512-HSFAT4+WYjIhrHxKBwGmOOSpphjYkcswF449j6EjsjbinTZbp8PJtjsVK1XFJStdzXdy/jaddAep2FGY+wyFAQ=="],
|
||||
|
||||
"@esbuild/netbsd-arm64": ["@esbuild/netbsd-arm64@0.25.11", "", { "os": "none", "cpu": "arm64" }, "sha512-hr9Oxj1Fa4r04dNpWr3P8QKVVsjQhqrMSUzZzf+LZcYjZNqhA3IAfPQdEh1FLVUJSiu6sgAwp3OmwBfbFgG2Xg=="],
|
||||
|
||||
"@esbuild/netbsd-x64": ["@esbuild/netbsd-x64@0.25.11", "", { "os": "none", "cpu": "x64" }, "sha512-u7tKA+qbzBydyj0vgpu+5h5AeudxOAGncb8N6C9Kh1N4n7wU1Xw1JDApsRjpShRpXRQlJLb9wY28ELpwdPcZ7A=="],
|
||||
|
||||
"@esbuild/openbsd-arm64": ["@esbuild/openbsd-arm64@0.25.11", "", { "os": "openbsd", "cpu": "arm64" }, "sha512-Qq6YHhayieor3DxFOoYM1q0q1uMFYb7cSpLD2qzDSvK1NAvqFi8Xgivv0cFC6J+hWVw2teCYltyy9/m/14ryHg=="],
|
||||
|
||||
"@esbuild/openbsd-x64": ["@esbuild/openbsd-x64@0.25.11", "", { "os": "openbsd", "cpu": "x64" }, "sha512-CN+7c++kkbrckTOz5hrehxWN7uIhFFlmS/hqziSFVWpAzpWrQoAG4chH+nN3Be+Kzv/uuo7zhX716x3Sn2Jduw=="],
|
||||
|
||||
"@esbuild/openharmony-arm64": ["@esbuild/openharmony-arm64@0.25.11", "", { "os": "none", "cpu": "arm64" }, "sha512-rOREuNIQgaiR+9QuNkbkxubbp8MSO9rONmwP5nKncnWJ9v5jQ4JxFnLu4zDSRPf3x4u+2VN4pM4RdyIzDty/wQ=="],
|
||||
|
||||
"@esbuild/sunos-x64": ["@esbuild/sunos-x64@0.25.11", "", { "os": "sunos", "cpu": "x64" }, "sha512-nq2xdYaWxyg9DcIyXkZhcYulC6pQ2FuCgem3LI92IwMgIZ69KHeY8T4Y88pcwoLIjbed8n36CyKoYRDygNSGhA=="],
|
||||
|
||||
"@esbuild/win32-arm64": ["@esbuild/win32-arm64@0.25.11", "", { "os": "win32", "cpu": "arm64" }, "sha512-3XxECOWJq1qMZ3MN8srCJ/QfoLpL+VaxD/WfNRm1O3B4+AZ/BnLVgFbUV3eiRYDMXetciH16dwPbbHqwe1uU0Q=="],
|
||||
|
||||
"@esbuild/win32-ia32": ["@esbuild/win32-ia32@0.25.11", "", { "os": "win32", "cpu": "ia32" }, "sha512-3ukss6gb9XZ8TlRyJlgLn17ecsK4NSQTmdIXRASVsiS2sQ6zPPZklNJT5GR5tE/MUarymmy8kCEf5xPCNCqVOA=="],
|
||||
|
||||
"@esbuild/win32-x64": ["@esbuild/win32-x64@0.25.11", "", { "os": "win32", "cpu": "x64" }, "sha512-D7Hpz6A2L4hzsRpPaCYkQnGOotdUpDzSGRIv9I+1ITdHROSFUWW95ZPZWQmGka1Fg7W3zFJowyn9WGwMJ0+KPA=="],
|
||||
|
||||
"@grpc/grpc-js": ["@grpc/grpc-js@1.14.1", "", { "dependencies": { "@grpc/proto-loader": "^0.8.0", "@js-sdsl/ordered-map": "^4.4.2" } }, "sha512-sPxgEWtPUR3EnRJCEtbGZG2iX8LQDUls2wUS3o27jg07KqJFMq6YDeWvMo1wfpmy3rqRdS0rivpLwhqQtEyCuQ=="],
|
||||
|
||||
"@grpc/proto-loader": ["@grpc/proto-loader@0.8.0", "", { "dependencies": { "lodash.camelcase": "^4.3.0", "long": "^5.0.0", "protobufjs": "^7.5.3", "yargs": "^17.7.2" }, "bin": { "proto-loader-gen-types": "build/bin/proto-loader-gen-types.js" } }, "sha512-rc1hOQtjIWGxcxpb9aHAfLpIctjEnsDehj0DAiVfBlmT84uvR0uUtN2hEi/ecvWVjXUGf5qPF4qEgiLOx1YIMQ=="],
|
||||
|
||||
"@img/colour": ["@img/colour@1.0.0", "", {}, "sha512-A5P/LfWGFSl6nsckYtjw9da+19jB8hkJ6ACTGcDfEJ0aE+l2n2El7dsVM7UVHZQ9s2lmYMWlrS21YLy2IR1LUw=="],
|
||||
|
||||
"@img/sharp-darwin-arm64": ["@img/sharp-darwin-arm64@0.34.4", "", { "optionalDependencies": { "@img/sharp-libvips-darwin-arm64": "1.2.3" }, "os": "darwin", "cpu": "arm64" }, "sha512-sitdlPzDVyvmINUdJle3TNHl+AG9QcwiAMsXmccqsCOMZNIdW2/7S26w0LyU8euiLVzFBL3dXPwVCq/ODnf2vA=="],
|
||||
|
||||
"@img/sharp-darwin-x64": ["@img/sharp-darwin-x64@0.34.4", "", { "optionalDependencies": { "@img/sharp-libvips-darwin-x64": "1.2.3" }, "os": "darwin", "cpu": "x64" }, "sha512-rZheupWIoa3+SOdF/IcUe1ah4ZDpKBGWcsPX6MT0lYniH9micvIU7HQkYTfrx5Xi8u+YqwLtxC/3vl8TQN6rMg=="],
|
||||
|
||||
"@img/sharp-libvips-darwin-arm64": ["@img/sharp-libvips-darwin-arm64@1.2.3", "", { "os": "darwin", "cpu": "arm64" }, "sha512-QzWAKo7kpHxbuHqUC28DZ9pIKpSi2ts2OJnoIGI26+HMgq92ZZ4vk8iJd4XsxN+tYfNJxzH6W62X5eTcsBymHw=="],
|
||||
|
||||
"@img/sharp-libvips-darwin-x64": ["@img/sharp-libvips-darwin-x64@1.2.3", "", { "os": "darwin", "cpu": "x64" }, "sha512-Ju+g2xn1E2AKO6YBhxjj+ACcsPQRHT0bhpglxcEf+3uyPY+/gL8veniKoo96335ZaPo03bdDXMv0t+BBFAbmRA=="],
|
||||
|
||||
"@img/sharp-libvips-linux-arm": ["@img/sharp-libvips-linux-arm@1.2.3", "", { "os": "linux", "cpu": "arm" }, "sha512-x1uE93lyP6wEwGvgAIV0gP6zmaL/a0tGzJs/BIDDG0zeBhMnuUPm7ptxGhUbcGs4okDJrk4nxgrmxpib9g6HpA=="],
|
||||
|
||||
"@img/sharp-libvips-linux-arm64": ["@img/sharp-libvips-linux-arm64@1.2.3", "", { "os": "linux", "cpu": "arm64" }, "sha512-I4RxkXU90cpufazhGPyVujYwfIm9Nk1QDEmiIsaPwdnm013F7RIceaCc87kAH+oUB1ezqEvC6ga4m7MSlqsJvQ=="],
|
||||
|
||||
"@img/sharp-libvips-linux-ppc64": ["@img/sharp-libvips-linux-ppc64@1.2.3", "", { "os": "linux", "cpu": "ppc64" }, "sha512-Y2T7IsQvJLMCBM+pmPbM3bKT/yYJvVtLJGfCs4Sp95SjvnFIjynbjzsa7dY1fRJX45FTSfDksbTp6AGWudiyCg=="],
|
||||
|
||||
"@img/sharp-libvips-linux-s390x": ["@img/sharp-libvips-linux-s390x@1.2.3", "", { "os": "linux", "cpu": "s390x" }, "sha512-RgWrs/gVU7f+K7P+KeHFaBAJlNkD1nIZuVXdQv6S+fNA6syCcoboNjsV2Pou7zNlVdNQoQUpQTk8SWDHUA3y/w=="],
|
||||
|
||||
"@img/sharp-libvips-linux-x64": ["@img/sharp-libvips-linux-x64@1.2.3", "", { "os": "linux", "cpu": "x64" }, "sha512-3JU7LmR85K6bBiRzSUc/Ff9JBVIFVvq6bomKE0e63UXGeRw2HPVEjoJke1Yx+iU4rL7/7kUjES4dZ/81Qjhyxg=="],
|
||||
|
||||
"@img/sharp-libvips-linuxmusl-arm64": ["@img/sharp-libvips-linuxmusl-arm64@1.2.3", "", { "os": "linux", "cpu": "arm64" }, "sha512-F9q83RZ8yaCwENw1GieztSfj5msz7GGykG/BA+MOUefvER69K/ubgFHNeSyUu64amHIYKGDs4sRCMzXVj8sEyw=="],
|
||||
|
||||
"@img/sharp-libvips-linuxmusl-x64": ["@img/sharp-libvips-linuxmusl-x64@1.2.3", "", { "os": "linux", "cpu": "x64" }, "sha512-U5PUY5jbc45ANM6tSJpsgqmBF/VsL6LnxJmIf11kB7J5DctHgqm0SkuXzVWtIY90GnJxKnC/JT251TDnk1fu/g=="],
|
||||
|
||||
"@img/sharp-linux-arm": ["@img/sharp-linux-arm@0.34.4", "", { "optionalDependencies": { "@img/sharp-libvips-linux-arm": "1.2.3" }, "os": "linux", "cpu": "arm" }, "sha512-Xyam4mlqM0KkTHYVSuc6wXRmM7LGN0P12li03jAnZ3EJWZqj83+hi8Y9UxZUbxsgsK1qOEwg7O0Bc0LjqQVtxA=="],
|
||||
|
||||
"@img/sharp-linux-arm64": ["@img/sharp-linux-arm64@0.34.4", "", { "optionalDependencies": { "@img/sharp-libvips-linux-arm64": "1.2.3" }, "os": "linux", "cpu": "arm64" }, "sha512-YXU1F/mN/Wu786tl72CyJjP/Ngl8mGHN1hST4BGl+hiW5jhCnV2uRVTNOcaYPs73NeT/H8Upm3y9582JVuZHrQ=="],
|
||||
|
||||
"@img/sharp-linux-ppc64": ["@img/sharp-linux-ppc64@0.34.4", "", { "optionalDependencies": { "@img/sharp-libvips-linux-ppc64": "1.2.3" }, "os": "linux", "cpu": "ppc64" }, "sha512-F4PDtF4Cy8L8hXA2p3TO6s4aDt93v+LKmpcYFLAVdkkD3hSxZzee0rh6/+94FpAynsuMpLX5h+LRsSG3rIciUQ=="],
|
||||
|
||||
"@img/sharp-linux-s390x": ["@img/sharp-linux-s390x@0.34.4", "", { "optionalDependencies": { "@img/sharp-libvips-linux-s390x": "1.2.3" }, "os": "linux", "cpu": "s390x" }, "sha512-qVrZKE9Bsnzy+myf7lFKvng6bQzhNUAYcVORq2P7bDlvmF6u2sCmK2KyEQEBdYk+u3T01pVsPrkj943T1aJAsw=="],
|
||||
|
||||
"@img/sharp-linux-x64": ["@img/sharp-linux-x64@0.34.4", "", { "optionalDependencies": { "@img/sharp-libvips-linux-x64": "1.2.3" }, "os": "linux", "cpu": "x64" }, "sha512-ZfGtcp2xS51iG79c6Vhw9CWqQC8l2Ot8dygxoDoIQPTat/Ov3qAa8qpxSrtAEAJW+UjTXc4yxCjNfxm4h6Xm2A=="],
|
||||
|
||||
"@img/sharp-linuxmusl-arm64": ["@img/sharp-linuxmusl-arm64@0.34.4", "", { "optionalDependencies": { "@img/sharp-libvips-linuxmusl-arm64": "1.2.3" }, "os": "linux", "cpu": "arm64" }, "sha512-8hDVvW9eu4yHWnjaOOR8kHVrew1iIX+MUgwxSuH2XyYeNRtLUe4VNioSqbNkB7ZYQJj9rUTT4PyRscyk2PXFKA=="],
|
||||
|
||||
"@img/sharp-linuxmusl-x64": ["@img/sharp-linuxmusl-x64@0.34.4", "", { "optionalDependencies": { "@img/sharp-libvips-linuxmusl-x64": "1.2.3" }, "os": "linux", "cpu": "x64" }, "sha512-lU0aA5L8QTlfKjpDCEFOZsTYGn3AEiO6db8W5aQDxj0nQkVrZWmN3ZP9sYKWJdtq3PWPhUNlqehWyXpYDcI9Sg=="],
|
||||
|
||||
"@img/sharp-wasm32": ["@img/sharp-wasm32@0.34.4", "", { "dependencies": { "@emnapi/runtime": "^1.5.0" }, "cpu": "none" }, "sha512-33QL6ZO/qpRyG7woB/HUALz28WnTMI2W1jgX3Nu2bypqLIKx/QKMILLJzJjI+SIbvXdG9fUnmrxR7vbi1sTBeA=="],
|
||||
|
||||
"@img/sharp-win32-arm64": ["@img/sharp-win32-arm64@0.34.4", "", { "os": "win32", "cpu": "arm64" }, "sha512-2Q250do/5WXTwxW3zjsEuMSv5sUU4Tq9VThWKlU2EYLm4MB7ZeMwF+SFJutldYODXF6jzc6YEOC+VfX0SZQPqA=="],
|
||||
|
||||
"@img/sharp-win32-ia32": ["@img/sharp-win32-ia32@0.34.4", "", { "os": "win32", "cpu": "ia32" }, "sha512-3ZeLue5V82dT92CNL6rsal6I2weKw1cYu+rGKm8fOCCtJTR2gYeUfY3FqUnIJsMUPIH68oS5jmZ0NiJ508YpEw=="],
|
||||
|
||||
"@img/sharp-win32-x64": ["@img/sharp-win32-x64@0.34.4", "", { "os": "win32", "cpu": "x64" }, "sha512-xIyj4wpYs8J18sVN3mSQjwrw7fKUqRw+Z5rnHNCy5fYTxigBz81u5mOMPmFumwjcn8+ld1ppptMBCLic1nz6ig=="],
|
||||
|
||||
"@js-sdsl/ordered-map": ["@js-sdsl/ordered-map@4.4.2", "", {}, "sha512-iUKgm52T8HOE/makSxjqoWhe95ZJA1/G1sYsGev2JDKUSS14KAgg1LHb+Ba+IPow0xflbnSkOsZcO08C7w1gYw=="],
|
||||
|
||||
"@kubiks/otel-drizzle": ["@kubiks/otel-drizzle@github:zoriya/drizzle-otel#cc1d59b", { "peerDependencies": { "@opentelemetry/api": ">=1.9.0 <2.0.0", "drizzle-orm": ">=0.28.0" } }, "zoriya-drizzle-otel-cc1d59b"],
|
||||
|
||||
"@opentelemetry/api": ["@opentelemetry/api@1.9.0", "", {}, "sha512-3giAOQvZiH5F9bMlMiv8+GSPMeqg0dbaeo58/0SlA9sxSqZhnUtxzX9/2FzyhS9sWQf5S0GJE0AKBrFqjpeYcg=="],
|
||||
|
||||
"@opentelemetry/api-logs": ["@opentelemetry/api-logs@0.200.0", "", { "dependencies": { "@opentelemetry/api": "^1.3.0" } }, "sha512-IKJBQxh91qJ+3ssRly5hYEJ8NDHu9oY/B1PXVSCWf7zytmYO9RNLB0Ox9XQ/fJ8m6gY6Q6NtBWlmXfaXt5Uc4Q=="],
|
||||
|
||||
"@opentelemetry/context-async-hooks": ["@opentelemetry/context-async-hooks@2.0.0", "", { "peerDependencies": { "@opentelemetry/api": ">=1.0.0 <1.10.0" } }, "sha512-IEkJGzK1A9v3/EHjXh3s2IiFc6L4jfK+lNgKVgUjeUJQRRhnVFMIO3TAvKwonm9O1HebCuoOt98v8bZW7oVQHA=="],
|
||||
|
||||
"@opentelemetry/core": ["@opentelemetry/core@2.0.0", "", { "dependencies": { "@opentelemetry/semantic-conventions": "^1.29.0" }, "peerDependencies": { "@opentelemetry/api": ">=1.0.0 <1.10.0" } }, "sha512-SLX36allrcnVaPYG3R78F/UZZsBsvbc7lMCLx37LyH5MJ1KAAZ2E3mW9OAD3zGz0G8q/BtoS5VUrjzDydhD6LQ=="],
|
||||
|
||||
"@opentelemetry/exporter-logs-otlp-grpc": ["@opentelemetry/exporter-logs-otlp-grpc@0.200.0", "", { "dependencies": { "@grpc/grpc-js": "^1.7.1", "@opentelemetry/core": "2.0.0", "@opentelemetry/otlp-exporter-base": "0.200.0", "@opentelemetry/otlp-grpc-exporter-base": "0.200.0", "@opentelemetry/otlp-transformer": "0.200.0", "@opentelemetry/sdk-logs": "0.200.0" }, "peerDependencies": { "@opentelemetry/api": "^1.3.0" } }, "sha512-+3MDfa5YQPGM3WXxW9kqGD85Q7s9wlEMVNhXXG7tYFLnIeaseUt9YtCeFhEDFzfEktacdFpOtXmJuNW8cHbU5A=="],
|
||||
|
||||
"@opentelemetry/exporter-logs-otlp-http": ["@opentelemetry/exporter-logs-otlp-http@0.200.0", "", { "dependencies": { "@opentelemetry/api-logs": "0.200.0", "@opentelemetry/core": "2.0.0", "@opentelemetry/otlp-exporter-base": "0.200.0", "@opentelemetry/otlp-transformer": "0.200.0", "@opentelemetry/sdk-logs": "0.200.0" }, "peerDependencies": { "@opentelemetry/api": "^1.3.0" } }, "sha512-KfWw49htbGGp9s8N4KI8EQ9XuqKJ0VG+yVYVYFiCYSjEV32qpQ5qZ9UZBzOZ6xRb+E16SXOSCT3RkqBVSABZ+g=="],
|
||||
|
||||
"@opentelemetry/exporter-logs-otlp-proto": ["@opentelemetry/exporter-logs-otlp-proto@0.200.0", "", { "dependencies": { "@opentelemetry/api-logs": "0.200.0", "@opentelemetry/core": "2.0.0", "@opentelemetry/otlp-exporter-base": "0.200.0", "@opentelemetry/otlp-transformer": "0.200.0", "@opentelemetry/resources": "2.0.0", "@opentelemetry/sdk-logs": "0.200.0", "@opentelemetry/sdk-trace-base": "2.0.0" }, "peerDependencies": { "@opentelemetry/api": "^1.3.0" } }, "sha512-GmahpUU/55hxfH4TP77ChOfftADsCq/nuri73I/AVLe2s4NIglvTsaACkFVZAVmnXXyPS00Fk3x27WS3yO07zA=="],
|
||||
|
||||
"@opentelemetry/exporter-metrics-otlp-grpc": ["@opentelemetry/exporter-metrics-otlp-grpc@0.200.0", "", { "dependencies": { "@grpc/grpc-js": "^1.7.1", "@opentelemetry/core": "2.0.0", "@opentelemetry/exporter-metrics-otlp-http": "0.200.0", "@opentelemetry/otlp-exporter-base": "0.200.0", "@opentelemetry/otlp-grpc-exporter-base": "0.200.0", "@opentelemetry/otlp-transformer": "0.200.0", "@opentelemetry/resources": "2.0.0", "@opentelemetry/sdk-metrics": "2.0.0" }, "peerDependencies": { "@opentelemetry/api": "^1.3.0" } }, "sha512-uHawPRvKIrhqH09GloTuYeq2BjyieYHIpiklOvxm9zhrCL2eRsnI/6g9v2BZTVtGp8tEgIa7rCQ6Ltxw6NBgew=="],
|
||||
|
||||
"@opentelemetry/exporter-metrics-otlp-http": ["@opentelemetry/exporter-metrics-otlp-http@0.200.0", "", { "dependencies": { "@opentelemetry/core": "2.0.0", "@opentelemetry/otlp-exporter-base": "0.200.0", "@opentelemetry/otlp-transformer": "0.200.0", "@opentelemetry/resources": "2.0.0", "@opentelemetry/sdk-metrics": "2.0.0" }, "peerDependencies": { "@opentelemetry/api": "^1.3.0" } }, "sha512-5BiR6i8yHc9+qW7F6LqkuUnIzVNA7lt0qRxIKcKT+gq3eGUPHZ3DY29sfxI3tkvnwMgtnHDMNze5DdxW39HsAw=="],
|
||||
|
||||
"@opentelemetry/exporter-metrics-otlp-proto": ["@opentelemetry/exporter-metrics-otlp-proto@0.200.0", "", { "dependencies": { "@opentelemetry/core": "2.0.0", "@opentelemetry/exporter-metrics-otlp-http": "0.200.0", "@opentelemetry/otlp-exporter-base": "0.200.0", "@opentelemetry/otlp-transformer": "0.200.0", "@opentelemetry/resources": "2.0.0", "@opentelemetry/sdk-metrics": "2.0.0" }, "peerDependencies": { "@opentelemetry/api": "^1.3.0" } }, "sha512-E+uPj0yyvz81U9pvLZp3oHtFrEzNSqKGVkIViTQY1rH3TOobeJPSpLnTVXACnCwkPR5XeTvPnK3pZ2Kni8AFMg=="],
|
||||
|
||||
"@opentelemetry/exporter-prometheus": ["@opentelemetry/exporter-prometheus@0.200.0", "", { "dependencies": { "@opentelemetry/core": "2.0.0", "@opentelemetry/resources": "2.0.0", "@opentelemetry/sdk-metrics": "2.0.0" }, "peerDependencies": { "@opentelemetry/api": "^1.3.0" } }, "sha512-ZYdlU9r0USuuYppiDyU2VFRA0kFl855ylnb3N/2aOlXrbA4PMCznen7gmPbetGQu7pz8Jbaf4fwvrDnVdQQXSw=="],
|
||||
|
||||
"@opentelemetry/exporter-trace-otlp-grpc": ["@opentelemetry/exporter-trace-otlp-grpc@0.200.0", "", { "dependencies": { "@grpc/grpc-js": "^1.7.1", "@opentelemetry/core": "2.0.0", "@opentelemetry/otlp-exporter-base": "0.200.0", "@opentelemetry/otlp-grpc-exporter-base": "0.200.0", "@opentelemetry/otlp-transformer": "0.200.0", "@opentelemetry/resources": "2.0.0", "@opentelemetry/sdk-trace-base": "2.0.0" }, "peerDependencies": { "@opentelemetry/api": "^1.3.0" } }, "sha512-hmeZrUkFl1YMsgukSuHCFPYeF9df0hHoKeHUthRKFCxiURs+GwF1VuabuHmBMZnjTbsuvNjOB+JSs37Csem/5Q=="],
|
||||
|
||||
"@opentelemetry/exporter-trace-otlp-http": ["@opentelemetry/exporter-trace-otlp-http@0.200.0", "", { "dependencies": { "@opentelemetry/core": "2.0.0", "@opentelemetry/otlp-exporter-base": "0.200.0", "@opentelemetry/otlp-transformer": "0.200.0", "@opentelemetry/resources": "2.0.0", "@opentelemetry/sdk-trace-base": "2.0.0" }, "peerDependencies": { "@opentelemetry/api": "^1.3.0" } }, "sha512-Goi//m/7ZHeUedxTGVmEzH19NgqJY+Bzr6zXo1Rni1+hwqaksEyJ44gdlEMREu6dzX1DlAaH/qSykSVzdrdafA=="],
|
||||
|
||||
"@opentelemetry/exporter-trace-otlp-proto": ["@opentelemetry/exporter-trace-otlp-proto@0.200.0", "", { "dependencies": { "@opentelemetry/core": "2.0.0", "@opentelemetry/otlp-exporter-base": "0.200.0", "@opentelemetry/otlp-transformer": "0.200.0", "@opentelemetry/resources": "2.0.0", "@opentelemetry/sdk-trace-base": "2.0.0" }, "peerDependencies": { "@opentelemetry/api": "^1.3.0" } }, "sha512-V9TDSD3PjK1OREw2iT9TUTzNYEVWJk4Nhodzhp9eiz4onDMYmPy3LaGbPv81yIR6dUb/hNp/SIhpiCHwFUq2Vg=="],
|
||||
|
||||
"@opentelemetry/exporter-zipkin": ["@opentelemetry/exporter-zipkin@2.0.0", "", { "dependencies": { "@opentelemetry/core": "2.0.0", "@opentelemetry/resources": "2.0.0", "@opentelemetry/sdk-trace-base": "2.0.0", "@opentelemetry/semantic-conventions": "^1.29.0" }, "peerDependencies": { "@opentelemetry/api": "^1.0.0" } }, "sha512-icxaKZ+jZL/NHXX8Aru4HGsrdhK0MLcuRXkX5G5IRmCgoRLw+Br6I/nMVozX2xjGGwV7hw2g+4Slj8K7s4HbVg=="],
|
||||
|
||||
"@opentelemetry/instrumentation": ["@opentelemetry/instrumentation@0.200.0", "", { "dependencies": { "@opentelemetry/api-logs": "0.200.0", "@types/shimmer": "^1.2.0", "import-in-the-middle": "^1.8.1", "require-in-the-middle": "^7.1.1", "shimmer": "^1.2.1" }, "peerDependencies": { "@opentelemetry/api": "^1.3.0" } }, "sha512-pmPlzfJd+vvgaZd/reMsC8RWgTXn2WY1OWT5RT42m3aOn5532TozwXNDhg1vzqJ+jnvmkREcdLr27ebJEQt0Jg=="],
|
||||
|
||||
"@opentelemetry/otlp-exporter-base": ["@opentelemetry/otlp-exporter-base@0.200.0", "", { "dependencies": { "@opentelemetry/core": "2.0.0", "@opentelemetry/otlp-transformer": "0.200.0" }, "peerDependencies": { "@opentelemetry/api": "^1.3.0" } }, "sha512-IxJgA3FD7q4V6gGq4bnmQM5nTIyMDkoGFGrBrrDjB6onEiq1pafma55V+bHvGYLWvcqbBbRfezr1GED88lacEQ=="],
|
||||
|
||||
"@opentelemetry/otlp-grpc-exporter-base": ["@opentelemetry/otlp-grpc-exporter-base@0.200.0", "", { "dependencies": { "@grpc/grpc-js": "^1.7.1", "@opentelemetry/core": "2.0.0", "@opentelemetry/otlp-exporter-base": "0.200.0", "@opentelemetry/otlp-transformer": "0.200.0" }, "peerDependencies": { "@opentelemetry/api": "^1.3.0" } }, "sha512-CK2S+bFgOZ66Bsu5hlDeOX6cvW5FVtVjFFbWuaJP0ELxJKBB6HlbLZQ2phqz/uLj1cWap5xJr/PsR3iGoB7Vqw=="],
|
||||
|
||||
"@opentelemetry/otlp-transformer": ["@opentelemetry/otlp-transformer@0.200.0", "", { "dependencies": { "@opentelemetry/api-logs": "0.200.0", "@opentelemetry/core": "2.0.0", "@opentelemetry/resources": "2.0.0", "@opentelemetry/sdk-logs": "0.200.0", "@opentelemetry/sdk-metrics": "2.0.0", "@opentelemetry/sdk-trace-base": "2.0.0", "protobufjs": "^7.3.0" }, "peerDependencies": { "@opentelemetry/api": "^1.3.0" } }, "sha512-+9YDZbYybOnv7sWzebWOeK6gKyt2XE7iarSyBFkwwnP559pEevKOUD8NyDHhRjCSp13ybh9iVXlMfcj/DwF/yw=="],
|
||||
|
||||
"@opentelemetry/propagator-b3": ["@opentelemetry/propagator-b3@2.0.0", "", { "dependencies": { "@opentelemetry/core": "2.0.0" }, "peerDependencies": { "@opentelemetry/api": ">=1.0.0 <1.10.0" } }, "sha512-blx9S2EI49Ycuw6VZq+bkpaIoiJFhsDuvFGhBIoH3vJ5oYjJ2U0s3fAM5jYft99xVIAv6HqoPtlP9gpVA2IZtA=="],
|
||||
|
||||
"@opentelemetry/propagator-jaeger": ["@opentelemetry/propagator-jaeger@2.0.0", "", { "dependencies": { "@opentelemetry/core": "2.0.0" }, "peerDependencies": { "@opentelemetry/api": ">=1.0.0 <1.10.0" } }, "sha512-Mbm/LSFyAtQKP0AQah4AfGgsD+vsZcyreZoQ5okFBk33hU7AquU4TltgyL9dvaO8/Zkoud8/0gEvwfOZ5d7EPA=="],
|
||||
|
||||
"@opentelemetry/resources": ["@opentelemetry/resources@2.0.0", "", { "dependencies": { "@opentelemetry/core": "2.0.0", "@opentelemetry/semantic-conventions": "^1.29.0" }, "peerDependencies": { "@opentelemetry/api": ">=1.3.0 <1.10.0" } }, "sha512-rnZr6dML2z4IARI4zPGQV4arDikF/9OXZQzrC01dLmn0CZxU5U5OLd/m1T7YkGRj5UitjeoCtg/zorlgMQcdTg=="],
|
||||
|
||||
"@opentelemetry/sdk-logs": ["@opentelemetry/sdk-logs@0.200.0", "", { "dependencies": { "@opentelemetry/api-logs": "0.200.0", "@opentelemetry/core": "2.0.0", "@opentelemetry/resources": "2.0.0" }, "peerDependencies": { "@opentelemetry/api": ">=1.4.0 <1.10.0" } }, "sha512-VZG870063NLfObmQQNtCVcdXXLzI3vOjjrRENmU37HYiPFa0ZXpXVDsTD02Nh3AT3xYJzQaWKl2X2lQ2l7TWJA=="],
|
||||
|
||||
"@opentelemetry/sdk-metrics": ["@opentelemetry/sdk-metrics@2.0.0", "", { "dependencies": { "@opentelemetry/core": "2.0.0", "@opentelemetry/resources": "2.0.0" }, "peerDependencies": { "@opentelemetry/api": ">=1.9.0 <1.10.0" } }, "sha512-Bvy8QDjO05umd0+j+gDeWcTaVa1/R2lDj/eOvjzpm8VQj1K1vVZJuyjThpV5/lSHyYW2JaHF2IQ7Z8twJFAhjA=="],
|
||||
|
||||
"@opentelemetry/sdk-node": ["@opentelemetry/sdk-node@0.200.0", "", { "dependencies": { "@opentelemetry/api-logs": "0.200.0", "@opentelemetry/core": "2.0.0", "@opentelemetry/exporter-logs-otlp-grpc": "0.200.0", "@opentelemetry/exporter-logs-otlp-http": "0.200.0", "@opentelemetry/exporter-logs-otlp-proto": "0.200.0", "@opentelemetry/exporter-metrics-otlp-grpc": "0.200.0", "@opentelemetry/exporter-metrics-otlp-http": "0.200.0", "@opentelemetry/exporter-metrics-otlp-proto": "0.200.0", "@opentelemetry/exporter-prometheus": "0.200.0", "@opentelemetry/exporter-trace-otlp-grpc": "0.200.0", "@opentelemetry/exporter-trace-otlp-http": "0.200.0", "@opentelemetry/exporter-trace-otlp-proto": "0.200.0", "@opentelemetry/exporter-zipkin": "2.0.0", "@opentelemetry/instrumentation": "0.200.0", "@opentelemetry/propagator-b3": "2.0.0", "@opentelemetry/propagator-jaeger": "2.0.0", "@opentelemetry/resources": "2.0.0", "@opentelemetry/sdk-logs": "0.200.0", "@opentelemetry/sdk-metrics": "2.0.0", "@opentelemetry/sdk-trace-base": "2.0.0", "@opentelemetry/sdk-trace-node": "2.0.0", "@opentelemetry/semantic-conventions": "^1.29.0" }, "peerDependencies": { "@opentelemetry/api": ">=1.3.0 <1.10.0" } }, "sha512-S/YSy9GIswnhYoDor1RusNkmRughipvTCOQrlF1dzI70yQaf68qgf5WMnzUxdlCl3/et/pvaO75xfPfuEmCK5A=="],
|
||||
|
||||
"@opentelemetry/sdk-trace-base": ["@opentelemetry/sdk-trace-base@2.0.0", "", { "dependencies": { "@opentelemetry/core": "2.0.0", "@opentelemetry/resources": "2.0.0", "@opentelemetry/semantic-conventions": "^1.29.0" }, "peerDependencies": { "@opentelemetry/api": ">=1.3.0 <1.10.0" } }, "sha512-qQnYdX+ZCkonM7tA5iU4fSRsVxbFGml8jbxOgipRGMFHKaXKHQ30js03rTobYjKjIfnOsZSbHKWF0/0v0OQGfw=="],
|
||||
|
||||
"@opentelemetry/sdk-trace-node": ["@opentelemetry/sdk-trace-node@2.0.0", "", { "dependencies": { "@opentelemetry/context-async-hooks": "2.0.0", "@opentelemetry/core": "2.0.0", "@opentelemetry/sdk-trace-base": "2.0.0" }, "peerDependencies": { "@opentelemetry/api": ">=1.0.0 <1.10.0" } }, "sha512-omdilCZozUjQwY3uZRBwbaRMJ3p09l4t187Lsdf0dGMye9WKD4NGcpgZRvqhI1dwcH6og+YXQEtoO9Wx3ykilg=="],
|
||||
|
||||
"@opentelemetry/semantic-conventions": ["@opentelemetry/semantic-conventions@1.38.0", "", {}, "sha512-kocjix+/sSggfJhwXqClZ3i9Y/MI0fp7b+g7kCRm6psy2dsf8uApTRclwG18h8Avm7C9+fnt+O36PspJ/OzoWg=="],
|
||||
|
||||
"@protobufjs/aspromise": ["@protobufjs/aspromise@1.1.2", "", {}, "sha512-j+gKExEuLmKwvz3OgROXtrJ2UG2x8Ch2YZUxahh+s1F2HZ+wAceUNLkvy6zKCPVRkU++ZWQrdxsUeQXmcg4uoQ=="],
|
||||
|
||||
"@protobufjs/base64": ["@protobufjs/base64@1.1.2", "", {}, "sha512-AZkcAA5vnN/v4PDqKyMR5lx7hZttPDgClv83E//FMNhR2TMcLUhfRUBHCmSl0oi9zMgDDqRUJkSxO3wm85+XLg=="],
|
||||
|
||||
"@protobufjs/codegen": ["@protobufjs/codegen@2.0.4", "", {}, "sha512-YyFaikqM5sH0ziFZCN3xDC7zeGaB/d0IUb9CATugHWbd1FRFwWwt4ld4OYMPWu5a3Xe01mGAULCdqhMlPl29Jg=="],
|
||||
|
||||
"@protobufjs/eventemitter": ["@protobufjs/eventemitter@1.1.0", "", {}, "sha512-j9ednRT81vYJ9OfVuXG6ERSTdEL1xVsNgqpkxMsbIabzSo3goCjDIveeGv5d03om39ML71RdmrGNjG5SReBP/Q=="],
|
||||
|
||||
"@protobufjs/fetch": ["@protobufjs/fetch@1.1.0", "", { "dependencies": { "@protobufjs/aspromise": "^1.1.1", "@protobufjs/inquire": "^1.1.0" } }, "sha512-lljVXpqXebpsijW71PZaCYeIcE5on1w5DlQy5WH6GLbFryLUrBD4932W/E2BSpfRJWseIL4v/KPgBFxDOIdKpQ=="],
|
||||
|
||||
"@protobufjs/float": ["@protobufjs/float@1.0.2", "", {}, "sha512-Ddb+kVXlXst9d+R9PfTIxh1EdNkgoRe5tOX6t01f1lYWOvJnSPDBlG241QLzcyPdoNTsblLUdujGSE4RzrTZGQ=="],
|
||||
|
||||
"@protobufjs/inquire": ["@protobufjs/inquire@1.1.0", "", {}, "sha512-kdSefcPdruJiFMVSbn801t4vFK7KB/5gd2fYvrxhuJYg8ILrmn9SKSX2tZdV6V+ksulWqS7aXjBcRXl3wHoD9Q=="],
|
||||
|
||||
"@protobufjs/path": ["@protobufjs/path@1.1.2", "", {}, "sha512-6JOcJ5Tm08dOHAbdR3GrvP+yUUfkjG5ePsHYczMFLq3ZmMkAD98cDgcT2iA1lJ9NVwFd4tH/iSSoe44YWkltEA=="],
|
||||
|
||||
"@protobufjs/pool": ["@protobufjs/pool@1.1.0", "", {}, "sha512-0kELaGSIDBKvcgS4zkjz1PeddatrjYcmMWOlAuAPwAeccUrPHdUqo/J6LiymHHEiJT5NrF1UVwxY14f+fy4WQw=="],
|
||||
|
||||
"@protobufjs/utf8": ["@protobufjs/utf8@1.1.0", "", {}, "sha512-Vvn3zZrhQZkkBE8LSuW3em98c0FwgO4nxzv6OdSxPKJIEKY2bGbHn+mhGIPerzI4twdxaP8/0+06HBpwf345Lw=="],
|
||||
|
||||
"@scalar/openapi-types": ["@scalar/openapi-types@0.1.9", "", {}, "sha512-HQQudOSQBU7ewzfnBW9LhDmBE2XOJgSfwrh5PlUB7zJup/kaRkBGNgV2wMjNz9Af/uztiU/xNrO179FysmUT+g=="],
|
||||
|
||||
"@scalar/themes": ["@scalar/themes@0.9.81", "", { "dependencies": { "@scalar/types": "0.1.3" } }, "sha512-asTgdqo8ZYibBBWVYy0503qPx3cvwDlYNuc/cLbrCmTav0MAEL4wNb/gz9iScMVSMwhdkSkL5g9LPdr2mQrHzw=="],
|
||||
|
||||
"@scalar/types": ["@scalar/types@0.1.3", "", { "dependencies": { "@scalar/openapi-types": "0.1.9", "@unhead/schema": "^1.11.11", "zod": "^3.23.8" } }, "sha512-Fxtgjp5wHhTzXiyODYWIoTsTy3oFC70vme+0I7MNwd8i6D8qplFNnpURueqBuP4MglBM2ZhFv3hPLw4D69anDA=="],
|
||||
|
||||
"@sinclair/typebox": ["@sinclair/typebox@0.34.33", "", {}, "sha512-5HAV9exOMcXRUxo+9iYB5n09XxzCXnfy4VTNW4xnDv+FgjzAGY989C28BIdljKqmF+ZltUwujE3aossvcVtq6g=="],
|
||||
|
||||
"@tokenizer/inflate": ["@tokenizer/inflate@0.2.7", "", { "dependencies": { "debug": "^4.4.0", "fflate": "^0.8.2", "token-types": "^6.0.0" } }, "sha512-MADQgmZT1eKjp06jpI2yozxaU9uVs4GzzgSL+uEq7bVcJ9V1ZXQkeGNql1fsSI0gMy1vhvNTNbUqrx+pZfJVmg=="],
|
||||
|
||||
"@tokenizer/token": ["@tokenizer/token@0.3.0", "", {}, "sha512-OvjF+z51L3ov0OyAU0duzsYuvO01PH7x4t6DJx+guahgTnBHkhJdG7soQeTSFLWN3efnHyibZ4Z8l2EuWwJN3A=="],
|
||||
|
||||
"@types/bun": ["@types/bun@1.3.1", "", { "dependencies": { "bun-types": "1.3.1" } }, "sha512-4jNMk2/K9YJtfqwoAa28c8wK+T7nvJFOjxI4h/7sORWcypRNxBpr+TPNaCfVWq70tLCJsqoFwcf0oI0JU/fvMQ=="],
|
||||
|
||||
"@types/node": ["@types/node@22.13.13", "", { "dependencies": { "undici-types": "~6.20.0" } }, "sha512-ClsL5nMwKaBRwPcCvH8E7+nU4GxHVx1axNvMZTFHMEfNI7oahimt26P5zjVCRrjiIWj6YFXfE1v3dEp94wLcGQ=="],
|
||||
|
||||
"@types/pg": ["@types/pg@8.15.5", "", { "dependencies": { "@types/node": "*", "pg-protocol": "*", "pg-types": "^2.2.0" } }, "sha512-LF7lF6zWEKxuT3/OR8wAZGzkg4ENGXFNyiV/JeOt9z5B+0ZVwbql9McqX5c/WStFq1GaGso7H1AzP/qSzmlCKQ=="],
|
||||
|
||||
"@types/react": ["@types/react@19.2.2", "", { "dependencies": { "csstype": "^3.0.2" } }, "sha512-6mDvHUFSjyT2B2yeNx2nUgMxh9LtOWvkhIU3uePn2I2oyNymUAX1NIsdgviM4CH+JSrp2D2hsMvJOkxY+0wNRA=="],
|
||||
|
||||
"@types/shimmer": ["@types/shimmer@1.2.0", "", {}, "sha512-UE7oxhQLLd9gub6JKIAhDq06T0F6FnztwMNRvYgjeQSBeMc1ZG/tA47EwfduvkuQS8apbkM/lpLpWsaCeYsXVg=="],
|
||||
|
||||
"@unhead/schema": ["@unhead/schema@1.11.20", "", { "dependencies": { "hookable": "^5.5.3", "zhead": "^2.2.4" } }, "sha512-0zWykKAaJdm+/Y7yi/Yds20PrUK7XabLe9c3IRcjnwYmSWY6z0Cr19VIs3ozCj8P+GhR+/TI2mwtGlueCEYouA=="],
|
||||
|
||||
"acorn": ["acorn@8.15.0", "", { "bin": { "acorn": "bin/acorn" } }, "sha512-NZyJarBfL7nWwIq+FDL6Zp/yHEhePMNnnJ0y3qfieCrmNvYct8uvtiV41UvlSe6apAfk0fY1FbWx+NwfmpvtTg=="],
|
||||
|
||||
"acorn-import-attributes": ["acorn-import-attributes@1.9.5", "", { "peerDependencies": { "acorn": "^8" } }, "sha512-n02Vykv5uA3eHGM/Z2dQrcD56kL8TyDb2p1+0P83PClMnC/nc+anbQRhIOWnSq4Ke/KvDPrY3C9hDtC/A3eHnQ=="],
|
||||
|
||||
"ansi-regex": ["ansi-regex@5.0.1", "", {}, "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ=="],
|
||||
|
||||
"ansi-styles": ["ansi-styles@4.3.0", "", { "dependencies": { "color-convert": "^2.0.1" } }, "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg=="],
|
||||
|
||||
"blurhash": ["blurhash@2.0.5", "", {}, "sha512-cRygWd7kGBQO3VEhPiTgq4Wc43ctsM+o46urrmPOiuAe+07fzlSB9OJVdpgDL0jPqXUVQ9ht7aq7kxOeJHRK+w=="],
|
||||
|
||||
"buffer-from": ["buffer-from@1.1.2", "", {}, "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ=="],
|
||||
|
||||
"bun-types": ["bun-types@1.3.1", "", { "dependencies": { "@types/node": "*" }, "peerDependencies": { "@types/react": "^19" } }, "sha512-NMrcy7smratanWJ2mMXdpatalovtxVggkj11bScuWuiOoXTiKIu2eVS1/7qbyI/4yHedtsn175n4Sm4JcdHLXw=="],
|
||||
|
||||
"char-info": ["char-info@0.3.5", "", { "dependencies": { "node-interval-tree": "^1.3.3" } }, "sha512-gRslEBFEcuLMGLNO1EFIrdN1MMUfO+aqa7y8iWzNyAzB3mYKnTIvP+ioW3jpyeEvqA5WapVLIPINGtFjEIH4cQ=="],
|
||||
|
||||
"cjs-module-lexer": ["cjs-module-lexer@1.4.3", "", {}, "sha512-9z8TZaGM1pfswYeXrUpzPrkx8UnWYdhJclsiYMm6x/w5+nN+8Tf/LnAgfLGQCm59qAOxU8WwHEq2vNwF6i4j+Q=="],
|
||||
|
||||
"cliui": ["cliui@8.0.1", "", { "dependencies": { "string-width": "^4.2.0", "strip-ansi": "^6.0.1", "wrap-ansi": "^7.0.0" } }, "sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ=="],
|
||||
|
||||
"color-convert": ["color-convert@2.0.1", "", { "dependencies": { "color-name": "~1.1.4" } }, "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ=="],
|
||||
|
||||
"color-name": ["color-name@1.1.4", "", {}, "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA=="],
|
||||
|
||||
"cookie": ["cookie@1.0.2", "", {}, "sha512-9Kr/j4O16ISv8zBBhJoi4bXOYNTkFLOqSL3UDB0njXxCXNezjeyVrJyGOWtgfs/q2km1gwBcfH8q1yEGoMYunA=="],
|
||||
|
||||
"csstype": ["csstype@3.1.3", "", {}, "sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw=="],
|
||||
|
||||
"debug": ["debug@4.4.0", "", { "dependencies": { "ms": "^2.1.3" } }, "sha512-6WTZ/IxCY/T6BALoZHaE4ctp9xm+Z5kY/pzYaCHRFeyVhojxlrm+46y68HA6hr0TcwEssoxNiDEUJQjfPZ/RYA=="],
|
||||
|
||||
"detect-libc": ["detect-libc@2.1.2", "", {}, "sha512-Btj2BOOO83o3WyH59e8MgXsxEQVcarkUOpEYrubB0urwnN10yQ364rsiByU11nZlqWYZm05i/of7io4mzihBtQ=="],
|
||||
|
||||
"drizzle-kit": ["drizzle-kit@0.31.5", "", { "dependencies": { "@drizzle-team/brocli": "^0.10.2", "@esbuild-kit/esm-loader": "^2.5.5", "esbuild": "^0.25.4", "esbuild-register": "^3.5.0" }, "bin": { "drizzle-kit": "bin.cjs" } }, "sha512-+CHgPFzuoTQTt7cOYCV6MOw2w8vqEn/ap1yv4bpZOWL03u7rlVRQhUY0WYT3rHsgVTXwYQDZaSUJSQrMBUKuWg=="],
|
||||
|
||||
"drizzle-orm": ["drizzle-orm@0.44.7", "", { "peerDependencies": { "@aws-sdk/client-rds-data": ">=3", "@cloudflare/workers-types": ">=4", "@electric-sql/pglite": ">=0.2.0", "@libsql/client": ">=0.10.0", "@libsql/client-wasm": ">=0.10.0", "@neondatabase/serverless": ">=0.10.0", "@op-engineering/op-sqlite": ">=2", "@opentelemetry/api": "^1.4.1", "@planetscale/database": ">=1.13", "@prisma/client": "*", "@tidbcloud/serverless": "*", "@types/better-sqlite3": "*", "@types/pg": "*", "@types/sql.js": "*", "@upstash/redis": ">=1.34.7", "@vercel/postgres": ">=0.8.0", "@xata.io/client": "*", "better-sqlite3": ">=7", "bun-types": "*", "expo-sqlite": ">=14.0.0", "gel": ">=2", "knex": "*", "kysely": "*", "mysql2": ">=2", "pg": ">=8", "postgres": ">=3", "sql.js": ">=1", "sqlite3": ">=5" }, "optionalPeers": ["@aws-sdk/client-rds-data", "@cloudflare/workers-types", "@electric-sql/pglite", "@libsql/client", "@libsql/client-wasm", "@neondatabase/serverless", "@op-engineering/op-sqlite", "@opentelemetry/api", "@planetscale/database", "@prisma/client", "@tidbcloud/serverless", "@types/better-sqlite3", "@types/pg", "@types/sql.js", "@upstash/redis", "@vercel/postgres", "@xata.io/client", "better-sqlite3", "bun-types", "expo-sqlite", "gel", "knex", "kysely", "mysql2", "pg", "postgres", "sql.js", "sqlite3"] }, "sha512-quIpnYznjU9lHshEOAYLoZ9s3jweleHlZIAWR/jX9gAWNg/JhQ1wj0KGRf7/Zm+obRrYd9GjPVJg790QY9N5AQ=="],
|
||||
|
||||
"elysia": ["elysia@1.4.13", "", { "dependencies": { "cookie": "^1.0.2", "exact-mirror": "0.2.2", "fast-decode-uri-component": "^1.0.1", "memoirist": "^0.4.0" }, "peerDependencies": { "@sinclair/typebox": ">= 0.34.0 < 1", "@types/bun": ">= 1.2.0", "file-type": ">= 20.0.0", "openapi-types": ">= 12.0.0", "typescript": ">= 5.0.0" }, "optionalPeers": ["@types/bun", "typescript"] }, "sha512-6QaWQEm7QN1UCo1TPpEjaRJPHUmnM7R29y6LY224frDGk5PrpAnWmdHkoZxkcv+JRWp1j2ROr2IHbxHbG/jRjw=="],
|
||||
|
||||
"emoji-regex": ["emoji-regex@8.0.0", "", {}, "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A=="],
|
||||
|
||||
"esbuild": ["esbuild@0.25.11", "", { "optionalDependencies": { "@esbuild/aix-ppc64": "0.25.11", "@esbuild/android-arm": "0.25.11", "@esbuild/android-arm64": "0.25.11", "@esbuild/android-x64": "0.25.11", "@esbuild/darwin-arm64": "0.25.11", "@esbuild/darwin-x64": "0.25.11", "@esbuild/freebsd-arm64": "0.25.11", "@esbuild/freebsd-x64": "0.25.11", "@esbuild/linux-arm": "0.25.11", "@esbuild/linux-arm64": "0.25.11", "@esbuild/linux-ia32": "0.25.11", "@esbuild/linux-loong64": "0.25.11", "@esbuild/linux-mips64el": "0.25.11", "@esbuild/linux-ppc64": "0.25.11", "@esbuild/linux-riscv64": "0.25.11", "@esbuild/linux-s390x": "0.25.11", "@esbuild/linux-x64": "0.25.11", "@esbuild/netbsd-arm64": "0.25.11", "@esbuild/netbsd-x64": "0.25.11", "@esbuild/openbsd-arm64": "0.25.11", "@esbuild/openbsd-x64": "0.25.11", "@esbuild/openharmony-arm64": "0.25.11", "@esbuild/sunos-x64": "0.25.11", "@esbuild/win32-arm64": "0.25.11", "@esbuild/win32-ia32": "0.25.11", "@esbuild/win32-x64": "0.25.11" }, "bin": { "esbuild": "bin/esbuild" } }, "sha512-KohQwyzrKTQmhXDW1PjCv3Tyspn9n5GcY2RTDqeORIdIJY8yKIF7sTSopFmn/wpMPW4rdPXI0UE5LJLuq3bx0Q=="],
|
||||
|
||||
"esbuild-register": ["esbuild-register@3.6.0", "", { "dependencies": { "debug": "^4.3.4" }, "peerDependencies": { "esbuild": ">=0.12 <1" } }, "sha512-H2/S7Pm8a9CL1uhp9OvjwrBh5Pvx0H8qVOxNu8Wed9Y7qv56MPtq+GGM8RJpq6glYJn9Wspr8uw7l55uyinNeg=="],
|
||||
|
||||
"escalade": ["escalade@3.2.0", "", {}, "sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA=="],
|
||||
|
||||
"exact-mirror": ["exact-mirror@0.2.2", "", { "peerDependencies": { "@sinclair/typebox": "^0.34.15" }, "optionalPeers": ["@sinclair/typebox"] }, "sha512-CrGe+4QzHZlnrXZVlo/WbUZ4qQZq8C0uATQVGVgXIrNXgHDBBNFD1VRfssRA2C9t3RYvh3MadZSdg2Wy7HBoQA=="],
|
||||
|
||||
"fast-decode-uri-component": ["fast-decode-uri-component@1.0.1", "", {}, "sha512-WKgKWg5eUxvRZGwW8FvfbaH7AXSh2cL+3j5fMGzUMCxWBJ3dV3a7Wz8y2f/uQ0e3B6WmodD3oS54jTQ9HVTIIg=="],
|
||||
|
||||
"fflate": ["fflate@0.8.2", "", {}, "sha512-cPJU47OaAoCbg0pBvzsgpTPhmhqI5eJjh/JIu8tPj5q+T7iLvW/JAYUqmE7KOB4R1ZyEhzBaIQpQpardBF5z8A=="],
|
||||
|
||||
"file-type": ["file-type@20.5.0", "", { "dependencies": { "@tokenizer/inflate": "^0.2.6", "strtok3": "^10.2.0", "token-types": "^6.0.0", "uint8array-extras": "^1.4.0" } }, "sha512-BfHZtG/l9iMm4Ecianu7P8HRD2tBHLtjXinm4X62XBOYzi7CYA7jyqfJzOvXHqzVrVPYqBo2/GvbARMaaJkKVg=="],
|
||||
|
||||
"function-bind": ["function-bind@1.1.2", "", {}, "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA=="],
|
||||
|
||||
"get-caller-file": ["get-caller-file@2.0.5", "", {}, "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg=="],
|
||||
|
||||
"get-tsconfig": ["get-tsconfig@4.10.0", "", { "dependencies": { "resolve-pkg-maps": "^1.0.0" } }, "sha512-kGzZ3LWWQcGIAmg6iWvXn0ei6WDtV26wzHRMwDSzmAbcXrTEXxHy6IehI6/4eT6VRKyMP1eF1VqwrVUmE/LR7A=="],
|
||||
|
||||
"hasown": ["hasown@2.0.2", "", { "dependencies": { "function-bind": "^1.1.2" } }, "sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ=="],
|
||||
|
||||
"hookable": ["hookable@5.5.3", "", {}, "sha512-Yc+BQe8SvoXH1643Qez1zqLRmbA5rCL+sSmk6TVos0LWVfNIB7PGncdlId77WzLGSIB5KaWgTaNTs2lNVEI6VQ=="],
|
||||
|
||||
"ieee754": ["ieee754@1.2.1", "", {}, "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA=="],
|
||||
|
||||
"import-in-the-middle": ["import-in-the-middle@1.15.0", "", { "dependencies": { "acorn": "^8.14.0", "acorn-import-attributes": "^1.9.5", "cjs-module-lexer": "^1.2.2", "module-details-from-path": "^1.0.3" } }, "sha512-bpQy+CrsRmYmoPMAE/0G33iwRqwW4ouqdRg8jgbH3aKuCtOc8lxgmYXg2dMM92CRiGP660EtBcymH/eVUpCSaA=="],
|
||||
|
||||
"is-core-module": ["is-core-module@2.16.1", "", { "dependencies": { "hasown": "^2.0.2" } }, "sha512-UfoeMA6fIJ8wTYFEUjelnaGI67v6+N7qXJEvQuIGa99l4xsCruSYOVSQ0uPANn4dAzm8lkYPaKLrrijLq7x23w=="],
|
||||
|
||||
"is-fullwidth-code-point": ["is-fullwidth-code-point@3.0.0", "", {}, "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg=="],
|
||||
|
||||
"jose": ["jose@6.1.0", "", {}, "sha512-TTQJyoEoKcC1lscpVDCSsVgYzUDg/0Bt3WE//WiTPK6uOCQC2KZS4MpugbMWt/zyjkopgZoXhZuCi00gLudfUA=="],
|
||||
|
||||
"lodash.camelcase": ["lodash.camelcase@4.3.0", "", {}, "sha512-TwuEnCnxbc3rAvhf/LbG7tJUDzhqXyFnv3dtzLOPgCG/hODL7WFnsbwktkD7yUV0RrreP/l1PALq/YSg6VvjlA=="],
|
||||
|
||||
"long": ["long@5.3.2", "", {}, "sha512-mNAgZ1GmyNhD7AuqnTG3/VQ26o760+ZYBPKjPvugO8+nLbYfX6TVpJPseBvopbdY+qpZ/lKUnmEc1LeZYS3QAA=="],
|
||||
|
||||
"memoirist": ["memoirist@0.4.0", "", {}, "sha512-zxTgA0mSYELa66DimuNQDvyLq36AwDlTuVRbnQtB+VuTcKWm5Qc4z3WkSpgsFWHNhexqkIooqpv4hdcqrX5Nmg=="],
|
||||
|
||||
"module-details-from-path": ["module-details-from-path@1.0.4", "", {}, "sha512-EGWKgxALGMgzvxYF1UyGTy0HXX/2vHLkw6+NvDKW2jypWbHpjQuj4UMcqQWXHERJhVGKikolT06G3bcKe4fi7w=="],
|
||||
|
||||
"ms": ["ms@2.1.3", "", {}, "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA=="],
|
||||
|
||||
"node-addon-api": ["node-addon-api@8.5.0", "", {}, "sha512-/bRZty2mXUIFY/xU5HLvveNHlswNJej+RnxBjOMkidWfwZzgTbPG1E3K5TOxRLOR+5hX7bSofy8yf1hZevMS8A=="],
|
||||
|
||||
"node-interval-tree": ["node-interval-tree@1.3.3", "", { "dependencies": { "shallowequal": "^1.0.2" } }, "sha512-K9vk96HdTK5fEipJwxSvIIqwTqr4e3HRJeJrNxBSeVMNSC/JWARRaX7etOLOuTmrRMeOI/K5TCJu3aWIwZiNTw=="],
|
||||
|
||||
"openapi-types": ["openapi-types@12.1.3", "", {}, "sha512-N4YtSYJqghVu4iek2ZUvcN/0aqH1kRDuNqzcycDxhOUpg7GdvLa2F3DgS6yBNhInhv2r/6I0Flkn7CqL8+nIcw=="],
|
||||
|
||||
"parjs": ["parjs@1.3.9", "", { "dependencies": { "char-info": "0.3.*" } }, "sha512-zmQhbzWM3M391tjwTGvNvvtoT8rRE/bBTjw6+54g8ANaPpnyekDF1d8q5tzN4kxmVud82cNj8zSd+uxSL4LE0A=="],
|
||||
|
||||
"path-parse": ["path-parse@1.0.7", "", {}, "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw=="],
|
||||
|
||||
"pathe": ["pathe@1.1.2", "", {}, "sha512-whLdWMYL2TwI08hn8/ZqAbrVemu0LNaNNJZX73O6qaIdCTfXutsLhMkjdENX0qhsQ9uIimo4/aQOmXkoon2nDQ=="],
|
||||
|
||||
"peek-readable": ["peek-readable@7.0.0", "", {}, "sha512-nri2TO5JE3/mRryik9LlHFT53cgHfRK0Lt0BAZQXku/AW3E6XLt2GaY8siWi7dvW/m1z0ecn+J+bpDa9ZN3IsQ=="],
|
||||
|
||||
"pg": ["pg@8.16.3", "", { "dependencies": { "pg-connection-string": "^2.9.1", "pg-pool": "^3.10.1", "pg-protocol": "^1.10.3", "pg-types": "2.2.0", "pgpass": "1.0.5" }, "optionalDependencies": { "pg-cloudflare": "^1.2.7" }, "peerDependencies": { "pg-native": ">=3.0.1" }, "optionalPeers": ["pg-native"] }, "sha512-enxc1h0jA/aq5oSDMvqyW3q89ra6XIIDZgCX9vkMrnz5DFTw/Ny3Li2lFQ+pt3L6MCgm/5o2o8HW9hiJji+xvw=="],
|
||||
|
||||
"pg-cloudflare": ["pg-cloudflare@1.2.7", "", {}, "sha512-YgCtzMH0ptvZJslLM1ffsY4EuGaU0cx4XSdXLRFae8bPP4dS5xL1tNB3k2o/N64cHJpwU7dxKli/nZ2lUa5fLg=="],
|
||||
|
||||
"pg-connection-string": ["pg-connection-string@2.9.1", "", {}, "sha512-nkc6NpDcvPVpZXxrreI/FOtX3XemeLl8E0qFr6F2Lrm/I8WOnaWNhIPK2Z7OHpw7gh5XJThi6j6ppgNoaT1w4w=="],
|
||||
|
||||
"pg-int8": ["pg-int8@1.0.1", "", {}, "sha512-WCtabS6t3c8SkpDBUlb1kjOs7l66xsGdKpIPZsg4wR+B3+u9UAum2odSsF9tnvxg80h4ZxLWMy4pRjOsFIqQpw=="],
|
||||
|
||||
"pg-pool": ["pg-pool@3.10.1", "", { "peerDependencies": { "pg": ">=8.0" } }, "sha512-Tu8jMlcX+9d8+QVzKIvM/uJtp07PKr82IUOYEphaWcoBhIYkoHpLXN3qO59nAI11ripznDsEzEv8nUxBVWajGg=="],
|
||||
|
||||
"pg-protocol": ["pg-protocol@1.10.0", "", {}, "sha512-IpdytjudNuLv8nhlHs/UrVBhU0e78J0oIS/0AVdTbWxSOkFUVdsHC/NrorO6nXsQNDTT1kzDSOMJubBQviX18Q=="],
|
||||
|
||||
"pg-types": ["pg-types@2.2.0", "", { "dependencies": { "pg-int8": "1.0.1", "postgres-array": "~2.0.0", "postgres-bytea": "~1.0.0", "postgres-date": "~1.0.4", "postgres-interval": "^1.1.0" } }, "sha512-qTAAlrEsl8s4OiEQY69wDvcMIdQN6wdz5ojQiOy6YRMuynxenON0O5oCpJI6lshc6scgAY8qvJ2On/p+CXY0GA=="],
|
||||
|
||||
"pgpass": ["pgpass@1.0.5", "", { "dependencies": { "split2": "^4.1.0" } }, "sha512-FdW9r/jQZhSeohs1Z3sI1yxFQNFvMcnmfuj4WBMUTxOrAyLMaTcE1aAMBiTlbMNaXvBCQuVi0R7hd8udDSP7ug=="],
|
||||
|
||||
"postgres-array": ["postgres-array@2.0.0", "", {}, "sha512-VpZrUqU5A69eQyW2c5CA1jtLecCsN2U/bD6VilrFDWq5+5UIEVO7nazS3TEcHf1zuPYO/sqGvUvW62g86RXZuA=="],
|
||||
|
||||
"postgres-bytea": ["postgres-bytea@1.0.0", "", {}, "sha512-xy3pmLuQqRBZBXDULy7KbaitYqLcmxigw14Q5sj8QBVLqEwXfeybIKVWiqAXTlcvdvb0+xkOtDbfQMOf4lST1w=="],
|
||||
|
||||
"postgres-date": ["postgres-date@1.0.7", "", {}, "sha512-suDmjLVQg78nMK2UZ454hAG+OAW+HQPZ6n++TNDUX+L0+uUlLywnoxJKDou51Zm+zTCjrCl0Nq6J9C5hP9vK/Q=="],
|
||||
|
||||
"postgres-interval": ["postgres-interval@1.2.0", "", { "dependencies": { "xtend": "^4.0.0" } }, "sha512-9ZhXKM/rw350N1ovuWHbGxnGh/SNJ4cnxHiM0rxE4VN41wsg8P8zWn9hv/buK00RP4WvlOyr/RBDiptyxVbkZQ=="],
|
||||
|
||||
"protobufjs": ["protobufjs@7.5.4", "", { "dependencies": { "@protobufjs/aspromise": "^1.1.2", "@protobufjs/base64": "^1.1.2", "@protobufjs/codegen": "^2.0.4", "@protobufjs/eventemitter": "^1.1.0", "@protobufjs/fetch": "^1.1.0", "@protobufjs/float": "^1.0.2", "@protobufjs/inquire": "^1.1.0", "@protobufjs/path": "^1.1.2", "@protobufjs/pool": "^1.1.0", "@protobufjs/utf8": "^1.1.0", "@types/node": ">=13.7.0", "long": "^5.0.0" } }, "sha512-CvexbZtbov6jW2eXAvLukXjXUW1TzFaivC46BpWc/3BpcCysb5Vffu+B3XHMm8lVEuy2Mm4XGex8hBSg1yapPg=="],
|
||||
|
||||
"require-directory": ["require-directory@2.1.1", "", {}, "sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q=="],
|
||||
|
||||
"require-in-the-middle": ["require-in-the-middle@7.5.2", "", { "dependencies": { "debug": "^4.3.5", "module-details-from-path": "^1.0.3", "resolve": "^1.22.8" } }, "sha512-gAZ+kLqBdHarXB64XpAe2VCjB7rIRv+mU8tfRWziHRJ5umKsIHN2tLLv6EtMw7WCdP19S0ERVMldNvxYCHnhSQ=="],
|
||||
|
||||
"resolve": ["resolve@1.22.11", "", { "dependencies": { "is-core-module": "^2.16.1", "path-parse": "^1.0.7", "supports-preserve-symlinks-flag": "^1.0.0" }, "bin": { "resolve": "bin/resolve" } }, "sha512-RfqAvLnMl313r7c9oclB1HhUEAezcpLjz95wFH4LVuhk9JF/r22qmVP9AMmOU4vMX7Q8pN8jwNg/CSpdFnMjTQ=="],
|
||||
|
||||
"resolve-pkg-maps": ["resolve-pkg-maps@1.0.0", "", {}, "sha512-seS2Tj26TBVOC2NIc2rOe2y2ZO7efxITtLZcGSOnHHNOQ7CkiUBfw0Iw2ck6xkIhPwLhKNLS8BO+hEpngQlqzw=="],
|
||||
|
||||
"semver": ["semver@7.7.2", "", { "bin": { "semver": "bin/semver.js" } }, "sha512-RF0Fw+rO5AMf9MAyaRXI4AV0Ulj5lMHqVxxdSgiVbixSCXoEmmX/jk0CuJw4+3SqroYO9VoUh+HcuJivvtJemA=="],
|
||||
|
||||
"shallowequal": ["shallowequal@1.1.0", "", {}, "sha512-y0m1JoUZSlPAjXVtPPW70aZWfIL/dSP7AFkRnniLCrK/8MDKog3TySTBmckD+RObVxH0v4Tox67+F14PdED2oQ=="],
|
||||
|
||||
"sharp": ["sharp@0.34.4", "", { "dependencies": { "@img/colour": "^1.0.0", "detect-libc": "^2.1.0", "semver": "^7.7.2" }, "optionalDependencies": { "@img/sharp-darwin-arm64": "0.34.4", "@img/sharp-darwin-x64": "0.34.4", "@img/sharp-libvips-darwin-arm64": "1.2.3", "@img/sharp-libvips-darwin-x64": "1.2.3", "@img/sharp-libvips-linux-arm": "1.2.3", "@img/sharp-libvips-linux-arm64": "1.2.3", "@img/sharp-libvips-linux-ppc64": "1.2.3", "@img/sharp-libvips-linux-s390x": "1.2.3", "@img/sharp-libvips-linux-x64": "1.2.3", "@img/sharp-libvips-linuxmusl-arm64": "1.2.3", "@img/sharp-libvips-linuxmusl-x64": "1.2.3", "@img/sharp-linux-arm": "0.34.4", "@img/sharp-linux-arm64": "0.34.4", "@img/sharp-linux-ppc64": "0.34.4", "@img/sharp-linux-s390x": "0.34.4", "@img/sharp-linux-x64": "0.34.4", "@img/sharp-linuxmusl-arm64": "0.34.4", "@img/sharp-linuxmusl-x64": "0.34.4", "@img/sharp-wasm32": "0.34.4", "@img/sharp-win32-arm64": "0.34.4", "@img/sharp-win32-ia32": "0.34.4", "@img/sharp-win32-x64": "0.34.4" } }, "sha512-FUH39xp3SBPnxWvd5iib1X8XY7J0K0X7d93sie9CJg2PO8/7gmg89Nve6OjItK53/MlAushNNxteBYfM6DEuoA=="],
|
||||
|
||||
"shimmer": ["shimmer@1.2.1", "", {}, "sha512-sQTKC1Re/rM6XyFM6fIAGHRPVGvyXfgzIDvzoq608vM+jeyVD0Tu1E6Np0Kc2zAIFWIj963V2800iF/9LPieQw=="],
|
||||
|
||||
"source-map": ["source-map@0.6.1", "", {}, "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g=="],
|
||||
|
||||
"source-map-support": ["source-map-support@0.5.21", "", { "dependencies": { "buffer-from": "^1.0.0", "source-map": "^0.6.0" } }, "sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w=="],
|
||||
|
||||
"split2": ["split2@4.2.0", "", {}, "sha512-UcjcJOWknrNkF6PLX83qcHM6KHgVKNkV62Y8a5uYDVv9ydGQVwAHMKqHdJje1VTWpljG0WYpCDhrCdAOYH4TWg=="],
|
||||
|
||||
"string-width": ["string-width@4.2.3", "", { "dependencies": { "emoji-regex": "^8.0.0", "is-fullwidth-code-point": "^3.0.0", "strip-ansi": "^6.0.1" } }, "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g=="],
|
||||
|
||||
"strip-ansi": ["strip-ansi@6.0.1", "", { "dependencies": { "ansi-regex": "^5.0.1" } }, "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A=="],
|
||||
|
||||
"strtok3": ["strtok3@10.2.2", "", { "dependencies": { "@tokenizer/token": "^0.3.0", "peek-readable": "^7.0.0" } }, "sha512-Xt18+h4s7Z8xyZ0tmBoRmzxcop97R4BAh+dXouUDCYn+Em+1P3qpkUfI5ueWLT8ynC5hZ+q4iPEmGG1urvQGBg=="],
|
||||
|
||||
"supports-preserve-symlinks-flag": ["supports-preserve-symlinks-flag@1.0.0", "", {}, "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w=="],
|
||||
|
||||
"token-types": ["token-types@6.0.0", "", { "dependencies": { "@tokenizer/token": "^0.3.0", "ieee754": "^1.2.1" } }, "sha512-lbDrTLVsHhOMljPscd0yitpozq7Ga2M5Cvez5AjGg8GASBjtt6iERCAJ93yommPmz62fb45oFIXHEZ3u9bfJEA=="],
|
||||
|
||||
"tslib": ["tslib@2.8.1", "", {}, "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w=="],
|
||||
|
||||
"uint8array-extras": ["uint8array-extras@1.4.0", "", {}, "sha512-ZPtzy0hu4cZjv3z5NW9gfKnNLjoz4y6uv4HlelAjDK7sY/xOkKZv9xK/WQpcsBB3jEybChz9DPC2U/+cusjJVQ=="],
|
||||
|
||||
"undici-types": ["undici-types@6.20.0", "", {}, "sha512-Ny6QZ2Nju20vw1SRHe3d9jVu6gJ+4e3+MMpqu7pqE5HT6WsTSlce++GQmK5UXS8mzV8DSYHrQH+Xrf2jVcuKNg=="],
|
||||
|
||||
"wrap-ansi": ["wrap-ansi@7.0.0", "", { "dependencies": { "ansi-styles": "^4.0.0", "string-width": "^4.1.0", "strip-ansi": "^6.0.0" } }, "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q=="],
|
||||
|
||||
"xtend": ["xtend@4.0.2", "", {}, "sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ=="],
|
||||
|
||||
"y18n": ["y18n@5.0.8", "", {}, "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA=="],
|
||||
|
||||
"yargs": ["yargs@17.7.2", "", { "dependencies": { "cliui": "^8.0.1", "escalade": "^3.1.1", "get-caller-file": "^2.0.5", "require-directory": "^2.1.1", "string-width": "^4.2.3", "y18n": "^5.0.5", "yargs-parser": "^21.1.1" } }, "sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w=="],
|
||||
|
||||
"yargs-parser": ["yargs-parser@21.1.1", "", {}, "sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw=="],
|
||||
|
||||
"zhead": ["zhead@2.2.4", "", {}, "sha512-8F0OI5dpWIA5IGG5NHUg9staDwz/ZPxZtvGVf01j7vHqSyZ0raHY+78atOVxRqb73AotX22uV1pXt3gYSstGag=="],
|
||||
|
||||
"zod": ["zod@3.24.2", "", {}, "sha512-lY7CDW43ECgW9u1TcT3IoXHflywfVqDYze4waEz812jR/bZ8FHDsl7pFQoSZTz5N+2NqRXs8GBwnAwo3ZNxqhQ=="],
|
||||
|
||||
"@esbuild-kit/core-utils/esbuild": ["esbuild@0.18.20", "", { "optionalDependencies": { "@esbuild/android-arm": "0.18.20", "@esbuild/android-arm64": "0.18.20", "@esbuild/android-x64": "0.18.20", "@esbuild/darwin-arm64": "0.18.20", "@esbuild/darwin-x64": "0.18.20", "@esbuild/freebsd-arm64": "0.18.20", "@esbuild/freebsd-x64": "0.18.20", "@esbuild/linux-arm": "0.18.20", "@esbuild/linux-arm64": "0.18.20", "@esbuild/linux-ia32": "0.18.20", "@esbuild/linux-loong64": "0.18.20", "@esbuild/linux-mips64el": "0.18.20", "@esbuild/linux-ppc64": "0.18.20", "@esbuild/linux-riscv64": "0.18.20", "@esbuild/linux-s390x": "0.18.20", "@esbuild/linux-x64": "0.18.20", "@esbuild/netbsd-x64": "0.18.20", "@esbuild/openbsd-x64": "0.18.20", "@esbuild/sunos-x64": "0.18.20", "@esbuild/win32-arm64": "0.18.20", "@esbuild/win32-ia32": "0.18.20", "@esbuild/win32-x64": "0.18.20" }, "bin": { "esbuild": "bin/esbuild" } }, "sha512-ceqxoedUrcayh7Y7ZX6NdbbDzGROiyVBgC4PriJThBKSVPWnnFHZAkfI1lJT8QFkOwH4qOS2SJkS4wvpGl8BpA=="],
|
||||
|
||||
"pg/pg-protocol": ["pg-protocol@1.10.3", "", {}, "sha512-6DIBgBQaTKDJyxnXaLiLR8wBpQQcGWuAESkRBX/t6OwA8YsqP+iVSiond2EDy6Y/dsGk8rh/jtax3js5NeV7JQ=="],
|
||||
|
||||
"@esbuild-kit/core-utils/esbuild/@esbuild/android-arm": ["@esbuild/android-arm@0.18.20", "", { "os": "android", "cpu": "arm" }, "sha512-fyi7TDI/ijKKNZTUJAQqiG5T7YjJXgnzkURqmGj13C6dCqckZBLdl4h7bkhHt/t0WP+zO9/zwroDvANaOqO5Sw=="],
|
||||
|
||||
"@esbuild-kit/core-utils/esbuild/@esbuild/android-arm64": ["@esbuild/android-arm64@0.18.20", "", { "os": "android", "cpu": "arm64" }, "sha512-Nz4rJcchGDtENV0eMKUNa6L12zz2zBDXuhj/Vjh18zGqB44Bi7MBMSXjgunJgjRhCmKOjnPuZp4Mb6OKqtMHLQ=="],
|
||||
|
||||
"@esbuild-kit/core-utils/esbuild/@esbuild/android-x64": ["@esbuild/android-x64@0.18.20", "", { "os": "android", "cpu": "x64" }, "sha512-8GDdlePJA8D6zlZYJV/jnrRAi6rOiNaCC/JclcXpB+KIuvfBN4owLtgzY2bsxnx666XjJx2kDPUmnTtR8qKQUg=="],
|
||||
|
||||
"@esbuild-kit/core-utils/esbuild/@esbuild/darwin-arm64": ["@esbuild/darwin-arm64@0.18.20", "", { "os": "darwin", "cpu": "arm64" }, "sha512-bxRHW5kHU38zS2lPTPOyuyTm+S+eobPUnTNkdJEfAddYgEcll4xkT8DB9d2008DtTbl7uJag2HuE5NZAZgnNEA=="],
|
||||
|
||||
"@esbuild-kit/core-utils/esbuild/@esbuild/darwin-x64": ["@esbuild/darwin-x64@0.18.20", "", { "os": "darwin", "cpu": "x64" }, "sha512-pc5gxlMDxzm513qPGbCbDukOdsGtKhfxD1zJKXjCCcU7ju50O7MeAZ8c4krSJcOIJGFR+qx21yMMVYwiQvyTyQ=="],
|
||||
|
||||
"@esbuild-kit/core-utils/esbuild/@esbuild/freebsd-arm64": ["@esbuild/freebsd-arm64@0.18.20", "", { "os": "freebsd", "cpu": "arm64" }, "sha512-yqDQHy4QHevpMAaxhhIwYPMv1NECwOvIpGCZkECn8w2WFHXjEwrBn3CeNIYsibZ/iZEUemj++M26W3cNR5h+Tw=="],
|
||||
|
||||
"@esbuild-kit/core-utils/esbuild/@esbuild/freebsd-x64": ["@esbuild/freebsd-x64@0.18.20", "", { "os": "freebsd", "cpu": "x64" }, "sha512-tgWRPPuQsd3RmBZwarGVHZQvtzfEBOreNuxEMKFcd5DaDn2PbBxfwLcj4+aenoh7ctXcbXmOQIn8HI6mCSw5MQ=="],
|
||||
|
||||
"@esbuild-kit/core-utils/esbuild/@esbuild/linux-arm": ["@esbuild/linux-arm@0.18.20", "", { "os": "linux", "cpu": "arm" }, "sha512-/5bHkMWnq1EgKr1V+Ybz3s1hWXok7mDFUMQ4cG10AfW3wL02PSZi5kFpYKrptDsgb2WAJIvRcDm+qIvXf/apvg=="],
|
||||
|
||||
"@esbuild-kit/core-utils/esbuild/@esbuild/linux-arm64": ["@esbuild/linux-arm64@0.18.20", "", { "os": "linux", "cpu": "arm64" }, "sha512-2YbscF+UL7SQAVIpnWvYwM+3LskyDmPhe31pE7/aoTMFKKzIc9lLbyGUpmmb8a8AixOL61sQ/mFh3jEjHYFvdA=="],
|
||||
|
||||
"@esbuild-kit/core-utils/esbuild/@esbuild/linux-ia32": ["@esbuild/linux-ia32@0.18.20", "", { "os": "linux", "cpu": "ia32" }, "sha512-P4etWwq6IsReT0E1KHU40bOnzMHoH73aXp96Fs8TIT6z9Hu8G6+0SHSw9i2isWrD2nbx2qo5yUqACgdfVGx7TA=="],
|
||||
|
||||
"@esbuild-kit/core-utils/esbuild/@esbuild/linux-loong64": ["@esbuild/linux-loong64@0.18.20", "", { "os": "linux", "cpu": "none" }, "sha512-nXW8nqBTrOpDLPgPY9uV+/1DjxoQ7DoB2N8eocyq8I9XuqJ7BiAMDMf9n1xZM9TgW0J8zrquIb/A7s3BJv7rjg=="],
|
||||
|
||||
"@esbuild-kit/core-utils/esbuild/@esbuild/linux-mips64el": ["@esbuild/linux-mips64el@0.18.20", "", { "os": "linux", "cpu": "none" }, "sha512-d5NeaXZcHp8PzYy5VnXV3VSd2D328Zb+9dEq5HE6bw6+N86JVPExrA6O68OPwobntbNJ0pzCpUFZTo3w0GyetQ=="],
|
||||
|
||||
"@esbuild-kit/core-utils/esbuild/@esbuild/linux-ppc64": ["@esbuild/linux-ppc64@0.18.20", "", { "os": "linux", "cpu": "ppc64" }, "sha512-WHPyeScRNcmANnLQkq6AfyXRFr5D6N2sKgkFo2FqguP44Nw2eyDlbTdZwd9GYk98DZG9QItIiTlFLHJHjxP3FA=="],
|
||||
|
||||
"@esbuild-kit/core-utils/esbuild/@esbuild/linux-riscv64": ["@esbuild/linux-riscv64@0.18.20", "", { "os": "linux", "cpu": "none" }, "sha512-WSxo6h5ecI5XH34KC7w5veNnKkju3zBRLEQNY7mv5mtBmrP/MjNBCAlsM2u5hDBlS3NGcTQpoBvRzqBcRtpq1A=="],
|
||||
|
||||
"@esbuild-kit/core-utils/esbuild/@esbuild/linux-s390x": ["@esbuild/linux-s390x@0.18.20", "", { "os": "linux", "cpu": "s390x" }, "sha512-+8231GMs3mAEth6Ja1iK0a1sQ3ohfcpzpRLH8uuc5/KVDFneH6jtAJLFGafpzpMRO6DzJ6AvXKze9LfFMrIHVQ=="],
|
||||
|
||||
"@esbuild-kit/core-utils/esbuild/@esbuild/linux-x64": ["@esbuild/linux-x64@0.18.20", "", { "os": "linux", "cpu": "x64" }, "sha512-UYqiqemphJcNsFEskc73jQ7B9jgwjWrSayxawS6UVFZGWrAAtkzjxSqnoclCXxWtfwLdzU+vTpcNYhpn43uP1w=="],
|
||||
|
||||
"@esbuild-kit/core-utils/esbuild/@esbuild/netbsd-x64": ["@esbuild/netbsd-x64@0.18.20", "", { "os": "none", "cpu": "x64" }, "sha512-iO1c++VP6xUBUmltHZoMtCUdPlnPGdBom6IrO4gyKPFFVBKioIImVooR5I83nTew5UOYrk3gIJhbZh8X44y06A=="],
|
||||
|
||||
"@esbuild-kit/core-utils/esbuild/@esbuild/openbsd-x64": ["@esbuild/openbsd-x64@0.18.20", "", { "os": "openbsd", "cpu": "x64" }, "sha512-e5e4YSsuQfX4cxcygw/UCPIEP6wbIL+se3sxPdCiMbFLBWu0eiZOJ7WoD+ptCLrmjZBK1Wk7I6D/I3NglUGOxg=="],
|
||||
|
||||
"@esbuild-kit/core-utils/esbuild/@esbuild/sunos-x64": ["@esbuild/sunos-x64@0.18.20", "", { "os": "sunos", "cpu": "x64" }, "sha512-kDbFRFp0YpTQVVrqUd5FTYmWo45zGaXe0X8E1G/LKFC0v8x0vWrhOWSLITcCn63lmZIxfOMXtCfti/RxN/0wnQ=="],
|
||||
|
||||
"@esbuild-kit/core-utils/esbuild/@esbuild/win32-arm64": ["@esbuild/win32-arm64@0.18.20", "", { "os": "win32", "cpu": "arm64" }, "sha512-ddYFR6ItYgoaq4v4JmQQaAI5s7npztfV4Ag6NrhiaW0RrnOXqBkgwZLofVTlq1daVTQNhtI5oieTvkRPfZrePg=="],
|
||||
|
||||
"@esbuild-kit/core-utils/esbuild/@esbuild/win32-ia32": ["@esbuild/win32-ia32@0.18.20", "", { "os": "win32", "cpu": "ia32" }, "sha512-Wv7QBi3ID/rROT08SABTS7eV4hX26sVduqDOTe1MvGMjNd3EjOz4b7zeexIR62GTIEKrfJXKL9LFxTYgkyeu7g=="],
|
||||
|
||||
"@esbuild-kit/core-utils/esbuild/@esbuild/win32-x64": ["@esbuild/win32-x64@0.18.20", "", { "os": "win32", "cpu": "x64" }, "sha512-kTdfRcSiDfQca/y9QIkng02avJ+NCaQvrMejlsB3RRv5sE9rRoeBPISaZpKxHELzRxZyLvNts1P27W3wV+8geQ=="],
|
||||
}
|
||||
}
|
||||
2
api/bunfig.toml
Normal file
2
api/bunfig.toml
Normal file
@@ -0,0 +1,2 @@
|
||||
[test]
|
||||
preload = ["./tests/setup.ts"]
|
||||
23
api/devspace.yaml
Normal file
23
api/devspace.yaml
Normal file
@@ -0,0 +1,23 @@
|
||||
version: v2beta1
|
||||
name: api
|
||||
dev:
|
||||
api:
|
||||
imageSelector: ghcr.io/zoriya/kyoo_api
|
||||
devImage: docker.io/oven/bun:latest
|
||||
workingDir: /app
|
||||
sync:
|
||||
- path: .:/app
|
||||
excludePaths:
|
||||
- node_modules
|
||||
startContainer: true
|
||||
onUpload:
|
||||
exec:
|
||||
- command: bun install --frozen-lockfile
|
||||
onChange:
|
||||
- "./bun.lock"
|
||||
command:
|
||||
- bash
|
||||
- -c
|
||||
- "bun install && bun dev"
|
||||
ports:
|
||||
- port: "3567"
|
||||
14
api/drizzle.config.ts
Normal file
14
api/drizzle.config.ts
Normal file
@@ -0,0 +1,14 @@
|
||||
import { defineConfig } from "drizzle-kit";
|
||||
|
||||
export default defineConfig({
|
||||
out: "./drizzle",
|
||||
schema: "./src/db/schema",
|
||||
dialect: "postgresql",
|
||||
casing: "snake_case",
|
||||
dbCredentials: {
|
||||
url: process.env.DATABASE_URL!,
|
||||
},
|
||||
migrations: {
|
||||
schema: "kyoo",
|
||||
},
|
||||
});
|
||||
102
api/drizzle/0000_init.sql
Normal file
102
api/drizzle/0000_init.sql
Normal file
@@ -0,0 +1,102 @@
|
||||
CREATE TYPE "kyoo"."entry_type" AS ENUM('unknown', 'episode', 'movie', 'special', 'extra');--> statement-breakpoint
|
||||
CREATE TYPE "kyoo"."genres" AS ENUM('action', 'adventure', 'animation', 'comedy', 'crime', 'documentary', 'drama', 'family', 'fantasy', 'history', 'horror', 'music', 'mystery', 'romance', 'science-fiction', 'thriller', 'war', 'western', 'kids', 'reality', 'politics', 'soap', 'talk');--> statement-breakpoint
|
||||
CREATE TYPE "kyoo"."show_kind" AS ENUM('serie', 'movie');--> statement-breakpoint
|
||||
CREATE TYPE "kyoo"."show_status" AS ENUM('unknown', 'finished', 'airing', 'planned');--> statement-breakpoint
|
||||
CREATE TABLE IF NOT EXISTS "kyoo"."entries" (
|
||||
"pk" integer PRIMARY KEY GENERATED ALWAYS AS IDENTITY (sequence name "kyoo"."entries_pk_seq" INCREMENT BY 1 MINVALUE 1 MAXVALUE 2147483647 START WITH 1 CACHE 1),
|
||||
"id" uuid DEFAULT gen_random_uuid() NOT NULL,
|
||||
"slug" varchar(255) NOT NULL,
|
||||
"show_pk" integer,
|
||||
"order" integer NOT NULL,
|
||||
"season_number" integer,
|
||||
"episode_number" integer,
|
||||
"type" "kyoo"."entry_type" NOT NULL,
|
||||
"air_date" date,
|
||||
"runtime" integer,
|
||||
"thumbnails" jsonb,
|
||||
"external_id" jsonb DEFAULT '{}'::jsonb NOT NULL,
|
||||
"created_at" timestamp with time zone DEFAULT now(),
|
||||
"next_refresh" timestamp with time zone,
|
||||
CONSTRAINT "entries_id_unique" UNIQUE("id"),
|
||||
CONSTRAINT "entries_slug_unique" UNIQUE("slug"),
|
||||
CONSTRAINT "entries_showPk_seasonNumber_episodeNumber_unique" UNIQUE("show_pk","season_number","episode_number"),
|
||||
CONSTRAINT "order_positive" CHECK ("entries"."order" >= 0)
|
||||
);
|
||||
--> statement-breakpoint
|
||||
CREATE TABLE IF NOT EXISTS "kyoo"."entries_translation" (
|
||||
"pk" integer NOT NULL,
|
||||
"language" varchar(255) NOT NULL,
|
||||
"name" text,
|
||||
"description" text,
|
||||
CONSTRAINT "entries_translation_pk_language_pk" PRIMARY KEY("pk","language")
|
||||
);
|
||||
--> statement-breakpoint
|
||||
CREATE TABLE IF NOT EXISTS "kyoo"."show_translations" (
|
||||
"pk" integer NOT NULL,
|
||||
"language" varchar(255) NOT NULL,
|
||||
"name" text NOT NULL,
|
||||
"description" text,
|
||||
"tagline" text,
|
||||
"aliases" text[] NOT NULL,
|
||||
"tags" text[] NOT NULL,
|
||||
"trailer_url" text,
|
||||
"poster" jsonb,
|
||||
"thumbnail" jsonb,
|
||||
"banner" jsonb,
|
||||
"logo" jsonb,
|
||||
CONSTRAINT "show_translations_pk_language_pk" PRIMARY KEY("pk","language")
|
||||
);
|
||||
--> statement-breakpoint
|
||||
CREATE TABLE IF NOT EXISTS "kyoo"."shows" (
|
||||
"pk" integer PRIMARY KEY GENERATED ALWAYS AS IDENTITY (sequence name "kyoo"."shows_pk_seq" INCREMENT BY 1 MINVALUE 1 MAXVALUE 2147483647 START WITH 1 CACHE 1),
|
||||
"id" uuid DEFAULT gen_random_uuid() NOT NULL,
|
||||
"slug" varchar(255) NOT NULL,
|
||||
"kind" "kyoo"."show_kind" NOT NULL,
|
||||
"genres" "kyoo"."genres"[] NOT NULL,
|
||||
"rating" smallint,
|
||||
"runtime" integer,
|
||||
"status" "kyoo"."show_status" NOT NULL,
|
||||
"start_air" date,
|
||||
"end_air" date,
|
||||
"original_language" varchar(255),
|
||||
"external_id" jsonb DEFAULT '{}'::jsonb NOT NULL,
|
||||
"created_at" timestamp with time zone DEFAULT now() NOT NULL,
|
||||
"next_refresh" timestamp with time zone NOT NULL,
|
||||
CONSTRAINT "shows_id_unique" UNIQUE("id"),
|
||||
CONSTRAINT "shows_slug_unique" UNIQUE("slug"),
|
||||
CONSTRAINT "rating_valid" CHECK ("shows"."rating" between 0 and 100),
|
||||
CONSTRAINT "runtime_valid" CHECK ("shows"."runtime" >= 0)
|
||||
);
|
||||
--> statement-breakpoint
|
||||
CREATE TABLE IF NOT EXISTS "kyoo"."videos" (
|
||||
"pk" integer PRIMARY KEY GENERATED ALWAYS AS IDENTITY (sequence name "kyoo"."videos_pk_seq" INCREMENT BY 1 MINVALUE 1 MAXVALUE 2147483647 START WITH 1 CACHE 1),
|
||||
"id" uuid DEFAULT gen_random_uuid() NOT NULL,
|
||||
"path" text NOT NULL,
|
||||
"rendering" integer,
|
||||
"part" integer,
|
||||
"version" integer,
|
||||
"created_at" timestamp with time zone DEFAULT now() NOT NULL,
|
||||
CONSTRAINT "videos_id_unique" UNIQUE("id"),
|
||||
CONSTRAINT "videos_path_unique" UNIQUE("path"),
|
||||
CONSTRAINT "rendering_pos" CHECK ("videos"."rendering" >= 0),
|
||||
CONSTRAINT "part_pos" CHECK ("videos"."part" >= 0),
|
||||
CONSTRAINT "version_pos" CHECK ("videos"."version" >= 0)
|
||||
);
|
||||
--> statement-breakpoint
|
||||
DO $$ BEGIN
|
||||
ALTER TABLE "kyoo"."entries" ADD CONSTRAINT "entries_show_pk_shows_pk_fk" FOREIGN KEY ("show_pk") REFERENCES "kyoo"."shows"("pk") ON DELETE cascade ON UPDATE no action;
|
||||
EXCEPTION
|
||||
WHEN duplicate_object THEN null;
|
||||
END $$;
|
||||
--> statement-breakpoint
|
||||
DO $$ BEGIN
|
||||
ALTER TABLE "kyoo"."entries_translation" ADD CONSTRAINT "entries_translation_pk_entries_pk_fk" FOREIGN KEY ("pk") REFERENCES "kyoo"."entries"("pk") ON DELETE cascade ON UPDATE no action;
|
||||
EXCEPTION
|
||||
WHEN duplicate_object THEN null;
|
||||
END $$;
|
||||
--> statement-breakpoint
|
||||
DO $$ BEGIN
|
||||
ALTER TABLE "kyoo"."show_translations" ADD CONSTRAINT "show_translations_pk_shows_pk_fk" FOREIGN KEY ("pk") REFERENCES "kyoo"."shows"("pk") ON DELETE cascade ON UPDATE no action;
|
||||
EXCEPTION
|
||||
WHEN duplicate_object THEN null;
|
||||
END $$;
|
||||
7
api/drizzle/0001_video.sql
Normal file
7
api/drizzle/0001_video.sql
Normal file
@@ -0,0 +1,7 @@
|
||||
ALTER TABLE "kyoo"."videos" DROP CONSTRAINT "rendering_pos";--> statement-breakpoint
|
||||
ALTER TABLE "kyoo"."videos" ALTER COLUMN "rendering" SET DATA TYPE text;--> statement-breakpoint
|
||||
ALTER TABLE "kyoo"."videos" ALTER COLUMN "rendering" SET NOT NULL;--> statement-breakpoint
|
||||
ALTER TABLE "kyoo"."videos" ALTER COLUMN "version" SET DEFAULT 1;--> statement-breakpoint
|
||||
ALTER TABLE "kyoo"."videos" ALTER COLUMN "version" SET NOT NULL;--> statement-breakpoint
|
||||
ALTER TABLE "kyoo"."videos" ADD COLUMN "slug" varchar(255) NOT NULL;--> statement-breakpoint
|
||||
ALTER TABLE "kyoo"."videos" ADD CONSTRAINT "videos_slug_unique" UNIQUE("slug");
|
||||
40
api/drizzle/0002_seasons.sql
Normal file
40
api/drizzle/0002_seasons.sql
Normal file
@@ -0,0 +1,40 @@
|
||||
CREATE TABLE IF NOT EXISTS "kyoo"."season_translation" (
|
||||
"pk" integer NOT NULL,
|
||||
"language" varchar(255) NOT NULL,
|
||||
"name" text,
|
||||
"description" text,
|
||||
"poster" jsonb,
|
||||
"thumbnail" jsonb,
|
||||
"logo" jsonb,
|
||||
"banner" jsonb,
|
||||
CONSTRAINT "season_translation_pk_language_pk" PRIMARY KEY("pk","language")
|
||||
);
|
||||
--> statement-breakpoint
|
||||
CREATE TABLE IF NOT EXISTS "kyoo"."seasons" (
|
||||
"pk" integer PRIMARY KEY GENERATED ALWAYS AS IDENTITY (sequence name "kyoo"."seasons_pk_seq" INCREMENT BY 1 MINVALUE 1 MAXVALUE 2147483647 START WITH 1 CACHE 1),
|
||||
"id" uuid DEFAULT gen_random_uuid() NOT NULL,
|
||||
"slug" varchar(255) NOT NULL,
|
||||
"show_pk" integer,
|
||||
"season_number" integer NOT NULL,
|
||||
"start_air" date,
|
||||
"end_air" date,
|
||||
"external_id" jsonb DEFAULT '{}'::jsonb NOT NULL,
|
||||
"created_at" timestamp with time zone DEFAULT now(),
|
||||
"next_refresh" timestamp with time zone,
|
||||
CONSTRAINT "seasons_id_unique" UNIQUE("id"),
|
||||
CONSTRAINT "seasons_slug_unique" UNIQUE("slug"),
|
||||
CONSTRAINT "seasons_showPk_seasonNumber_unique" UNIQUE("show_pk","season_number")
|
||||
);
|
||||
--> statement-breakpoint
|
||||
ALTER TABLE "kyoo"."entries" ALTER COLUMN "order" DROP NOT NULL;--> statement-breakpoint
|
||||
DO $$ BEGIN
|
||||
ALTER TABLE "kyoo"."season_translation" ADD CONSTRAINT "season_translation_pk_seasons_pk_fk" FOREIGN KEY ("pk") REFERENCES "kyoo"."seasons"("pk") ON DELETE cascade ON UPDATE no action;
|
||||
EXCEPTION
|
||||
WHEN duplicate_object THEN null;
|
||||
END $$;
|
||||
--> statement-breakpoint
|
||||
DO $$ BEGIN
|
||||
ALTER TABLE "kyoo"."seasons" ADD CONSTRAINT "seasons_show_pk_shows_pk_fk" FOREIGN KEY ("show_pk") REFERENCES "kyoo"."shows"("pk") ON DELETE cascade ON UPDATE no action;
|
||||
EXCEPTION
|
||||
WHEN duplicate_object THEN null;
|
||||
END $$;
|
||||
3
api/drizzle/0003_order.sql
Normal file
3
api/drizzle/0003_order.sql
Normal file
@@ -0,0 +1,3 @@
|
||||
ALTER TABLE "kyoo"."entries" ALTER COLUMN "order" SET DATA TYPE real;--> statement-breakpoint
|
||||
ALTER TABLE "kyoo"."entries_translation" ADD COLUMN "tagline" text;--> statement-breakpoint
|
||||
ALTER TABLE "kyoo"."season_translation" DROP COLUMN IF EXISTS "logo";
|
||||
56
api/drizzle/0004_jointures.sql
Normal file
56
api/drizzle/0004_jointures.sql
Normal file
@@ -0,0 +1,56 @@
|
||||
CREATE TABLE IF NOT EXISTS "kyoo"."entry_video_jointure" (
|
||||
"entry" integer NOT NULL,
|
||||
"video" integer NOT NULL,
|
||||
"slug" varchar(255) NOT NULL,
|
||||
CONSTRAINT "entry_video_jointure_entry_video_pk" PRIMARY KEY("entry","video"),
|
||||
CONSTRAINT "entry_video_jointure_slug_unique" UNIQUE("slug")
|
||||
);
|
||||
--> statement-breakpoint
|
||||
ALTER TABLE "kyoo"."entries_translation" RENAME TO "entry_translations";--> statement-breakpoint
|
||||
ALTER TABLE "kyoo"."season_translation" RENAME TO "season_translations";--> statement-breakpoint
|
||||
ALTER TABLE "kyoo"."videos" DROP CONSTRAINT "videos_slug_unique";--> statement-breakpoint
|
||||
ALTER TABLE "kyoo"."entries" DROP CONSTRAINT "order_positive";--> statement-breakpoint
|
||||
ALTER TABLE "kyoo"."shows" DROP CONSTRAINT "rating_valid";--> statement-breakpoint
|
||||
ALTER TABLE "kyoo"."shows" DROP CONSTRAINT "runtime_valid";--> statement-breakpoint
|
||||
ALTER TABLE "kyoo"."videos" DROP CONSTRAINT "part_pos";--> statement-breakpoint
|
||||
ALTER TABLE "kyoo"."videos" DROP CONSTRAINT "version_pos";--> statement-breakpoint
|
||||
ALTER TABLE "kyoo"."entry_translations" DROP CONSTRAINT "entries_translation_pk_entries_pk_fk";
|
||||
--> statement-breakpoint
|
||||
ALTER TABLE "kyoo"."season_translations" DROP CONSTRAINT "season_translation_pk_seasons_pk_fk";
|
||||
--> statement-breakpoint
|
||||
ALTER TABLE "kyoo"."entry_translations" DROP CONSTRAINT "entries_translation_pk_language_pk";--> statement-breakpoint
|
||||
ALTER TABLE "kyoo"."season_translations" DROP CONSTRAINT "season_translation_pk_language_pk";--> statement-breakpoint
|
||||
ALTER TABLE "kyoo"."entry_translations" ADD CONSTRAINT "entry_translations_pk_language_pk" PRIMARY KEY("pk","language");--> statement-breakpoint
|
||||
ALTER TABLE "kyoo"."season_translations" ADD CONSTRAINT "season_translations_pk_language_pk" PRIMARY KEY("pk","language");--> statement-breakpoint
|
||||
ALTER TABLE "kyoo"."entry_translations" ADD COLUMN "poster" jsonb;--> statement-breakpoint
|
||||
ALTER TABLE "kyoo"."videos" ADD COLUMN "guess" jsonb DEFAULT '{}'::jsonb NOT NULL;--> statement-breakpoint
|
||||
DO $$ BEGIN
|
||||
ALTER TABLE "kyoo"."entry_video_jointure" ADD CONSTRAINT "entry_video_jointure_entry_entries_pk_fk" FOREIGN KEY ("entry") REFERENCES "kyoo"."entries"("pk") ON DELETE cascade ON UPDATE no action;
|
||||
EXCEPTION
|
||||
WHEN duplicate_object THEN null;
|
||||
END $$;
|
||||
--> statement-breakpoint
|
||||
DO $$ BEGIN
|
||||
ALTER TABLE "kyoo"."entry_video_jointure" ADD CONSTRAINT "entry_video_jointure_video_videos_pk_fk" FOREIGN KEY ("video") REFERENCES "kyoo"."videos"("pk") ON DELETE cascade ON UPDATE no action;
|
||||
EXCEPTION
|
||||
WHEN duplicate_object THEN null;
|
||||
END $$;
|
||||
--> statement-breakpoint
|
||||
DO $$ BEGIN
|
||||
ALTER TABLE "kyoo"."entry_translations" ADD CONSTRAINT "entry_translations_pk_entries_pk_fk" FOREIGN KEY ("pk") REFERENCES "kyoo"."entries"("pk") ON DELETE cascade ON UPDATE no action;
|
||||
EXCEPTION
|
||||
WHEN duplicate_object THEN null;
|
||||
END $$;
|
||||
--> statement-breakpoint
|
||||
DO $$ BEGIN
|
||||
ALTER TABLE "kyoo"."season_translations" ADD CONSTRAINT "season_translations_pk_seasons_pk_fk" FOREIGN KEY ("pk") REFERENCES "kyoo"."seasons"("pk") ON DELETE cascade ON UPDATE no action;
|
||||
EXCEPTION
|
||||
WHEN duplicate_object THEN null;
|
||||
END $$;
|
||||
--> statement-breakpoint
|
||||
ALTER TABLE "kyoo"."videos" DROP COLUMN IF EXISTS "slug";--> statement-breakpoint
|
||||
ALTER TABLE "kyoo"."entries" ADD CONSTRAINT "order_positive" CHECK ("kyoo"."entries"."order" >= 0);--> statement-breakpoint
|
||||
ALTER TABLE "kyoo"."shows" ADD CONSTRAINT "rating_valid" CHECK ("kyoo"."shows"."rating" between 0 and 100);--> statement-breakpoint
|
||||
ALTER TABLE "kyoo"."shows" ADD CONSTRAINT "runtime_valid" CHECK ("kyoo"."shows"."runtime" >= 0);--> statement-breakpoint
|
||||
ALTER TABLE "kyoo"."videos" ADD CONSTRAINT "part_pos" CHECK ("kyoo"."videos"."part" >= 0);--> statement-breakpoint
|
||||
ALTER TABLE "kyoo"."videos" ADD CONSTRAINT "version_pos" CHECK ("kyoo"."videos"."version" >= 0);
|
||||
5
api/drizzle/0005_trigram.sql
Normal file
5
api/drizzle/0005_trigram.sql
Normal file
@@ -0,0 +1,5 @@
|
||||
CREATE INDEX "name_trgm" ON "kyoo"."show_translations" USING gin ("name" gin_trgm_ops);--> statement-breakpoint
|
||||
CREATE INDEX "tags" ON "kyoo"."show_translations" USING btree ("tags");--> statement-breakpoint
|
||||
CREATE INDEX "kind" ON "kyoo"."shows" USING hash ("kind");--> statement-breakpoint
|
||||
CREATE INDEX "rating" ON "kyoo"."shows" USING btree ("rating");--> statement-breakpoint
|
||||
CREATE INDEX "startAir" ON "kyoo"."shows" USING btree ("start_air");
|
||||
5
api/drizzle/0006_seasons.sql
Normal file
5
api/drizzle/0006_seasons.sql
Normal file
@@ -0,0 +1,5 @@
|
||||
ALTER TABLE "kyoo"."entries" ALTER COLUMN "created_at" SET NOT NULL;--> statement-breakpoint
|
||||
ALTER TABLE "kyoo"."entries" ALTER COLUMN "next_refresh" SET NOT NULL;--> statement-breakpoint
|
||||
ALTER TABLE "kyoo"."seasons" ALTER COLUMN "created_at" SET NOT NULL;--> statement-breakpoint
|
||||
ALTER TABLE "kyoo"."seasons" ALTER COLUMN "next_refresh" SET NOT NULL;--> statement-breakpoint
|
||||
CREATE INDEX "show_fk" ON "kyoo"."seasons" USING hash ("show_pk");
|
||||
3
api/drizzle/0007_entries.sql
Normal file
3
api/drizzle/0007_entries.sql
Normal file
@@ -0,0 +1,3 @@
|
||||
ALTER TABLE "kyoo"."entries" RENAME COLUMN "type" TO "kind";--> statement-breakpoint
|
||||
ALTER TABLE "kyoo"."entries" ALTER COLUMN "show_pk" SET NOT NULL;--> statement-breakpoint
|
||||
ALTER TABLE "kyoo"."entries" ADD COLUMN "extra_kind" text;
|
||||
12
api/drizzle/0008_entries.sql
Normal file
12
api/drizzle/0008_entries.sql
Normal file
@@ -0,0 +1,12 @@
|
||||
ALTER TABLE "kyoo"."entry_video_jointure" RENAME TO "entry_video_join";--> statement-breakpoint
|
||||
ALTER TABLE "kyoo"."entries" RENAME COLUMN "thumbnails" TO "thumbnail";--> statement-breakpoint
|
||||
ALTER TABLE "kyoo"."entry_video_join" DROP CONSTRAINT "entry_video_jointure_slug_unique";--> statement-breakpoint
|
||||
ALTER TABLE "kyoo"."entry_video_join" DROP CONSTRAINT "entry_video_jointure_entry_entries_pk_fk";
|
||||
--> statement-breakpoint
|
||||
ALTER TABLE "kyoo"."entry_video_join" DROP CONSTRAINT "entry_video_jointure_video_videos_pk_fk";
|
||||
--> statement-breakpoint
|
||||
ALTER TABLE "kyoo"."entry_video_join" DROP CONSTRAINT "entry_video_jointure_entry_video_pk";--> statement-breakpoint
|
||||
ALTER TABLE "kyoo"."entry_video_join" ADD CONSTRAINT "entry_video_join_entry_video_pk" PRIMARY KEY("entry","video");--> statement-breakpoint
|
||||
ALTER TABLE "kyoo"."entry_video_join" ADD CONSTRAINT "entry_video_join_entry_entries_pk_fk" FOREIGN KEY ("entry") REFERENCES "kyoo"."entries"("pk") ON DELETE cascade ON UPDATE no action;--> statement-breakpoint
|
||||
ALTER TABLE "kyoo"."entry_video_join" ADD CONSTRAINT "entry_video_join_video_videos_pk_fk" FOREIGN KEY ("video") REFERENCES "kyoo"."videos"("pk") ON DELETE cascade ON UPDATE no action;--> statement-breakpoint
|
||||
ALTER TABLE "kyoo"."entry_video_join" ADD CONSTRAINT "entry_video_join_slug_unique" UNIQUE("slug");
|
||||
3
api/drizzle/0009_collections.sql
Normal file
3
api/drizzle/0009_collections.sql
Normal file
@@ -0,0 +1,3 @@
|
||||
ALTER TYPE "kyoo"."show_kind" ADD VALUE 'collection';--> statement-breakpoint
|
||||
ALTER TABLE "kyoo"."shows" ADD COLUMN "collection_pk" integer;--> statement-breakpoint
|
||||
ALTER TABLE "kyoo"."shows" ADD CONSTRAINT "shows_collection_pk_shows_pk_fk" FOREIGN KEY ("collection_pk") REFERENCES "kyoo"."shows"("pk") ON DELETE set null ON UPDATE no action;
|
||||
38
api/drizzle/0010_studios.sql
Normal file
38
api/drizzle/0010_studios.sql
Normal file
@@ -0,0 +1,38 @@
|
||||
CREATE TABLE "kyoo"."show_studio_join" (
|
||||
"show" integer NOT NULL,
|
||||
"studio" integer NOT NULL,
|
||||
CONSTRAINT "show_studio_join_show_studio_pk" PRIMARY KEY("show","studio")
|
||||
);
|
||||
--> statement-breakpoint
|
||||
CREATE TABLE "kyoo"."studio_translations" (
|
||||
"pk" integer NOT NULL,
|
||||
"language" varchar(255) NOT NULL,
|
||||
"name" text NOT NULL,
|
||||
"logo" jsonb,
|
||||
CONSTRAINT "studio_translations_pk_language_pk" PRIMARY KEY("pk","language")
|
||||
);
|
||||
--> statement-breakpoint
|
||||
CREATE TABLE "kyoo"."studios" (
|
||||
"pk" integer PRIMARY KEY GENERATED ALWAYS AS IDENTITY (sequence name "kyoo"."studios_pk_seq" INCREMENT BY 1 MINVALUE 1 MAXVALUE 2147483647 START WITH 1 CACHE 1),
|
||||
"id" uuid DEFAULT gen_random_uuid() NOT NULL,
|
||||
"slug" varchar(255) NOT NULL,
|
||||
"external_id" jsonb DEFAULT '{}'::jsonb NOT NULL,
|
||||
"created_at" timestamp with time zone DEFAULT now() NOT NULL,
|
||||
"updated_at" timestamp with time zone NOT NULL,
|
||||
CONSTRAINT "studios_id_unique" UNIQUE("id"),
|
||||
CONSTRAINT "studios_slug_unique" UNIQUE("slug")
|
||||
);
|
||||
--> statement-breakpoint
|
||||
ALTER TABLE "kyoo"."entries" ADD COLUMN "updated_at" timestamp with time zone NOT NULL;--> statement-breakpoint
|
||||
ALTER TABLE "kyoo"."seasons" ADD COLUMN "updated_at" timestamp with time zone NOT NULL;--> statement-breakpoint
|
||||
ALTER TABLE "kyoo"."shows" ADD COLUMN "updated_at" timestamp with time zone NOT NULL;--> statement-breakpoint
|
||||
ALTER TABLE "kyoo"."videos" ADD COLUMN "updated_at" timestamp with time zone NOT NULL;--> statement-breakpoint
|
||||
ALTER TABLE "kyoo"."show_studio_join" ADD CONSTRAINT "show_studio_join_show_shows_pk_fk" FOREIGN KEY ("show") REFERENCES "kyoo"."shows"("pk") ON DELETE cascade ON UPDATE no action;--> statement-breakpoint
|
||||
ALTER TABLE "kyoo"."show_studio_join" ADD CONSTRAINT "show_studio_join_studio_studios_pk_fk" FOREIGN KEY ("studio") REFERENCES "kyoo"."studios"("pk") ON DELETE cascade ON UPDATE no action;--> statement-breakpoint
|
||||
ALTER TABLE "kyoo"."studio_translations" ADD CONSTRAINT "studio_translations_pk_studios_pk_fk" FOREIGN KEY ("pk") REFERENCES "kyoo"."studios"("pk") ON DELETE cascade ON UPDATE no action;--> statement-breakpoint
|
||||
CREATE INDEX "studio_name_trgm" ON "kyoo"."studio_translations" USING gin ("name" gin_trgm_ops);--> statement-breakpoint
|
||||
CREATE INDEX "entry_kind" ON "kyoo"."entries" USING hash ("kind");--> statement-breakpoint
|
||||
CREATE INDEX "entry_order" ON "kyoo"."entries" USING btree ("order");--> statement-breakpoint
|
||||
CREATE INDEX "entry_name_trgm" ON "kyoo"."entry_translations" USING gin ("name" gin_trgm_ops);--> statement-breakpoint
|
||||
CREATE INDEX "season_name_trgm" ON "kyoo"."season_translations" USING gin ("name" gin_trgm_ops);--> statement-breakpoint
|
||||
CREATE INDEX "season_nbr" ON "kyoo"."seasons" USING btree ("season_number");
|
||||
20
api/drizzle/0011_join_rename.sql
Normal file
20
api/drizzle/0011_join_rename.sql
Normal file
@@ -0,0 +1,20 @@
|
||||
ALTER TABLE "kyoo"."show_studio_join" RENAME COLUMN "show" TO "show_pk";--> statement-breakpoint
|
||||
ALTER TABLE "kyoo"."show_studio_join" RENAME COLUMN "studio" TO "studio_pk";--> statement-breakpoint
|
||||
ALTER TABLE "kyoo"."entry_video_join" RENAME COLUMN "entry" TO "entry_pk";--> statement-breakpoint
|
||||
ALTER TABLE "kyoo"."entry_video_join" RENAME COLUMN "video" TO "video_pk";--> statement-breakpoint
|
||||
ALTER TABLE "kyoo"."show_studio_join" DROP CONSTRAINT "show_studio_join_show_shows_pk_fk";
|
||||
--> statement-breakpoint
|
||||
ALTER TABLE "kyoo"."show_studio_join" DROP CONSTRAINT "show_studio_join_studio_studios_pk_fk";
|
||||
--> statement-breakpoint
|
||||
ALTER TABLE "kyoo"."entry_video_join" DROP CONSTRAINT "entry_video_join_entry_entries_pk_fk";
|
||||
--> statement-breakpoint
|
||||
ALTER TABLE "kyoo"."entry_video_join" DROP CONSTRAINT "entry_video_join_video_videos_pk_fk";
|
||||
--> statement-breakpoint
|
||||
ALTER TABLE "kyoo"."show_studio_join" DROP CONSTRAINT "show_studio_join_show_studio_pk";--> statement-breakpoint
|
||||
ALTER TABLE "kyoo"."entry_video_join" DROP CONSTRAINT "entry_video_join_entry_video_pk";--> statement-breakpoint
|
||||
ALTER TABLE "kyoo"."show_studio_join" ADD CONSTRAINT "show_studio_join_show_pk_studio_pk_pk" PRIMARY KEY("show_pk","studio_pk");--> statement-breakpoint
|
||||
ALTER TABLE "kyoo"."entry_video_join" ADD CONSTRAINT "entry_video_join_entry_pk_video_pk_pk" PRIMARY KEY("entry_pk","video_pk");--> statement-breakpoint
|
||||
ALTER TABLE "kyoo"."show_studio_join" ADD CONSTRAINT "show_studio_join_show_pk_shows_pk_fk" FOREIGN KEY ("show_pk") REFERENCES "kyoo"."shows"("pk") ON DELETE cascade ON UPDATE no action;--> statement-breakpoint
|
||||
ALTER TABLE "kyoo"."show_studio_join" ADD CONSTRAINT "show_studio_join_studio_pk_studios_pk_fk" FOREIGN KEY ("studio_pk") REFERENCES "kyoo"."studios"("pk") ON DELETE cascade ON UPDATE no action;--> statement-breakpoint
|
||||
ALTER TABLE "kyoo"."entry_video_join" ADD CONSTRAINT "entry_video_join_entry_pk_entries_pk_fk" FOREIGN KEY ("entry_pk") REFERENCES "kyoo"."entries"("pk") ON DELETE cascade ON UPDATE no action;--> statement-breakpoint
|
||||
ALTER TABLE "kyoo"."entry_video_join" ADD CONSTRAINT "entry_video_join_video_pk_videos_pk_fk" FOREIGN KEY ("video_pk") REFERENCES "kyoo"."videos"("pk") ON DELETE cascade ON UPDATE no action;
|
||||
2
api/drizzle/0012_available_count.sql
Normal file
2
api/drizzle/0012_available_count.sql
Normal file
@@ -0,0 +1,2 @@
|
||||
ALTER TABLE "kyoo"."shows" ADD COLUMN "entries_count" integer NOT NULL;--> statement-breakpoint
|
||||
ALTER TABLE "kyoo"."shows" ADD COLUMN "available_count" integer DEFAULT 0 NOT NULL;
|
||||
3
api/drizzle/0013_original.sql
Normal file
3
api/drizzle/0013_original.sql
Normal file
@@ -0,0 +1,3 @@
|
||||
ALTER TABLE "kyoo"."videos" ALTER COLUMN "guess" DROP DEFAULT;--> statement-breakpoint
|
||||
ALTER TABLE "kyoo"."shows" ADD COLUMN "original" jsonb NOT NULL;--> statement-breakpoint
|
||||
ALTER TABLE "kyoo"."shows" DROP COLUMN "original_language";
|
||||
28
api/drizzle/0014_staff.sql
Normal file
28
api/drizzle/0014_staff.sql
Normal file
@@ -0,0 +1,28 @@
|
||||
CREATE TYPE "kyoo"."role_kind" AS ENUM('actor', 'director', 'writter', 'producer', 'music', 'other');--> statement-breakpoint
|
||||
CREATE TABLE "kyoo"."roles" (
|
||||
"pk" integer PRIMARY KEY GENERATED ALWAYS AS IDENTITY (sequence name "kyoo"."roles_pk_seq" INCREMENT BY 1 MINVALUE 1 MAXVALUE 2147483647 START WITH 1 CACHE 1),
|
||||
"show_pk" integer NOT NULL,
|
||||
"staff_pk" integer NOT NULL,
|
||||
"kind" "kyoo"."role_kind" NOT NULL,
|
||||
"order" integer NOT NULL,
|
||||
"character" jsonb
|
||||
);
|
||||
--> statement-breakpoint
|
||||
CREATE TABLE "kyoo"."staff" (
|
||||
"pk" integer PRIMARY KEY GENERATED ALWAYS AS IDENTITY (sequence name "kyoo"."staff_pk_seq" INCREMENT BY 1 MINVALUE 1 MAXVALUE 2147483647 START WITH 1 CACHE 1),
|
||||
"id" uuid DEFAULT gen_random_uuid() NOT NULL,
|
||||
"slug" varchar(255) NOT NULL,
|
||||
"name" text NOT NULL,
|
||||
"latin_name" text,
|
||||
"image" jsonb,
|
||||
"external_id" jsonb DEFAULT '{}'::jsonb NOT NULL,
|
||||
"created_at" timestamp with time zone DEFAULT now() NOT NULL,
|
||||
"updated_at" timestamp with time zone NOT NULL,
|
||||
CONSTRAINT "staff_id_unique" UNIQUE("id"),
|
||||
CONSTRAINT "staff_slug_unique" UNIQUE("slug")
|
||||
);
|
||||
--> statement-breakpoint
|
||||
ALTER TABLE "kyoo"."roles" ADD CONSTRAINT "roles_show_pk_shows_pk_fk" FOREIGN KEY ("show_pk") REFERENCES "kyoo"."shows"("pk") ON DELETE cascade ON UPDATE no action;--> statement-breakpoint
|
||||
ALTER TABLE "kyoo"."roles" ADD CONSTRAINT "roles_staff_pk_staff_pk_fk" FOREIGN KEY ("staff_pk") REFERENCES "kyoo"."staff"("pk") ON DELETE cascade ON UPDATE no action;--> statement-breakpoint
|
||||
CREATE INDEX "role_kind" ON "kyoo"."roles" USING hash ("kind");--> statement-breakpoint
|
||||
CREATE INDEX "role_order" ON "kyoo"."roles" USING btree ("order");
|
||||
1
api/drizzle/0015_news.sql
Normal file
1
api/drizzle/0015_news.sql
Normal file
@@ -0,0 +1 @@
|
||||
ALTER TABLE "kyoo"."entries" ADD COLUMN "available_since" timestamp with time zone;
|
||||
9
api/drizzle/0016_mqueue.sql
Normal file
9
api/drizzle/0016_mqueue.sql
Normal file
@@ -0,0 +1,9 @@
|
||||
CREATE TABLE "kyoo"."mqueue" (
|
||||
"id" uuid PRIMARY KEY DEFAULT gen_random_uuid() NOT NULL,
|
||||
"kind" varchar(255) NOT NULL,
|
||||
"message" jsonb NOT NULL,
|
||||
"attempt" integer DEFAULT 0 NOT NULL,
|
||||
"created_at" timestamp with time zone DEFAULT now() NOT NULL
|
||||
);
|
||||
--> statement-breakpoint
|
||||
CREATE INDEX "mqueue_created" ON "kyoo"."mqueue" USING btree ("created_at");
|
||||
40
api/drizzle/0017_watchlist.sql
Normal file
40
api/drizzle/0017_watchlist.sql
Normal file
@@ -0,0 +1,40 @@
|
||||
CREATE TYPE "kyoo"."watchlist_status" AS ENUM('completed', 'watching', 'rewatching', 'dropped', 'planned');--> statement-breakpoint
|
||||
CREATE TABLE "kyoo"."history" (
|
||||
"pk" integer PRIMARY KEY GENERATED ALWAYS AS IDENTITY (sequence name "kyoo"."history_pk_seq" INCREMENT BY 1 MINVALUE 1 MAXVALUE 2147483647 START WITH 1 CACHE 1),
|
||||
"profile_pk" integer NOT NULL,
|
||||
"entry_pk" integer NOT NULL,
|
||||
"video_pk" integer NOT NULL,
|
||||
"percent" integer DEFAULT 0 NOT NULL,
|
||||
"time" integer,
|
||||
"played_date" timestamp with time zone DEFAULT now() NOT NULL,
|
||||
CONSTRAINT "percent_valid" CHECK ("kyoo"."history"."percent" between 0 and 100)
|
||||
);
|
||||
--> statement-breakpoint
|
||||
CREATE TABLE "kyoo"."profiles" (
|
||||
"pk" integer PRIMARY KEY GENERATED ALWAYS AS IDENTITY (sequence name "kyoo"."profiles_pk_seq" INCREMENT BY 1 MINVALUE 1 MAXVALUE 2147483647 START WITH 1 CACHE 1),
|
||||
"id" uuid NOT NULL,
|
||||
CONSTRAINT "profiles_id_unique" UNIQUE("id")
|
||||
);
|
||||
--> statement-breakpoint
|
||||
CREATE TABLE "kyoo"."watchlist" (
|
||||
"profile_pk" integer NOT NULL,
|
||||
"show_pk" integer NOT NULL,
|
||||
"status" "kyoo"."watchlist_status" NOT NULL,
|
||||
"seen_count" integer DEFAULT 0 NOT NULL,
|
||||
"next_entry" integer,
|
||||
"score" integer,
|
||||
"started_at" timestamp with time zone,
|
||||
"completed_at" timestamp with time zone,
|
||||
"created_at" timestamp with time zone DEFAULT now() NOT NULL,
|
||||
"updated_at" timestamp with time zone NOT NULL,
|
||||
CONSTRAINT "watchlist_profile_pk_show_pk_pk" PRIMARY KEY("profile_pk","show_pk"),
|
||||
CONSTRAINT "score_percent" CHECK ("kyoo"."watchlist"."score" between 0 and 100)
|
||||
);
|
||||
--> statement-breakpoint
|
||||
ALTER TABLE "kyoo"."history" ADD CONSTRAINT "history_profile_pk_profiles_pk_fk" FOREIGN KEY ("profile_pk") REFERENCES "kyoo"."profiles"("pk") ON DELETE cascade ON UPDATE no action;--> statement-breakpoint
|
||||
ALTER TABLE "kyoo"."history" ADD CONSTRAINT "history_entry_pk_entries_pk_fk" FOREIGN KEY ("entry_pk") REFERENCES "kyoo"."entries"("pk") ON DELETE cascade ON UPDATE no action;--> statement-breakpoint
|
||||
ALTER TABLE "kyoo"."history" ADD CONSTRAINT "history_video_pk_videos_pk_fk" FOREIGN KEY ("video_pk") REFERENCES "kyoo"."videos"("pk") ON DELETE set null ON UPDATE no action;--> statement-breakpoint
|
||||
ALTER TABLE "kyoo"."watchlist" ADD CONSTRAINT "watchlist_profile_pk_profiles_pk_fk" FOREIGN KEY ("profile_pk") REFERENCES "kyoo"."profiles"("pk") ON DELETE cascade ON UPDATE no action;--> statement-breakpoint
|
||||
ALTER TABLE "kyoo"."watchlist" ADD CONSTRAINT "watchlist_show_pk_shows_pk_fk" FOREIGN KEY ("show_pk") REFERENCES "kyoo"."shows"("pk") ON DELETE cascade ON UPDATE no action;--> statement-breakpoint
|
||||
ALTER TABLE "kyoo"."watchlist" ADD CONSTRAINT "watchlist_next_entry_entries_pk_fk" FOREIGN KEY ("next_entry") REFERENCES "kyoo"."entries"("pk") ON DELETE set null ON UPDATE no action;--> statement-breakpoint
|
||||
CREATE INDEX "history_play_date" ON "kyoo"."history" USING btree ("played_date" DESC NULLS LAST);
|
||||
5
api/drizzle/0018_history.sql
Normal file
5
api/drizzle/0018_history.sql
Normal file
@@ -0,0 +1,5 @@
|
||||
ALTER TABLE "kyoo"."history" ALTER COLUMN "video_pk" DROP NOT NULL;--> statement-breakpoint
|
||||
ALTER TABLE "kyoo"."watchlist" ALTER COLUMN "status" SET DATA TYPE text;--> statement-breakpoint
|
||||
DROP TYPE "kyoo"."watchlist_status";--> statement-breakpoint
|
||||
CREATE TYPE "kyoo"."watchlist_status" AS ENUM('watching', 'rewatching', 'completed', 'dropped', 'planned');--> statement-breakpoint
|
||||
ALTER TABLE "kyoo"."watchlist" ALTER COLUMN "status" SET DATA TYPE "kyoo"."watchlist_status" USING "status"::"kyoo"."watchlist_status";
|
||||
1
api/drizzle/0019_nextup.sql
Normal file
1
api/drizzle/0019_nextup.sql
Normal file
@@ -0,0 +1 @@
|
||||
ALTER TABLE "kyoo"."watchlist" ADD COLUMN "last_played_at" timestamp with time zone;
|
||||
5
api/drizzle/0020_video_unique.sql
Normal file
5
api/drizzle/0020_video_unique.sql
Normal file
@@ -0,0 +1,5 @@
|
||||
ALTER TABLE "kyoo"."entries" ALTER COLUMN "kind" SET DATA TYPE text;--> statement-breakpoint
|
||||
DROP TYPE "kyoo"."entry_type";--> statement-breakpoint
|
||||
CREATE TYPE "kyoo"."entry_type" AS ENUM('episode', 'movie', 'special', 'extra');--> statement-breakpoint
|
||||
ALTER TABLE "kyoo"."entries" ALTER COLUMN "kind" SET DATA TYPE "kyoo"."entry_type" USING "kind"::"kyoo"."entry_type";--> statement-breakpoint
|
||||
ALTER TABLE "kyoo"."videos" ADD CONSTRAINT "rendering_unique" UNIQUE NULLS NOT DISTINCT("rendering","part","version");
|
||||
1
api/drizzle/0021_crew.sql
Normal file
1
api/drizzle/0021_crew.sql
Normal file
@@ -0,0 +1 @@
|
||||
ALTER TYPE "kyoo"."role_kind" ADD VALUE 'crew' BEFORE 'other';
|
||||
2
api/drizzle/0022_seasons-count.sql
Normal file
2
api/drizzle/0022_seasons-count.sql
Normal file
@@ -0,0 +1,2 @@
|
||||
ALTER TABLE "kyoo"."seasons" ADD COLUMN "entries_count" integer NOT NULL;--> statement-breakpoint
|
||||
ALTER TABLE "kyoo"."seasons" ADD COLUMN "available_count" integer DEFAULT 0 NOT NULL;
|
||||
3
api/drizzle/0023_mqueue-priority.sql
Normal file
3
api/drizzle/0023_mqueue-priority.sql
Normal file
@@ -0,0 +1,3 @@
|
||||
ALTER TABLE "kyoo"."history" ALTER COLUMN "time" SET DEFAULT 0;--> statement-breakpoint
|
||||
ALTER TABLE "kyoo"."history" ALTER COLUMN "time" SET NOT NULL;--> statement-breakpoint
|
||||
ALTER TABLE "kyoo"."mqueue" ADD COLUMN "priority" integer DEFAULT 0 NOT NULL;
|
||||
1
api/drizzle/0024_fix-season-count.sql
Normal file
1
api/drizzle/0024_fix-season-count.sql
Normal file
@@ -0,0 +1 @@
|
||||
ALTER TABLE "kyoo"."seasons" ALTER COLUMN "entries_count" SET DEFAULT 0;
|
||||
589
api/drizzle/meta/0000_snapshot.json
Normal file
589
api/drizzle/meta/0000_snapshot.json
Normal file
@@ -0,0 +1,589 @@
|
||||
{
|
||||
"id": "82560792-5f4a-4723-9543-808719ade682",
|
||||
"prevId": "00000000-0000-0000-0000-000000000000",
|
||||
"version": "7",
|
||||
"dialect": "postgresql",
|
||||
"tables": {
|
||||
"kyoo.entries": {
|
||||
"name": "entries",
|
||||
"schema": "kyoo",
|
||||
"columns": {
|
||||
"pk": {
|
||||
"name": "pk",
|
||||
"type": "integer",
|
||||
"primaryKey": true,
|
||||
"notNull": true,
|
||||
"identity": {
|
||||
"type": "always",
|
||||
"name": "entries_pk_seq",
|
||||
"schema": "kyoo",
|
||||
"increment": "1",
|
||||
"startWith": "1",
|
||||
"minValue": "1",
|
||||
"maxValue": "2147483647",
|
||||
"cache": "1",
|
||||
"cycle": false
|
||||
}
|
||||
},
|
||||
"id": {
|
||||
"name": "id",
|
||||
"type": "uuid",
|
||||
"primaryKey": false,
|
||||
"notNull": true,
|
||||
"default": "gen_random_uuid()"
|
||||
},
|
||||
"slug": {
|
||||
"name": "slug",
|
||||
"type": "varchar(255)",
|
||||
"primaryKey": false,
|
||||
"notNull": true
|
||||
},
|
||||
"show_pk": {
|
||||
"name": "show_pk",
|
||||
"type": "integer",
|
||||
"primaryKey": false,
|
||||
"notNull": false
|
||||
},
|
||||
"order": {
|
||||
"name": "order",
|
||||
"type": "integer",
|
||||
"primaryKey": false,
|
||||
"notNull": true
|
||||
},
|
||||
"season_number": {
|
||||
"name": "season_number",
|
||||
"type": "integer",
|
||||
"primaryKey": false,
|
||||
"notNull": false
|
||||
},
|
||||
"episode_number": {
|
||||
"name": "episode_number",
|
||||
"type": "integer",
|
||||
"primaryKey": false,
|
||||
"notNull": false
|
||||
},
|
||||
"type": {
|
||||
"name": "type",
|
||||
"type": "entry_type",
|
||||
"typeSchema": "kyoo",
|
||||
"primaryKey": false,
|
||||
"notNull": true
|
||||
},
|
||||
"air_date": {
|
||||
"name": "air_date",
|
||||
"type": "date",
|
||||
"primaryKey": false,
|
||||
"notNull": false
|
||||
},
|
||||
"runtime": {
|
||||
"name": "runtime",
|
||||
"type": "integer",
|
||||
"primaryKey": false,
|
||||
"notNull": false
|
||||
},
|
||||
"thumbnails": {
|
||||
"name": "thumbnails",
|
||||
"type": "jsonb",
|
||||
"primaryKey": false,
|
||||
"notNull": false
|
||||
},
|
||||
"external_id": {
|
||||
"name": "external_id",
|
||||
"type": "jsonb",
|
||||
"primaryKey": false,
|
||||
"notNull": true,
|
||||
"default": "'{}'::jsonb"
|
||||
},
|
||||
"created_at": {
|
||||
"name": "created_at",
|
||||
"type": "timestamp with time zone",
|
||||
"primaryKey": false,
|
||||
"notNull": false,
|
||||
"default": "now()"
|
||||
},
|
||||
"next_refresh": {
|
||||
"name": "next_refresh",
|
||||
"type": "timestamp with time zone",
|
||||
"primaryKey": false,
|
||||
"notNull": false
|
||||
}
|
||||
},
|
||||
"indexes": {},
|
||||
"foreignKeys": {
|
||||
"entries_show_pk_shows_pk_fk": {
|
||||
"name": "entries_show_pk_shows_pk_fk",
|
||||
"tableFrom": "entries",
|
||||
"tableTo": "shows",
|
||||
"schemaTo": "kyoo",
|
||||
"columnsFrom": ["show_pk"],
|
||||
"columnsTo": ["pk"],
|
||||
"onDelete": "cascade",
|
||||
"onUpdate": "no action"
|
||||
}
|
||||
},
|
||||
"compositePrimaryKeys": {},
|
||||
"uniqueConstraints": {
|
||||
"entries_id_unique": {
|
||||
"name": "entries_id_unique",
|
||||
"nullsNotDistinct": false,
|
||||
"columns": ["id"]
|
||||
},
|
||||
"entries_slug_unique": {
|
||||
"name": "entries_slug_unique",
|
||||
"nullsNotDistinct": false,
|
||||
"columns": ["slug"]
|
||||
},
|
||||
"entries_showPk_seasonNumber_episodeNumber_unique": {
|
||||
"name": "entries_showPk_seasonNumber_episodeNumber_unique",
|
||||
"nullsNotDistinct": false,
|
||||
"columns": ["show_pk", "season_number", "episode_number"]
|
||||
}
|
||||
},
|
||||
"policies": {},
|
||||
"checkConstraints": {
|
||||
"order_positive": {
|
||||
"name": "order_positive",
|
||||
"value": "\"entries\".\"order\" >= 0"
|
||||
}
|
||||
},
|
||||
"isRLSEnabled": false
|
||||
},
|
||||
"kyoo.entries_translation": {
|
||||
"name": "entries_translation",
|
||||
"schema": "kyoo",
|
||||
"columns": {
|
||||
"pk": {
|
||||
"name": "pk",
|
||||
"type": "integer",
|
||||
"primaryKey": false,
|
||||
"notNull": true
|
||||
},
|
||||
"language": {
|
||||
"name": "language",
|
||||
"type": "varchar(255)",
|
||||
"primaryKey": false,
|
||||
"notNull": true
|
||||
},
|
||||
"name": {
|
||||
"name": "name",
|
||||
"type": "text",
|
||||
"primaryKey": false,
|
||||
"notNull": false
|
||||
},
|
||||
"description": {
|
||||
"name": "description",
|
||||
"type": "text",
|
||||
"primaryKey": false,
|
||||
"notNull": false
|
||||
}
|
||||
},
|
||||
"indexes": {},
|
||||
"foreignKeys": {
|
||||
"entries_translation_pk_entries_pk_fk": {
|
||||
"name": "entries_translation_pk_entries_pk_fk",
|
||||
"tableFrom": "entries_translation",
|
||||
"tableTo": "entries",
|
||||
"schemaTo": "kyoo",
|
||||
"columnsFrom": ["pk"],
|
||||
"columnsTo": ["pk"],
|
||||
"onDelete": "cascade",
|
||||
"onUpdate": "no action"
|
||||
}
|
||||
},
|
||||
"compositePrimaryKeys": {
|
||||
"entries_translation_pk_language_pk": {
|
||||
"name": "entries_translation_pk_language_pk",
|
||||
"columns": ["pk", "language"]
|
||||
}
|
||||
},
|
||||
"uniqueConstraints": {},
|
||||
"policies": {},
|
||||
"checkConstraints": {},
|
||||
"isRLSEnabled": false
|
||||
},
|
||||
"kyoo.show_translations": {
|
||||
"name": "show_translations",
|
||||
"schema": "kyoo",
|
||||
"columns": {
|
||||
"pk": {
|
||||
"name": "pk",
|
||||
"type": "integer",
|
||||
"primaryKey": false,
|
||||
"notNull": true
|
||||
},
|
||||
"language": {
|
||||
"name": "language",
|
||||
"type": "varchar(255)",
|
||||
"primaryKey": false,
|
||||
"notNull": true
|
||||
},
|
||||
"name": {
|
||||
"name": "name",
|
||||
"type": "text",
|
||||
"primaryKey": false,
|
||||
"notNull": true
|
||||
},
|
||||
"description": {
|
||||
"name": "description",
|
||||
"type": "text",
|
||||
"primaryKey": false,
|
||||
"notNull": false
|
||||
},
|
||||
"tagline": {
|
||||
"name": "tagline",
|
||||
"type": "text",
|
||||
"primaryKey": false,
|
||||
"notNull": false
|
||||
},
|
||||
"aliases": {
|
||||
"name": "aliases",
|
||||
"type": "text[]",
|
||||
"primaryKey": false,
|
||||
"notNull": true
|
||||
},
|
||||
"tags": {
|
||||
"name": "tags",
|
||||
"type": "text[]",
|
||||
"primaryKey": false,
|
||||
"notNull": true
|
||||
},
|
||||
"trailer_url": {
|
||||
"name": "trailer_url",
|
||||
"type": "text",
|
||||
"primaryKey": false,
|
||||
"notNull": false
|
||||
},
|
||||
"poster": {
|
||||
"name": "poster",
|
||||
"type": "jsonb",
|
||||
"primaryKey": false,
|
||||
"notNull": false
|
||||
},
|
||||
"thumbnail": {
|
||||
"name": "thumbnail",
|
||||
"type": "jsonb",
|
||||
"primaryKey": false,
|
||||
"notNull": false
|
||||
},
|
||||
"banner": {
|
||||
"name": "banner",
|
||||
"type": "jsonb",
|
||||
"primaryKey": false,
|
||||
"notNull": false
|
||||
},
|
||||
"logo": {
|
||||
"name": "logo",
|
||||
"type": "jsonb",
|
||||
"primaryKey": false,
|
||||
"notNull": false
|
||||
}
|
||||
},
|
||||
"indexes": {},
|
||||
"foreignKeys": {
|
||||
"show_translations_pk_shows_pk_fk": {
|
||||
"name": "show_translations_pk_shows_pk_fk",
|
||||
"tableFrom": "show_translations",
|
||||
"tableTo": "shows",
|
||||
"schemaTo": "kyoo",
|
||||
"columnsFrom": ["pk"],
|
||||
"columnsTo": ["pk"],
|
||||
"onDelete": "cascade",
|
||||
"onUpdate": "no action"
|
||||
}
|
||||
},
|
||||
"compositePrimaryKeys": {
|
||||
"show_translations_pk_language_pk": {
|
||||
"name": "show_translations_pk_language_pk",
|
||||
"columns": ["pk", "language"]
|
||||
}
|
||||
},
|
||||
"uniqueConstraints": {},
|
||||
"policies": {},
|
||||
"checkConstraints": {},
|
||||
"isRLSEnabled": false
|
||||
},
|
||||
"kyoo.shows": {
|
||||
"name": "shows",
|
||||
"schema": "kyoo",
|
||||
"columns": {
|
||||
"pk": {
|
||||
"name": "pk",
|
||||
"type": "integer",
|
||||
"primaryKey": true,
|
||||
"notNull": true,
|
||||
"identity": {
|
||||
"type": "always",
|
||||
"name": "shows_pk_seq",
|
||||
"schema": "kyoo",
|
||||
"increment": "1",
|
||||
"startWith": "1",
|
||||
"minValue": "1",
|
||||
"maxValue": "2147483647",
|
||||
"cache": "1",
|
||||
"cycle": false
|
||||
}
|
||||
},
|
||||
"id": {
|
||||
"name": "id",
|
||||
"type": "uuid",
|
||||
"primaryKey": false,
|
||||
"notNull": true,
|
||||
"default": "gen_random_uuid()"
|
||||
},
|
||||
"slug": {
|
||||
"name": "slug",
|
||||
"type": "varchar(255)",
|
||||
"primaryKey": false,
|
||||
"notNull": true
|
||||
},
|
||||
"kind": {
|
||||
"name": "kind",
|
||||
"type": "show_kind",
|
||||
"typeSchema": "kyoo",
|
||||
"primaryKey": false,
|
||||
"notNull": true
|
||||
},
|
||||
"genres": {
|
||||
"name": "genres",
|
||||
"type": "genres[]",
|
||||
"primaryKey": false,
|
||||
"notNull": true
|
||||
},
|
||||
"rating": {
|
||||
"name": "rating",
|
||||
"type": "smallint",
|
||||
"primaryKey": false,
|
||||
"notNull": false
|
||||
},
|
||||
"runtime": {
|
||||
"name": "runtime",
|
||||
"type": "integer",
|
||||
"primaryKey": false,
|
||||
"notNull": false
|
||||
},
|
||||
"status": {
|
||||
"name": "status",
|
||||
"type": "show_status",
|
||||
"typeSchema": "kyoo",
|
||||
"primaryKey": false,
|
||||
"notNull": true
|
||||
},
|
||||
"start_air": {
|
||||
"name": "start_air",
|
||||
"type": "date",
|
||||
"primaryKey": false,
|
||||
"notNull": false
|
||||
},
|
||||
"end_air": {
|
||||
"name": "end_air",
|
||||
"type": "date",
|
||||
"primaryKey": false,
|
||||
"notNull": false
|
||||
},
|
||||
"original_language": {
|
||||
"name": "original_language",
|
||||
"type": "varchar(255)",
|
||||
"primaryKey": false,
|
||||
"notNull": false
|
||||
},
|
||||
"external_id": {
|
||||
"name": "external_id",
|
||||
"type": "jsonb",
|
||||
"primaryKey": false,
|
||||
"notNull": true,
|
||||
"default": "'{}'::jsonb"
|
||||
},
|
||||
"created_at": {
|
||||
"name": "created_at",
|
||||
"type": "timestamp with time zone",
|
||||
"primaryKey": false,
|
||||
"notNull": true,
|
||||
"default": "now()"
|
||||
},
|
||||
"next_refresh": {
|
||||
"name": "next_refresh",
|
||||
"type": "timestamp with time zone",
|
||||
"primaryKey": false,
|
||||
"notNull": true
|
||||
}
|
||||
},
|
||||
"indexes": {},
|
||||
"foreignKeys": {},
|
||||
"compositePrimaryKeys": {},
|
||||
"uniqueConstraints": {
|
||||
"shows_id_unique": {
|
||||
"name": "shows_id_unique",
|
||||
"nullsNotDistinct": false,
|
||||
"columns": ["id"]
|
||||
},
|
||||
"shows_slug_unique": {
|
||||
"name": "shows_slug_unique",
|
||||
"nullsNotDistinct": false,
|
||||
"columns": ["slug"]
|
||||
}
|
||||
},
|
||||
"policies": {},
|
||||
"checkConstraints": {
|
||||
"rating_valid": {
|
||||
"name": "rating_valid",
|
||||
"value": "\"shows\".\"rating\" between 0 and 100"
|
||||
},
|
||||
"runtime_valid": {
|
||||
"name": "runtime_valid",
|
||||
"value": "\"shows\".\"runtime\" >= 0"
|
||||
}
|
||||
},
|
||||
"isRLSEnabled": false
|
||||
},
|
||||
"kyoo.videos": {
|
||||
"name": "videos",
|
||||
"schema": "kyoo",
|
||||
"columns": {
|
||||
"pk": {
|
||||
"name": "pk",
|
||||
"type": "integer",
|
||||
"primaryKey": true,
|
||||
"notNull": true,
|
||||
"identity": {
|
||||
"type": "always",
|
||||
"name": "videos_pk_seq",
|
||||
"schema": "kyoo",
|
||||
"increment": "1",
|
||||
"startWith": "1",
|
||||
"minValue": "1",
|
||||
"maxValue": "2147483647",
|
||||
"cache": "1",
|
||||
"cycle": false
|
||||
}
|
||||
},
|
||||
"id": {
|
||||
"name": "id",
|
||||
"type": "uuid",
|
||||
"primaryKey": false,
|
||||
"notNull": true,
|
||||
"default": "gen_random_uuid()"
|
||||
},
|
||||
"path": {
|
||||
"name": "path",
|
||||
"type": "text",
|
||||
"primaryKey": false,
|
||||
"notNull": true
|
||||
},
|
||||
"rendering": {
|
||||
"name": "rendering",
|
||||
"type": "integer",
|
||||
"primaryKey": false,
|
||||
"notNull": false
|
||||
},
|
||||
"part": {
|
||||
"name": "part",
|
||||
"type": "integer",
|
||||
"primaryKey": false,
|
||||
"notNull": false
|
||||
},
|
||||
"version": {
|
||||
"name": "version",
|
||||
"type": "integer",
|
||||
"primaryKey": false,
|
||||
"notNull": false
|
||||
},
|
||||
"created_at": {
|
||||
"name": "created_at",
|
||||
"type": "timestamp with time zone",
|
||||
"primaryKey": false,
|
||||
"notNull": true,
|
||||
"default": "now()"
|
||||
}
|
||||
},
|
||||
"indexes": {},
|
||||
"foreignKeys": {},
|
||||
"compositePrimaryKeys": {},
|
||||
"uniqueConstraints": {
|
||||
"videos_id_unique": {
|
||||
"name": "videos_id_unique",
|
||||
"nullsNotDistinct": false,
|
||||
"columns": ["id"]
|
||||
},
|
||||
"videos_path_unique": {
|
||||
"name": "videos_path_unique",
|
||||
"nullsNotDistinct": false,
|
||||
"columns": ["path"]
|
||||
}
|
||||
},
|
||||
"policies": {},
|
||||
"checkConstraints": {
|
||||
"rendering_pos": {
|
||||
"name": "rendering_pos",
|
||||
"value": "\"videos\".\"rendering\" >= 0"
|
||||
},
|
||||
"part_pos": {
|
||||
"name": "part_pos",
|
||||
"value": "\"videos\".\"part\" >= 0"
|
||||
},
|
||||
"version_pos": {
|
||||
"name": "version_pos",
|
||||
"value": "\"videos\".\"version\" >= 0"
|
||||
}
|
||||
},
|
||||
"isRLSEnabled": false
|
||||
}
|
||||
},
|
||||
"enums": {
|
||||
"kyoo.entry_type": {
|
||||
"name": "entry_type",
|
||||
"schema": "kyoo",
|
||||
"values": ["unknown", "episode", "movie", "special", "extra"]
|
||||
},
|
||||
"kyoo.genres": {
|
||||
"name": "genres",
|
||||
"schema": "kyoo",
|
||||
"values": [
|
||||
"action",
|
||||
"adventure",
|
||||
"animation",
|
||||
"comedy",
|
||||
"crime",
|
||||
"documentary",
|
||||
"drama",
|
||||
"family",
|
||||
"fantasy",
|
||||
"history",
|
||||
"horror",
|
||||
"music",
|
||||
"mystery",
|
||||
"romance",
|
||||
"science-fiction",
|
||||
"thriller",
|
||||
"war",
|
||||
"western",
|
||||
"kids",
|
||||
"reality",
|
||||
"politics",
|
||||
"soap",
|
||||
"talk"
|
||||
]
|
||||
},
|
||||
"kyoo.show_kind": {
|
||||
"name": "show_kind",
|
||||
"schema": "kyoo",
|
||||
"values": ["serie", "movie"]
|
||||
},
|
||||
"kyoo.show_status": {
|
||||
"name": "show_status",
|
||||
"schema": "kyoo",
|
||||
"values": ["unknown", "finished", "airing", "planned"]
|
||||
}
|
||||
},
|
||||
"schemas": {
|
||||
"kyoo": "kyoo"
|
||||
},
|
||||
"sequences": {},
|
||||
"roles": {},
|
||||
"policies": {},
|
||||
"views": {},
|
||||
"_meta": {
|
||||
"columns": {},
|
||||
"schemas": {},
|
||||
"tables": {}
|
||||
}
|
||||
}
|
||||
597
api/drizzle/meta/0001_snapshot.json
Normal file
597
api/drizzle/meta/0001_snapshot.json
Normal file
@@ -0,0 +1,597 @@
|
||||
{
|
||||
"id": "32090852-33a7-430a-9df1-97608c063124",
|
||||
"prevId": "82560792-5f4a-4723-9543-808719ade682",
|
||||
"version": "7",
|
||||
"dialect": "postgresql",
|
||||
"tables": {
|
||||
"kyoo.entries": {
|
||||
"name": "entries",
|
||||
"schema": "kyoo",
|
||||
"columns": {
|
||||
"pk": {
|
||||
"name": "pk",
|
||||
"type": "integer",
|
||||
"primaryKey": true,
|
||||
"notNull": true,
|
||||
"identity": {
|
||||
"type": "always",
|
||||
"name": "entries_pk_seq",
|
||||
"schema": "kyoo",
|
||||
"increment": "1",
|
||||
"startWith": "1",
|
||||
"minValue": "1",
|
||||
"maxValue": "2147483647",
|
||||
"cache": "1",
|
||||
"cycle": false
|
||||
}
|
||||
},
|
||||
"id": {
|
||||
"name": "id",
|
||||
"type": "uuid",
|
||||
"primaryKey": false,
|
||||
"notNull": true,
|
||||
"default": "gen_random_uuid()"
|
||||
},
|
||||
"slug": {
|
||||
"name": "slug",
|
||||
"type": "varchar(255)",
|
||||
"primaryKey": false,
|
||||
"notNull": true
|
||||
},
|
||||
"show_pk": {
|
||||
"name": "show_pk",
|
||||
"type": "integer",
|
||||
"primaryKey": false,
|
||||
"notNull": false
|
||||
},
|
||||
"order": {
|
||||
"name": "order",
|
||||
"type": "integer",
|
||||
"primaryKey": false,
|
||||
"notNull": true
|
||||
},
|
||||
"season_number": {
|
||||
"name": "season_number",
|
||||
"type": "integer",
|
||||
"primaryKey": false,
|
||||
"notNull": false
|
||||
},
|
||||
"episode_number": {
|
||||
"name": "episode_number",
|
||||
"type": "integer",
|
||||
"primaryKey": false,
|
||||
"notNull": false
|
||||
},
|
||||
"type": {
|
||||
"name": "type",
|
||||
"type": "entry_type",
|
||||
"typeSchema": "kyoo",
|
||||
"primaryKey": false,
|
||||
"notNull": true
|
||||
},
|
||||
"air_date": {
|
||||
"name": "air_date",
|
||||
"type": "date",
|
||||
"primaryKey": false,
|
||||
"notNull": false
|
||||
},
|
||||
"runtime": {
|
||||
"name": "runtime",
|
||||
"type": "integer",
|
||||
"primaryKey": false,
|
||||
"notNull": false
|
||||
},
|
||||
"thumbnails": {
|
||||
"name": "thumbnails",
|
||||
"type": "jsonb",
|
||||
"primaryKey": false,
|
||||
"notNull": false
|
||||
},
|
||||
"external_id": {
|
||||
"name": "external_id",
|
||||
"type": "jsonb",
|
||||
"primaryKey": false,
|
||||
"notNull": true,
|
||||
"default": "'{}'::jsonb"
|
||||
},
|
||||
"created_at": {
|
||||
"name": "created_at",
|
||||
"type": "timestamp with time zone",
|
||||
"primaryKey": false,
|
||||
"notNull": false,
|
||||
"default": "now()"
|
||||
},
|
||||
"next_refresh": {
|
||||
"name": "next_refresh",
|
||||
"type": "timestamp with time zone",
|
||||
"primaryKey": false,
|
||||
"notNull": false
|
||||
}
|
||||
},
|
||||
"indexes": {},
|
||||
"foreignKeys": {
|
||||
"entries_show_pk_shows_pk_fk": {
|
||||
"name": "entries_show_pk_shows_pk_fk",
|
||||
"tableFrom": "entries",
|
||||
"tableTo": "shows",
|
||||
"schemaTo": "kyoo",
|
||||
"columnsFrom": ["show_pk"],
|
||||
"columnsTo": ["pk"],
|
||||
"onDelete": "cascade",
|
||||
"onUpdate": "no action"
|
||||
}
|
||||
},
|
||||
"compositePrimaryKeys": {},
|
||||
"uniqueConstraints": {
|
||||
"entries_id_unique": {
|
||||
"name": "entries_id_unique",
|
||||
"nullsNotDistinct": false,
|
||||
"columns": ["id"]
|
||||
},
|
||||
"entries_slug_unique": {
|
||||
"name": "entries_slug_unique",
|
||||
"nullsNotDistinct": false,
|
||||
"columns": ["slug"]
|
||||
},
|
||||
"entries_showPk_seasonNumber_episodeNumber_unique": {
|
||||
"name": "entries_showPk_seasonNumber_episodeNumber_unique",
|
||||
"nullsNotDistinct": false,
|
||||
"columns": ["show_pk", "season_number", "episode_number"]
|
||||
}
|
||||
},
|
||||
"policies": {},
|
||||
"checkConstraints": {
|
||||
"order_positive": {
|
||||
"name": "order_positive",
|
||||
"value": "\"entries\".\"order\" >= 0"
|
||||
}
|
||||
},
|
||||
"isRLSEnabled": false
|
||||
},
|
||||
"kyoo.entries_translation": {
|
||||
"name": "entries_translation",
|
||||
"schema": "kyoo",
|
||||
"columns": {
|
||||
"pk": {
|
||||
"name": "pk",
|
||||
"type": "integer",
|
||||
"primaryKey": false,
|
||||
"notNull": true
|
||||
},
|
||||
"language": {
|
||||
"name": "language",
|
||||
"type": "varchar(255)",
|
||||
"primaryKey": false,
|
||||
"notNull": true
|
||||
},
|
||||
"name": {
|
||||
"name": "name",
|
||||
"type": "text",
|
||||
"primaryKey": false,
|
||||
"notNull": false
|
||||
},
|
||||
"description": {
|
||||
"name": "description",
|
||||
"type": "text",
|
||||
"primaryKey": false,
|
||||
"notNull": false
|
||||
}
|
||||
},
|
||||
"indexes": {},
|
||||
"foreignKeys": {
|
||||
"entries_translation_pk_entries_pk_fk": {
|
||||
"name": "entries_translation_pk_entries_pk_fk",
|
||||
"tableFrom": "entries_translation",
|
||||
"tableTo": "entries",
|
||||
"schemaTo": "kyoo",
|
||||
"columnsFrom": ["pk"],
|
||||
"columnsTo": ["pk"],
|
||||
"onDelete": "cascade",
|
||||
"onUpdate": "no action"
|
||||
}
|
||||
},
|
||||
"compositePrimaryKeys": {
|
||||
"entries_translation_pk_language_pk": {
|
||||
"name": "entries_translation_pk_language_pk",
|
||||
"columns": ["pk", "language"]
|
||||
}
|
||||
},
|
||||
"uniqueConstraints": {},
|
||||
"policies": {},
|
||||
"checkConstraints": {},
|
||||
"isRLSEnabled": false
|
||||
},
|
||||
"kyoo.show_translations": {
|
||||
"name": "show_translations",
|
||||
"schema": "kyoo",
|
||||
"columns": {
|
||||
"pk": {
|
||||
"name": "pk",
|
||||
"type": "integer",
|
||||
"primaryKey": false,
|
||||
"notNull": true
|
||||
},
|
||||
"language": {
|
||||
"name": "language",
|
||||
"type": "varchar(255)",
|
||||
"primaryKey": false,
|
||||
"notNull": true
|
||||
},
|
||||
"name": {
|
||||
"name": "name",
|
||||
"type": "text",
|
||||
"primaryKey": false,
|
||||
"notNull": true
|
||||
},
|
||||
"description": {
|
||||
"name": "description",
|
||||
"type": "text",
|
||||
"primaryKey": false,
|
||||
"notNull": false
|
||||
},
|
||||
"tagline": {
|
||||
"name": "tagline",
|
||||
"type": "text",
|
||||
"primaryKey": false,
|
||||
"notNull": false
|
||||
},
|
||||
"aliases": {
|
||||
"name": "aliases",
|
||||
"type": "text[]",
|
||||
"primaryKey": false,
|
||||
"notNull": true
|
||||
},
|
||||
"tags": {
|
||||
"name": "tags",
|
||||
"type": "text[]",
|
||||
"primaryKey": false,
|
||||
"notNull": true
|
||||
},
|
||||
"trailer_url": {
|
||||
"name": "trailer_url",
|
||||
"type": "text",
|
||||
"primaryKey": false,
|
||||
"notNull": false
|
||||
},
|
||||
"poster": {
|
||||
"name": "poster",
|
||||
"type": "jsonb",
|
||||
"primaryKey": false,
|
||||
"notNull": false
|
||||
},
|
||||
"thumbnail": {
|
||||
"name": "thumbnail",
|
||||
"type": "jsonb",
|
||||
"primaryKey": false,
|
||||
"notNull": false
|
||||
},
|
||||
"banner": {
|
||||
"name": "banner",
|
||||
"type": "jsonb",
|
||||
"primaryKey": false,
|
||||
"notNull": false
|
||||
},
|
||||
"logo": {
|
||||
"name": "logo",
|
||||
"type": "jsonb",
|
||||
"primaryKey": false,
|
||||
"notNull": false
|
||||
}
|
||||
},
|
||||
"indexes": {},
|
||||
"foreignKeys": {
|
||||
"show_translations_pk_shows_pk_fk": {
|
||||
"name": "show_translations_pk_shows_pk_fk",
|
||||
"tableFrom": "show_translations",
|
||||
"tableTo": "shows",
|
||||
"schemaTo": "kyoo",
|
||||
"columnsFrom": ["pk"],
|
||||
"columnsTo": ["pk"],
|
||||
"onDelete": "cascade",
|
||||
"onUpdate": "no action"
|
||||
}
|
||||
},
|
||||
"compositePrimaryKeys": {
|
||||
"show_translations_pk_language_pk": {
|
||||
"name": "show_translations_pk_language_pk",
|
||||
"columns": ["pk", "language"]
|
||||
}
|
||||
},
|
||||
"uniqueConstraints": {},
|
||||
"policies": {},
|
||||
"checkConstraints": {},
|
||||
"isRLSEnabled": false
|
||||
},
|
||||
"kyoo.shows": {
|
||||
"name": "shows",
|
||||
"schema": "kyoo",
|
||||
"columns": {
|
||||
"pk": {
|
||||
"name": "pk",
|
||||
"type": "integer",
|
||||
"primaryKey": true,
|
||||
"notNull": true,
|
||||
"identity": {
|
||||
"type": "always",
|
||||
"name": "shows_pk_seq",
|
||||
"schema": "kyoo",
|
||||
"increment": "1",
|
||||
"startWith": "1",
|
||||
"minValue": "1",
|
||||
"maxValue": "2147483647",
|
||||
"cache": "1",
|
||||
"cycle": false
|
||||
}
|
||||
},
|
||||
"id": {
|
||||
"name": "id",
|
||||
"type": "uuid",
|
||||
"primaryKey": false,
|
||||
"notNull": true,
|
||||
"default": "gen_random_uuid()"
|
||||
},
|
||||
"slug": {
|
||||
"name": "slug",
|
||||
"type": "varchar(255)",
|
||||
"primaryKey": false,
|
||||
"notNull": true
|
||||
},
|
||||
"kind": {
|
||||
"name": "kind",
|
||||
"type": "show_kind",
|
||||
"typeSchema": "kyoo",
|
||||
"primaryKey": false,
|
||||
"notNull": true
|
||||
},
|
||||
"genres": {
|
||||
"name": "genres",
|
||||
"type": "genres[]",
|
||||
"primaryKey": false,
|
||||
"notNull": true
|
||||
},
|
||||
"rating": {
|
||||
"name": "rating",
|
||||
"type": "smallint",
|
||||
"primaryKey": false,
|
||||
"notNull": false
|
||||
},
|
||||
"runtime": {
|
||||
"name": "runtime",
|
||||
"type": "integer",
|
||||
"primaryKey": false,
|
||||
"notNull": false
|
||||
},
|
||||
"status": {
|
||||
"name": "status",
|
||||
"type": "show_status",
|
||||
"typeSchema": "kyoo",
|
||||
"primaryKey": false,
|
||||
"notNull": true
|
||||
},
|
||||
"start_air": {
|
||||
"name": "start_air",
|
||||
"type": "date",
|
||||
"primaryKey": false,
|
||||
"notNull": false
|
||||
},
|
||||
"end_air": {
|
||||
"name": "end_air",
|
||||
"type": "date",
|
||||
"primaryKey": false,
|
||||
"notNull": false
|
||||
},
|
||||
"original_language": {
|
||||
"name": "original_language",
|
||||
"type": "varchar(255)",
|
||||
"primaryKey": false,
|
||||
"notNull": false
|
||||
},
|
||||
"external_id": {
|
||||
"name": "external_id",
|
||||
"type": "jsonb",
|
||||
"primaryKey": false,
|
||||
"notNull": true,
|
||||
"default": "'{}'::jsonb"
|
||||
},
|
||||
"created_at": {
|
||||
"name": "created_at",
|
||||
"type": "timestamp with time zone",
|
||||
"primaryKey": false,
|
||||
"notNull": true,
|
||||
"default": "now()"
|
||||
},
|
||||
"next_refresh": {
|
||||
"name": "next_refresh",
|
||||
"type": "timestamp with time zone",
|
||||
"primaryKey": false,
|
||||
"notNull": true
|
||||
}
|
||||
},
|
||||
"indexes": {},
|
||||
"foreignKeys": {},
|
||||
"compositePrimaryKeys": {},
|
||||
"uniqueConstraints": {
|
||||
"shows_id_unique": {
|
||||
"name": "shows_id_unique",
|
||||
"nullsNotDistinct": false,
|
||||
"columns": ["id"]
|
||||
},
|
||||
"shows_slug_unique": {
|
||||
"name": "shows_slug_unique",
|
||||
"nullsNotDistinct": false,
|
||||
"columns": ["slug"]
|
||||
}
|
||||
},
|
||||
"policies": {},
|
||||
"checkConstraints": {
|
||||
"rating_valid": {
|
||||
"name": "rating_valid",
|
||||
"value": "\"shows\".\"rating\" between 0 and 100"
|
||||
},
|
||||
"runtime_valid": {
|
||||
"name": "runtime_valid",
|
||||
"value": "\"shows\".\"runtime\" >= 0"
|
||||
}
|
||||
},
|
||||
"isRLSEnabled": false
|
||||
},
|
||||
"kyoo.videos": {
|
||||
"name": "videos",
|
||||
"schema": "kyoo",
|
||||
"columns": {
|
||||
"pk": {
|
||||
"name": "pk",
|
||||
"type": "integer",
|
||||
"primaryKey": true,
|
||||
"notNull": true,
|
||||
"identity": {
|
||||
"type": "always",
|
||||
"name": "videos_pk_seq",
|
||||
"schema": "kyoo",
|
||||
"increment": "1",
|
||||
"startWith": "1",
|
||||
"minValue": "1",
|
||||
"maxValue": "2147483647",
|
||||
"cache": "1",
|
||||
"cycle": false
|
||||
}
|
||||
},
|
||||
"id": {
|
||||
"name": "id",
|
||||
"type": "uuid",
|
||||
"primaryKey": false,
|
||||
"notNull": true,
|
||||
"default": "gen_random_uuid()"
|
||||
},
|
||||
"slug": {
|
||||
"name": "slug",
|
||||
"type": "varchar(255)",
|
||||
"primaryKey": false,
|
||||
"notNull": true
|
||||
},
|
||||
"path": {
|
||||
"name": "path",
|
||||
"type": "text",
|
||||
"primaryKey": false,
|
||||
"notNull": true
|
||||
},
|
||||
"rendering": {
|
||||
"name": "rendering",
|
||||
"type": "text",
|
||||
"primaryKey": false,
|
||||
"notNull": true
|
||||
},
|
||||
"part": {
|
||||
"name": "part",
|
||||
"type": "integer",
|
||||
"primaryKey": false,
|
||||
"notNull": false
|
||||
},
|
||||
"version": {
|
||||
"name": "version",
|
||||
"type": "integer",
|
||||
"primaryKey": false,
|
||||
"notNull": true,
|
||||
"default": 1
|
||||
},
|
||||
"created_at": {
|
||||
"name": "created_at",
|
||||
"type": "timestamp with time zone",
|
||||
"primaryKey": false,
|
||||
"notNull": true,
|
||||
"default": "now()"
|
||||
}
|
||||
},
|
||||
"indexes": {},
|
||||
"foreignKeys": {},
|
||||
"compositePrimaryKeys": {},
|
||||
"uniqueConstraints": {
|
||||
"videos_id_unique": {
|
||||
"name": "videos_id_unique",
|
||||
"nullsNotDistinct": false,
|
||||
"columns": ["id"]
|
||||
},
|
||||
"videos_slug_unique": {
|
||||
"name": "videos_slug_unique",
|
||||
"nullsNotDistinct": false,
|
||||
"columns": ["slug"]
|
||||
},
|
||||
"videos_path_unique": {
|
||||
"name": "videos_path_unique",
|
||||
"nullsNotDistinct": false,
|
||||
"columns": ["path"]
|
||||
}
|
||||
},
|
||||
"policies": {},
|
||||
"checkConstraints": {
|
||||
"part_pos": {
|
||||
"name": "part_pos",
|
||||
"value": "\"videos\".\"part\" >= 0"
|
||||
},
|
||||
"version_pos": {
|
||||
"name": "version_pos",
|
||||
"value": "\"videos\".\"version\" >= 0"
|
||||
}
|
||||
},
|
||||
"isRLSEnabled": false
|
||||
}
|
||||
},
|
||||
"enums": {
|
||||
"kyoo.entry_type": {
|
||||
"name": "entry_type",
|
||||
"schema": "kyoo",
|
||||
"values": ["unknown", "episode", "movie", "special", "extra"]
|
||||
},
|
||||
"kyoo.genres": {
|
||||
"name": "genres",
|
||||
"schema": "kyoo",
|
||||
"values": [
|
||||
"action",
|
||||
"adventure",
|
||||
"animation",
|
||||
"comedy",
|
||||
"crime",
|
||||
"documentary",
|
||||
"drama",
|
||||
"family",
|
||||
"fantasy",
|
||||
"history",
|
||||
"horror",
|
||||
"music",
|
||||
"mystery",
|
||||
"romance",
|
||||
"science-fiction",
|
||||
"thriller",
|
||||
"war",
|
||||
"western",
|
||||
"kids",
|
||||
"reality",
|
||||
"politics",
|
||||
"soap",
|
||||
"talk"
|
||||
]
|
||||
},
|
||||
"kyoo.show_kind": {
|
||||
"name": "show_kind",
|
||||
"schema": "kyoo",
|
||||
"values": ["serie", "movie"]
|
||||
},
|
||||
"kyoo.show_status": {
|
||||
"name": "show_status",
|
||||
"schema": "kyoo",
|
||||
"values": ["unknown", "finished", "airing", "planned"]
|
||||
}
|
||||
},
|
||||
"schemas": {
|
||||
"kyoo": "kyoo"
|
||||
},
|
||||
"sequences": {},
|
||||
"roles": {},
|
||||
"policies": {},
|
||||
"views": {},
|
||||
"_meta": {
|
||||
"columns": {},
|
||||
"schemas": {},
|
||||
"tables": {}
|
||||
}
|
||||
}
|
||||
788
api/drizzle/meta/0002_snapshot.json
Normal file
788
api/drizzle/meta/0002_snapshot.json
Normal file
@@ -0,0 +1,788 @@
|
||||
{
|
||||
"id": "d0f6c500-aa2b-4592-aa31-db646817f708",
|
||||
"prevId": "32090852-33a7-430a-9df1-97608c063124",
|
||||
"version": "7",
|
||||
"dialect": "postgresql",
|
||||
"tables": {
|
||||
"kyoo.entries": {
|
||||
"name": "entries",
|
||||
"schema": "kyoo",
|
||||
"columns": {
|
||||
"pk": {
|
||||
"name": "pk",
|
||||
"type": "integer",
|
||||
"primaryKey": true,
|
||||
"notNull": true,
|
||||
"identity": {
|
||||
"type": "always",
|
||||
"name": "entries_pk_seq",
|
||||
"schema": "kyoo",
|
||||
"increment": "1",
|
||||
"startWith": "1",
|
||||
"minValue": "1",
|
||||
"maxValue": "2147483647",
|
||||
"cache": "1",
|
||||
"cycle": false
|
||||
}
|
||||
},
|
||||
"id": {
|
||||
"name": "id",
|
||||
"type": "uuid",
|
||||
"primaryKey": false,
|
||||
"notNull": true,
|
||||
"default": "gen_random_uuid()"
|
||||
},
|
||||
"slug": {
|
||||
"name": "slug",
|
||||
"type": "varchar(255)",
|
||||
"primaryKey": false,
|
||||
"notNull": true
|
||||
},
|
||||
"show_pk": {
|
||||
"name": "show_pk",
|
||||
"type": "integer",
|
||||
"primaryKey": false,
|
||||
"notNull": false
|
||||
},
|
||||
"order": {
|
||||
"name": "order",
|
||||
"type": "integer",
|
||||
"primaryKey": false,
|
||||
"notNull": false
|
||||
},
|
||||
"season_number": {
|
||||
"name": "season_number",
|
||||
"type": "integer",
|
||||
"primaryKey": false,
|
||||
"notNull": false
|
||||
},
|
||||
"episode_number": {
|
||||
"name": "episode_number",
|
||||
"type": "integer",
|
||||
"primaryKey": false,
|
||||
"notNull": false
|
||||
},
|
||||
"type": {
|
||||
"name": "type",
|
||||
"type": "entry_type",
|
||||
"typeSchema": "kyoo",
|
||||
"primaryKey": false,
|
||||
"notNull": true
|
||||
},
|
||||
"air_date": {
|
||||
"name": "air_date",
|
||||
"type": "date",
|
||||
"primaryKey": false,
|
||||
"notNull": false
|
||||
},
|
||||
"runtime": {
|
||||
"name": "runtime",
|
||||
"type": "integer",
|
||||
"primaryKey": false,
|
||||
"notNull": false
|
||||
},
|
||||
"thumbnails": {
|
||||
"name": "thumbnails",
|
||||
"type": "jsonb",
|
||||
"primaryKey": false,
|
||||
"notNull": false
|
||||
},
|
||||
"external_id": {
|
||||
"name": "external_id",
|
||||
"type": "jsonb",
|
||||
"primaryKey": false,
|
||||
"notNull": true,
|
||||
"default": "'{}'::jsonb"
|
||||
},
|
||||
"created_at": {
|
||||
"name": "created_at",
|
||||
"type": "timestamp with time zone",
|
||||
"primaryKey": false,
|
||||
"notNull": false,
|
||||
"default": "now()"
|
||||
},
|
||||
"next_refresh": {
|
||||
"name": "next_refresh",
|
||||
"type": "timestamp with time zone",
|
||||
"primaryKey": false,
|
||||
"notNull": false
|
||||
}
|
||||
},
|
||||
"indexes": {},
|
||||
"foreignKeys": {
|
||||
"entries_show_pk_shows_pk_fk": {
|
||||
"name": "entries_show_pk_shows_pk_fk",
|
||||
"tableFrom": "entries",
|
||||
"tableTo": "shows",
|
||||
"schemaTo": "kyoo",
|
||||
"columnsFrom": ["show_pk"],
|
||||
"columnsTo": ["pk"],
|
||||
"onDelete": "cascade",
|
||||
"onUpdate": "no action"
|
||||
}
|
||||
},
|
||||
"compositePrimaryKeys": {},
|
||||
"uniqueConstraints": {
|
||||
"entries_id_unique": {
|
||||
"name": "entries_id_unique",
|
||||
"nullsNotDistinct": false,
|
||||
"columns": ["id"]
|
||||
},
|
||||
"entries_slug_unique": {
|
||||
"name": "entries_slug_unique",
|
||||
"nullsNotDistinct": false,
|
||||
"columns": ["slug"]
|
||||
},
|
||||
"entries_showPk_seasonNumber_episodeNumber_unique": {
|
||||
"name": "entries_showPk_seasonNumber_episodeNumber_unique",
|
||||
"nullsNotDistinct": false,
|
||||
"columns": ["show_pk", "season_number", "episode_number"]
|
||||
}
|
||||
},
|
||||
"policies": {},
|
||||
"checkConstraints": {
|
||||
"order_positive": {
|
||||
"name": "order_positive",
|
||||
"value": "\"entries\".\"order\" >= 0"
|
||||
}
|
||||
},
|
||||
"isRLSEnabled": false
|
||||
},
|
||||
"kyoo.entries_translation": {
|
||||
"name": "entries_translation",
|
||||
"schema": "kyoo",
|
||||
"columns": {
|
||||
"pk": {
|
||||
"name": "pk",
|
||||
"type": "integer",
|
||||
"primaryKey": false,
|
||||
"notNull": true
|
||||
},
|
||||
"language": {
|
||||
"name": "language",
|
||||
"type": "varchar(255)",
|
||||
"primaryKey": false,
|
||||
"notNull": true
|
||||
},
|
||||
"name": {
|
||||
"name": "name",
|
||||
"type": "text",
|
||||
"primaryKey": false,
|
||||
"notNull": false
|
||||
},
|
||||
"description": {
|
||||
"name": "description",
|
||||
"type": "text",
|
||||
"primaryKey": false,
|
||||
"notNull": false
|
||||
}
|
||||
},
|
||||
"indexes": {},
|
||||
"foreignKeys": {
|
||||
"entries_translation_pk_entries_pk_fk": {
|
||||
"name": "entries_translation_pk_entries_pk_fk",
|
||||
"tableFrom": "entries_translation",
|
||||
"tableTo": "entries",
|
||||
"schemaTo": "kyoo",
|
||||
"columnsFrom": ["pk"],
|
||||
"columnsTo": ["pk"],
|
||||
"onDelete": "cascade",
|
||||
"onUpdate": "no action"
|
||||
}
|
||||
},
|
||||
"compositePrimaryKeys": {
|
||||
"entries_translation_pk_language_pk": {
|
||||
"name": "entries_translation_pk_language_pk",
|
||||
"columns": ["pk", "language"]
|
||||
}
|
||||
},
|
||||
"uniqueConstraints": {},
|
||||
"policies": {},
|
||||
"checkConstraints": {},
|
||||
"isRLSEnabled": false
|
||||
},
|
||||
"kyoo.season_translation": {
|
||||
"name": "season_translation",
|
||||
"schema": "kyoo",
|
||||
"columns": {
|
||||
"pk": {
|
||||
"name": "pk",
|
||||
"type": "integer",
|
||||
"primaryKey": false,
|
||||
"notNull": true
|
||||
},
|
||||
"language": {
|
||||
"name": "language",
|
||||
"type": "varchar(255)",
|
||||
"primaryKey": false,
|
||||
"notNull": true
|
||||
},
|
||||
"name": {
|
||||
"name": "name",
|
||||
"type": "text",
|
||||
"primaryKey": false,
|
||||
"notNull": false
|
||||
},
|
||||
"description": {
|
||||
"name": "description",
|
||||
"type": "text",
|
||||
"primaryKey": false,
|
||||
"notNull": false
|
||||
},
|
||||
"poster": {
|
||||
"name": "poster",
|
||||
"type": "jsonb",
|
||||
"primaryKey": false,
|
||||
"notNull": false
|
||||
},
|
||||
"thumbnail": {
|
||||
"name": "thumbnail",
|
||||
"type": "jsonb",
|
||||
"primaryKey": false,
|
||||
"notNull": false
|
||||
},
|
||||
"logo": {
|
||||
"name": "logo",
|
||||
"type": "jsonb",
|
||||
"primaryKey": false,
|
||||
"notNull": false
|
||||
},
|
||||
"banner": {
|
||||
"name": "banner",
|
||||
"type": "jsonb",
|
||||
"primaryKey": false,
|
||||
"notNull": false
|
||||
}
|
||||
},
|
||||
"indexes": {},
|
||||
"foreignKeys": {
|
||||
"season_translation_pk_seasons_pk_fk": {
|
||||
"name": "season_translation_pk_seasons_pk_fk",
|
||||
"tableFrom": "season_translation",
|
||||
"tableTo": "seasons",
|
||||
"schemaTo": "kyoo",
|
||||
"columnsFrom": ["pk"],
|
||||
"columnsTo": ["pk"],
|
||||
"onDelete": "cascade",
|
||||
"onUpdate": "no action"
|
||||
}
|
||||
},
|
||||
"compositePrimaryKeys": {
|
||||
"season_translation_pk_language_pk": {
|
||||
"name": "season_translation_pk_language_pk",
|
||||
"columns": ["pk", "language"]
|
||||
}
|
||||
},
|
||||
"uniqueConstraints": {},
|
||||
"policies": {},
|
||||
"checkConstraints": {},
|
||||
"isRLSEnabled": false
|
||||
},
|
||||
"kyoo.seasons": {
|
||||
"name": "seasons",
|
||||
"schema": "kyoo",
|
||||
"columns": {
|
||||
"pk": {
|
||||
"name": "pk",
|
||||
"type": "integer",
|
||||
"primaryKey": true,
|
||||
"notNull": true,
|
||||
"identity": {
|
||||
"type": "always",
|
||||
"name": "seasons_pk_seq",
|
||||
"schema": "kyoo",
|
||||
"increment": "1",
|
||||
"startWith": "1",
|
||||
"minValue": "1",
|
||||
"maxValue": "2147483647",
|
||||
"cache": "1",
|
||||
"cycle": false
|
||||
}
|
||||
},
|
||||
"id": {
|
||||
"name": "id",
|
||||
"type": "uuid",
|
||||
"primaryKey": false,
|
||||
"notNull": true,
|
||||
"default": "gen_random_uuid()"
|
||||
},
|
||||
"slug": {
|
||||
"name": "slug",
|
||||
"type": "varchar(255)",
|
||||
"primaryKey": false,
|
||||
"notNull": true
|
||||
},
|
||||
"show_pk": {
|
||||
"name": "show_pk",
|
||||
"type": "integer",
|
||||
"primaryKey": false,
|
||||
"notNull": false
|
||||
},
|
||||
"season_number": {
|
||||
"name": "season_number",
|
||||
"type": "integer",
|
||||
"primaryKey": false,
|
||||
"notNull": true
|
||||
},
|
||||
"start_air": {
|
||||
"name": "start_air",
|
||||
"type": "date",
|
||||
"primaryKey": false,
|
||||
"notNull": false
|
||||
},
|
||||
"end_air": {
|
||||
"name": "end_air",
|
||||
"type": "date",
|
||||
"primaryKey": false,
|
||||
"notNull": false
|
||||
},
|
||||
"external_id": {
|
||||
"name": "external_id",
|
||||
"type": "jsonb",
|
||||
"primaryKey": false,
|
||||
"notNull": true,
|
||||
"default": "'{}'::jsonb"
|
||||
},
|
||||
"created_at": {
|
||||
"name": "created_at",
|
||||
"type": "timestamp with time zone",
|
||||
"primaryKey": false,
|
||||
"notNull": false,
|
||||
"default": "now()"
|
||||
},
|
||||
"next_refresh": {
|
||||
"name": "next_refresh",
|
||||
"type": "timestamp with time zone",
|
||||
"primaryKey": false,
|
||||
"notNull": false
|
||||
}
|
||||
},
|
||||
"indexes": {},
|
||||
"foreignKeys": {
|
||||
"seasons_show_pk_shows_pk_fk": {
|
||||
"name": "seasons_show_pk_shows_pk_fk",
|
||||
"tableFrom": "seasons",
|
||||
"tableTo": "shows",
|
||||
"schemaTo": "kyoo",
|
||||
"columnsFrom": ["show_pk"],
|
||||
"columnsTo": ["pk"],
|
||||
"onDelete": "cascade",
|
||||
"onUpdate": "no action"
|
||||
}
|
||||
},
|
||||
"compositePrimaryKeys": {},
|
||||
"uniqueConstraints": {
|
||||
"seasons_id_unique": {
|
||||
"name": "seasons_id_unique",
|
||||
"nullsNotDistinct": false,
|
||||
"columns": ["id"]
|
||||
},
|
||||
"seasons_slug_unique": {
|
||||
"name": "seasons_slug_unique",
|
||||
"nullsNotDistinct": false,
|
||||
"columns": ["slug"]
|
||||
},
|
||||
"seasons_showPk_seasonNumber_unique": {
|
||||
"name": "seasons_showPk_seasonNumber_unique",
|
||||
"nullsNotDistinct": false,
|
||||
"columns": ["show_pk", "season_number"]
|
||||
}
|
||||
},
|
||||
"policies": {},
|
||||
"checkConstraints": {},
|
||||
"isRLSEnabled": false
|
||||
},
|
||||
"kyoo.show_translations": {
|
||||
"name": "show_translations",
|
||||
"schema": "kyoo",
|
||||
"columns": {
|
||||
"pk": {
|
||||
"name": "pk",
|
||||
"type": "integer",
|
||||
"primaryKey": false,
|
||||
"notNull": true
|
||||
},
|
||||
"language": {
|
||||
"name": "language",
|
||||
"type": "varchar(255)",
|
||||
"primaryKey": false,
|
||||
"notNull": true
|
||||
},
|
||||
"name": {
|
||||
"name": "name",
|
||||
"type": "text",
|
||||
"primaryKey": false,
|
||||
"notNull": true
|
||||
},
|
||||
"description": {
|
||||
"name": "description",
|
||||
"type": "text",
|
||||
"primaryKey": false,
|
||||
"notNull": false
|
||||
},
|
||||
"tagline": {
|
||||
"name": "tagline",
|
||||
"type": "text",
|
||||
"primaryKey": false,
|
||||
"notNull": false
|
||||
},
|
||||
"aliases": {
|
||||
"name": "aliases",
|
||||
"type": "text[]",
|
||||
"primaryKey": false,
|
||||
"notNull": true
|
||||
},
|
||||
"tags": {
|
||||
"name": "tags",
|
||||
"type": "text[]",
|
||||
"primaryKey": false,
|
||||
"notNull": true
|
||||
},
|
||||
"trailer_url": {
|
||||
"name": "trailer_url",
|
||||
"type": "text",
|
||||
"primaryKey": false,
|
||||
"notNull": false
|
||||
},
|
||||
"poster": {
|
||||
"name": "poster",
|
||||
"type": "jsonb",
|
||||
"primaryKey": false,
|
||||
"notNull": false
|
||||
},
|
||||
"thumbnail": {
|
||||
"name": "thumbnail",
|
||||
"type": "jsonb",
|
||||
"primaryKey": false,
|
||||
"notNull": false
|
||||
},
|
||||
"banner": {
|
||||
"name": "banner",
|
||||
"type": "jsonb",
|
||||
"primaryKey": false,
|
||||
"notNull": false
|
||||
},
|
||||
"logo": {
|
||||
"name": "logo",
|
||||
"type": "jsonb",
|
||||
"primaryKey": false,
|
||||
"notNull": false
|
||||
}
|
||||
},
|
||||
"indexes": {},
|
||||
"foreignKeys": {
|
||||
"show_translations_pk_shows_pk_fk": {
|
||||
"name": "show_translations_pk_shows_pk_fk",
|
||||
"tableFrom": "show_translations",
|
||||
"tableTo": "shows",
|
||||
"schemaTo": "kyoo",
|
||||
"columnsFrom": ["pk"],
|
||||
"columnsTo": ["pk"],
|
||||
"onDelete": "cascade",
|
||||
"onUpdate": "no action"
|
||||
}
|
||||
},
|
||||
"compositePrimaryKeys": {
|
||||
"show_translations_pk_language_pk": {
|
||||
"name": "show_translations_pk_language_pk",
|
||||
"columns": ["pk", "language"]
|
||||
}
|
||||
},
|
||||
"uniqueConstraints": {},
|
||||
"policies": {},
|
||||
"checkConstraints": {},
|
||||
"isRLSEnabled": false
|
||||
},
|
||||
"kyoo.shows": {
|
||||
"name": "shows",
|
||||
"schema": "kyoo",
|
||||
"columns": {
|
||||
"pk": {
|
||||
"name": "pk",
|
||||
"type": "integer",
|
||||
"primaryKey": true,
|
||||
"notNull": true,
|
||||
"identity": {
|
||||
"type": "always",
|
||||
"name": "shows_pk_seq",
|
||||
"schema": "kyoo",
|
||||
"increment": "1",
|
||||
"startWith": "1",
|
||||
"minValue": "1",
|
||||
"maxValue": "2147483647",
|
||||
"cache": "1",
|
||||
"cycle": false
|
||||
}
|
||||
},
|
||||
"id": {
|
||||
"name": "id",
|
||||
"type": "uuid",
|
||||
"primaryKey": false,
|
||||
"notNull": true,
|
||||
"default": "gen_random_uuid()"
|
||||
},
|
||||
"slug": {
|
||||
"name": "slug",
|
||||
"type": "varchar(255)",
|
||||
"primaryKey": false,
|
||||
"notNull": true
|
||||
},
|
||||
"kind": {
|
||||
"name": "kind",
|
||||
"type": "show_kind",
|
||||
"typeSchema": "kyoo",
|
||||
"primaryKey": false,
|
||||
"notNull": true
|
||||
},
|
||||
"genres": {
|
||||
"name": "genres",
|
||||
"type": "genres[]",
|
||||
"primaryKey": false,
|
||||
"notNull": true
|
||||
},
|
||||
"rating": {
|
||||
"name": "rating",
|
||||
"type": "smallint",
|
||||
"primaryKey": false,
|
||||
"notNull": false
|
||||
},
|
||||
"runtime": {
|
||||
"name": "runtime",
|
||||
"type": "integer",
|
||||
"primaryKey": false,
|
||||
"notNull": false
|
||||
},
|
||||
"status": {
|
||||
"name": "status",
|
||||
"type": "show_status",
|
||||
"typeSchema": "kyoo",
|
||||
"primaryKey": false,
|
||||
"notNull": true
|
||||
},
|
||||
"start_air": {
|
||||
"name": "start_air",
|
||||
"type": "date",
|
||||
"primaryKey": false,
|
||||
"notNull": false
|
||||
},
|
||||
"end_air": {
|
||||
"name": "end_air",
|
||||
"type": "date",
|
||||
"primaryKey": false,
|
||||
"notNull": false
|
||||
},
|
||||
"original_language": {
|
||||
"name": "original_language",
|
||||
"type": "varchar(255)",
|
||||
"primaryKey": false,
|
||||
"notNull": false
|
||||
},
|
||||
"external_id": {
|
||||
"name": "external_id",
|
||||
"type": "jsonb",
|
||||
"primaryKey": false,
|
||||
"notNull": true,
|
||||
"default": "'{}'::jsonb"
|
||||
},
|
||||
"created_at": {
|
||||
"name": "created_at",
|
||||
"type": "timestamp with time zone",
|
||||
"primaryKey": false,
|
||||
"notNull": true,
|
||||
"default": "now()"
|
||||
},
|
||||
"next_refresh": {
|
||||
"name": "next_refresh",
|
||||
"type": "timestamp with time zone",
|
||||
"primaryKey": false,
|
||||
"notNull": true
|
||||
}
|
||||
},
|
||||
"indexes": {},
|
||||
"foreignKeys": {},
|
||||
"compositePrimaryKeys": {},
|
||||
"uniqueConstraints": {
|
||||
"shows_id_unique": {
|
||||
"name": "shows_id_unique",
|
||||
"nullsNotDistinct": false,
|
||||
"columns": ["id"]
|
||||
},
|
||||
"shows_slug_unique": {
|
||||
"name": "shows_slug_unique",
|
||||
"nullsNotDistinct": false,
|
||||
"columns": ["slug"]
|
||||
}
|
||||
},
|
||||
"policies": {},
|
||||
"checkConstraints": {
|
||||
"rating_valid": {
|
||||
"name": "rating_valid",
|
||||
"value": "\"shows\".\"rating\" between 0 and 100"
|
||||
},
|
||||
"runtime_valid": {
|
||||
"name": "runtime_valid",
|
||||
"value": "\"shows\".\"runtime\" >= 0"
|
||||
}
|
||||
},
|
||||
"isRLSEnabled": false
|
||||
},
|
||||
"kyoo.videos": {
|
||||
"name": "videos",
|
||||
"schema": "kyoo",
|
||||
"columns": {
|
||||
"pk": {
|
||||
"name": "pk",
|
||||
"type": "integer",
|
||||
"primaryKey": true,
|
||||
"notNull": true,
|
||||
"identity": {
|
||||
"type": "always",
|
||||
"name": "videos_pk_seq",
|
||||
"schema": "kyoo",
|
||||
"increment": "1",
|
||||
"startWith": "1",
|
||||
"minValue": "1",
|
||||
"maxValue": "2147483647",
|
||||
"cache": "1",
|
||||
"cycle": false
|
||||
}
|
||||
},
|
||||
"id": {
|
||||
"name": "id",
|
||||
"type": "uuid",
|
||||
"primaryKey": false,
|
||||
"notNull": true,
|
||||
"default": "gen_random_uuid()"
|
||||
},
|
||||
"slug": {
|
||||
"name": "slug",
|
||||
"type": "varchar(255)",
|
||||
"primaryKey": false,
|
||||
"notNull": true
|
||||
},
|
||||
"path": {
|
||||
"name": "path",
|
||||
"type": "text",
|
||||
"primaryKey": false,
|
||||
"notNull": true
|
||||
},
|
||||
"rendering": {
|
||||
"name": "rendering",
|
||||
"type": "text",
|
||||
"primaryKey": false,
|
||||
"notNull": true
|
||||
},
|
||||
"part": {
|
||||
"name": "part",
|
||||
"type": "integer",
|
||||
"primaryKey": false,
|
||||
"notNull": false
|
||||
},
|
||||
"version": {
|
||||
"name": "version",
|
||||
"type": "integer",
|
||||
"primaryKey": false,
|
||||
"notNull": true,
|
||||
"default": 1
|
||||
},
|
||||
"created_at": {
|
||||
"name": "created_at",
|
||||
"type": "timestamp with time zone",
|
||||
"primaryKey": false,
|
||||
"notNull": true,
|
||||
"default": "now()"
|
||||
}
|
||||
},
|
||||
"indexes": {},
|
||||
"foreignKeys": {},
|
||||
"compositePrimaryKeys": {},
|
||||
"uniqueConstraints": {
|
||||
"videos_id_unique": {
|
||||
"name": "videos_id_unique",
|
||||
"nullsNotDistinct": false,
|
||||
"columns": ["id"]
|
||||
},
|
||||
"videos_slug_unique": {
|
||||
"name": "videos_slug_unique",
|
||||
"nullsNotDistinct": false,
|
||||
"columns": ["slug"]
|
||||
},
|
||||
"videos_path_unique": {
|
||||
"name": "videos_path_unique",
|
||||
"nullsNotDistinct": false,
|
||||
"columns": ["path"]
|
||||
}
|
||||
},
|
||||
"policies": {},
|
||||
"checkConstraints": {
|
||||
"part_pos": {
|
||||
"name": "part_pos",
|
||||
"value": "\"videos\".\"part\" >= 0"
|
||||
},
|
||||
"version_pos": {
|
||||
"name": "version_pos",
|
||||
"value": "\"videos\".\"version\" >= 0"
|
||||
}
|
||||
},
|
||||
"isRLSEnabled": false
|
||||
}
|
||||
},
|
||||
"enums": {
|
||||
"kyoo.entry_type": {
|
||||
"name": "entry_type",
|
||||
"schema": "kyoo",
|
||||
"values": ["unknown", "episode", "movie", "special", "extra"]
|
||||
},
|
||||
"kyoo.genres": {
|
||||
"name": "genres",
|
||||
"schema": "kyoo",
|
||||
"values": [
|
||||
"action",
|
||||
"adventure",
|
||||
"animation",
|
||||
"comedy",
|
||||
"crime",
|
||||
"documentary",
|
||||
"drama",
|
||||
"family",
|
||||
"fantasy",
|
||||
"history",
|
||||
"horror",
|
||||
"music",
|
||||
"mystery",
|
||||
"romance",
|
||||
"science-fiction",
|
||||
"thriller",
|
||||
"war",
|
||||
"western",
|
||||
"kids",
|
||||
"reality",
|
||||
"politics",
|
||||
"soap",
|
||||
"talk"
|
||||
]
|
||||
},
|
||||
"kyoo.show_kind": {
|
||||
"name": "show_kind",
|
||||
"schema": "kyoo",
|
||||
"values": ["serie", "movie"]
|
||||
},
|
||||
"kyoo.show_status": {
|
||||
"name": "show_status",
|
||||
"schema": "kyoo",
|
||||
"values": ["unknown", "finished", "airing", "planned"]
|
||||
}
|
||||
},
|
||||
"schemas": {
|
||||
"kyoo": "kyoo"
|
||||
},
|
||||
"sequences": {},
|
||||
"roles": {},
|
||||
"policies": {},
|
||||
"views": {},
|
||||
"_meta": {
|
||||
"columns": {},
|
||||
"schemas": {},
|
||||
"tables": {}
|
||||
}
|
||||
}
|
||||
788
api/drizzle/meta/0003_snapshot.json
Normal file
788
api/drizzle/meta/0003_snapshot.json
Normal file
@@ -0,0 +1,788 @@
|
||||
{
|
||||
"id": "2210fd60-8e6a-4503-a2b3-56cc7f3cf15a",
|
||||
"prevId": "d0f6c500-aa2b-4592-aa31-db646817f708",
|
||||
"version": "7",
|
||||
"dialect": "postgresql",
|
||||
"tables": {
|
||||
"kyoo.entries": {
|
||||
"name": "entries",
|
||||
"schema": "kyoo",
|
||||
"columns": {
|
||||
"pk": {
|
||||
"name": "pk",
|
||||
"type": "integer",
|
||||
"primaryKey": true,
|
||||
"notNull": true,
|
||||
"identity": {
|
||||
"type": "always",
|
||||
"name": "entries_pk_seq",
|
||||
"schema": "kyoo",
|
||||
"increment": "1",
|
||||
"startWith": "1",
|
||||
"minValue": "1",
|
||||
"maxValue": "2147483647",
|
||||
"cache": "1",
|
||||
"cycle": false
|
||||
}
|
||||
},
|
||||
"id": {
|
||||
"name": "id",
|
||||
"type": "uuid",
|
||||
"primaryKey": false,
|
||||
"notNull": true,
|
||||
"default": "gen_random_uuid()"
|
||||
},
|
||||
"slug": {
|
||||
"name": "slug",
|
||||
"type": "varchar(255)",
|
||||
"primaryKey": false,
|
||||
"notNull": true
|
||||
},
|
||||
"show_pk": {
|
||||
"name": "show_pk",
|
||||
"type": "integer",
|
||||
"primaryKey": false,
|
||||
"notNull": false
|
||||
},
|
||||
"order": {
|
||||
"name": "order",
|
||||
"type": "real",
|
||||
"primaryKey": false,
|
||||
"notNull": false
|
||||
},
|
||||
"season_number": {
|
||||
"name": "season_number",
|
||||
"type": "integer",
|
||||
"primaryKey": false,
|
||||
"notNull": false
|
||||
},
|
||||
"episode_number": {
|
||||
"name": "episode_number",
|
||||
"type": "integer",
|
||||
"primaryKey": false,
|
||||
"notNull": false
|
||||
},
|
||||
"type": {
|
||||
"name": "type",
|
||||
"type": "entry_type",
|
||||
"typeSchema": "kyoo",
|
||||
"primaryKey": false,
|
||||
"notNull": true
|
||||
},
|
||||
"air_date": {
|
||||
"name": "air_date",
|
||||
"type": "date",
|
||||
"primaryKey": false,
|
||||
"notNull": false
|
||||
},
|
||||
"runtime": {
|
||||
"name": "runtime",
|
||||
"type": "integer",
|
||||
"primaryKey": false,
|
||||
"notNull": false
|
||||
},
|
||||
"thumbnails": {
|
||||
"name": "thumbnails",
|
||||
"type": "jsonb",
|
||||
"primaryKey": false,
|
||||
"notNull": false
|
||||
},
|
||||
"external_id": {
|
||||
"name": "external_id",
|
||||
"type": "jsonb",
|
||||
"primaryKey": false,
|
||||
"notNull": true,
|
||||
"default": "'{}'::jsonb"
|
||||
},
|
||||
"created_at": {
|
||||
"name": "created_at",
|
||||
"type": "timestamp with time zone",
|
||||
"primaryKey": false,
|
||||
"notNull": false,
|
||||
"default": "now()"
|
||||
},
|
||||
"next_refresh": {
|
||||
"name": "next_refresh",
|
||||
"type": "timestamp with time zone",
|
||||
"primaryKey": false,
|
||||
"notNull": false
|
||||
}
|
||||
},
|
||||
"indexes": {},
|
||||
"foreignKeys": {
|
||||
"entries_show_pk_shows_pk_fk": {
|
||||
"name": "entries_show_pk_shows_pk_fk",
|
||||
"tableFrom": "entries",
|
||||
"tableTo": "shows",
|
||||
"schemaTo": "kyoo",
|
||||
"columnsFrom": ["show_pk"],
|
||||
"columnsTo": ["pk"],
|
||||
"onDelete": "cascade",
|
||||
"onUpdate": "no action"
|
||||
}
|
||||
},
|
||||
"compositePrimaryKeys": {},
|
||||
"uniqueConstraints": {
|
||||
"entries_id_unique": {
|
||||
"name": "entries_id_unique",
|
||||
"nullsNotDistinct": false,
|
||||
"columns": ["id"]
|
||||
},
|
||||
"entries_slug_unique": {
|
||||
"name": "entries_slug_unique",
|
||||
"nullsNotDistinct": false,
|
||||
"columns": ["slug"]
|
||||
},
|
||||
"entries_showPk_seasonNumber_episodeNumber_unique": {
|
||||
"name": "entries_showPk_seasonNumber_episodeNumber_unique",
|
||||
"nullsNotDistinct": false,
|
||||
"columns": ["show_pk", "season_number", "episode_number"]
|
||||
}
|
||||
},
|
||||
"policies": {},
|
||||
"checkConstraints": {
|
||||
"order_positive": {
|
||||
"name": "order_positive",
|
||||
"value": "\"entries\".\"order\" >= 0"
|
||||
}
|
||||
},
|
||||
"isRLSEnabled": false
|
||||
},
|
||||
"kyoo.entries_translation": {
|
||||
"name": "entries_translation",
|
||||
"schema": "kyoo",
|
||||
"columns": {
|
||||
"pk": {
|
||||
"name": "pk",
|
||||
"type": "integer",
|
||||
"primaryKey": false,
|
||||
"notNull": true
|
||||
},
|
||||
"language": {
|
||||
"name": "language",
|
||||
"type": "varchar(255)",
|
||||
"primaryKey": false,
|
||||
"notNull": true
|
||||
},
|
||||
"name": {
|
||||
"name": "name",
|
||||
"type": "text",
|
||||
"primaryKey": false,
|
||||
"notNull": false
|
||||
},
|
||||
"description": {
|
||||
"name": "description",
|
||||
"type": "text",
|
||||
"primaryKey": false,
|
||||
"notNull": false
|
||||
},
|
||||
"tagline": {
|
||||
"name": "tagline",
|
||||
"type": "text",
|
||||
"primaryKey": false,
|
||||
"notNull": false
|
||||
}
|
||||
},
|
||||
"indexes": {},
|
||||
"foreignKeys": {
|
||||
"entries_translation_pk_entries_pk_fk": {
|
||||
"name": "entries_translation_pk_entries_pk_fk",
|
||||
"tableFrom": "entries_translation",
|
||||
"tableTo": "entries",
|
||||
"schemaTo": "kyoo",
|
||||
"columnsFrom": ["pk"],
|
||||
"columnsTo": ["pk"],
|
||||
"onDelete": "cascade",
|
||||
"onUpdate": "no action"
|
||||
}
|
||||
},
|
||||
"compositePrimaryKeys": {
|
||||
"entries_translation_pk_language_pk": {
|
||||
"name": "entries_translation_pk_language_pk",
|
||||
"columns": ["pk", "language"]
|
||||
}
|
||||
},
|
||||
"uniqueConstraints": {},
|
||||
"policies": {},
|
||||
"checkConstraints": {},
|
||||
"isRLSEnabled": false
|
||||
},
|
||||
"kyoo.season_translation": {
|
||||
"name": "season_translation",
|
||||
"schema": "kyoo",
|
||||
"columns": {
|
||||
"pk": {
|
||||
"name": "pk",
|
||||
"type": "integer",
|
||||
"primaryKey": false,
|
||||
"notNull": true
|
||||
},
|
||||
"language": {
|
||||
"name": "language",
|
||||
"type": "varchar(255)",
|
||||
"primaryKey": false,
|
||||
"notNull": true
|
||||
},
|
||||
"name": {
|
||||
"name": "name",
|
||||
"type": "text",
|
||||
"primaryKey": false,
|
||||
"notNull": false
|
||||
},
|
||||
"description": {
|
||||
"name": "description",
|
||||
"type": "text",
|
||||
"primaryKey": false,
|
||||
"notNull": false
|
||||
},
|
||||
"poster": {
|
||||
"name": "poster",
|
||||
"type": "jsonb",
|
||||
"primaryKey": false,
|
||||
"notNull": false
|
||||
},
|
||||
"thumbnail": {
|
||||
"name": "thumbnail",
|
||||
"type": "jsonb",
|
||||
"primaryKey": false,
|
||||
"notNull": false
|
||||
},
|
||||
"banner": {
|
||||
"name": "banner",
|
||||
"type": "jsonb",
|
||||
"primaryKey": false,
|
||||
"notNull": false
|
||||
}
|
||||
},
|
||||
"indexes": {},
|
||||
"foreignKeys": {
|
||||
"season_translation_pk_seasons_pk_fk": {
|
||||
"name": "season_translation_pk_seasons_pk_fk",
|
||||
"tableFrom": "season_translation",
|
||||
"tableTo": "seasons",
|
||||
"schemaTo": "kyoo",
|
||||
"columnsFrom": ["pk"],
|
||||
"columnsTo": ["pk"],
|
||||
"onDelete": "cascade",
|
||||
"onUpdate": "no action"
|
||||
}
|
||||
},
|
||||
"compositePrimaryKeys": {
|
||||
"season_translation_pk_language_pk": {
|
||||
"name": "season_translation_pk_language_pk",
|
||||
"columns": ["pk", "language"]
|
||||
}
|
||||
},
|
||||
"uniqueConstraints": {},
|
||||
"policies": {},
|
||||
"checkConstraints": {},
|
||||
"isRLSEnabled": false
|
||||
},
|
||||
"kyoo.seasons": {
|
||||
"name": "seasons",
|
||||
"schema": "kyoo",
|
||||
"columns": {
|
||||
"pk": {
|
||||
"name": "pk",
|
||||
"type": "integer",
|
||||
"primaryKey": true,
|
||||
"notNull": true,
|
||||
"identity": {
|
||||
"type": "always",
|
||||
"name": "seasons_pk_seq",
|
||||
"schema": "kyoo",
|
||||
"increment": "1",
|
||||
"startWith": "1",
|
||||
"minValue": "1",
|
||||
"maxValue": "2147483647",
|
||||
"cache": "1",
|
||||
"cycle": false
|
||||
}
|
||||
},
|
||||
"id": {
|
||||
"name": "id",
|
||||
"type": "uuid",
|
||||
"primaryKey": false,
|
||||
"notNull": true,
|
||||
"default": "gen_random_uuid()"
|
||||
},
|
||||
"slug": {
|
||||
"name": "slug",
|
||||
"type": "varchar(255)",
|
||||
"primaryKey": false,
|
||||
"notNull": true
|
||||
},
|
||||
"show_pk": {
|
||||
"name": "show_pk",
|
||||
"type": "integer",
|
||||
"primaryKey": false,
|
||||
"notNull": false
|
||||
},
|
||||
"season_number": {
|
||||
"name": "season_number",
|
||||
"type": "integer",
|
||||
"primaryKey": false,
|
||||
"notNull": true
|
||||
},
|
||||
"start_air": {
|
||||
"name": "start_air",
|
||||
"type": "date",
|
||||
"primaryKey": false,
|
||||
"notNull": false
|
||||
},
|
||||
"end_air": {
|
||||
"name": "end_air",
|
||||
"type": "date",
|
||||
"primaryKey": false,
|
||||
"notNull": false
|
||||
},
|
||||
"external_id": {
|
||||
"name": "external_id",
|
||||
"type": "jsonb",
|
||||
"primaryKey": false,
|
||||
"notNull": true,
|
||||
"default": "'{}'::jsonb"
|
||||
},
|
||||
"created_at": {
|
||||
"name": "created_at",
|
||||
"type": "timestamp with time zone",
|
||||
"primaryKey": false,
|
||||
"notNull": false,
|
||||
"default": "now()"
|
||||
},
|
||||
"next_refresh": {
|
||||
"name": "next_refresh",
|
||||
"type": "timestamp with time zone",
|
||||
"primaryKey": false,
|
||||
"notNull": false
|
||||
}
|
||||
},
|
||||
"indexes": {},
|
||||
"foreignKeys": {
|
||||
"seasons_show_pk_shows_pk_fk": {
|
||||
"name": "seasons_show_pk_shows_pk_fk",
|
||||
"tableFrom": "seasons",
|
||||
"tableTo": "shows",
|
||||
"schemaTo": "kyoo",
|
||||
"columnsFrom": ["show_pk"],
|
||||
"columnsTo": ["pk"],
|
||||
"onDelete": "cascade",
|
||||
"onUpdate": "no action"
|
||||
}
|
||||
},
|
||||
"compositePrimaryKeys": {},
|
||||
"uniqueConstraints": {
|
||||
"seasons_id_unique": {
|
||||
"name": "seasons_id_unique",
|
||||
"nullsNotDistinct": false,
|
||||
"columns": ["id"]
|
||||
},
|
||||
"seasons_slug_unique": {
|
||||
"name": "seasons_slug_unique",
|
||||
"nullsNotDistinct": false,
|
||||
"columns": ["slug"]
|
||||
},
|
||||
"seasons_showPk_seasonNumber_unique": {
|
||||
"name": "seasons_showPk_seasonNumber_unique",
|
||||
"nullsNotDistinct": false,
|
||||
"columns": ["show_pk", "season_number"]
|
||||
}
|
||||
},
|
||||
"policies": {},
|
||||
"checkConstraints": {},
|
||||
"isRLSEnabled": false
|
||||
},
|
||||
"kyoo.show_translations": {
|
||||
"name": "show_translations",
|
||||
"schema": "kyoo",
|
||||
"columns": {
|
||||
"pk": {
|
||||
"name": "pk",
|
||||
"type": "integer",
|
||||
"primaryKey": false,
|
||||
"notNull": true
|
||||
},
|
||||
"language": {
|
||||
"name": "language",
|
||||
"type": "varchar(255)",
|
||||
"primaryKey": false,
|
||||
"notNull": true
|
||||
},
|
||||
"name": {
|
||||
"name": "name",
|
||||
"type": "text",
|
||||
"primaryKey": false,
|
||||
"notNull": true
|
||||
},
|
||||
"description": {
|
||||
"name": "description",
|
||||
"type": "text",
|
||||
"primaryKey": false,
|
||||
"notNull": false
|
||||
},
|
||||
"tagline": {
|
||||
"name": "tagline",
|
||||
"type": "text",
|
||||
"primaryKey": false,
|
||||
"notNull": false
|
||||
},
|
||||
"aliases": {
|
||||
"name": "aliases",
|
||||
"type": "text[]",
|
||||
"primaryKey": false,
|
||||
"notNull": true
|
||||
},
|
||||
"tags": {
|
||||
"name": "tags",
|
||||
"type": "text[]",
|
||||
"primaryKey": false,
|
||||
"notNull": true
|
||||
},
|
||||
"trailer_url": {
|
||||
"name": "trailer_url",
|
||||
"type": "text",
|
||||
"primaryKey": false,
|
||||
"notNull": false
|
||||
},
|
||||
"poster": {
|
||||
"name": "poster",
|
||||
"type": "jsonb",
|
||||
"primaryKey": false,
|
||||
"notNull": false
|
||||
},
|
||||
"thumbnail": {
|
||||
"name": "thumbnail",
|
||||
"type": "jsonb",
|
||||
"primaryKey": false,
|
||||
"notNull": false
|
||||
},
|
||||
"banner": {
|
||||
"name": "banner",
|
||||
"type": "jsonb",
|
||||
"primaryKey": false,
|
||||
"notNull": false
|
||||
},
|
||||
"logo": {
|
||||
"name": "logo",
|
||||
"type": "jsonb",
|
||||
"primaryKey": false,
|
||||
"notNull": false
|
||||
}
|
||||
},
|
||||
"indexes": {},
|
||||
"foreignKeys": {
|
||||
"show_translations_pk_shows_pk_fk": {
|
||||
"name": "show_translations_pk_shows_pk_fk",
|
||||
"tableFrom": "show_translations",
|
||||
"tableTo": "shows",
|
||||
"schemaTo": "kyoo",
|
||||
"columnsFrom": ["pk"],
|
||||
"columnsTo": ["pk"],
|
||||
"onDelete": "cascade",
|
||||
"onUpdate": "no action"
|
||||
}
|
||||
},
|
||||
"compositePrimaryKeys": {
|
||||
"show_translations_pk_language_pk": {
|
||||
"name": "show_translations_pk_language_pk",
|
||||
"columns": ["pk", "language"]
|
||||
}
|
||||
},
|
||||
"uniqueConstraints": {},
|
||||
"policies": {},
|
||||
"checkConstraints": {},
|
||||
"isRLSEnabled": false
|
||||
},
|
||||
"kyoo.shows": {
|
||||
"name": "shows",
|
||||
"schema": "kyoo",
|
||||
"columns": {
|
||||
"pk": {
|
||||
"name": "pk",
|
||||
"type": "integer",
|
||||
"primaryKey": true,
|
||||
"notNull": true,
|
||||
"identity": {
|
||||
"type": "always",
|
||||
"name": "shows_pk_seq",
|
||||
"schema": "kyoo",
|
||||
"increment": "1",
|
||||
"startWith": "1",
|
||||
"minValue": "1",
|
||||
"maxValue": "2147483647",
|
||||
"cache": "1",
|
||||
"cycle": false
|
||||
}
|
||||
},
|
||||
"id": {
|
||||
"name": "id",
|
||||
"type": "uuid",
|
||||
"primaryKey": false,
|
||||
"notNull": true,
|
||||
"default": "gen_random_uuid()"
|
||||
},
|
||||
"slug": {
|
||||
"name": "slug",
|
||||
"type": "varchar(255)",
|
||||
"primaryKey": false,
|
||||
"notNull": true
|
||||
},
|
||||
"kind": {
|
||||
"name": "kind",
|
||||
"type": "show_kind",
|
||||
"typeSchema": "kyoo",
|
||||
"primaryKey": false,
|
||||
"notNull": true
|
||||
},
|
||||
"genres": {
|
||||
"name": "genres",
|
||||
"type": "genres[]",
|
||||
"primaryKey": false,
|
||||
"notNull": true
|
||||
},
|
||||
"rating": {
|
||||
"name": "rating",
|
||||
"type": "smallint",
|
||||
"primaryKey": false,
|
||||
"notNull": false
|
||||
},
|
||||
"runtime": {
|
||||
"name": "runtime",
|
||||
"type": "integer",
|
||||
"primaryKey": false,
|
||||
"notNull": false
|
||||
},
|
||||
"status": {
|
||||
"name": "status",
|
||||
"type": "show_status",
|
||||
"typeSchema": "kyoo",
|
||||
"primaryKey": false,
|
||||
"notNull": true
|
||||
},
|
||||
"start_air": {
|
||||
"name": "start_air",
|
||||
"type": "date",
|
||||
"primaryKey": false,
|
||||
"notNull": false
|
||||
},
|
||||
"end_air": {
|
||||
"name": "end_air",
|
||||
"type": "date",
|
||||
"primaryKey": false,
|
||||
"notNull": false
|
||||
},
|
||||
"original_language": {
|
||||
"name": "original_language",
|
||||
"type": "varchar(255)",
|
||||
"primaryKey": false,
|
||||
"notNull": false
|
||||
},
|
||||
"external_id": {
|
||||
"name": "external_id",
|
||||
"type": "jsonb",
|
||||
"primaryKey": false,
|
||||
"notNull": true,
|
||||
"default": "'{}'::jsonb"
|
||||
},
|
||||
"created_at": {
|
||||
"name": "created_at",
|
||||
"type": "timestamp with time zone",
|
||||
"primaryKey": false,
|
||||
"notNull": true,
|
||||
"default": "now()"
|
||||
},
|
||||
"next_refresh": {
|
||||
"name": "next_refresh",
|
||||
"type": "timestamp with time zone",
|
||||
"primaryKey": false,
|
||||
"notNull": true
|
||||
}
|
||||
},
|
||||
"indexes": {},
|
||||
"foreignKeys": {},
|
||||
"compositePrimaryKeys": {},
|
||||
"uniqueConstraints": {
|
||||
"shows_id_unique": {
|
||||
"name": "shows_id_unique",
|
||||
"nullsNotDistinct": false,
|
||||
"columns": ["id"]
|
||||
},
|
||||
"shows_slug_unique": {
|
||||
"name": "shows_slug_unique",
|
||||
"nullsNotDistinct": false,
|
||||
"columns": ["slug"]
|
||||
}
|
||||
},
|
||||
"policies": {},
|
||||
"checkConstraints": {
|
||||
"rating_valid": {
|
||||
"name": "rating_valid",
|
||||
"value": "\"shows\".\"rating\" between 0 and 100"
|
||||
},
|
||||
"runtime_valid": {
|
||||
"name": "runtime_valid",
|
||||
"value": "\"shows\".\"runtime\" >= 0"
|
||||
}
|
||||
},
|
||||
"isRLSEnabled": false
|
||||
},
|
||||
"kyoo.videos": {
|
||||
"name": "videos",
|
||||
"schema": "kyoo",
|
||||
"columns": {
|
||||
"pk": {
|
||||
"name": "pk",
|
||||
"type": "integer",
|
||||
"primaryKey": true,
|
||||
"notNull": true,
|
||||
"identity": {
|
||||
"type": "always",
|
||||
"name": "videos_pk_seq",
|
||||
"schema": "kyoo",
|
||||
"increment": "1",
|
||||
"startWith": "1",
|
||||
"minValue": "1",
|
||||
"maxValue": "2147483647",
|
||||
"cache": "1",
|
||||
"cycle": false
|
||||
}
|
||||
},
|
||||
"id": {
|
||||
"name": "id",
|
||||
"type": "uuid",
|
||||
"primaryKey": false,
|
||||
"notNull": true,
|
||||
"default": "gen_random_uuid()"
|
||||
},
|
||||
"slug": {
|
||||
"name": "slug",
|
||||
"type": "varchar(255)",
|
||||
"primaryKey": false,
|
||||
"notNull": true
|
||||
},
|
||||
"path": {
|
||||
"name": "path",
|
||||
"type": "text",
|
||||
"primaryKey": false,
|
||||
"notNull": true
|
||||
},
|
||||
"rendering": {
|
||||
"name": "rendering",
|
||||
"type": "text",
|
||||
"primaryKey": false,
|
||||
"notNull": true
|
||||
},
|
||||
"part": {
|
||||
"name": "part",
|
||||
"type": "integer",
|
||||
"primaryKey": false,
|
||||
"notNull": false
|
||||
},
|
||||
"version": {
|
||||
"name": "version",
|
||||
"type": "integer",
|
||||
"primaryKey": false,
|
||||
"notNull": true,
|
||||
"default": 1
|
||||
},
|
||||
"created_at": {
|
||||
"name": "created_at",
|
||||
"type": "timestamp with time zone",
|
||||
"primaryKey": false,
|
||||
"notNull": true,
|
||||
"default": "now()"
|
||||
}
|
||||
},
|
||||
"indexes": {},
|
||||
"foreignKeys": {},
|
||||
"compositePrimaryKeys": {},
|
||||
"uniqueConstraints": {
|
||||
"videos_id_unique": {
|
||||
"name": "videos_id_unique",
|
||||
"nullsNotDistinct": false,
|
||||
"columns": ["id"]
|
||||
},
|
||||
"videos_slug_unique": {
|
||||
"name": "videos_slug_unique",
|
||||
"nullsNotDistinct": false,
|
||||
"columns": ["slug"]
|
||||
},
|
||||
"videos_path_unique": {
|
||||
"name": "videos_path_unique",
|
||||
"nullsNotDistinct": false,
|
||||
"columns": ["path"]
|
||||
}
|
||||
},
|
||||
"policies": {},
|
||||
"checkConstraints": {
|
||||
"part_pos": {
|
||||
"name": "part_pos",
|
||||
"value": "\"videos\".\"part\" >= 0"
|
||||
},
|
||||
"version_pos": {
|
||||
"name": "version_pos",
|
||||
"value": "\"videos\".\"version\" >= 0"
|
||||
}
|
||||
},
|
||||
"isRLSEnabled": false
|
||||
}
|
||||
},
|
||||
"enums": {
|
||||
"kyoo.entry_type": {
|
||||
"name": "entry_type",
|
||||
"schema": "kyoo",
|
||||
"values": ["unknown", "episode", "movie", "special", "extra"]
|
||||
},
|
||||
"kyoo.genres": {
|
||||
"name": "genres",
|
||||
"schema": "kyoo",
|
||||
"values": [
|
||||
"action",
|
||||
"adventure",
|
||||
"animation",
|
||||
"comedy",
|
||||
"crime",
|
||||
"documentary",
|
||||
"drama",
|
||||
"family",
|
||||
"fantasy",
|
||||
"history",
|
||||
"horror",
|
||||
"music",
|
||||
"mystery",
|
||||
"romance",
|
||||
"science-fiction",
|
||||
"thriller",
|
||||
"war",
|
||||
"western",
|
||||
"kids",
|
||||
"reality",
|
||||
"politics",
|
||||
"soap",
|
||||
"talk"
|
||||
]
|
||||
},
|
||||
"kyoo.show_kind": {
|
||||
"name": "show_kind",
|
||||
"schema": "kyoo",
|
||||
"values": ["serie", "movie"]
|
||||
},
|
||||
"kyoo.show_status": {
|
||||
"name": "show_status",
|
||||
"schema": "kyoo",
|
||||
"values": ["unknown", "finished", "airing", "planned"]
|
||||
}
|
||||
},
|
||||
"schemas": {
|
||||
"kyoo": "kyoo"
|
||||
},
|
||||
"sequences": {},
|
||||
"roles": {},
|
||||
"policies": {},
|
||||
"views": {},
|
||||
"_meta": {
|
||||
"columns": {},
|
||||
"schemas": {},
|
||||
"tables": {}
|
||||
}
|
||||
}
|
||||
853
api/drizzle/meta/0004_snapshot.json
Normal file
853
api/drizzle/meta/0004_snapshot.json
Normal file
@@ -0,0 +1,853 @@
|
||||
{
|
||||
"id": "0d5d6d22-dc13-4f3d-9975-cb7b38f628d4",
|
||||
"prevId": "2210fd60-8e6a-4503-a2b3-56cc7f3cf15a",
|
||||
"version": "7",
|
||||
"dialect": "postgresql",
|
||||
"tables": {
|
||||
"kyoo.entries": {
|
||||
"name": "entries",
|
||||
"schema": "kyoo",
|
||||
"columns": {
|
||||
"pk": {
|
||||
"name": "pk",
|
||||
"type": "integer",
|
||||
"primaryKey": true,
|
||||
"notNull": true,
|
||||
"identity": {
|
||||
"type": "always",
|
||||
"name": "entries_pk_seq",
|
||||
"schema": "kyoo",
|
||||
"increment": "1",
|
||||
"startWith": "1",
|
||||
"minValue": "1",
|
||||
"maxValue": "2147483647",
|
||||
"cache": "1",
|
||||
"cycle": false
|
||||
}
|
||||
},
|
||||
"id": {
|
||||
"name": "id",
|
||||
"type": "uuid",
|
||||
"primaryKey": false,
|
||||
"notNull": true,
|
||||
"default": "gen_random_uuid()"
|
||||
},
|
||||
"slug": {
|
||||
"name": "slug",
|
||||
"type": "varchar(255)",
|
||||
"primaryKey": false,
|
||||
"notNull": true
|
||||
},
|
||||
"show_pk": {
|
||||
"name": "show_pk",
|
||||
"type": "integer",
|
||||
"primaryKey": false,
|
||||
"notNull": false
|
||||
},
|
||||
"order": {
|
||||
"name": "order",
|
||||
"type": "real",
|
||||
"primaryKey": false,
|
||||
"notNull": false
|
||||
},
|
||||
"season_number": {
|
||||
"name": "season_number",
|
||||
"type": "integer",
|
||||
"primaryKey": false,
|
||||
"notNull": false
|
||||
},
|
||||
"episode_number": {
|
||||
"name": "episode_number",
|
||||
"type": "integer",
|
||||
"primaryKey": false,
|
||||
"notNull": false
|
||||
},
|
||||
"type": {
|
||||
"name": "type",
|
||||
"type": "entry_type",
|
||||
"typeSchema": "kyoo",
|
||||
"primaryKey": false,
|
||||
"notNull": true
|
||||
},
|
||||
"air_date": {
|
||||
"name": "air_date",
|
||||
"type": "date",
|
||||
"primaryKey": false,
|
||||
"notNull": false
|
||||
},
|
||||
"runtime": {
|
||||
"name": "runtime",
|
||||
"type": "integer",
|
||||
"primaryKey": false,
|
||||
"notNull": false
|
||||
},
|
||||
"thumbnails": {
|
||||
"name": "thumbnails",
|
||||
"type": "jsonb",
|
||||
"primaryKey": false,
|
||||
"notNull": false
|
||||
},
|
||||
"external_id": {
|
||||
"name": "external_id",
|
||||
"type": "jsonb",
|
||||
"primaryKey": false,
|
||||
"notNull": true,
|
||||
"default": "'{}'::jsonb"
|
||||
},
|
||||
"created_at": {
|
||||
"name": "created_at",
|
||||
"type": "timestamp with time zone",
|
||||
"primaryKey": false,
|
||||
"notNull": false,
|
||||
"default": "now()"
|
||||
},
|
||||
"next_refresh": {
|
||||
"name": "next_refresh",
|
||||
"type": "timestamp with time zone",
|
||||
"primaryKey": false,
|
||||
"notNull": false
|
||||
}
|
||||
},
|
||||
"indexes": {},
|
||||
"foreignKeys": {
|
||||
"entries_show_pk_shows_pk_fk": {
|
||||
"name": "entries_show_pk_shows_pk_fk",
|
||||
"tableFrom": "entries",
|
||||
"tableTo": "shows",
|
||||
"schemaTo": "kyoo",
|
||||
"columnsFrom": ["show_pk"],
|
||||
"columnsTo": ["pk"],
|
||||
"onDelete": "cascade",
|
||||
"onUpdate": "no action"
|
||||
}
|
||||
},
|
||||
"compositePrimaryKeys": {},
|
||||
"uniqueConstraints": {
|
||||
"entries_id_unique": {
|
||||
"name": "entries_id_unique",
|
||||
"nullsNotDistinct": false,
|
||||
"columns": ["id"]
|
||||
},
|
||||
"entries_slug_unique": {
|
||||
"name": "entries_slug_unique",
|
||||
"nullsNotDistinct": false,
|
||||
"columns": ["slug"]
|
||||
},
|
||||
"entries_showPk_seasonNumber_episodeNumber_unique": {
|
||||
"name": "entries_showPk_seasonNumber_episodeNumber_unique",
|
||||
"nullsNotDistinct": false,
|
||||
"columns": ["show_pk", "season_number", "episode_number"]
|
||||
}
|
||||
},
|
||||
"policies": {},
|
||||
"checkConstraints": {
|
||||
"order_positive": {
|
||||
"name": "order_positive",
|
||||
"value": "\"kyoo\".\"entries\".\"order\" >= 0"
|
||||
}
|
||||
},
|
||||
"isRLSEnabled": false
|
||||
},
|
||||
"kyoo.entry_translations": {
|
||||
"name": "entry_translations",
|
||||
"schema": "kyoo",
|
||||
"columns": {
|
||||
"pk": {
|
||||
"name": "pk",
|
||||
"type": "integer",
|
||||
"primaryKey": false,
|
||||
"notNull": true
|
||||
},
|
||||
"language": {
|
||||
"name": "language",
|
||||
"type": "varchar(255)",
|
||||
"primaryKey": false,
|
||||
"notNull": true
|
||||
},
|
||||
"name": {
|
||||
"name": "name",
|
||||
"type": "text",
|
||||
"primaryKey": false,
|
||||
"notNull": false
|
||||
},
|
||||
"description": {
|
||||
"name": "description",
|
||||
"type": "text",
|
||||
"primaryKey": false,
|
||||
"notNull": false
|
||||
},
|
||||
"tagline": {
|
||||
"name": "tagline",
|
||||
"type": "text",
|
||||
"primaryKey": false,
|
||||
"notNull": false
|
||||
},
|
||||
"poster": {
|
||||
"name": "poster",
|
||||
"type": "jsonb",
|
||||
"primaryKey": false,
|
||||
"notNull": false
|
||||
}
|
||||
},
|
||||
"indexes": {},
|
||||
"foreignKeys": {
|
||||
"entry_translations_pk_entries_pk_fk": {
|
||||
"name": "entry_translations_pk_entries_pk_fk",
|
||||
"tableFrom": "entry_translations",
|
||||
"tableTo": "entries",
|
||||
"schemaTo": "kyoo",
|
||||
"columnsFrom": ["pk"],
|
||||
"columnsTo": ["pk"],
|
||||
"onDelete": "cascade",
|
||||
"onUpdate": "no action"
|
||||
}
|
||||
},
|
||||
"compositePrimaryKeys": {
|
||||
"entry_translations_pk_language_pk": {
|
||||
"name": "entry_translations_pk_language_pk",
|
||||
"columns": ["pk", "language"]
|
||||
}
|
||||
},
|
||||
"uniqueConstraints": {},
|
||||
"policies": {},
|
||||
"checkConstraints": {},
|
||||
"isRLSEnabled": false
|
||||
},
|
||||
"kyoo.season_translations": {
|
||||
"name": "season_translations",
|
||||
"schema": "kyoo",
|
||||
"columns": {
|
||||
"pk": {
|
||||
"name": "pk",
|
||||
"type": "integer",
|
||||
"primaryKey": false,
|
||||
"notNull": true
|
||||
},
|
||||
"language": {
|
||||
"name": "language",
|
||||
"type": "varchar(255)",
|
||||
"primaryKey": false,
|
||||
"notNull": true
|
||||
},
|
||||
"name": {
|
||||
"name": "name",
|
||||
"type": "text",
|
||||
"primaryKey": false,
|
||||
"notNull": false
|
||||
},
|
||||
"description": {
|
||||
"name": "description",
|
||||
"type": "text",
|
||||
"primaryKey": false,
|
||||
"notNull": false
|
||||
},
|
||||
"poster": {
|
||||
"name": "poster",
|
||||
"type": "jsonb",
|
||||
"primaryKey": false,
|
||||
"notNull": false
|
||||
},
|
||||
"thumbnail": {
|
||||
"name": "thumbnail",
|
||||
"type": "jsonb",
|
||||
"primaryKey": false,
|
||||
"notNull": false
|
||||
},
|
||||
"banner": {
|
||||
"name": "banner",
|
||||
"type": "jsonb",
|
||||
"primaryKey": false,
|
||||
"notNull": false
|
||||
}
|
||||
},
|
||||
"indexes": {},
|
||||
"foreignKeys": {
|
||||
"season_translations_pk_seasons_pk_fk": {
|
||||
"name": "season_translations_pk_seasons_pk_fk",
|
||||
"tableFrom": "season_translations",
|
||||
"tableTo": "seasons",
|
||||
"schemaTo": "kyoo",
|
||||
"columnsFrom": ["pk"],
|
||||
"columnsTo": ["pk"],
|
||||
"onDelete": "cascade",
|
||||
"onUpdate": "no action"
|
||||
}
|
||||
},
|
||||
"compositePrimaryKeys": {
|
||||
"season_translations_pk_language_pk": {
|
||||
"name": "season_translations_pk_language_pk",
|
||||
"columns": ["pk", "language"]
|
||||
}
|
||||
},
|
||||
"uniqueConstraints": {},
|
||||
"policies": {},
|
||||
"checkConstraints": {},
|
||||
"isRLSEnabled": false
|
||||
},
|
||||
"kyoo.seasons": {
|
||||
"name": "seasons",
|
||||
"schema": "kyoo",
|
||||
"columns": {
|
||||
"pk": {
|
||||
"name": "pk",
|
||||
"type": "integer",
|
||||
"primaryKey": true,
|
||||
"notNull": true,
|
||||
"identity": {
|
||||
"type": "always",
|
||||
"name": "seasons_pk_seq",
|
||||
"schema": "kyoo",
|
||||
"increment": "1",
|
||||
"startWith": "1",
|
||||
"minValue": "1",
|
||||
"maxValue": "2147483647",
|
||||
"cache": "1",
|
||||
"cycle": false
|
||||
}
|
||||
},
|
||||
"id": {
|
||||
"name": "id",
|
||||
"type": "uuid",
|
||||
"primaryKey": false,
|
||||
"notNull": true,
|
||||
"default": "gen_random_uuid()"
|
||||
},
|
||||
"slug": {
|
||||
"name": "slug",
|
||||
"type": "varchar(255)",
|
||||
"primaryKey": false,
|
||||
"notNull": true
|
||||
},
|
||||
"show_pk": {
|
||||
"name": "show_pk",
|
||||
"type": "integer",
|
||||
"primaryKey": false,
|
||||
"notNull": false
|
||||
},
|
||||
"season_number": {
|
||||
"name": "season_number",
|
||||
"type": "integer",
|
||||
"primaryKey": false,
|
||||
"notNull": true
|
||||
},
|
||||
"start_air": {
|
||||
"name": "start_air",
|
||||
"type": "date",
|
||||
"primaryKey": false,
|
||||
"notNull": false
|
||||
},
|
||||
"end_air": {
|
||||
"name": "end_air",
|
||||
"type": "date",
|
||||
"primaryKey": false,
|
||||
"notNull": false
|
||||
},
|
||||
"external_id": {
|
||||
"name": "external_id",
|
||||
"type": "jsonb",
|
||||
"primaryKey": false,
|
||||
"notNull": true,
|
||||
"default": "'{}'::jsonb"
|
||||
},
|
||||
"created_at": {
|
||||
"name": "created_at",
|
||||
"type": "timestamp with time zone",
|
||||
"primaryKey": false,
|
||||
"notNull": false,
|
||||
"default": "now()"
|
||||
},
|
||||
"next_refresh": {
|
||||
"name": "next_refresh",
|
||||
"type": "timestamp with time zone",
|
||||
"primaryKey": false,
|
||||
"notNull": false
|
||||
}
|
||||
},
|
||||
"indexes": {},
|
||||
"foreignKeys": {
|
||||
"seasons_show_pk_shows_pk_fk": {
|
||||
"name": "seasons_show_pk_shows_pk_fk",
|
||||
"tableFrom": "seasons",
|
||||
"tableTo": "shows",
|
||||
"schemaTo": "kyoo",
|
||||
"columnsFrom": ["show_pk"],
|
||||
"columnsTo": ["pk"],
|
||||
"onDelete": "cascade",
|
||||
"onUpdate": "no action"
|
||||
}
|
||||
},
|
||||
"compositePrimaryKeys": {},
|
||||
"uniqueConstraints": {
|
||||
"seasons_id_unique": {
|
||||
"name": "seasons_id_unique",
|
||||
"nullsNotDistinct": false,
|
||||
"columns": ["id"]
|
||||
},
|
||||
"seasons_slug_unique": {
|
||||
"name": "seasons_slug_unique",
|
||||
"nullsNotDistinct": false,
|
||||
"columns": ["slug"]
|
||||
},
|
||||
"seasons_showPk_seasonNumber_unique": {
|
||||
"name": "seasons_showPk_seasonNumber_unique",
|
||||
"nullsNotDistinct": false,
|
||||
"columns": ["show_pk", "season_number"]
|
||||
}
|
||||
},
|
||||
"policies": {},
|
||||
"checkConstraints": {},
|
||||
"isRLSEnabled": false
|
||||
},
|
||||
"kyoo.show_translations": {
|
||||
"name": "show_translations",
|
||||
"schema": "kyoo",
|
||||
"columns": {
|
||||
"pk": {
|
||||
"name": "pk",
|
||||
"type": "integer",
|
||||
"primaryKey": false,
|
||||
"notNull": true
|
||||
},
|
||||
"language": {
|
||||
"name": "language",
|
||||
"type": "varchar(255)",
|
||||
"primaryKey": false,
|
||||
"notNull": true
|
||||
},
|
||||
"name": {
|
||||
"name": "name",
|
||||
"type": "text",
|
||||
"primaryKey": false,
|
||||
"notNull": true
|
||||
},
|
||||
"description": {
|
||||
"name": "description",
|
||||
"type": "text",
|
||||
"primaryKey": false,
|
||||
"notNull": false
|
||||
},
|
||||
"tagline": {
|
||||
"name": "tagline",
|
||||
"type": "text",
|
||||
"primaryKey": false,
|
||||
"notNull": false
|
||||
},
|
||||
"aliases": {
|
||||
"name": "aliases",
|
||||
"type": "text[]",
|
||||
"primaryKey": false,
|
||||
"notNull": true
|
||||
},
|
||||
"tags": {
|
||||
"name": "tags",
|
||||
"type": "text[]",
|
||||
"primaryKey": false,
|
||||
"notNull": true
|
||||
},
|
||||
"poster": {
|
||||
"name": "poster",
|
||||
"type": "jsonb",
|
||||
"primaryKey": false,
|
||||
"notNull": false
|
||||
},
|
||||
"thumbnail": {
|
||||
"name": "thumbnail",
|
||||
"type": "jsonb",
|
||||
"primaryKey": false,
|
||||
"notNull": false
|
||||
},
|
||||
"banner": {
|
||||
"name": "banner",
|
||||
"type": "jsonb",
|
||||
"primaryKey": false,
|
||||
"notNull": false
|
||||
},
|
||||
"logo": {
|
||||
"name": "logo",
|
||||
"type": "jsonb",
|
||||
"primaryKey": false,
|
||||
"notNull": false
|
||||
},
|
||||
"trailer_url": {
|
||||
"name": "trailer_url",
|
||||
"type": "text",
|
||||
"primaryKey": false,
|
||||
"notNull": false
|
||||
}
|
||||
},
|
||||
"indexes": {},
|
||||
"foreignKeys": {
|
||||
"show_translations_pk_shows_pk_fk": {
|
||||
"name": "show_translations_pk_shows_pk_fk",
|
||||
"tableFrom": "show_translations",
|
||||
"tableTo": "shows",
|
||||
"schemaTo": "kyoo",
|
||||
"columnsFrom": ["pk"],
|
||||
"columnsTo": ["pk"],
|
||||
"onDelete": "cascade",
|
||||
"onUpdate": "no action"
|
||||
}
|
||||
},
|
||||
"compositePrimaryKeys": {
|
||||
"show_translations_pk_language_pk": {
|
||||
"name": "show_translations_pk_language_pk",
|
||||
"columns": ["pk", "language"]
|
||||
}
|
||||
},
|
||||
"uniqueConstraints": {},
|
||||
"policies": {},
|
||||
"checkConstraints": {},
|
||||
"isRLSEnabled": false
|
||||
},
|
||||
"kyoo.shows": {
|
||||
"name": "shows",
|
||||
"schema": "kyoo",
|
||||
"columns": {
|
||||
"pk": {
|
||||
"name": "pk",
|
||||
"type": "integer",
|
||||
"primaryKey": true,
|
||||
"notNull": true,
|
||||
"identity": {
|
||||
"type": "always",
|
||||
"name": "shows_pk_seq",
|
||||
"schema": "kyoo",
|
||||
"increment": "1",
|
||||
"startWith": "1",
|
||||
"minValue": "1",
|
||||
"maxValue": "2147483647",
|
||||
"cache": "1",
|
||||
"cycle": false
|
||||
}
|
||||
},
|
||||
"id": {
|
||||
"name": "id",
|
||||
"type": "uuid",
|
||||
"primaryKey": false,
|
||||
"notNull": true,
|
||||
"default": "gen_random_uuid()"
|
||||
},
|
||||
"slug": {
|
||||
"name": "slug",
|
||||
"type": "varchar(255)",
|
||||
"primaryKey": false,
|
||||
"notNull": true
|
||||
},
|
||||
"kind": {
|
||||
"name": "kind",
|
||||
"type": "show_kind",
|
||||
"typeSchema": "kyoo",
|
||||
"primaryKey": false,
|
||||
"notNull": true
|
||||
},
|
||||
"genres": {
|
||||
"name": "genres",
|
||||
"type": "genres[]",
|
||||
"primaryKey": false,
|
||||
"notNull": true
|
||||
},
|
||||
"rating": {
|
||||
"name": "rating",
|
||||
"type": "smallint",
|
||||
"primaryKey": false,
|
||||
"notNull": false
|
||||
},
|
||||
"runtime": {
|
||||
"name": "runtime",
|
||||
"type": "integer",
|
||||
"primaryKey": false,
|
||||
"notNull": false
|
||||
},
|
||||
"status": {
|
||||
"name": "status",
|
||||
"type": "show_status",
|
||||
"typeSchema": "kyoo",
|
||||
"primaryKey": false,
|
||||
"notNull": true
|
||||
},
|
||||
"start_air": {
|
||||
"name": "start_air",
|
||||
"type": "date",
|
||||
"primaryKey": false,
|
||||
"notNull": false
|
||||
},
|
||||
"end_air": {
|
||||
"name": "end_air",
|
||||
"type": "date",
|
||||
"primaryKey": false,
|
||||
"notNull": false
|
||||
},
|
||||
"original_language": {
|
||||
"name": "original_language",
|
||||
"type": "varchar(255)",
|
||||
"primaryKey": false,
|
||||
"notNull": false
|
||||
},
|
||||
"external_id": {
|
||||
"name": "external_id",
|
||||
"type": "jsonb",
|
||||
"primaryKey": false,
|
||||
"notNull": true,
|
||||
"default": "'{}'::jsonb"
|
||||
},
|
||||
"created_at": {
|
||||
"name": "created_at",
|
||||
"type": "timestamp with time zone",
|
||||
"primaryKey": false,
|
||||
"notNull": true,
|
||||
"default": "now()"
|
||||
},
|
||||
"next_refresh": {
|
||||
"name": "next_refresh",
|
||||
"type": "timestamp with time zone",
|
||||
"primaryKey": false,
|
||||
"notNull": true
|
||||
}
|
||||
},
|
||||
"indexes": {},
|
||||
"foreignKeys": {},
|
||||
"compositePrimaryKeys": {},
|
||||
"uniqueConstraints": {
|
||||
"shows_id_unique": {
|
||||
"name": "shows_id_unique",
|
||||
"nullsNotDistinct": false,
|
||||
"columns": ["id"]
|
||||
},
|
||||
"shows_slug_unique": {
|
||||
"name": "shows_slug_unique",
|
||||
"nullsNotDistinct": false,
|
||||
"columns": ["slug"]
|
||||
}
|
||||
},
|
||||
"policies": {},
|
||||
"checkConstraints": {
|
||||
"rating_valid": {
|
||||
"name": "rating_valid",
|
||||
"value": "\"kyoo\".\"shows\".\"rating\" between 0 and 100"
|
||||
},
|
||||
"runtime_valid": {
|
||||
"name": "runtime_valid",
|
||||
"value": "\"kyoo\".\"shows\".\"runtime\" >= 0"
|
||||
}
|
||||
},
|
||||
"isRLSEnabled": false
|
||||
},
|
||||
"kyoo.entry_video_jointure": {
|
||||
"name": "entry_video_jointure",
|
||||
"schema": "kyoo",
|
||||
"columns": {
|
||||
"entry": {
|
||||
"name": "entry",
|
||||
"type": "integer",
|
||||
"primaryKey": false,
|
||||
"notNull": true
|
||||
},
|
||||
"video": {
|
||||
"name": "video",
|
||||
"type": "integer",
|
||||
"primaryKey": false,
|
||||
"notNull": true
|
||||
},
|
||||
"slug": {
|
||||
"name": "slug",
|
||||
"type": "varchar(255)",
|
||||
"primaryKey": false,
|
||||
"notNull": true
|
||||
}
|
||||
},
|
||||
"indexes": {},
|
||||
"foreignKeys": {
|
||||
"entry_video_jointure_entry_entries_pk_fk": {
|
||||
"name": "entry_video_jointure_entry_entries_pk_fk",
|
||||
"tableFrom": "entry_video_jointure",
|
||||
"tableTo": "entries",
|
||||
"schemaTo": "kyoo",
|
||||
"columnsFrom": ["entry"],
|
||||
"columnsTo": ["pk"],
|
||||
"onDelete": "cascade",
|
||||
"onUpdate": "no action"
|
||||
},
|
||||
"entry_video_jointure_video_videos_pk_fk": {
|
||||
"name": "entry_video_jointure_video_videos_pk_fk",
|
||||
"tableFrom": "entry_video_jointure",
|
||||
"tableTo": "videos",
|
||||
"schemaTo": "kyoo",
|
||||
"columnsFrom": ["video"],
|
||||
"columnsTo": ["pk"],
|
||||
"onDelete": "cascade",
|
||||
"onUpdate": "no action"
|
||||
}
|
||||
},
|
||||
"compositePrimaryKeys": {
|
||||
"entry_video_jointure_entry_video_pk": {
|
||||
"name": "entry_video_jointure_entry_video_pk",
|
||||
"columns": ["entry", "video"]
|
||||
}
|
||||
},
|
||||
"uniqueConstraints": {
|
||||
"entry_video_jointure_slug_unique": {
|
||||
"name": "entry_video_jointure_slug_unique",
|
||||
"nullsNotDistinct": false,
|
||||
"columns": ["slug"]
|
||||
}
|
||||
},
|
||||
"policies": {},
|
||||
"checkConstraints": {},
|
||||
"isRLSEnabled": false
|
||||
},
|
||||
"kyoo.videos": {
|
||||
"name": "videos",
|
||||
"schema": "kyoo",
|
||||
"columns": {
|
||||
"pk": {
|
||||
"name": "pk",
|
||||
"type": "integer",
|
||||
"primaryKey": true,
|
||||
"notNull": true,
|
||||
"identity": {
|
||||
"type": "always",
|
||||
"name": "videos_pk_seq",
|
||||
"schema": "kyoo",
|
||||
"increment": "1",
|
||||
"startWith": "1",
|
||||
"minValue": "1",
|
||||
"maxValue": "2147483647",
|
||||
"cache": "1",
|
||||
"cycle": false
|
||||
}
|
||||
},
|
||||
"id": {
|
||||
"name": "id",
|
||||
"type": "uuid",
|
||||
"primaryKey": false,
|
||||
"notNull": true,
|
||||
"default": "gen_random_uuid()"
|
||||
},
|
||||
"path": {
|
||||
"name": "path",
|
||||
"type": "text",
|
||||
"primaryKey": false,
|
||||
"notNull": true
|
||||
},
|
||||
"rendering": {
|
||||
"name": "rendering",
|
||||
"type": "text",
|
||||
"primaryKey": false,
|
||||
"notNull": true
|
||||
},
|
||||
"part": {
|
||||
"name": "part",
|
||||
"type": "integer",
|
||||
"primaryKey": false,
|
||||
"notNull": false
|
||||
},
|
||||
"version": {
|
||||
"name": "version",
|
||||
"type": "integer",
|
||||
"primaryKey": false,
|
||||
"notNull": true,
|
||||
"default": 1
|
||||
},
|
||||
"guess": {
|
||||
"name": "guess",
|
||||
"type": "jsonb",
|
||||
"primaryKey": false,
|
||||
"notNull": true,
|
||||
"default": "'{}'::jsonb"
|
||||
},
|
||||
"created_at": {
|
||||
"name": "created_at",
|
||||
"type": "timestamp with time zone",
|
||||
"primaryKey": false,
|
||||
"notNull": true,
|
||||
"default": "now()"
|
||||
}
|
||||
},
|
||||
"indexes": {},
|
||||
"foreignKeys": {},
|
||||
"compositePrimaryKeys": {},
|
||||
"uniqueConstraints": {
|
||||
"videos_id_unique": {
|
||||
"name": "videos_id_unique",
|
||||
"nullsNotDistinct": false,
|
||||
"columns": ["id"]
|
||||
},
|
||||
"videos_path_unique": {
|
||||
"name": "videos_path_unique",
|
||||
"nullsNotDistinct": false,
|
||||
"columns": ["path"]
|
||||
}
|
||||
},
|
||||
"policies": {},
|
||||
"checkConstraints": {
|
||||
"part_pos": {
|
||||
"name": "part_pos",
|
||||
"value": "\"kyoo\".\"videos\".\"part\" >= 0"
|
||||
},
|
||||
"version_pos": {
|
||||
"name": "version_pos",
|
||||
"value": "\"kyoo\".\"videos\".\"version\" >= 0"
|
||||
}
|
||||
},
|
||||
"isRLSEnabled": false
|
||||
}
|
||||
},
|
||||
"enums": {
|
||||
"kyoo.entry_type": {
|
||||
"name": "entry_type",
|
||||
"schema": "kyoo",
|
||||
"values": ["unknown", "episode", "movie", "special", "extra"]
|
||||
},
|
||||
"kyoo.genres": {
|
||||
"name": "genres",
|
||||
"schema": "kyoo",
|
||||
"values": [
|
||||
"action",
|
||||
"adventure",
|
||||
"animation",
|
||||
"comedy",
|
||||
"crime",
|
||||
"documentary",
|
||||
"drama",
|
||||
"family",
|
||||
"fantasy",
|
||||
"history",
|
||||
"horror",
|
||||
"music",
|
||||
"mystery",
|
||||
"romance",
|
||||
"science-fiction",
|
||||
"thriller",
|
||||
"war",
|
||||
"western",
|
||||
"kids",
|
||||
"reality",
|
||||
"politics",
|
||||
"soap",
|
||||
"talk"
|
||||
]
|
||||
},
|
||||
"kyoo.show_kind": {
|
||||
"name": "show_kind",
|
||||
"schema": "kyoo",
|
||||
"values": ["serie", "movie"]
|
||||
},
|
||||
"kyoo.show_status": {
|
||||
"name": "show_status",
|
||||
"schema": "kyoo",
|
||||
"values": ["unknown", "finished", "airing", "planned"]
|
||||
}
|
||||
},
|
||||
"schemas": {
|
||||
"kyoo": "kyoo"
|
||||
},
|
||||
"sequences": {},
|
||||
"roles": {},
|
||||
"policies": {},
|
||||
"views": {},
|
||||
"_meta": {
|
||||
"columns": {},
|
||||
"schemas": {},
|
||||
"tables": {}
|
||||
}
|
||||
}
|
||||
930
api/drizzle/meta/0005_snapshot.json
Normal file
930
api/drizzle/meta/0005_snapshot.json
Normal file
@@ -0,0 +1,930 @@
|
||||
{
|
||||
"id": "1d98727c-290d-4491-8bb8-74390da0c021",
|
||||
"prevId": "0d5d6d22-dc13-4f3d-9975-cb7b38f628d4",
|
||||
"version": "7",
|
||||
"dialect": "postgresql",
|
||||
"tables": {
|
||||
"kyoo.entries": {
|
||||
"name": "entries",
|
||||
"schema": "kyoo",
|
||||
"columns": {
|
||||
"pk": {
|
||||
"name": "pk",
|
||||
"type": "integer",
|
||||
"primaryKey": true,
|
||||
"notNull": true,
|
||||
"identity": {
|
||||
"type": "always",
|
||||
"name": "entries_pk_seq",
|
||||
"schema": "kyoo",
|
||||
"increment": "1",
|
||||
"startWith": "1",
|
||||
"minValue": "1",
|
||||
"maxValue": "2147483647",
|
||||
"cache": "1",
|
||||
"cycle": false
|
||||
}
|
||||
},
|
||||
"id": {
|
||||
"name": "id",
|
||||
"type": "uuid",
|
||||
"primaryKey": false,
|
||||
"notNull": true,
|
||||
"default": "gen_random_uuid()"
|
||||
},
|
||||
"slug": {
|
||||
"name": "slug",
|
||||
"type": "varchar(255)",
|
||||
"primaryKey": false,
|
||||
"notNull": true
|
||||
},
|
||||
"show_pk": {
|
||||
"name": "show_pk",
|
||||
"type": "integer",
|
||||
"primaryKey": false,
|
||||
"notNull": false
|
||||
},
|
||||
"order": {
|
||||
"name": "order",
|
||||
"type": "real",
|
||||
"primaryKey": false,
|
||||
"notNull": false
|
||||
},
|
||||
"season_number": {
|
||||
"name": "season_number",
|
||||
"type": "integer",
|
||||
"primaryKey": false,
|
||||
"notNull": false
|
||||
},
|
||||
"episode_number": {
|
||||
"name": "episode_number",
|
||||
"type": "integer",
|
||||
"primaryKey": false,
|
||||
"notNull": false
|
||||
},
|
||||
"type": {
|
||||
"name": "type",
|
||||
"type": "entry_type",
|
||||
"typeSchema": "kyoo",
|
||||
"primaryKey": false,
|
||||
"notNull": true
|
||||
},
|
||||
"air_date": {
|
||||
"name": "air_date",
|
||||
"type": "date",
|
||||
"primaryKey": false,
|
||||
"notNull": false
|
||||
},
|
||||
"runtime": {
|
||||
"name": "runtime",
|
||||
"type": "integer",
|
||||
"primaryKey": false,
|
||||
"notNull": false
|
||||
},
|
||||
"thumbnails": {
|
||||
"name": "thumbnails",
|
||||
"type": "jsonb",
|
||||
"primaryKey": false,
|
||||
"notNull": false
|
||||
},
|
||||
"external_id": {
|
||||
"name": "external_id",
|
||||
"type": "jsonb",
|
||||
"primaryKey": false,
|
||||
"notNull": true,
|
||||
"default": "'{}'::jsonb"
|
||||
},
|
||||
"created_at": {
|
||||
"name": "created_at",
|
||||
"type": "timestamp with time zone",
|
||||
"primaryKey": false,
|
||||
"notNull": false,
|
||||
"default": "now()"
|
||||
},
|
||||
"next_refresh": {
|
||||
"name": "next_refresh",
|
||||
"type": "timestamp with time zone",
|
||||
"primaryKey": false,
|
||||
"notNull": false
|
||||
}
|
||||
},
|
||||
"indexes": {},
|
||||
"foreignKeys": {
|
||||
"entries_show_pk_shows_pk_fk": {
|
||||
"name": "entries_show_pk_shows_pk_fk",
|
||||
"tableFrom": "entries",
|
||||
"tableTo": "shows",
|
||||
"schemaTo": "kyoo",
|
||||
"columnsFrom": ["show_pk"],
|
||||
"columnsTo": ["pk"],
|
||||
"onDelete": "cascade",
|
||||
"onUpdate": "no action"
|
||||
}
|
||||
},
|
||||
"compositePrimaryKeys": {},
|
||||
"uniqueConstraints": {
|
||||
"entries_id_unique": {
|
||||
"name": "entries_id_unique",
|
||||
"nullsNotDistinct": false,
|
||||
"columns": ["id"]
|
||||
},
|
||||
"entries_slug_unique": {
|
||||
"name": "entries_slug_unique",
|
||||
"nullsNotDistinct": false,
|
||||
"columns": ["slug"]
|
||||
},
|
||||
"entries_showPk_seasonNumber_episodeNumber_unique": {
|
||||
"name": "entries_showPk_seasonNumber_episodeNumber_unique",
|
||||
"nullsNotDistinct": false,
|
||||
"columns": ["show_pk", "season_number", "episode_number"]
|
||||
}
|
||||
},
|
||||
"policies": {},
|
||||
"checkConstraints": {
|
||||
"order_positive": {
|
||||
"name": "order_positive",
|
||||
"value": "\"kyoo\".\"entries\".\"order\" >= 0"
|
||||
}
|
||||
},
|
||||
"isRLSEnabled": false
|
||||
},
|
||||
"kyoo.entry_translations": {
|
||||
"name": "entry_translations",
|
||||
"schema": "kyoo",
|
||||
"columns": {
|
||||
"pk": {
|
||||
"name": "pk",
|
||||
"type": "integer",
|
||||
"primaryKey": false,
|
||||
"notNull": true
|
||||
},
|
||||
"language": {
|
||||
"name": "language",
|
||||
"type": "varchar(255)",
|
||||
"primaryKey": false,
|
||||
"notNull": true
|
||||
},
|
||||
"name": {
|
||||
"name": "name",
|
||||
"type": "text",
|
||||
"primaryKey": false,
|
||||
"notNull": false
|
||||
},
|
||||
"description": {
|
||||
"name": "description",
|
||||
"type": "text",
|
||||
"primaryKey": false,
|
||||
"notNull": false
|
||||
},
|
||||
"tagline": {
|
||||
"name": "tagline",
|
||||
"type": "text",
|
||||
"primaryKey": false,
|
||||
"notNull": false
|
||||
},
|
||||
"poster": {
|
||||
"name": "poster",
|
||||
"type": "jsonb",
|
||||
"primaryKey": false,
|
||||
"notNull": false
|
||||
}
|
||||
},
|
||||
"indexes": {},
|
||||
"foreignKeys": {
|
||||
"entry_translations_pk_entries_pk_fk": {
|
||||
"name": "entry_translations_pk_entries_pk_fk",
|
||||
"tableFrom": "entry_translations",
|
||||
"tableTo": "entries",
|
||||
"schemaTo": "kyoo",
|
||||
"columnsFrom": ["pk"],
|
||||
"columnsTo": ["pk"],
|
||||
"onDelete": "cascade",
|
||||
"onUpdate": "no action"
|
||||
}
|
||||
},
|
||||
"compositePrimaryKeys": {
|
||||
"entry_translations_pk_language_pk": {
|
||||
"name": "entry_translations_pk_language_pk",
|
||||
"columns": ["pk", "language"]
|
||||
}
|
||||
},
|
||||
"uniqueConstraints": {},
|
||||
"policies": {},
|
||||
"checkConstraints": {},
|
||||
"isRLSEnabled": false
|
||||
},
|
||||
"kyoo.season_translations": {
|
||||
"name": "season_translations",
|
||||
"schema": "kyoo",
|
||||
"columns": {
|
||||
"pk": {
|
||||
"name": "pk",
|
||||
"type": "integer",
|
||||
"primaryKey": false,
|
||||
"notNull": true
|
||||
},
|
||||
"language": {
|
||||
"name": "language",
|
||||
"type": "varchar(255)",
|
||||
"primaryKey": false,
|
||||
"notNull": true
|
||||
},
|
||||
"name": {
|
||||
"name": "name",
|
||||
"type": "text",
|
||||
"primaryKey": false,
|
||||
"notNull": false
|
||||
},
|
||||
"description": {
|
||||
"name": "description",
|
||||
"type": "text",
|
||||
"primaryKey": false,
|
||||
"notNull": false
|
||||
},
|
||||
"poster": {
|
||||
"name": "poster",
|
||||
"type": "jsonb",
|
||||
"primaryKey": false,
|
||||
"notNull": false
|
||||
},
|
||||
"thumbnail": {
|
||||
"name": "thumbnail",
|
||||
"type": "jsonb",
|
||||
"primaryKey": false,
|
||||
"notNull": false
|
||||
},
|
||||
"banner": {
|
||||
"name": "banner",
|
||||
"type": "jsonb",
|
||||
"primaryKey": false,
|
||||
"notNull": false
|
||||
}
|
||||
},
|
||||
"indexes": {},
|
||||
"foreignKeys": {
|
||||
"season_translations_pk_seasons_pk_fk": {
|
||||
"name": "season_translations_pk_seasons_pk_fk",
|
||||
"tableFrom": "season_translations",
|
||||
"tableTo": "seasons",
|
||||
"schemaTo": "kyoo",
|
||||
"columnsFrom": ["pk"],
|
||||
"columnsTo": ["pk"],
|
||||
"onDelete": "cascade",
|
||||
"onUpdate": "no action"
|
||||
}
|
||||
},
|
||||
"compositePrimaryKeys": {
|
||||
"season_translations_pk_language_pk": {
|
||||
"name": "season_translations_pk_language_pk",
|
||||
"columns": ["pk", "language"]
|
||||
}
|
||||
},
|
||||
"uniqueConstraints": {},
|
||||
"policies": {},
|
||||
"checkConstraints": {},
|
||||
"isRLSEnabled": false
|
||||
},
|
||||
"kyoo.seasons": {
|
||||
"name": "seasons",
|
||||
"schema": "kyoo",
|
||||
"columns": {
|
||||
"pk": {
|
||||
"name": "pk",
|
||||
"type": "integer",
|
||||
"primaryKey": true,
|
||||
"notNull": true,
|
||||
"identity": {
|
||||
"type": "always",
|
||||
"name": "seasons_pk_seq",
|
||||
"schema": "kyoo",
|
||||
"increment": "1",
|
||||
"startWith": "1",
|
||||
"minValue": "1",
|
||||
"maxValue": "2147483647",
|
||||
"cache": "1",
|
||||
"cycle": false
|
||||
}
|
||||
},
|
||||
"id": {
|
||||
"name": "id",
|
||||
"type": "uuid",
|
||||
"primaryKey": false,
|
||||
"notNull": true,
|
||||
"default": "gen_random_uuid()"
|
||||
},
|
||||
"slug": {
|
||||
"name": "slug",
|
||||
"type": "varchar(255)",
|
||||
"primaryKey": false,
|
||||
"notNull": true
|
||||
},
|
||||
"show_pk": {
|
||||
"name": "show_pk",
|
||||
"type": "integer",
|
||||
"primaryKey": false,
|
||||
"notNull": false
|
||||
},
|
||||
"season_number": {
|
||||
"name": "season_number",
|
||||
"type": "integer",
|
||||
"primaryKey": false,
|
||||
"notNull": true
|
||||
},
|
||||
"start_air": {
|
||||
"name": "start_air",
|
||||
"type": "date",
|
||||
"primaryKey": false,
|
||||
"notNull": false
|
||||
},
|
||||
"end_air": {
|
||||
"name": "end_air",
|
||||
"type": "date",
|
||||
"primaryKey": false,
|
||||
"notNull": false
|
||||
},
|
||||
"external_id": {
|
||||
"name": "external_id",
|
||||
"type": "jsonb",
|
||||
"primaryKey": false,
|
||||
"notNull": true,
|
||||
"default": "'{}'::jsonb"
|
||||
},
|
||||
"created_at": {
|
||||
"name": "created_at",
|
||||
"type": "timestamp with time zone",
|
||||
"primaryKey": false,
|
||||
"notNull": false,
|
||||
"default": "now()"
|
||||
},
|
||||
"next_refresh": {
|
||||
"name": "next_refresh",
|
||||
"type": "timestamp with time zone",
|
||||
"primaryKey": false,
|
||||
"notNull": false
|
||||
}
|
||||
},
|
||||
"indexes": {},
|
||||
"foreignKeys": {
|
||||
"seasons_show_pk_shows_pk_fk": {
|
||||
"name": "seasons_show_pk_shows_pk_fk",
|
||||
"tableFrom": "seasons",
|
||||
"tableTo": "shows",
|
||||
"schemaTo": "kyoo",
|
||||
"columnsFrom": ["show_pk"],
|
||||
"columnsTo": ["pk"],
|
||||
"onDelete": "cascade",
|
||||
"onUpdate": "no action"
|
||||
}
|
||||
},
|
||||
"compositePrimaryKeys": {},
|
||||
"uniqueConstraints": {
|
||||
"seasons_id_unique": {
|
||||
"name": "seasons_id_unique",
|
||||
"nullsNotDistinct": false,
|
||||
"columns": ["id"]
|
||||
},
|
||||
"seasons_slug_unique": {
|
||||
"name": "seasons_slug_unique",
|
||||
"nullsNotDistinct": false,
|
||||
"columns": ["slug"]
|
||||
},
|
||||
"seasons_showPk_seasonNumber_unique": {
|
||||
"name": "seasons_showPk_seasonNumber_unique",
|
||||
"nullsNotDistinct": false,
|
||||
"columns": ["show_pk", "season_number"]
|
||||
}
|
||||
},
|
||||
"policies": {},
|
||||
"checkConstraints": {},
|
||||
"isRLSEnabled": false
|
||||
},
|
||||
"kyoo.show_translations": {
|
||||
"name": "show_translations",
|
||||
"schema": "kyoo",
|
||||
"columns": {
|
||||
"pk": {
|
||||
"name": "pk",
|
||||
"type": "integer",
|
||||
"primaryKey": false,
|
||||
"notNull": true
|
||||
},
|
||||
"language": {
|
||||
"name": "language",
|
||||
"type": "varchar(255)",
|
||||
"primaryKey": false,
|
||||
"notNull": true
|
||||
},
|
||||
"name": {
|
||||
"name": "name",
|
||||
"type": "text",
|
||||
"primaryKey": false,
|
||||
"notNull": true
|
||||
},
|
||||
"description": {
|
||||
"name": "description",
|
||||
"type": "text",
|
||||
"primaryKey": false,
|
||||
"notNull": false
|
||||
},
|
||||
"tagline": {
|
||||
"name": "tagline",
|
||||
"type": "text",
|
||||
"primaryKey": false,
|
||||
"notNull": false
|
||||
},
|
||||
"aliases": {
|
||||
"name": "aliases",
|
||||
"type": "text[]",
|
||||
"primaryKey": false,
|
||||
"notNull": true
|
||||
},
|
||||
"tags": {
|
||||
"name": "tags",
|
||||
"type": "text[]",
|
||||
"primaryKey": false,
|
||||
"notNull": true
|
||||
},
|
||||
"poster": {
|
||||
"name": "poster",
|
||||
"type": "jsonb",
|
||||
"primaryKey": false,
|
||||
"notNull": false
|
||||
},
|
||||
"thumbnail": {
|
||||
"name": "thumbnail",
|
||||
"type": "jsonb",
|
||||
"primaryKey": false,
|
||||
"notNull": false
|
||||
},
|
||||
"banner": {
|
||||
"name": "banner",
|
||||
"type": "jsonb",
|
||||
"primaryKey": false,
|
||||
"notNull": false
|
||||
},
|
||||
"logo": {
|
||||
"name": "logo",
|
||||
"type": "jsonb",
|
||||
"primaryKey": false,
|
||||
"notNull": false
|
||||
},
|
||||
"trailer_url": {
|
||||
"name": "trailer_url",
|
||||
"type": "text",
|
||||
"primaryKey": false,
|
||||
"notNull": false
|
||||
}
|
||||
},
|
||||
"indexes": {
|
||||
"name_trgm": {
|
||||
"name": "name_trgm",
|
||||
"columns": [
|
||||
{
|
||||
"expression": "\"name\" gin_trgm_ops",
|
||||
"asc": true,
|
||||
"isExpression": true,
|
||||
"nulls": "last"
|
||||
}
|
||||
],
|
||||
"isUnique": false,
|
||||
"concurrently": false,
|
||||
"method": "gin",
|
||||
"with": {}
|
||||
},
|
||||
"tags": {
|
||||
"name": "tags",
|
||||
"columns": [
|
||||
{
|
||||
"expression": "tags",
|
||||
"isExpression": false,
|
||||
"asc": true,
|
||||
"nulls": "last"
|
||||
}
|
||||
],
|
||||
"isUnique": false,
|
||||
"concurrently": false,
|
||||
"method": "btree",
|
||||
"with": {}
|
||||
}
|
||||
},
|
||||
"foreignKeys": {
|
||||
"show_translations_pk_shows_pk_fk": {
|
||||
"name": "show_translations_pk_shows_pk_fk",
|
||||
"tableFrom": "show_translations",
|
||||
"tableTo": "shows",
|
||||
"schemaTo": "kyoo",
|
||||
"columnsFrom": ["pk"],
|
||||
"columnsTo": ["pk"],
|
||||
"onDelete": "cascade",
|
||||
"onUpdate": "no action"
|
||||
}
|
||||
},
|
||||
"compositePrimaryKeys": {
|
||||
"show_translations_pk_language_pk": {
|
||||
"name": "show_translations_pk_language_pk",
|
||||
"columns": ["pk", "language"]
|
||||
}
|
||||
},
|
||||
"uniqueConstraints": {},
|
||||
"policies": {},
|
||||
"checkConstraints": {},
|
||||
"isRLSEnabled": false
|
||||
},
|
||||
"kyoo.shows": {
|
||||
"name": "shows",
|
||||
"schema": "kyoo",
|
||||
"columns": {
|
||||
"pk": {
|
||||
"name": "pk",
|
||||
"type": "integer",
|
||||
"primaryKey": true,
|
||||
"notNull": true,
|
||||
"identity": {
|
||||
"type": "always",
|
||||
"name": "shows_pk_seq",
|
||||
"schema": "kyoo",
|
||||
"increment": "1",
|
||||
"startWith": "1",
|
||||
"minValue": "1",
|
||||
"maxValue": "2147483647",
|
||||
"cache": "1",
|
||||
"cycle": false
|
||||
}
|
||||
},
|
||||
"id": {
|
||||
"name": "id",
|
||||
"type": "uuid",
|
||||
"primaryKey": false,
|
||||
"notNull": true,
|
||||
"default": "gen_random_uuid()"
|
||||
},
|
||||
"slug": {
|
||||
"name": "slug",
|
||||
"type": "varchar(255)",
|
||||
"primaryKey": false,
|
||||
"notNull": true
|
||||
},
|
||||
"kind": {
|
||||
"name": "kind",
|
||||
"type": "show_kind",
|
||||
"typeSchema": "kyoo",
|
||||
"primaryKey": false,
|
||||
"notNull": true
|
||||
},
|
||||
"genres": {
|
||||
"name": "genres",
|
||||
"type": "genres[]",
|
||||
"primaryKey": false,
|
||||
"notNull": true
|
||||
},
|
||||
"rating": {
|
||||
"name": "rating",
|
||||
"type": "smallint",
|
||||
"primaryKey": false,
|
||||
"notNull": false
|
||||
},
|
||||
"runtime": {
|
||||
"name": "runtime",
|
||||
"type": "integer",
|
||||
"primaryKey": false,
|
||||
"notNull": false
|
||||
},
|
||||
"status": {
|
||||
"name": "status",
|
||||
"type": "show_status",
|
||||
"typeSchema": "kyoo",
|
||||
"primaryKey": false,
|
||||
"notNull": true
|
||||
},
|
||||
"start_air": {
|
||||
"name": "start_air",
|
||||
"type": "date",
|
||||
"primaryKey": false,
|
||||
"notNull": false
|
||||
},
|
||||
"end_air": {
|
||||
"name": "end_air",
|
||||
"type": "date",
|
||||
"primaryKey": false,
|
||||
"notNull": false
|
||||
},
|
||||
"original_language": {
|
||||
"name": "original_language",
|
||||
"type": "varchar(255)",
|
||||
"primaryKey": false,
|
||||
"notNull": false
|
||||
},
|
||||
"external_id": {
|
||||
"name": "external_id",
|
||||
"type": "jsonb",
|
||||
"primaryKey": false,
|
||||
"notNull": true,
|
||||
"default": "'{}'::jsonb"
|
||||
},
|
||||
"created_at": {
|
||||
"name": "created_at",
|
||||
"type": "timestamp with time zone",
|
||||
"primaryKey": false,
|
||||
"notNull": true,
|
||||
"default": "now()"
|
||||
},
|
||||
"next_refresh": {
|
||||
"name": "next_refresh",
|
||||
"type": "timestamp with time zone",
|
||||
"primaryKey": false,
|
||||
"notNull": true
|
||||
}
|
||||
},
|
||||
"indexes": {
|
||||
"kind": {
|
||||
"name": "kind",
|
||||
"columns": [
|
||||
{
|
||||
"expression": "kind",
|
||||
"isExpression": false,
|
||||
"asc": true,
|
||||
"nulls": "last"
|
||||
}
|
||||
],
|
||||
"isUnique": false,
|
||||
"concurrently": false,
|
||||
"method": "hash",
|
||||
"with": {}
|
||||
},
|
||||
"rating": {
|
||||
"name": "rating",
|
||||
"columns": [
|
||||
{
|
||||
"expression": "rating",
|
||||
"isExpression": false,
|
||||
"asc": true,
|
||||
"nulls": "last"
|
||||
}
|
||||
],
|
||||
"isUnique": false,
|
||||
"concurrently": false,
|
||||
"method": "btree",
|
||||
"with": {}
|
||||
},
|
||||
"startAir": {
|
||||
"name": "startAir",
|
||||
"columns": [
|
||||
{
|
||||
"expression": "start_air",
|
||||
"isExpression": false,
|
||||
"asc": true,
|
||||
"nulls": "last"
|
||||
}
|
||||
],
|
||||
"isUnique": false,
|
||||
"concurrently": false,
|
||||
"method": "btree",
|
||||
"with": {}
|
||||
}
|
||||
},
|
||||
"foreignKeys": {},
|
||||
"compositePrimaryKeys": {},
|
||||
"uniqueConstraints": {
|
||||
"shows_id_unique": {
|
||||
"name": "shows_id_unique",
|
||||
"nullsNotDistinct": false,
|
||||
"columns": ["id"]
|
||||
},
|
||||
"shows_slug_unique": {
|
||||
"name": "shows_slug_unique",
|
||||
"nullsNotDistinct": false,
|
||||
"columns": ["slug"]
|
||||
}
|
||||
},
|
||||
"policies": {},
|
||||
"checkConstraints": {
|
||||
"rating_valid": {
|
||||
"name": "rating_valid",
|
||||
"value": "\"kyoo\".\"shows\".\"rating\" between 0 and 100"
|
||||
},
|
||||
"runtime_valid": {
|
||||
"name": "runtime_valid",
|
||||
"value": "\"kyoo\".\"shows\".\"runtime\" >= 0"
|
||||
}
|
||||
},
|
||||
"isRLSEnabled": false
|
||||
},
|
||||
"kyoo.entry_video_jointure": {
|
||||
"name": "entry_video_jointure",
|
||||
"schema": "kyoo",
|
||||
"columns": {
|
||||
"entry": {
|
||||
"name": "entry",
|
||||
"type": "integer",
|
||||
"primaryKey": false,
|
||||
"notNull": true
|
||||
},
|
||||
"video": {
|
||||
"name": "video",
|
||||
"type": "integer",
|
||||
"primaryKey": false,
|
||||
"notNull": true
|
||||
},
|
||||
"slug": {
|
||||
"name": "slug",
|
||||
"type": "varchar(255)",
|
||||
"primaryKey": false,
|
||||
"notNull": true
|
||||
}
|
||||
},
|
||||
"indexes": {},
|
||||
"foreignKeys": {
|
||||
"entry_video_jointure_entry_entries_pk_fk": {
|
||||
"name": "entry_video_jointure_entry_entries_pk_fk",
|
||||
"tableFrom": "entry_video_jointure",
|
||||
"tableTo": "entries",
|
||||
"schemaTo": "kyoo",
|
||||
"columnsFrom": ["entry"],
|
||||
"columnsTo": ["pk"],
|
||||
"onDelete": "cascade",
|
||||
"onUpdate": "no action"
|
||||
},
|
||||
"entry_video_jointure_video_videos_pk_fk": {
|
||||
"name": "entry_video_jointure_video_videos_pk_fk",
|
||||
"tableFrom": "entry_video_jointure",
|
||||
"tableTo": "videos",
|
||||
"schemaTo": "kyoo",
|
||||
"columnsFrom": ["video"],
|
||||
"columnsTo": ["pk"],
|
||||
"onDelete": "cascade",
|
||||
"onUpdate": "no action"
|
||||
}
|
||||
},
|
||||
"compositePrimaryKeys": {
|
||||
"entry_video_jointure_entry_video_pk": {
|
||||
"name": "entry_video_jointure_entry_video_pk",
|
||||
"columns": ["entry", "video"]
|
||||
}
|
||||
},
|
||||
"uniqueConstraints": {
|
||||
"entry_video_jointure_slug_unique": {
|
||||
"name": "entry_video_jointure_slug_unique",
|
||||
"nullsNotDistinct": false,
|
||||
"columns": ["slug"]
|
||||
}
|
||||
},
|
||||
"policies": {},
|
||||
"checkConstraints": {},
|
||||
"isRLSEnabled": false
|
||||
},
|
||||
"kyoo.videos": {
|
||||
"name": "videos",
|
||||
"schema": "kyoo",
|
||||
"columns": {
|
||||
"pk": {
|
||||
"name": "pk",
|
||||
"type": "integer",
|
||||
"primaryKey": true,
|
||||
"notNull": true,
|
||||
"identity": {
|
||||
"type": "always",
|
||||
"name": "videos_pk_seq",
|
||||
"schema": "kyoo",
|
||||
"increment": "1",
|
||||
"startWith": "1",
|
||||
"minValue": "1",
|
||||
"maxValue": "2147483647",
|
||||
"cache": "1",
|
||||
"cycle": false
|
||||
}
|
||||
},
|
||||
"id": {
|
||||
"name": "id",
|
||||
"type": "uuid",
|
||||
"primaryKey": false,
|
||||
"notNull": true,
|
||||
"default": "gen_random_uuid()"
|
||||
},
|
||||
"path": {
|
||||
"name": "path",
|
||||
"type": "text",
|
||||
"primaryKey": false,
|
||||
"notNull": true
|
||||
},
|
||||
"rendering": {
|
||||
"name": "rendering",
|
||||
"type": "text",
|
||||
"primaryKey": false,
|
||||
"notNull": true
|
||||
},
|
||||
"part": {
|
||||
"name": "part",
|
||||
"type": "integer",
|
||||
"primaryKey": false,
|
||||
"notNull": false
|
||||
},
|
||||
"version": {
|
||||
"name": "version",
|
||||
"type": "integer",
|
||||
"primaryKey": false,
|
||||
"notNull": true,
|
||||
"default": 1
|
||||
},
|
||||
"guess": {
|
||||
"name": "guess",
|
||||
"type": "jsonb",
|
||||
"primaryKey": false,
|
||||
"notNull": true,
|
||||
"default": "'{}'::jsonb"
|
||||
},
|
||||
"created_at": {
|
||||
"name": "created_at",
|
||||
"type": "timestamp with time zone",
|
||||
"primaryKey": false,
|
||||
"notNull": true,
|
||||
"default": "now()"
|
||||
}
|
||||
},
|
||||
"indexes": {},
|
||||
"foreignKeys": {},
|
||||
"compositePrimaryKeys": {},
|
||||
"uniqueConstraints": {
|
||||
"videos_id_unique": {
|
||||
"name": "videos_id_unique",
|
||||
"nullsNotDistinct": false,
|
||||
"columns": ["id"]
|
||||
},
|
||||
"videos_path_unique": {
|
||||
"name": "videos_path_unique",
|
||||
"nullsNotDistinct": false,
|
||||
"columns": ["path"]
|
||||
}
|
||||
},
|
||||
"policies": {},
|
||||
"checkConstraints": {
|
||||
"part_pos": {
|
||||
"name": "part_pos",
|
||||
"value": "\"kyoo\".\"videos\".\"part\" >= 0"
|
||||
},
|
||||
"version_pos": {
|
||||
"name": "version_pos",
|
||||
"value": "\"kyoo\".\"videos\".\"version\" >= 0"
|
||||
}
|
||||
},
|
||||
"isRLSEnabled": false
|
||||
}
|
||||
},
|
||||
"enums": {
|
||||
"kyoo.entry_type": {
|
||||
"name": "entry_type",
|
||||
"schema": "kyoo",
|
||||
"values": ["unknown", "episode", "movie", "special", "extra"]
|
||||
},
|
||||
"kyoo.genres": {
|
||||
"name": "genres",
|
||||
"schema": "kyoo",
|
||||
"values": [
|
||||
"action",
|
||||
"adventure",
|
||||
"animation",
|
||||
"comedy",
|
||||
"crime",
|
||||
"documentary",
|
||||
"drama",
|
||||
"family",
|
||||
"fantasy",
|
||||
"history",
|
||||
"horror",
|
||||
"music",
|
||||
"mystery",
|
||||
"romance",
|
||||
"science-fiction",
|
||||
"thriller",
|
||||
"war",
|
||||
"western",
|
||||
"kids",
|
||||
"reality",
|
||||
"politics",
|
||||
"soap",
|
||||
"talk"
|
||||
]
|
||||
},
|
||||
"kyoo.show_kind": {
|
||||
"name": "show_kind",
|
||||
"schema": "kyoo",
|
||||
"values": ["serie", "movie"]
|
||||
},
|
||||
"kyoo.show_status": {
|
||||
"name": "show_status",
|
||||
"schema": "kyoo",
|
||||
"values": ["unknown", "finished", "airing", "planned"]
|
||||
}
|
||||
},
|
||||
"schemas": {
|
||||
"kyoo": "kyoo"
|
||||
},
|
||||
"sequences": {},
|
||||
"roles": {},
|
||||
"policies": {},
|
||||
"views": {},
|
||||
"_meta": {
|
||||
"columns": {},
|
||||
"schemas": {},
|
||||
"tables": {}
|
||||
}
|
||||
}
|
||||
946
api/drizzle/meta/0006_snapshot.json
Normal file
946
api/drizzle/meta/0006_snapshot.json
Normal file
@@ -0,0 +1,946 @@
|
||||
{
|
||||
"id": "ca86d88f-b380-4b41-9c3d-d8acef369e4c",
|
||||
"prevId": "1d98727c-290d-4491-8bb8-74390da0c021",
|
||||
"version": "7",
|
||||
"dialect": "postgresql",
|
||||
"tables": {
|
||||
"kyoo.entries": {
|
||||
"name": "entries",
|
||||
"schema": "kyoo",
|
||||
"columns": {
|
||||
"pk": {
|
||||
"name": "pk",
|
||||
"type": "integer",
|
||||
"primaryKey": true,
|
||||
"notNull": true,
|
||||
"identity": {
|
||||
"type": "always",
|
||||
"name": "entries_pk_seq",
|
||||
"schema": "kyoo",
|
||||
"increment": "1",
|
||||
"startWith": "1",
|
||||
"minValue": "1",
|
||||
"maxValue": "2147483647",
|
||||
"cache": "1",
|
||||
"cycle": false
|
||||
}
|
||||
},
|
||||
"id": {
|
||||
"name": "id",
|
||||
"type": "uuid",
|
||||
"primaryKey": false,
|
||||
"notNull": true,
|
||||
"default": "gen_random_uuid()"
|
||||
},
|
||||
"slug": {
|
||||
"name": "slug",
|
||||
"type": "varchar(255)",
|
||||
"primaryKey": false,
|
||||
"notNull": true
|
||||
},
|
||||
"show_pk": {
|
||||
"name": "show_pk",
|
||||
"type": "integer",
|
||||
"primaryKey": false,
|
||||
"notNull": false
|
||||
},
|
||||
"order": {
|
||||
"name": "order",
|
||||
"type": "real",
|
||||
"primaryKey": false,
|
||||
"notNull": false
|
||||
},
|
||||
"season_number": {
|
||||
"name": "season_number",
|
||||
"type": "integer",
|
||||
"primaryKey": false,
|
||||
"notNull": false
|
||||
},
|
||||
"episode_number": {
|
||||
"name": "episode_number",
|
||||
"type": "integer",
|
||||
"primaryKey": false,
|
||||
"notNull": false
|
||||
},
|
||||
"type": {
|
||||
"name": "type",
|
||||
"type": "entry_type",
|
||||
"typeSchema": "kyoo",
|
||||
"primaryKey": false,
|
||||
"notNull": true
|
||||
},
|
||||
"air_date": {
|
||||
"name": "air_date",
|
||||
"type": "date",
|
||||
"primaryKey": false,
|
||||
"notNull": false
|
||||
},
|
||||
"runtime": {
|
||||
"name": "runtime",
|
||||
"type": "integer",
|
||||
"primaryKey": false,
|
||||
"notNull": false
|
||||
},
|
||||
"thumbnails": {
|
||||
"name": "thumbnails",
|
||||
"type": "jsonb",
|
||||
"primaryKey": false,
|
||||
"notNull": false
|
||||
},
|
||||
"external_id": {
|
||||
"name": "external_id",
|
||||
"type": "jsonb",
|
||||
"primaryKey": false,
|
||||
"notNull": true,
|
||||
"default": "'{}'::jsonb"
|
||||
},
|
||||
"created_at": {
|
||||
"name": "created_at",
|
||||
"type": "timestamp with time zone",
|
||||
"primaryKey": false,
|
||||
"notNull": true,
|
||||
"default": "now()"
|
||||
},
|
||||
"next_refresh": {
|
||||
"name": "next_refresh",
|
||||
"type": "timestamp with time zone",
|
||||
"primaryKey": false,
|
||||
"notNull": true
|
||||
}
|
||||
},
|
||||
"indexes": {},
|
||||
"foreignKeys": {
|
||||
"entries_show_pk_shows_pk_fk": {
|
||||
"name": "entries_show_pk_shows_pk_fk",
|
||||
"tableFrom": "entries",
|
||||
"tableTo": "shows",
|
||||
"schemaTo": "kyoo",
|
||||
"columnsFrom": ["show_pk"],
|
||||
"columnsTo": ["pk"],
|
||||
"onDelete": "cascade",
|
||||
"onUpdate": "no action"
|
||||
}
|
||||
},
|
||||
"compositePrimaryKeys": {},
|
||||
"uniqueConstraints": {
|
||||
"entries_id_unique": {
|
||||
"name": "entries_id_unique",
|
||||
"nullsNotDistinct": false,
|
||||
"columns": ["id"]
|
||||
},
|
||||
"entries_slug_unique": {
|
||||
"name": "entries_slug_unique",
|
||||
"nullsNotDistinct": false,
|
||||
"columns": ["slug"]
|
||||
},
|
||||
"entries_showPk_seasonNumber_episodeNumber_unique": {
|
||||
"name": "entries_showPk_seasonNumber_episodeNumber_unique",
|
||||
"nullsNotDistinct": false,
|
||||
"columns": ["show_pk", "season_number", "episode_number"]
|
||||
}
|
||||
},
|
||||
"policies": {},
|
||||
"checkConstraints": {
|
||||
"order_positive": {
|
||||
"name": "order_positive",
|
||||
"value": "\"kyoo\".\"entries\".\"order\" >= 0"
|
||||
}
|
||||
},
|
||||
"isRLSEnabled": false
|
||||
},
|
||||
"kyoo.entry_translations": {
|
||||
"name": "entry_translations",
|
||||
"schema": "kyoo",
|
||||
"columns": {
|
||||
"pk": {
|
||||
"name": "pk",
|
||||
"type": "integer",
|
||||
"primaryKey": false,
|
||||
"notNull": true
|
||||
},
|
||||
"language": {
|
||||
"name": "language",
|
||||
"type": "varchar(255)",
|
||||
"primaryKey": false,
|
||||
"notNull": true
|
||||
},
|
||||
"name": {
|
||||
"name": "name",
|
||||
"type": "text",
|
||||
"primaryKey": false,
|
||||
"notNull": false
|
||||
},
|
||||
"description": {
|
||||
"name": "description",
|
||||
"type": "text",
|
||||
"primaryKey": false,
|
||||
"notNull": false
|
||||
},
|
||||
"tagline": {
|
||||
"name": "tagline",
|
||||
"type": "text",
|
||||
"primaryKey": false,
|
||||
"notNull": false
|
||||
},
|
||||
"poster": {
|
||||
"name": "poster",
|
||||
"type": "jsonb",
|
||||
"primaryKey": false,
|
||||
"notNull": false
|
||||
}
|
||||
},
|
||||
"indexes": {},
|
||||
"foreignKeys": {
|
||||
"entry_translations_pk_entries_pk_fk": {
|
||||
"name": "entry_translations_pk_entries_pk_fk",
|
||||
"tableFrom": "entry_translations",
|
||||
"tableTo": "entries",
|
||||
"schemaTo": "kyoo",
|
||||
"columnsFrom": ["pk"],
|
||||
"columnsTo": ["pk"],
|
||||
"onDelete": "cascade",
|
||||
"onUpdate": "no action"
|
||||
}
|
||||
},
|
||||
"compositePrimaryKeys": {
|
||||
"entry_translations_pk_language_pk": {
|
||||
"name": "entry_translations_pk_language_pk",
|
||||
"columns": ["pk", "language"]
|
||||
}
|
||||
},
|
||||
"uniqueConstraints": {},
|
||||
"policies": {},
|
||||
"checkConstraints": {},
|
||||
"isRLSEnabled": false
|
||||
},
|
||||
"kyoo.season_translations": {
|
||||
"name": "season_translations",
|
||||
"schema": "kyoo",
|
||||
"columns": {
|
||||
"pk": {
|
||||
"name": "pk",
|
||||
"type": "integer",
|
||||
"primaryKey": false,
|
||||
"notNull": true
|
||||
},
|
||||
"language": {
|
||||
"name": "language",
|
||||
"type": "varchar(255)",
|
||||
"primaryKey": false,
|
||||
"notNull": true
|
||||
},
|
||||
"name": {
|
||||
"name": "name",
|
||||
"type": "text",
|
||||
"primaryKey": false,
|
||||
"notNull": false
|
||||
},
|
||||
"description": {
|
||||
"name": "description",
|
||||
"type": "text",
|
||||
"primaryKey": false,
|
||||
"notNull": false
|
||||
},
|
||||
"poster": {
|
||||
"name": "poster",
|
||||
"type": "jsonb",
|
||||
"primaryKey": false,
|
||||
"notNull": false
|
||||
},
|
||||
"thumbnail": {
|
||||
"name": "thumbnail",
|
||||
"type": "jsonb",
|
||||
"primaryKey": false,
|
||||
"notNull": false
|
||||
},
|
||||
"banner": {
|
||||
"name": "banner",
|
||||
"type": "jsonb",
|
||||
"primaryKey": false,
|
||||
"notNull": false
|
||||
}
|
||||
},
|
||||
"indexes": {},
|
||||
"foreignKeys": {
|
||||
"season_translations_pk_seasons_pk_fk": {
|
||||
"name": "season_translations_pk_seasons_pk_fk",
|
||||
"tableFrom": "season_translations",
|
||||
"tableTo": "seasons",
|
||||
"schemaTo": "kyoo",
|
||||
"columnsFrom": ["pk"],
|
||||
"columnsTo": ["pk"],
|
||||
"onDelete": "cascade",
|
||||
"onUpdate": "no action"
|
||||
}
|
||||
},
|
||||
"compositePrimaryKeys": {
|
||||
"season_translations_pk_language_pk": {
|
||||
"name": "season_translations_pk_language_pk",
|
||||
"columns": ["pk", "language"]
|
||||
}
|
||||
},
|
||||
"uniqueConstraints": {},
|
||||
"policies": {},
|
||||
"checkConstraints": {},
|
||||
"isRLSEnabled": false
|
||||
},
|
||||
"kyoo.seasons": {
|
||||
"name": "seasons",
|
||||
"schema": "kyoo",
|
||||
"columns": {
|
||||
"pk": {
|
||||
"name": "pk",
|
||||
"type": "integer",
|
||||
"primaryKey": true,
|
||||
"notNull": true,
|
||||
"identity": {
|
||||
"type": "always",
|
||||
"name": "seasons_pk_seq",
|
||||
"schema": "kyoo",
|
||||
"increment": "1",
|
||||
"startWith": "1",
|
||||
"minValue": "1",
|
||||
"maxValue": "2147483647",
|
||||
"cache": "1",
|
||||
"cycle": false
|
||||
}
|
||||
},
|
||||
"id": {
|
||||
"name": "id",
|
||||
"type": "uuid",
|
||||
"primaryKey": false,
|
||||
"notNull": true,
|
||||
"default": "gen_random_uuid()"
|
||||
},
|
||||
"slug": {
|
||||
"name": "slug",
|
||||
"type": "varchar(255)",
|
||||
"primaryKey": false,
|
||||
"notNull": true
|
||||
},
|
||||
"show_pk": {
|
||||
"name": "show_pk",
|
||||
"type": "integer",
|
||||
"primaryKey": false,
|
||||
"notNull": false
|
||||
},
|
||||
"season_number": {
|
||||
"name": "season_number",
|
||||
"type": "integer",
|
||||
"primaryKey": false,
|
||||
"notNull": true
|
||||
},
|
||||
"start_air": {
|
||||
"name": "start_air",
|
||||
"type": "date",
|
||||
"primaryKey": false,
|
||||
"notNull": false
|
||||
},
|
||||
"end_air": {
|
||||
"name": "end_air",
|
||||
"type": "date",
|
||||
"primaryKey": false,
|
||||
"notNull": false
|
||||
},
|
||||
"external_id": {
|
||||
"name": "external_id",
|
||||
"type": "jsonb",
|
||||
"primaryKey": false,
|
||||
"notNull": true,
|
||||
"default": "'{}'::jsonb"
|
||||
},
|
||||
"created_at": {
|
||||
"name": "created_at",
|
||||
"type": "timestamp with time zone",
|
||||
"primaryKey": false,
|
||||
"notNull": true,
|
||||
"default": "now()"
|
||||
},
|
||||
"next_refresh": {
|
||||
"name": "next_refresh",
|
||||
"type": "timestamp with time zone",
|
||||
"primaryKey": false,
|
||||
"notNull": true
|
||||
}
|
||||
},
|
||||
"indexes": {
|
||||
"show_fk": {
|
||||
"name": "show_fk",
|
||||
"columns": [
|
||||
{
|
||||
"expression": "show_pk",
|
||||
"isExpression": false,
|
||||
"asc": true,
|
||||
"nulls": "last"
|
||||
}
|
||||
],
|
||||
"isUnique": false,
|
||||
"concurrently": false,
|
||||
"method": "hash",
|
||||
"with": {}
|
||||
}
|
||||
},
|
||||
"foreignKeys": {
|
||||
"seasons_show_pk_shows_pk_fk": {
|
||||
"name": "seasons_show_pk_shows_pk_fk",
|
||||
"tableFrom": "seasons",
|
||||
"tableTo": "shows",
|
||||
"schemaTo": "kyoo",
|
||||
"columnsFrom": ["show_pk"],
|
||||
"columnsTo": ["pk"],
|
||||
"onDelete": "cascade",
|
||||
"onUpdate": "no action"
|
||||
}
|
||||
},
|
||||
"compositePrimaryKeys": {},
|
||||
"uniqueConstraints": {
|
||||
"seasons_id_unique": {
|
||||
"name": "seasons_id_unique",
|
||||
"nullsNotDistinct": false,
|
||||
"columns": ["id"]
|
||||
},
|
||||
"seasons_slug_unique": {
|
||||
"name": "seasons_slug_unique",
|
||||
"nullsNotDistinct": false,
|
||||
"columns": ["slug"]
|
||||
},
|
||||
"seasons_showPk_seasonNumber_unique": {
|
||||
"name": "seasons_showPk_seasonNumber_unique",
|
||||
"nullsNotDistinct": false,
|
||||
"columns": ["show_pk", "season_number"]
|
||||
}
|
||||
},
|
||||
"policies": {},
|
||||
"checkConstraints": {},
|
||||
"isRLSEnabled": false
|
||||
},
|
||||
"kyoo.show_translations": {
|
||||
"name": "show_translations",
|
||||
"schema": "kyoo",
|
||||
"columns": {
|
||||
"pk": {
|
||||
"name": "pk",
|
||||
"type": "integer",
|
||||
"primaryKey": false,
|
||||
"notNull": true
|
||||
},
|
||||
"language": {
|
||||
"name": "language",
|
||||
"type": "varchar(255)",
|
||||
"primaryKey": false,
|
||||
"notNull": true
|
||||
},
|
||||
"name": {
|
||||
"name": "name",
|
||||
"type": "text",
|
||||
"primaryKey": false,
|
||||
"notNull": true
|
||||
},
|
||||
"description": {
|
||||
"name": "description",
|
||||
"type": "text",
|
||||
"primaryKey": false,
|
||||
"notNull": false
|
||||
},
|
||||
"tagline": {
|
||||
"name": "tagline",
|
||||
"type": "text",
|
||||
"primaryKey": false,
|
||||
"notNull": false
|
||||
},
|
||||
"aliases": {
|
||||
"name": "aliases",
|
||||
"type": "text[]",
|
||||
"primaryKey": false,
|
||||
"notNull": true
|
||||
},
|
||||
"tags": {
|
||||
"name": "tags",
|
||||
"type": "text[]",
|
||||
"primaryKey": false,
|
||||
"notNull": true
|
||||
},
|
||||
"poster": {
|
||||
"name": "poster",
|
||||
"type": "jsonb",
|
||||
"primaryKey": false,
|
||||
"notNull": false
|
||||
},
|
||||
"thumbnail": {
|
||||
"name": "thumbnail",
|
||||
"type": "jsonb",
|
||||
"primaryKey": false,
|
||||
"notNull": false
|
||||
},
|
||||
"banner": {
|
||||
"name": "banner",
|
||||
"type": "jsonb",
|
||||
"primaryKey": false,
|
||||
"notNull": false
|
||||
},
|
||||
"logo": {
|
||||
"name": "logo",
|
||||
"type": "jsonb",
|
||||
"primaryKey": false,
|
||||
"notNull": false
|
||||
},
|
||||
"trailer_url": {
|
||||
"name": "trailer_url",
|
||||
"type": "text",
|
||||
"primaryKey": false,
|
||||
"notNull": false
|
||||
}
|
||||
},
|
||||
"indexes": {
|
||||
"name_trgm": {
|
||||
"name": "name_trgm",
|
||||
"columns": [
|
||||
{
|
||||
"expression": "\"name\" gin_trgm_ops",
|
||||
"asc": true,
|
||||
"isExpression": true,
|
||||
"nulls": "last"
|
||||
}
|
||||
],
|
||||
"isUnique": false,
|
||||
"concurrently": false,
|
||||
"method": "gin",
|
||||
"with": {}
|
||||
},
|
||||
"tags": {
|
||||
"name": "tags",
|
||||
"columns": [
|
||||
{
|
||||
"expression": "tags",
|
||||
"isExpression": false,
|
||||
"asc": true,
|
||||
"nulls": "last"
|
||||
}
|
||||
],
|
||||
"isUnique": false,
|
||||
"concurrently": false,
|
||||
"method": "btree",
|
||||
"with": {}
|
||||
}
|
||||
},
|
||||
"foreignKeys": {
|
||||
"show_translations_pk_shows_pk_fk": {
|
||||
"name": "show_translations_pk_shows_pk_fk",
|
||||
"tableFrom": "show_translations",
|
||||
"tableTo": "shows",
|
||||
"schemaTo": "kyoo",
|
||||
"columnsFrom": ["pk"],
|
||||
"columnsTo": ["pk"],
|
||||
"onDelete": "cascade",
|
||||
"onUpdate": "no action"
|
||||
}
|
||||
},
|
||||
"compositePrimaryKeys": {
|
||||
"show_translations_pk_language_pk": {
|
||||
"name": "show_translations_pk_language_pk",
|
||||
"columns": ["pk", "language"]
|
||||
}
|
||||
},
|
||||
"uniqueConstraints": {},
|
||||
"policies": {},
|
||||
"checkConstraints": {},
|
||||
"isRLSEnabled": false
|
||||
},
|
||||
"kyoo.shows": {
|
||||
"name": "shows",
|
||||
"schema": "kyoo",
|
||||
"columns": {
|
||||
"pk": {
|
||||
"name": "pk",
|
||||
"type": "integer",
|
||||
"primaryKey": true,
|
||||
"notNull": true,
|
||||
"identity": {
|
||||
"type": "always",
|
||||
"name": "shows_pk_seq",
|
||||
"schema": "kyoo",
|
||||
"increment": "1",
|
||||
"startWith": "1",
|
||||
"minValue": "1",
|
||||
"maxValue": "2147483647",
|
||||
"cache": "1",
|
||||
"cycle": false
|
||||
}
|
||||
},
|
||||
"id": {
|
||||
"name": "id",
|
||||
"type": "uuid",
|
||||
"primaryKey": false,
|
||||
"notNull": true,
|
||||
"default": "gen_random_uuid()"
|
||||
},
|
||||
"slug": {
|
||||
"name": "slug",
|
||||
"type": "varchar(255)",
|
||||
"primaryKey": false,
|
||||
"notNull": true
|
||||
},
|
||||
"kind": {
|
||||
"name": "kind",
|
||||
"type": "show_kind",
|
||||
"typeSchema": "kyoo",
|
||||
"primaryKey": false,
|
||||
"notNull": true
|
||||
},
|
||||
"genres": {
|
||||
"name": "genres",
|
||||
"type": "genres[]",
|
||||
"primaryKey": false,
|
||||
"notNull": true
|
||||
},
|
||||
"rating": {
|
||||
"name": "rating",
|
||||
"type": "smallint",
|
||||
"primaryKey": false,
|
||||
"notNull": false
|
||||
},
|
||||
"runtime": {
|
||||
"name": "runtime",
|
||||
"type": "integer",
|
||||
"primaryKey": false,
|
||||
"notNull": false
|
||||
},
|
||||
"status": {
|
||||
"name": "status",
|
||||
"type": "show_status",
|
||||
"typeSchema": "kyoo",
|
||||
"primaryKey": false,
|
||||
"notNull": true
|
||||
},
|
||||
"start_air": {
|
||||
"name": "start_air",
|
||||
"type": "date",
|
||||
"primaryKey": false,
|
||||
"notNull": false
|
||||
},
|
||||
"end_air": {
|
||||
"name": "end_air",
|
||||
"type": "date",
|
||||
"primaryKey": false,
|
||||
"notNull": false
|
||||
},
|
||||
"original_language": {
|
||||
"name": "original_language",
|
||||
"type": "varchar(255)",
|
||||
"primaryKey": false,
|
||||
"notNull": false
|
||||
},
|
||||
"external_id": {
|
||||
"name": "external_id",
|
||||
"type": "jsonb",
|
||||
"primaryKey": false,
|
||||
"notNull": true,
|
||||
"default": "'{}'::jsonb"
|
||||
},
|
||||
"created_at": {
|
||||
"name": "created_at",
|
||||
"type": "timestamp with time zone",
|
||||
"primaryKey": false,
|
||||
"notNull": true,
|
||||
"default": "now()"
|
||||
},
|
||||
"next_refresh": {
|
||||
"name": "next_refresh",
|
||||
"type": "timestamp with time zone",
|
||||
"primaryKey": false,
|
||||
"notNull": true
|
||||
}
|
||||
},
|
||||
"indexes": {
|
||||
"kind": {
|
||||
"name": "kind",
|
||||
"columns": [
|
||||
{
|
||||
"expression": "kind",
|
||||
"isExpression": false,
|
||||
"asc": true,
|
||||
"nulls": "last"
|
||||
}
|
||||
],
|
||||
"isUnique": false,
|
||||
"concurrently": false,
|
||||
"method": "hash",
|
||||
"with": {}
|
||||
},
|
||||
"rating": {
|
||||
"name": "rating",
|
||||
"columns": [
|
||||
{
|
||||
"expression": "rating",
|
||||
"isExpression": false,
|
||||
"asc": true,
|
||||
"nulls": "last"
|
||||
}
|
||||
],
|
||||
"isUnique": false,
|
||||
"concurrently": false,
|
||||
"method": "btree",
|
||||
"with": {}
|
||||
},
|
||||
"startAir": {
|
||||
"name": "startAir",
|
||||
"columns": [
|
||||
{
|
||||
"expression": "start_air",
|
||||
"isExpression": false,
|
||||
"asc": true,
|
||||
"nulls": "last"
|
||||
}
|
||||
],
|
||||
"isUnique": false,
|
||||
"concurrently": false,
|
||||
"method": "btree",
|
||||
"with": {}
|
||||
}
|
||||
},
|
||||
"foreignKeys": {},
|
||||
"compositePrimaryKeys": {},
|
||||
"uniqueConstraints": {
|
||||
"shows_id_unique": {
|
||||
"name": "shows_id_unique",
|
||||
"nullsNotDistinct": false,
|
||||
"columns": ["id"]
|
||||
},
|
||||
"shows_slug_unique": {
|
||||
"name": "shows_slug_unique",
|
||||
"nullsNotDistinct": false,
|
||||
"columns": ["slug"]
|
||||
}
|
||||
},
|
||||
"policies": {},
|
||||
"checkConstraints": {
|
||||
"rating_valid": {
|
||||
"name": "rating_valid",
|
||||
"value": "\"kyoo\".\"shows\".\"rating\" between 0 and 100"
|
||||
},
|
||||
"runtime_valid": {
|
||||
"name": "runtime_valid",
|
||||
"value": "\"kyoo\".\"shows\".\"runtime\" >= 0"
|
||||
}
|
||||
},
|
||||
"isRLSEnabled": false
|
||||
},
|
||||
"kyoo.entry_video_jointure": {
|
||||
"name": "entry_video_jointure",
|
||||
"schema": "kyoo",
|
||||
"columns": {
|
||||
"entry": {
|
||||
"name": "entry",
|
||||
"type": "integer",
|
||||
"primaryKey": false,
|
||||
"notNull": true
|
||||
},
|
||||
"video": {
|
||||
"name": "video",
|
||||
"type": "integer",
|
||||
"primaryKey": false,
|
||||
"notNull": true
|
||||
},
|
||||
"slug": {
|
||||
"name": "slug",
|
||||
"type": "varchar(255)",
|
||||
"primaryKey": false,
|
||||
"notNull": true
|
||||
}
|
||||
},
|
||||
"indexes": {},
|
||||
"foreignKeys": {
|
||||
"entry_video_jointure_entry_entries_pk_fk": {
|
||||
"name": "entry_video_jointure_entry_entries_pk_fk",
|
||||
"tableFrom": "entry_video_jointure",
|
||||
"tableTo": "entries",
|
||||
"schemaTo": "kyoo",
|
||||
"columnsFrom": ["entry"],
|
||||
"columnsTo": ["pk"],
|
||||
"onDelete": "cascade",
|
||||
"onUpdate": "no action"
|
||||
},
|
||||
"entry_video_jointure_video_videos_pk_fk": {
|
||||
"name": "entry_video_jointure_video_videos_pk_fk",
|
||||
"tableFrom": "entry_video_jointure",
|
||||
"tableTo": "videos",
|
||||
"schemaTo": "kyoo",
|
||||
"columnsFrom": ["video"],
|
||||
"columnsTo": ["pk"],
|
||||
"onDelete": "cascade",
|
||||
"onUpdate": "no action"
|
||||
}
|
||||
},
|
||||
"compositePrimaryKeys": {
|
||||
"entry_video_jointure_entry_video_pk": {
|
||||
"name": "entry_video_jointure_entry_video_pk",
|
||||
"columns": ["entry", "video"]
|
||||
}
|
||||
},
|
||||
"uniqueConstraints": {
|
||||
"entry_video_jointure_slug_unique": {
|
||||
"name": "entry_video_jointure_slug_unique",
|
||||
"nullsNotDistinct": false,
|
||||
"columns": ["slug"]
|
||||
}
|
||||
},
|
||||
"policies": {},
|
||||
"checkConstraints": {},
|
||||
"isRLSEnabled": false
|
||||
},
|
||||
"kyoo.videos": {
|
||||
"name": "videos",
|
||||
"schema": "kyoo",
|
||||
"columns": {
|
||||
"pk": {
|
||||
"name": "pk",
|
||||
"type": "integer",
|
||||
"primaryKey": true,
|
||||
"notNull": true,
|
||||
"identity": {
|
||||
"type": "always",
|
||||
"name": "videos_pk_seq",
|
||||
"schema": "kyoo",
|
||||
"increment": "1",
|
||||
"startWith": "1",
|
||||
"minValue": "1",
|
||||
"maxValue": "2147483647",
|
||||
"cache": "1",
|
||||
"cycle": false
|
||||
}
|
||||
},
|
||||
"id": {
|
||||
"name": "id",
|
||||
"type": "uuid",
|
||||
"primaryKey": false,
|
||||
"notNull": true,
|
||||
"default": "gen_random_uuid()"
|
||||
},
|
||||
"path": {
|
||||
"name": "path",
|
||||
"type": "text",
|
||||
"primaryKey": false,
|
||||
"notNull": true
|
||||
},
|
||||
"rendering": {
|
||||
"name": "rendering",
|
||||
"type": "text",
|
||||
"primaryKey": false,
|
||||
"notNull": true
|
||||
},
|
||||
"part": {
|
||||
"name": "part",
|
||||
"type": "integer",
|
||||
"primaryKey": false,
|
||||
"notNull": false
|
||||
},
|
||||
"version": {
|
||||
"name": "version",
|
||||
"type": "integer",
|
||||
"primaryKey": false,
|
||||
"notNull": true,
|
||||
"default": 1
|
||||
},
|
||||
"guess": {
|
||||
"name": "guess",
|
||||
"type": "jsonb",
|
||||
"primaryKey": false,
|
||||
"notNull": true,
|
||||
"default": "'{}'::jsonb"
|
||||
},
|
||||
"created_at": {
|
||||
"name": "created_at",
|
||||
"type": "timestamp with time zone",
|
||||
"primaryKey": false,
|
||||
"notNull": true,
|
||||
"default": "now()"
|
||||
}
|
||||
},
|
||||
"indexes": {},
|
||||
"foreignKeys": {},
|
||||
"compositePrimaryKeys": {},
|
||||
"uniqueConstraints": {
|
||||
"videos_id_unique": {
|
||||
"name": "videos_id_unique",
|
||||
"nullsNotDistinct": false,
|
||||
"columns": ["id"]
|
||||
},
|
||||
"videos_path_unique": {
|
||||
"name": "videos_path_unique",
|
||||
"nullsNotDistinct": false,
|
||||
"columns": ["path"]
|
||||
}
|
||||
},
|
||||
"policies": {},
|
||||
"checkConstraints": {
|
||||
"part_pos": {
|
||||
"name": "part_pos",
|
||||
"value": "\"kyoo\".\"videos\".\"part\" >= 0"
|
||||
},
|
||||
"version_pos": {
|
||||
"name": "version_pos",
|
||||
"value": "\"kyoo\".\"videos\".\"version\" >= 0"
|
||||
}
|
||||
},
|
||||
"isRLSEnabled": false
|
||||
}
|
||||
},
|
||||
"enums": {
|
||||
"kyoo.entry_type": {
|
||||
"name": "entry_type",
|
||||
"schema": "kyoo",
|
||||
"values": ["unknown", "episode", "movie", "special", "extra"]
|
||||
},
|
||||
"kyoo.genres": {
|
||||
"name": "genres",
|
||||
"schema": "kyoo",
|
||||
"values": [
|
||||
"action",
|
||||
"adventure",
|
||||
"animation",
|
||||
"comedy",
|
||||
"crime",
|
||||
"documentary",
|
||||
"drama",
|
||||
"family",
|
||||
"fantasy",
|
||||
"history",
|
||||
"horror",
|
||||
"music",
|
||||
"mystery",
|
||||
"romance",
|
||||
"science-fiction",
|
||||
"thriller",
|
||||
"war",
|
||||
"western",
|
||||
"kids",
|
||||
"reality",
|
||||
"politics",
|
||||
"soap",
|
||||
"talk"
|
||||
]
|
||||
},
|
||||
"kyoo.show_kind": {
|
||||
"name": "show_kind",
|
||||
"schema": "kyoo",
|
||||
"values": ["serie", "movie"]
|
||||
},
|
||||
"kyoo.show_status": {
|
||||
"name": "show_status",
|
||||
"schema": "kyoo",
|
||||
"values": ["unknown", "finished", "airing", "planned"]
|
||||
}
|
||||
},
|
||||
"schemas": {
|
||||
"kyoo": "kyoo"
|
||||
},
|
||||
"sequences": {},
|
||||
"roles": {},
|
||||
"policies": {},
|
||||
"views": {},
|
||||
"_meta": {
|
||||
"columns": {},
|
||||
"schemas": {},
|
||||
"tables": {}
|
||||
}
|
||||
}
|
||||
952
api/drizzle/meta/0007_snapshot.json
Normal file
952
api/drizzle/meta/0007_snapshot.json
Normal file
@@ -0,0 +1,952 @@
|
||||
{
|
||||
"id": "e70b1585-a927-4436-b2a0-d0ef216911f1",
|
||||
"prevId": "ca86d88f-b380-4b41-9c3d-d8acef369e4c",
|
||||
"version": "7",
|
||||
"dialect": "postgresql",
|
||||
"tables": {
|
||||
"kyoo.entries": {
|
||||
"name": "entries",
|
||||
"schema": "kyoo",
|
||||
"columns": {
|
||||
"pk": {
|
||||
"name": "pk",
|
||||
"type": "integer",
|
||||
"primaryKey": true,
|
||||
"notNull": true,
|
||||
"identity": {
|
||||
"type": "always",
|
||||
"name": "entries_pk_seq",
|
||||
"schema": "kyoo",
|
||||
"increment": "1",
|
||||
"startWith": "1",
|
||||
"minValue": "1",
|
||||
"maxValue": "2147483647",
|
||||
"cache": "1",
|
||||
"cycle": false
|
||||
}
|
||||
},
|
||||
"id": {
|
||||
"name": "id",
|
||||
"type": "uuid",
|
||||
"primaryKey": false,
|
||||
"notNull": true,
|
||||
"default": "gen_random_uuid()"
|
||||
},
|
||||
"slug": {
|
||||
"name": "slug",
|
||||
"type": "varchar(255)",
|
||||
"primaryKey": false,
|
||||
"notNull": true
|
||||
},
|
||||
"show_pk": {
|
||||
"name": "show_pk",
|
||||
"type": "integer",
|
||||
"primaryKey": false,
|
||||
"notNull": true
|
||||
},
|
||||
"order": {
|
||||
"name": "order",
|
||||
"type": "real",
|
||||
"primaryKey": false,
|
||||
"notNull": false
|
||||
},
|
||||
"season_number": {
|
||||
"name": "season_number",
|
||||
"type": "integer",
|
||||
"primaryKey": false,
|
||||
"notNull": false
|
||||
},
|
||||
"episode_number": {
|
||||
"name": "episode_number",
|
||||
"type": "integer",
|
||||
"primaryKey": false,
|
||||
"notNull": false
|
||||
},
|
||||
"kind": {
|
||||
"name": "kind",
|
||||
"type": "entry_type",
|
||||
"typeSchema": "kyoo",
|
||||
"primaryKey": false,
|
||||
"notNull": true
|
||||
},
|
||||
"extra_kind": {
|
||||
"name": "extra_kind",
|
||||
"type": "text",
|
||||
"primaryKey": false,
|
||||
"notNull": false
|
||||
},
|
||||
"air_date": {
|
||||
"name": "air_date",
|
||||
"type": "date",
|
||||
"primaryKey": false,
|
||||
"notNull": false
|
||||
},
|
||||
"runtime": {
|
||||
"name": "runtime",
|
||||
"type": "integer",
|
||||
"primaryKey": false,
|
||||
"notNull": false
|
||||
},
|
||||
"thumbnails": {
|
||||
"name": "thumbnails",
|
||||
"type": "jsonb",
|
||||
"primaryKey": false,
|
||||
"notNull": false
|
||||
},
|
||||
"external_id": {
|
||||
"name": "external_id",
|
||||
"type": "jsonb",
|
||||
"primaryKey": false,
|
||||
"notNull": true,
|
||||
"default": "'{}'::jsonb"
|
||||
},
|
||||
"created_at": {
|
||||
"name": "created_at",
|
||||
"type": "timestamp with time zone",
|
||||
"primaryKey": false,
|
||||
"notNull": true,
|
||||
"default": "now()"
|
||||
},
|
||||
"next_refresh": {
|
||||
"name": "next_refresh",
|
||||
"type": "timestamp with time zone",
|
||||
"primaryKey": false,
|
||||
"notNull": true
|
||||
}
|
||||
},
|
||||
"indexes": {},
|
||||
"foreignKeys": {
|
||||
"entries_show_pk_shows_pk_fk": {
|
||||
"name": "entries_show_pk_shows_pk_fk",
|
||||
"tableFrom": "entries",
|
||||
"tableTo": "shows",
|
||||
"schemaTo": "kyoo",
|
||||
"columnsFrom": ["show_pk"],
|
||||
"columnsTo": ["pk"],
|
||||
"onDelete": "cascade",
|
||||
"onUpdate": "no action"
|
||||
}
|
||||
},
|
||||
"compositePrimaryKeys": {},
|
||||
"uniqueConstraints": {
|
||||
"entries_id_unique": {
|
||||
"name": "entries_id_unique",
|
||||
"nullsNotDistinct": false,
|
||||
"columns": ["id"]
|
||||
},
|
||||
"entries_slug_unique": {
|
||||
"name": "entries_slug_unique",
|
||||
"nullsNotDistinct": false,
|
||||
"columns": ["slug"]
|
||||
},
|
||||
"entries_showPk_seasonNumber_episodeNumber_unique": {
|
||||
"name": "entries_showPk_seasonNumber_episodeNumber_unique",
|
||||
"nullsNotDistinct": false,
|
||||
"columns": ["show_pk", "season_number", "episode_number"]
|
||||
}
|
||||
},
|
||||
"policies": {},
|
||||
"checkConstraints": {
|
||||
"order_positive": {
|
||||
"name": "order_positive",
|
||||
"value": "\"kyoo\".\"entries\".\"order\" >= 0"
|
||||
}
|
||||
},
|
||||
"isRLSEnabled": false
|
||||
},
|
||||
"kyoo.entry_translations": {
|
||||
"name": "entry_translations",
|
||||
"schema": "kyoo",
|
||||
"columns": {
|
||||
"pk": {
|
||||
"name": "pk",
|
||||
"type": "integer",
|
||||
"primaryKey": false,
|
||||
"notNull": true
|
||||
},
|
||||
"language": {
|
||||
"name": "language",
|
||||
"type": "varchar(255)",
|
||||
"primaryKey": false,
|
||||
"notNull": true
|
||||
},
|
||||
"name": {
|
||||
"name": "name",
|
||||
"type": "text",
|
||||
"primaryKey": false,
|
||||
"notNull": false
|
||||
},
|
||||
"description": {
|
||||
"name": "description",
|
||||
"type": "text",
|
||||
"primaryKey": false,
|
||||
"notNull": false
|
||||
},
|
||||
"tagline": {
|
||||
"name": "tagline",
|
||||
"type": "text",
|
||||
"primaryKey": false,
|
||||
"notNull": false
|
||||
},
|
||||
"poster": {
|
||||
"name": "poster",
|
||||
"type": "jsonb",
|
||||
"primaryKey": false,
|
||||
"notNull": false
|
||||
}
|
||||
},
|
||||
"indexes": {},
|
||||
"foreignKeys": {
|
||||
"entry_translations_pk_entries_pk_fk": {
|
||||
"name": "entry_translations_pk_entries_pk_fk",
|
||||
"tableFrom": "entry_translations",
|
||||
"tableTo": "entries",
|
||||
"schemaTo": "kyoo",
|
||||
"columnsFrom": ["pk"],
|
||||
"columnsTo": ["pk"],
|
||||
"onDelete": "cascade",
|
||||
"onUpdate": "no action"
|
||||
}
|
||||
},
|
||||
"compositePrimaryKeys": {
|
||||
"entry_translations_pk_language_pk": {
|
||||
"name": "entry_translations_pk_language_pk",
|
||||
"columns": ["pk", "language"]
|
||||
}
|
||||
},
|
||||
"uniqueConstraints": {},
|
||||
"policies": {},
|
||||
"checkConstraints": {},
|
||||
"isRLSEnabled": false
|
||||
},
|
||||
"kyoo.season_translations": {
|
||||
"name": "season_translations",
|
||||
"schema": "kyoo",
|
||||
"columns": {
|
||||
"pk": {
|
||||
"name": "pk",
|
||||
"type": "integer",
|
||||
"primaryKey": false,
|
||||
"notNull": true
|
||||
},
|
||||
"language": {
|
||||
"name": "language",
|
||||
"type": "varchar(255)",
|
||||
"primaryKey": false,
|
||||
"notNull": true
|
||||
},
|
||||
"name": {
|
||||
"name": "name",
|
||||
"type": "text",
|
||||
"primaryKey": false,
|
||||
"notNull": false
|
||||
},
|
||||
"description": {
|
||||
"name": "description",
|
||||
"type": "text",
|
||||
"primaryKey": false,
|
||||
"notNull": false
|
||||
},
|
||||
"poster": {
|
||||
"name": "poster",
|
||||
"type": "jsonb",
|
||||
"primaryKey": false,
|
||||
"notNull": false
|
||||
},
|
||||
"thumbnail": {
|
||||
"name": "thumbnail",
|
||||
"type": "jsonb",
|
||||
"primaryKey": false,
|
||||
"notNull": false
|
||||
},
|
||||
"banner": {
|
||||
"name": "banner",
|
||||
"type": "jsonb",
|
||||
"primaryKey": false,
|
||||
"notNull": false
|
||||
}
|
||||
},
|
||||
"indexes": {},
|
||||
"foreignKeys": {
|
||||
"season_translations_pk_seasons_pk_fk": {
|
||||
"name": "season_translations_pk_seasons_pk_fk",
|
||||
"tableFrom": "season_translations",
|
||||
"tableTo": "seasons",
|
||||
"schemaTo": "kyoo",
|
||||
"columnsFrom": ["pk"],
|
||||
"columnsTo": ["pk"],
|
||||
"onDelete": "cascade",
|
||||
"onUpdate": "no action"
|
||||
}
|
||||
},
|
||||
"compositePrimaryKeys": {
|
||||
"season_translations_pk_language_pk": {
|
||||
"name": "season_translations_pk_language_pk",
|
||||
"columns": ["pk", "language"]
|
||||
}
|
||||
},
|
||||
"uniqueConstraints": {},
|
||||
"policies": {},
|
||||
"checkConstraints": {},
|
||||
"isRLSEnabled": false
|
||||
},
|
||||
"kyoo.seasons": {
|
||||
"name": "seasons",
|
||||
"schema": "kyoo",
|
||||
"columns": {
|
||||
"pk": {
|
||||
"name": "pk",
|
||||
"type": "integer",
|
||||
"primaryKey": true,
|
||||
"notNull": true,
|
||||
"identity": {
|
||||
"type": "always",
|
||||
"name": "seasons_pk_seq",
|
||||
"schema": "kyoo",
|
||||
"increment": "1",
|
||||
"startWith": "1",
|
||||
"minValue": "1",
|
||||
"maxValue": "2147483647",
|
||||
"cache": "1",
|
||||
"cycle": false
|
||||
}
|
||||
},
|
||||
"id": {
|
||||
"name": "id",
|
||||
"type": "uuid",
|
||||
"primaryKey": false,
|
||||
"notNull": true,
|
||||
"default": "gen_random_uuid()"
|
||||
},
|
||||
"slug": {
|
||||
"name": "slug",
|
||||
"type": "varchar(255)",
|
||||
"primaryKey": false,
|
||||
"notNull": true
|
||||
},
|
||||
"show_pk": {
|
||||
"name": "show_pk",
|
||||
"type": "integer",
|
||||
"primaryKey": false,
|
||||
"notNull": false
|
||||
},
|
||||
"season_number": {
|
||||
"name": "season_number",
|
||||
"type": "integer",
|
||||
"primaryKey": false,
|
||||
"notNull": true
|
||||
},
|
||||
"start_air": {
|
||||
"name": "start_air",
|
||||
"type": "date",
|
||||
"primaryKey": false,
|
||||
"notNull": false
|
||||
},
|
||||
"end_air": {
|
||||
"name": "end_air",
|
||||
"type": "date",
|
||||
"primaryKey": false,
|
||||
"notNull": false
|
||||
},
|
||||
"external_id": {
|
||||
"name": "external_id",
|
||||
"type": "jsonb",
|
||||
"primaryKey": false,
|
||||
"notNull": true,
|
||||
"default": "'{}'::jsonb"
|
||||
},
|
||||
"created_at": {
|
||||
"name": "created_at",
|
||||
"type": "timestamp with time zone",
|
||||
"primaryKey": false,
|
||||
"notNull": true,
|
||||
"default": "now()"
|
||||
},
|
||||
"next_refresh": {
|
||||
"name": "next_refresh",
|
||||
"type": "timestamp with time zone",
|
||||
"primaryKey": false,
|
||||
"notNull": true
|
||||
}
|
||||
},
|
||||
"indexes": {
|
||||
"show_fk": {
|
||||
"name": "show_fk",
|
||||
"columns": [
|
||||
{
|
||||
"expression": "show_pk",
|
||||
"isExpression": false,
|
||||
"asc": true,
|
||||
"nulls": "last"
|
||||
}
|
||||
],
|
||||
"isUnique": false,
|
||||
"concurrently": false,
|
||||
"method": "hash",
|
||||
"with": {}
|
||||
}
|
||||
},
|
||||
"foreignKeys": {
|
||||
"seasons_show_pk_shows_pk_fk": {
|
||||
"name": "seasons_show_pk_shows_pk_fk",
|
||||
"tableFrom": "seasons",
|
||||
"tableTo": "shows",
|
||||
"schemaTo": "kyoo",
|
||||
"columnsFrom": ["show_pk"],
|
||||
"columnsTo": ["pk"],
|
||||
"onDelete": "cascade",
|
||||
"onUpdate": "no action"
|
||||
}
|
||||
},
|
||||
"compositePrimaryKeys": {},
|
||||
"uniqueConstraints": {
|
||||
"seasons_id_unique": {
|
||||
"name": "seasons_id_unique",
|
||||
"nullsNotDistinct": false,
|
||||
"columns": ["id"]
|
||||
},
|
||||
"seasons_slug_unique": {
|
||||
"name": "seasons_slug_unique",
|
||||
"nullsNotDistinct": false,
|
||||
"columns": ["slug"]
|
||||
},
|
||||
"seasons_showPk_seasonNumber_unique": {
|
||||
"name": "seasons_showPk_seasonNumber_unique",
|
||||
"nullsNotDistinct": false,
|
||||
"columns": ["show_pk", "season_number"]
|
||||
}
|
||||
},
|
||||
"policies": {},
|
||||
"checkConstraints": {},
|
||||
"isRLSEnabled": false
|
||||
},
|
||||
"kyoo.show_translations": {
|
||||
"name": "show_translations",
|
||||
"schema": "kyoo",
|
||||
"columns": {
|
||||
"pk": {
|
||||
"name": "pk",
|
||||
"type": "integer",
|
||||
"primaryKey": false,
|
||||
"notNull": true
|
||||
},
|
||||
"language": {
|
||||
"name": "language",
|
||||
"type": "varchar(255)",
|
||||
"primaryKey": false,
|
||||
"notNull": true
|
||||
},
|
||||
"name": {
|
||||
"name": "name",
|
||||
"type": "text",
|
||||
"primaryKey": false,
|
||||
"notNull": true
|
||||
},
|
||||
"description": {
|
||||
"name": "description",
|
||||
"type": "text",
|
||||
"primaryKey": false,
|
||||
"notNull": false
|
||||
},
|
||||
"tagline": {
|
||||
"name": "tagline",
|
||||
"type": "text",
|
||||
"primaryKey": false,
|
||||
"notNull": false
|
||||
},
|
||||
"aliases": {
|
||||
"name": "aliases",
|
||||
"type": "text[]",
|
||||
"primaryKey": false,
|
||||
"notNull": true
|
||||
},
|
||||
"tags": {
|
||||
"name": "tags",
|
||||
"type": "text[]",
|
||||
"primaryKey": false,
|
||||
"notNull": true
|
||||
},
|
||||
"poster": {
|
||||
"name": "poster",
|
||||
"type": "jsonb",
|
||||
"primaryKey": false,
|
||||
"notNull": false
|
||||
},
|
||||
"thumbnail": {
|
||||
"name": "thumbnail",
|
||||
"type": "jsonb",
|
||||
"primaryKey": false,
|
||||
"notNull": false
|
||||
},
|
||||
"banner": {
|
||||
"name": "banner",
|
||||
"type": "jsonb",
|
||||
"primaryKey": false,
|
||||
"notNull": false
|
||||
},
|
||||
"logo": {
|
||||
"name": "logo",
|
||||
"type": "jsonb",
|
||||
"primaryKey": false,
|
||||
"notNull": false
|
||||
},
|
||||
"trailer_url": {
|
||||
"name": "trailer_url",
|
||||
"type": "text",
|
||||
"primaryKey": false,
|
||||
"notNull": false
|
||||
}
|
||||
},
|
||||
"indexes": {
|
||||
"name_trgm": {
|
||||
"name": "name_trgm",
|
||||
"columns": [
|
||||
{
|
||||
"expression": "\"name\" gin_trgm_ops",
|
||||
"asc": true,
|
||||
"isExpression": true,
|
||||
"nulls": "last"
|
||||
}
|
||||
],
|
||||
"isUnique": false,
|
||||
"concurrently": false,
|
||||
"method": "gin",
|
||||
"with": {}
|
||||
},
|
||||
"tags": {
|
||||
"name": "tags",
|
||||
"columns": [
|
||||
{
|
||||
"expression": "tags",
|
||||
"isExpression": false,
|
||||
"asc": true,
|
||||
"nulls": "last"
|
||||
}
|
||||
],
|
||||
"isUnique": false,
|
||||
"concurrently": false,
|
||||
"method": "btree",
|
||||
"with": {}
|
||||
}
|
||||
},
|
||||
"foreignKeys": {
|
||||
"show_translations_pk_shows_pk_fk": {
|
||||
"name": "show_translations_pk_shows_pk_fk",
|
||||
"tableFrom": "show_translations",
|
||||
"tableTo": "shows",
|
||||
"schemaTo": "kyoo",
|
||||
"columnsFrom": ["pk"],
|
||||
"columnsTo": ["pk"],
|
||||
"onDelete": "cascade",
|
||||
"onUpdate": "no action"
|
||||
}
|
||||
},
|
||||
"compositePrimaryKeys": {
|
||||
"show_translations_pk_language_pk": {
|
||||
"name": "show_translations_pk_language_pk",
|
||||
"columns": ["pk", "language"]
|
||||
}
|
||||
},
|
||||
"uniqueConstraints": {},
|
||||
"policies": {},
|
||||
"checkConstraints": {},
|
||||
"isRLSEnabled": false
|
||||
},
|
||||
"kyoo.shows": {
|
||||
"name": "shows",
|
||||
"schema": "kyoo",
|
||||
"columns": {
|
||||
"pk": {
|
||||
"name": "pk",
|
||||
"type": "integer",
|
||||
"primaryKey": true,
|
||||
"notNull": true,
|
||||
"identity": {
|
||||
"type": "always",
|
||||
"name": "shows_pk_seq",
|
||||
"schema": "kyoo",
|
||||
"increment": "1",
|
||||
"startWith": "1",
|
||||
"minValue": "1",
|
||||
"maxValue": "2147483647",
|
||||
"cache": "1",
|
||||
"cycle": false
|
||||
}
|
||||
},
|
||||
"id": {
|
||||
"name": "id",
|
||||
"type": "uuid",
|
||||
"primaryKey": false,
|
||||
"notNull": true,
|
||||
"default": "gen_random_uuid()"
|
||||
},
|
||||
"slug": {
|
||||
"name": "slug",
|
||||
"type": "varchar(255)",
|
||||
"primaryKey": false,
|
||||
"notNull": true
|
||||
},
|
||||
"kind": {
|
||||
"name": "kind",
|
||||
"type": "show_kind",
|
||||
"typeSchema": "kyoo",
|
||||
"primaryKey": false,
|
||||
"notNull": true
|
||||
},
|
||||
"genres": {
|
||||
"name": "genres",
|
||||
"type": "genres[]",
|
||||
"primaryKey": false,
|
||||
"notNull": true
|
||||
},
|
||||
"rating": {
|
||||
"name": "rating",
|
||||
"type": "smallint",
|
||||
"primaryKey": false,
|
||||
"notNull": false
|
||||
},
|
||||
"runtime": {
|
||||
"name": "runtime",
|
||||
"type": "integer",
|
||||
"primaryKey": false,
|
||||
"notNull": false
|
||||
},
|
||||
"status": {
|
||||
"name": "status",
|
||||
"type": "show_status",
|
||||
"typeSchema": "kyoo",
|
||||
"primaryKey": false,
|
||||
"notNull": true
|
||||
},
|
||||
"start_air": {
|
||||
"name": "start_air",
|
||||
"type": "date",
|
||||
"primaryKey": false,
|
||||
"notNull": false
|
||||
},
|
||||
"end_air": {
|
||||
"name": "end_air",
|
||||
"type": "date",
|
||||
"primaryKey": false,
|
||||
"notNull": false
|
||||
},
|
||||
"original_language": {
|
||||
"name": "original_language",
|
||||
"type": "varchar(255)",
|
||||
"primaryKey": false,
|
||||
"notNull": false
|
||||
},
|
||||
"external_id": {
|
||||
"name": "external_id",
|
||||
"type": "jsonb",
|
||||
"primaryKey": false,
|
||||
"notNull": true,
|
||||
"default": "'{}'::jsonb"
|
||||
},
|
||||
"created_at": {
|
||||
"name": "created_at",
|
||||
"type": "timestamp with time zone",
|
||||
"primaryKey": false,
|
||||
"notNull": true,
|
||||
"default": "now()"
|
||||
},
|
||||
"next_refresh": {
|
||||
"name": "next_refresh",
|
||||
"type": "timestamp with time zone",
|
||||
"primaryKey": false,
|
||||
"notNull": true
|
||||
}
|
||||
},
|
||||
"indexes": {
|
||||
"kind": {
|
||||
"name": "kind",
|
||||
"columns": [
|
||||
{
|
||||
"expression": "kind",
|
||||
"isExpression": false,
|
||||
"asc": true,
|
||||
"nulls": "last"
|
||||
}
|
||||
],
|
||||
"isUnique": false,
|
||||
"concurrently": false,
|
||||
"method": "hash",
|
||||
"with": {}
|
||||
},
|
||||
"rating": {
|
||||
"name": "rating",
|
||||
"columns": [
|
||||
{
|
||||
"expression": "rating",
|
||||
"isExpression": false,
|
||||
"asc": true,
|
||||
"nulls": "last"
|
||||
}
|
||||
],
|
||||
"isUnique": false,
|
||||
"concurrently": false,
|
||||
"method": "btree",
|
||||
"with": {}
|
||||
},
|
||||
"startAir": {
|
||||
"name": "startAir",
|
||||
"columns": [
|
||||
{
|
||||
"expression": "start_air",
|
||||
"isExpression": false,
|
||||
"asc": true,
|
||||
"nulls": "last"
|
||||
}
|
||||
],
|
||||
"isUnique": false,
|
||||
"concurrently": false,
|
||||
"method": "btree",
|
||||
"with": {}
|
||||
}
|
||||
},
|
||||
"foreignKeys": {},
|
||||
"compositePrimaryKeys": {},
|
||||
"uniqueConstraints": {
|
||||
"shows_id_unique": {
|
||||
"name": "shows_id_unique",
|
||||
"nullsNotDistinct": false,
|
||||
"columns": ["id"]
|
||||
},
|
||||
"shows_slug_unique": {
|
||||
"name": "shows_slug_unique",
|
||||
"nullsNotDistinct": false,
|
||||
"columns": ["slug"]
|
||||
}
|
||||
},
|
||||
"policies": {},
|
||||
"checkConstraints": {
|
||||
"rating_valid": {
|
||||
"name": "rating_valid",
|
||||
"value": "\"kyoo\".\"shows\".\"rating\" between 0 and 100"
|
||||
},
|
||||
"runtime_valid": {
|
||||
"name": "runtime_valid",
|
||||
"value": "\"kyoo\".\"shows\".\"runtime\" >= 0"
|
||||
}
|
||||
},
|
||||
"isRLSEnabled": false
|
||||
},
|
||||
"kyoo.entry_video_jointure": {
|
||||
"name": "entry_video_jointure",
|
||||
"schema": "kyoo",
|
||||
"columns": {
|
||||
"entry": {
|
||||
"name": "entry",
|
||||
"type": "integer",
|
||||
"primaryKey": false,
|
||||
"notNull": true
|
||||
},
|
||||
"video": {
|
||||
"name": "video",
|
||||
"type": "integer",
|
||||
"primaryKey": false,
|
||||
"notNull": true
|
||||
},
|
||||
"slug": {
|
||||
"name": "slug",
|
||||
"type": "varchar(255)",
|
||||
"primaryKey": false,
|
||||
"notNull": true
|
||||
}
|
||||
},
|
||||
"indexes": {},
|
||||
"foreignKeys": {
|
||||
"entry_video_jointure_entry_entries_pk_fk": {
|
||||
"name": "entry_video_jointure_entry_entries_pk_fk",
|
||||
"tableFrom": "entry_video_jointure",
|
||||
"tableTo": "entries",
|
||||
"schemaTo": "kyoo",
|
||||
"columnsFrom": ["entry"],
|
||||
"columnsTo": ["pk"],
|
||||
"onDelete": "cascade",
|
||||
"onUpdate": "no action"
|
||||
},
|
||||
"entry_video_jointure_video_videos_pk_fk": {
|
||||
"name": "entry_video_jointure_video_videos_pk_fk",
|
||||
"tableFrom": "entry_video_jointure",
|
||||
"tableTo": "videos",
|
||||
"schemaTo": "kyoo",
|
||||
"columnsFrom": ["video"],
|
||||
"columnsTo": ["pk"],
|
||||
"onDelete": "cascade",
|
||||
"onUpdate": "no action"
|
||||
}
|
||||
},
|
||||
"compositePrimaryKeys": {
|
||||
"entry_video_jointure_entry_video_pk": {
|
||||
"name": "entry_video_jointure_entry_video_pk",
|
||||
"columns": ["entry", "video"]
|
||||
}
|
||||
},
|
||||
"uniqueConstraints": {
|
||||
"entry_video_jointure_slug_unique": {
|
||||
"name": "entry_video_jointure_slug_unique",
|
||||
"nullsNotDistinct": false,
|
||||
"columns": ["slug"]
|
||||
}
|
||||
},
|
||||
"policies": {},
|
||||
"checkConstraints": {},
|
||||
"isRLSEnabled": false
|
||||
},
|
||||
"kyoo.videos": {
|
||||
"name": "videos",
|
||||
"schema": "kyoo",
|
||||
"columns": {
|
||||
"pk": {
|
||||
"name": "pk",
|
||||
"type": "integer",
|
||||
"primaryKey": true,
|
||||
"notNull": true,
|
||||
"identity": {
|
||||
"type": "always",
|
||||
"name": "videos_pk_seq",
|
||||
"schema": "kyoo",
|
||||
"increment": "1",
|
||||
"startWith": "1",
|
||||
"minValue": "1",
|
||||
"maxValue": "2147483647",
|
||||
"cache": "1",
|
||||
"cycle": false
|
||||
}
|
||||
},
|
||||
"id": {
|
||||
"name": "id",
|
||||
"type": "uuid",
|
||||
"primaryKey": false,
|
||||
"notNull": true,
|
||||
"default": "gen_random_uuid()"
|
||||
},
|
||||
"path": {
|
||||
"name": "path",
|
||||
"type": "text",
|
||||
"primaryKey": false,
|
||||
"notNull": true
|
||||
},
|
||||
"rendering": {
|
||||
"name": "rendering",
|
||||
"type": "text",
|
||||
"primaryKey": false,
|
||||
"notNull": true
|
||||
},
|
||||
"part": {
|
||||
"name": "part",
|
||||
"type": "integer",
|
||||
"primaryKey": false,
|
||||
"notNull": false
|
||||
},
|
||||
"version": {
|
||||
"name": "version",
|
||||
"type": "integer",
|
||||
"primaryKey": false,
|
||||
"notNull": true,
|
||||
"default": 1
|
||||
},
|
||||
"guess": {
|
||||
"name": "guess",
|
||||
"type": "jsonb",
|
||||
"primaryKey": false,
|
||||
"notNull": true,
|
||||
"default": "'{}'::jsonb"
|
||||
},
|
||||
"created_at": {
|
||||
"name": "created_at",
|
||||
"type": "timestamp with time zone",
|
||||
"primaryKey": false,
|
||||
"notNull": true,
|
||||
"default": "now()"
|
||||
}
|
||||
},
|
||||
"indexes": {},
|
||||
"foreignKeys": {},
|
||||
"compositePrimaryKeys": {},
|
||||
"uniqueConstraints": {
|
||||
"videos_id_unique": {
|
||||
"name": "videos_id_unique",
|
||||
"nullsNotDistinct": false,
|
||||
"columns": ["id"]
|
||||
},
|
||||
"videos_path_unique": {
|
||||
"name": "videos_path_unique",
|
||||
"nullsNotDistinct": false,
|
||||
"columns": ["path"]
|
||||
}
|
||||
},
|
||||
"policies": {},
|
||||
"checkConstraints": {
|
||||
"part_pos": {
|
||||
"name": "part_pos",
|
||||
"value": "\"kyoo\".\"videos\".\"part\" >= 0"
|
||||
},
|
||||
"version_pos": {
|
||||
"name": "version_pos",
|
||||
"value": "\"kyoo\".\"videos\".\"version\" >= 0"
|
||||
}
|
||||
},
|
||||
"isRLSEnabled": false
|
||||
}
|
||||
},
|
||||
"enums": {
|
||||
"kyoo.entry_type": {
|
||||
"name": "entry_type",
|
||||
"schema": "kyoo",
|
||||
"values": ["unknown", "episode", "movie", "special", "extra"]
|
||||
},
|
||||
"kyoo.genres": {
|
||||
"name": "genres",
|
||||
"schema": "kyoo",
|
||||
"values": [
|
||||
"action",
|
||||
"adventure",
|
||||
"animation",
|
||||
"comedy",
|
||||
"crime",
|
||||
"documentary",
|
||||
"drama",
|
||||
"family",
|
||||
"fantasy",
|
||||
"history",
|
||||
"horror",
|
||||
"music",
|
||||
"mystery",
|
||||
"romance",
|
||||
"science-fiction",
|
||||
"thriller",
|
||||
"war",
|
||||
"western",
|
||||
"kids",
|
||||
"reality",
|
||||
"politics",
|
||||
"soap",
|
||||
"talk"
|
||||
]
|
||||
},
|
||||
"kyoo.show_kind": {
|
||||
"name": "show_kind",
|
||||
"schema": "kyoo",
|
||||
"values": ["serie", "movie"]
|
||||
},
|
||||
"kyoo.show_status": {
|
||||
"name": "show_status",
|
||||
"schema": "kyoo",
|
||||
"values": ["unknown", "finished", "airing", "planned"]
|
||||
}
|
||||
},
|
||||
"schemas": {
|
||||
"kyoo": "kyoo"
|
||||
},
|
||||
"sequences": {},
|
||||
"roles": {},
|
||||
"policies": {},
|
||||
"views": {},
|
||||
"_meta": {
|
||||
"columns": {},
|
||||
"schemas": {},
|
||||
"tables": {}
|
||||
}
|
||||
}
|
||||
952
api/drizzle/meta/0008_snapshot.json
Normal file
952
api/drizzle/meta/0008_snapshot.json
Normal file
@@ -0,0 +1,952 @@
|
||||
{
|
||||
"id": "5c17dd71-409a-4c80-870d-f12386676738",
|
||||
"prevId": "e70b1585-a927-4436-b2a0-d0ef216911f1",
|
||||
"version": "7",
|
||||
"dialect": "postgresql",
|
||||
"tables": {
|
||||
"kyoo.entries": {
|
||||
"name": "entries",
|
||||
"schema": "kyoo",
|
||||
"columns": {
|
||||
"pk": {
|
||||
"name": "pk",
|
||||
"type": "integer",
|
||||
"primaryKey": true,
|
||||
"notNull": true,
|
||||
"identity": {
|
||||
"type": "always",
|
||||
"name": "entries_pk_seq",
|
||||
"schema": "kyoo",
|
||||
"increment": "1",
|
||||
"startWith": "1",
|
||||
"minValue": "1",
|
||||
"maxValue": "2147483647",
|
||||
"cache": "1",
|
||||
"cycle": false
|
||||
}
|
||||
},
|
||||
"id": {
|
||||
"name": "id",
|
||||
"type": "uuid",
|
||||
"primaryKey": false,
|
||||
"notNull": true,
|
||||
"default": "gen_random_uuid()"
|
||||
},
|
||||
"slug": {
|
||||
"name": "slug",
|
||||
"type": "varchar(255)",
|
||||
"primaryKey": false,
|
||||
"notNull": true
|
||||
},
|
||||
"show_pk": {
|
||||
"name": "show_pk",
|
||||
"type": "integer",
|
||||
"primaryKey": false,
|
||||
"notNull": true
|
||||
},
|
||||
"order": {
|
||||
"name": "order",
|
||||
"type": "real",
|
||||
"primaryKey": false,
|
||||
"notNull": false
|
||||
},
|
||||
"season_number": {
|
||||
"name": "season_number",
|
||||
"type": "integer",
|
||||
"primaryKey": false,
|
||||
"notNull": false
|
||||
},
|
||||
"episode_number": {
|
||||
"name": "episode_number",
|
||||
"type": "integer",
|
||||
"primaryKey": false,
|
||||
"notNull": false
|
||||
},
|
||||
"kind": {
|
||||
"name": "kind",
|
||||
"type": "entry_type",
|
||||
"typeSchema": "kyoo",
|
||||
"primaryKey": false,
|
||||
"notNull": true
|
||||
},
|
||||
"extra_kind": {
|
||||
"name": "extra_kind",
|
||||
"type": "text",
|
||||
"primaryKey": false,
|
||||
"notNull": false
|
||||
},
|
||||
"air_date": {
|
||||
"name": "air_date",
|
||||
"type": "date",
|
||||
"primaryKey": false,
|
||||
"notNull": false
|
||||
},
|
||||
"runtime": {
|
||||
"name": "runtime",
|
||||
"type": "integer",
|
||||
"primaryKey": false,
|
||||
"notNull": false
|
||||
},
|
||||
"thumbnail": {
|
||||
"name": "thumbnail",
|
||||
"type": "jsonb",
|
||||
"primaryKey": false,
|
||||
"notNull": false
|
||||
},
|
||||
"external_id": {
|
||||
"name": "external_id",
|
||||
"type": "jsonb",
|
||||
"primaryKey": false,
|
||||
"notNull": true,
|
||||
"default": "'{}'::jsonb"
|
||||
},
|
||||
"created_at": {
|
||||
"name": "created_at",
|
||||
"type": "timestamp with time zone",
|
||||
"primaryKey": false,
|
||||
"notNull": true,
|
||||
"default": "now()"
|
||||
},
|
||||
"next_refresh": {
|
||||
"name": "next_refresh",
|
||||
"type": "timestamp with time zone",
|
||||
"primaryKey": false,
|
||||
"notNull": true
|
||||
}
|
||||
},
|
||||
"indexes": {},
|
||||
"foreignKeys": {
|
||||
"entries_show_pk_shows_pk_fk": {
|
||||
"name": "entries_show_pk_shows_pk_fk",
|
||||
"tableFrom": "entries",
|
||||
"tableTo": "shows",
|
||||
"schemaTo": "kyoo",
|
||||
"columnsFrom": ["show_pk"],
|
||||
"columnsTo": ["pk"],
|
||||
"onDelete": "cascade",
|
||||
"onUpdate": "no action"
|
||||
}
|
||||
},
|
||||
"compositePrimaryKeys": {},
|
||||
"uniqueConstraints": {
|
||||
"entries_id_unique": {
|
||||
"name": "entries_id_unique",
|
||||
"nullsNotDistinct": false,
|
||||
"columns": ["id"]
|
||||
},
|
||||
"entries_slug_unique": {
|
||||
"name": "entries_slug_unique",
|
||||
"nullsNotDistinct": false,
|
||||
"columns": ["slug"]
|
||||
},
|
||||
"entries_showPk_seasonNumber_episodeNumber_unique": {
|
||||
"name": "entries_showPk_seasonNumber_episodeNumber_unique",
|
||||
"nullsNotDistinct": false,
|
||||
"columns": ["show_pk", "season_number", "episode_number"]
|
||||
}
|
||||
},
|
||||
"policies": {},
|
||||
"checkConstraints": {
|
||||
"order_positive": {
|
||||
"name": "order_positive",
|
||||
"value": "\"kyoo\".\"entries\".\"order\" >= 0"
|
||||
}
|
||||
},
|
||||
"isRLSEnabled": false
|
||||
},
|
||||
"kyoo.entry_translations": {
|
||||
"name": "entry_translations",
|
||||
"schema": "kyoo",
|
||||
"columns": {
|
||||
"pk": {
|
||||
"name": "pk",
|
||||
"type": "integer",
|
||||
"primaryKey": false,
|
||||
"notNull": true
|
||||
},
|
||||
"language": {
|
||||
"name": "language",
|
||||
"type": "varchar(255)",
|
||||
"primaryKey": false,
|
||||
"notNull": true
|
||||
},
|
||||
"name": {
|
||||
"name": "name",
|
||||
"type": "text",
|
||||
"primaryKey": false,
|
||||
"notNull": false
|
||||
},
|
||||
"description": {
|
||||
"name": "description",
|
||||
"type": "text",
|
||||
"primaryKey": false,
|
||||
"notNull": false
|
||||
},
|
||||
"tagline": {
|
||||
"name": "tagline",
|
||||
"type": "text",
|
||||
"primaryKey": false,
|
||||
"notNull": false
|
||||
},
|
||||
"poster": {
|
||||
"name": "poster",
|
||||
"type": "jsonb",
|
||||
"primaryKey": false,
|
||||
"notNull": false
|
||||
}
|
||||
},
|
||||
"indexes": {},
|
||||
"foreignKeys": {
|
||||
"entry_translations_pk_entries_pk_fk": {
|
||||
"name": "entry_translations_pk_entries_pk_fk",
|
||||
"tableFrom": "entry_translations",
|
||||
"tableTo": "entries",
|
||||
"schemaTo": "kyoo",
|
||||
"columnsFrom": ["pk"],
|
||||
"columnsTo": ["pk"],
|
||||
"onDelete": "cascade",
|
||||
"onUpdate": "no action"
|
||||
}
|
||||
},
|
||||
"compositePrimaryKeys": {
|
||||
"entry_translations_pk_language_pk": {
|
||||
"name": "entry_translations_pk_language_pk",
|
||||
"columns": ["pk", "language"]
|
||||
}
|
||||
},
|
||||
"uniqueConstraints": {},
|
||||
"policies": {},
|
||||
"checkConstraints": {},
|
||||
"isRLSEnabled": false
|
||||
},
|
||||
"kyoo.season_translations": {
|
||||
"name": "season_translations",
|
||||
"schema": "kyoo",
|
||||
"columns": {
|
||||
"pk": {
|
||||
"name": "pk",
|
||||
"type": "integer",
|
||||
"primaryKey": false,
|
||||
"notNull": true
|
||||
},
|
||||
"language": {
|
||||
"name": "language",
|
||||
"type": "varchar(255)",
|
||||
"primaryKey": false,
|
||||
"notNull": true
|
||||
},
|
||||
"name": {
|
||||
"name": "name",
|
||||
"type": "text",
|
||||
"primaryKey": false,
|
||||
"notNull": false
|
||||
},
|
||||
"description": {
|
||||
"name": "description",
|
||||
"type": "text",
|
||||
"primaryKey": false,
|
||||
"notNull": false
|
||||
},
|
||||
"poster": {
|
||||
"name": "poster",
|
||||
"type": "jsonb",
|
||||
"primaryKey": false,
|
||||
"notNull": false
|
||||
},
|
||||
"thumbnail": {
|
||||
"name": "thumbnail",
|
||||
"type": "jsonb",
|
||||
"primaryKey": false,
|
||||
"notNull": false
|
||||
},
|
||||
"banner": {
|
||||
"name": "banner",
|
||||
"type": "jsonb",
|
||||
"primaryKey": false,
|
||||
"notNull": false
|
||||
}
|
||||
},
|
||||
"indexes": {},
|
||||
"foreignKeys": {
|
||||
"season_translations_pk_seasons_pk_fk": {
|
||||
"name": "season_translations_pk_seasons_pk_fk",
|
||||
"tableFrom": "season_translations",
|
||||
"tableTo": "seasons",
|
||||
"schemaTo": "kyoo",
|
||||
"columnsFrom": ["pk"],
|
||||
"columnsTo": ["pk"],
|
||||
"onDelete": "cascade",
|
||||
"onUpdate": "no action"
|
||||
}
|
||||
},
|
||||
"compositePrimaryKeys": {
|
||||
"season_translations_pk_language_pk": {
|
||||
"name": "season_translations_pk_language_pk",
|
||||
"columns": ["pk", "language"]
|
||||
}
|
||||
},
|
||||
"uniqueConstraints": {},
|
||||
"policies": {},
|
||||
"checkConstraints": {},
|
||||
"isRLSEnabled": false
|
||||
},
|
||||
"kyoo.seasons": {
|
||||
"name": "seasons",
|
||||
"schema": "kyoo",
|
||||
"columns": {
|
||||
"pk": {
|
||||
"name": "pk",
|
||||
"type": "integer",
|
||||
"primaryKey": true,
|
||||
"notNull": true,
|
||||
"identity": {
|
||||
"type": "always",
|
||||
"name": "seasons_pk_seq",
|
||||
"schema": "kyoo",
|
||||
"increment": "1",
|
||||
"startWith": "1",
|
||||
"minValue": "1",
|
||||
"maxValue": "2147483647",
|
||||
"cache": "1",
|
||||
"cycle": false
|
||||
}
|
||||
},
|
||||
"id": {
|
||||
"name": "id",
|
||||
"type": "uuid",
|
||||
"primaryKey": false,
|
||||
"notNull": true,
|
||||
"default": "gen_random_uuid()"
|
||||
},
|
||||
"slug": {
|
||||
"name": "slug",
|
||||
"type": "varchar(255)",
|
||||
"primaryKey": false,
|
||||
"notNull": true
|
||||
},
|
||||
"show_pk": {
|
||||
"name": "show_pk",
|
||||
"type": "integer",
|
||||
"primaryKey": false,
|
||||
"notNull": false
|
||||
},
|
||||
"season_number": {
|
||||
"name": "season_number",
|
||||
"type": "integer",
|
||||
"primaryKey": false,
|
||||
"notNull": true
|
||||
},
|
||||
"start_air": {
|
||||
"name": "start_air",
|
||||
"type": "date",
|
||||
"primaryKey": false,
|
||||
"notNull": false
|
||||
},
|
||||
"end_air": {
|
||||
"name": "end_air",
|
||||
"type": "date",
|
||||
"primaryKey": false,
|
||||
"notNull": false
|
||||
},
|
||||
"external_id": {
|
||||
"name": "external_id",
|
||||
"type": "jsonb",
|
||||
"primaryKey": false,
|
||||
"notNull": true,
|
||||
"default": "'{}'::jsonb"
|
||||
},
|
||||
"created_at": {
|
||||
"name": "created_at",
|
||||
"type": "timestamp with time zone",
|
||||
"primaryKey": false,
|
||||
"notNull": true,
|
||||
"default": "now()"
|
||||
},
|
||||
"next_refresh": {
|
||||
"name": "next_refresh",
|
||||
"type": "timestamp with time zone",
|
||||
"primaryKey": false,
|
||||
"notNull": true
|
||||
}
|
||||
},
|
||||
"indexes": {
|
||||
"show_fk": {
|
||||
"name": "show_fk",
|
||||
"columns": [
|
||||
{
|
||||
"expression": "show_pk",
|
||||
"isExpression": false,
|
||||
"asc": true,
|
||||
"nulls": "last"
|
||||
}
|
||||
],
|
||||
"isUnique": false,
|
||||
"concurrently": false,
|
||||
"method": "hash",
|
||||
"with": {}
|
||||
}
|
||||
},
|
||||
"foreignKeys": {
|
||||
"seasons_show_pk_shows_pk_fk": {
|
||||
"name": "seasons_show_pk_shows_pk_fk",
|
||||
"tableFrom": "seasons",
|
||||
"tableTo": "shows",
|
||||
"schemaTo": "kyoo",
|
||||
"columnsFrom": ["show_pk"],
|
||||
"columnsTo": ["pk"],
|
||||
"onDelete": "cascade",
|
||||
"onUpdate": "no action"
|
||||
}
|
||||
},
|
||||
"compositePrimaryKeys": {},
|
||||
"uniqueConstraints": {
|
||||
"seasons_id_unique": {
|
||||
"name": "seasons_id_unique",
|
||||
"nullsNotDistinct": false,
|
||||
"columns": ["id"]
|
||||
},
|
||||
"seasons_slug_unique": {
|
||||
"name": "seasons_slug_unique",
|
||||
"nullsNotDistinct": false,
|
||||
"columns": ["slug"]
|
||||
},
|
||||
"seasons_showPk_seasonNumber_unique": {
|
||||
"name": "seasons_showPk_seasonNumber_unique",
|
||||
"nullsNotDistinct": false,
|
||||
"columns": ["show_pk", "season_number"]
|
||||
}
|
||||
},
|
||||
"policies": {},
|
||||
"checkConstraints": {},
|
||||
"isRLSEnabled": false
|
||||
},
|
||||
"kyoo.show_translations": {
|
||||
"name": "show_translations",
|
||||
"schema": "kyoo",
|
||||
"columns": {
|
||||
"pk": {
|
||||
"name": "pk",
|
||||
"type": "integer",
|
||||
"primaryKey": false,
|
||||
"notNull": true
|
||||
},
|
||||
"language": {
|
||||
"name": "language",
|
||||
"type": "varchar(255)",
|
||||
"primaryKey": false,
|
||||
"notNull": true
|
||||
},
|
||||
"name": {
|
||||
"name": "name",
|
||||
"type": "text",
|
||||
"primaryKey": false,
|
||||
"notNull": true
|
||||
},
|
||||
"description": {
|
||||
"name": "description",
|
||||
"type": "text",
|
||||
"primaryKey": false,
|
||||
"notNull": false
|
||||
},
|
||||
"tagline": {
|
||||
"name": "tagline",
|
||||
"type": "text",
|
||||
"primaryKey": false,
|
||||
"notNull": false
|
||||
},
|
||||
"aliases": {
|
||||
"name": "aliases",
|
||||
"type": "text[]",
|
||||
"primaryKey": false,
|
||||
"notNull": true
|
||||
},
|
||||
"tags": {
|
||||
"name": "tags",
|
||||
"type": "text[]",
|
||||
"primaryKey": false,
|
||||
"notNull": true
|
||||
},
|
||||
"poster": {
|
||||
"name": "poster",
|
||||
"type": "jsonb",
|
||||
"primaryKey": false,
|
||||
"notNull": false
|
||||
},
|
||||
"thumbnail": {
|
||||
"name": "thumbnail",
|
||||
"type": "jsonb",
|
||||
"primaryKey": false,
|
||||
"notNull": false
|
||||
},
|
||||
"banner": {
|
||||
"name": "banner",
|
||||
"type": "jsonb",
|
||||
"primaryKey": false,
|
||||
"notNull": false
|
||||
},
|
||||
"logo": {
|
||||
"name": "logo",
|
||||
"type": "jsonb",
|
||||
"primaryKey": false,
|
||||
"notNull": false
|
||||
},
|
||||
"trailer_url": {
|
||||
"name": "trailer_url",
|
||||
"type": "text",
|
||||
"primaryKey": false,
|
||||
"notNull": false
|
||||
}
|
||||
},
|
||||
"indexes": {
|
||||
"name_trgm": {
|
||||
"name": "name_trgm",
|
||||
"columns": [
|
||||
{
|
||||
"expression": "\"name\" gin_trgm_ops",
|
||||
"asc": true,
|
||||
"isExpression": true,
|
||||
"nulls": "last"
|
||||
}
|
||||
],
|
||||
"isUnique": false,
|
||||
"concurrently": false,
|
||||
"method": "gin",
|
||||
"with": {}
|
||||
},
|
||||
"tags": {
|
||||
"name": "tags",
|
||||
"columns": [
|
||||
{
|
||||
"expression": "tags",
|
||||
"isExpression": false,
|
||||
"asc": true,
|
||||
"nulls": "last"
|
||||
}
|
||||
],
|
||||
"isUnique": false,
|
||||
"concurrently": false,
|
||||
"method": "btree",
|
||||
"with": {}
|
||||
}
|
||||
},
|
||||
"foreignKeys": {
|
||||
"show_translations_pk_shows_pk_fk": {
|
||||
"name": "show_translations_pk_shows_pk_fk",
|
||||
"tableFrom": "show_translations",
|
||||
"tableTo": "shows",
|
||||
"schemaTo": "kyoo",
|
||||
"columnsFrom": ["pk"],
|
||||
"columnsTo": ["pk"],
|
||||
"onDelete": "cascade",
|
||||
"onUpdate": "no action"
|
||||
}
|
||||
},
|
||||
"compositePrimaryKeys": {
|
||||
"show_translations_pk_language_pk": {
|
||||
"name": "show_translations_pk_language_pk",
|
||||
"columns": ["pk", "language"]
|
||||
}
|
||||
},
|
||||
"uniqueConstraints": {},
|
||||
"policies": {},
|
||||
"checkConstraints": {},
|
||||
"isRLSEnabled": false
|
||||
},
|
||||
"kyoo.shows": {
|
||||
"name": "shows",
|
||||
"schema": "kyoo",
|
||||
"columns": {
|
||||
"pk": {
|
||||
"name": "pk",
|
||||
"type": "integer",
|
||||
"primaryKey": true,
|
||||
"notNull": true,
|
||||
"identity": {
|
||||
"type": "always",
|
||||
"name": "shows_pk_seq",
|
||||
"schema": "kyoo",
|
||||
"increment": "1",
|
||||
"startWith": "1",
|
||||
"minValue": "1",
|
||||
"maxValue": "2147483647",
|
||||
"cache": "1",
|
||||
"cycle": false
|
||||
}
|
||||
},
|
||||
"id": {
|
||||
"name": "id",
|
||||
"type": "uuid",
|
||||
"primaryKey": false,
|
||||
"notNull": true,
|
||||
"default": "gen_random_uuid()"
|
||||
},
|
||||
"slug": {
|
||||
"name": "slug",
|
||||
"type": "varchar(255)",
|
||||
"primaryKey": false,
|
||||
"notNull": true
|
||||
},
|
||||
"kind": {
|
||||
"name": "kind",
|
||||
"type": "show_kind",
|
||||
"typeSchema": "kyoo",
|
||||
"primaryKey": false,
|
||||
"notNull": true
|
||||
},
|
||||
"genres": {
|
||||
"name": "genres",
|
||||
"type": "genres[]",
|
||||
"primaryKey": false,
|
||||
"notNull": true
|
||||
},
|
||||
"rating": {
|
||||
"name": "rating",
|
||||
"type": "smallint",
|
||||
"primaryKey": false,
|
||||
"notNull": false
|
||||
},
|
||||
"runtime": {
|
||||
"name": "runtime",
|
||||
"type": "integer",
|
||||
"primaryKey": false,
|
||||
"notNull": false
|
||||
},
|
||||
"status": {
|
||||
"name": "status",
|
||||
"type": "show_status",
|
||||
"typeSchema": "kyoo",
|
||||
"primaryKey": false,
|
||||
"notNull": true
|
||||
},
|
||||
"start_air": {
|
||||
"name": "start_air",
|
||||
"type": "date",
|
||||
"primaryKey": false,
|
||||
"notNull": false
|
||||
},
|
||||
"end_air": {
|
||||
"name": "end_air",
|
||||
"type": "date",
|
||||
"primaryKey": false,
|
||||
"notNull": false
|
||||
},
|
||||
"original_language": {
|
||||
"name": "original_language",
|
||||
"type": "varchar(255)",
|
||||
"primaryKey": false,
|
||||
"notNull": false
|
||||
},
|
||||
"external_id": {
|
||||
"name": "external_id",
|
||||
"type": "jsonb",
|
||||
"primaryKey": false,
|
||||
"notNull": true,
|
||||
"default": "'{}'::jsonb"
|
||||
},
|
||||
"created_at": {
|
||||
"name": "created_at",
|
||||
"type": "timestamp with time zone",
|
||||
"primaryKey": false,
|
||||
"notNull": true,
|
||||
"default": "now()"
|
||||
},
|
||||
"next_refresh": {
|
||||
"name": "next_refresh",
|
||||
"type": "timestamp with time zone",
|
||||
"primaryKey": false,
|
||||
"notNull": true
|
||||
}
|
||||
},
|
||||
"indexes": {
|
||||
"kind": {
|
||||
"name": "kind",
|
||||
"columns": [
|
||||
{
|
||||
"expression": "kind",
|
||||
"isExpression": false,
|
||||
"asc": true,
|
||||
"nulls": "last"
|
||||
}
|
||||
],
|
||||
"isUnique": false,
|
||||
"concurrently": false,
|
||||
"method": "hash",
|
||||
"with": {}
|
||||
},
|
||||
"rating": {
|
||||
"name": "rating",
|
||||
"columns": [
|
||||
{
|
||||
"expression": "rating",
|
||||
"isExpression": false,
|
||||
"asc": true,
|
||||
"nulls": "last"
|
||||
}
|
||||
],
|
||||
"isUnique": false,
|
||||
"concurrently": false,
|
||||
"method": "btree",
|
||||
"with": {}
|
||||
},
|
||||
"startAir": {
|
||||
"name": "startAir",
|
||||
"columns": [
|
||||
{
|
||||
"expression": "start_air",
|
||||
"isExpression": false,
|
||||
"asc": true,
|
||||
"nulls": "last"
|
||||
}
|
||||
],
|
||||
"isUnique": false,
|
||||
"concurrently": false,
|
||||
"method": "btree",
|
||||
"with": {}
|
||||
}
|
||||
},
|
||||
"foreignKeys": {},
|
||||
"compositePrimaryKeys": {},
|
||||
"uniqueConstraints": {
|
||||
"shows_id_unique": {
|
||||
"name": "shows_id_unique",
|
||||
"nullsNotDistinct": false,
|
||||
"columns": ["id"]
|
||||
},
|
||||
"shows_slug_unique": {
|
||||
"name": "shows_slug_unique",
|
||||
"nullsNotDistinct": false,
|
||||
"columns": ["slug"]
|
||||
}
|
||||
},
|
||||
"policies": {},
|
||||
"checkConstraints": {
|
||||
"rating_valid": {
|
||||
"name": "rating_valid",
|
||||
"value": "\"kyoo\".\"shows\".\"rating\" between 0 and 100"
|
||||
},
|
||||
"runtime_valid": {
|
||||
"name": "runtime_valid",
|
||||
"value": "\"kyoo\".\"shows\".\"runtime\" >= 0"
|
||||
}
|
||||
},
|
||||
"isRLSEnabled": false
|
||||
},
|
||||
"kyoo.entry_video_join": {
|
||||
"name": "entry_video_join",
|
||||
"schema": "kyoo",
|
||||
"columns": {
|
||||
"entry": {
|
||||
"name": "entry",
|
||||
"type": "integer",
|
||||
"primaryKey": false,
|
||||
"notNull": true
|
||||
},
|
||||
"video": {
|
||||
"name": "video",
|
||||
"type": "integer",
|
||||
"primaryKey": false,
|
||||
"notNull": true
|
||||
},
|
||||
"slug": {
|
||||
"name": "slug",
|
||||
"type": "varchar(255)",
|
||||
"primaryKey": false,
|
||||
"notNull": true
|
||||
}
|
||||
},
|
||||
"indexes": {},
|
||||
"foreignKeys": {
|
||||
"entry_video_join_entry_entries_pk_fk": {
|
||||
"name": "entry_video_join_entry_entries_pk_fk",
|
||||
"tableFrom": "entry_video_join",
|
||||
"tableTo": "entries",
|
||||
"schemaTo": "kyoo",
|
||||
"columnsFrom": ["entry"],
|
||||
"columnsTo": ["pk"],
|
||||
"onDelete": "cascade",
|
||||
"onUpdate": "no action"
|
||||
},
|
||||
"entry_video_join_video_videos_pk_fk": {
|
||||
"name": "entry_video_join_video_videos_pk_fk",
|
||||
"tableFrom": "entry_video_join",
|
||||
"tableTo": "videos",
|
||||
"schemaTo": "kyoo",
|
||||
"columnsFrom": ["video"],
|
||||
"columnsTo": ["pk"],
|
||||
"onDelete": "cascade",
|
||||
"onUpdate": "no action"
|
||||
}
|
||||
},
|
||||
"compositePrimaryKeys": {
|
||||
"entry_video_join_entry_video_pk": {
|
||||
"name": "entry_video_join_entry_video_pk",
|
||||
"columns": ["entry", "video"]
|
||||
}
|
||||
},
|
||||
"uniqueConstraints": {
|
||||
"entry_video_join_slug_unique": {
|
||||
"name": "entry_video_join_slug_unique",
|
||||
"nullsNotDistinct": false,
|
||||
"columns": ["slug"]
|
||||
}
|
||||
},
|
||||
"policies": {},
|
||||
"checkConstraints": {},
|
||||
"isRLSEnabled": false
|
||||
},
|
||||
"kyoo.videos": {
|
||||
"name": "videos",
|
||||
"schema": "kyoo",
|
||||
"columns": {
|
||||
"pk": {
|
||||
"name": "pk",
|
||||
"type": "integer",
|
||||
"primaryKey": true,
|
||||
"notNull": true,
|
||||
"identity": {
|
||||
"type": "always",
|
||||
"name": "videos_pk_seq",
|
||||
"schema": "kyoo",
|
||||
"increment": "1",
|
||||
"startWith": "1",
|
||||
"minValue": "1",
|
||||
"maxValue": "2147483647",
|
||||
"cache": "1",
|
||||
"cycle": false
|
||||
}
|
||||
},
|
||||
"id": {
|
||||
"name": "id",
|
||||
"type": "uuid",
|
||||
"primaryKey": false,
|
||||
"notNull": true,
|
||||
"default": "gen_random_uuid()"
|
||||
},
|
||||
"path": {
|
||||
"name": "path",
|
||||
"type": "text",
|
||||
"primaryKey": false,
|
||||
"notNull": true
|
||||
},
|
||||
"rendering": {
|
||||
"name": "rendering",
|
||||
"type": "text",
|
||||
"primaryKey": false,
|
||||
"notNull": true
|
||||
},
|
||||
"part": {
|
||||
"name": "part",
|
||||
"type": "integer",
|
||||
"primaryKey": false,
|
||||
"notNull": false
|
||||
},
|
||||
"version": {
|
||||
"name": "version",
|
||||
"type": "integer",
|
||||
"primaryKey": false,
|
||||
"notNull": true,
|
||||
"default": 1
|
||||
},
|
||||
"guess": {
|
||||
"name": "guess",
|
||||
"type": "jsonb",
|
||||
"primaryKey": false,
|
||||
"notNull": true,
|
||||
"default": "'{}'::jsonb"
|
||||
},
|
||||
"created_at": {
|
||||
"name": "created_at",
|
||||
"type": "timestamp with time zone",
|
||||
"primaryKey": false,
|
||||
"notNull": true,
|
||||
"default": "now()"
|
||||
}
|
||||
},
|
||||
"indexes": {},
|
||||
"foreignKeys": {},
|
||||
"compositePrimaryKeys": {},
|
||||
"uniqueConstraints": {
|
||||
"videos_id_unique": {
|
||||
"name": "videos_id_unique",
|
||||
"nullsNotDistinct": false,
|
||||
"columns": ["id"]
|
||||
},
|
||||
"videos_path_unique": {
|
||||
"name": "videos_path_unique",
|
||||
"nullsNotDistinct": false,
|
||||
"columns": ["path"]
|
||||
}
|
||||
},
|
||||
"policies": {},
|
||||
"checkConstraints": {
|
||||
"part_pos": {
|
||||
"name": "part_pos",
|
||||
"value": "\"kyoo\".\"videos\".\"part\" >= 0"
|
||||
},
|
||||
"version_pos": {
|
||||
"name": "version_pos",
|
||||
"value": "\"kyoo\".\"videos\".\"version\" >= 0"
|
||||
}
|
||||
},
|
||||
"isRLSEnabled": false
|
||||
}
|
||||
},
|
||||
"enums": {
|
||||
"kyoo.entry_type": {
|
||||
"name": "entry_type",
|
||||
"schema": "kyoo",
|
||||
"values": ["unknown", "episode", "movie", "special", "extra"]
|
||||
},
|
||||
"kyoo.genres": {
|
||||
"name": "genres",
|
||||
"schema": "kyoo",
|
||||
"values": [
|
||||
"action",
|
||||
"adventure",
|
||||
"animation",
|
||||
"comedy",
|
||||
"crime",
|
||||
"documentary",
|
||||
"drama",
|
||||
"family",
|
||||
"fantasy",
|
||||
"history",
|
||||
"horror",
|
||||
"music",
|
||||
"mystery",
|
||||
"romance",
|
||||
"science-fiction",
|
||||
"thriller",
|
||||
"war",
|
||||
"western",
|
||||
"kids",
|
||||
"reality",
|
||||
"politics",
|
||||
"soap",
|
||||
"talk"
|
||||
]
|
||||
},
|
||||
"kyoo.show_kind": {
|
||||
"name": "show_kind",
|
||||
"schema": "kyoo",
|
||||
"values": ["serie", "movie"]
|
||||
},
|
||||
"kyoo.show_status": {
|
||||
"name": "show_status",
|
||||
"schema": "kyoo",
|
||||
"values": ["unknown", "finished", "airing", "planned"]
|
||||
}
|
||||
},
|
||||
"schemas": {
|
||||
"kyoo": "kyoo"
|
||||
},
|
||||
"sequences": {},
|
||||
"roles": {},
|
||||
"policies": {},
|
||||
"views": {},
|
||||
"_meta": {
|
||||
"columns": {},
|
||||
"schemas": {},
|
||||
"tables": {}
|
||||
}
|
||||
}
|
||||
969
api/drizzle/meta/0009_snapshot.json
Normal file
969
api/drizzle/meta/0009_snapshot.json
Normal file
@@ -0,0 +1,969 @@
|
||||
{
|
||||
"id": "7a04670c-5fb9-4535-b6be-dc291b8b0b09",
|
||||
"prevId": "5c17dd71-409a-4c80-870d-f12386676738",
|
||||
"version": "7",
|
||||
"dialect": "postgresql",
|
||||
"tables": {
|
||||
"kyoo.entries": {
|
||||
"name": "entries",
|
||||
"schema": "kyoo",
|
||||
"columns": {
|
||||
"pk": {
|
||||
"name": "pk",
|
||||
"type": "integer",
|
||||
"primaryKey": true,
|
||||
"notNull": true,
|
||||
"identity": {
|
||||
"type": "always",
|
||||
"name": "entries_pk_seq",
|
||||
"schema": "kyoo",
|
||||
"increment": "1",
|
||||
"startWith": "1",
|
||||
"minValue": "1",
|
||||
"maxValue": "2147483647",
|
||||
"cache": "1",
|
||||
"cycle": false
|
||||
}
|
||||
},
|
||||
"id": {
|
||||
"name": "id",
|
||||
"type": "uuid",
|
||||
"primaryKey": false,
|
||||
"notNull": true,
|
||||
"default": "gen_random_uuid()"
|
||||
},
|
||||
"slug": {
|
||||
"name": "slug",
|
||||
"type": "varchar(255)",
|
||||
"primaryKey": false,
|
||||
"notNull": true
|
||||
},
|
||||
"show_pk": {
|
||||
"name": "show_pk",
|
||||
"type": "integer",
|
||||
"primaryKey": false,
|
||||
"notNull": true
|
||||
},
|
||||
"order": {
|
||||
"name": "order",
|
||||
"type": "real",
|
||||
"primaryKey": false,
|
||||
"notNull": false
|
||||
},
|
||||
"season_number": {
|
||||
"name": "season_number",
|
||||
"type": "integer",
|
||||
"primaryKey": false,
|
||||
"notNull": false
|
||||
},
|
||||
"episode_number": {
|
||||
"name": "episode_number",
|
||||
"type": "integer",
|
||||
"primaryKey": false,
|
||||
"notNull": false
|
||||
},
|
||||
"kind": {
|
||||
"name": "kind",
|
||||
"type": "entry_type",
|
||||
"typeSchema": "kyoo",
|
||||
"primaryKey": false,
|
||||
"notNull": true
|
||||
},
|
||||
"extra_kind": {
|
||||
"name": "extra_kind",
|
||||
"type": "text",
|
||||
"primaryKey": false,
|
||||
"notNull": false
|
||||
},
|
||||
"air_date": {
|
||||
"name": "air_date",
|
||||
"type": "date",
|
||||
"primaryKey": false,
|
||||
"notNull": false
|
||||
},
|
||||
"runtime": {
|
||||
"name": "runtime",
|
||||
"type": "integer",
|
||||
"primaryKey": false,
|
||||
"notNull": false
|
||||
},
|
||||
"thumbnail": {
|
||||
"name": "thumbnail",
|
||||
"type": "jsonb",
|
||||
"primaryKey": false,
|
||||
"notNull": false
|
||||
},
|
||||
"external_id": {
|
||||
"name": "external_id",
|
||||
"type": "jsonb",
|
||||
"primaryKey": false,
|
||||
"notNull": true,
|
||||
"default": "'{}'::jsonb"
|
||||
},
|
||||
"created_at": {
|
||||
"name": "created_at",
|
||||
"type": "timestamp with time zone",
|
||||
"primaryKey": false,
|
||||
"notNull": true,
|
||||
"default": "now()"
|
||||
},
|
||||
"next_refresh": {
|
||||
"name": "next_refresh",
|
||||
"type": "timestamp with time zone",
|
||||
"primaryKey": false,
|
||||
"notNull": true
|
||||
}
|
||||
},
|
||||
"indexes": {},
|
||||
"foreignKeys": {
|
||||
"entries_show_pk_shows_pk_fk": {
|
||||
"name": "entries_show_pk_shows_pk_fk",
|
||||
"tableFrom": "entries",
|
||||
"tableTo": "shows",
|
||||
"schemaTo": "kyoo",
|
||||
"columnsFrom": ["show_pk"],
|
||||
"columnsTo": ["pk"],
|
||||
"onDelete": "cascade",
|
||||
"onUpdate": "no action"
|
||||
}
|
||||
},
|
||||
"compositePrimaryKeys": {},
|
||||
"uniqueConstraints": {
|
||||
"entries_id_unique": {
|
||||
"name": "entries_id_unique",
|
||||
"nullsNotDistinct": false,
|
||||
"columns": ["id"]
|
||||
},
|
||||
"entries_slug_unique": {
|
||||
"name": "entries_slug_unique",
|
||||
"nullsNotDistinct": false,
|
||||
"columns": ["slug"]
|
||||
},
|
||||
"entries_showPk_seasonNumber_episodeNumber_unique": {
|
||||
"name": "entries_showPk_seasonNumber_episodeNumber_unique",
|
||||
"nullsNotDistinct": false,
|
||||
"columns": ["show_pk", "season_number", "episode_number"]
|
||||
}
|
||||
},
|
||||
"policies": {},
|
||||
"checkConstraints": {
|
||||
"order_positive": {
|
||||
"name": "order_positive",
|
||||
"value": "\"kyoo\".\"entries\".\"order\" >= 0"
|
||||
}
|
||||
},
|
||||
"isRLSEnabled": false
|
||||
},
|
||||
"kyoo.entry_translations": {
|
||||
"name": "entry_translations",
|
||||
"schema": "kyoo",
|
||||
"columns": {
|
||||
"pk": {
|
||||
"name": "pk",
|
||||
"type": "integer",
|
||||
"primaryKey": false,
|
||||
"notNull": true
|
||||
},
|
||||
"language": {
|
||||
"name": "language",
|
||||
"type": "varchar(255)",
|
||||
"primaryKey": false,
|
||||
"notNull": true
|
||||
},
|
||||
"name": {
|
||||
"name": "name",
|
||||
"type": "text",
|
||||
"primaryKey": false,
|
||||
"notNull": false
|
||||
},
|
||||
"description": {
|
||||
"name": "description",
|
||||
"type": "text",
|
||||
"primaryKey": false,
|
||||
"notNull": false
|
||||
},
|
||||
"tagline": {
|
||||
"name": "tagline",
|
||||
"type": "text",
|
||||
"primaryKey": false,
|
||||
"notNull": false
|
||||
},
|
||||
"poster": {
|
||||
"name": "poster",
|
||||
"type": "jsonb",
|
||||
"primaryKey": false,
|
||||
"notNull": false
|
||||
}
|
||||
},
|
||||
"indexes": {},
|
||||
"foreignKeys": {
|
||||
"entry_translations_pk_entries_pk_fk": {
|
||||
"name": "entry_translations_pk_entries_pk_fk",
|
||||
"tableFrom": "entry_translations",
|
||||
"tableTo": "entries",
|
||||
"schemaTo": "kyoo",
|
||||
"columnsFrom": ["pk"],
|
||||
"columnsTo": ["pk"],
|
||||
"onDelete": "cascade",
|
||||
"onUpdate": "no action"
|
||||
}
|
||||
},
|
||||
"compositePrimaryKeys": {
|
||||
"entry_translations_pk_language_pk": {
|
||||
"name": "entry_translations_pk_language_pk",
|
||||
"columns": ["pk", "language"]
|
||||
}
|
||||
},
|
||||
"uniqueConstraints": {},
|
||||
"policies": {},
|
||||
"checkConstraints": {},
|
||||
"isRLSEnabled": false
|
||||
},
|
||||
"kyoo.season_translations": {
|
||||
"name": "season_translations",
|
||||
"schema": "kyoo",
|
||||
"columns": {
|
||||
"pk": {
|
||||
"name": "pk",
|
||||
"type": "integer",
|
||||
"primaryKey": false,
|
||||
"notNull": true
|
||||
},
|
||||
"language": {
|
||||
"name": "language",
|
||||
"type": "varchar(255)",
|
||||
"primaryKey": false,
|
||||
"notNull": true
|
||||
},
|
||||
"name": {
|
||||
"name": "name",
|
||||
"type": "text",
|
||||
"primaryKey": false,
|
||||
"notNull": false
|
||||
},
|
||||
"description": {
|
||||
"name": "description",
|
||||
"type": "text",
|
||||
"primaryKey": false,
|
||||
"notNull": false
|
||||
},
|
||||
"poster": {
|
||||
"name": "poster",
|
||||
"type": "jsonb",
|
||||
"primaryKey": false,
|
||||
"notNull": false
|
||||
},
|
||||
"thumbnail": {
|
||||
"name": "thumbnail",
|
||||
"type": "jsonb",
|
||||
"primaryKey": false,
|
||||
"notNull": false
|
||||
},
|
||||
"banner": {
|
||||
"name": "banner",
|
||||
"type": "jsonb",
|
||||
"primaryKey": false,
|
||||
"notNull": false
|
||||
}
|
||||
},
|
||||
"indexes": {},
|
||||
"foreignKeys": {
|
||||
"season_translations_pk_seasons_pk_fk": {
|
||||
"name": "season_translations_pk_seasons_pk_fk",
|
||||
"tableFrom": "season_translations",
|
||||
"tableTo": "seasons",
|
||||
"schemaTo": "kyoo",
|
||||
"columnsFrom": ["pk"],
|
||||
"columnsTo": ["pk"],
|
||||
"onDelete": "cascade",
|
||||
"onUpdate": "no action"
|
||||
}
|
||||
},
|
||||
"compositePrimaryKeys": {
|
||||
"season_translations_pk_language_pk": {
|
||||
"name": "season_translations_pk_language_pk",
|
||||
"columns": ["pk", "language"]
|
||||
}
|
||||
},
|
||||
"uniqueConstraints": {},
|
||||
"policies": {},
|
||||
"checkConstraints": {},
|
||||
"isRLSEnabled": false
|
||||
},
|
||||
"kyoo.seasons": {
|
||||
"name": "seasons",
|
||||
"schema": "kyoo",
|
||||
"columns": {
|
||||
"pk": {
|
||||
"name": "pk",
|
||||
"type": "integer",
|
||||
"primaryKey": true,
|
||||
"notNull": true,
|
||||
"identity": {
|
||||
"type": "always",
|
||||
"name": "seasons_pk_seq",
|
||||
"schema": "kyoo",
|
||||
"increment": "1",
|
||||
"startWith": "1",
|
||||
"minValue": "1",
|
||||
"maxValue": "2147483647",
|
||||
"cache": "1",
|
||||
"cycle": false
|
||||
}
|
||||
},
|
||||
"id": {
|
||||
"name": "id",
|
||||
"type": "uuid",
|
||||
"primaryKey": false,
|
||||
"notNull": true,
|
||||
"default": "gen_random_uuid()"
|
||||
},
|
||||
"slug": {
|
||||
"name": "slug",
|
||||
"type": "varchar(255)",
|
||||
"primaryKey": false,
|
||||
"notNull": true
|
||||
},
|
||||
"show_pk": {
|
||||
"name": "show_pk",
|
||||
"type": "integer",
|
||||
"primaryKey": false,
|
||||
"notNull": false
|
||||
},
|
||||
"season_number": {
|
||||
"name": "season_number",
|
||||
"type": "integer",
|
||||
"primaryKey": false,
|
||||
"notNull": true
|
||||
},
|
||||
"start_air": {
|
||||
"name": "start_air",
|
||||
"type": "date",
|
||||
"primaryKey": false,
|
||||
"notNull": false
|
||||
},
|
||||
"end_air": {
|
||||
"name": "end_air",
|
||||
"type": "date",
|
||||
"primaryKey": false,
|
||||
"notNull": false
|
||||
},
|
||||
"external_id": {
|
||||
"name": "external_id",
|
||||
"type": "jsonb",
|
||||
"primaryKey": false,
|
||||
"notNull": true,
|
||||
"default": "'{}'::jsonb"
|
||||
},
|
||||
"created_at": {
|
||||
"name": "created_at",
|
||||
"type": "timestamp with time zone",
|
||||
"primaryKey": false,
|
||||
"notNull": true,
|
||||
"default": "now()"
|
||||
},
|
||||
"next_refresh": {
|
||||
"name": "next_refresh",
|
||||
"type": "timestamp with time zone",
|
||||
"primaryKey": false,
|
||||
"notNull": true
|
||||
}
|
||||
},
|
||||
"indexes": {
|
||||
"show_fk": {
|
||||
"name": "show_fk",
|
||||
"columns": [
|
||||
{
|
||||
"expression": "show_pk",
|
||||
"isExpression": false,
|
||||
"asc": true,
|
||||
"nulls": "last"
|
||||
}
|
||||
],
|
||||
"isUnique": false,
|
||||
"concurrently": false,
|
||||
"method": "hash",
|
||||
"with": {}
|
||||
}
|
||||
},
|
||||
"foreignKeys": {
|
||||
"seasons_show_pk_shows_pk_fk": {
|
||||
"name": "seasons_show_pk_shows_pk_fk",
|
||||
"tableFrom": "seasons",
|
||||
"tableTo": "shows",
|
||||
"schemaTo": "kyoo",
|
||||
"columnsFrom": ["show_pk"],
|
||||
"columnsTo": ["pk"],
|
||||
"onDelete": "cascade",
|
||||
"onUpdate": "no action"
|
||||
}
|
||||
},
|
||||
"compositePrimaryKeys": {},
|
||||
"uniqueConstraints": {
|
||||
"seasons_id_unique": {
|
||||
"name": "seasons_id_unique",
|
||||
"nullsNotDistinct": false,
|
||||
"columns": ["id"]
|
||||
},
|
||||
"seasons_slug_unique": {
|
||||
"name": "seasons_slug_unique",
|
||||
"nullsNotDistinct": false,
|
||||
"columns": ["slug"]
|
||||
},
|
||||
"seasons_showPk_seasonNumber_unique": {
|
||||
"name": "seasons_showPk_seasonNumber_unique",
|
||||
"nullsNotDistinct": false,
|
||||
"columns": ["show_pk", "season_number"]
|
||||
}
|
||||
},
|
||||
"policies": {},
|
||||
"checkConstraints": {},
|
||||
"isRLSEnabled": false
|
||||
},
|
||||
"kyoo.show_translations": {
|
||||
"name": "show_translations",
|
||||
"schema": "kyoo",
|
||||
"columns": {
|
||||
"pk": {
|
||||
"name": "pk",
|
||||
"type": "integer",
|
||||
"primaryKey": false,
|
||||
"notNull": true
|
||||
},
|
||||
"language": {
|
||||
"name": "language",
|
||||
"type": "varchar(255)",
|
||||
"primaryKey": false,
|
||||
"notNull": true
|
||||
},
|
||||
"name": {
|
||||
"name": "name",
|
||||
"type": "text",
|
||||
"primaryKey": false,
|
||||
"notNull": true
|
||||
},
|
||||
"description": {
|
||||
"name": "description",
|
||||
"type": "text",
|
||||
"primaryKey": false,
|
||||
"notNull": false
|
||||
},
|
||||
"tagline": {
|
||||
"name": "tagline",
|
||||
"type": "text",
|
||||
"primaryKey": false,
|
||||
"notNull": false
|
||||
},
|
||||
"aliases": {
|
||||
"name": "aliases",
|
||||
"type": "text[]",
|
||||
"primaryKey": false,
|
||||
"notNull": true
|
||||
},
|
||||
"tags": {
|
||||
"name": "tags",
|
||||
"type": "text[]",
|
||||
"primaryKey": false,
|
||||
"notNull": true
|
||||
},
|
||||
"poster": {
|
||||
"name": "poster",
|
||||
"type": "jsonb",
|
||||
"primaryKey": false,
|
||||
"notNull": false
|
||||
},
|
||||
"thumbnail": {
|
||||
"name": "thumbnail",
|
||||
"type": "jsonb",
|
||||
"primaryKey": false,
|
||||
"notNull": false
|
||||
},
|
||||
"banner": {
|
||||
"name": "banner",
|
||||
"type": "jsonb",
|
||||
"primaryKey": false,
|
||||
"notNull": false
|
||||
},
|
||||
"logo": {
|
||||
"name": "logo",
|
||||
"type": "jsonb",
|
||||
"primaryKey": false,
|
||||
"notNull": false
|
||||
},
|
||||
"trailer_url": {
|
||||
"name": "trailer_url",
|
||||
"type": "text",
|
||||
"primaryKey": false,
|
||||
"notNull": false
|
||||
}
|
||||
},
|
||||
"indexes": {
|
||||
"name_trgm": {
|
||||
"name": "name_trgm",
|
||||
"columns": [
|
||||
{
|
||||
"expression": "\"name\" gin_trgm_ops",
|
||||
"asc": true,
|
||||
"isExpression": true,
|
||||
"nulls": "last"
|
||||
}
|
||||
],
|
||||
"isUnique": false,
|
||||
"concurrently": false,
|
||||
"method": "gin",
|
||||
"with": {}
|
||||
},
|
||||
"tags": {
|
||||
"name": "tags",
|
||||
"columns": [
|
||||
{
|
||||
"expression": "tags",
|
||||
"isExpression": false,
|
||||
"asc": true,
|
||||
"nulls": "last"
|
||||
}
|
||||
],
|
||||
"isUnique": false,
|
||||
"concurrently": false,
|
||||
"method": "btree",
|
||||
"with": {}
|
||||
}
|
||||
},
|
||||
"foreignKeys": {
|
||||
"show_translations_pk_shows_pk_fk": {
|
||||
"name": "show_translations_pk_shows_pk_fk",
|
||||
"tableFrom": "show_translations",
|
||||
"tableTo": "shows",
|
||||
"schemaTo": "kyoo",
|
||||
"columnsFrom": ["pk"],
|
||||
"columnsTo": ["pk"],
|
||||
"onDelete": "cascade",
|
||||
"onUpdate": "no action"
|
||||
}
|
||||
},
|
||||
"compositePrimaryKeys": {
|
||||
"show_translations_pk_language_pk": {
|
||||
"name": "show_translations_pk_language_pk",
|
||||
"columns": ["pk", "language"]
|
||||
}
|
||||
},
|
||||
"uniqueConstraints": {},
|
||||
"policies": {},
|
||||
"checkConstraints": {},
|
||||
"isRLSEnabled": false
|
||||
},
|
||||
"kyoo.shows": {
|
||||
"name": "shows",
|
||||
"schema": "kyoo",
|
||||
"columns": {
|
||||
"pk": {
|
||||
"name": "pk",
|
||||
"type": "integer",
|
||||
"primaryKey": true,
|
||||
"notNull": true,
|
||||
"identity": {
|
||||
"type": "always",
|
||||
"name": "shows_pk_seq",
|
||||
"schema": "kyoo",
|
||||
"increment": "1",
|
||||
"startWith": "1",
|
||||
"minValue": "1",
|
||||
"maxValue": "2147483647",
|
||||
"cache": "1",
|
||||
"cycle": false
|
||||
}
|
||||
},
|
||||
"id": {
|
||||
"name": "id",
|
||||
"type": "uuid",
|
||||
"primaryKey": false,
|
||||
"notNull": true,
|
||||
"default": "gen_random_uuid()"
|
||||
},
|
||||
"slug": {
|
||||
"name": "slug",
|
||||
"type": "varchar(255)",
|
||||
"primaryKey": false,
|
||||
"notNull": true
|
||||
},
|
||||
"kind": {
|
||||
"name": "kind",
|
||||
"type": "show_kind",
|
||||
"typeSchema": "kyoo",
|
||||
"primaryKey": false,
|
||||
"notNull": true
|
||||
},
|
||||
"genres": {
|
||||
"name": "genres",
|
||||
"type": "genres[]",
|
||||
"primaryKey": false,
|
||||
"notNull": true
|
||||
},
|
||||
"rating": {
|
||||
"name": "rating",
|
||||
"type": "smallint",
|
||||
"primaryKey": false,
|
||||
"notNull": false
|
||||
},
|
||||
"runtime": {
|
||||
"name": "runtime",
|
||||
"type": "integer",
|
||||
"primaryKey": false,
|
||||
"notNull": false
|
||||
},
|
||||
"status": {
|
||||
"name": "status",
|
||||
"type": "show_status",
|
||||
"typeSchema": "kyoo",
|
||||
"primaryKey": false,
|
||||
"notNull": true
|
||||
},
|
||||
"start_air": {
|
||||
"name": "start_air",
|
||||
"type": "date",
|
||||
"primaryKey": false,
|
||||
"notNull": false
|
||||
},
|
||||
"end_air": {
|
||||
"name": "end_air",
|
||||
"type": "date",
|
||||
"primaryKey": false,
|
||||
"notNull": false
|
||||
},
|
||||
"original_language": {
|
||||
"name": "original_language",
|
||||
"type": "varchar(255)",
|
||||
"primaryKey": false,
|
||||
"notNull": false
|
||||
},
|
||||
"collection_pk": {
|
||||
"name": "collection_pk",
|
||||
"type": "integer",
|
||||
"primaryKey": false,
|
||||
"notNull": false
|
||||
},
|
||||
"external_id": {
|
||||
"name": "external_id",
|
||||
"type": "jsonb",
|
||||
"primaryKey": false,
|
||||
"notNull": true,
|
||||
"default": "'{}'::jsonb"
|
||||
},
|
||||
"created_at": {
|
||||
"name": "created_at",
|
||||
"type": "timestamp with time zone",
|
||||
"primaryKey": false,
|
||||
"notNull": true,
|
||||
"default": "now()"
|
||||
},
|
||||
"next_refresh": {
|
||||
"name": "next_refresh",
|
||||
"type": "timestamp with time zone",
|
||||
"primaryKey": false,
|
||||
"notNull": true
|
||||
}
|
||||
},
|
||||
"indexes": {
|
||||
"kind": {
|
||||
"name": "kind",
|
||||
"columns": [
|
||||
{
|
||||
"expression": "kind",
|
||||
"isExpression": false,
|
||||
"asc": true,
|
||||
"nulls": "last"
|
||||
}
|
||||
],
|
||||
"isUnique": false,
|
||||
"concurrently": false,
|
||||
"method": "hash",
|
||||
"with": {}
|
||||
},
|
||||
"rating": {
|
||||
"name": "rating",
|
||||
"columns": [
|
||||
{
|
||||
"expression": "rating",
|
||||
"isExpression": false,
|
||||
"asc": true,
|
||||
"nulls": "last"
|
||||
}
|
||||
],
|
||||
"isUnique": false,
|
||||
"concurrently": false,
|
||||
"method": "btree",
|
||||
"with": {}
|
||||
},
|
||||
"startAir": {
|
||||
"name": "startAir",
|
||||
"columns": [
|
||||
{
|
||||
"expression": "start_air",
|
||||
"isExpression": false,
|
||||
"asc": true,
|
||||
"nulls": "last"
|
||||
}
|
||||
],
|
||||
"isUnique": false,
|
||||
"concurrently": false,
|
||||
"method": "btree",
|
||||
"with": {}
|
||||
}
|
||||
},
|
||||
"foreignKeys": {
|
||||
"shows_collection_pk_shows_pk_fk": {
|
||||
"name": "shows_collection_pk_shows_pk_fk",
|
||||
"tableFrom": "shows",
|
||||
"tableTo": "shows",
|
||||
"schemaTo": "kyoo",
|
||||
"columnsFrom": ["collection_pk"],
|
||||
"columnsTo": ["pk"],
|
||||
"onDelete": "set null",
|
||||
"onUpdate": "no action"
|
||||
}
|
||||
},
|
||||
"compositePrimaryKeys": {},
|
||||
"uniqueConstraints": {
|
||||
"shows_id_unique": {
|
||||
"name": "shows_id_unique",
|
||||
"nullsNotDistinct": false,
|
||||
"columns": ["id"]
|
||||
},
|
||||
"shows_slug_unique": {
|
||||
"name": "shows_slug_unique",
|
||||
"nullsNotDistinct": false,
|
||||
"columns": ["slug"]
|
||||
}
|
||||
},
|
||||
"policies": {},
|
||||
"checkConstraints": {
|
||||
"rating_valid": {
|
||||
"name": "rating_valid",
|
||||
"value": "\"kyoo\".\"shows\".\"rating\" between 0 and 100"
|
||||
},
|
||||
"runtime_valid": {
|
||||
"name": "runtime_valid",
|
||||
"value": "\"kyoo\".\"shows\".\"runtime\" >= 0"
|
||||
}
|
||||
},
|
||||
"isRLSEnabled": false
|
||||
},
|
||||
"kyoo.entry_video_join": {
|
||||
"name": "entry_video_join",
|
||||
"schema": "kyoo",
|
||||
"columns": {
|
||||
"entry": {
|
||||
"name": "entry",
|
||||
"type": "integer",
|
||||
"primaryKey": false,
|
||||
"notNull": true
|
||||
},
|
||||
"video": {
|
||||
"name": "video",
|
||||
"type": "integer",
|
||||
"primaryKey": false,
|
||||
"notNull": true
|
||||
},
|
||||
"slug": {
|
||||
"name": "slug",
|
||||
"type": "varchar(255)",
|
||||
"primaryKey": false,
|
||||
"notNull": true
|
||||
}
|
||||
},
|
||||
"indexes": {},
|
||||
"foreignKeys": {
|
||||
"entry_video_join_entry_entries_pk_fk": {
|
||||
"name": "entry_video_join_entry_entries_pk_fk",
|
||||
"tableFrom": "entry_video_join",
|
||||
"tableTo": "entries",
|
||||
"schemaTo": "kyoo",
|
||||
"columnsFrom": ["entry"],
|
||||
"columnsTo": ["pk"],
|
||||
"onDelete": "cascade",
|
||||
"onUpdate": "no action"
|
||||
},
|
||||
"entry_video_join_video_videos_pk_fk": {
|
||||
"name": "entry_video_join_video_videos_pk_fk",
|
||||
"tableFrom": "entry_video_join",
|
||||
"tableTo": "videos",
|
||||
"schemaTo": "kyoo",
|
||||
"columnsFrom": ["video"],
|
||||
"columnsTo": ["pk"],
|
||||
"onDelete": "cascade",
|
||||
"onUpdate": "no action"
|
||||
}
|
||||
},
|
||||
"compositePrimaryKeys": {
|
||||
"entry_video_join_entry_video_pk": {
|
||||
"name": "entry_video_join_entry_video_pk",
|
||||
"columns": ["entry", "video"]
|
||||
}
|
||||
},
|
||||
"uniqueConstraints": {
|
||||
"entry_video_join_slug_unique": {
|
||||
"name": "entry_video_join_slug_unique",
|
||||
"nullsNotDistinct": false,
|
||||
"columns": ["slug"]
|
||||
}
|
||||
},
|
||||
"policies": {},
|
||||
"checkConstraints": {},
|
||||
"isRLSEnabled": false
|
||||
},
|
||||
"kyoo.videos": {
|
||||
"name": "videos",
|
||||
"schema": "kyoo",
|
||||
"columns": {
|
||||
"pk": {
|
||||
"name": "pk",
|
||||
"type": "integer",
|
||||
"primaryKey": true,
|
||||
"notNull": true,
|
||||
"identity": {
|
||||
"type": "always",
|
||||
"name": "videos_pk_seq",
|
||||
"schema": "kyoo",
|
||||
"increment": "1",
|
||||
"startWith": "1",
|
||||
"minValue": "1",
|
||||
"maxValue": "2147483647",
|
||||
"cache": "1",
|
||||
"cycle": false
|
||||
}
|
||||
},
|
||||
"id": {
|
||||
"name": "id",
|
||||
"type": "uuid",
|
||||
"primaryKey": false,
|
||||
"notNull": true,
|
||||
"default": "gen_random_uuid()"
|
||||
},
|
||||
"path": {
|
||||
"name": "path",
|
||||
"type": "text",
|
||||
"primaryKey": false,
|
||||
"notNull": true
|
||||
},
|
||||
"rendering": {
|
||||
"name": "rendering",
|
||||
"type": "text",
|
||||
"primaryKey": false,
|
||||
"notNull": true
|
||||
},
|
||||
"part": {
|
||||
"name": "part",
|
||||
"type": "integer",
|
||||
"primaryKey": false,
|
||||
"notNull": false
|
||||
},
|
||||
"version": {
|
||||
"name": "version",
|
||||
"type": "integer",
|
||||
"primaryKey": false,
|
||||
"notNull": true,
|
||||
"default": 1
|
||||
},
|
||||
"guess": {
|
||||
"name": "guess",
|
||||
"type": "jsonb",
|
||||
"primaryKey": false,
|
||||
"notNull": true,
|
||||
"default": "'{}'::jsonb"
|
||||
},
|
||||
"created_at": {
|
||||
"name": "created_at",
|
||||
"type": "timestamp with time zone",
|
||||
"primaryKey": false,
|
||||
"notNull": true,
|
||||
"default": "now()"
|
||||
}
|
||||
},
|
||||
"indexes": {},
|
||||
"foreignKeys": {},
|
||||
"compositePrimaryKeys": {},
|
||||
"uniqueConstraints": {
|
||||
"videos_id_unique": {
|
||||
"name": "videos_id_unique",
|
||||
"nullsNotDistinct": false,
|
||||
"columns": ["id"]
|
||||
},
|
||||
"videos_path_unique": {
|
||||
"name": "videos_path_unique",
|
||||
"nullsNotDistinct": false,
|
||||
"columns": ["path"]
|
||||
}
|
||||
},
|
||||
"policies": {},
|
||||
"checkConstraints": {
|
||||
"part_pos": {
|
||||
"name": "part_pos",
|
||||
"value": "\"kyoo\".\"videos\".\"part\" >= 0"
|
||||
},
|
||||
"version_pos": {
|
||||
"name": "version_pos",
|
||||
"value": "\"kyoo\".\"videos\".\"version\" >= 0"
|
||||
}
|
||||
},
|
||||
"isRLSEnabled": false
|
||||
}
|
||||
},
|
||||
"enums": {
|
||||
"kyoo.entry_type": {
|
||||
"name": "entry_type",
|
||||
"schema": "kyoo",
|
||||
"values": ["unknown", "episode", "movie", "special", "extra"]
|
||||
},
|
||||
"kyoo.genres": {
|
||||
"name": "genres",
|
||||
"schema": "kyoo",
|
||||
"values": [
|
||||
"action",
|
||||
"adventure",
|
||||
"animation",
|
||||
"comedy",
|
||||
"crime",
|
||||
"documentary",
|
||||
"drama",
|
||||
"family",
|
||||
"fantasy",
|
||||
"history",
|
||||
"horror",
|
||||
"music",
|
||||
"mystery",
|
||||
"romance",
|
||||
"science-fiction",
|
||||
"thriller",
|
||||
"war",
|
||||
"western",
|
||||
"kids",
|
||||
"reality",
|
||||
"politics",
|
||||
"soap",
|
||||
"talk"
|
||||
]
|
||||
},
|
||||
"kyoo.show_kind": {
|
||||
"name": "show_kind",
|
||||
"schema": "kyoo",
|
||||
"values": ["serie", "movie", "collection"]
|
||||
},
|
||||
"kyoo.show_status": {
|
||||
"name": "show_status",
|
||||
"schema": "kyoo",
|
||||
"values": ["unknown", "finished", "airing", "planned"]
|
||||
}
|
||||
},
|
||||
"schemas": {
|
||||
"kyoo": "kyoo"
|
||||
},
|
||||
"sequences": {},
|
||||
"roles": {},
|
||||
"policies": {},
|
||||
"views": {},
|
||||
"_meta": {
|
||||
"columns": {},
|
||||
"schemas": {},
|
||||
"tables": {}
|
||||
}
|
||||
}
|
||||
1265
api/drizzle/meta/0010_snapshot.json
Normal file
1265
api/drizzle/meta/0010_snapshot.json
Normal file
File diff suppressed because it is too large
Load Diff
1265
api/drizzle/meta/0011_snapshot.json
Normal file
1265
api/drizzle/meta/0011_snapshot.json
Normal file
File diff suppressed because it is too large
Load Diff
1278
api/drizzle/meta/0012_snapshot.json
Normal file
1278
api/drizzle/meta/0012_snapshot.json
Normal file
File diff suppressed because it is too large
Load Diff
1277
api/drizzle/meta/0013_snapshot.json
Normal file
1277
api/drizzle/meta/0013_snapshot.json
Normal file
File diff suppressed because it is too large
Load Diff
1487
api/drizzle/meta/0014_snapshot.json
Normal file
1487
api/drizzle/meta/0014_snapshot.json
Normal file
File diff suppressed because it is too large
Load Diff
1493
api/drizzle/meta/0015_snapshot.json
Normal file
1493
api/drizzle/meta/0015_snapshot.json
Normal file
File diff suppressed because it is too large
Load Diff
1555
api/drizzle/meta/0016_snapshot.json
Normal file
1555
api/drizzle/meta/0016_snapshot.json
Normal file
File diff suppressed because it is too large
Load Diff
1839
api/drizzle/meta/0017_snapshot.json
Normal file
1839
api/drizzle/meta/0017_snapshot.json
Normal file
File diff suppressed because it is too large
Load Diff
1839
api/drizzle/meta/0018_snapshot.json
Normal file
1839
api/drizzle/meta/0018_snapshot.json
Normal file
File diff suppressed because it is too large
Load Diff
1845
api/drizzle/meta/0019_snapshot.json
Normal file
1845
api/drizzle/meta/0019_snapshot.json
Normal file
File diff suppressed because it is too large
Load Diff
1851
api/drizzle/meta/0020_snapshot.json
Normal file
1851
api/drizzle/meta/0020_snapshot.json
Normal file
File diff suppressed because it is too large
Load Diff
1859
api/drizzle/meta/0021_snapshot.json
Normal file
1859
api/drizzle/meta/0021_snapshot.json
Normal file
File diff suppressed because it is too large
Load Diff
1872
api/drizzle/meta/0022_snapshot.json
Normal file
1872
api/drizzle/meta/0022_snapshot.json
Normal file
File diff suppressed because it is too large
Load Diff
1880
api/drizzle/meta/0023_snapshot.json
Normal file
1880
api/drizzle/meta/0023_snapshot.json
Normal file
File diff suppressed because it is too large
Load Diff
1881
api/drizzle/meta/0024_snapshot.json
Normal file
1881
api/drizzle/meta/0024_snapshot.json
Normal file
File diff suppressed because it is too large
Load Diff
181
api/drizzle/meta/_journal.json
Normal file
181
api/drizzle/meta/_journal.json
Normal file
@@ -0,0 +1,181 @@
|
||||
{
|
||||
"version": "7",
|
||||
"dialect": "postgresql",
|
||||
"entries": [
|
||||
{
|
||||
"idx": 0,
|
||||
"version": "7",
|
||||
"when": 1731105746157,
|
||||
"tag": "0000_init",
|
||||
"breakpoints": true
|
||||
},
|
||||
{
|
||||
"idx": 1,
|
||||
"version": "7",
|
||||
"when": 1731149082556,
|
||||
"tag": "0001_video",
|
||||
"breakpoints": true
|
||||
},
|
||||
{
|
||||
"idx": 2,
|
||||
"version": "7",
|
||||
"when": 1731165599920,
|
||||
"tag": "0002_seasons",
|
||||
"breakpoints": true
|
||||
},
|
||||
{
|
||||
"idx": 3,
|
||||
"version": "7",
|
||||
"when": 1731258712255,
|
||||
"tag": "0003_order",
|
||||
"breakpoints": true
|
||||
},
|
||||
{
|
||||
"idx": 4,
|
||||
"version": "7",
|
||||
"when": 1732738409330,
|
||||
"tag": "0004_jointures",
|
||||
"breakpoints": true
|
||||
},
|
||||
{
|
||||
"idx": 5,
|
||||
"version": "7",
|
||||
"when": 1737742695309,
|
||||
"tag": "0005_trigram",
|
||||
"breakpoints": true
|
||||
},
|
||||
{
|
||||
"idx": 6,
|
||||
"version": "7",
|
||||
"when": 1737763164759,
|
||||
"tag": "0006_seasons",
|
||||
"breakpoints": true
|
||||
},
|
||||
{
|
||||
"idx": 7,
|
||||
"version": "7",
|
||||
"when": 1737913931275,
|
||||
"tag": "0007_entries",
|
||||
"breakpoints": true
|
||||
},
|
||||
{
|
||||
"idx": 8,
|
||||
"version": "7",
|
||||
"when": 1738064522937,
|
||||
"tag": "0008_entries",
|
||||
"breakpoints": true
|
||||
},
|
||||
{
|
||||
"idx": 9,
|
||||
"version": "7",
|
||||
"when": 1740872363604,
|
||||
"tag": "0009_collections",
|
||||
"breakpoints": true
|
||||
},
|
||||
{
|
||||
"idx": 10,
|
||||
"version": "7",
|
||||
"when": 1740950531468,
|
||||
"tag": "0010_studios",
|
||||
"breakpoints": true
|
||||
},
|
||||
{
|
||||
"idx": 11,
|
||||
"version": "7",
|
||||
"when": 1741014917375,
|
||||
"tag": "0011_join_rename",
|
||||
"breakpoints": true
|
||||
},
|
||||
{
|
||||
"idx": 12,
|
||||
"version": "7",
|
||||
"when": 1741360992371,
|
||||
"tag": "0012_available_count",
|
||||
"breakpoints": true
|
||||
},
|
||||
{
|
||||
"idx": 13,
|
||||
"version": "7",
|
||||
"when": 1741444868735,
|
||||
"tag": "0013_original",
|
||||
"breakpoints": true
|
||||
},
|
||||
{
|
||||
"idx": 14,
|
||||
"version": "7",
|
||||
"when": 1741601145901,
|
||||
"tag": "0014_staff",
|
||||
"breakpoints": true
|
||||
},
|
||||
{
|
||||
"idx": 15,
|
||||
"version": "7",
|
||||
"when": 1741623934941,
|
||||
"tag": "0015_news",
|
||||
"breakpoints": true
|
||||
},
|
||||
{
|
||||
"idx": 16,
|
||||
"version": "7",
|
||||
"when": 1742205790510,
|
||||
"tag": "0016_mqueue",
|
||||
"breakpoints": true
|
||||
},
|
||||
{
|
||||
"idx": 17,
|
||||
"version": "7",
|
||||
"when": 1743944773824,
|
||||
"tag": "0017_watchlist",
|
||||
"breakpoints": true
|
||||
},
|
||||
{
|
||||
"idx": 18,
|
||||
"version": "7",
|
||||
"when": 1744053556621,
|
||||
"tag": "0018_history",
|
||||
"breakpoints": true
|
||||
},
|
||||
{
|
||||
"idx": 19,
|
||||
"version": "7",
|
||||
"when": 1744120518941,
|
||||
"tag": "0019_nextup",
|
||||
"breakpoints": true
|
||||
},
|
||||
{
|
||||
"idx": 20,
|
||||
"version": "7",
|
||||
"when": 1746198322219,
|
||||
"tag": "0020_video_unique",
|
||||
"breakpoints": true
|
||||
},
|
||||
{
|
||||
"idx": 21,
|
||||
"version": "7",
|
||||
"when": 1747727831649,
|
||||
"tag": "0021_crew",
|
||||
"breakpoints": true
|
||||
},
|
||||
{
|
||||
"idx": 22,
|
||||
"version": "7",
|
||||
"when": 1752446736231,
|
||||
"tag": "0022_seasons-count",
|
||||
"breakpoints": true
|
||||
},
|
||||
{
|
||||
"idx": 23,
|
||||
"version": "7",
|
||||
"when": 1763924097229,
|
||||
"tag": "0023_mqueue-priority",
|
||||
"breakpoints": true
|
||||
},
|
||||
{
|
||||
"idx": 24,
|
||||
"version": "7",
|
||||
"when": 1763932730557,
|
||||
"tag": "0024_fix-season-count",
|
||||
"breakpoints": true
|
||||
}
|
||||
]
|
||||
}
|
||||
34
api/package.json
Normal file
34
api/package.json
Normal file
@@ -0,0 +1,34 @@
|
||||
{
|
||||
"name": "api",
|
||||
"version": "5.0.0",
|
||||
"scripts": {
|
||||
"dev": "bun --watch src/index.ts",
|
||||
"build": "bun build src/index.ts --target bun --outdir ./dist",
|
||||
"start": "NODE_ENV=production bun dist/index.js",
|
||||
"test": "bun test",
|
||||
"format": "biome check --write ."
|
||||
},
|
||||
"dependencies": {
|
||||
"@elysiajs/opentelemetry": "^1.4.8",
|
||||
"@elysiajs/swagger": "zoriya/elysia-swagger#build",
|
||||
"@kubiks/otel-drizzle": "zoriya/drizzle-otel#build",
|
||||
"@types/bun": "^1.3.1",
|
||||
"blurhash": "^2.0.5",
|
||||
"drizzle-kit": "^0.31.5",
|
||||
"drizzle-orm": "0.44.7",
|
||||
"elysia": "^1.4.13",
|
||||
"jose": "^6.1.0",
|
||||
"node-addon-api": "^8.5.0",
|
||||
"parjs": "^1.3.9",
|
||||
"pg": "^8.16.3",
|
||||
"sharp": "^0.34.4"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@biomejs/biome": "2.3.7",
|
||||
"@types/pg": "^8.15.5"
|
||||
},
|
||||
"module": "src/index.js",
|
||||
"patchedDependencies": {
|
||||
"drizzle-orm@0.44.7": "patches/drizzle-orm@0.44.7.patch"
|
||||
}
|
||||
}
|
||||
72
api/patches/drizzle-orm@0.44.7.patch
Normal file
72
api/patches/drizzle-orm@0.44.7.patch
Normal file
@@ -0,0 +1,72 @@
|
||||
diff --git a/pg-core/dialect.cjs b/pg-core/dialect.cjs
|
||||
index d776a1fb503f35b5e53c6d3c1c086efa8230ea94..86541bf408e4955029c65be59d7b8ec98bb6e914 100644
|
||||
--- a/pg-core/dialect.cjs
|
||||
+++ b/pg-core/dialect.cjs
|
||||
@@ -347,7 +347,14 @@ class PgDialect {
|
||||
buildInsertQuery({ table, values: valuesOrSelect, onConflict, returning, withList, select, overridingSystemValue_ }) {
|
||||
const valuesSqlList = [];
|
||||
const columns = table[import_table2.Table.Symbol.Columns];
|
||||
- const colEntries = Object.entries(columns).filter(([_, col]) => !col.shouldDisableInsert());
|
||||
+ let colEntries = Object.entries(columns);
|
||||
+ colEntries = select && !is(valuesOrSelect, SQL)
|
||||
+ ? Object
|
||||
+ .keys(valuesOrSelect._.selectedFields)
|
||||
+ .map((key) => [key, columns[key]])
|
||||
+ : overridingSystemValue_
|
||||
+ ? colEntries
|
||||
+ : colEntries.filter(([_, col]) => !col.shouldDisableInsert());
|
||||
const insertOrder = colEntries.map(
|
||||
([, column]) => import_sql2.sql.identifier(this.casing.getColumnCasing(column))
|
||||
);
|
||||
diff --git a/pg-core/dialect.js b/pg-core/dialect.js
|
||||
index 74a16c9e86fe3a89ced32af44af0a72f1cf43cf6..08f820d46a040c315fed40b8b36d94d094174425 100644
|
||||
--- a/pg-core/dialect.js
|
||||
+++ b/pg-core/dialect.js
|
||||
@@ -345,7 +345,14 @@ class PgDialect {
|
||||
buildInsertQuery({ table, values: valuesOrSelect, onConflict, returning, withList, select, overridingSystemValue_ }) {
|
||||
const valuesSqlList = [];
|
||||
const columns = table[Table.Symbol.Columns];
|
||||
- const colEntries = Object.entries(columns).filter(([_, col]) => !col.shouldDisableInsert());
|
||||
+ let colEntries = Object.entries(columns);
|
||||
+ colEntries = select && !is(valuesOrSelect, SQL)
|
||||
+ ? Object
|
||||
+ .keys(valuesOrSelect._.selectedFields)
|
||||
+ .map((key) => [key, columns[key]])
|
||||
+ : overridingSystemValue_
|
||||
+ ? colEntries
|
||||
+ : colEntries.filter(([_, col]) => !col.shouldDisableInsert());
|
||||
const insertOrder = colEntries.map(
|
||||
([, column]) => sql.identifier(this.casing.getColumnCasing(column))
|
||||
);
|
||||
diff --git a/pg-core/query-builders/insert.cjs b/pg-core/query-builders/insert.cjs
|
||||
index 22e0a4b4ad7ac64b065fc540416c6ed15ff4336b..fd590a6a3feb48c9f1894a0619b09ca6a5d22a5c 100644
|
||||
--- a/pg-core/query-builders/insert.cjs
|
||||
+++ b/pg-core/query-builders/insert.cjs
|
||||
@@ -76,11 +76,6 @@ class PgInsertBuilder {
|
||||
}
|
||||
select(selectQuery) {
|
||||
const select = typeof selectQuery === "function" ? selectQuery(new import_query_builder.QueryBuilder()) : selectQuery;
|
||||
- if (!(0, import_entity.is)(select, import_sql.SQL) && !(0, import_utils.haveSameKeys)(this.table[import_table.Columns], select._.selectedFields)) {
|
||||
- throw new Error(
|
||||
- "Insert select error: selected fields are not the same or are in a different order compared to the table definition"
|
||||
- );
|
||||
- }
|
||||
return new PgInsertBase(this.table, select, this.session, this.dialect, this.withList, true);
|
||||
}
|
||||
}
|
||||
diff --git a/pg-core/query-builders/insert.js b/pg-core/query-builders/insert.js
|
||||
index 60a8bb0d1c22b890bd8fbf4c85d5df41ca42444c..8754d0f2923f905816016c42f339c3e9097b4128 100644
|
||||
--- a/pg-core/query-builders/insert.js
|
||||
+++ b/pg-core/query-builders/insert.js
|
||||
@@ -52,11 +52,6 @@ class PgInsertBuilder {
|
||||
}
|
||||
select(selectQuery) {
|
||||
const select = typeof selectQuery === "function" ? selectQuery(new QueryBuilder()) : selectQuery;
|
||||
- if (!is(select, SQL) && !haveSameKeys(this.table[Columns], select._.selectedFields)) {
|
||||
- throw new Error(
|
||||
- "Insert select error: selected fields are not the same or are in a different order compared to the table definition"
|
||||
- );
|
||||
- }
|
||||
return new PgInsertBase(this.table, select, this.session, this.dialect, this.withList, true);
|
||||
}
|
||||
}
|
||||
16
api/shell.nix
Normal file
16
api/shell.nix
Normal file
@@ -0,0 +1,16 @@
|
||||
{pkgs ? import <nixpkgs> {}}:
|
||||
pkgs.mkShell {
|
||||
packages = with pkgs; [
|
||||
bun
|
||||
biome
|
||||
# for psql to debug from the cli
|
||||
postgresql_18
|
||||
# to build libvips (for sharp)
|
||||
nodejs
|
||||
node-gyp
|
||||
pkg-config
|
||||
vips
|
||||
];
|
||||
|
||||
SHARP_FORCE_GLOBAL_LIBVIPS = 1;
|
||||
}
|
||||
120
api/src/auth.ts
Normal file
120
api/src/auth.ts
Normal file
@@ -0,0 +1,120 @@
|
||||
import { TypeCompiler } from "@sinclair/typebox/compiler";
|
||||
import { Value } from "@sinclair/typebox/value";
|
||||
import Elysia, { t } from "elysia";
|
||||
import { createRemoteJWKSet, jwtVerify } from "jose";
|
||||
import { KError } from "./models/error";
|
||||
import type { Prettify } from "./utils";
|
||||
|
||||
const jwtSecret = process.env.JWT_SECRET
|
||||
? new TextEncoder().encode(process.env.JWT_SECRET)
|
||||
: null;
|
||||
const jwks = createRemoteJWKSet(
|
||||
new URL(
|
||||
".well-known/jwks.json",
|
||||
process.env.AUTH_SERVER ?? "http://auth:4568",
|
||||
),
|
||||
);
|
||||
|
||||
const Settings = t.Object(
|
||||
{
|
||||
preferOriginal: t.Boolean({ default: true }),
|
||||
},
|
||||
{ additionalProperties: true },
|
||||
);
|
||||
type Settings = typeof Settings.static;
|
||||
|
||||
const Jwt = t.Object({
|
||||
sub: t.String({ description: "User id" }),
|
||||
sid: t.String({ description: "Session id" }),
|
||||
username: t.String(),
|
||||
permissions: t.Array(t.String()),
|
||||
settings: t.Optional(t.Partial(Settings, { default: {} })),
|
||||
});
|
||||
type Jwt = typeof Jwt.static;
|
||||
const validator = TypeCompiler.Compile(Jwt);
|
||||
|
||||
export const auth = new Elysia({ name: "auth" })
|
||||
.guard({
|
||||
headers: t.Object(
|
||||
{
|
||||
authorization: t.Optional(t.TemplateLiteral("Bearer ${string}")),
|
||||
},
|
||||
{ additionalProperties: true },
|
||||
),
|
||||
})
|
||||
.resolve(async ({ headers: { authorization }, status }) => {
|
||||
const bearer = authorization?.slice(7);
|
||||
if (!bearer) {
|
||||
return status(403, {
|
||||
status: 403,
|
||||
message: "No authorization header was found.",
|
||||
});
|
||||
}
|
||||
|
||||
try {
|
||||
// @ts-expect-error ts can't understand that there's two overload idk why
|
||||
const { payload } = await jwtVerify(bearer, jwtSecret ?? jwks, {
|
||||
issuer: process.env.JWT_ISSUER,
|
||||
});
|
||||
const raw = validator.Decode(payload);
|
||||
const jwt = Value.Default(Jwt, raw) as Prettify<
|
||||
Jwt & { settings: Settings }
|
||||
>;
|
||||
|
||||
return { jwt };
|
||||
} catch (err) {
|
||||
return status(403, {
|
||||
status: 403,
|
||||
message: "Invalid jwt. Verification vailed",
|
||||
details: err,
|
||||
});
|
||||
}
|
||||
})
|
||||
.macro({
|
||||
permissions(perms: string[]) {
|
||||
return {
|
||||
beforeHandle: function permissionCheck({ jwt, status }) {
|
||||
for (const perm of perms) {
|
||||
if (!jwt!.permissions.includes(perm)) {
|
||||
return status(403, {
|
||||
status: 403,
|
||||
message: `Missing permission: '${perm}'.`,
|
||||
details: { current: jwt!.permissions, required: perms },
|
||||
});
|
||||
}
|
||||
}
|
||||
},
|
||||
};
|
||||
},
|
||||
})
|
||||
.as("scoped");
|
||||
|
||||
const User = t.Object({
|
||||
id: t.String({ format: "uuid" }),
|
||||
username: t.String(),
|
||||
email: t.String({ format: "email" }),
|
||||
createdDate: t.String({ format: "date-time" }),
|
||||
lastSeen: t.String({ format: "date-time" }),
|
||||
claims: t.Record(t.String(), t.Any()),
|
||||
oidc: t.Record(
|
||||
t.String(),
|
||||
t.Object({
|
||||
id: t.String({ format: "uuid" }),
|
||||
username: t.String(),
|
||||
profileUrl: t.Nullable(t.String({ format: "url" })),
|
||||
}),
|
||||
),
|
||||
});
|
||||
const UserC = TypeCompiler.Compile(t.Union([User, KError]));
|
||||
|
||||
export async function getUserInfo(
|
||||
id: string,
|
||||
headers: { authorization: string },
|
||||
) {
|
||||
const resp = await fetch(
|
||||
new URL(`/auth/users/${id}`, process.env.AUTH_SERVER ?? "http://auth:4568"),
|
||||
{ headers },
|
||||
);
|
||||
|
||||
return UserC.Decode(await resp.json());
|
||||
}
|
||||
139
api/src/base.ts
Normal file
139
api/src/base.ts
Normal file
@@ -0,0 +1,139 @@
|
||||
import { Elysia, t } from "elysia";
|
||||
import { auth } from "./auth";
|
||||
import { entriesH } from "./controllers/entries";
|
||||
import { imagesH } from "./controllers/images";
|
||||
import { historyH } from "./controllers/profiles/history";
|
||||
import { nextup } from "./controllers/profiles/nextup";
|
||||
import { watchlistH } from "./controllers/profiles/watchlist";
|
||||
import { seasonsH } from "./controllers/seasons";
|
||||
import { seed } from "./controllers/seed";
|
||||
import { collections } from "./controllers/shows/collections";
|
||||
import { movies } from "./controllers/shows/movies";
|
||||
import { series } from "./controllers/shows/series";
|
||||
import { showsH } from "./controllers/shows/shows";
|
||||
import { staffH } from "./controllers/staff";
|
||||
import { studiosH } from "./controllers/studios";
|
||||
import { videosReadH, videosWriteH } from "./controllers/videos";
|
||||
import { db } from "./db";
|
||||
import type { KError } from "./models/error";
|
||||
import { otel } from "./otel";
|
||||
|
||||
export const base = new Elysia({ name: "base" })
|
||||
.onError(({ code, error }) => {
|
||||
// sometimes elysia as an unknown code when throwing errors
|
||||
if (code === "UNKNOWN") {
|
||||
try {
|
||||
const details = JSON.parse(error.message);
|
||||
if (details?.code === "KError") {
|
||||
const { code, ...ret } = details;
|
||||
return ret;
|
||||
}
|
||||
} catch {}
|
||||
}
|
||||
if (code === "VALIDATION") {
|
||||
const details = JSON.parse(error.message);
|
||||
if (details.code === "KError") {
|
||||
const { code, ...ret } = details;
|
||||
return ret;
|
||||
}
|
||||
details.errors = details.errors.map((x: any) => {
|
||||
const { schema, ...err } = x;
|
||||
return err;
|
||||
});
|
||||
return {
|
||||
status: error.status,
|
||||
message: `Validation error on ${details.on}.`,
|
||||
details: details,
|
||||
} as KError;
|
||||
}
|
||||
if (code === "NOT_FOUND") {
|
||||
return error;
|
||||
}
|
||||
console.error(code, error);
|
||||
return {
|
||||
status: 500,
|
||||
message: "message" in error ? (error?.message ?? code) : code,
|
||||
details: error,
|
||||
} as KError;
|
||||
})
|
||||
.get("/health", () => ({ status: "healthy" }) as const, {
|
||||
detail: { description: "Check if the api is healthy." },
|
||||
response: { 200: t.Object({ status: t.Literal("healthy") }) },
|
||||
})
|
||||
.get(
|
||||
"/ready",
|
||||
async ({ status }) => {
|
||||
try {
|
||||
await db.execute("select 1");
|
||||
return { status: "healthy", database: "healthy" } as const;
|
||||
} catch (e) {
|
||||
return status(500, {
|
||||
status: "unhealthy",
|
||||
database: e,
|
||||
});
|
||||
}
|
||||
},
|
||||
{
|
||||
detail: { description: "Check if the api is healthy." },
|
||||
response: {
|
||||
200: t.Object({
|
||||
status: t.Literal("healthy"),
|
||||
database: t.Literal("healthy"),
|
||||
}),
|
||||
500: t.Object({
|
||||
status: t.Literal("unhealthy"),
|
||||
database: t.Any(),
|
||||
}),
|
||||
},
|
||||
},
|
||||
)
|
||||
.as("global");
|
||||
|
||||
export const prefix = "/api";
|
||||
export const handlers = new Elysia({ prefix })
|
||||
.use(base)
|
||||
.use(auth)
|
||||
.use(otel)
|
||||
.guard(
|
||||
{
|
||||
// Those are not applied for now. See https://github.com/elysiajs/elysia/issues/1139
|
||||
detail: {
|
||||
security: [{ bearer: ["core.read"] }, { api: ["core.read"] }],
|
||||
},
|
||||
// See https://github.com/elysiajs/elysia/issues/1158
|
||||
// response: {
|
||||
// 401: { ...KError, description: "" },
|
||||
// 403: { ...KError, description: "" },
|
||||
// },
|
||||
permissions: ["core.read"],
|
||||
},
|
||||
(app) =>
|
||||
app
|
||||
.use(showsH)
|
||||
.use(movies)
|
||||
.use(series)
|
||||
.use(collections)
|
||||
.use(entriesH)
|
||||
.use(seasonsH)
|
||||
.use(studiosH)
|
||||
.use(staffH)
|
||||
.use(imagesH)
|
||||
.use(watchlistH)
|
||||
.use(historyH)
|
||||
.use(nextup)
|
||||
.use(videosReadH),
|
||||
)
|
||||
.guard(
|
||||
{
|
||||
detail: {
|
||||
security: [{ bearer: ["core.write"] }, { api: ["core.write"] }],
|
||||
},
|
||||
// See https://github.com/elysiajs/elysia/issues/1158
|
||||
// response: {
|
||||
// 401: { ...KError, description: "" },
|
||||
// 403: { ...KError, description: "" },
|
||||
// },
|
||||
permissions: ["core.write"],
|
||||
},
|
||||
(app) => app.use(videosWriteH).use(seed),
|
||||
);
|
||||
453
api/src/controllers/entries.ts
Normal file
453
api/src/controllers/entries.ts
Normal file
@@ -0,0 +1,453 @@
|
||||
import { and, desc, eq, isNotNull, ne, type SQL, sql } from "drizzle-orm";
|
||||
import { Elysia, t } from "elysia";
|
||||
import { auth } from "~/auth";
|
||||
import { db } from "~/db";
|
||||
import {
|
||||
entries,
|
||||
entryTranslations,
|
||||
entryVideoJoin,
|
||||
history,
|
||||
profiles,
|
||||
shows,
|
||||
videos,
|
||||
} from "~/db/schema";
|
||||
import {
|
||||
coalesce,
|
||||
getColumns,
|
||||
jsonbAgg,
|
||||
jsonbBuildObject,
|
||||
sqlarr,
|
||||
} from "~/db/utils";
|
||||
import {
|
||||
Entry,
|
||||
type EntryKind,
|
||||
Episode,
|
||||
Extra,
|
||||
ExtraType,
|
||||
MovieEntry,
|
||||
Special,
|
||||
} from "~/models/entry";
|
||||
import { KError } from "~/models/error";
|
||||
import { madeInAbyss } from "~/models/examples";
|
||||
import {
|
||||
AcceptLanguage,
|
||||
createPage,
|
||||
Filter,
|
||||
type FilterDef,
|
||||
isUuid,
|
||||
keysetPaginate,
|
||||
Page,
|
||||
processLanguages,
|
||||
Sort,
|
||||
sortToSql,
|
||||
} from "~/models/utils";
|
||||
import { desc as description } from "~/models/utils/descriptions";
|
||||
import type { EmbeddedVideo } from "~/models/video";
|
||||
|
||||
export const entryProgressQ = db
|
||||
.selectDistinctOn([history.entryPk], {
|
||||
percent: history.percent,
|
||||
time: history.time,
|
||||
entryPk: history.entryPk,
|
||||
playedDate: history.playedDate,
|
||||
videoId: videos.id,
|
||||
})
|
||||
.from(history)
|
||||
.leftJoin(videos, eq(history.videoPk, videos.pk))
|
||||
.innerJoin(profiles, eq(history.profilePk, profiles.pk))
|
||||
.where(eq(profiles.id, sql.placeholder("userId")))
|
||||
.orderBy(history.entryPk, desc(history.playedDate))
|
||||
.as("progress");
|
||||
|
||||
export const entryFilters: FilterDef = {
|
||||
kind: {
|
||||
column: entries.kind,
|
||||
type: "enum",
|
||||
values: ["episode", "movie", "special"],
|
||||
},
|
||||
seasonNumber: { column: entries.seasonNumber, type: "int" },
|
||||
episodeNumber: { column: entries.episodeNumber, type: "int" },
|
||||
number: { column: entries.episodeNumber, type: "int" },
|
||||
order: { column: entries.order, type: "float" },
|
||||
runtime: { column: entries.runtime, type: "float" },
|
||||
airDate: { column: entries.airDate, type: "date" },
|
||||
playedDate: { column: entryProgressQ.playedDate, type: "date" },
|
||||
isAvailable: { column: isNotNull(entries.availableSince), type: "bool" },
|
||||
};
|
||||
|
||||
const extraFilters: FilterDef = {
|
||||
kind: { column: entries.extraKind, type: "enum", values: ExtraType.enum },
|
||||
runtime: { column: entries.runtime, type: "float" },
|
||||
playedDate: { column: entryProgressQ.playedDate, type: "date" },
|
||||
};
|
||||
|
||||
export const entrySort = Sort(
|
||||
{
|
||||
order: entries.order,
|
||||
seasonNumber: entries.seasonNumber,
|
||||
episodeNumber: entries.episodeNumber,
|
||||
number: entries.episodeNumber,
|
||||
airDate: entries.airDate,
|
||||
nextRefresh: entries.nextRefresh,
|
||||
playedDate: entryProgressQ.playedDate,
|
||||
},
|
||||
{
|
||||
default: ["order"],
|
||||
tablePk: entries.pk,
|
||||
},
|
||||
);
|
||||
|
||||
const extraSort = Sort(
|
||||
{
|
||||
slug: entries.slug,
|
||||
name: entryTranslations.name,
|
||||
runtime: entries.runtime,
|
||||
createdAt: entries.createdAt,
|
||||
playedDate: entryProgressQ.playedDate,
|
||||
},
|
||||
{
|
||||
default: ["slug"],
|
||||
tablePk: entries.pk,
|
||||
},
|
||||
);
|
||||
|
||||
const newsSort: Sort = {
|
||||
tablePk: entries.pk,
|
||||
sort: [
|
||||
{
|
||||
sql: entries.availableSince,
|
||||
// in the news query we already filter nulls out
|
||||
isNullable: false,
|
||||
accessor: (x) => x.availableSince,
|
||||
desc: false,
|
||||
},
|
||||
],
|
||||
};
|
||||
const { guess, createdAt, updatedAt, ...videosCol } = getColumns(videos);
|
||||
export const entryVideosQ = db
|
||||
.select({
|
||||
videos: coalesce(
|
||||
jsonbAgg(
|
||||
jsonbBuildObject<EmbeddedVideo>({
|
||||
slug: entryVideoJoin.slug,
|
||||
...videosCol,
|
||||
}),
|
||||
),
|
||||
sql`'[]'::jsonb`,
|
||||
).as("videos"),
|
||||
})
|
||||
.from(entryVideoJoin)
|
||||
.where(eq(entryVideoJoin.entryPk, entries.pk))
|
||||
.leftJoin(videos, eq(videos.pk, entryVideoJoin.videoPk))
|
||||
.as("videos");
|
||||
|
||||
export const getEntryTransQ = (languages: string[]) => {
|
||||
return db
|
||||
.selectDistinctOn([entryTranslations.pk])
|
||||
.from(entryTranslations)
|
||||
.orderBy(
|
||||
entryTranslations.pk,
|
||||
sql`array_position(${sqlarr(languages)}, ${entryTranslations.language})`,
|
||||
)
|
||||
.as("entry_t");
|
||||
};
|
||||
|
||||
export const mapProgress = ({ aliased }: { aliased: boolean }) => {
|
||||
const { time, percent, playedDate, videoId } = getColumns(entryProgressQ);
|
||||
const ret = {
|
||||
time: coalesce(time, sql<number>`0`),
|
||||
percent: coalesce(percent, sql<number>`0`),
|
||||
playedDate: sql<string>`to_char(${playedDate}, 'YYYY-MM-DD"T"HH24:MI:SS"Z"')`,
|
||||
videoId: sql<string>`${videoId}`,
|
||||
};
|
||||
if (!aliased) return ret;
|
||||
return Object.fromEntries(
|
||||
Object.entries(ret).map(([k, v]) => [k, v.as(k)]),
|
||||
) as unknown as typeof ret;
|
||||
};
|
||||
|
||||
export async function getEntries({
|
||||
after,
|
||||
limit,
|
||||
query,
|
||||
sort,
|
||||
filter,
|
||||
languages,
|
||||
userId,
|
||||
progressQ = entryProgressQ,
|
||||
}: {
|
||||
after: string | undefined;
|
||||
limit: number;
|
||||
query: string | undefined;
|
||||
sort: Sort;
|
||||
filter: SQL | undefined;
|
||||
languages: string[];
|
||||
userId: string;
|
||||
progressQ?: typeof entryProgressQ;
|
||||
}): Promise<(Entry | Extra)[]> {
|
||||
const transQ = getEntryTransQ(languages);
|
||||
|
||||
const {
|
||||
kind,
|
||||
externalId,
|
||||
order,
|
||||
seasonNumber,
|
||||
episodeNumber,
|
||||
extraKind,
|
||||
...entryCol
|
||||
} = getColumns(entries);
|
||||
return await db
|
||||
.select({
|
||||
...entryCol,
|
||||
...getColumns(transQ),
|
||||
videos: entryVideosQ.videos,
|
||||
progress: mapProgress({ aliased: true }),
|
||||
// specials don't have an `episodeNumber` but a `number` field.
|
||||
number: sql<number>`${episodeNumber}`,
|
||||
|
||||
// merge `extraKind` into `kind`
|
||||
kind: sql<EntryKind>`case when ${kind} = 'extra' then ${extraKind} else ${kind}::text end`.as(
|
||||
"kind",
|
||||
),
|
||||
|
||||
// assign more restrained types to make typescript happy.
|
||||
externalId: sql<any>`${externalId}`,
|
||||
order: sql<number>`${order}`,
|
||||
seasonNumber: sql<number>`${seasonNumber}`,
|
||||
episodeNumber: sql<number>`${episodeNumber}`,
|
||||
name: sql<string>`${transQ.name}`,
|
||||
})
|
||||
.from(entries)
|
||||
.innerJoin(transQ, eq(entries.pk, transQ.pk))
|
||||
.crossJoinLateral(entryVideosQ)
|
||||
.leftJoin(progressQ, eq(entries.pk, progressQ.entryPk))
|
||||
.where(
|
||||
and(
|
||||
filter,
|
||||
query ? sql`${transQ.name} %> ${query}::text` : undefined,
|
||||
keysetPaginate({ after, sort }),
|
||||
),
|
||||
)
|
||||
.orderBy(
|
||||
...(query
|
||||
? [sql`word_similarity(${query}::text, ${transQ.name})`]
|
||||
: sortToSql(sort)),
|
||||
entries.pk,
|
||||
)
|
||||
.limit(limit)
|
||||
.execute({ userId });
|
||||
}
|
||||
|
||||
export const entriesH = new Elysia({ tags: ["series"] })
|
||||
.model({
|
||||
episode: Episode,
|
||||
movie_entry: MovieEntry,
|
||||
special: Special,
|
||||
extra: Extra,
|
||||
error: t.Object({}),
|
||||
})
|
||||
.model((models) => ({
|
||||
...models,
|
||||
entry: t.Union([models.episode, models.movie_entry, models.special]),
|
||||
}))
|
||||
.use(auth)
|
||||
.get(
|
||||
"/series/:id/entries",
|
||||
async ({
|
||||
params: { id },
|
||||
query: { limit, after, query, sort, filter },
|
||||
headers: { "accept-language": languages, ...headers },
|
||||
request: { url },
|
||||
jwt: { sub },
|
||||
status,
|
||||
}) => {
|
||||
const [serie] = await db
|
||||
.select({ pk: shows.pk })
|
||||
.from(shows)
|
||||
.where(
|
||||
and(
|
||||
eq(shows.kind, "serie"),
|
||||
isUuid(id) ? eq(shows.id, id) : eq(shows.slug, id),
|
||||
),
|
||||
)
|
||||
.limit(1);
|
||||
|
||||
if (!serie) {
|
||||
return status(404, {
|
||||
status: 404,
|
||||
message: `No serie with the id or slug: '${id}'.`,
|
||||
});
|
||||
}
|
||||
|
||||
const langs = processLanguages(languages);
|
||||
const items = (await getEntries({
|
||||
limit,
|
||||
after,
|
||||
query,
|
||||
sort,
|
||||
filter: and(
|
||||
eq(entries.showPk, serie.pk),
|
||||
ne(entries.kind, "extra"),
|
||||
filter,
|
||||
),
|
||||
languages: langs,
|
||||
userId: sub,
|
||||
})) as Entry[];
|
||||
|
||||
return createPage(items, { url, sort, limit, headers });
|
||||
},
|
||||
{
|
||||
detail: { description: "Get entries of a serie" },
|
||||
params: t.Object({
|
||||
id: t.String({
|
||||
description: "The id or slug of the serie.",
|
||||
example: madeInAbyss.slug,
|
||||
}),
|
||||
}),
|
||||
query: t.Object({
|
||||
sort: entrySort,
|
||||
filter: t.Optional(Filter({ def: entryFilters })),
|
||||
query: t.Optional(t.String({ description: description.query })),
|
||||
limit: t.Integer({
|
||||
minimum: 1,
|
||||
maximum: 250,
|
||||
default: 50,
|
||||
description: "Max page size.",
|
||||
}),
|
||||
after: t.Optional(t.String({ description: description.after })),
|
||||
}),
|
||||
headers: t.Object(
|
||||
{
|
||||
"accept-language": AcceptLanguage({ autoFallback: true }),
|
||||
},
|
||||
{ additionalProperties: true },
|
||||
),
|
||||
response: {
|
||||
200: Page(Entry),
|
||||
404: {
|
||||
...KError,
|
||||
description: "No serie found with the given id or slug.",
|
||||
},
|
||||
422: KError,
|
||||
},
|
||||
},
|
||||
)
|
||||
.get(
|
||||
"/series/:id/extras",
|
||||
async ({
|
||||
params: { id },
|
||||
query: { limit, after, query, sort, filter },
|
||||
request: { url },
|
||||
headers,
|
||||
jwt: { sub },
|
||||
status,
|
||||
}) => {
|
||||
const [serie] = await db
|
||||
.select({ pk: shows.pk })
|
||||
.from(shows)
|
||||
.where(
|
||||
and(
|
||||
eq(shows.kind, "serie"),
|
||||
isUuid(id) ? eq(shows.id, id) : eq(shows.slug, id),
|
||||
),
|
||||
)
|
||||
.limit(1);
|
||||
|
||||
if (!serie) {
|
||||
return status(404, {
|
||||
status: 404,
|
||||
message: `No serie with the id or slug: '${id}'.`,
|
||||
});
|
||||
}
|
||||
|
||||
const items = (await getEntries({
|
||||
limit,
|
||||
after,
|
||||
query,
|
||||
sort: sort,
|
||||
filter: and(
|
||||
eq(entries.showPk, serie.pk),
|
||||
eq(entries.kind, "extra"),
|
||||
filter,
|
||||
),
|
||||
languages: ["extra"],
|
||||
userId: sub,
|
||||
})) as Extra[];
|
||||
|
||||
return createPage(items, { url, sort, limit, headers });
|
||||
},
|
||||
{
|
||||
detail: { description: "Get extras of a serie" },
|
||||
params: t.Object({
|
||||
id: t.String({
|
||||
description: "The id or slug of the serie.",
|
||||
example: madeInAbyss.slug,
|
||||
}),
|
||||
}),
|
||||
query: t.Object({
|
||||
sort: extraSort,
|
||||
filter: t.Optional(Filter({ def: extraFilters })),
|
||||
query: t.Optional(t.String({ description: description.query })),
|
||||
limit: t.Integer({
|
||||
minimum: 1,
|
||||
maximum: 250,
|
||||
default: 50,
|
||||
description: "Max page size.",
|
||||
}),
|
||||
after: t.Optional(t.String({ description: description.after })),
|
||||
}),
|
||||
response: {
|
||||
200: Page(Extra),
|
||||
404: {
|
||||
...KError,
|
||||
description: "No serie found with the given id or slug.",
|
||||
},
|
||||
422: KError,
|
||||
},
|
||||
},
|
||||
)
|
||||
.get(
|
||||
"/news",
|
||||
async ({
|
||||
query: { limit, after, query, filter },
|
||||
request: { url },
|
||||
headers,
|
||||
jwt: { sub },
|
||||
}) => {
|
||||
const sort = newsSort;
|
||||
const items = (await getEntries({
|
||||
limit,
|
||||
after,
|
||||
query,
|
||||
sort,
|
||||
filter: and(
|
||||
isNotNull(entries.availableSince),
|
||||
ne(entries.kind, "extra"),
|
||||
filter,
|
||||
),
|
||||
languages: ["extra"],
|
||||
userId: sub,
|
||||
})) as Entry[];
|
||||
|
||||
return createPage(items, { url, sort, limit, headers });
|
||||
},
|
||||
{
|
||||
detail: { description: "Get new movies/episodes added recently." },
|
||||
query: t.Object({
|
||||
filter: t.Optional(Filter({ def: entryFilters })),
|
||||
query: t.Optional(t.String({ description: description.query })),
|
||||
limit: t.Integer({
|
||||
minimum: 1,
|
||||
maximum: 250,
|
||||
default: 50,
|
||||
description: "Max page size.",
|
||||
}),
|
||||
after: t.Optional(t.String({ description: description.after })),
|
||||
}),
|
||||
response: {
|
||||
200: Page(Entry),
|
||||
422: KError,
|
||||
},
|
||||
tags: ["shows"],
|
||||
},
|
||||
);
|
||||
404
api/src/controllers/images.ts
Normal file
404
api/src/controllers/images.ts
Normal file
@@ -0,0 +1,404 @@
|
||||
import type { Stats } from "node:fs";
|
||||
import type { S3Stats } from "bun";
|
||||
import { and, eq, type SQL, sql } from "drizzle-orm";
|
||||
import Elysia, { type Context, t } from "elysia";
|
||||
import { prefix } from "~/base";
|
||||
import { db } from "~/db";
|
||||
import {
|
||||
shows,
|
||||
showTranslations,
|
||||
staff,
|
||||
studios,
|
||||
studioTranslations,
|
||||
} from "~/db/schema";
|
||||
import { sqlarr } from "~/db/utils";
|
||||
import { KError } from "~/models/error";
|
||||
import { bubble } from "~/models/examples";
|
||||
import { AcceptLanguage, isUuid, processLanguages } from "~/models/utils";
|
||||
import { comment, getFile } from "~/utils";
|
||||
import { imageDir } from "./seed/images";
|
||||
|
||||
function getRedirectToImageHandler({ filter }: { filter?: SQL }) {
|
||||
return async function Handler({
|
||||
params: { id, image },
|
||||
headers: { "accept-language": languages },
|
||||
query: { quality },
|
||||
set,
|
||||
status,
|
||||
redirect,
|
||||
}: {
|
||||
params: { id?: string; image: "poster" | "thumbnail" | "banner" | "logo" };
|
||||
headers: { "accept-language": string };
|
||||
query: { quality?: "high" | "medium" | "low" };
|
||||
set: Context["set"];
|
||||
status: Context["status"];
|
||||
redirect: Context["redirect"];
|
||||
}) {
|
||||
id ??= "random";
|
||||
const lang = processLanguages(languages);
|
||||
const item = db.$with("item").as(
|
||||
db
|
||||
.select({ pk: shows.pk })
|
||||
.from(shows)
|
||||
.where(
|
||||
and(
|
||||
filter,
|
||||
id !== "random"
|
||||
? isUuid(id)
|
||||
? eq(shows.id, id)
|
||||
: eq(shows.slug, id)
|
||||
: undefined,
|
||||
),
|
||||
)
|
||||
.orderBy(sql`random()`)
|
||||
.limit(1),
|
||||
);
|
||||
const [ret] = await db
|
||||
.with(item)
|
||||
.select({
|
||||
image: showTranslations[image],
|
||||
language: showTranslations.language,
|
||||
})
|
||||
.from(item)
|
||||
.leftJoin(showTranslations, eq(item.pk, showTranslations.pk))
|
||||
.where(
|
||||
!lang.includes("*")
|
||||
? eq(showTranslations.language, sql`any(${sqlarr(lang)})`)
|
||||
: undefined,
|
||||
)
|
||||
.orderBy(
|
||||
sql`array_position(${sqlarr(lang)}, ${showTranslations.language})`,
|
||||
)
|
||||
.limit(1);
|
||||
|
||||
if (!ret) {
|
||||
return status(404, {
|
||||
status: 404,
|
||||
message: `No item found with id or slug: '${id}'.`,
|
||||
});
|
||||
}
|
||||
if (!ret.language) {
|
||||
return status(422, {
|
||||
status: 422,
|
||||
message: "Accept-Language header could not be satisfied.",
|
||||
});
|
||||
}
|
||||
set.headers["content-language"] = ret.language;
|
||||
return quality
|
||||
? redirect(`${prefix}/images/${ret.image!.id}?quality=${quality}`)
|
||||
: redirect(`${prefix}/images/${ret.image!.id}`);
|
||||
};
|
||||
}
|
||||
|
||||
export const imagesH = new Elysia({ tags: ["images"] })
|
||||
.get(
|
||||
"/images/:id",
|
||||
async ({
|
||||
params: { id },
|
||||
query: { quality },
|
||||
headers: reqHeaders,
|
||||
status,
|
||||
}) => {
|
||||
const path = `${imageDir}/${id}.${quality}.jpg`;
|
||||
const file = getFile(path);
|
||||
|
||||
const stat = await file.stat().catch(() => undefined);
|
||||
if (!stat) {
|
||||
return status(404, {
|
||||
status: 404,
|
||||
message: comment`
|
||||
No image available with this ID.
|
||||
Either the id is invalid or the image has not been downloaded yet.
|
||||
`,
|
||||
});
|
||||
}
|
||||
const etag =
|
||||
"etag" in stat
|
||||
? stat.etag
|
||||
: Buffer.from(stat.mtime.toISOString(), "utf8").toString("base64");
|
||||
|
||||
if (await isCached(reqHeaders, etag, path))
|
||||
return new Response(null, { status: 304 });
|
||||
|
||||
const [start = 0, end = Number.POSITIVE_INFINITY] =
|
||||
reqHeaders.range?.split("-").map(Number) ?? [];
|
||||
return new Response(file.slice(start, end), {
|
||||
headers: {
|
||||
Etag: etag,
|
||||
"Cache-Control": `public, max-age=${3 * 60 * 60}`,
|
||||
},
|
||||
}) as any;
|
||||
},
|
||||
{
|
||||
detail: { description: "Access an image by id." },
|
||||
params: t.Object({
|
||||
id: t.String({
|
||||
desription: "Id of the image to retrive.",
|
||||
format: "regex",
|
||||
pattern: "^[0-9a-fA-F]*$",
|
||||
}),
|
||||
}),
|
||||
query: t.Object({
|
||||
quality: t.Optional(
|
||||
t.UnionEnum(["high", "medium", "low"], {
|
||||
default: "high",
|
||||
description: "The quality you want your image to be in.",
|
||||
}),
|
||||
),
|
||||
}),
|
||||
response: {
|
||||
200: t.File({ description: "The whole image" }),
|
||||
206: t.File({ description: "Only the range of the image requested" }),
|
||||
304: t.Void({ description: "Cached image already up-to-date" }),
|
||||
404: { ...KError, description: "No image found with this id." },
|
||||
},
|
||||
},
|
||||
)
|
||||
.guard({
|
||||
query: t.Object({
|
||||
quality: t.Optional(
|
||||
t.UnionEnum(["high", "medium", "low"], {
|
||||
default: "high",
|
||||
description: "The quality you want your image to be in.",
|
||||
}),
|
||||
),
|
||||
}),
|
||||
response: {
|
||||
302: t.Void({
|
||||
description:
|
||||
"Redirected to the [/images/{id}](#tag/images/get/api/images/{id}) route.",
|
||||
}),
|
||||
404: {
|
||||
...KError,
|
||||
description: "No item found with the given id or slug.",
|
||||
},
|
||||
422: KError,
|
||||
},
|
||||
})
|
||||
.get(
|
||||
"/staff/:id/image",
|
||||
async ({ params: { id }, query: { quality }, status, redirect }) => {
|
||||
const [ret] = await db
|
||||
.select({ image: staff.image })
|
||||
.from(staff)
|
||||
.where(
|
||||
id !== "random"
|
||||
? isUuid(id)
|
||||
? eq(shows.id, id)
|
||||
: eq(shows.slug, id)
|
||||
: undefined,
|
||||
)
|
||||
.orderBy(sql`random()`)
|
||||
.limit(1);
|
||||
|
||||
if (!ret) {
|
||||
return status(404, {
|
||||
status: 404,
|
||||
message: `No staff member found with id or slug: '${id}'.`,
|
||||
});
|
||||
}
|
||||
return quality
|
||||
? redirect(`${prefix}/images/${ret.image!.id}?quality=${quality}`)
|
||||
: redirect(`${prefix}/images/${ret.image!.id}`);
|
||||
},
|
||||
{
|
||||
detail: { description: "Get the image of a staff member." },
|
||||
params: t.Object({
|
||||
id: t.String({
|
||||
description: "The id or slug of the staff member.",
|
||||
example: bubble.slug,
|
||||
}),
|
||||
}),
|
||||
},
|
||||
)
|
||||
.guard({
|
||||
headers: t.Object({
|
||||
"accept-language": AcceptLanguage(),
|
||||
}),
|
||||
})
|
||||
.get(
|
||||
"/studios/:id/logo",
|
||||
async ({
|
||||
params: { id },
|
||||
headers: { "accept-language": languages },
|
||||
query: { quality },
|
||||
set,
|
||||
status,
|
||||
redirect,
|
||||
}) => {
|
||||
const lang = processLanguages(languages);
|
||||
const item = db.$with("item").as(
|
||||
db
|
||||
.select({ pk: studios.pk })
|
||||
.from(studios)
|
||||
.where(
|
||||
id !== "random"
|
||||
? isUuid(id)
|
||||
? eq(studios.id, id)
|
||||
: eq(studios.slug, id)
|
||||
: undefined,
|
||||
)
|
||||
.orderBy(sql`random()`)
|
||||
.limit(1),
|
||||
);
|
||||
const [ret] = await db
|
||||
.with(item)
|
||||
.select({
|
||||
image: studioTranslations.logo,
|
||||
language: studioTranslations.language,
|
||||
})
|
||||
.from(item)
|
||||
.leftJoin(studioTranslations, eq(item.pk, studioTranslations.pk))
|
||||
.where(
|
||||
!lang.includes("*")
|
||||
? eq(studioTranslations.language, sql`any(${sqlarr(lang)})`)
|
||||
: undefined,
|
||||
)
|
||||
.orderBy(
|
||||
sql`array_position(${sqlarr(lang)}, ${studioTranslations.language})`,
|
||||
)
|
||||
.limit(1);
|
||||
|
||||
if (!ret) {
|
||||
return status(404, {
|
||||
status: 404,
|
||||
message: `No studio found with id or slug: '${id}'.`,
|
||||
});
|
||||
}
|
||||
if (!ret.language) {
|
||||
return status(422, {
|
||||
status: 422,
|
||||
message: "Accept-Language header could not be satisfied.",
|
||||
});
|
||||
}
|
||||
set.headers["content-language"] = ret.language;
|
||||
return quality
|
||||
? redirect(`${prefix}/images/${ret.image!.id}?quality=${quality}`)
|
||||
: redirect(`${prefix}/images/${ret.image!.id}`);
|
||||
},
|
||||
{
|
||||
detail: { description: "Get the logo of a studio." },
|
||||
params: t.Object({
|
||||
id: t.String({
|
||||
description: "The id or slug of the studio.",
|
||||
example: bubble.slug,
|
||||
}),
|
||||
}),
|
||||
},
|
||||
)
|
||||
.get("/shows/random/:image", getRedirectToImageHandler({}), {
|
||||
detail: { description: "Get the specified image of a random show." },
|
||||
params: t.Object({
|
||||
image: t.UnionEnum(["poster", "thumbnail", "logo", "banner"], {
|
||||
description: "The type of image to retrive.",
|
||||
}),
|
||||
}),
|
||||
})
|
||||
.guard({
|
||||
params: t.Object({
|
||||
id: t.String({
|
||||
description: "The id or slug of the item to retrieve.",
|
||||
example: bubble.slug,
|
||||
}),
|
||||
image: t.UnionEnum(["poster", "thumbnail", "logo", "banner"], {
|
||||
description: "The type of image to retrive.",
|
||||
}),
|
||||
}),
|
||||
headers: t.Object({
|
||||
"accept-language": AcceptLanguage(),
|
||||
}),
|
||||
})
|
||||
.get(
|
||||
"/movies/:id/:image",
|
||||
getRedirectToImageHandler({
|
||||
filter: eq(shows.kind, "movie"),
|
||||
}),
|
||||
{
|
||||
detail: { description: "Get the specified image of a movie" },
|
||||
},
|
||||
)
|
||||
.get(
|
||||
"/series/:id/:image",
|
||||
getRedirectToImageHandler({
|
||||
filter: eq(shows.kind, "serie"),
|
||||
}),
|
||||
{
|
||||
detail: { description: "Get the specified image of a serie" },
|
||||
},
|
||||
)
|
||||
.get(
|
||||
"/collections/:id/:image",
|
||||
getRedirectToImageHandler({
|
||||
filter: eq(shows.kind, "collection"),
|
||||
}),
|
||||
{
|
||||
detail: { description: "Get the specified image of a collection" },
|
||||
},
|
||||
);
|
||||
|
||||
// stolen from https://github.com/elysiajs/elysia-static/blob/main/src/cache.ts
|
||||
|
||||
export async function isCached(
|
||||
headers: Record<string, string | undefined>,
|
||||
etag: string,
|
||||
filePath: string,
|
||||
) {
|
||||
// Always return stale when Cache-Control: no-cache
|
||||
// to support end-to-end reload requests
|
||||
// https://tools.ietf.org/html/rfc2616#section-14.9.4
|
||||
if (
|
||||
headers["cache-control"] &&
|
||||
headers["cache-control"].indexOf("no-cache") !== -1
|
||||
)
|
||||
return false;
|
||||
|
||||
// if-none-match
|
||||
if ("if-none-match" in headers) {
|
||||
const ifNoneMatch = headers["if-none-match"];
|
||||
|
||||
if (ifNoneMatch === "*") return true;
|
||||
|
||||
if (ifNoneMatch === null) return false;
|
||||
|
||||
if (typeof etag !== "string") return false;
|
||||
|
||||
const isMatching = ifNoneMatch === etag;
|
||||
|
||||
if (isMatching) return true;
|
||||
|
||||
/**
|
||||
* A recipient MUST ignore If-Modified-Since if the request contains an
|
||||
* If-None-Match header field; the condition in If-None-Match is considered
|
||||
* to be a more accurate replacement for the condition in If-Modified-Since,
|
||||
* and the two are only combined for the sake of interoperating with older
|
||||
* intermediaries that might not implement If-None-Match.
|
||||
*
|
||||
* @see RFC 9110 section 13.1.3
|
||||
*/
|
||||
return false;
|
||||
}
|
||||
|
||||
// if-modified-since
|
||||
if (headers["if-modified-since"]) {
|
||||
const ifModifiedSince = headers["if-modified-since"];
|
||||
let lastModified: Date | undefined;
|
||||
const stat = await getFile(filePath).stat();
|
||||
try {
|
||||
if ((stat as S3Stats).lastModified) {
|
||||
lastModified = (stat as S3Stats).lastModified;
|
||||
} else if ((stat as Stats).mtime) {
|
||||
lastModified = (stat as Stats).mtime;
|
||||
}
|
||||
} catch {
|
||||
/* empty */
|
||||
}
|
||||
|
||||
if (
|
||||
lastModified !== undefined &&
|
||||
lastModified.getTime() <= Date.parse(ifModifiedSince)
|
||||
)
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
344
api/src/controllers/profiles/history.ts
Normal file
344
api/src/controllers/profiles/history.ts
Normal file
@@ -0,0 +1,344 @@
|
||||
import { and, count, eq, exists, gt, isNotNull, ne, sql } from "drizzle-orm";
|
||||
import { alias } from "drizzle-orm/pg-core";
|
||||
import Elysia, { t } from "elysia";
|
||||
import { auth, getUserInfo } from "~/auth";
|
||||
import { db } from "~/db";
|
||||
import { entries, history, profiles, shows, videos } from "~/db/schema";
|
||||
import { watchlist } from "~/db/schema/watchlist";
|
||||
import { coalesce, values } from "~/db/utils";
|
||||
import { Entry } from "~/models/entry";
|
||||
import { KError } from "~/models/error";
|
||||
import { SeedHistory } from "~/models/history";
|
||||
import {
|
||||
AcceptLanguage,
|
||||
createPage,
|
||||
Filter,
|
||||
isUuid,
|
||||
Page,
|
||||
processLanguages,
|
||||
} from "~/models/utils";
|
||||
import { desc } from "~/models/utils/descriptions";
|
||||
import type { WatchlistStatus } from "~/models/watchlist";
|
||||
import {
|
||||
entryFilters,
|
||||
entryProgressQ,
|
||||
entrySort,
|
||||
getEntries,
|
||||
} from "../entries";
|
||||
import { getOrCreateProfile } from "./profile";
|
||||
|
||||
const historyProgressQ: typeof entryProgressQ = db
|
||||
.select({
|
||||
percent: history.percent,
|
||||
time: history.time,
|
||||
entryPk: history.entryPk,
|
||||
playedDate: history.playedDate,
|
||||
videoId: videos.id,
|
||||
})
|
||||
.from(history)
|
||||
.leftJoin(videos, eq(history.videoPk, videos.pk))
|
||||
.leftJoin(profiles, eq(history.profilePk, profiles.pk))
|
||||
.where(eq(profiles.id, sql.placeholder("userId")))
|
||||
.as("progress");
|
||||
|
||||
export const historyH = new Elysia({ tags: ["profiles"] })
|
||||
.use(auth)
|
||||
.guard(
|
||||
{
|
||||
query: t.Object({
|
||||
sort: {
|
||||
...entrySort,
|
||||
default: ["-playedDate"],
|
||||
},
|
||||
filter: t.Optional(Filter({ def: entryFilters })),
|
||||
query: t.Optional(t.String({ description: desc.query })),
|
||||
limit: t.Integer({
|
||||
minimum: 1,
|
||||
maximum: 250,
|
||||
default: 50,
|
||||
description: "Max page size.",
|
||||
}),
|
||||
after: t.Optional(t.String({ description: desc.after })),
|
||||
}),
|
||||
},
|
||||
(app) =>
|
||||
app
|
||||
.get(
|
||||
"/profiles/me/history",
|
||||
async ({
|
||||
query: { sort, filter, query, limit, after },
|
||||
headers: { "accept-language": languages, ...headers },
|
||||
request: { url },
|
||||
jwt: { sub },
|
||||
}) => {
|
||||
const langs = processLanguages(languages);
|
||||
const items = (await getEntries({
|
||||
limit,
|
||||
after,
|
||||
query,
|
||||
sort,
|
||||
filter: and(
|
||||
isNotNull(entryProgressQ.playedDate),
|
||||
ne(entries.kind, "extra"),
|
||||
filter,
|
||||
),
|
||||
languages: langs,
|
||||
userId: sub,
|
||||
progressQ: historyProgressQ,
|
||||
})) as Entry[];
|
||||
|
||||
return createPage(items, { url, sort, limit, headers });
|
||||
},
|
||||
{
|
||||
detail: {
|
||||
description: "List your watch history (episodes/movies seen)",
|
||||
},
|
||||
headers: t.Object(
|
||||
{
|
||||
"accept-language": AcceptLanguage({ autoFallback: true }),
|
||||
},
|
||||
{ additionalProperties: true },
|
||||
),
|
||||
response: {
|
||||
200: Page(Entry),
|
||||
},
|
||||
},
|
||||
)
|
||||
.get(
|
||||
"/profiles/:id/history",
|
||||
async ({
|
||||
params: { id },
|
||||
query: { sort, filter, query, limit, after },
|
||||
headers: {
|
||||
"accept-language": languages,
|
||||
authorization,
|
||||
...headers
|
||||
},
|
||||
request: { url },
|
||||
status,
|
||||
}) => {
|
||||
const uInfo = await getUserInfo(id, { authorization });
|
||||
if ("status" in uInfo) return status(uInfo.status as 404, uInfo);
|
||||
|
||||
const langs = processLanguages(languages);
|
||||
const items = (await getEntries({
|
||||
limit,
|
||||
after,
|
||||
query,
|
||||
sort,
|
||||
filter: and(
|
||||
isNotNull(entryProgressQ.playedDate),
|
||||
ne(entries.kind, "extra"),
|
||||
filter,
|
||||
),
|
||||
languages: langs,
|
||||
userId: uInfo.id,
|
||||
progressQ: historyProgressQ,
|
||||
})) as Entry[];
|
||||
|
||||
return createPage(items, { url, sort, limit, headers });
|
||||
},
|
||||
{
|
||||
detail: {
|
||||
description: "List your watch history (episodes/movies seen)",
|
||||
},
|
||||
params: t.Object({
|
||||
id: t.String({
|
||||
description:
|
||||
"The id or username of the user to read the watchlist of",
|
||||
example: "zoriya",
|
||||
}),
|
||||
}),
|
||||
headers: t.Object({
|
||||
authorization: t.TemplateLiteral("Bearer ${string}"),
|
||||
"accept-language": AcceptLanguage({ autoFallback: true }),
|
||||
}),
|
||||
response: {
|
||||
200: Page(Entry),
|
||||
403: KError,
|
||||
404: {
|
||||
...KError,
|
||||
description: "No user found with the specified id/username.",
|
||||
},
|
||||
422: KError,
|
||||
},
|
||||
},
|
||||
),
|
||||
)
|
||||
.post(
|
||||
"/profiles/me/history",
|
||||
async ({ body, jwt: { sub }, status }) => {
|
||||
const profilePk = await getOrCreateProfile(sub);
|
||||
|
||||
const hist = values(
|
||||
body.map((x) => ({ ...x, entryUseId: isUuid(x.entry) })),
|
||||
{
|
||||
percent: "integer",
|
||||
time: "integer",
|
||||
playedDate: "timestamptz",
|
||||
videoId: "uuid",
|
||||
},
|
||||
).as("hist");
|
||||
const valEqEntries = sql`
|
||||
case
|
||||
when hist.entryUseId::boolean then ${entries.id} = hist.entry::uuid
|
||||
else ${entries.slug} = hist.entry
|
||||
end
|
||||
`;
|
||||
|
||||
const rows = await db
|
||||
.insert(history)
|
||||
.select(
|
||||
db
|
||||
.select({
|
||||
profilePk: sql`${profilePk}`.as("profilePk"),
|
||||
entryPk: entries.pk,
|
||||
videoPk: videos.pk,
|
||||
percent: sql`hist.percent`.as("percent"),
|
||||
time: sql`hist.time`.as("time"),
|
||||
playedDate: sql`hist.playedDate`.as("playedDate"),
|
||||
})
|
||||
.from(hist)
|
||||
.innerJoin(entries, valEqEntries)
|
||||
.leftJoin(videos, eq(videos.id, sql`hist.videoId`)),
|
||||
)
|
||||
.returning({ pk: history.pk });
|
||||
|
||||
// automatically update watchlist with this new info
|
||||
|
||||
const nextEntry = alias(entries, "next_entry");
|
||||
const nextEntryQ = db
|
||||
.select({
|
||||
pk: nextEntry.pk,
|
||||
})
|
||||
.from(nextEntry)
|
||||
.where(
|
||||
and(
|
||||
eq(nextEntry.showPk, entries.showPk),
|
||||
ne(nextEntry.kind, "extra"),
|
||||
gt(nextEntry.order, entries.order),
|
||||
),
|
||||
)
|
||||
.orderBy(nextEntry.order)
|
||||
.limit(1)
|
||||
.as("nextEntryQ");
|
||||
|
||||
const seenCountQ = db
|
||||
.select({ c: count() })
|
||||
.from(entries)
|
||||
.where(
|
||||
and(
|
||||
eq(entries.showPk, sql`excluded.show_pk`),
|
||||
exists(
|
||||
db
|
||||
.select()
|
||||
.from(history)
|
||||
.where(
|
||||
and(
|
||||
eq(history.profilePk, profilePk),
|
||||
eq(history.entryPk, entries.pk),
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
|
||||
const showKindQ = db
|
||||
.select({ k: shows.kind })
|
||||
.from(shows)
|
||||
.where(eq(shows.pk, sql`excluded.show_pk`));
|
||||
|
||||
await db
|
||||
.insert(watchlist)
|
||||
.select(
|
||||
db
|
||||
.select({
|
||||
profilePk: sql`${profilePk}`.as("profilePk"),
|
||||
showPk: entries.showPk,
|
||||
status: sql<WatchlistStatus>`
|
||||
case
|
||||
when
|
||||
hist.percent >= 95
|
||||
and ${nextEntryQ.pk} is null
|
||||
then 'completed'::watchlist_status
|
||||
else 'watching'::watchlist_status
|
||||
end
|
||||
`.as("status"),
|
||||
seenCount: sql`
|
||||
case
|
||||
when ${entries.kind} = 'movie' then hist.percent
|
||||
when hist.percent >= 95 then 1
|
||||
else 0
|
||||
end
|
||||
`.as("seen_count"),
|
||||
nextEntry: sql`
|
||||
case
|
||||
when hist.percent >= 95 then ${nextEntryQ.pk}
|
||||
else ${entries.pk}
|
||||
end
|
||||
`.as("next_entry"),
|
||||
score: sql`null`.as("score"),
|
||||
startedAt: sql`hist.playedDate`.as("startedAt"),
|
||||
lastPlayedAt: sql`hist.playedDate`.as("lastPlayedAt"),
|
||||
completedAt: sql`
|
||||
case
|
||||
when ${nextEntryQ.pk} is null then hist.playedDate
|
||||
else null
|
||||
end
|
||||
`.as("completedAt"),
|
||||
// see https://github.com/drizzle-team/drizzle-orm/issues/3608
|
||||
updatedAt: sql`now()`.as("updatedAt"),
|
||||
})
|
||||
.from(hist)
|
||||
.leftJoin(entries, valEqEntries)
|
||||
.leftJoinLateral(nextEntryQ, sql`true`),
|
||||
)
|
||||
.onConflictDoUpdate({
|
||||
target: [watchlist.profilePk, watchlist.showPk],
|
||||
set: {
|
||||
status: sql`
|
||||
case
|
||||
when excluded.status = 'completed' then excluded.status
|
||||
when
|
||||
${watchlist.status} != 'completed'
|
||||
and ${watchlist.status} != 'rewatching'
|
||||
then excluded.status
|
||||
else ${watchlist.status}
|
||||
end
|
||||
`,
|
||||
seenCount: sql`
|
||||
case
|
||||
when ${showKindQ} = 'movie' then excluded.seen_count
|
||||
else ${seenCountQ}
|
||||
end`,
|
||||
nextEntry: sql`
|
||||
case
|
||||
when ${watchlist.status} = 'completed' then null
|
||||
else excluded.next_entry
|
||||
end
|
||||
`,
|
||||
lastPlayedAt: sql`excluded.last_played_at`,
|
||||
completedAt: coalesce(
|
||||
watchlist.completedAt,
|
||||
sql`excluded.completed_at`,
|
||||
),
|
||||
},
|
||||
});
|
||||
|
||||
return status(201, { status: 201, inserted: rows.length });
|
||||
},
|
||||
{
|
||||
detail: { description: "Bulk add entries/movies to your watch history." },
|
||||
body: t.Array(SeedHistory),
|
||||
permissions: ["core.read"],
|
||||
response: {
|
||||
201: t.Object({
|
||||
status: t.Literal(201),
|
||||
inserted: t.Integer({
|
||||
description: "The number of history entry inserted",
|
||||
}),
|
||||
}),
|
||||
422: KError,
|
||||
},
|
||||
},
|
||||
);
|
||||
143
api/src/controllers/profiles/nextup.ts
Normal file
143
api/src/controllers/profiles/nextup.ts
Normal file
@@ -0,0 +1,143 @@
|
||||
import { and, eq, sql } from "drizzle-orm";
|
||||
import Elysia, { t } from "elysia";
|
||||
import { auth } from "~/auth";
|
||||
import { db } from "~/db";
|
||||
import { entries } from "~/db/schema";
|
||||
import { watchlist } from "~/db/schema/watchlist";
|
||||
import { getColumns } from "~/db/utils";
|
||||
import { Entry } from "~/models/entry";
|
||||
import {
|
||||
AcceptLanguage,
|
||||
createPage,
|
||||
Filter,
|
||||
type FilterDef,
|
||||
keysetPaginate,
|
||||
Page,
|
||||
processLanguages,
|
||||
Sort,
|
||||
sortToSql,
|
||||
} from "~/models/utils";
|
||||
import { desc } from "~/models/utils/descriptions";
|
||||
import {
|
||||
entryFilters,
|
||||
entryProgressQ,
|
||||
entryVideosQ,
|
||||
getEntryTransQ,
|
||||
mapProgress,
|
||||
} from "../entries";
|
||||
|
||||
const nextupSort = Sort(
|
||||
// copy pasted from entrySort + adding new stuff
|
||||
{
|
||||
order: entries.order,
|
||||
seasonNumber: entries.seasonNumber,
|
||||
episodeNumber: entries.episodeNumber,
|
||||
number: entries.episodeNumber,
|
||||
airDate: entries.airDate,
|
||||
|
||||
started: watchlist.startedAt,
|
||||
added: watchlist.createdAt,
|
||||
lastPlayed: watchlist.lastPlayedAt,
|
||||
},
|
||||
{
|
||||
default: ["-lastPlayed"],
|
||||
tablePk: entries.pk,
|
||||
},
|
||||
);
|
||||
|
||||
const nextupFilters: FilterDef = {
|
||||
...entryFilters,
|
||||
};
|
||||
|
||||
export const nextup = new Elysia({ tags: ["profiles"] })
|
||||
.use(auth)
|
||||
.guard({
|
||||
query: t.Object({
|
||||
sort: nextupSort,
|
||||
filter: t.Optional(Filter({ def: nextupFilters })),
|
||||
query: t.Optional(t.String({ description: desc.query })),
|
||||
limit: t.Integer({
|
||||
minimum: 1,
|
||||
maximum: 250,
|
||||
default: 50,
|
||||
description: "Max page size.",
|
||||
}),
|
||||
after: t.Optional(t.String({ description: desc.after })),
|
||||
}),
|
||||
})
|
||||
.get(
|
||||
"/profiles/me/nextup",
|
||||
async ({
|
||||
query: { sort, filter, query, limit, after },
|
||||
headers: { "accept-language": languages, ...headers },
|
||||
request: { url },
|
||||
jwt: { sub },
|
||||
}) => {
|
||||
const langs = processLanguages(languages);
|
||||
const transQ = getEntryTransQ(langs);
|
||||
|
||||
const {
|
||||
externalId,
|
||||
order,
|
||||
seasonNumber,
|
||||
episodeNumber,
|
||||
extraKind,
|
||||
kind,
|
||||
...entryCol
|
||||
} = getColumns(entries);
|
||||
|
||||
const items = await db
|
||||
.select({
|
||||
...entryCol,
|
||||
...getColumns(transQ),
|
||||
videos: entryVideosQ.videos,
|
||||
progress: mapProgress({ aliased: true }),
|
||||
// specials don't have an `episodeNumber` but a `number` field.
|
||||
number: sql<number>`${episodeNumber}`,
|
||||
|
||||
// assign more restrained types to make typescript happy.
|
||||
kind: sql<Entry["kind"]>`${kind}`,
|
||||
externalId: sql<any>`${externalId}`,
|
||||
order: sql<number>`${order}`,
|
||||
seasonNumber: sql<number>`${seasonNumber}`,
|
||||
episodeNumber: sql<number>`${episodeNumber}`,
|
||||
name: sql<string>`${transQ.name}`,
|
||||
})
|
||||
.from(entries)
|
||||
.innerJoin(watchlist, eq(watchlist.nextEntry, entries.pk))
|
||||
.innerJoin(transQ, eq(entries.pk, transQ.pk))
|
||||
.crossJoinLateral(entryVideosQ)
|
||||
.leftJoin(entryProgressQ, eq(entries.pk, entryProgressQ.entryPk))
|
||||
.where(
|
||||
and(
|
||||
filter,
|
||||
query ? sql`${transQ.name} %> ${query}::text` : undefined,
|
||||
keysetPaginate({ after, sort }),
|
||||
),
|
||||
)
|
||||
.orderBy(
|
||||
...(query
|
||||
? [sql`word_similarity(${query}::text, ${transQ.name})`]
|
||||
: sortToSql(sort)),
|
||||
entries.pk,
|
||||
)
|
||||
.limit(limit)
|
||||
.execute({ userId: sub });
|
||||
|
||||
return createPage(items, { url, sort, limit, headers });
|
||||
},
|
||||
{
|
||||
detail: {
|
||||
description: "",
|
||||
},
|
||||
headers: t.Object(
|
||||
{
|
||||
"accept-language": AcceptLanguage({ autoFallback: true }),
|
||||
},
|
||||
{ additionalProperties: true },
|
||||
),
|
||||
response: {
|
||||
200: Page(Entry),
|
||||
},
|
||||
},
|
||||
);
|
||||
24
api/src/controllers/profiles/profile.ts
Normal file
24
api/src/controllers/profiles/profile.ts
Normal file
@@ -0,0 +1,24 @@
|
||||
import { eq, sql } from "drizzle-orm";
|
||||
import { db } from "~/db";
|
||||
import { profiles } from "~/db/schema";
|
||||
|
||||
export async function getOrCreateProfile(userId: string) {
|
||||
let [profile] = await db
|
||||
.select({ pk: profiles.pk })
|
||||
.from(profiles)
|
||||
.where(eq(profiles.id, userId))
|
||||
.limit(1);
|
||||
if (profile) return profile.pk;
|
||||
|
||||
[profile] = await db
|
||||
.insert(profiles)
|
||||
.values({ id: userId })
|
||||
.onConflictDoUpdate({
|
||||
// we can't do `onConflictDoNothing` because on race conditions
|
||||
// we still want the profile to be returned.
|
||||
target: [profiles.id],
|
||||
set: { id: sql`excluded.id` },
|
||||
})
|
||||
.returning({ pk: profiles.pk });
|
||||
return profile.pk;
|
||||
}
|
||||
351
api/src/controllers/profiles/watchlist.ts
Normal file
351
api/src/controllers/profiles/watchlist.ts
Normal file
@@ -0,0 +1,351 @@
|
||||
import { and, eq, isNotNull, isNull, sql } from "drizzle-orm";
|
||||
import Elysia, { t } from "elysia";
|
||||
import { auth, getUserInfo } from "~/auth";
|
||||
import {
|
||||
getShows,
|
||||
showFilters,
|
||||
showSort,
|
||||
watchStatusQ,
|
||||
} from "~/controllers/shows/logic";
|
||||
import { db } from "~/db";
|
||||
import { entries, shows } from "~/db/schema";
|
||||
import { watchlist } from "~/db/schema/watchlist";
|
||||
import { conflictUpdateAllExcept, getColumns } from "~/db/utils";
|
||||
import { Entry } from "~/models/entry";
|
||||
import { KError } from "~/models/error";
|
||||
import { bubble, madeInAbyss } from "~/models/examples";
|
||||
import { Movie } from "~/models/movie";
|
||||
import { Serie } from "~/models/serie";
|
||||
import {
|
||||
AcceptLanguage,
|
||||
createPage,
|
||||
DbMetadata,
|
||||
Filter,
|
||||
isUuid,
|
||||
Page,
|
||||
processLanguages,
|
||||
} from "~/models/utils";
|
||||
import { desc } from "~/models/utils/descriptions";
|
||||
import { MovieWatchStatus, SerieWatchStatus } from "~/models/watchlist";
|
||||
import { getOrCreateProfile } from "./profile";
|
||||
|
||||
async function setWatchStatus({
|
||||
show,
|
||||
status,
|
||||
userId,
|
||||
}: {
|
||||
show:
|
||||
| { pk: number; kind: "movie" }
|
||||
| { pk: number; kind: "serie"; entriesCount: number };
|
||||
status: Omit<SerieWatchStatus, "seenCount">;
|
||||
userId: string;
|
||||
}) {
|
||||
const profilePk = await getOrCreateProfile(userId);
|
||||
|
||||
const firstEntryQ = db
|
||||
.select({ pk: entries.pk })
|
||||
.from(entries)
|
||||
.where(eq(entries.showPk, show.pk))
|
||||
.orderBy(entries.order)
|
||||
.limit(1);
|
||||
|
||||
const [ret] = await db
|
||||
.insert(watchlist)
|
||||
.values({
|
||||
...status,
|
||||
profilePk: profilePk,
|
||||
seenCount:
|
||||
status.status === "completed"
|
||||
? show.kind === "movie"
|
||||
? 100
|
||||
: show.entriesCount
|
||||
: 0,
|
||||
showPk: show.pk,
|
||||
nextEntry:
|
||||
status.status === "watching" || status.status === "rewatching"
|
||||
? sql`${firstEntryQ}`
|
||||
: sql`null`,
|
||||
lastPlayedAt: status.startedAt,
|
||||
})
|
||||
.onConflictDoUpdate({
|
||||
target: [watchlist.profilePk, watchlist.showPk],
|
||||
set: {
|
||||
...conflictUpdateAllExcept(watchlist, [
|
||||
"profilePk",
|
||||
"showPk",
|
||||
"createdAt",
|
||||
"seenCount",
|
||||
"nextEntry",
|
||||
"lastPlayedAt",
|
||||
]),
|
||||
...(status.status === "completed"
|
||||
? {
|
||||
seenCount: sql`excluded.seen_count`,
|
||||
nextEntry: sql`null`,
|
||||
}
|
||||
: {}),
|
||||
// only set seenCount & nextEntry when marking as "rewatching"
|
||||
// if it's already rewatching, the history updates are more up-dated.
|
||||
...(status.status === "rewatching"
|
||||
? {
|
||||
seenCount: sql`
|
||||
case when ${watchlist.status} != 'rewatching'
|
||||
then excluded.seen_count
|
||||
else
|
||||
${watchlist.seenCount}
|
||||
end`,
|
||||
nextEntry: sql`
|
||||
case when ${watchlist.status} != 'rewatching'
|
||||
then excluded.next_entry
|
||||
else
|
||||
${watchlist.nextEntry}
|
||||
end`,
|
||||
}
|
||||
: {}),
|
||||
},
|
||||
})
|
||||
.returning({
|
||||
...getColumns(watchlist),
|
||||
percent: sql<number>`${watchlist.seenCount}`.as("percent"),
|
||||
});
|
||||
return ret;
|
||||
}
|
||||
|
||||
export const watchlistH = new Elysia({ tags: ["profiles"] })
|
||||
.use(auth)
|
||||
.guard(
|
||||
{
|
||||
query: t.Object({
|
||||
sort: {
|
||||
...showSort,
|
||||
default: ["watchStatus", ...showSort.default],
|
||||
},
|
||||
filter: t.Optional(Filter({ def: showFilters })),
|
||||
query: t.Optional(t.String({ description: desc.query })),
|
||||
limit: t.Integer({
|
||||
minimum: 1,
|
||||
maximum: 250,
|
||||
default: 50,
|
||||
description: "Max page size.",
|
||||
}),
|
||||
after: t.Optional(t.String({ description: desc.after })),
|
||||
preferOriginal: t.Optional(
|
||||
t.Boolean({
|
||||
description: desc.preferOriginal,
|
||||
}),
|
||||
),
|
||||
}),
|
||||
},
|
||||
(app) =>
|
||||
app
|
||||
.get(
|
||||
"/profiles/me/watchlist",
|
||||
async ({
|
||||
query: { limit, after, query, sort, filter, preferOriginal },
|
||||
headers: { "accept-language": languages, ...headers },
|
||||
request: { url },
|
||||
jwt: { sub, settings },
|
||||
}) => {
|
||||
const langs = processLanguages(languages);
|
||||
const items = await getShows({
|
||||
limit,
|
||||
after,
|
||||
query,
|
||||
sort,
|
||||
filter: and(
|
||||
isNotNull(watchStatusQ.status),
|
||||
isNull(shows.collectionPk),
|
||||
filter,
|
||||
),
|
||||
languages: langs,
|
||||
preferOriginal: preferOriginal ?? settings.preferOriginal,
|
||||
relations: ["nextEntry"],
|
||||
userId: sub,
|
||||
});
|
||||
return createPage(items, { url, sort, limit, headers });
|
||||
},
|
||||
{
|
||||
detail: { description: "Get all movies/series in your watchlist" },
|
||||
headers: t.Object(
|
||||
{
|
||||
"accept-language": AcceptLanguage({ autoFallback: true }),
|
||||
},
|
||||
{ additionalProperties: true },
|
||||
),
|
||||
response: {
|
||||
200: Page(
|
||||
t.Union([
|
||||
t.Intersect([Movie, t.Object({ kind: t.Literal("movie") })]),
|
||||
t.Intersect([
|
||||
Serie,
|
||||
t.Object({
|
||||
kind: t.Literal("serie"),
|
||||
nextEntry: t.Optional(t.Nullable(Entry)),
|
||||
}),
|
||||
]),
|
||||
]),
|
||||
),
|
||||
422: KError,
|
||||
},
|
||||
},
|
||||
)
|
||||
.get(
|
||||
"/profiles/:id/watchlist",
|
||||
async ({
|
||||
params: { id },
|
||||
query: { limit, after, query, sort, filter, preferOriginal },
|
||||
jwt: { settings },
|
||||
headers: {
|
||||
"accept-language": languages,
|
||||
authorization,
|
||||
...headers
|
||||
},
|
||||
request: { url },
|
||||
status,
|
||||
}) => {
|
||||
const uInfo = await getUserInfo(id, { authorization });
|
||||
if ("status" in uInfo) return status(uInfo.status as 404, uInfo);
|
||||
|
||||
const langs = processLanguages(languages);
|
||||
const items = await getShows({
|
||||
limit,
|
||||
after,
|
||||
query,
|
||||
sort,
|
||||
filter: and(
|
||||
isNotNull(watchStatusQ.status),
|
||||
isNull(shows.collectionPk),
|
||||
filter,
|
||||
),
|
||||
languages: langs,
|
||||
preferOriginal: preferOriginal ?? settings.preferOriginal,
|
||||
relations: ["nextEntry"],
|
||||
userId: uInfo.id,
|
||||
});
|
||||
return createPage(items, { url, sort, limit, headers });
|
||||
},
|
||||
{
|
||||
detail: {
|
||||
description: "Get all movies/series in someone's watchlist",
|
||||
},
|
||||
params: t.Object({
|
||||
id: t.String({
|
||||
description:
|
||||
"The id or username of the user to read the watchlist of",
|
||||
example: "zoriya",
|
||||
}),
|
||||
}),
|
||||
headers: t.Object({
|
||||
authorization: t.TemplateLiteral("Bearer ${string}"),
|
||||
"accept-language": AcceptLanguage({ autoFallback: true }),
|
||||
}),
|
||||
response: {
|
||||
200: Page(
|
||||
t.Union([
|
||||
t.Intersect([Movie, t.Object({ kind: t.Literal("movie") })]),
|
||||
t.Intersect([
|
||||
Serie,
|
||||
t.Object({
|
||||
kind: t.Literal("serie"),
|
||||
nextEntry: t.Optional(t.Nullable(Entry)),
|
||||
}),
|
||||
]),
|
||||
]),
|
||||
),
|
||||
403: KError,
|
||||
404: {
|
||||
...KError,
|
||||
description: "No user found with the specified id/username.",
|
||||
},
|
||||
422: KError,
|
||||
},
|
||||
permissions: ["users.read"],
|
||||
},
|
||||
),
|
||||
)
|
||||
.post(
|
||||
"/series/:id/watchstatus",
|
||||
async ({ params: { id }, body, jwt: { sub }, status }) => {
|
||||
const [show] = await db
|
||||
.select({ pk: shows.pk, entriesCount: shows.entriesCount })
|
||||
.from(shows)
|
||||
.where(
|
||||
and(
|
||||
eq(shows.kind, "serie"),
|
||||
isUuid(id) ? eq(shows.id, id) : eq(shows.slug, id),
|
||||
),
|
||||
);
|
||||
|
||||
if (!show) {
|
||||
return status(404, {
|
||||
status: 404,
|
||||
message: `No serie found for the id/slug: '${id}'.`,
|
||||
});
|
||||
}
|
||||
return await setWatchStatus({
|
||||
show: { pk: show.pk, kind: "serie", entriesCount: show.entriesCount },
|
||||
userId: sub,
|
||||
status: body,
|
||||
});
|
||||
},
|
||||
{
|
||||
detail: { description: "Set watchstatus of a series." },
|
||||
params: t.Object({
|
||||
id: t.String({
|
||||
description: "The id or slug of the serie.",
|
||||
example: madeInAbyss.slug,
|
||||
}),
|
||||
}),
|
||||
body: t.Omit(SerieWatchStatus, ["seenCount"]),
|
||||
response: {
|
||||
200: t.Intersect([SerieWatchStatus, DbMetadata]),
|
||||
404: KError,
|
||||
},
|
||||
permissions: ["core.read"],
|
||||
},
|
||||
)
|
||||
.post(
|
||||
"/movies/:id/watchstatus",
|
||||
async ({ params: { id }, body, jwt: { sub }, status }) => {
|
||||
const [show] = await db
|
||||
.select({ pk: shows.pk })
|
||||
.from(shows)
|
||||
.where(
|
||||
and(
|
||||
eq(shows.kind, "movie"),
|
||||
isUuid(id) ? eq(shows.id, id) : eq(shows.slug, id),
|
||||
),
|
||||
);
|
||||
|
||||
if (!show) {
|
||||
return status(404, {
|
||||
status: 404,
|
||||
message: `No movie found for the id/slug: '${id}'.`,
|
||||
});
|
||||
}
|
||||
|
||||
return await setWatchStatus({
|
||||
show: { pk: show.pk, kind: "movie" },
|
||||
userId: sub,
|
||||
status: {
|
||||
...body,
|
||||
startedAt: body.completedAt,
|
||||
},
|
||||
});
|
||||
},
|
||||
{
|
||||
detail: { description: "Set watchstatus of a movie." },
|
||||
params: t.Object({
|
||||
id: t.String({
|
||||
description: "The id or slug of the movie.",
|
||||
example: bubble.slug,
|
||||
}),
|
||||
}),
|
||||
body: t.Omit(MovieWatchStatus, ["percent"]),
|
||||
response: {
|
||||
200: t.Intersect([MovieWatchStatus, DbMetadata]),
|
||||
404: KError,
|
||||
},
|
||||
permissions: ["core.read"],
|
||||
},
|
||||
);
|
||||
150
api/src/controllers/seasons.ts
Normal file
150
api/src/controllers/seasons.ts
Normal file
@@ -0,0 +1,150 @@
|
||||
import { and, eq, sql } from "drizzle-orm";
|
||||
import { Elysia, t } from "elysia";
|
||||
import { db } from "~/db";
|
||||
import { seasons, seasonTranslations, shows } from "~/db/schema";
|
||||
import { getColumns, sqlarr } from "~/db/utils";
|
||||
import { KError } from "~/models/error";
|
||||
import { madeInAbyss } from "~/models/examples";
|
||||
import {
|
||||
AcceptLanguage,
|
||||
createPage,
|
||||
Filter,
|
||||
type FilterDef,
|
||||
isUuid,
|
||||
keysetPaginate,
|
||||
Page,
|
||||
processLanguages,
|
||||
Sort,
|
||||
sortToSql,
|
||||
} from "~/models/utils";
|
||||
import { desc } from "~/models/utils/descriptions";
|
||||
import { Season, SeasonTranslation } from "../models/season";
|
||||
|
||||
const seasonFilters: FilterDef = {
|
||||
seasonNumber: { column: seasons.seasonNumber, type: "int" },
|
||||
startAir: { column: seasons.startAir, type: "date" },
|
||||
endAir: { column: seasons.endAir, type: "date" },
|
||||
entriesCount: { column: seasons.entriesCount, type: "int" },
|
||||
availableCount: { column: seasons.availableCount, type: "int" },
|
||||
};
|
||||
|
||||
const seasonSort = Sort(
|
||||
{
|
||||
seasonNumber: seasons.seasonNumber,
|
||||
startAir: seasons.startAir,
|
||||
endAir: seasons.endAir,
|
||||
entriesCount: seasons.entriesCount,
|
||||
availableCount: seasons.availableCount,
|
||||
nextRefresh: seasons.nextRefresh,
|
||||
},
|
||||
{
|
||||
default: ["seasonNumber"],
|
||||
tablePk: seasons.pk,
|
||||
},
|
||||
);
|
||||
|
||||
export const seasonsH = new Elysia({ tags: ["series"] })
|
||||
.model({
|
||||
season: Season,
|
||||
"season-translation": SeasonTranslation,
|
||||
})
|
||||
.get(
|
||||
"/series/:id/seasons",
|
||||
async ({
|
||||
params: { id },
|
||||
query: { limit, after, query, sort, filter },
|
||||
headers: { "accept-language": languages, ...headers },
|
||||
request: { url },
|
||||
status,
|
||||
}) => {
|
||||
const langs = processLanguages(languages);
|
||||
|
||||
const [serie] = await db
|
||||
.select({ pk: shows.pk })
|
||||
.from(shows)
|
||||
.where(
|
||||
and(
|
||||
eq(shows.kind, "serie"),
|
||||
isUuid(id) ? eq(shows.id, id) : eq(shows.slug, id),
|
||||
),
|
||||
)
|
||||
.limit(1);
|
||||
|
||||
if (!serie) {
|
||||
return status(404, {
|
||||
status: 404,
|
||||
message: `No serie with the id or slug: '${id}'.`,
|
||||
});
|
||||
}
|
||||
|
||||
const transQ = db
|
||||
.selectDistinctOn([seasonTranslations.pk])
|
||||
.from(seasonTranslations)
|
||||
.orderBy(
|
||||
seasonTranslations.pk,
|
||||
sql`array_position(${sqlarr(langs)}, ${seasonTranslations.language})`,
|
||||
)
|
||||
.as("t");
|
||||
const { pk, ...transCol } = getColumns(transQ);
|
||||
|
||||
const items = await db
|
||||
.select({
|
||||
...getColumns(seasons),
|
||||
...transCol,
|
||||
})
|
||||
.from(seasons)
|
||||
.innerJoin(transQ, eq(seasons.pk, transQ.pk))
|
||||
.where(
|
||||
and(
|
||||
eq(seasons.showPk, serie.pk),
|
||||
filter,
|
||||
query ? sql`${transQ.name} %> ${query}::text` : undefined,
|
||||
keysetPaginate({ after, sort }),
|
||||
),
|
||||
)
|
||||
.orderBy(
|
||||
...(query
|
||||
? [sql`word_similarity(${query}::text, ${transQ.name})`]
|
||||
: sortToSql(sort)),
|
||||
seasons.pk,
|
||||
)
|
||||
.limit(limit);
|
||||
|
||||
return createPage(items, { url, sort, limit, headers });
|
||||
},
|
||||
{
|
||||
detail: { description: "Get seasons of a serie" },
|
||||
params: t.Object({
|
||||
id: t.String({
|
||||
description: "The id or slug of the serie.",
|
||||
example: madeInAbyss.slug,
|
||||
}),
|
||||
}),
|
||||
query: t.Object({
|
||||
sort: seasonSort,
|
||||
filter: t.Optional(Filter({ def: seasonFilters })),
|
||||
query: t.Optional(t.String({ description: desc.query })),
|
||||
limit: t.Integer({
|
||||
minimum: 1,
|
||||
maximum: 250,
|
||||
default: 50,
|
||||
description: "Max page size.",
|
||||
}),
|
||||
after: t.Optional(t.String({ description: desc.after })),
|
||||
}),
|
||||
headers: t.Object(
|
||||
{
|
||||
"accept-language": AcceptLanguage({ autoFallback: true }),
|
||||
},
|
||||
{ additionalProperties: true },
|
||||
),
|
||||
response: {
|
||||
200: Page(Season),
|
||||
404: {
|
||||
...KError,
|
||||
description: "No serie found with the given id or slug.",
|
||||
},
|
||||
422: KError,
|
||||
},
|
||||
},
|
||||
);
|
||||
209
api/src/controllers/seed/images.ts
Normal file
209
api/src/controllers/seed/images.ts
Normal file
@@ -0,0 +1,209 @@
|
||||
import path from "node:path";
|
||||
import { getCurrentSpan, setAttributes } from "@elysiajs/opentelemetry";
|
||||
import { SpanStatusCode } from "@opentelemetry/api";
|
||||
import { encode } from "blurhash";
|
||||
import { and, eq, is, lt, type SQL, sql } from "drizzle-orm";
|
||||
import { PgColumn, type PgTable } from "drizzle-orm/pg-core";
|
||||
import { version } from "package.json";
|
||||
import type { PoolClient } from "pg";
|
||||
import sharp from "sharp";
|
||||
import { db, type Transaction } from "~/db";
|
||||
import { mqueue } from "~/db/schema/mqueue";
|
||||
import { unnestValues } from "~/db/utils";
|
||||
import type { Image } from "~/models/utils";
|
||||
import { record } from "~/otel";
|
||||
import { getFile } from "~/utils";
|
||||
|
||||
export const imageDir = process.env.IMAGES_PATH ?? "/images";
|
||||
export const defaultBlurhash = "000000";
|
||||
|
||||
export type ImageTask = {
|
||||
id: string;
|
||||
url: string;
|
||||
table: string;
|
||||
column: string;
|
||||
};
|
||||
|
||||
// this will only push a task to the image downloader service and not download it instantly.
|
||||
// this is both done to prevent too many requests to be sent at once and to make sure POST
|
||||
// requests are not blocked by image downloading or blurhash calculation
|
||||
export const enqueueOptImage = (
|
||||
imgQueue: ImageTask[],
|
||||
img:
|
||||
| { url: string | null; column: PgColumn }
|
||||
| { url: string | null; table: PgTable; column: SQL },
|
||||
): Image | null => {
|
||||
if (!img.url) return null;
|
||||
|
||||
const hasher = new Bun.CryptoHasher("sha256");
|
||||
hasher.update(img.url);
|
||||
const id = hasher.digest().toString("hex");
|
||||
|
||||
const cleanupColumn = (column: SQL) =>
|
||||
// @ts-expect-error dialect is private
|
||||
db.dialect.sqlToQuery(
|
||||
sql.join(
|
||||
column.queryChunks.map((x) => {
|
||||
if (is(x, PgColumn)) {
|
||||
return sql.identifier(x.name);
|
||||
}
|
||||
return x;
|
||||
}),
|
||||
),
|
||||
).sql;
|
||||
|
||||
const message: ImageTask =
|
||||
"table" in img
|
||||
? {
|
||||
id,
|
||||
url: img.url,
|
||||
// @ts-expect-error dialect is private
|
||||
table: db.dialect.sqlToQuery(sql`${img.table}`).sql,
|
||||
column: cleanupColumn(img.column),
|
||||
}
|
||||
: {
|
||||
id,
|
||||
url: img.url,
|
||||
// @ts-expect-error dialect is private
|
||||
table: db.dialect.sqlToQuery(sql`${img.column.table}`).sql,
|
||||
column: sql.identifier(img.column.name).value,
|
||||
};
|
||||
|
||||
imgQueue.push(message);
|
||||
|
||||
return {
|
||||
id,
|
||||
source: img.url,
|
||||
blurhash: defaultBlurhash,
|
||||
};
|
||||
};
|
||||
|
||||
export const flushImageQueue = record(
|
||||
"enqueueImages",
|
||||
async (tx: Transaction, imgQueue: ImageTask[], priority: number) => {
|
||||
if (!imgQueue.length) return;
|
||||
await tx.insert(mqueue).select(
|
||||
unnestValues(
|
||||
imgQueue.map((x) => ({ kind: "image", message: x, priority })),
|
||||
mqueue,
|
||||
),
|
||||
);
|
||||
await tx.execute(sql`notify kyoo_image`);
|
||||
},
|
||||
);
|
||||
|
||||
export const processImages = record("processImages", async () => {
|
||||
let running = false;
|
||||
async function processAll() {
|
||||
if (running) return;
|
||||
running = true;
|
||||
|
||||
let found = true;
|
||||
while (found) {
|
||||
found = await processOne();
|
||||
}
|
||||
running = false;
|
||||
}
|
||||
|
||||
const client = (await db.$client.connect()) as PoolClient;
|
||||
client.on("notification", (evt) => {
|
||||
if (evt.channel !== "kyoo_image") return;
|
||||
processAll();
|
||||
});
|
||||
await client.query("listen kyoo_image");
|
||||
|
||||
// start processing old tasks
|
||||
await processAll();
|
||||
return () => client.release(true);
|
||||
});
|
||||
|
||||
const processOne = record("download", async () => {
|
||||
return await db.transaction(async (tx) => {
|
||||
const [item] = await tx
|
||||
.select()
|
||||
.from(mqueue)
|
||||
.for("update", { skipLocked: true })
|
||||
.where(and(eq(mqueue.kind, "image"), lt(mqueue.attempt, 5)))
|
||||
.orderBy(mqueue.priority, mqueue.attempt, mqueue.createdAt)
|
||||
.limit(1);
|
||||
|
||||
if (!item) return false;
|
||||
|
||||
const img = item.message as ImageTask;
|
||||
setAttributes({ "item.url": img.url });
|
||||
try {
|
||||
const blurhash = await downloadImage(img.id, img.url);
|
||||
const ret: Image = { id: img.id, source: img.url, blurhash };
|
||||
|
||||
const table = sql.raw(img.table);
|
||||
const column = sql.raw(img.column);
|
||||
|
||||
await tx.execute(sql`
|
||||
update ${table} set ${column} = ${ret}
|
||||
where ${column}->'id' = ${sql.raw(`'"${img.id}"'::jsonb`)}
|
||||
`);
|
||||
|
||||
await tx.delete(mqueue).where(eq(mqueue.id, item.id));
|
||||
} catch (err: any) {
|
||||
const span = getCurrentSpan();
|
||||
if (span) {
|
||||
span.recordException(err);
|
||||
span.setStatus({ code: SpanStatusCode.ERROR });
|
||||
}
|
||||
console.error("Failed to download image", img.url, err.message);
|
||||
await tx
|
||||
.update(mqueue)
|
||||
.set({ attempt: sql`${mqueue.attempt}+1` })
|
||||
.where(eq(mqueue.id, item.id));
|
||||
}
|
||||
return true;
|
||||
});
|
||||
});
|
||||
|
||||
async function downloadImage(id: string, url: string): Promise<string> {
|
||||
const low = await getFile(path.join(imageDir, `${id}.low.jpg`))
|
||||
.arrayBuffer()
|
||||
.catch(() => false as const);
|
||||
if (low) {
|
||||
return await getBlurhash(sharp(low));
|
||||
}
|
||||
|
||||
const resp = await fetch(url, {
|
||||
headers: { "User-Agent": `Kyoo v${version}` },
|
||||
});
|
||||
if (!resp.ok) {
|
||||
throw new Error(`Failed to fetch image: ${resp.status} ${resp.statusText}`);
|
||||
}
|
||||
const buf = Buffer.from(await resp.arrayBuffer());
|
||||
|
||||
const image = sharp(buf);
|
||||
const metadata = await image.metadata();
|
||||
|
||||
if (!metadata.width || !metadata.height) {
|
||||
throw new Error("Could not determine image dimensions");
|
||||
}
|
||||
const resolutions = {
|
||||
low: { width: 320 },
|
||||
medium: { width: 640 },
|
||||
high: { width: 1280 },
|
||||
};
|
||||
await Promise.all(
|
||||
Object.entries(resolutions).map(async ([resolution, dimensions]) => {
|
||||
const buffer = await image.clone().resize(dimensions.width).toBuffer();
|
||||
const file = getFile(path.join(imageDir, `${id}.${resolution}.jpg`));
|
||||
|
||||
await Bun.write(file, buffer, { mode: 0o660 });
|
||||
}),
|
||||
);
|
||||
return await getBlurhash(image);
|
||||
}
|
||||
|
||||
async function getBlurhash(image: sharp.Sharp): Promise<string> {
|
||||
const { data, info } = await image
|
||||
.resize(32, 32, { fit: "inside" })
|
||||
.ensureAlpha()
|
||||
.raw()
|
||||
.toBuffer({ resolveWithObject: true });
|
||||
|
||||
return encode(new Uint8ClampedArray(data), info.width, info.height, 4, 3);
|
||||
}
|
||||
78
api/src/controllers/seed/index.ts
Normal file
78
api/src/controllers/seed/index.ts
Normal file
@@ -0,0 +1,78 @@
|
||||
import Elysia from "elysia";
|
||||
import { KError } from "~/models/error";
|
||||
import { SeedMovie } from "~/models/movie";
|
||||
import { SeedSerie } from "~/models/serie";
|
||||
import { Resource } from "~/models/utils";
|
||||
import { comment } from "~/utils";
|
||||
import { SeedMovieResponse, seedMovie } from "./movies";
|
||||
import { SeedSerieResponse, seedSerie } from "./series";
|
||||
|
||||
export const seed = new Elysia()
|
||||
.model({
|
||||
"seed-movie": SeedMovie,
|
||||
"seed-movie-response": SeedMovieResponse,
|
||||
"seed-serie": SeedSerie,
|
||||
"seed-serie-response": SeedSerieResponse,
|
||||
})
|
||||
.post(
|
||||
"/movies",
|
||||
async ({ body, status }) => {
|
||||
const ret = await seedMovie(body);
|
||||
if ("status" in ret) return status(ret.status, ret as any);
|
||||
return status(ret.updated ? 200 : 201, ret);
|
||||
},
|
||||
{
|
||||
detail: {
|
||||
tags: ["movies"],
|
||||
description:
|
||||
"Create a movie & all related metadata. Can also link videos.",
|
||||
},
|
||||
body: SeedMovie,
|
||||
response: {
|
||||
200: {
|
||||
...SeedMovieResponse,
|
||||
description: "Existing movie edited/updated.",
|
||||
},
|
||||
201: { ...SeedMovieResponse, description: "Created a new movie." },
|
||||
409: {
|
||||
...Resource(),
|
||||
description: comment`
|
||||
A movie with the same slug but a different air date already exists.
|
||||
Change the slug and re-run the request.
|
||||
`,
|
||||
},
|
||||
422: KError,
|
||||
},
|
||||
},
|
||||
)
|
||||
.post(
|
||||
"/series",
|
||||
async ({ body, status }) => {
|
||||
const ret = await seedSerie(body);
|
||||
if ("status" in ret) return status(ret.status, ret as any);
|
||||
return status(ret.updated ? 200 : 201, ret);
|
||||
},
|
||||
{
|
||||
detail: {
|
||||
tags: ["series"],
|
||||
description:
|
||||
"Create a series & all related metadata. Can also link videos.",
|
||||
},
|
||||
body: SeedSerie,
|
||||
response: {
|
||||
200: {
|
||||
...SeedSerieResponse,
|
||||
description: "Existing serie edited/updated.",
|
||||
},
|
||||
201: { ...SeedSerieResponse, description: "Created a new serie." },
|
||||
409: {
|
||||
...Resource(),
|
||||
description: comment`
|
||||
A serie with the same slug but a different air date already exists.
|
||||
Change the slug and re-run the request.
|
||||
`,
|
||||
},
|
||||
422: KError,
|
||||
},
|
||||
},
|
||||
);
|
||||
93
api/src/controllers/seed/insert/collection.ts
Normal file
93
api/src/controllers/seed/insert/collection.ts
Normal file
@@ -0,0 +1,93 @@
|
||||
import { sql } from "drizzle-orm";
|
||||
import { db } from "~/db";
|
||||
import { shows, showTranslations } from "~/db/schema";
|
||||
import { conflictUpdateAllExcept } from "~/db/utils";
|
||||
import type { SeedCollection } from "~/models/collections";
|
||||
import type { SeedMovie } from "~/models/movie";
|
||||
import type { SeedSerie } from "~/models/serie";
|
||||
import { record } from "~/otel";
|
||||
import { enqueueOptImage, flushImageQueue, type ImageTask } from "../images";
|
||||
|
||||
type ShowTrans = typeof showTranslations.$inferInsert;
|
||||
|
||||
export const insertCollection = record(
|
||||
"insertCollection",
|
||||
async (
|
||||
collection: SeedCollection | undefined,
|
||||
show: (
|
||||
| ({ kind: "movie" } & SeedMovie)
|
||||
| ({ kind: "serie" } & SeedSerie)
|
||||
) & {
|
||||
nextRefresh: string;
|
||||
},
|
||||
) => {
|
||||
if (!collection) return null;
|
||||
const { translations, ...col } = collection;
|
||||
|
||||
return await db.transaction(async (tx) => {
|
||||
const imgQueue: ImageTask[] = [];
|
||||
const [ret] = await tx
|
||||
.insert(shows)
|
||||
.values({
|
||||
kind: "collection",
|
||||
status: "unknown",
|
||||
startAir: show.kind === "movie" ? show.airDate : show.startAir,
|
||||
endAir: show.kind === "movie" ? show.airDate : show.endAir,
|
||||
nextRefresh: show.nextRefresh,
|
||||
entriesCount: 0,
|
||||
original: {} as any,
|
||||
...col,
|
||||
})
|
||||
.onConflictDoUpdate({
|
||||
target: shows.slug,
|
||||
set: {
|
||||
...conflictUpdateAllExcept(shows, [
|
||||
"pk",
|
||||
"id",
|
||||
"slug",
|
||||
"createdAt",
|
||||
"startAir",
|
||||
"endAir",
|
||||
]),
|
||||
startAir: sql`least(${shows.startAir}, excluded.start_air)`,
|
||||
endAir: sql`greatest(${shows.endAir}, excluded.end_air)`,
|
||||
},
|
||||
})
|
||||
.returning({ pk: shows.pk, id: shows.id, slug: shows.slug });
|
||||
|
||||
const trans: ShowTrans[] = Object.entries(translations).map(
|
||||
([lang, tr]) => ({
|
||||
pk: ret.pk,
|
||||
language: lang,
|
||||
...tr,
|
||||
poster: enqueueOptImage(imgQueue, {
|
||||
url: tr.poster,
|
||||
column: showTranslations.poster,
|
||||
}),
|
||||
thumbnail: enqueueOptImage(imgQueue, {
|
||||
url: tr.thumbnail,
|
||||
column: showTranslations.thumbnail,
|
||||
}),
|
||||
logo: enqueueOptImage(imgQueue, {
|
||||
url: tr.logo,
|
||||
column: showTranslations.logo,
|
||||
}),
|
||||
banner: enqueueOptImage(imgQueue, {
|
||||
url: tr.banner,
|
||||
column: showTranslations.banner,
|
||||
}),
|
||||
}),
|
||||
);
|
||||
await flushImageQueue(tx, imgQueue, 100);
|
||||
// we can't unnest values here because show translations contains arrays.
|
||||
await tx
|
||||
.insert(showTranslations)
|
||||
.values(trans)
|
||||
.onConflictDoUpdate({
|
||||
target: [showTranslations.pk, showTranslations.language],
|
||||
set: conflictUpdateAllExcept(showTranslations, ["pk", "language"]),
|
||||
});
|
||||
return ret;
|
||||
});
|
||||
},
|
||||
);
|
||||
214
api/src/controllers/seed/insert/entries.ts
Normal file
214
api/src/controllers/seed/insert/entries.ts
Normal file
@@ -0,0 +1,214 @@
|
||||
import { type Column, eq, type SQL, sql } from "drizzle-orm";
|
||||
import { db } from "~/db";
|
||||
import {
|
||||
entries,
|
||||
entryTranslations,
|
||||
entryVideoJoin,
|
||||
videos,
|
||||
} from "~/db/schema";
|
||||
import { conflictUpdateAllExcept, unnest, unnestValues } from "~/db/utils";
|
||||
import type { SeedEntry as SEntry, SeedExtra as SExtra } from "~/models/entry";
|
||||
import { record } from "~/otel";
|
||||
import { enqueueOptImage, flushImageQueue, type ImageTask } from "../images";
|
||||
import { guessNextRefresh } from "../refresh";
|
||||
import { updateAvailableCount, updateAvailableSince } from "./shows";
|
||||
|
||||
type SeedEntry = SEntry & {
|
||||
video?: undefined;
|
||||
};
|
||||
type SeedExtra = Omit<SExtra, "kind"> & {
|
||||
videos?: undefined;
|
||||
translations?: undefined;
|
||||
kind: "extra";
|
||||
extraKind: SExtra["kind"];
|
||||
};
|
||||
|
||||
type EntryI = typeof entries.$inferInsert;
|
||||
type EntryTransI = typeof entryTranslations.$inferInsert;
|
||||
|
||||
const generateSlug = (
|
||||
showSlug: string,
|
||||
entry: SeedEntry | SeedExtra,
|
||||
): string => {
|
||||
switch (entry.kind) {
|
||||
case "episode":
|
||||
return `${showSlug}-s${entry.seasonNumber}e${entry.episodeNumber}`;
|
||||
case "special":
|
||||
return `${showSlug}-sp${entry.number}`;
|
||||
case "movie":
|
||||
if (entry.slug) return entry.slug;
|
||||
return entry.order === 1 ? showSlug : `${showSlug}-${entry.order}`;
|
||||
case "extra":
|
||||
return entry.slug;
|
||||
}
|
||||
};
|
||||
|
||||
export const insertEntries = record(
|
||||
"insertEntries",
|
||||
async (
|
||||
show: { pk: number; slug: string; kind: "movie" | "serie" | "collection" },
|
||||
items: (SeedEntry | SeedExtra)[],
|
||||
onlyExtras = false,
|
||||
) => {
|
||||
if (!items.length) return [];
|
||||
|
||||
const retEntries = await db.transaction(async (tx) => {
|
||||
const imgQueue: ImageTask[] = [];
|
||||
const vals: EntryI[] = items.map((seed) => {
|
||||
const { translations, videos, video, ...entry } = seed;
|
||||
return {
|
||||
...entry,
|
||||
showPk: show.pk,
|
||||
slug: generateSlug(show.slug, seed),
|
||||
thumbnail: enqueueOptImage(imgQueue, {
|
||||
url: seed.thumbnail,
|
||||
column: entries.thumbnail,
|
||||
}),
|
||||
nextRefresh:
|
||||
entry.kind !== "extra"
|
||||
? guessNextRefresh(entry.airDate ?? new Date())
|
||||
: guessNextRefresh(new Date()),
|
||||
episodeNumber:
|
||||
entry.kind === "episode"
|
||||
? entry.episodeNumber
|
||||
: entry.kind === "special"
|
||||
? entry.number
|
||||
: undefined,
|
||||
};
|
||||
});
|
||||
const ret = await tx
|
||||
.insert(entries)
|
||||
.select(unnestValues(vals, entries))
|
||||
.onConflictDoUpdate({
|
||||
target: entries.slug,
|
||||
set: conflictUpdateAllExcept(entries, [
|
||||
"pk",
|
||||
"showPk",
|
||||
"id",
|
||||
"slug",
|
||||
"createdAt",
|
||||
]),
|
||||
})
|
||||
.returning({ pk: entries.pk, id: entries.id, slug: entries.slug });
|
||||
|
||||
const trans: EntryTransI[] = items.flatMap((seed, i) => {
|
||||
if (seed.kind === "extra") {
|
||||
return [
|
||||
{
|
||||
pk: ret[i].pk,
|
||||
// yeah we hardcode the language to extra because if we want to support
|
||||
// translations one day it won't be awkward
|
||||
language: "extra",
|
||||
name: seed.name,
|
||||
description: null,
|
||||
poster: undefined,
|
||||
},
|
||||
];
|
||||
}
|
||||
|
||||
return Object.entries(seed.translations).map(([lang, tr]) => ({
|
||||
// assumes ret is ordered like items.
|
||||
pk: ret[i].pk,
|
||||
language: lang,
|
||||
...tr,
|
||||
poster:
|
||||
seed.kind === "movie"
|
||||
? enqueueOptImage(imgQueue, {
|
||||
url: (tr as any).poster,
|
||||
column: entryTranslations.poster,
|
||||
})
|
||||
: undefined,
|
||||
}));
|
||||
});
|
||||
await flushImageQueue(tx, imgQueue, 0);
|
||||
await tx
|
||||
.insert(entryTranslations)
|
||||
.select(unnestValues(trans, entryTranslations))
|
||||
.onConflictDoUpdate({
|
||||
target: [entryTranslations.pk, entryTranslations.language],
|
||||
set: conflictUpdateAllExcept(entryTranslations, ["pk", "language"]),
|
||||
});
|
||||
|
||||
return ret;
|
||||
});
|
||||
|
||||
const vids = items.flatMap((seed, i) => {
|
||||
if (seed.kind === "extra") {
|
||||
return {
|
||||
videoId: seed.video,
|
||||
entryPk: retEntries[i].pk,
|
||||
entrySlug: retEntries[i].slug,
|
||||
needRendering: false,
|
||||
};
|
||||
}
|
||||
if (!seed.videos) return [];
|
||||
return seed.videos.map((x, j) => ({
|
||||
videoId: x,
|
||||
entryPk: retEntries[i].pk,
|
||||
entrySlug: retEntries[i].slug,
|
||||
// The first video should not have a rendering.
|
||||
needRendering: j !== 0 && seed.videos!.length > 1,
|
||||
}));
|
||||
});
|
||||
|
||||
if (vids.length === 0) {
|
||||
// we have not added videos but we need to update the `entriesCount`
|
||||
if (show.kind === "serie" && !onlyExtras)
|
||||
await updateAvailableCount(db, [show.pk], true);
|
||||
return retEntries.map((x) => ({ id: x.id, slug: x.slug, videos: [] }));
|
||||
}
|
||||
|
||||
const retVideos = await db.transaction(async (tx) => {
|
||||
const ret = await tx
|
||||
.insert(entryVideoJoin)
|
||||
.select(
|
||||
db
|
||||
.select({
|
||||
entryPk: sql<number>`vids."entryPk"`.as("entry"),
|
||||
videoPk: videos.pk,
|
||||
slug: computeVideoSlug(
|
||||
sql`vids."entrySlug"`,
|
||||
sql`vids."needRendering"`,
|
||||
),
|
||||
})
|
||||
.from(
|
||||
unnest(vids, "vids", {
|
||||
entryPk: "integer",
|
||||
entrySlug: "varchar(255)",
|
||||
needRendering: "boolean",
|
||||
videoId: "uuid",
|
||||
}),
|
||||
)
|
||||
.innerJoin(videos, eq(videos.id, sql`vids."videoId"`)),
|
||||
)
|
||||
.onConflictDoNothing()
|
||||
.returning({
|
||||
slug: entryVideoJoin.slug,
|
||||
entryPk: entryVideoJoin.entryPk,
|
||||
});
|
||||
|
||||
if (!onlyExtras)
|
||||
await updateAvailableCount(tx, [show.pk], show.kind === "serie");
|
||||
|
||||
await updateAvailableSince(tx, [...new Set(vids.map((x) => x.entryPk))]);
|
||||
return ret;
|
||||
});
|
||||
|
||||
return retEntries.map((entry) => ({
|
||||
id: entry.id,
|
||||
slug: entry.slug,
|
||||
videos: retVideos.filter((x) => x.entryPk === entry.pk),
|
||||
}));
|
||||
},
|
||||
);
|
||||
|
||||
export function computeVideoSlug(entrySlug: SQL | Column, needsRendering: SQL) {
|
||||
return sql<string>`
|
||||
concat(
|
||||
${entrySlug},
|
||||
case when ${videos.part} is not null then ('-p' || ${videos.part}) else '' end,
|
||||
case when ${videos.version} <> 1 then ('-v' || ${videos.version}) else '' end,
|
||||
case when ${needsRendering} then concat('-', ${videos.rendering}) else '' end
|
||||
)
|
||||
`.as("slug");
|
||||
}
|
||||
78
api/src/controllers/seed/insert/seasons.ts
Normal file
78
api/src/controllers/seed/insert/seasons.ts
Normal file
@@ -0,0 +1,78 @@
|
||||
import { db } from "~/db";
|
||||
import { seasons, seasonTranslations } from "~/db/schema";
|
||||
import { conflictUpdateAllExcept, unnestValues } from "~/db/utils";
|
||||
import type { SeedSeason } from "~/models/season";
|
||||
import { record } from "~/otel";
|
||||
import { enqueueOptImage, flushImageQueue, type ImageTask } from "../images";
|
||||
import { guessNextRefresh } from "../refresh";
|
||||
|
||||
type SeasonI = typeof seasons.$inferInsert;
|
||||
type SeasonTransI = typeof seasonTranslations.$inferInsert;
|
||||
|
||||
export const insertSeasons = record(
|
||||
"insertSeasons",
|
||||
async (show: { pk: number; slug: string }, items: SeedSeason[]) => {
|
||||
if (!items.length) return [];
|
||||
|
||||
return db.transaction(async (tx) => {
|
||||
const imgQueue: ImageTask[] = [];
|
||||
const vals: SeasonI[] = items.map((x) => {
|
||||
const { translations, ...season } = x;
|
||||
return {
|
||||
...season,
|
||||
showPk: show.pk,
|
||||
slug:
|
||||
season.seasonNumber === 0
|
||||
? `${show.slug}-specials`
|
||||
: `${show.slug}-s${season.seasonNumber}`,
|
||||
nextRefresh: guessNextRefresh(season.startAir ?? new Date()),
|
||||
};
|
||||
});
|
||||
const ret = await tx
|
||||
.insert(seasons)
|
||||
.select(unnestValues(vals, seasons))
|
||||
.onConflictDoUpdate({
|
||||
target: seasons.slug,
|
||||
set: conflictUpdateAllExcept(seasons, [
|
||||
"pk",
|
||||
"showPk",
|
||||
"id",
|
||||
"slug",
|
||||
"createdAt",
|
||||
]),
|
||||
})
|
||||
.returning({ pk: seasons.pk, id: seasons.id, slug: seasons.slug });
|
||||
|
||||
const trans: SeasonTransI[] = items.flatMap((seed, i) =>
|
||||
Object.entries(seed.translations).map(([lang, tr]) => ({
|
||||
// assumes ret is ordered like items.
|
||||
pk: ret[i].pk,
|
||||
language: lang,
|
||||
...tr,
|
||||
poster: enqueueOptImage(imgQueue, {
|
||||
url: tr.poster,
|
||||
column: seasonTranslations.poster,
|
||||
}),
|
||||
thumbnail: enqueueOptImage(imgQueue, {
|
||||
url: tr.thumbnail,
|
||||
column: seasonTranslations.thumbnail,
|
||||
}),
|
||||
banner: enqueueOptImage(imgQueue, {
|
||||
url: tr.banner,
|
||||
column: seasonTranslations.banner,
|
||||
}),
|
||||
})),
|
||||
);
|
||||
await flushImageQueue(tx, imgQueue, -10);
|
||||
await tx
|
||||
.insert(seasonTranslations)
|
||||
.select(unnestValues(trans, seasonTranslations))
|
||||
.onConflictDoUpdate({
|
||||
target: [seasonTranslations.pk, seasonTranslations.language],
|
||||
set: conflictUpdateAllExcept(seasonTranslations, ["pk", "language"]),
|
||||
});
|
||||
|
||||
return ret;
|
||||
});
|
||||
},
|
||||
);
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user