mirror of
https://github.com/mountain-loop/yaak.git
synced 2026-05-17 13:17:07 +02:00
Compare commits
976 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| ad3c2ed113 | |||
| 166bae6104 | |||
| b3e6a2b34f | |||
| 547f1c9139 | |||
| 4d7ded61f8 | |||
| c92472dbac | |||
| d347f2db77 | |||
| 80c1675331 | |||
| 23fba45fcb | |||
| 80777f712c | |||
| 6ffb0015c6 | |||
| 9d9b855c04 | |||
| e7cbcc7b20 | |||
| 20a5ab3666 | |||
| 311fda887f | |||
| 55e33df8d6 | |||
| 71c9c8ba8c | |||
| 11c2b9bb2c | |||
| 5cfd208c23 | |||
| 3a0b647ce4 | |||
| 8367835061 | |||
| 55276b968e | |||
| 9e04226097 | |||
| 51487d5412 | |||
| 0dccba4ab2 | |||
| 13183ae837 | |||
| f24fd13c45 | |||
| 972dffe959 | |||
| 9f7033ab06 | |||
| cd07123157 | |||
| b62901e295 | |||
| 96996f73d5 | |||
| 4782fd376b | |||
| 41dfa15feb | |||
| 47d4fffc20 | |||
| 994f314cff | |||
| 0f8f086e01 | |||
| 19280c3bbc | |||
| 3cd7c1ef2e | |||
| 6a5f61e84b | |||
| a444984aed | |||
| c0e253ef84 | |||
| 7910d1b0fc | |||
| d26d20180e | |||
| 54d9a78474 | |||
| 216c41d8cf | |||
| bf2c392380 | |||
| 1835fa3ba4 | |||
| d701381041 | |||
| 89c19858df | |||
| 01136921df | |||
| 17ab201b96 | |||
| 5d3182da4c | |||
| 293a91012f | |||
| a43f601b6a | |||
| 447932697d | |||
| 0c75c2289e | |||
| c97c9b599d | |||
| fc972b04f7 | |||
| e8410f70a1 | |||
| 70c63fc63c | |||
| c4e1353b51 | |||
| fd6959e868 | |||
| 854c19c1a1 | |||
| 9370b4879b | |||
| 0b2da8e7ae | |||
| 2e0982b999 | |||
| 2ec3be4374 | |||
| b1e6f52396 | |||
| 5ce928068c | |||
| 76b1e5b103 | |||
| 4a95128416 | |||
| cae6eb2b24 | |||
| cdcfb585cf | |||
| d4d56dfe1b | |||
| f6c491498b | |||
| e01cdd1dad | |||
| 9e41d366c1 | |||
| fee46de974 | |||
| fa14b7aaf8 | |||
| bb44bfca49 | |||
| 6fcb3948ce | |||
| f716291328 | |||
| 9f8eabe22b | |||
| 6d9e14784f | |||
| 1d5f3260e2 | |||
| 883fcdb6b8 | |||
| c9040a6e5f | |||
| 151450f55b | |||
| 5722880890 | |||
| d361a40903 | |||
| cd9e720835 | |||
| 50e2ab3a03 | |||
| dc5dfeb022 | |||
| 0b8a18edae | |||
| 0bb3f14b4c | |||
| c18d30b89f | |||
| 8f06a834c8 | |||
| bd948f9cd6 | |||
| d70254bcdc | |||
| fac5385d5d | |||
| e8bcc695bb | |||
| 88aeb0e530 | |||
| 92b1582232 | |||
| 196990c077 | |||
| c42b8cf538 | |||
| 085274c960 | |||
| 7ef187abf6 | |||
| 12eac34d95 | |||
| c29b3c6509 | |||
| 7faa423aba | |||
| 5b2162e48d | |||
| ee776143b2 | |||
| 7a18fb29e4 | |||
| 4485cad9e8 | |||
| 33763b6d2f | |||
| 641fe86cf7 | |||
| 65e7c804d7 | |||
| 23ec8bee8f | |||
| 8aeeaa2e09 | |||
| 57f01d249e | |||
| 6c5a914db6 | |||
| 155e51aa74 | |||
| 012a984456 | |||
| 25800202f2 | |||
| a058064f1f | |||
| 9f40804532 | |||
| 26cc467858 | |||
| be1cf7bf65 | |||
| ea4f104ca7 | |||
| 32a28a3170 | |||
| 6215914212 | |||
| a2dbd7f849 | |||
| 5bb9815f4b | |||
| 7cd8ac3b21 | |||
| 456d3aaf52 | |||
| 113743f7cf | |||
| 01a4d6f4ac | |||
| ff5cfe744e | |||
| 29c4b51f54 | |||
| 2f74bf8db8 | |||
| b30d784d06 | |||
| ac0adaf3d8 | |||
| c246d3a748 | |||
| ae40728c1e | |||
| 0430ec883b | |||
| eba6f33536 | |||
| dae2873376 | |||
| cb2f56d9a1 | |||
| 7d82aa70a4 | |||
| adea234987 | |||
| 37d0b487b8 | |||
| d507f8c99f | |||
| 60406ac83f | |||
| 8fe6f3a335 | |||
| 69e027c302 | |||
| 4232bdd298 | |||
| ef1c5da027 | |||
| e250326868 | |||
| 125f503cfa | |||
| 8f086425fe | |||
| ae2da73873 | |||
| 3cd6688ffb | |||
| 8538da8879 | |||
| b0e4ece278 | |||
| 5e058af03e | |||
| 5108bc92f3 | |||
| 3c5fdcb18d | |||
| 4672de4a47 | |||
| 239f6da141 | |||
| ec148d1736 | |||
| 392b549646 | |||
| 993d4dc65d | |||
| e326405f4f | |||
| a83e094f00 | |||
| e683a2cb2a | |||
| 1f231c2722 | |||
| 0fc2575ef6 | |||
| 44c718e6bc | |||
| 495df847ab | |||
| 5dbb9852f3 | |||
| 82d3304c38 | |||
| 5e2218fd64 | |||
| 5b12fad173 | |||
| 8d6f23eacb | |||
| 75a09859bc | |||
| dc47c4ceba | |||
| 8ae0290aed | |||
| f01d1e704b | |||
| 3f72996e64 | |||
| fe862517fb | |||
| b39335dc4f | |||
| 8f3bdb5039 | |||
| b47ec01f9c | |||
| 36728d1d1f | |||
| c3f0351445 | |||
| 9a5364187c | |||
| a9db14994f | |||
| 2383e8468f | |||
| a79d485b6a | |||
| 7eb931d689 | |||
| 995cd2aa7b | |||
| 1ce50e0c1b | |||
| bce3d26a1a | |||
| d9680ad0fa | |||
| e2e026e1ff | |||
| 16739d9a37 | |||
| 524a4f2275 | |||
| ba66883dc2 | |||
| 2caa735a2e | |||
| 90637fda6b | |||
| 2cef46b46a | |||
| 14b3abf76c | |||
| 8cd3961f87 | |||
| 5eb2e2b5a2 | |||
| 5dd897e042 | |||
| 9c77ec296d | |||
| 696e72323b | |||
| 3e8c01f436 | |||
| 80fc4dec09 | |||
| 671885fc8c | |||
| 002b61f0d7 | |||
| d32b462bd9 | |||
| 5c8b47288a | |||
| 8e662e6feb | |||
| 83aaeb94f6 | |||
| 8606940dee | |||
| 60e469a1c9 | |||
| 57d548743f | |||
| dab7ee2492 | |||
| 9360fd7e43 | |||
| 7b4bc53c0f | |||
| 0f7969d10a | |||
| 6b373b5985 | |||
| c0068a1561 | |||
| fad5e03f8b | |||
| a22fc68764 | |||
| 59a442e8c0 | |||
| 35e8155ecf | |||
| 8b9a5cb5fb | |||
| 29f9825f04 | |||
| ad8a6beacf | |||
| 194ac78814 | |||
| 0542f1ebea | |||
| 8de917ea5e | |||
| 0b494bbfbf | |||
| 7e74f71c79 | |||
| bd7fd676a5 | |||
| cb1c6a4d8c | |||
| b640f0c357 | |||
| 967590c7ff | |||
| 321d6ec9d7 | |||
| 79b4fd7829 | |||
| 52eb4d338f | |||
| 4b8b48e92f | |||
| e3f45b58e5 | |||
| a5f1922446 | |||
| 22e7b15a63 | |||
| c6bb2a73f8 | |||
| bde961f95d | |||
| c4867b3f68 | |||
| 1c36e9a2f0 | |||
| 1c82d8a738 | |||
| a2df591102 | |||
| c950ee0fb8 | |||
| 0ce5a9fcce | |||
| bd1970a805 | |||
| 3aaa4b1050 | |||
| 31d2426846 | |||
| 25c4e4edaf | |||
| 1a5bf53b02 | |||
| e2d1b62044 | |||
| 6186104d11 | |||
| f1e97eaea4 | |||
| bb0e58bf8b | |||
| dc802fa055 | |||
| 3c8e19367f | |||
| a89887eab8 | |||
| 7d3f0ad549 | |||
| 5608db1334 | |||
| 10443b3c02 | |||
| 7d272f3cd6 | |||
| d60a62ab24 | |||
| 2b0f73b7c5 | |||
| 0915ea8585 | |||
| ed9a0b8ac7 | |||
| 7437f39ed3 | |||
| 27f80cd97b | |||
| 04cf688a9b | |||
| 178af308ce | |||
| d40732a910 | |||
| d8a579b7b3 | |||
| bf8ef40708 | |||
| 41060d5d43 | |||
| ab6cef064c | |||
| 829d10d7b9 | |||
| 57e1f641a7 | |||
| 7df965e74b | |||
| 0e1153fdfd | |||
| 9797bc1830 | |||
| 9d00eb98d2 | |||
| 88f6e882c6 | |||
| 230a773909 | |||
| e6da1afa82 | |||
| a70d9e57be | |||
| 8afe0c0755 | |||
| e47c2513a8 | |||
| 276bcfceeb | |||
| 6fd1b35a50 | |||
| bc33244549 | |||
| 33c982b288 | |||
| 98493a1167 | |||
| a8c10f9601 | |||
| 1051f84bbf | |||
| eea137e677 | |||
| 27cf4e925f | |||
| 6b239c4e3f | |||
| 4c7ee5ef80 | |||
| 3ddb79899e | |||
| b14595a3e2 | |||
| 82c94369ae | |||
| 7e77d2e9a8 | |||
| ce5ce76b21 | |||
| 27d6b30cf9 | |||
| 9285dd5d70 | |||
| 977234808e | |||
| e1ccd327f5 | |||
| a0e3e71a4b | |||
| 2d4037da37 | |||
| d21608bb82 | |||
| f16239de73 | |||
| d00f34c240 | |||
| fd77437f59 | |||
| f9cd8d24a1 | |||
| c0a9f79834 | |||
| ca63c101a1 | |||
| dbd0b46ef2 | |||
| 89793ebe2f | |||
| e1ffc387ea | |||
| 1efd0852ef | |||
| 59d532ed4d | |||
| f034cda7cd | |||
| 5c1cf1e57d | |||
| 780960f5de | |||
| aada95e9da | |||
| 89b5003cce | |||
| 3559333461 | |||
| fbb6cab567 | |||
| 30fca29c6d | |||
| ec1e521b39 | |||
| a8998cd696 | |||
| df178baed6 | |||
| e2f75371e6 | |||
| 9f25ab39c6 | |||
| 937df6a024 | |||
| 7deb7182a8 | |||
| 82b14c56be | |||
| 58b98734c9 | |||
| c2f58f328c | |||
| 36eabe7528 | |||
| 8347093e8b | |||
| 75282cb43a | |||
| 3a253a758d | |||
| f2955c26c1 | |||
| e6c0317b37 | |||
| 0cfb218b07 | |||
| 8ef103fbde | |||
| ec5cdfb025 | |||
| 7f4d082c17 | |||
| e10011ef34 | |||
| 1eb6999c37 | |||
| 35596916bf | |||
| d61b22dd87 | |||
| 5565a9db9a | |||
| b803655306 | |||
| 20df2bf13a | |||
| e8fab85ce5 | |||
| ce730f3dbe | |||
| 2328973de5 | |||
| 37dea50c91 | |||
| 40dfc8b30a | |||
| 72971bb9ec | |||
| f835599502 | |||
| 0caa4f8099 | |||
| 71d3c9acd1 | |||
| 239ffa174a | |||
| eae79ab14b | |||
| ef7912615a | |||
| 7f20b67380 | |||
| 504337c178 | |||
| d6b4f06ac8 | |||
| 28cbf5474d | |||
| d797b84d4e | |||
| 720745857d | |||
| a74ea1aeda | |||
| 643f5e7f26 | |||
| a208b934e4 | |||
| 5892774082 | |||
| 13bfc1c3bd | |||
| 00289734c7 | |||
| 09c7c2cb91 | |||
| bbe62abd20 | |||
| cae9a4fd36 | |||
| e7ee4a8867 | |||
| b020574c88 | |||
| 192e1da5b6 | |||
| 0640079e59 | |||
| a9d99aa17f | |||
| b4667e1f88 | |||
| 7bc26fd448 | |||
| 94a9a5d5d5 | |||
| bcfa2c411f | |||
| 1e3d43dbae | |||
| c6b5e4d5df | |||
| 1293870e11 | |||
| 8309c19167 | |||
| 63a381c55a | |||
| d891f891b7 | |||
| 0b12a6b318 | |||
| 0144ab05a0 | |||
| 1f71d4372f | |||
| 5ed1ea07ef | |||
| 4d2b101278 | |||
| 1dfdadde98 | |||
| d19729869e | |||
| 5f782ad109 | |||
| 27dbdc9b5a | |||
| 4892863dd7 | |||
| dc077209cc | |||
| d8d5344d21 | |||
| d148a8384d | |||
| 6884e9428b | |||
| 25ebccfcd7 | |||
| 7adb0cbb50 | |||
| 50866abda4 | |||
| c83d904cf0 | |||
| 160447f8f6 | |||
| 184b13cc2a | |||
| 8fa965e055 | |||
| 1dd0b69079 | |||
| be8dd107e3 | |||
| 8f139f10ef | |||
| 8b0823984b | |||
| d82d2229d4 | |||
| 4be1bc17f3 | |||
| e6af0c6009 | |||
| e5d10bd72b | |||
| 9426885bb8 | |||
| 89e5d4f235 | |||
| eecb3fbc7f | |||
| 244f1319b4 | |||
| 6a2b76e760 | |||
| bc0278fce9 | |||
| 959841fb22 | |||
| fbc878dbe5 | |||
| 7d183c6580 | |||
| 0555420ad9 | |||
| ae25561c7e | |||
| 92e2b2b8f9 | |||
| 2a4a830fb7 | |||
| 0ad4c7cd7e | |||
| 41413d52ad | |||
| eabc1bd305 | |||
| 9c312e12c1 | |||
| 18ea9dda3d | |||
| 56d4212f68 | |||
| d932c19513 | |||
| b800f00b7e | |||
| e43af5234f | |||
| aa59d96e55 | |||
| 5be04ceea6 | |||
| da3392ac53 | |||
| a2c9c98b21 | |||
| 8298d6e031 | |||
| d6331022ad | |||
| 5e75d8c9a7 | |||
| 51944a212a | |||
| 49ed756479 | |||
| 1d207d5fbd | |||
| 6b1d15415d | |||
| df3bfaaab7 | |||
| ad0b8a8e7d | |||
| d5459229b9 | |||
| adbf596f0b | |||
| c740966394 | |||
| 7adab73af3 | |||
| c964f255d8 | |||
| a7ffed9716 | |||
| 488d66d248 | |||
| 93cb469cb8 | |||
| 03a2fc8ee5 | |||
| 2d72e5792e | |||
| 9bf9a87f12 | |||
| e2fca399e0 | |||
| e13fdddf98 | |||
| 890eea299d | |||
| 9beac00981 | |||
| 1a64d7d9e6 | |||
| bd5ae12f2e | |||
| dbaf1da3ce | |||
| a03c5df440 | |||
| 0776f6a2be | |||
| ac9d050d9e | |||
| b885c358a3 | |||
| 84d447973e | |||
| 019ec4de20 | |||
| 26189067cd | |||
| caf39071af | |||
| 08a1223482 | |||
| 24bd90745e | |||
| 7a72920e66 | |||
| 81a8276e2b | |||
| 8fb6f51555 | |||
| b0026aff66 | |||
| 3ced7f7c18 | |||
| 33f6995193 | |||
| 8af526682a | |||
| d0d4324957 | |||
| 2bcd0e0bbe | |||
| 1b99c7e10f | |||
| 2831bb61b8 | |||
| 320670de2a | |||
| 1f39a36f26 | |||
| 1f84ba716e | |||
| d034965d9c | |||
| 5eb30489e5 | |||
| 05458a0753 | |||
| 7975ef0699 | |||
| 5f810a1b4c | |||
| c4093e79cf | |||
| 956f8ed2ea | |||
| 7b32f76a1e | |||
| 0dd11bc051 | |||
| aa38df28af | |||
| 32962a6336 | |||
| b268b72a4a | |||
| eb0c90311b | |||
| 1070bf8e8f | |||
| 9bdb01987c | |||
| 3130fb948a | |||
| e46de9eebd | |||
| 4360355c8c | |||
| 3baaddba0b | |||
| e77c1c2a46 | |||
| 38422d59fd | |||
| c884cedfc2 | |||
| 91074a35d8 | |||
| 9a02b63a6b | |||
| 4470409a24 | |||
| 8a978420be | |||
| dfc01d51ca | |||
| 758154fa14 | |||
| ef23a85577 | |||
| e4533088ed | |||
| 4ffce4a534 | |||
| 6b77a62934 | |||
| f603867040 | |||
| b6eb7418aa | |||
| 39c97681cf | |||
| 2d0f0d8f6b | |||
| 209a767c91 | |||
| 71f2a724cb | |||
| 4b89b95738 | |||
| b535722acd | |||
| a9806a06a2 | |||
| 948e19b82f | |||
| cd841fa13a | |||
| 3ffcf91abd | |||
| 9fd84a3bfc | |||
| 627c451cd1 | |||
| e6ee89464a | |||
| 136e9f2738 | |||
| d97986e526 | |||
| 7661aa9819 | |||
| b7596f3f78 | |||
| 4e2231674c | |||
| d36d023a5c | |||
| 3d5a7ebe3d | |||
| 819384e952 | |||
| 2f34c5e821 | |||
| 0c89c154ee | |||
| 060dce7440 | |||
| 91707529bd | |||
| 22f182a8eb | |||
| 6ccc42dc3f | |||
| 655f5a8eed | |||
| cd06a72d6f | |||
| 0a5d71ecc2 | |||
| 9c214b619c | |||
| 6fddb727be | |||
| b5d3b9a803 | |||
| a74c8a94db | |||
| abc6d0ff1e | |||
| afdbcd0a38 | |||
| c31ae805a6 | |||
| 7c1afd7fe5 | |||
| ad470a3fd2 | |||
| 7755d06bba | |||
| 5aed4b79be | |||
| f0e3f29606 | |||
| abbcc525bf | |||
| ef8ade45b1 | |||
| 8919d598c2 | |||
| e21e42f5fe | |||
| 658aed8a29 | |||
| a666f7d216 | |||
| 62429df469 | |||
| 7aed699c3f | |||
| a14db0ab74 | |||
| 7b67770dc7 | |||
| 7766d8439b | |||
| fac0683a71 | |||
| 79e04967f5 | |||
| 47eb8947f5 | |||
| 959c55315c | |||
| b392f0c00f | |||
| c8e674d015 | |||
| 90fbb81e1d | |||
| 21e58ca644 | |||
| cfb0aa55ea | |||
| 9e0c021481 | |||
| 4acca8dd06 | |||
| 88eea09428 | |||
| 90d2743267 | |||
| 89945532a0 | |||
| 671860e053 | |||
| a87ca6af47 | |||
| b59ea4991c | |||
| b6fd59219f | |||
| 38ce7650c1 | |||
| 2b21e28096 | |||
| 3206651248 | |||
| ba8aa0e218 | |||
| 975a001635 | |||
| 30e7f7ccfe | |||
| cca8d97d63 | |||
| 455e6c3520 | |||
| d05ee3ec16 | |||
| b1b5d08e89 | |||
| 6202e59daa | |||
| c4a8603b81 | |||
| 5d15d1565c | |||
| 045ff558f8 | |||
| 504ed583cc | |||
| 15087f2d5a | |||
| eb1cd1c14b | |||
| 0918d86654 | |||
| d0e2220df7 | |||
| ccb04f0b45 | |||
| 54b6e1c7c3 | |||
| 7c8acdc956 | |||
| 3973ae15be | |||
| 86dadf4f5e | |||
| dc4cb4be74 | |||
| 2a29c4b551 | |||
| 2f64f45aba | |||
| 2f998ddfb6 | |||
| 93369a779d | |||
| 74e28123a8 | |||
| fef7db8710 | |||
| cb5d7626ac | |||
| e74f9f33c0 | |||
| 0d27c17e28 | |||
| f0b6d32639 | |||
| 9ebd506056 | |||
| a5a91d2444 | |||
| 4435a66ece | |||
| 874a1079c3 | |||
| 1dc239d243 | |||
| 73a04276c0 | |||
| 9955064484 | |||
| 7975b528ec | |||
| 7d9fbda975 | |||
| fce06747e3 | |||
| db0cca54a7 | |||
| 4424caecc5 | |||
| b866dcd566 | |||
| 9e4e6435ab | |||
| 41b10ff442 | |||
| 79f3307104 | |||
| 026629cd6d | |||
| cf570a8f88 | |||
| 4a64384468 | |||
| a9065c3380 | |||
| e5e5548562 | |||
| 44cf2f670f | |||
| d04d91d6dd | |||
| 3eb25b1507 | |||
| a95cae5610 | |||
| 9cc6e62f28 | |||
| 24117f7c8d | |||
| 7245e6e593 | |||
| 4a5b1f4da3 | |||
| c1ac67cc31 | |||
| 4085361b7e | |||
| 8b4227dbff | |||
| 3f7ed9e177 | |||
| f9f1ba9e24 | |||
| 29309500a6 | |||
| 6b07fe105f | |||
| 90b03a0b97 | |||
| d54a468006 | |||
| 7e98b6d853 | |||
| 8069094201 | |||
| b28dc01e6b | |||
| 6bc1f9f494 | |||
| e85dd32005 | |||
| efc4e3bf6c | |||
| 768a13ff4d | |||
| a8d73f74f4 | |||
| 4dddfc0cc5 | |||
| 4163bebe3b | |||
| ad13744d14 | |||
| 9f9b3a5b21 | |||
| 63e68baeb1 | |||
| 4382ca6582 | |||
| 99f2f4c211 | |||
| 6b23379e5a | |||
| 4deda36e8f | |||
| 0ce7831cfb | |||
| 4e9005e240 | |||
| 9147252e5b | |||
| b6b549ca18 | |||
| 85c25fb71e | |||
| 50637ba9fd | |||
| bfe55dd55a | |||
| 1a2bb3d12e | |||
| 452a0c3ed5 | |||
| b594a4690f | |||
| 7d2ba43463 | |||
| 107db42c33 | |||
| dbacb9fc8d | |||
| 1fa3499ca6 | |||
| 62f3198d27 | |||
| 529550934b | |||
| ca3b22a881 | |||
| 0ecf2d9123 | |||
| af9bb7138b | |||
| 6cbfa74f97 | |||
| 2845fb8d35 | |||
| fbe2660a57 | |||
| 1519282ac6 | |||
| 5d8d8dca70 | |||
| 0254e2c31d | |||
| 368b494d62 | |||
| 00d2213d05 | |||
| b04602bcb9 | |||
| 80bfbd503a | |||
| bfa186aebb | |||
| 818595e961 | |||
| b5e9852f8d | |||
| ff3734d65a | |||
| 4aa771ba29 | |||
| 5848c381fa | |||
| 03b35beae4 | |||
| 49856bb6f7 | |||
| 0cb56f1a85 | |||
| 4a0d698776 | |||
| a4ebdb5736 | |||
| 6a5ecc2880 | |||
| 7a5bd92442 | |||
| 63c1111608 | |||
| 5704fb560a | |||
| 33dc3b719d | |||
| d3329b4628 | |||
| 42e2c9f96f | |||
| 3e8a10757f | |||
| 8028d82fd0 | |||
| 4ad9feba68 | |||
| ef469be7a9 | |||
| 14cd73d75a | |||
| fbe6039845 | |||
| f3fbd070dd | |||
| 7c2611a5a7 | |||
| ae949f4616 | |||
| 89da434c0e | |||
| 4a98d1d655 | |||
| bb41f0e4fe | |||
| d2e0717d91 | |||
| 7912204fcb | |||
| 83e41ad618 | |||
| dd7e46c2cc | |||
| fb7424714a | |||
| 47481b711e | |||
| 0f86c3a731 | |||
| b91d1b8b3c | |||
| cd5ae6691c | |||
| 0f58986b4c | |||
| af9755c513 | |||
| 56ce25f953 | |||
| ed70c15ee9 | |||
| d88ae99425 | |||
| cf7ef55b7d | |||
| 2f12424f8d | |||
| 96aacec4fc | |||
| 7e57bb98a8 | |||
| 298f5c5a99 | |||
| bf44ea7864 | |||
| 9abdc45e93 | |||
| 0d82cc7574 | |||
| 402b2a551f | |||
| 700c589ae2 | |||
| 8929d736d9 | |||
| 8c65fce357 | |||
| b81f1e9e6b | |||
| 44d083d773 | |||
| 2b308282d4 | |||
| c7738743c5 | |||
| abc60667c6 | |||
| 53162e8bca | |||
| 6b95574e3d | |||
| c9d62ae961 | |||
| a70019927d | |||
| 01cd7f951a | |||
| 50f92bcfab | |||
| 362d9f8e59 | |||
| 0b1cf53942 | |||
| a4c769b33c | |||
| 74a1cb61c1 | |||
| 268545c728 | |||
| 184bbb01c5 | |||
| 66fa7ac419 | |||
| a80f3d997e | |||
| efa7c24c9f | |||
| 91de21c7ad | |||
| 1e9ba57ef0 | |||
| 464389b248 | |||
| 107eb72eda | |||
| ee7bf838f4 | |||
| f63bcd94d1 | |||
| 16d5cb6ade | |||
| 63decdef8b | |||
| e54e88f46d | |||
| b6f53d059e | |||
| 9e1771c5ec | |||
| 8306bc2198 | |||
| 3810fb7d51 | |||
| 5b4984113e | |||
| baf9efe246 | |||
| f4a3109a31 | |||
| 241f2f39ec | |||
| d9b40dca83 | |||
| cb3f053057 | |||
| c4ab045e57 | |||
| d9b38efd97 | |||
| 5981588c95 | |||
| 388bef59b8 | |||
| 3d8de61c1c | |||
| 91b818f98d | |||
| 3a7f0898f9 | |||
| c2f6de875a | |||
| 0647001807 | |||
| 4181d87792 | |||
| 58cf0a2015 | |||
| d80c3d305b | |||
| 4d64a2bc2f | |||
| 5c54beaaa9 | |||
| eee98f32b2 | |||
| 0949de66bf | |||
| 5a6acb24d9 | |||
| 2e5cab62c7 | |||
| 903db5fffd | |||
| e3faf32708 | |||
| 97926ddc03 | |||
| e891804051 | |||
| a2982f8b77 | |||
| 321941baab | |||
| e2e25dc30b | |||
| 1170ca4789 | |||
| d159f62138 | |||
| 25005eef1b | |||
| b17824c88d | |||
| 00f4a008f8 | |||
| 3e2bc67b59 | |||
| efe072c7c4 | |||
| 59f1d11e40 | |||
| 5f947ac983 | |||
| aa66f957f2 | |||
| cf5f69271f | |||
| c6653af782 | |||
| fa1f33a2ac | |||
| 9f479882ad | |||
| 41db316489 | |||
| 50f0f5885e | |||
| a609f09d50 | |||
| 43f2aa3068 | |||
| a094e13bd5 | |||
| eb076afbe4 | |||
| 7b41488a38 | |||
| ca12d48352 | |||
| 0331d3b2b0 | |||
| 4d4814583c | |||
| da3e158516 | |||
| 7b9d6baff0 | |||
| 550f1b7c6f | |||
| 74e8ee1786 | |||
| 55d3ea01b6 | |||
| 4cfe51cbb2 | |||
| 1f5ac60523 | |||
| 26bf4f2abd | |||
| 54671fff79 | |||
| 378309d763 | |||
| e7d4bba8b3 | |||
| fe3de0bc98 | |||
| f3e38d7b71 | |||
| eafa3b2de9 | |||
| d8cc075bd0 | |||
| bdb877a936 | |||
| 5c96e83a22 | |||
| 43abb57f77 | |||
| 9c6d821978 | |||
| 7e9babf515 | |||
| ee36baf432 | |||
| 0bf57dcab7 | |||
| e647d23adc | |||
| d1b5b9c371 | |||
| 92ec514442 | |||
| 107466dd58 | |||
| 4246260ce6 | |||
| 936787d327 | |||
| f976397283 | |||
| 657c6ad9a9 | |||
| ede07c3b0e | |||
| 9326e8dcce | |||
| 8ff2adf833 | |||
| 5e387b513a | |||
| dca316c0d5 | |||
| db2d786d50 | |||
| c0d7962142 | |||
| 5d14354ca9 | |||
| 347dace6de | |||
| d952c75e3c | |||
| abc3745be1 | |||
| 1382d7c523 | |||
| 3de0edf0f9 | |||
| 5513d39152 | |||
| 1a9547d1d2 | |||
| 26cc64d3a0 | |||
| e465b33365 | |||
| 957739ba5e | |||
| 59967374c5 | |||
| 43bc346a2b | |||
| 5fbd3f67cd | |||
| e352343d62 | |||
| baee0f0c6f | |||
| fcc5eead88 | |||
| 29d1f687d1 | |||
| f568266c7f | |||
| a1e42b8ddb | |||
| e6389b1153 | |||
| f0835acb33 | |||
| 35b04b219f | |||
| 01b62e936a | |||
| 09d16a03ef | |||
| bb61602fd2 | |||
| f30b78ea1f | |||
| 6ee652ca75 | |||
| 67d8bbc154 | |||
| b852484559 | |||
| 0b077e5e88 | |||
| 381d957db2 | |||
| f8f77abc12 | |||
| 0b0484c610 | |||
| 2b769088af | |||
| 856d13c603 | |||
| 76e398b8a1 | |||
| 24a7d85be0 | |||
| 989271f653 | |||
| 3fd8cd5713 | |||
| 43f1c7caf6 | |||
| bd91ac88a3 | |||
| fbcbf2e5a5 | |||
| 31eb03da0d | |||
| a4dbfed712 | |||
| 784cb53ec6 | |||
| 43c799bd60 |
+34
-22
@@ -1,25 +1,37 @@
|
|||||||
module.exports = {
|
module.exports = {
|
||||||
extends: [
|
extends: [
|
||||||
'eslint:recommended',
|
"eslint:recommended",
|
||||||
'plugin:react/recommended',
|
"plugin:react/recommended",
|
||||||
'plugin:import/recommended',
|
"plugin:react-hooks/recommended",
|
||||||
'plugin:jsx-a11y/recommended',
|
"plugin:import/recommended",
|
||||||
'plugin:@typescript-eslint/recommended',
|
"plugin:jsx-a11y/recommended",
|
||||||
'eslint-config-prettier',
|
"plugin:@typescript-eslint/recommended",
|
||||||
],
|
"eslint-config-prettier"
|
||||||
ignorePatterns: ['src-tauri/**/*'],
|
],
|
||||||
settings: {
|
parser: "@typescript-eslint/parser",
|
||||||
react: {
|
parserOptions: {
|
||||||
version: 'detect',
|
project: ["./tsconfig.json"]
|
||||||
},
|
},
|
||||||
'import/resolver': {
|
ignorePatterns: ["scripts/**/*", "plugin-runtime/**/*", "src-tauri/**/*", "plugins/**/*"],
|
||||||
node: {
|
settings: {
|
||||||
paths: ['src-web'],
|
react: {
|
||||||
extensions: ['.js', '.jsx', '.ts', '.tsx'],
|
version: "detect"
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
rules: {
|
|
||||||
"react/react-in-jsx-scope": "off",
|
|
||||||
},
|
},
|
||||||
|
"import/resolver": {
|
||||||
|
node: {
|
||||||
|
paths: ["src-web"],
|
||||||
|
extensions: [".ts", ".tsx"]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
rules: {
|
||||||
|
"jsx-a11y/no-autofocus": "off",
|
||||||
|
"react/react-in-jsx-scope": "off",
|
||||||
|
"import/no-unresolved": "off",
|
||||||
|
"@typescript-eslint/consistent-type-imports": ["error", {
|
||||||
|
prefer: "type-imports",
|
||||||
|
disallowTypeAnnotations: true,
|
||||||
|
fixStyle: "separate-type-imports"
|
||||||
|
}]
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -0,0 +1,18 @@
|
|||||||
|
on:
|
||||||
|
pull_request:
|
||||||
|
branches: [develop]
|
||||||
|
|
||||||
|
name: CI (JS)
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
test:
|
||||||
|
name: Lint/Test
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v4
|
||||||
|
- uses: actions/setup-node@v4
|
||||||
|
with:
|
||||||
|
node-version: 20
|
||||||
|
- run: npm ci
|
||||||
|
- run: npm run lint
|
||||||
|
- run: npm test
|
||||||
@@ -0,0 +1,36 @@
|
|||||||
|
on:
|
||||||
|
pull_request:
|
||||||
|
branches: [develop]
|
||||||
|
paths:
|
||||||
|
- src-tauri/**
|
||||||
|
- .github/workflows/**
|
||||||
|
|
||||||
|
name: CI (Rust)
|
||||||
|
|
||||||
|
defaults:
|
||||||
|
run:
|
||||||
|
working-directory: src-tauri
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
test:
|
||||||
|
name: Check/Test
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v4
|
||||||
|
- run: |
|
||||||
|
sudo apt-get update
|
||||||
|
sudo apt-get install -y libwebkit2gtk-4.1-dev
|
||||||
|
- uses: dtolnay/rust-toolchain@stable
|
||||||
|
- uses: actions/cache@v3
|
||||||
|
continue-on-error: false
|
||||||
|
with:
|
||||||
|
path: |
|
||||||
|
~/.cargo/bin/
|
||||||
|
~/.cargo/registry/index/
|
||||||
|
~/.cargo/registry/cache/
|
||||||
|
~/.cargo/git/db/
|
||||||
|
target/
|
||||||
|
key: ${{ runner.os }}-cargo-${{ hashFiles('**/Cargo.lock') }}
|
||||||
|
restore-keys: ${{ runner.os }}-cargo-
|
||||||
|
- run: cargo check --all
|
||||||
|
- run: cargo test --all
|
||||||
@@ -0,0 +1,120 @@
|
|||||||
|
name: Generate Artifacts
|
||||||
|
on:
|
||||||
|
push:
|
||||||
|
tags: [ v* ]
|
||||||
|
|
||||||
|
env:
|
||||||
|
YAAK_PLUGINS_DIR: checkout/plugins
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
build-artifacts:
|
||||||
|
permissions:
|
||||||
|
contents: write
|
||||||
|
|
||||||
|
name: Build
|
||||||
|
strategy:
|
||||||
|
fail-fast: false
|
||||||
|
matrix:
|
||||||
|
include:
|
||||||
|
- platform: 'macos-latest' # for Arm-based macs (M1 and above).
|
||||||
|
args: '--target aarch64-apple-darwin'
|
||||||
|
yaak_arch: 'arm64'
|
||||||
|
- platform: 'macos-latest' # for Intel-based macs.
|
||||||
|
args: '--target x86_64-apple-darwin'
|
||||||
|
yaak_arch: 'x64'
|
||||||
|
- platform: 'ubuntu-22.04' # for Tauri v1, you could replace this with ubuntu-20.04.
|
||||||
|
args: ''
|
||||||
|
yaak_arch: 'x64'
|
||||||
|
- platform: 'windows-latest'
|
||||||
|
args: ''
|
||||||
|
yaak_arch: 'x64'
|
||||||
|
runs-on: ${{ matrix.platform }}
|
||||||
|
steps:
|
||||||
|
- name: Checkout yaakapp/app
|
||||||
|
uses: actions/checkout@v4
|
||||||
|
|
||||||
|
- name: Setup Node
|
||||||
|
uses: actions/setup-node@v4
|
||||||
|
with:
|
||||||
|
node-version: 20
|
||||||
|
|
||||||
|
- uses: actions/setup-go@v5
|
||||||
|
with:
|
||||||
|
go-version: '1.22'
|
||||||
|
|
||||||
|
- name: install Rust stable
|
||||||
|
uses: dtolnay/rust-toolchain@stable
|
||||||
|
with:
|
||||||
|
# Those targets are only used on macos runners so it's in an `if` to slightly speed up windows and linux builds.
|
||||||
|
targets: ${{ matrix.platform == 'macos-latest' && 'aarch64-apple-darwin,x86_64-apple-darwin' || '' }}
|
||||||
|
|
||||||
|
- uses: actions/cache@v3
|
||||||
|
continue-on-error: false
|
||||||
|
with:
|
||||||
|
path: |
|
||||||
|
~/.cargo/bin/
|
||||||
|
~/.cargo/registry/index/
|
||||||
|
~/.cargo/registry/cache/
|
||||||
|
~/.cargo/git/db/
|
||||||
|
target/
|
||||||
|
key: ${{ runner.os }}-cargo-${{ hashFiles('**/Cargo.lock') }}
|
||||||
|
restore-keys: ${{ runner.os }}-cargo-
|
||||||
|
|
||||||
|
- name: install dependencies (ubuntu only)
|
||||||
|
if: matrix.platform == 'ubuntu-22.04' # This must match the platform value defined above.
|
||||||
|
run: |
|
||||||
|
sudo apt-get update
|
||||||
|
sudo apt-get install -y libwebkit2gtk-4.1-dev libappindicator3-dev librsvg2-dev patchelf
|
||||||
|
|
||||||
|
- name: Install Node dependencies
|
||||||
|
run: |
|
||||||
|
npm ci
|
||||||
|
|
||||||
|
- name: Install plugin-runtime Node dependencies
|
||||||
|
working-directory: plugin-runtime
|
||||||
|
run: |
|
||||||
|
npm ci
|
||||||
|
|
||||||
|
- name: Install Protoc for plugin-runtime
|
||||||
|
uses: arduino/setup-protoc@v3
|
||||||
|
with:
|
||||||
|
repo-token: ${{ secrets.GITHUB_TOKEN }}
|
||||||
|
|
||||||
|
- name: Install yaak CLI
|
||||||
|
run: go install github.com/yaakapp/yaakcli@latest
|
||||||
|
|
||||||
|
- name: Run lint
|
||||||
|
run: npm run lint
|
||||||
|
|
||||||
|
- name: Checkout yaakapp/plugins
|
||||||
|
uses: actions/checkout@v4
|
||||||
|
with:
|
||||||
|
repository: yaakapp/plugins
|
||||||
|
path: ${{ env.YAAK_PLUGINS_DIR }}
|
||||||
|
|
||||||
|
- name: Set version
|
||||||
|
run: npm run replace-version
|
||||||
|
env:
|
||||||
|
YAAK_VERSION: ${{ github.ref_name }}
|
||||||
|
|
||||||
|
- uses: tauri-apps/tauri-action@v0
|
||||||
|
env:
|
||||||
|
YAAK_PLUGINS_DIR: ${{ env.YAAK_PLUGINS_DIR }}
|
||||||
|
YAAK_TARGET_ARCH: ${{ matrix.yaak_arch }}
|
||||||
|
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||||
|
TAURI_SIGNING_PRIVATE_KEY: ${{ secrets.TAURI_PRIVATE_KEY }}
|
||||||
|
TAURI_SIGNING_PRIVATE_KEY_PASSWORD: ${{ secrets.TAURI_KEY_PASSWORD }}
|
||||||
|
ENABLE_CODE_SIGNING: ${{ secrets.APPLE_CERTIFICATE }}
|
||||||
|
APPLE_CERTIFICATE: ${{ secrets.APPLE_CERTIFICATE }}
|
||||||
|
APPLE_CERTIFICATE_PASSWORD: ${{ secrets.APPLE_CERTIFICATE_PASSWORD }}
|
||||||
|
APPLE_SIGNING_IDENTITY: ${{ secrets.APPLE_SIGNING_IDENTITY }}
|
||||||
|
APPLE_ID: ${{ secrets.APPLE_ID }}
|
||||||
|
APPLE_TEAM_ID: ${{ secrets.APPLE_TEAM_ID }}
|
||||||
|
APPLE_PASSWORD: ${{ secrets.APPLE_PASSWORD }}
|
||||||
|
with:
|
||||||
|
tagName: 'v__VERSION__'
|
||||||
|
releaseName: 'Release __VERSION__'
|
||||||
|
releaseBody: 'https://yaak.app/changelog/__VERSION__'
|
||||||
|
releaseDraft: true
|
||||||
|
prerelease: false
|
||||||
|
args: ${{ matrix.args }}
|
||||||
+8
-1
@@ -22,5 +22,12 @@ dist-ssr
|
|||||||
*.njsproj
|
*.njsproj
|
||||||
*.sln
|
*.sln
|
||||||
*.sw?
|
*.sw?
|
||||||
|
.eslintcache
|
||||||
|
|
||||||
.rsw
|
*.sqlite
|
||||||
|
*.sqlite-*
|
||||||
|
|
||||||
|
.cargo
|
||||||
|
|
||||||
|
.tmp
|
||||||
|
tmp
|
||||||
|
|||||||
@@ -0,0 +1 @@
|
|||||||
|
_
|
||||||
Executable
+4
@@ -0,0 +1,4 @@
|
|||||||
|
#!/bin/sh
|
||||||
|
. "$(dirname "$0")/_/husky.sh"
|
||||||
|
|
||||||
|
npx lint-staged
|
||||||
@@ -1,3 +1,4 @@
|
|||||||
node_modules/
|
node_modules/
|
||||||
dist/
|
dist/
|
||||||
|
out/
|
||||||
.prettierrc.cjs
|
.prettierrc.cjs
|
||||||
|
|||||||
@@ -0,0 +1,13 @@
|
|||||||
|
<component name="ProjectRunConfigurationManager">
|
||||||
|
<configuration default="false" name="Dev Desktop" type="js.build_tools.npm">
|
||||||
|
<package-json value="$PROJECT_DIR$/package.json" />
|
||||||
|
<command value="run" />
|
||||||
|
<scripts>
|
||||||
|
<script value="start" />
|
||||||
|
</scripts>
|
||||||
|
<node-interpreter value="project" />
|
||||||
|
<envs>
|
||||||
|
</envs>
|
||||||
|
<method v="2" />
|
||||||
|
</configuration>
|
||||||
|
</component>
|
||||||
@@ -0,0 +1,5 @@
|
|||||||
|
{
|
||||||
|
"name": "yaak-dev",
|
||||||
|
"adapter": "sqlite3",
|
||||||
|
"filename": "src-tauri/db.sqlite"
|
||||||
|
}
|
||||||
@@ -0,0 +1,13 @@
|
|||||||
|
.PHONY: sqlx-prepare, dev, migrate, build
|
||||||
|
|
||||||
|
sqlx-prepare:
|
||||||
|
cd src-tauri && cargo sqlx prepare --database-url 'sqlite://db.sqlite'
|
||||||
|
|
||||||
|
dev:
|
||||||
|
npm run tauri-dev
|
||||||
|
|
||||||
|
migrate:
|
||||||
|
cd src-tauri && cargo sqlx migrate run --database-url 'sqlite://db.sqlite?mode=rw'
|
||||||
|
|
||||||
|
build:
|
||||||
|
./node_modules/.bin/tauri build
|
||||||
@@ -1,3 +1,16 @@
|
|||||||
# Tauri REST Client
|
# Yaak Network Toolkit
|
||||||
|
|
||||||
It's a REST client, yo.
|
The most fun you'll ever have working with APIs.
|
||||||
|
|
||||||
|
## Common Commands
|
||||||
|
|
||||||
|
```sh
|
||||||
|
# Start dev app
|
||||||
|
npm run tauri-dev
|
||||||
|
|
||||||
|
# Migration commands
|
||||||
|
cd src-tauri
|
||||||
|
cargo sqlx migrate add ${MIGRATION_NAME}
|
||||||
|
cargo sqlx migrate run --database-url 'sqlite://db.sqlite?mode=rw'
|
||||||
|
cargo sqlx prepare --database-url 'sqlite://db.sqlite'
|
||||||
|
```
|
||||||
|
|||||||
Binary file not shown.
Binary file not shown.
|
After Width: | Height: | Size: 31 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 356 KiB |
Binary file not shown.
+27
-11
@@ -1,15 +1,31 @@
|
|||||||
<!DOCTYPE html>
|
<!DOCTYPE html>
|
||||||
<html lang="en">
|
<html lang="en">
|
||||||
<head>
|
<head>
|
||||||
<meta charset="UTF-8" />
|
<meta charset="UTF-8"/>
|
||||||
<link rel="icon" type="image/svg+xml" href="/vite.svg" />
|
<meta name="viewport" content="width=device-width, initial-scale=1.0"/>
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
<title>Yaak App</title>
|
||||||
<title>Tauri + React + TS</title>
|
<script src="http://localhost:8097"></script>
|
||||||
</head>
|
|
||||||
|
|
||||||
<body>
|
<!-- Certain elements like webview (and maybe <select>?) will use background
|
||||||
<div id="root"></div>
|
color depending on document background color-->
|
||||||
<div id="radix-portal"></div>
|
<style>
|
||||||
<script type="module" src="/src-web/main.tsx"></script>
|
html, body {
|
||||||
</body>
|
background-color: white;
|
||||||
|
}
|
||||||
|
|
||||||
|
@media (prefers-color-scheme: dark) {
|
||||||
|
html, body {
|
||||||
|
background-color: #1b1a29;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
</head>
|
||||||
|
|
||||||
|
<body class="text-base">
|
||||||
|
<div id="root"></div>
|
||||||
|
<div id="cm-portal" class="cm-portal"></div>
|
||||||
|
<div id="react-portal"></div>
|
||||||
|
<div id="radix-portal" class="cm-portal"></div>
|
||||||
|
<script type="module" src="/src-web/main.tsx"></script>
|
||||||
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
|||||||
Generated
+8511
-6759
File diff suppressed because it is too large
Load Diff
+95
-32
@@ -1,51 +1,114 @@
|
|||||||
{
|
{
|
||||||
"name": "tauri-app",
|
"name": "yaak-app",
|
||||||
"private": true,
|
"private": true,
|
||||||
"version": "0.0.0",
|
"version": "0.0.0",
|
||||||
"type": "module",
|
"type": "module",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"build": "rsw build && tsc && vite build",
|
"start": "npm run tauri-dev:desktop",
|
||||||
"dev": "vite",
|
"tauri-dev:desktop": "tauri dev --no-watch --config ./src-tauri/tauri-dev.conf.json",
|
||||||
"lint": "eslint . --ext .ts,.tsx",
|
"tauri-dev:ios": "tauri ios dev --force-ip-prompt --config ./src-tauri/tauri-dev.conf.json",
|
||||||
"preview": "vite preview",
|
"tauri-build": "tauri build",
|
||||||
"tauri-dev": "concurrently -n app,rsw \"tauri dev\" \"rsw watch\""
|
"tauri": "tauri",
|
||||||
|
"dev:js": "vite dev",
|
||||||
|
"lint": "tsc && eslint . --ext .ts,.tsx",
|
||||||
|
"build:icon:release": "tauri icon design/icon.png --output ./src-tauri/icons/release",
|
||||||
|
"build:icon:dev": "tauri icon design/icon-dev.png --output ./src-tauri/icons/dev",
|
||||||
|
"build": "run-p build:*",
|
||||||
|
"build:js": "vite build",
|
||||||
|
"build:vendor-protoc": "node scripts/vendor-protoc.cjs",
|
||||||
|
"build:vendor-plugins": "node scripts/vendor-plugins.cjs",
|
||||||
|
"build:vendor-node": "node scripts/vendor-node.cjs",
|
||||||
|
"build:plugin-runtime": "npm run --prefix plugin-runtime build",
|
||||||
|
"prepare": "husky install",
|
||||||
|
"replace-version": "node scripts/replace-version.cjs"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@codemirror/lang-html": "^6.4.2",
|
"@codemirror/commands": "^6.2.1",
|
||||||
"@codemirror/lang-javascript": "^6.1.4",
|
"@codemirror/lang-javascript": "^6.2.2",
|
||||||
"@codemirror/lang-json": "^6.0.1",
|
"@codemirror/lang-json": "^6.0.1",
|
||||||
"@radix-ui/react-dropdown-menu": "^2.0.2",
|
"@codemirror/lang-xml": "^6.0.2",
|
||||||
"@radix-ui/react-icons": "^1.2.0",
|
"@codemirror/language": "^6.6.0",
|
||||||
"@radix-ui/react-popover": "1.0.3",
|
"@codemirror/search": "^6.2.3",
|
||||||
"@tauri-apps/api": "^1.2.0",
|
"@lezer/generator": "^1.2.2",
|
||||||
"@typescript-eslint/eslint-plugin": "^5.52.0",
|
"@lezer/highlight": "^1.1.3",
|
||||||
"@typescript-eslint/parser": "^5.52.0",
|
"@lezer/lr": "^1.3.3",
|
||||||
|
"@react-hook/resize-observer": "^1.2.6",
|
||||||
|
"@tailwindcss/container-queries": "^0.1.0",
|
||||||
|
"@tanstack/react-query": "^5.45.1",
|
||||||
|
"@tauri-apps/api": ">=2.0.0-beta.0",
|
||||||
|
"@tauri-apps/plugin-clipboard-manager": "^2.1.0-beta.1",
|
||||||
|
"@tauri-apps/plugin-dialog": ">=2.0.0-beta.0",
|
||||||
|
"@tauri-apps/plugin-fs": ">=2.0.0-beta.0",
|
||||||
|
"@tauri-apps/plugin-os": ">=2.0.0-beta.0",
|
||||||
|
"@tauri-apps/plugin-shell": ">=2.0.0-beta.0",
|
||||||
|
"buffer": "^6.0.3",
|
||||||
"classnames": "^2.3.2",
|
"classnames": "^2.3.2",
|
||||||
|
"cm6-graphql": "^0.0.9",
|
||||||
"codemirror": "^6.0.1",
|
"codemirror": "^6.0.1",
|
||||||
|
"codemirror-json-schema": "^0.6.1",
|
||||||
|
"date-fns": "^3.3.1",
|
||||||
|
"fast-fuzzy": "^1.12.0",
|
||||||
|
"focus-trap-react": "^10.1.1",
|
||||||
|
"format-graphql": "^1.4.0",
|
||||||
|
"framer-motion": "^9.0.4",
|
||||||
|
"lucide-react": "^0.309.0",
|
||||||
|
"mime": "^4.0.1",
|
||||||
|
"papaparse": "^5.4.1",
|
||||||
|
"parse-color": "^1.0.0",
|
||||||
|
"react": "^18.2.0",
|
||||||
|
"react-dnd": "^16.0.1",
|
||||||
|
"react-dnd-html5-backend": "^16.0.1",
|
||||||
|
"react-dom": "^18.2.0",
|
||||||
|
"react-helmet-async": "^1.3.0",
|
||||||
|
"react-pdf": "^9.0.0",
|
||||||
|
"react-router-dom": "^6.8.1",
|
||||||
|
"react-use": "^17.4.0",
|
||||||
|
"slugify": "^1.6.6",
|
||||||
|
"tauri-plugin-log-api": "github:tauri-apps/tauri-plugin-log#v2",
|
||||||
|
"uuid": "^9.0.0",
|
||||||
|
"xml-formatter": "^3.6.2"
|
||||||
|
},
|
||||||
|
"devDependencies": {
|
||||||
|
"@tailwindcss/nesting": "^0.0.0-insiders.565cd3e",
|
||||||
|
"@tanstack/react-query-devtools": "^5.45.1",
|
||||||
|
"@tauri-apps/cli": ">=2.0.0-beta.0",
|
||||||
|
"@types/node": "^18.7.10",
|
||||||
|
"@types/papaparse": "^5.3.7",
|
||||||
|
"@types/parse-color": "^1.0.1",
|
||||||
|
"@types/parse-json": "^4.0.0",
|
||||||
|
"@types/react": "^18.0.31",
|
||||||
|
"@types/react-dom": "^18.0.11",
|
||||||
|
"@types/uuid": "^9.0.1",
|
||||||
|
"@typescript-eslint/eslint-plugin": "^7.0.2",
|
||||||
|
"@typescript-eslint/parser": "^7.0.2",
|
||||||
|
"@vitejs/plugin-react": "^4.2.1",
|
||||||
|
"autoprefixer": "^10.4.13",
|
||||||
"eslint": "^8.34.0",
|
"eslint": "^8.34.0",
|
||||||
"eslint-config-prettier": "^8.6.0",
|
"eslint-config-prettier": "^8.6.0",
|
||||||
"eslint-plugin-import": "^2.27.5",
|
"eslint-plugin-import": "^2.27.5",
|
||||||
"eslint-plugin-jsx-a11y": "^6.7.1",
|
"eslint-plugin-jsx-a11y": "^6.7.1",
|
||||||
"eslint-plugin-react": "^7.32.2",
|
"eslint-plugin-react": "^7.32.2",
|
||||||
"framer-motion": "^9.0.4",
|
"eslint-plugin-react-hooks": "^4.6.0",
|
||||||
"prettier": "^2.8.4",
|
"husky": "^8.0.3",
|
||||||
"react": "^18.2.0",
|
"internal-ip": "^8.0.0",
|
||||||
"react-dom": "^18.2.0",
|
"lint-staged": "^15.0.2",
|
||||||
"react-helmet-async": "^1.3.0"
|
"npm-run-all": "^4.1.5",
|
||||||
},
|
|
||||||
"devDependencies": {
|
|
||||||
"@tauri-apps/cli": "^1.2.2",
|
|
||||||
"@types/node": "^18.7.10",
|
|
||||||
"@types/react": "^18.0.15",
|
|
||||||
"@types/react-dom": "^18.0.6",
|
|
||||||
"@vitejs/plugin-react": "^3.0.0",
|
|
||||||
"autoprefixer": "^10.4.13",
|
|
||||||
"concurrently": "^7.6.0",
|
|
||||||
"postcss": "^8.4.21",
|
"postcss": "^8.4.21",
|
||||||
|
"postcss-nesting": "^11.2.1",
|
||||||
|
"prettier": "^2.8.4",
|
||||||
|
"react-devtools": "^4.27.2",
|
||||||
"tailwindcss": "^3.2.7",
|
"tailwindcss": "^3.2.7",
|
||||||
"typescript": "^4.6.4",
|
"typescript": "^5.4.5",
|
||||||
"vite": "^4.0.0",
|
"vite": "^5.0.0",
|
||||||
"vite-plugin-rsw": "^2.0.11",
|
"vite-plugin-static-copy": "^1.0.5",
|
||||||
"vite-plugin-top-level-await": "^1.2.4"
|
"decompress": "^4.2.1",
|
||||||
|
"nodejs-file-downloader": "^4.13.0",
|
||||||
|
"rimraf": "^5.0.7",
|
||||||
|
"vite-plugin-svgr": "^4.2.0",
|
||||||
|
"vite-plugin-top-level-await": "^1.4.1"
|
||||||
|
},
|
||||||
|
"lint-staged": {
|
||||||
|
"*.{ts,tsx}": "eslint --cache --fix",
|
||||||
|
"*.{js,css,md}": "prettier --write"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,3 @@
|
|||||||
|
build
|
||||||
|
node_modules
|
||||||
|
*.blob
|
||||||
@@ -0,0 +1,5 @@
|
|||||||
|
{
|
||||||
|
"watch": ["src"],
|
||||||
|
"ext": "ts",
|
||||||
|
"exec": "node -r ts-node/register ./src/index.ts"
|
||||||
|
}
|
||||||
Generated
+3004
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,23 @@
|
|||||||
|
{
|
||||||
|
"name": "@yaak/plugin-runtime",
|
||||||
|
"scripts": {
|
||||||
|
"dev": "nodemon",
|
||||||
|
"build": "run-p build:*",
|
||||||
|
"build:main": "esbuild src/index.ts --bundle --platform=node --outfile=build/index.cjs",
|
||||||
|
"build:worker": "esbuild src/index.worker.ts --bundle --platform=node --outfile=build/index.worker.cjs",
|
||||||
|
"build:proto": "grpc_tools_node_protoc --ts_proto_out=src/gen --ts_proto_opt=outputServices=nice-grpc,outputServices=generic-definitions,useExactTypes=false --proto_path=../proto ../proto/plugins/*.proto"
|
||||||
|
},
|
||||||
|
"dependencies": {
|
||||||
|
"long": "^5.2.3",
|
||||||
|
"nice-grpc": "^2.1.9",
|
||||||
|
"protobufjs": "^7.3.2"
|
||||||
|
},
|
||||||
|
"devDependencies": {
|
||||||
|
"grpc-tools": "^1.12.4",
|
||||||
|
"nodemon": "^3.1.4",
|
||||||
|
"npm-run-all": "^4.1.5",
|
||||||
|
"ts-node": "^10.9.2",
|
||||||
|
"ts-proto": "^1.180.0",
|
||||||
|
"typescript": "^5.5.2"
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,92 @@
|
|||||||
|
import { randomUUID } from 'node:crypto';
|
||||||
|
import path from 'node:path';
|
||||||
|
import { Worker } from 'node:worker_threads';
|
||||||
|
import { PluginInfo } from './plugins';
|
||||||
|
|
||||||
|
export interface ParentToWorkerEvent<T = any> {
|
||||||
|
callbackId: string;
|
||||||
|
name: string;
|
||||||
|
payload: T;
|
||||||
|
}
|
||||||
|
|
||||||
|
export type WorkerToParentSuccessEvent<T> = {
|
||||||
|
callbackId: string;
|
||||||
|
payload: T;
|
||||||
|
};
|
||||||
|
|
||||||
|
export type WorkerToParentErrorEvent = {
|
||||||
|
callbackId: string;
|
||||||
|
error: string;
|
||||||
|
};
|
||||||
|
|
||||||
|
export type WorkerToParentEvent<T = any> = WorkerToParentErrorEvent | WorkerToParentSuccessEvent<T>;
|
||||||
|
|
||||||
|
export class PluginHandle {
|
||||||
|
readonly pluginDir: string;
|
||||||
|
readonly #worker: Worker;
|
||||||
|
|
||||||
|
constructor(pluginDir: string) {
|
||||||
|
this.pluginDir = pluginDir;
|
||||||
|
|
||||||
|
const workerPath = path.join(__dirname, 'index.worker.cjs');
|
||||||
|
this.#worker = new Worker(workerPath, {
|
||||||
|
workerData: {
|
||||||
|
pluginDir: this.pluginDir,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
this.#worker.on('error', this.#handleError.bind(this));
|
||||||
|
this.#worker.on('exit', this.#handleExit.bind(this));
|
||||||
|
}
|
||||||
|
|
||||||
|
async getInfo(): Promise<PluginInfo> {
|
||||||
|
return this.#callPlugin('info', null);
|
||||||
|
}
|
||||||
|
|
||||||
|
async runResponseFilter({ filter, body }: { filter: string; body: string }): Promise<string> {
|
||||||
|
return this.#callPlugin('run-filter', { filter, body });
|
||||||
|
}
|
||||||
|
|
||||||
|
async runExport(request: any): Promise<string> {
|
||||||
|
return this.#callPlugin('run-export', request);
|
||||||
|
}
|
||||||
|
|
||||||
|
async runImport(data: string): Promise<string> {
|
||||||
|
const result = await this.#callPlugin('run-import', data);
|
||||||
|
|
||||||
|
// Plugin returns object, but we convert to string
|
||||||
|
return JSON.stringify(result, null, 2);
|
||||||
|
}
|
||||||
|
|
||||||
|
#callPlugin<P, R>(name: string, payload: P): Promise<R> {
|
||||||
|
const callbackId = `cb_${randomUUID().replaceAll('-', '')}`;
|
||||||
|
return new Promise((resolve, reject) => {
|
||||||
|
const cb = (e: WorkerToParentEvent<R>) => {
|
||||||
|
if (e.callbackId !== callbackId) return;
|
||||||
|
|
||||||
|
if ('error' in e) {
|
||||||
|
reject(e.error);
|
||||||
|
} else {
|
||||||
|
resolve(e.payload as R);
|
||||||
|
}
|
||||||
|
|
||||||
|
this.#worker.removeListener('message', cb);
|
||||||
|
};
|
||||||
|
|
||||||
|
this.#worker.addListener('message', cb);
|
||||||
|
this.#worker.postMessage({ callbackId, name, payload });
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
async #handleError(err: Error) {
|
||||||
|
console.error('Plugin errored', this.pluginDir, err);
|
||||||
|
}
|
||||||
|
|
||||||
|
async #handleExit(code: number) {
|
||||||
|
if (code === 0) {
|
||||||
|
console.log('Plugin exited successfully', this.pluginDir);
|
||||||
|
} else {
|
||||||
|
console.log('Plugin exited with error', code, this.pluginDir);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,44 @@
|
|||||||
|
import { PluginHandle } from './PluginHandle';
|
||||||
|
import { loadPlugins, PluginInfo } from './plugins';
|
||||||
|
|
||||||
|
export class PluginManager {
|
||||||
|
#handles: PluginHandle[] | null = null;
|
||||||
|
static #instance: PluginManager | null = null;
|
||||||
|
|
||||||
|
public static instance(): PluginManager {
|
||||||
|
if (PluginManager.#instance == null) {
|
||||||
|
PluginManager.#instance = new PluginManager();
|
||||||
|
PluginManager.#instance.plugins(); // Trigger workers to boot, as it takes a few seconds
|
||||||
|
}
|
||||||
|
return PluginManager.#instance;
|
||||||
|
}
|
||||||
|
|
||||||
|
async plugins(): Promise<PluginHandle[]> {
|
||||||
|
this.#handles = this.#handles ?? loadPlugins();
|
||||||
|
return this.#handles;
|
||||||
|
}
|
||||||
|
|
||||||
|
async #pluginsWithInfo(): Promise<{ plugin: PluginHandle; info: PluginInfo }[]> {
|
||||||
|
const plugins = await this.plugins();
|
||||||
|
return Promise.all(plugins.map(async (plugin) => ({ plugin, info: await plugin.getInfo() })));
|
||||||
|
}
|
||||||
|
|
||||||
|
async pluginsWith(capability: PluginInfo['capabilities'][0]): Promise<PluginHandle[]> {
|
||||||
|
return (await this.#pluginsWithInfo())
|
||||||
|
.filter((v) => v.info.capabilities.includes(capability))
|
||||||
|
.map((v) => v.plugin);
|
||||||
|
}
|
||||||
|
|
||||||
|
async plugin(name: string): Promise<PluginHandle | null> {
|
||||||
|
return (await this.#pluginsWithInfo()).find((v) => v.info.name === name)?.plugin ?? null;
|
||||||
|
}
|
||||||
|
|
||||||
|
async pluginOrThrow(name: string): Promise<PluginHandle> {
|
||||||
|
const plugin = await this.plugin(name);
|
||||||
|
if (plugin == null) {
|
||||||
|
throw new Error(`Failed to find plugin by ${name}`);
|
||||||
|
}
|
||||||
|
|
||||||
|
return plugin;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,432 @@
|
|||||||
|
// Code generated by protoc-gen-ts_proto. DO NOT EDIT.
|
||||||
|
// versions:
|
||||||
|
// protoc-gen-ts_proto v1.180.0
|
||||||
|
// protoc v3.19.1
|
||||||
|
// source: plugins/runtime.proto
|
||||||
|
|
||||||
|
/* eslint-disable */
|
||||||
|
import { type CallContext, type CallOptions } from "nice-grpc-common";
|
||||||
|
import * as _m0 from "protobufjs/minimal";
|
||||||
|
|
||||||
|
export const protobufPackage = "yaak.plugins.runtime";
|
||||||
|
|
||||||
|
export interface PluginInfo {
|
||||||
|
plugin: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface HookResponse {
|
||||||
|
info: PluginInfo | undefined;
|
||||||
|
data: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface HookImportRequest {
|
||||||
|
data: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface HookResponseFilterRequest {
|
||||||
|
filter: string;
|
||||||
|
body: string;
|
||||||
|
contentType: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface HookExportRequest {
|
||||||
|
request: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
function createBasePluginInfo(): PluginInfo {
|
||||||
|
return { plugin: "" };
|
||||||
|
}
|
||||||
|
|
||||||
|
export const PluginInfo = {
|
||||||
|
encode(message: PluginInfo, writer: _m0.Writer = _m0.Writer.create()): _m0.Writer {
|
||||||
|
if (message.plugin !== "") {
|
||||||
|
writer.uint32(10).string(message.plugin);
|
||||||
|
}
|
||||||
|
return writer;
|
||||||
|
},
|
||||||
|
|
||||||
|
decode(input: _m0.Reader | Uint8Array, length?: number): PluginInfo {
|
||||||
|
const reader = input instanceof _m0.Reader ? input : _m0.Reader.create(input);
|
||||||
|
let end = length === undefined ? reader.len : reader.pos + length;
|
||||||
|
const message = createBasePluginInfo();
|
||||||
|
while (reader.pos < end) {
|
||||||
|
const tag = reader.uint32();
|
||||||
|
switch (tag >>> 3) {
|
||||||
|
case 1:
|
||||||
|
if (tag !== 10) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
message.plugin = reader.string();
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if ((tag & 7) === 4 || tag === 0) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
reader.skipType(tag & 7);
|
||||||
|
}
|
||||||
|
return message;
|
||||||
|
},
|
||||||
|
|
||||||
|
fromJSON(object: any): PluginInfo {
|
||||||
|
return { plugin: isSet(object.plugin) ? globalThis.String(object.plugin) : "" };
|
||||||
|
},
|
||||||
|
|
||||||
|
toJSON(message: PluginInfo): unknown {
|
||||||
|
const obj: any = {};
|
||||||
|
if (message.plugin !== "") {
|
||||||
|
obj.plugin = message.plugin;
|
||||||
|
}
|
||||||
|
return obj;
|
||||||
|
},
|
||||||
|
|
||||||
|
create(base?: DeepPartial<PluginInfo>): PluginInfo {
|
||||||
|
return PluginInfo.fromPartial(base ?? {});
|
||||||
|
},
|
||||||
|
fromPartial(object: DeepPartial<PluginInfo>): PluginInfo {
|
||||||
|
const message = createBasePluginInfo();
|
||||||
|
message.plugin = object.plugin ?? "";
|
||||||
|
return message;
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
function createBaseHookResponse(): HookResponse {
|
||||||
|
return { info: undefined, data: "" };
|
||||||
|
}
|
||||||
|
|
||||||
|
export const HookResponse = {
|
||||||
|
encode(message: HookResponse, writer: _m0.Writer = _m0.Writer.create()): _m0.Writer {
|
||||||
|
if (message.info !== undefined) {
|
||||||
|
PluginInfo.encode(message.info, writer.uint32(10).fork()).ldelim();
|
||||||
|
}
|
||||||
|
if (message.data !== "") {
|
||||||
|
writer.uint32(18).string(message.data);
|
||||||
|
}
|
||||||
|
return writer;
|
||||||
|
},
|
||||||
|
|
||||||
|
decode(input: _m0.Reader | Uint8Array, length?: number): HookResponse {
|
||||||
|
const reader = input instanceof _m0.Reader ? input : _m0.Reader.create(input);
|
||||||
|
let end = length === undefined ? reader.len : reader.pos + length;
|
||||||
|
const message = createBaseHookResponse();
|
||||||
|
while (reader.pos < end) {
|
||||||
|
const tag = reader.uint32();
|
||||||
|
switch (tag >>> 3) {
|
||||||
|
case 1:
|
||||||
|
if (tag !== 10) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
message.info = PluginInfo.decode(reader, reader.uint32());
|
||||||
|
continue;
|
||||||
|
case 2:
|
||||||
|
if (tag !== 18) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
message.data = reader.string();
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if ((tag & 7) === 4 || tag === 0) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
reader.skipType(tag & 7);
|
||||||
|
}
|
||||||
|
return message;
|
||||||
|
},
|
||||||
|
|
||||||
|
fromJSON(object: any): HookResponse {
|
||||||
|
return {
|
||||||
|
info: isSet(object.info) ? PluginInfo.fromJSON(object.info) : undefined,
|
||||||
|
data: isSet(object.data) ? globalThis.String(object.data) : "",
|
||||||
|
};
|
||||||
|
},
|
||||||
|
|
||||||
|
toJSON(message: HookResponse): unknown {
|
||||||
|
const obj: any = {};
|
||||||
|
if (message.info !== undefined) {
|
||||||
|
obj.info = PluginInfo.toJSON(message.info);
|
||||||
|
}
|
||||||
|
if (message.data !== "") {
|
||||||
|
obj.data = message.data;
|
||||||
|
}
|
||||||
|
return obj;
|
||||||
|
},
|
||||||
|
|
||||||
|
create(base?: DeepPartial<HookResponse>): HookResponse {
|
||||||
|
return HookResponse.fromPartial(base ?? {});
|
||||||
|
},
|
||||||
|
fromPartial(object: DeepPartial<HookResponse>): HookResponse {
|
||||||
|
const message = createBaseHookResponse();
|
||||||
|
message.info = (object.info !== undefined && object.info !== null)
|
||||||
|
? PluginInfo.fromPartial(object.info)
|
||||||
|
: undefined;
|
||||||
|
message.data = object.data ?? "";
|
||||||
|
return message;
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
function createBaseHookImportRequest(): HookImportRequest {
|
||||||
|
return { data: "" };
|
||||||
|
}
|
||||||
|
|
||||||
|
export const HookImportRequest = {
|
||||||
|
encode(message: HookImportRequest, writer: _m0.Writer = _m0.Writer.create()): _m0.Writer {
|
||||||
|
if (message.data !== "") {
|
||||||
|
writer.uint32(10).string(message.data);
|
||||||
|
}
|
||||||
|
return writer;
|
||||||
|
},
|
||||||
|
|
||||||
|
decode(input: _m0.Reader | Uint8Array, length?: number): HookImportRequest {
|
||||||
|
const reader = input instanceof _m0.Reader ? input : _m0.Reader.create(input);
|
||||||
|
let end = length === undefined ? reader.len : reader.pos + length;
|
||||||
|
const message = createBaseHookImportRequest();
|
||||||
|
while (reader.pos < end) {
|
||||||
|
const tag = reader.uint32();
|
||||||
|
switch (tag >>> 3) {
|
||||||
|
case 1:
|
||||||
|
if (tag !== 10) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
message.data = reader.string();
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if ((tag & 7) === 4 || tag === 0) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
reader.skipType(tag & 7);
|
||||||
|
}
|
||||||
|
return message;
|
||||||
|
},
|
||||||
|
|
||||||
|
fromJSON(object: any): HookImportRequest {
|
||||||
|
return { data: isSet(object.data) ? globalThis.String(object.data) : "" };
|
||||||
|
},
|
||||||
|
|
||||||
|
toJSON(message: HookImportRequest): unknown {
|
||||||
|
const obj: any = {};
|
||||||
|
if (message.data !== "") {
|
||||||
|
obj.data = message.data;
|
||||||
|
}
|
||||||
|
return obj;
|
||||||
|
},
|
||||||
|
|
||||||
|
create(base?: DeepPartial<HookImportRequest>): HookImportRequest {
|
||||||
|
return HookImportRequest.fromPartial(base ?? {});
|
||||||
|
},
|
||||||
|
fromPartial(object: DeepPartial<HookImportRequest>): HookImportRequest {
|
||||||
|
const message = createBaseHookImportRequest();
|
||||||
|
message.data = object.data ?? "";
|
||||||
|
return message;
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
function createBaseHookResponseFilterRequest(): HookResponseFilterRequest {
|
||||||
|
return { filter: "", body: "", contentType: "" };
|
||||||
|
}
|
||||||
|
|
||||||
|
export const HookResponseFilterRequest = {
|
||||||
|
encode(message: HookResponseFilterRequest, writer: _m0.Writer = _m0.Writer.create()): _m0.Writer {
|
||||||
|
if (message.filter !== "") {
|
||||||
|
writer.uint32(10).string(message.filter);
|
||||||
|
}
|
||||||
|
if (message.body !== "") {
|
||||||
|
writer.uint32(18).string(message.body);
|
||||||
|
}
|
||||||
|
if (message.contentType !== "") {
|
||||||
|
writer.uint32(26).string(message.contentType);
|
||||||
|
}
|
||||||
|
return writer;
|
||||||
|
},
|
||||||
|
|
||||||
|
decode(input: _m0.Reader | Uint8Array, length?: number): HookResponseFilterRequest {
|
||||||
|
const reader = input instanceof _m0.Reader ? input : _m0.Reader.create(input);
|
||||||
|
let end = length === undefined ? reader.len : reader.pos + length;
|
||||||
|
const message = createBaseHookResponseFilterRequest();
|
||||||
|
while (reader.pos < end) {
|
||||||
|
const tag = reader.uint32();
|
||||||
|
switch (tag >>> 3) {
|
||||||
|
case 1:
|
||||||
|
if (tag !== 10) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
message.filter = reader.string();
|
||||||
|
continue;
|
||||||
|
case 2:
|
||||||
|
if (tag !== 18) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
message.body = reader.string();
|
||||||
|
continue;
|
||||||
|
case 3:
|
||||||
|
if (tag !== 26) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
message.contentType = reader.string();
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if ((tag & 7) === 4 || tag === 0) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
reader.skipType(tag & 7);
|
||||||
|
}
|
||||||
|
return message;
|
||||||
|
},
|
||||||
|
|
||||||
|
fromJSON(object: any): HookResponseFilterRequest {
|
||||||
|
return {
|
||||||
|
filter: isSet(object.filter) ? globalThis.String(object.filter) : "",
|
||||||
|
body: isSet(object.body) ? globalThis.String(object.body) : "",
|
||||||
|
contentType: isSet(object.contentType) ? globalThis.String(object.contentType) : "",
|
||||||
|
};
|
||||||
|
},
|
||||||
|
|
||||||
|
toJSON(message: HookResponseFilterRequest): unknown {
|
||||||
|
const obj: any = {};
|
||||||
|
if (message.filter !== "") {
|
||||||
|
obj.filter = message.filter;
|
||||||
|
}
|
||||||
|
if (message.body !== "") {
|
||||||
|
obj.body = message.body;
|
||||||
|
}
|
||||||
|
if (message.contentType !== "") {
|
||||||
|
obj.contentType = message.contentType;
|
||||||
|
}
|
||||||
|
return obj;
|
||||||
|
},
|
||||||
|
|
||||||
|
create(base?: DeepPartial<HookResponseFilterRequest>): HookResponseFilterRequest {
|
||||||
|
return HookResponseFilterRequest.fromPartial(base ?? {});
|
||||||
|
},
|
||||||
|
fromPartial(object: DeepPartial<HookResponseFilterRequest>): HookResponseFilterRequest {
|
||||||
|
const message = createBaseHookResponseFilterRequest();
|
||||||
|
message.filter = object.filter ?? "";
|
||||||
|
message.body = object.body ?? "";
|
||||||
|
message.contentType = object.contentType ?? "";
|
||||||
|
return message;
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
function createBaseHookExportRequest(): HookExportRequest {
|
||||||
|
return { request: "" };
|
||||||
|
}
|
||||||
|
|
||||||
|
export const HookExportRequest = {
|
||||||
|
encode(message: HookExportRequest, writer: _m0.Writer = _m0.Writer.create()): _m0.Writer {
|
||||||
|
if (message.request !== "") {
|
||||||
|
writer.uint32(10).string(message.request);
|
||||||
|
}
|
||||||
|
return writer;
|
||||||
|
},
|
||||||
|
|
||||||
|
decode(input: _m0.Reader | Uint8Array, length?: number): HookExportRequest {
|
||||||
|
const reader = input instanceof _m0.Reader ? input : _m0.Reader.create(input);
|
||||||
|
let end = length === undefined ? reader.len : reader.pos + length;
|
||||||
|
const message = createBaseHookExportRequest();
|
||||||
|
while (reader.pos < end) {
|
||||||
|
const tag = reader.uint32();
|
||||||
|
switch (tag >>> 3) {
|
||||||
|
case 1:
|
||||||
|
if (tag !== 10) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
message.request = reader.string();
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if ((tag & 7) === 4 || tag === 0) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
reader.skipType(tag & 7);
|
||||||
|
}
|
||||||
|
return message;
|
||||||
|
},
|
||||||
|
|
||||||
|
fromJSON(object: any): HookExportRequest {
|
||||||
|
return { request: isSet(object.request) ? globalThis.String(object.request) : "" };
|
||||||
|
},
|
||||||
|
|
||||||
|
toJSON(message: HookExportRequest): unknown {
|
||||||
|
const obj: any = {};
|
||||||
|
if (message.request !== "") {
|
||||||
|
obj.request = message.request;
|
||||||
|
}
|
||||||
|
return obj;
|
||||||
|
},
|
||||||
|
|
||||||
|
create(base?: DeepPartial<HookExportRequest>): HookExportRequest {
|
||||||
|
return HookExportRequest.fromPartial(base ?? {});
|
||||||
|
},
|
||||||
|
fromPartial(object: DeepPartial<HookExportRequest>): HookExportRequest {
|
||||||
|
const message = createBaseHookExportRequest();
|
||||||
|
message.request = object.request ?? "";
|
||||||
|
return message;
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
export type PluginRuntimeDefinition = typeof PluginRuntimeDefinition;
|
||||||
|
export const PluginRuntimeDefinition = {
|
||||||
|
name: "PluginRuntime",
|
||||||
|
fullName: "yaak.plugins.runtime.PluginRuntime",
|
||||||
|
methods: {
|
||||||
|
hookImport: {
|
||||||
|
name: "hookImport",
|
||||||
|
requestType: HookImportRequest,
|
||||||
|
requestStream: false,
|
||||||
|
responseType: HookResponse,
|
||||||
|
responseStream: false,
|
||||||
|
options: {},
|
||||||
|
},
|
||||||
|
hookExport: {
|
||||||
|
name: "hookExport",
|
||||||
|
requestType: HookExportRequest,
|
||||||
|
requestStream: false,
|
||||||
|
responseType: HookResponse,
|
||||||
|
responseStream: false,
|
||||||
|
options: {},
|
||||||
|
},
|
||||||
|
hookResponseFilter: {
|
||||||
|
name: "hookResponseFilter",
|
||||||
|
requestType: HookResponseFilterRequest,
|
||||||
|
requestStream: false,
|
||||||
|
responseType: HookResponse,
|
||||||
|
responseStream: false,
|
||||||
|
options: {},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
} as const;
|
||||||
|
|
||||||
|
export interface PluginRuntimeServiceImplementation<CallContextExt = {}> {
|
||||||
|
hookImport(request: HookImportRequest, context: CallContext & CallContextExt): Promise<DeepPartial<HookResponse>>;
|
||||||
|
hookExport(request: HookExportRequest, context: CallContext & CallContextExt): Promise<DeepPartial<HookResponse>>;
|
||||||
|
hookResponseFilter(
|
||||||
|
request: HookResponseFilterRequest,
|
||||||
|
context: CallContext & CallContextExt,
|
||||||
|
): Promise<DeepPartial<HookResponse>>;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface PluginRuntimeClient<CallOptionsExt = {}> {
|
||||||
|
hookImport(request: DeepPartial<HookImportRequest>, options?: CallOptions & CallOptionsExt): Promise<HookResponse>;
|
||||||
|
hookExport(request: DeepPartial<HookExportRequest>, options?: CallOptions & CallOptionsExt): Promise<HookResponse>;
|
||||||
|
hookResponseFilter(
|
||||||
|
request: DeepPartial<HookResponseFilterRequest>,
|
||||||
|
options?: CallOptions & CallOptionsExt,
|
||||||
|
): Promise<HookResponse>;
|
||||||
|
}
|
||||||
|
|
||||||
|
type Builtin = Date | Function | Uint8Array | string | number | boolean | undefined;
|
||||||
|
|
||||||
|
export type DeepPartial<T> = T extends Builtin ? T
|
||||||
|
: T extends globalThis.Array<infer U> ? globalThis.Array<DeepPartial<U>>
|
||||||
|
: T extends ReadonlyArray<infer U> ? ReadonlyArray<DeepPartial<U>>
|
||||||
|
: T extends {} ? { [K in keyof T]?: DeepPartial<T[K]> }
|
||||||
|
: Partial<T>;
|
||||||
|
|
||||||
|
function isSet(value: any): boolean {
|
||||||
|
return value !== null && value !== undefined;
|
||||||
|
}
|
||||||
@@ -0,0 +1,87 @@
|
|||||||
|
import { isAbortError } from 'abort-controller-x';
|
||||||
|
import { createServer, ServerError, ServerMiddlewareCall, Status } from 'nice-grpc';
|
||||||
|
import { CallContext } from 'nice-grpc-common';
|
||||||
|
import * as fs from 'node:fs';
|
||||||
|
import {
|
||||||
|
DeepPartial,
|
||||||
|
HookExportRequest,
|
||||||
|
HookImportRequest,
|
||||||
|
HookResponse,
|
||||||
|
HookResponseFilterRequest,
|
||||||
|
PluginRuntimeDefinition,
|
||||||
|
PluginRuntimeServiceImplementation,
|
||||||
|
} from './gen/plugins/runtime';
|
||||||
|
import { PluginManager } from './PluginManager';
|
||||||
|
|
||||||
|
class PluginRuntimeService implements PluginRuntimeServiceImplementation {
|
||||||
|
#manager: PluginManager;
|
||||||
|
|
||||||
|
constructor() {
|
||||||
|
this.#manager = PluginManager.instance();
|
||||||
|
}
|
||||||
|
|
||||||
|
async hookExport(request: HookExportRequest): Promise<DeepPartial<HookResponse>> {
|
||||||
|
const plugin = await this.#manager.pluginOrThrow('exporter-curl');
|
||||||
|
const data = await plugin.runExport(JSON.parse(request.request));
|
||||||
|
const info = { plugin: (await plugin.getInfo()).name };
|
||||||
|
return { info, data };
|
||||||
|
}
|
||||||
|
|
||||||
|
async hookImport(request: HookImportRequest): Promise<DeepPartial<HookResponse>> {
|
||||||
|
const plugins = await this.#manager.pluginsWith('import');
|
||||||
|
for (const p of plugins) {
|
||||||
|
const data = await p.runImport(request.data);
|
||||||
|
if (data != null && data !== 'null') {
|
||||||
|
const info = { plugin: (await p.getInfo()).name };
|
||||||
|
return { info, data };
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
throw new ServerError(Status.UNKNOWN, 'No importers found for data');
|
||||||
|
}
|
||||||
|
|
||||||
|
async hookResponseFilter(request: HookResponseFilterRequest): Promise<DeepPartial<HookResponse>> {
|
||||||
|
const pluginName = request.contentType.includes('json') ? 'filter-jsonpath' : 'filter-xpath';
|
||||||
|
const plugin = await this.#manager.pluginOrThrow(pluginName);
|
||||||
|
const data = await plugin.runResponseFilter(request);
|
||||||
|
const info = { plugin: (await plugin.getInfo()).name };
|
||||||
|
return { info, data };
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
let server = createServer();
|
||||||
|
|
||||||
|
async function* errorHandlingMiddleware<Request, Response>(
|
||||||
|
call: ServerMiddlewareCall<Request, Response>,
|
||||||
|
context: CallContext,
|
||||||
|
) {
|
||||||
|
try {
|
||||||
|
return yield* call.next(call.request, context);
|
||||||
|
} catch (error: unknown) {
|
||||||
|
if (error instanceof ServerError || isAbortError(error)) {
|
||||||
|
throw error;
|
||||||
|
}
|
||||||
|
|
||||||
|
let details = String(error);
|
||||||
|
|
||||||
|
if (process.env.NODE_ENV === 'development') {
|
||||||
|
// @ts-ignore
|
||||||
|
details += `: ${error.stack}`;
|
||||||
|
}
|
||||||
|
|
||||||
|
throw new ServerError(Status.UNKNOWN, details);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
server = server.use(errorHandlingMiddleware);
|
||||||
|
server.add(PluginRuntimeDefinition, new PluginRuntimeService());
|
||||||
|
|
||||||
|
// Start on random port if YAAK_GRPC_PORT_FILE_PATH is set, or :4000
|
||||||
|
const addr = process.env.YAAK_GRPC_PORT_FILE_PATH ? 'localhost:0' : 'localhost:4000';
|
||||||
|
server.listen(addr).then((port) => {
|
||||||
|
console.log('gRPC server listening on', `http://localhost:${port}`);
|
||||||
|
if (process.env.YAAK_GRPC_PORT_FILE_PATH) {
|
||||||
|
console.log('Wrote port file to', process.env.YAAK_GRPC_PORT_FILE_PATH);
|
||||||
|
fs.writeFileSync(process.env.YAAK_GRPC_PORT_FILE_PATH, JSON.stringify({ port }, null, 2));
|
||||||
|
}
|
||||||
|
});
|
||||||
@@ -0,0 +1,76 @@
|
|||||||
|
import { readFileSync } from 'node:fs';
|
||||||
|
import path from 'node:path';
|
||||||
|
import { parentPort, workerData } from 'node:worker_threads';
|
||||||
|
import { ParentToWorkerEvent } from './PluginHandle';
|
||||||
|
import { PluginInfo } from './plugins';
|
||||||
|
|
||||||
|
new Promise<void>(async (resolve, reject) => {
|
||||||
|
const { pluginDir } = workerData;
|
||||||
|
const pathMod = path.join(pluginDir, 'build/index.js');
|
||||||
|
const pathPkg = path.join(pluginDir, 'package.json');
|
||||||
|
|
||||||
|
let pkg: { [x: string]: any };
|
||||||
|
try {
|
||||||
|
pkg = JSON.parse(readFileSync(pathPkg, 'utf8'));
|
||||||
|
} catch (err) {
|
||||||
|
// TODO: Do something better here
|
||||||
|
reject(err);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const mod = (await import(`file://${pathMod}`)).default ?? {};
|
||||||
|
|
||||||
|
const info: PluginInfo = {
|
||||||
|
capabilities: [],
|
||||||
|
name: pkg['name'] ?? 'n/a',
|
||||||
|
dir: pluginDir,
|
||||||
|
};
|
||||||
|
|
||||||
|
if (typeof mod['pluginHookImport'] === 'function') {
|
||||||
|
info.capabilities.push('import');
|
||||||
|
}
|
||||||
|
|
||||||
|
if (typeof mod['pluginHookExport'] === 'function') {
|
||||||
|
info.capabilities.push('export');
|
||||||
|
}
|
||||||
|
|
||||||
|
if (typeof mod['pluginHookResponseFilter'] === 'function') {
|
||||||
|
info.capabilities.push('filter');
|
||||||
|
}
|
||||||
|
|
||||||
|
console.log('Loaded plugin', info.name, info.capabilities, info.dir);
|
||||||
|
|
||||||
|
function reply<T>(originalMsg: ParentToWorkerEvent, payload: T) {
|
||||||
|
parentPort!.postMessage({ payload, callbackId: originalMsg.callbackId });
|
||||||
|
}
|
||||||
|
|
||||||
|
function replyErr(originalMsg: ParentToWorkerEvent, error: unknown) {
|
||||||
|
parentPort!.postMessage({
|
||||||
|
error: String(error),
|
||||||
|
callbackId: originalMsg.callbackId,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
parentPort!.on('message', async (msg: ParentToWorkerEvent) => {
|
||||||
|
try {
|
||||||
|
const ctx = { todo: 'implement me' };
|
||||||
|
if (msg.name === 'run-import') {
|
||||||
|
reply(msg, await mod.pluginHookImport(ctx, msg.payload));
|
||||||
|
} else if (msg.name === 'run-filter') {
|
||||||
|
reply(msg, await mod.pluginHookResponseFilter(ctx, msg.payload));
|
||||||
|
} else if (msg.name === 'run-export') {
|
||||||
|
reply(msg, await mod.pluginHookExport(ctx, msg.payload));
|
||||||
|
} else if (msg.name === 'info') {
|
||||||
|
reply(msg, info);
|
||||||
|
} else {
|
||||||
|
console.log('Unknown message', msg);
|
||||||
|
}
|
||||||
|
} catch (err: unknown) {
|
||||||
|
replyErr(msg, err);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
resolve();
|
||||||
|
}).catch((err) => {
|
||||||
|
console.log('failed to boot plugin', err);
|
||||||
|
});
|
||||||
@@ -0,0 +1,18 @@
|
|||||||
|
import * as fs from 'node:fs';
|
||||||
|
import path from 'node:path';
|
||||||
|
import { PluginHandle } from './PluginHandle';
|
||||||
|
|
||||||
|
export interface PluginInfo {
|
||||||
|
name: string;
|
||||||
|
dir: string;
|
||||||
|
capabilities: ('import' | 'export' | 'filter')[];
|
||||||
|
}
|
||||||
|
|
||||||
|
export function loadPlugins(): PluginHandle[] {
|
||||||
|
const pluginsDir = process.env.YAAK_PLUGINS_DIR;
|
||||||
|
if (!pluginsDir) throw new Error('YAAK_PLUGINS_DIR is not set');
|
||||||
|
console.log('Loading plugins from', pluginsDir);
|
||||||
|
|
||||||
|
const pluginDirs = fs.readdirSync(pluginsDir).map((p) => path.join(pluginsDir, p));
|
||||||
|
return pluginDirs.map((pluginDir) => new PluginHandle(pluginDir));
|
||||||
|
}
|
||||||
@@ -0,0 +1,25 @@
|
|||||||
|
{
|
||||||
|
"compilerOptions": {
|
||||||
|
"module": "node16",
|
||||||
|
"strict": true,
|
||||||
|
"esModuleInterop": true,
|
||||||
|
"allowSyntheticDefaultImports": true,
|
||||||
|
"target": "es2021",
|
||||||
|
"lib": ["es2021"],
|
||||||
|
"noImplicitAny": false,
|
||||||
|
"moduleResolution": "node",
|
||||||
|
"sourceMap": true,
|
||||||
|
"outDir": "dist",
|
||||||
|
"baseUrl": ".",
|
||||||
|
"skipLibCheck": true,
|
||||||
|
"paths": {
|
||||||
|
"*": [
|
||||||
|
"node_modules/*",
|
||||||
|
"src/types/*"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"include": [
|
||||||
|
"src/**/*"
|
||||||
|
]
|
||||||
|
}
|
||||||
+5
-4
@@ -1,6 +1,7 @@
|
|||||||
module.exports = {
|
module.exports = {
|
||||||
plugins: {
|
plugins: [
|
||||||
tailwindcss: {},
|
require('@tailwindcss/nesting')(require('postcss-nesting')),
|
||||||
autoprefixer: {},
|
require('tailwindcss'),
|
||||||
},
|
require('autoprefixer'),
|
||||||
|
]
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,32 @@
|
|||||||
|
syntax = "proto3";
|
||||||
|
|
||||||
|
package yaak.plugins.runtime;
|
||||||
|
|
||||||
|
service PluginRuntime {
|
||||||
|
rpc hookImport (HookImportRequest) returns (HookResponse);
|
||||||
|
rpc hookExport (HookExportRequest) returns (HookResponse);
|
||||||
|
rpc hookResponseFilter (HookResponseFilterRequest) returns (HookResponse);
|
||||||
|
}
|
||||||
|
|
||||||
|
message PluginInfo {
|
||||||
|
string plugin = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
message HookResponse {
|
||||||
|
PluginInfo info = 1;
|
||||||
|
string data = 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
message HookImportRequest {
|
||||||
|
string data = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
message HookResponseFilterRequest {
|
||||||
|
string filter = 1;
|
||||||
|
string body = 2;
|
||||||
|
string contentType = 3;
|
||||||
|
}
|
||||||
|
|
||||||
|
message HookExportRequest {
|
||||||
|
string request = 1;
|
||||||
|
}
|
||||||
@@ -1,39 +0,0 @@
|
|||||||
name = "rsw"
|
|
||||||
version = "0.1.0"
|
|
||||||
|
|
||||||
#! time interval for file changes to trigger wasm-pack build, default `50` milliseconds
|
|
||||||
interval = 50
|
|
||||||
|
|
||||||
#! link
|
|
||||||
#! npm link @see https://docs.npmjs.com/cli/v8/commands/npm-link
|
|
||||||
#! yarn link @see https://classic.yarnpkg.com/en/docs/cli/link
|
|
||||||
#! pnpm link @see https://pnpm.io/cli/link
|
|
||||||
#! The link command will only be executed if `[[crates]] link = true`
|
|
||||||
#! cli: `npm` | `yarn` | `pnpm`, default is `npm`
|
|
||||||
cli = "npm"
|
|
||||||
|
|
||||||
#! ---------------------------
|
|
||||||
|
|
||||||
#! rsw new <name>
|
|
||||||
[new]
|
|
||||||
#! @see https://rustwasm.github.io/docs/wasm-pack/commands/new.html
|
|
||||||
#! using: `wasm-pack` | `rsw` | `user`, default is `wasm-pack`
|
|
||||||
#! 1. wasm-pack: `rsw new <name> --template <template> --mode <normal|noinstall|force>`
|
|
||||||
#! 2. rsw: `rsw new <name>`, built-in templates
|
|
||||||
#! 3. user: `rsw new <name>`, if `dir` is not configured, use `wasm-pack new <name>` to initialize the project
|
|
||||||
using = "wasm-pack"
|
|
||||||
#! this field needs to be configured when `using = "user"`
|
|
||||||
#! `using = "wasm-pack"` or `using = "rsw"`, this field will be ignored
|
|
||||||
#! copy all files in this directory
|
|
||||||
dir = "my-template"
|
|
||||||
|
|
||||||
#! ################# NPM Package #################
|
|
||||||
|
|
||||||
#! When there is only `name`, other fields will use the default configuration
|
|
||||||
|
|
||||||
#! 📦 -------- package: @rsw --------
|
|
||||||
[[crates]]
|
|
||||||
#! npm package name (path: $ROOT/@rsw)
|
|
||||||
name = "src-wasm/hello"
|
|
||||||
#! run `npm link`: `true` | `false`, default is `false`
|
|
||||||
link = true
|
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
edition = "2018"
|
||||||
@@ -0,0 +1,15 @@
|
|||||||
|
const path = require('path');
|
||||||
|
const fs = require('fs');
|
||||||
|
|
||||||
|
const version = process.env.YAAK_VERSION?.replace('v', '');
|
||||||
|
if (!version) {
|
||||||
|
throw new Error('YAAK_VERSION environment variable not set')
|
||||||
|
}
|
||||||
|
|
||||||
|
const tauriConfigPath = path.join(__dirname, '../src-tauri/tauri.conf.json');
|
||||||
|
const tauriConfig = JSON.parse(fs.readFileSync(tauriConfigPath, 'utf8'));
|
||||||
|
|
||||||
|
tauriConfig.version = version;
|
||||||
|
|
||||||
|
console.log('Writing version ' + version + ' to ' + tauriConfigPath)
|
||||||
|
fs.writeFileSync(tauriConfigPath, JSON.stringify(tauriConfig, null, 2));
|
||||||
@@ -0,0 +1,72 @@
|
|||||||
|
const path = require('node:path');
|
||||||
|
const decompress = require('decompress');
|
||||||
|
const Downloader = require("nodejs-file-downloader");
|
||||||
|
const {rmSync, unlinkSync, cpSync, mkdirSync, existsSync} = require("node:fs");
|
||||||
|
const {execSync} = require("node:child_process");
|
||||||
|
|
||||||
|
const NODE_VERSION = 'v22.5.1';
|
||||||
|
|
||||||
|
// `${process.platform}_${process.arch}`
|
||||||
|
const MAC_ARM = 'darwin_arm64';
|
||||||
|
const MAC_X64 = 'darwin_x64';
|
||||||
|
const LNX_X64 = 'linux_x64';
|
||||||
|
const WIN_X64 = 'win32_x64';
|
||||||
|
|
||||||
|
const URL_MAP = {
|
||||||
|
[MAC_ARM]: `https://nodejs.org/download/release/${NODE_VERSION}/node-${NODE_VERSION}-darwin-arm64.tar.gz`,
|
||||||
|
[MAC_X64]: `https://nodejs.org/download/release/${NODE_VERSION}/node-${NODE_VERSION}-darwin-x64.tar.gz`,
|
||||||
|
[LNX_X64]: `https://nodejs.org/download/release/${NODE_VERSION}/node-${NODE_VERSION}-linux-x64.tar.gz`,
|
||||||
|
[WIN_X64]: `https://nodejs.org/download/release/${NODE_VERSION}/node-${NODE_VERSION}-win-x64.zip`,
|
||||||
|
};
|
||||||
|
|
||||||
|
const SRC_BIN_MAP = {
|
||||||
|
[MAC_ARM]: `node-${NODE_VERSION}-darwin-arm64/bin/node`,
|
||||||
|
[MAC_X64]: `node-${NODE_VERSION}-darwin-x64/bin/node`,
|
||||||
|
[LNX_X64]: `node-${NODE_VERSION}-linux-x64/bin/node`,
|
||||||
|
[WIN_X64]: `node-${NODE_VERSION}-win-x64/node.exe`,
|
||||||
|
};
|
||||||
|
|
||||||
|
const DST_BIN_MAP = {
|
||||||
|
darwin_arm64: 'yaaknode-aarch64-apple-darwin',
|
||||||
|
darwin_x64: 'yaaknode-x86_64-apple-darwin',
|
||||||
|
linux_x64: 'yaaknode-x86_64-unknown-linux-gnu',
|
||||||
|
win32_x64: 'yaaknode-x86_64-pc-windows-msvc.exe',
|
||||||
|
};
|
||||||
|
|
||||||
|
const key = `${process.platform}_${process.env.YAAK_TARGET_ARCH ?? process.arch}`;
|
||||||
|
|
||||||
|
const destDir = path.join(__dirname, `..`, 'src-tauri', 'vendored', 'node');
|
||||||
|
const binDest = path.join(destDir, DST_BIN_MAP[key]);
|
||||||
|
console.log(`Vendoring NodeJS ${NODE_VERSION} for ${key}`);
|
||||||
|
|
||||||
|
if (existsSync(binDest) && execSync(`${binDest} --version`).toString('utf-8').trim() === NODE_VERSION) {
|
||||||
|
console.log("NodeJS already vendored");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
rmSync(destDir, {recursive: true, force: true});
|
||||||
|
mkdirSync(destDir, {recursive: true});
|
||||||
|
|
||||||
|
(async function () {
|
||||||
|
const url = URL_MAP[key];
|
||||||
|
const tmpDir = path.join(__dirname, 'tmp', Date.now().toString());
|
||||||
|
|
||||||
|
// Download GitHub release artifact
|
||||||
|
const {filePath} = await new Downloader({url, directory: tmpDir,}).download();
|
||||||
|
|
||||||
|
// Decompress to the same directory
|
||||||
|
await decompress(filePath, tmpDir, {});
|
||||||
|
|
||||||
|
// Remove the original archive
|
||||||
|
unlinkSync(filePath);
|
||||||
|
|
||||||
|
// Copy binary
|
||||||
|
const binSrc = path.join(tmpDir, SRC_BIN_MAP[key]);
|
||||||
|
cpSync(binSrc, binDest);
|
||||||
|
rmSync(tmpDir, {recursive: true, force: true});
|
||||||
|
|
||||||
|
console.log("Downloaded NodeJS to", binDest);
|
||||||
|
})().catch(err => {
|
||||||
|
console.log('Script failed:', err);
|
||||||
|
process.exit(1);
|
||||||
|
});
|
||||||
@@ -0,0 +1,25 @@
|
|||||||
|
const {readdirSync, cpSync} = require("node:fs");
|
||||||
|
const path = require("node:path");
|
||||||
|
const {execSync} = require("node:child_process");
|
||||||
|
const pluginsDir = process.env.YAAK_PLUGINS_DIR;
|
||||||
|
if (!pluginsDir) {
|
||||||
|
console.log("YAAK_PLUGINS_DIR is not set");
|
||||||
|
process.exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
console.log('Installing Yaak plugins dependencies', pluginsDir);
|
||||||
|
execSync('npm ci', {cwd: pluginsDir});
|
||||||
|
console.log('Building Yaak plugins', pluginsDir);
|
||||||
|
execSync('npm run build', {cwd: pluginsDir});
|
||||||
|
|
||||||
|
console.log('Copying Yaak plugins to', pluginsDir);
|
||||||
|
|
||||||
|
const pluginsRoot = path.join(pluginsDir, 'plugins');
|
||||||
|
for (const name of readdirSync(pluginsRoot)) {
|
||||||
|
const dir = path.join(pluginsRoot, name);
|
||||||
|
if (name.startsWith('.')) continue;
|
||||||
|
const destDir = path.join(__dirname, '../src-tauri/vendored/plugins/', name);
|
||||||
|
console.log(`Copying ${name} to ${destDir}`);
|
||||||
|
cpSync(path.join(dir, 'package.json'), path.join(destDir, 'package.json'));
|
||||||
|
cpSync(path.join(dir, 'build/index.js'), path.join(destDir, 'build/index.js'));
|
||||||
|
}
|
||||||
@@ -0,0 +1,66 @@
|
|||||||
|
const decompress = require('decompress');
|
||||||
|
const Downloader = require("nodejs-file-downloader");
|
||||||
|
const path = require("node:path");
|
||||||
|
const fs = require("node:fs");
|
||||||
|
const {rmSync, mkdirSync} = require("node:fs");
|
||||||
|
|
||||||
|
// `${process.platform}_${process.arch}`
|
||||||
|
const MAC_ARM = 'darwin_arm64';
|
||||||
|
const MAC_X64 = 'darwin_x64';
|
||||||
|
const LNX_X64 = 'linux_x64';
|
||||||
|
const WIN_X64 = 'win32_x64';
|
||||||
|
|
||||||
|
const URL_MAP = {
|
||||||
|
[MAC_ARM]: 'https://github.com/protocolbuffers/protobuf/releases/download/v27.2/protoc-27.2-osx-aarch_64.zip',
|
||||||
|
[MAC_X64]: 'https://github.com/protocolbuffers/protobuf/releases/download/v27.2/protoc-27.2-osx-x86_64.zip',
|
||||||
|
[LNX_X64]: 'https://github.com/protocolbuffers/protobuf/releases/download/v27.2/protoc-27.2-linux-x86_64.zip',
|
||||||
|
[WIN_X64]: 'https://github.com/protocolbuffers/protobuf/releases/download/v27.2/protoc-27.2-win64.zip',
|
||||||
|
};
|
||||||
|
|
||||||
|
const SRC_BIN_MAP = {
|
||||||
|
[MAC_ARM]: 'bin/protoc',
|
||||||
|
[MAC_X64]: 'bin/protoc',
|
||||||
|
[LNX_X64]: 'bin/protoc',
|
||||||
|
[WIN_X64]: 'bin/protoc.exe',
|
||||||
|
};
|
||||||
|
|
||||||
|
const DST_BIN_MAP = {
|
||||||
|
[MAC_ARM]: 'yaakprotoc-aarch64-apple-darwin',
|
||||||
|
[MAC_X64]: 'yaakprotoc-x86_64-apple-darwin',
|
||||||
|
[LNX_X64]: 'yaakprotoc-x86_64-unknown-linux-gnu',
|
||||||
|
[WIN_X64]: 'yaakprotoc-x86_64-pc-windows-msvc.exe',
|
||||||
|
};
|
||||||
|
|
||||||
|
const dstDir = path.join(__dirname, `..`, 'src-tauri', 'vendored', 'protoc');
|
||||||
|
rmSync(dstDir, {recursive: true, force: true});
|
||||||
|
mkdirSync(dstDir, {recursive: true});
|
||||||
|
|
||||||
|
(async function () {
|
||||||
|
const key = `${process.platform}_${process.env.YAAK_TARGET_ARCH ?? process.arch}`;
|
||||||
|
console.log("Vendoring protoc binary for", key);
|
||||||
|
const url = URL_MAP[key];
|
||||||
|
const tmpDir = path.join(__dirname, 'tmp', Date.now().toString());
|
||||||
|
|
||||||
|
// Download GitHub release artifact
|
||||||
|
const {filePath} = await new Downloader({url, directory: tmpDir,}).download();
|
||||||
|
|
||||||
|
// Decompress to the same directory
|
||||||
|
await decompress(filePath, tmpDir, {});
|
||||||
|
|
||||||
|
// Remove the original archive
|
||||||
|
fs.unlinkSync(filePath);
|
||||||
|
|
||||||
|
// Copy binary
|
||||||
|
const binSrc = path.join(tmpDir, SRC_BIN_MAP[key]);
|
||||||
|
const binDst = path.join(dstDir, DST_BIN_MAP[key]);
|
||||||
|
fs.cpSync(binSrc, binDst);
|
||||||
|
|
||||||
|
// Copy other files
|
||||||
|
const includeSrc = path.join(tmpDir, 'include');
|
||||||
|
const includeDst = path.join(dstDir, 'include');
|
||||||
|
fs.cpSync(includeSrc, includeDst, {recursive: true});
|
||||||
|
|
||||||
|
rmSync(tmpDir, {recursive: true, force: true});
|
||||||
|
|
||||||
|
console.log("Downloaded protoc to", binDst);
|
||||||
|
})().catch(err => console.log('Script failed:', err));
|
||||||
@@ -2,3 +2,4 @@
|
|||||||
# will have compiled files and executables
|
# will have compiled files and executables
|
||||||
/target/
|
/target/
|
||||||
|
|
||||||
|
vendored
|
||||||
|
|||||||
Generated
+50
@@ -0,0 +1,50 @@
|
|||||||
|
{
|
||||||
|
"db_name": "SQLite",
|
||||||
|
"query": "\n SELECT model, created_at, updated_at, namespace, key, value\n FROM key_values\n WHERE namespace = ? AND key = ?\n ",
|
||||||
|
"describe": {
|
||||||
|
"columns": [
|
||||||
|
{
|
||||||
|
"name": "model",
|
||||||
|
"ordinal": 0,
|
||||||
|
"type_info": "Text"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "created_at",
|
||||||
|
"ordinal": 1,
|
||||||
|
"type_info": "Datetime"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "updated_at",
|
||||||
|
"ordinal": 2,
|
||||||
|
"type_info": "Datetime"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "namespace",
|
||||||
|
"ordinal": 3,
|
||||||
|
"type_info": "Text"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "key",
|
||||||
|
"ordinal": 4,
|
||||||
|
"type_info": "Text"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "value",
|
||||||
|
"ordinal": 5,
|
||||||
|
"type_info": "Text"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"parameters": {
|
||||||
|
"Right": 2
|
||||||
|
},
|
||||||
|
"nullable": [
|
||||||
|
false,
|
||||||
|
false,
|
||||||
|
false,
|
||||||
|
false,
|
||||||
|
false,
|
||||||
|
false
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"hash": "06aaf8f4a17566f1d25da2a60f0baf4b5fc28c3cf0c001a84e25edf9eab3c7e3"
|
||||||
|
}
|
||||||
Generated
+12
@@ -0,0 +1,12 @@
|
|||||||
|
{
|
||||||
|
"db_name": "SQLite",
|
||||||
|
"query": "\n DELETE FROM http_responses\n WHERE id = ?\n ",
|
||||||
|
"describe": {
|
||||||
|
"columns": [],
|
||||||
|
"parameters": {
|
||||||
|
"Right": 1
|
||||||
|
},
|
||||||
|
"nullable": []
|
||||||
|
},
|
||||||
|
"hash": "07d1a1c7b4f3d9625a766e60fd57bb779b71dae30e5bbce34885a911a5a42428"
|
||||||
|
}
|
||||||
Generated
+116
@@ -0,0 +1,116 @@
|
|||||||
|
{
|
||||||
|
"db_name": "SQLite",
|
||||||
|
"query": "\n SELECT\n id, model, workspace_id, request_id, updated_at, created_at, url, status,\n status_reason, content_length, body_path, elapsed, elapsed_headers, error,\n version, remote_addr,\n headers AS \"headers!: sqlx::types::Json<Vec<HttpResponseHeader>>\"\n FROM http_responses\n WHERE id = ?\n ",
|
||||||
|
"describe": {
|
||||||
|
"columns": [
|
||||||
|
{
|
||||||
|
"name": "id",
|
||||||
|
"ordinal": 0,
|
||||||
|
"type_info": "Text"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "model",
|
||||||
|
"ordinal": 1,
|
||||||
|
"type_info": "Text"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "workspace_id",
|
||||||
|
"ordinal": 2,
|
||||||
|
"type_info": "Text"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "request_id",
|
||||||
|
"ordinal": 3,
|
||||||
|
"type_info": "Text"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "updated_at",
|
||||||
|
"ordinal": 4,
|
||||||
|
"type_info": "Datetime"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "created_at",
|
||||||
|
"ordinal": 5,
|
||||||
|
"type_info": "Datetime"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "url",
|
||||||
|
"ordinal": 6,
|
||||||
|
"type_info": "Text"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "status",
|
||||||
|
"ordinal": 7,
|
||||||
|
"type_info": "Int64"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "status_reason",
|
||||||
|
"ordinal": 8,
|
||||||
|
"type_info": "Text"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "content_length",
|
||||||
|
"ordinal": 9,
|
||||||
|
"type_info": "Int64"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "body_path",
|
||||||
|
"ordinal": 10,
|
||||||
|
"type_info": "Text"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "elapsed",
|
||||||
|
"ordinal": 11,
|
||||||
|
"type_info": "Int64"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "elapsed_headers",
|
||||||
|
"ordinal": 12,
|
||||||
|
"type_info": "Int64"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "error",
|
||||||
|
"ordinal": 13,
|
||||||
|
"type_info": "Text"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "version",
|
||||||
|
"ordinal": 14,
|
||||||
|
"type_info": "Text"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "remote_addr",
|
||||||
|
"ordinal": 15,
|
||||||
|
"type_info": "Text"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "headers!: sqlx::types::Json<Vec<HttpResponseHeader>>",
|
||||||
|
"ordinal": 16,
|
||||||
|
"type_info": "Text"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"parameters": {
|
||||||
|
"Right": 1
|
||||||
|
},
|
||||||
|
"nullable": [
|
||||||
|
false,
|
||||||
|
false,
|
||||||
|
false,
|
||||||
|
false,
|
||||||
|
false,
|
||||||
|
false,
|
||||||
|
false,
|
||||||
|
false,
|
||||||
|
true,
|
||||||
|
true,
|
||||||
|
true,
|
||||||
|
false,
|
||||||
|
false,
|
||||||
|
true,
|
||||||
|
true,
|
||||||
|
true,
|
||||||
|
false
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"hash": "0fa6b56f8c996d14908a56928674b4b35af5fa36f63dc48b9b66ee6dfde78976"
|
||||||
|
}
|
||||||
Generated
+12
@@ -0,0 +1,12 @@
|
|||||||
|
{
|
||||||
|
"db_name": "SQLite",
|
||||||
|
"query": "\n INSERT INTO workspaces (\n id, name, description, variables, setting_request_timeout,\n setting_follow_redirects, setting_validate_certificates\n )\n VALUES (?, ?, ?, ?, ?, ?, ?)\n ON CONFLICT (id) DO UPDATE SET\n updated_at = CURRENT_TIMESTAMP,\n name = excluded.name,\n description = excluded.description,\n variables = excluded.variables,\n setting_request_timeout = excluded.setting_request_timeout,\n setting_follow_redirects = excluded.setting_follow_redirects,\n setting_validate_certificates = excluded.setting_validate_certificates\n ",
|
||||||
|
"describe": {
|
||||||
|
"columns": [],
|
||||||
|
"parameters": {
|
||||||
|
"Right": 7
|
||||||
|
},
|
||||||
|
"nullable": []
|
||||||
|
},
|
||||||
|
"hash": "12b265491d1ebba19e1ce8a660e458ffbcd8c0850aef16ba1f70e358623ac66a"
|
||||||
|
}
|
||||||
Generated
+12
@@ -0,0 +1,12 @@
|
|||||||
|
{
|
||||||
|
"db_name": "SQLite",
|
||||||
|
"query": "\n INSERT INTO environments (\n id, workspace_id, name, variables\n )\n VALUES (?, ?, ?, ?)\n ON CONFLICT (id) DO UPDATE SET\n updated_at = CURRENT_TIMESTAMP,\n name = excluded.name,\n variables = excluded.variables\n ",
|
||||||
|
"describe": {
|
||||||
|
"columns": [],
|
||||||
|
"parameters": {
|
||||||
|
"Right": 4
|
||||||
|
},
|
||||||
|
"nullable": []
|
||||||
|
},
|
||||||
|
"hash": "13cb883199e81966174e6fda9c252bf7213fe01b5346266c0a89dc0ac89eda64"
|
||||||
|
}
|
||||||
Generated
+12
@@ -0,0 +1,12 @@
|
|||||||
|
{
|
||||||
|
"db_name": "SQLite",
|
||||||
|
"query": "\n INSERT INTO grpc_events (\n id, workspace_id, request_id, connection_id, content, event_type, metadata,\n status, error\n )\n VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)\n ON CONFLICT (id) DO UPDATE SET\n updated_at = CURRENT_TIMESTAMP,\n content = excluded.content,\n event_type = excluded.event_type,\n metadata = excluded.metadata,\n status = excluded.status,\n error = excluded.error\n ",
|
||||||
|
"describe": {
|
||||||
|
"columns": [],
|
||||||
|
"parameters": {
|
||||||
|
"Right": 9
|
||||||
|
},
|
||||||
|
"nullable": []
|
||||||
|
},
|
||||||
|
"hash": "14930955e8a914e292dfbebfce2ea43cc41c1d517386ed816c16d436bf626bf3"
|
||||||
|
}
|
||||||
Generated
+104
@@ -0,0 +1,104 @@
|
|||||||
|
{
|
||||||
|
"db_name": "SQLite",
|
||||||
|
"query": "\n SELECT\n id, model, workspace_id, folder_id, created_at, updated_at, name, sort_priority,\n url, service, method, message, authentication_type,\n authentication AS \"authentication!: Json<HashMap<String, JsonValue>>\",\n metadata AS \"metadata!: sqlx::types::Json<Vec<GrpcMetadataEntry>>\"\n FROM grpc_requests\n WHERE workspace_id = ?\n ",
|
||||||
|
"describe": {
|
||||||
|
"columns": [
|
||||||
|
{
|
||||||
|
"name": "id",
|
||||||
|
"ordinal": 0,
|
||||||
|
"type_info": "Text"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "model",
|
||||||
|
"ordinal": 1,
|
||||||
|
"type_info": "Text"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "workspace_id",
|
||||||
|
"ordinal": 2,
|
||||||
|
"type_info": "Text"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "folder_id",
|
||||||
|
"ordinal": 3,
|
||||||
|
"type_info": "Text"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "created_at",
|
||||||
|
"ordinal": 4,
|
||||||
|
"type_info": "Datetime"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "updated_at",
|
||||||
|
"ordinal": 5,
|
||||||
|
"type_info": "Datetime"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "name",
|
||||||
|
"ordinal": 6,
|
||||||
|
"type_info": "Text"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "sort_priority",
|
||||||
|
"ordinal": 7,
|
||||||
|
"type_info": "Float"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "url",
|
||||||
|
"ordinal": 8,
|
||||||
|
"type_info": "Text"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "service",
|
||||||
|
"ordinal": 9,
|
||||||
|
"type_info": "Text"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "method",
|
||||||
|
"ordinal": 10,
|
||||||
|
"type_info": "Text"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "message",
|
||||||
|
"ordinal": 11,
|
||||||
|
"type_info": "Text"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "authentication_type",
|
||||||
|
"ordinal": 12,
|
||||||
|
"type_info": "Text"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "authentication!: Json<HashMap<String, JsonValue>>",
|
||||||
|
"ordinal": 13,
|
||||||
|
"type_info": "Text"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "metadata!: sqlx::types::Json<Vec<GrpcMetadataEntry>>",
|
||||||
|
"ordinal": 14,
|
||||||
|
"type_info": "Text"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"parameters": {
|
||||||
|
"Right": 1
|
||||||
|
},
|
||||||
|
"nullable": [
|
||||||
|
false,
|
||||||
|
false,
|
||||||
|
false,
|
||||||
|
true,
|
||||||
|
false,
|
||||||
|
false,
|
||||||
|
false,
|
||||||
|
false,
|
||||||
|
false,
|
||||||
|
true,
|
||||||
|
true,
|
||||||
|
false,
|
||||||
|
true,
|
||||||
|
false,
|
||||||
|
false
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"hash": "1821c2f60b9fa4514d58eb73b23e25ad683b80b9bd0c2944063190a0d0a19ee5"
|
||||||
|
}
|
||||||
Generated
+80
@@ -0,0 +1,80 @@
|
|||||||
|
{
|
||||||
|
"db_name": "SQLite",
|
||||||
|
"query": "\n SELECT\n id, model, workspace_id, request_id, connection_id, created_at, content, status, error,\n event_type AS \"event_type!: GrpcEventType\",\n metadata AS \"metadata!: sqlx::types::Json<HashMap<String, String>>\"\n FROM grpc_events\n WHERE connection_id = ?\n ",
|
||||||
|
"describe": {
|
||||||
|
"columns": [
|
||||||
|
{
|
||||||
|
"name": "id",
|
||||||
|
"ordinal": 0,
|
||||||
|
"type_info": "Text"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "model",
|
||||||
|
"ordinal": 1,
|
||||||
|
"type_info": "Text"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "workspace_id",
|
||||||
|
"ordinal": 2,
|
||||||
|
"type_info": "Text"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "request_id",
|
||||||
|
"ordinal": 3,
|
||||||
|
"type_info": "Text"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "connection_id",
|
||||||
|
"ordinal": 4,
|
||||||
|
"type_info": "Text"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "created_at",
|
||||||
|
"ordinal": 5,
|
||||||
|
"type_info": "Datetime"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "content",
|
||||||
|
"ordinal": 6,
|
||||||
|
"type_info": "Text"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "status",
|
||||||
|
"ordinal": 7,
|
||||||
|
"type_info": "Int64"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "error",
|
||||||
|
"ordinal": 8,
|
||||||
|
"type_info": "Text"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "event_type!: GrpcEventType",
|
||||||
|
"ordinal": 9,
|
||||||
|
"type_info": "Text"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "metadata!: sqlx::types::Json<HashMap<String, String>>",
|
||||||
|
"ordinal": 10,
|
||||||
|
"type_info": "Text"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"parameters": {
|
||||||
|
"Right": 1
|
||||||
|
},
|
||||||
|
"nullable": [
|
||||||
|
false,
|
||||||
|
false,
|
||||||
|
false,
|
||||||
|
false,
|
||||||
|
false,
|
||||||
|
false,
|
||||||
|
false,
|
||||||
|
true,
|
||||||
|
true,
|
||||||
|
false,
|
||||||
|
false
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"hash": "18ada3bb42c29f1940ab2e61961d79cdd69210f3dc2076aedcadeba8e34dcb6e"
|
||||||
|
}
|
||||||
Generated
+12
@@ -0,0 +1,12 @@
|
|||||||
|
{
|
||||||
|
"db_name": "SQLite",
|
||||||
|
"query": "\n INSERT INTO settings (id)\n VALUES ('default')\n ",
|
||||||
|
"describe": {
|
||||||
|
"columns": [],
|
||||||
|
"parameters": {
|
||||||
|
"Right": 0
|
||||||
|
},
|
||||||
|
"nullable": []
|
||||||
|
},
|
||||||
|
"hash": "2c181a4dc13efc52fe6a5a68291c5678a9624020df4ea744e78396f6926d5c88"
|
||||||
|
}
|
||||||
Generated
+12
@@ -0,0 +1,12 @@
|
|||||||
|
{
|
||||||
|
"db_name": "SQLite",
|
||||||
|
"query": "\n INSERT INTO http_responses (\n id, request_id, workspace_id, elapsed, elapsed_headers, url, status, status_reason,\n content_length, body_path, headers, version, remote_addr\n )\n VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?);\n ",
|
||||||
|
"describe": {
|
||||||
|
"columns": [],
|
||||||
|
"parameters": {
|
||||||
|
"Right": 13
|
||||||
|
},
|
||||||
|
"nullable": []
|
||||||
|
},
|
||||||
|
"hash": "2c9658a639c5e4994ae9c8ec30bd4e40a1945d640962991f879928619950ef62"
|
||||||
|
}
|
||||||
Generated
+92
@@ -0,0 +1,92 @@
|
|||||||
|
{
|
||||||
|
"db_name": "SQLite",
|
||||||
|
"query": "\n SELECT\n id, model, workspace_id, request_id, created_at, updated_at, service,\n method, elapsed, status, error, url,\n trailers AS \"trailers!: sqlx::types::Json<HashMap<String, String>>\"\n FROM grpc_connections\n WHERE request_id = ?\n ORDER BY created_at DESC\n ",
|
||||||
|
"describe": {
|
||||||
|
"columns": [
|
||||||
|
{
|
||||||
|
"name": "id",
|
||||||
|
"ordinal": 0,
|
||||||
|
"type_info": "Text"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "model",
|
||||||
|
"ordinal": 1,
|
||||||
|
"type_info": "Text"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "workspace_id",
|
||||||
|
"ordinal": 2,
|
||||||
|
"type_info": "Text"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "request_id",
|
||||||
|
"ordinal": 3,
|
||||||
|
"type_info": "Text"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "created_at",
|
||||||
|
"ordinal": 4,
|
||||||
|
"type_info": "Datetime"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "updated_at",
|
||||||
|
"ordinal": 5,
|
||||||
|
"type_info": "Datetime"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "service",
|
||||||
|
"ordinal": 6,
|
||||||
|
"type_info": "Text"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "method",
|
||||||
|
"ordinal": 7,
|
||||||
|
"type_info": "Text"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "elapsed",
|
||||||
|
"ordinal": 8,
|
||||||
|
"type_info": "Int64"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "status",
|
||||||
|
"ordinal": 9,
|
||||||
|
"type_info": "Int64"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "error",
|
||||||
|
"ordinal": 10,
|
||||||
|
"type_info": "Text"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "url",
|
||||||
|
"ordinal": 11,
|
||||||
|
"type_info": "Text"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "trailers!: sqlx::types::Json<HashMap<String, String>>",
|
||||||
|
"ordinal": 12,
|
||||||
|
"type_info": "Text"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"parameters": {
|
||||||
|
"Right": 1
|
||||||
|
},
|
||||||
|
"nullable": [
|
||||||
|
false,
|
||||||
|
false,
|
||||||
|
false,
|
||||||
|
false,
|
||||||
|
false,
|
||||||
|
false,
|
||||||
|
false,
|
||||||
|
false,
|
||||||
|
false,
|
||||||
|
false,
|
||||||
|
true,
|
||||||
|
false,
|
||||||
|
false
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"hash": "3e8651cca7feecc208a676dfd24c7d8775040d5287c16890056dcb474674edfb"
|
||||||
|
}
|
||||||
Generated
+12
@@ -0,0 +1,12 @@
|
|||||||
|
{
|
||||||
|
"db_name": "SQLite",
|
||||||
|
"query": "\n DELETE FROM grpc_connections\n WHERE id = ?\n ",
|
||||||
|
"describe": {
|
||||||
|
"columns": [],
|
||||||
|
"parameters": {
|
||||||
|
"Right": 1
|
||||||
|
},
|
||||||
|
"nullable": []
|
||||||
|
},
|
||||||
|
"hash": "42bc0ded60b44dab19daf6d8fc7df83d83af5d88ea0b84514fdc877a668c27cd"
|
||||||
|
}
|
||||||
Generated
+12
@@ -0,0 +1,12 @@
|
|||||||
|
{
|
||||||
|
"db_name": "SQLite",
|
||||||
|
"query": "\n DELETE FROM http_requests\n WHERE id = ?\n ",
|
||||||
|
"describe": {
|
||||||
|
"columns": [],
|
||||||
|
"parameters": {
|
||||||
|
"Right": 1
|
||||||
|
},
|
||||||
|
"nullable": []
|
||||||
|
},
|
||||||
|
"hash": "448a1d1f1866ab42c0f81fcf8eb2930bf21dfdd43ca4831bc1a198cf45ac3732"
|
||||||
|
}
|
||||||
Generated
+62
@@ -0,0 +1,62 @@
|
|||||||
|
{
|
||||||
|
"db_name": "SQLite",
|
||||||
|
"query": "\n SELECT\n id, model, workspace_id, created_at, updated_at, folder_id, name, sort_priority\n FROM folders\n WHERE workspace_id = ?\n ",
|
||||||
|
"describe": {
|
||||||
|
"columns": [
|
||||||
|
{
|
||||||
|
"name": "id",
|
||||||
|
"ordinal": 0,
|
||||||
|
"type_info": "Text"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "model",
|
||||||
|
"ordinal": 1,
|
||||||
|
"type_info": "Text"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "workspace_id",
|
||||||
|
"ordinal": 2,
|
||||||
|
"type_info": "Text"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "created_at",
|
||||||
|
"ordinal": 3,
|
||||||
|
"type_info": "Datetime"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "updated_at",
|
||||||
|
"ordinal": 4,
|
||||||
|
"type_info": "Datetime"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "folder_id",
|
||||||
|
"ordinal": 5,
|
||||||
|
"type_info": "Text"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "name",
|
||||||
|
"ordinal": 6,
|
||||||
|
"type_info": "Text"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "sort_priority",
|
||||||
|
"ordinal": 7,
|
||||||
|
"type_info": "Float"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"parameters": {
|
||||||
|
"Right": 1
|
||||||
|
},
|
||||||
|
"nullable": [
|
||||||
|
false,
|
||||||
|
false,
|
||||||
|
false,
|
||||||
|
false,
|
||||||
|
false,
|
||||||
|
true,
|
||||||
|
false,
|
||||||
|
false
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"hash": "558e72df3c6f2635c6b3d52a199f9a5f7a3d82b379ff9af36645dcfb92548fdd"
|
||||||
|
}
|
||||||
Generated
+110
@@ -0,0 +1,110 @@
|
|||||||
|
{
|
||||||
|
"db_name": "SQLite",
|
||||||
|
"query": "\n SELECT\n id, model, workspace_id, folder_id, created_at, updated_at, name, url, method,\n body_type, authentication_type, sort_priority,\n url_parameters AS \"url_parameters!: sqlx::types::Json<Vec<HttpUrlParameter>>\",\n body AS \"body!: Json<HashMap<String, JsonValue>>\",\n authentication AS \"authentication!: Json<HashMap<String, JsonValue>>\",\n headers AS \"headers!: sqlx::types::Json<Vec<HttpRequestHeader>>\"\n FROM http_requests\n WHERE id = ?\n ",
|
||||||
|
"describe": {
|
||||||
|
"columns": [
|
||||||
|
{
|
||||||
|
"name": "id",
|
||||||
|
"ordinal": 0,
|
||||||
|
"type_info": "Text"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "model",
|
||||||
|
"ordinal": 1,
|
||||||
|
"type_info": "Text"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "workspace_id",
|
||||||
|
"ordinal": 2,
|
||||||
|
"type_info": "Text"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "folder_id",
|
||||||
|
"ordinal": 3,
|
||||||
|
"type_info": "Text"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "created_at",
|
||||||
|
"ordinal": 4,
|
||||||
|
"type_info": "Datetime"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "updated_at",
|
||||||
|
"ordinal": 5,
|
||||||
|
"type_info": "Datetime"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "name",
|
||||||
|
"ordinal": 6,
|
||||||
|
"type_info": "Text"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "url",
|
||||||
|
"ordinal": 7,
|
||||||
|
"type_info": "Text"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "method",
|
||||||
|
"ordinal": 8,
|
||||||
|
"type_info": "Text"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "body_type",
|
||||||
|
"ordinal": 9,
|
||||||
|
"type_info": "Text"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "authentication_type",
|
||||||
|
"ordinal": 10,
|
||||||
|
"type_info": "Text"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "sort_priority",
|
||||||
|
"ordinal": 11,
|
||||||
|
"type_info": "Float"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "url_parameters!: sqlx::types::Json<Vec<HttpUrlParameter>>",
|
||||||
|
"ordinal": 12,
|
||||||
|
"type_info": "Text"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "body!: Json<HashMap<String, JsonValue>>",
|
||||||
|
"ordinal": 13,
|
||||||
|
"type_info": "Text"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "authentication!: Json<HashMap<String, JsonValue>>",
|
||||||
|
"ordinal": 14,
|
||||||
|
"type_info": "Text"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "headers!: sqlx::types::Json<Vec<HttpRequestHeader>>",
|
||||||
|
"ordinal": 15,
|
||||||
|
"type_info": "Text"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"parameters": {
|
||||||
|
"Right": 1
|
||||||
|
},
|
||||||
|
"nullable": [
|
||||||
|
false,
|
||||||
|
false,
|
||||||
|
false,
|
||||||
|
true,
|
||||||
|
false,
|
||||||
|
false,
|
||||||
|
false,
|
||||||
|
false,
|
||||||
|
false,
|
||||||
|
true,
|
||||||
|
true,
|
||||||
|
false,
|
||||||
|
false,
|
||||||
|
false,
|
||||||
|
false,
|
||||||
|
false
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"hash": "573db23160de025e5c72efb90be7fff5e3ec4619b962d149fdd4d618fe02c680"
|
||||||
|
}
|
||||||
Generated
+56
@@ -0,0 +1,56 @@
|
|||||||
|
{
|
||||||
|
"db_name": "SQLite",
|
||||||
|
"query": "\n SELECT\n id, model, workspace_id, created_at, updated_at, name,\n variables AS \"variables!: sqlx::types::Json<Vec<EnvironmentVariable>>\"\n FROM environments\n WHERE id = ?\n ",
|
||||||
|
"describe": {
|
||||||
|
"columns": [
|
||||||
|
{
|
||||||
|
"name": "id",
|
||||||
|
"ordinal": 0,
|
||||||
|
"type_info": "Text"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "model",
|
||||||
|
"ordinal": 1,
|
||||||
|
"type_info": "Text"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "workspace_id",
|
||||||
|
"ordinal": 2,
|
||||||
|
"type_info": "Text"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "created_at",
|
||||||
|
"ordinal": 3,
|
||||||
|
"type_info": "Datetime"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "updated_at",
|
||||||
|
"ordinal": 4,
|
||||||
|
"type_info": "Datetime"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "name",
|
||||||
|
"ordinal": 5,
|
||||||
|
"type_info": "Text"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "variables!: sqlx::types::Json<Vec<EnvironmentVariable>>",
|
||||||
|
"ordinal": 6,
|
||||||
|
"type_info": "Null"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"parameters": {
|
||||||
|
"Right": 1
|
||||||
|
},
|
||||||
|
"nullable": [
|
||||||
|
false,
|
||||||
|
false,
|
||||||
|
false,
|
||||||
|
false,
|
||||||
|
false,
|
||||||
|
false,
|
||||||
|
false
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"hash": "5765e9565a8b89c5bc2d72197e0e4a1093739e9abba69f6fe5527d453fab4db8"
|
||||||
|
}
|
||||||
Generated
+12
@@ -0,0 +1,12 @@
|
|||||||
|
{
|
||||||
|
"db_name": "SQLite",
|
||||||
|
"query": "\n INSERT INTO grpc_requests (\n id, name, workspace_id, folder_id, sort_priority, url, service, method, message,\n authentication_type, authentication, metadata\n )\n VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)\n ON CONFLICT (id) DO UPDATE SET\n updated_at = CURRENT_TIMESTAMP,\n workspace_id = excluded.workspace_id,\n name = excluded.name,\n folder_id = excluded.folder_id,\n sort_priority = excluded.sort_priority,\n url = excluded.url,\n service = excluded.service,\n method = excluded.method,\n message = excluded.message,\n authentication_type = excluded.authentication_type,\n authentication = excluded.authentication,\n metadata = excluded.metadata\n ",
|
||||||
|
"describe": {
|
||||||
|
"columns": [],
|
||||||
|
"parameters": {
|
||||||
|
"Right": 12
|
||||||
|
},
|
||||||
|
"nullable": []
|
||||||
|
},
|
||||||
|
"hash": "5af82cd333895d3d7d67a92f37b0feb338f615b88aea2bd09cb5809008c645a3"
|
||||||
|
}
|
||||||
Generated
+12
@@ -0,0 +1,12 @@
|
|||||||
|
{
|
||||||
|
"db_name": "SQLite",
|
||||||
|
"query": "\n INSERT INTO http_requests (\n id, workspace_id, folder_id, name, url, url_parameters, method, body, body_type,\n authentication, authentication_type, headers, sort_priority\n )\n VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)\n ON CONFLICT (id) DO UPDATE SET\n updated_at = CURRENT_TIMESTAMP,\n workspace_id = excluded.workspace_id,\n name = excluded.name,\n folder_id = excluded.folder_id,\n method = excluded.method,\n headers = excluded.headers,\n body = excluded.body,\n body_type = excluded.body_type,\n authentication = excluded.authentication,\n authentication_type = excluded.authentication_type,\n url = excluded.url,\n url_parameters = excluded.url_parameters,\n sort_priority = excluded.sort_priority\n ",
|
||||||
|
"describe": {
|
||||||
|
"columns": [],
|
||||||
|
"parameters": {
|
||||||
|
"Right": 13
|
||||||
|
},
|
||||||
|
"nullable": []
|
||||||
|
},
|
||||||
|
"hash": "5f2f40062abbe93e23b38876319cf16d4d2b3f8d0be32ffe7848528c725e1429"
|
||||||
|
}
|
||||||
Generated
+56
@@ -0,0 +1,56 @@
|
|||||||
|
{
|
||||||
|
"db_name": "SQLite",
|
||||||
|
"query": "\n SELECT\n id, model, created_at, updated_at, workspace_id, name,\n cookies AS \"cookies!: sqlx::types::Json<Vec<JsonValue>>\"\n FROM cookie_jars WHERE workspace_id = ?\n ",
|
||||||
|
"describe": {
|
||||||
|
"columns": [
|
||||||
|
{
|
||||||
|
"name": "id",
|
||||||
|
"ordinal": 0,
|
||||||
|
"type_info": "Text"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "model",
|
||||||
|
"ordinal": 1,
|
||||||
|
"type_info": "Text"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "created_at",
|
||||||
|
"ordinal": 2,
|
||||||
|
"type_info": "Datetime"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "updated_at",
|
||||||
|
"ordinal": 3,
|
||||||
|
"type_info": "Datetime"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "workspace_id",
|
||||||
|
"ordinal": 4,
|
||||||
|
"type_info": "Text"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "name",
|
||||||
|
"ordinal": 5,
|
||||||
|
"type_info": "Text"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "cookies!: sqlx::types::Json<Vec<JsonValue>>",
|
||||||
|
"ordinal": 6,
|
||||||
|
"type_info": "Text"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"parameters": {
|
||||||
|
"Right": 1
|
||||||
|
},
|
||||||
|
"nullable": [
|
||||||
|
false,
|
||||||
|
false,
|
||||||
|
false,
|
||||||
|
false,
|
||||||
|
false,
|
||||||
|
false,
|
||||||
|
false
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"hash": "612efa9ac45723dc604a88f5e7e288b4055fec4ba7d9102131bd255c037fa021"
|
||||||
|
}
|
||||||
Generated
+12
@@ -0,0 +1,12 @@
|
|||||||
|
{
|
||||||
|
"db_name": "SQLite",
|
||||||
|
"query": "\n INSERT INTO grpc_connections (\n id, workspace_id, request_id, service, method, elapsed,\n status, error, trailers, url\n )\n VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)\n ON CONFLICT (id) DO UPDATE SET\n updated_at = CURRENT_TIMESTAMP,\n service = excluded.service,\n method = excluded.method,\n elapsed = excluded.elapsed,\n status = excluded.status,\n error = excluded.error,\n trailers = excluded.trailers,\n url = excluded.url\n ",
|
||||||
|
"describe": {
|
||||||
|
"columns": [],
|
||||||
|
"parameters": {
|
||||||
|
"Right": 10
|
||||||
|
},
|
||||||
|
"nullable": []
|
||||||
|
},
|
||||||
|
"hash": "66deed028199c78ed15ea2f837907887c2a2cb564d1d076dd4ebf0ecbc82e098"
|
||||||
|
}
|
||||||
Generated
+12
@@ -0,0 +1,12 @@
|
|||||||
|
{
|
||||||
|
"db_name": "SQLite",
|
||||||
|
"query": "\n UPDATE settings SET (\n theme, appearance, theme_dark, theme_light, update_channel,\n interface_font_size, interface_scale, editor_font_size, editor_soft_wrap,\n open_workspace_new_window\n ) = (?, ?, ?, ?, ?, ?, ?, ?, ?, ?) WHERE id = 'default';\n ",
|
||||||
|
"describe": {
|
||||||
|
"columns": [],
|
||||||
|
"parameters": {
|
||||||
|
"Right": 10
|
||||||
|
},
|
||||||
|
"nullable": []
|
||||||
|
},
|
||||||
|
"hash": "6b5edf45a6799cd7f87c23a3c7f818ad110d58c601f694a619d9345ae9e8e11d"
|
||||||
|
}
|
||||||
Generated
+12
@@ -0,0 +1,12 @@
|
|||||||
|
{
|
||||||
|
"db_name": "SQLite",
|
||||||
|
"query": "\n DELETE FROM workspaces\n WHERE id = ?\n ",
|
||||||
|
"describe": {
|
||||||
|
"columns": [],
|
||||||
|
"parameters": {
|
||||||
|
"Right": 1
|
||||||
|
},
|
||||||
|
"nullable": []
|
||||||
|
},
|
||||||
|
"hash": "84be2b954870ab181738656ecd4d03fca2ff21012947014c79626abfce8e999b"
|
||||||
|
}
|
||||||
Generated
+74
@@ -0,0 +1,74 @@
|
|||||||
|
{
|
||||||
|
"db_name": "SQLite",
|
||||||
|
"query": "\n SELECT\n id, model, created_at, updated_at, name, description, setting_request_timeout,\n setting_follow_redirects, setting_validate_certificates,\n variables AS \"variables!: sqlx::types::Json<Vec<EnvironmentVariable>>\"\n FROM workspaces\n ",
|
||||||
|
"describe": {
|
||||||
|
"columns": [
|
||||||
|
{
|
||||||
|
"name": "id",
|
||||||
|
"ordinal": 0,
|
||||||
|
"type_info": "Text"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "model",
|
||||||
|
"ordinal": 1,
|
||||||
|
"type_info": "Text"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "created_at",
|
||||||
|
"ordinal": 2,
|
||||||
|
"type_info": "Datetime"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "updated_at",
|
||||||
|
"ordinal": 3,
|
||||||
|
"type_info": "Datetime"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "name",
|
||||||
|
"ordinal": 4,
|
||||||
|
"type_info": "Text"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "description",
|
||||||
|
"ordinal": 5,
|
||||||
|
"type_info": "Text"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "setting_request_timeout",
|
||||||
|
"ordinal": 6,
|
||||||
|
"type_info": "Int64"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "setting_follow_redirects",
|
||||||
|
"ordinal": 7,
|
||||||
|
"type_info": "Bool"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "setting_validate_certificates",
|
||||||
|
"ordinal": 8,
|
||||||
|
"type_info": "Bool"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "variables!: sqlx::types::Json<Vec<EnvironmentVariable>>",
|
||||||
|
"ordinal": 9,
|
||||||
|
"type_info": "Text"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"parameters": {
|
||||||
|
"Right": 0
|
||||||
|
},
|
||||||
|
"nullable": [
|
||||||
|
false,
|
||||||
|
false,
|
||||||
|
false,
|
||||||
|
false,
|
||||||
|
false,
|
||||||
|
false,
|
||||||
|
false,
|
||||||
|
false,
|
||||||
|
false,
|
||||||
|
false
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"hash": "8dfbae65ddec905ea3734448cc9f7029b6c78de227c6fa3a85d75d0a7f21e0e9"
|
||||||
|
}
|
||||||
Generated
+12
@@ -0,0 +1,12 @@
|
|||||||
|
{
|
||||||
|
"db_name": "SQLite",
|
||||||
|
"query": "\n INSERT INTO folders (\n id, workspace_id, folder_id, name, sort_priority\n )\n VALUES (?, ?, ?, ?, ?)\n ON CONFLICT (id) DO UPDATE SET\n updated_at = CURRENT_TIMESTAMP,\n name = excluded.name,\n folder_id = excluded.folder_id,\n sort_priority = excluded.sort_priority\n ",
|
||||||
|
"describe": {
|
||||||
|
"columns": [],
|
||||||
|
"parameters": {
|
||||||
|
"Right": 5
|
||||||
|
},
|
||||||
|
"nullable": []
|
||||||
|
},
|
||||||
|
"hash": "9238f94c688d91f42627e5b73c627c514bab4039ab5edadc79b77dfdfd63b208"
|
||||||
|
}
|
||||||
Generated
+80
@@ -0,0 +1,80 @@
|
|||||||
|
{
|
||||||
|
"db_name": "SQLite",
|
||||||
|
"query": "\n SELECT\n id, model, workspace_id, request_id, connection_id, created_at, content, status, error,\n event_type AS \"event_type!: GrpcEventType\",\n metadata AS \"metadata!: sqlx::types::Json<HashMap<String, String>>\"\n FROM grpc_events\n WHERE id = ?\n ",
|
||||||
|
"describe": {
|
||||||
|
"columns": [
|
||||||
|
{
|
||||||
|
"name": "id",
|
||||||
|
"ordinal": 0,
|
||||||
|
"type_info": "Text"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "model",
|
||||||
|
"ordinal": 1,
|
||||||
|
"type_info": "Text"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "workspace_id",
|
||||||
|
"ordinal": 2,
|
||||||
|
"type_info": "Text"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "request_id",
|
||||||
|
"ordinal": 3,
|
||||||
|
"type_info": "Text"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "connection_id",
|
||||||
|
"ordinal": 4,
|
||||||
|
"type_info": "Text"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "created_at",
|
||||||
|
"ordinal": 5,
|
||||||
|
"type_info": "Datetime"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "content",
|
||||||
|
"ordinal": 6,
|
||||||
|
"type_info": "Text"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "status",
|
||||||
|
"ordinal": 7,
|
||||||
|
"type_info": "Int64"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "error",
|
||||||
|
"ordinal": 8,
|
||||||
|
"type_info": "Text"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "event_type!: GrpcEventType",
|
||||||
|
"ordinal": 9,
|
||||||
|
"type_info": "Text"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "metadata!: sqlx::types::Json<HashMap<String, String>>",
|
||||||
|
"ordinal": 10,
|
||||||
|
"type_info": "Text"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"parameters": {
|
||||||
|
"Right": 1
|
||||||
|
},
|
||||||
|
"nullable": [
|
||||||
|
false,
|
||||||
|
false,
|
||||||
|
false,
|
||||||
|
false,
|
||||||
|
false,
|
||||||
|
false,
|
||||||
|
false,
|
||||||
|
true,
|
||||||
|
true,
|
||||||
|
false,
|
||||||
|
false
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"hash": "92d8f003a8f7df692345f2d2fd2504c9222645976e3433e32e190f4ee4bf100d"
|
||||||
|
}
|
||||||
Generated
+12
@@ -0,0 +1,12 @@
|
|||||||
|
{
|
||||||
|
"db_name": "SQLite",
|
||||||
|
"query": "\n DELETE FROM folders\n WHERE id = ?\n ",
|
||||||
|
"describe": {
|
||||||
|
"columns": [],
|
||||||
|
"parameters": {
|
||||||
|
"Right": 1
|
||||||
|
},
|
||||||
|
"nullable": []
|
||||||
|
},
|
||||||
|
"hash": "93aea3881dffb70a82325263740a0bb6477e78f27991ce7456b394e84383acb6"
|
||||||
|
}
|
||||||
Generated
+74
@@ -0,0 +1,74 @@
|
|||||||
|
{
|
||||||
|
"db_name": "SQLite",
|
||||||
|
"query": "\n SELECT\n id, model, created_at, updated_at, name, description, setting_request_timeout,\n setting_follow_redirects, setting_validate_certificates,\n variables AS \"variables!: sqlx::types::Json<Vec<EnvironmentVariable>>\"\n FROM workspaces WHERE id = ?\n ",
|
||||||
|
"describe": {
|
||||||
|
"columns": [
|
||||||
|
{
|
||||||
|
"name": "id",
|
||||||
|
"ordinal": 0,
|
||||||
|
"type_info": "Text"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "model",
|
||||||
|
"ordinal": 1,
|
||||||
|
"type_info": "Text"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "created_at",
|
||||||
|
"ordinal": 2,
|
||||||
|
"type_info": "Datetime"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "updated_at",
|
||||||
|
"ordinal": 3,
|
||||||
|
"type_info": "Datetime"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "name",
|
||||||
|
"ordinal": 4,
|
||||||
|
"type_info": "Text"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "description",
|
||||||
|
"ordinal": 5,
|
||||||
|
"type_info": "Text"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "setting_request_timeout",
|
||||||
|
"ordinal": 6,
|
||||||
|
"type_info": "Int64"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "setting_follow_redirects",
|
||||||
|
"ordinal": 7,
|
||||||
|
"type_info": "Bool"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "setting_validate_certificates",
|
||||||
|
"ordinal": 8,
|
||||||
|
"type_info": "Bool"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "variables!: sqlx::types::Json<Vec<EnvironmentVariable>>",
|
||||||
|
"ordinal": 9,
|
||||||
|
"type_info": "Null"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"parameters": {
|
||||||
|
"Right": 1
|
||||||
|
},
|
||||||
|
"nullable": [
|
||||||
|
false,
|
||||||
|
false,
|
||||||
|
false,
|
||||||
|
false,
|
||||||
|
false,
|
||||||
|
false,
|
||||||
|
false,
|
||||||
|
false,
|
||||||
|
false,
|
||||||
|
false
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"hash": "9ba3f783238b77637ffded4171b2fbb5e5ad0be952a0d832448d65cc5f0effc1"
|
||||||
|
}
|
||||||
Generated
+12
@@ -0,0 +1,12 @@
|
|||||||
|
{
|
||||||
|
"db_name": "SQLite",
|
||||||
|
"query": "\n UPDATE grpc_connections\n SET (elapsed) = (-1)\n WHERE elapsed = 0;\n ",
|
||||||
|
"describe": {
|
||||||
|
"columns": [],
|
||||||
|
"parameters": {
|
||||||
|
"Right": 0
|
||||||
|
},
|
||||||
|
"nullable": []
|
||||||
|
},
|
||||||
|
"hash": "a690a04cd1ebe8c3dbfd0cd98ae4ef093a1696d7b7ecaf694d12e5fafd62b685"
|
||||||
|
}
|
||||||
Generated
+12
@@ -0,0 +1,12 @@
|
|||||||
|
{
|
||||||
|
"db_name": "SQLite",
|
||||||
|
"query": "\n UPDATE http_responses\n SET (elapsed, status_reason) = (-1, 'Cancelled')\n WHERE elapsed = 0;\n ",
|
||||||
|
"describe": {
|
||||||
|
"columns": [],
|
||||||
|
"parameters": {
|
||||||
|
"Right": 0
|
||||||
|
},
|
||||||
|
"nullable": []
|
||||||
|
},
|
||||||
|
"hash": "ac1b4ffbd98b67f0a1a74e3525387d679dd6f44c561d55c7bbea747053e53671"
|
||||||
|
}
|
||||||
Generated
+116
@@ -0,0 +1,116 @@
|
|||||||
|
{
|
||||||
|
"db_name": "SQLite",
|
||||||
|
"query": "\n SELECT\n id, model, workspace_id, request_id, updated_at, created_at, url, status,\n status_reason, content_length, body_path, elapsed, elapsed_headers, error,\n version, remote_addr,\n headers AS \"headers!: sqlx::types::Json<Vec<HttpResponseHeader>>\"\n FROM http_responses\n WHERE request_id = ?\n ORDER BY created_at DESC\n LIMIT ?\n ",
|
||||||
|
"describe": {
|
||||||
|
"columns": [
|
||||||
|
{
|
||||||
|
"name": "id",
|
||||||
|
"ordinal": 0,
|
||||||
|
"type_info": "Text"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "model",
|
||||||
|
"ordinal": 1,
|
||||||
|
"type_info": "Text"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "workspace_id",
|
||||||
|
"ordinal": 2,
|
||||||
|
"type_info": "Text"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "request_id",
|
||||||
|
"ordinal": 3,
|
||||||
|
"type_info": "Text"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "updated_at",
|
||||||
|
"ordinal": 4,
|
||||||
|
"type_info": "Datetime"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "created_at",
|
||||||
|
"ordinal": 5,
|
||||||
|
"type_info": "Datetime"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "url",
|
||||||
|
"ordinal": 6,
|
||||||
|
"type_info": "Text"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "status",
|
||||||
|
"ordinal": 7,
|
||||||
|
"type_info": "Int64"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "status_reason",
|
||||||
|
"ordinal": 8,
|
||||||
|
"type_info": "Text"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "content_length",
|
||||||
|
"ordinal": 9,
|
||||||
|
"type_info": "Int64"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "body_path",
|
||||||
|
"ordinal": 10,
|
||||||
|
"type_info": "Text"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "elapsed",
|
||||||
|
"ordinal": 11,
|
||||||
|
"type_info": "Int64"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "elapsed_headers",
|
||||||
|
"ordinal": 12,
|
||||||
|
"type_info": "Int64"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "error",
|
||||||
|
"ordinal": 13,
|
||||||
|
"type_info": "Text"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "version",
|
||||||
|
"ordinal": 14,
|
||||||
|
"type_info": "Text"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "remote_addr",
|
||||||
|
"ordinal": 15,
|
||||||
|
"type_info": "Text"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "headers!: sqlx::types::Json<Vec<HttpResponseHeader>>",
|
||||||
|
"ordinal": 16,
|
||||||
|
"type_info": "Text"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"parameters": {
|
||||||
|
"Right": 2
|
||||||
|
},
|
||||||
|
"nullable": [
|
||||||
|
false,
|
||||||
|
false,
|
||||||
|
false,
|
||||||
|
false,
|
||||||
|
false,
|
||||||
|
false,
|
||||||
|
false,
|
||||||
|
false,
|
||||||
|
true,
|
||||||
|
true,
|
||||||
|
true,
|
||||||
|
false,
|
||||||
|
false,
|
||||||
|
true,
|
||||||
|
true,
|
||||||
|
true,
|
||||||
|
false
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"hash": "ac38621cd947c3be9ca0d8ea73325fe35c3866d16f6482fc32c23762f112dc83"
|
||||||
|
}
|
||||||
Generated
+62
@@ -0,0 +1,62 @@
|
|||||||
|
{
|
||||||
|
"db_name": "SQLite",
|
||||||
|
"query": "\n SELECT\n id, model, workspace_id, created_at, updated_at, folder_id, name, sort_priority\n FROM folders\n WHERE id = ?\n ",
|
||||||
|
"describe": {
|
||||||
|
"columns": [
|
||||||
|
{
|
||||||
|
"name": "id",
|
||||||
|
"ordinal": 0,
|
||||||
|
"type_info": "Text"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "model",
|
||||||
|
"ordinal": 1,
|
||||||
|
"type_info": "Text"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "workspace_id",
|
||||||
|
"ordinal": 2,
|
||||||
|
"type_info": "Text"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "created_at",
|
||||||
|
"ordinal": 3,
|
||||||
|
"type_info": "Datetime"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "updated_at",
|
||||||
|
"ordinal": 4,
|
||||||
|
"type_info": "Datetime"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "folder_id",
|
||||||
|
"ordinal": 5,
|
||||||
|
"type_info": "Text"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "name",
|
||||||
|
"ordinal": 6,
|
||||||
|
"type_info": "Text"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "sort_priority",
|
||||||
|
"ordinal": 7,
|
||||||
|
"type_info": "Float"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"parameters": {
|
||||||
|
"Right": 1
|
||||||
|
},
|
||||||
|
"nullable": [
|
||||||
|
false,
|
||||||
|
false,
|
||||||
|
false,
|
||||||
|
false,
|
||||||
|
false,
|
||||||
|
true,
|
||||||
|
false,
|
||||||
|
false
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"hash": "ae98a7b35a5cb80a4bcd04faa22545deac2a5e9bfb814b60191f16b98ed49796"
|
||||||
|
}
|
||||||
Generated
+12
@@ -0,0 +1,12 @@
|
|||||||
|
{
|
||||||
|
"db_name": "SQLite",
|
||||||
|
"query": "\n DELETE FROM environments\n WHERE id = ?\n ",
|
||||||
|
"describe": {
|
||||||
|
"columns": [],
|
||||||
|
"parameters": {
|
||||||
|
"Right": 1
|
||||||
|
},
|
||||||
|
"nullable": []
|
||||||
|
},
|
||||||
|
"hash": "aeb0712785a9964d516dc8939bc54aa8206ad852e608b362d014b67a0f21b0ed"
|
||||||
|
}
|
||||||
Generated
+12
@@ -0,0 +1,12 @@
|
|||||||
|
{
|
||||||
|
"db_name": "SQLite",
|
||||||
|
"query": "\n INSERT INTO cookie_jars (\n id, workspace_id, name, cookies\n )\n VALUES (?, ?, ?, ?)\n ON CONFLICT (id) DO UPDATE SET\n updated_at = CURRENT_TIMESTAMP,\n name = excluded.name,\n cookies = excluded.cookies\n ",
|
||||||
|
"describe": {
|
||||||
|
"columns": [],
|
||||||
|
"parameters": {
|
||||||
|
"Right": 4
|
||||||
|
},
|
||||||
|
"nullable": []
|
||||||
|
},
|
||||||
|
"hash": "b3fae40a793a6724dd2286a9ca4bc0a9c000a631ee0d751a9dc4f3e76de3d57c"
|
||||||
|
}
|
||||||
Generated
+12
@@ -0,0 +1,12 @@
|
|||||||
|
{
|
||||||
|
"db_name": "SQLite",
|
||||||
|
"query": "\n DELETE FROM cookie_jars\n WHERE id = ?\n ",
|
||||||
|
"describe": {
|
||||||
|
"columns": [],
|
||||||
|
"parameters": {
|
||||||
|
"Right": 1
|
||||||
|
},
|
||||||
|
"nullable": []
|
||||||
|
},
|
||||||
|
"hash": "b98609f65dd3a6bbd1ea8dc8bed2840a6d5d13fec1bbc0aa61ca4f60de98a09c"
|
||||||
|
}
|
||||||
Generated
+56
@@ -0,0 +1,56 @@
|
|||||||
|
{
|
||||||
|
"db_name": "SQLite",
|
||||||
|
"query": "\n SELECT id, workspace_id, model, created_at, updated_at, name,\n variables AS \"variables!: sqlx::types::Json<Vec<EnvironmentVariable>>\"\n FROM environments\n WHERE workspace_id = ?\n ",
|
||||||
|
"describe": {
|
||||||
|
"columns": [
|
||||||
|
{
|
||||||
|
"name": "id",
|
||||||
|
"ordinal": 0,
|
||||||
|
"type_info": "Text"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "workspace_id",
|
||||||
|
"ordinal": 1,
|
||||||
|
"type_info": "Text"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "model",
|
||||||
|
"ordinal": 2,
|
||||||
|
"type_info": "Text"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "created_at",
|
||||||
|
"ordinal": 3,
|
||||||
|
"type_info": "Datetime"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "updated_at",
|
||||||
|
"ordinal": 4,
|
||||||
|
"type_info": "Datetime"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "name",
|
||||||
|
"ordinal": 5,
|
||||||
|
"type_info": "Text"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "variables!: sqlx::types::Json<Vec<EnvironmentVariable>>",
|
||||||
|
"ordinal": 6,
|
||||||
|
"type_info": "Null"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"parameters": {
|
||||||
|
"Right": 1
|
||||||
|
},
|
||||||
|
"nullable": [
|
||||||
|
false,
|
||||||
|
false,
|
||||||
|
false,
|
||||||
|
false,
|
||||||
|
false,
|
||||||
|
false,
|
||||||
|
false
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"hash": "ba2b34a77723f24f86e4c3c45274dbfec6ca130e16e592f948844c037bdc0593"
|
||||||
|
}
|
||||||
Generated
+92
@@ -0,0 +1,92 @@
|
|||||||
|
{
|
||||||
|
"db_name": "SQLite",
|
||||||
|
"query": "\n SELECT\n id, model, workspace_id, request_id, created_at, updated_at, service,\n method, elapsed, status, error, url,\n trailers AS \"trailers!: sqlx::types::Json<HashMap<String, String>>\"\n FROM grpc_connections\n WHERE id = ?\n ",
|
||||||
|
"describe": {
|
||||||
|
"columns": [
|
||||||
|
{
|
||||||
|
"name": "id",
|
||||||
|
"ordinal": 0,
|
||||||
|
"type_info": "Text"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "model",
|
||||||
|
"ordinal": 1,
|
||||||
|
"type_info": "Text"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "workspace_id",
|
||||||
|
"ordinal": 2,
|
||||||
|
"type_info": "Text"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "request_id",
|
||||||
|
"ordinal": 3,
|
||||||
|
"type_info": "Text"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "created_at",
|
||||||
|
"ordinal": 4,
|
||||||
|
"type_info": "Datetime"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "updated_at",
|
||||||
|
"ordinal": 5,
|
||||||
|
"type_info": "Datetime"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "service",
|
||||||
|
"ordinal": 6,
|
||||||
|
"type_info": "Text"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "method",
|
||||||
|
"ordinal": 7,
|
||||||
|
"type_info": "Text"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "elapsed",
|
||||||
|
"ordinal": 8,
|
||||||
|
"type_info": "Int64"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "status",
|
||||||
|
"ordinal": 9,
|
||||||
|
"type_info": "Int64"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "error",
|
||||||
|
"ordinal": 10,
|
||||||
|
"type_info": "Text"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "url",
|
||||||
|
"ordinal": 11,
|
||||||
|
"type_info": "Text"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "trailers!: sqlx::types::Json<HashMap<String, String>>",
|
||||||
|
"ordinal": 12,
|
||||||
|
"type_info": "Text"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"parameters": {
|
||||||
|
"Right": 1
|
||||||
|
},
|
||||||
|
"nullable": [
|
||||||
|
false,
|
||||||
|
false,
|
||||||
|
false,
|
||||||
|
false,
|
||||||
|
false,
|
||||||
|
false,
|
||||||
|
false,
|
||||||
|
false,
|
||||||
|
false,
|
||||||
|
false,
|
||||||
|
true,
|
||||||
|
false,
|
||||||
|
false
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"hash": "d4b64c466624eb75e0f5bd201ebfb6a73d25eb7c9e09cb9690afdb7fef5fca8b"
|
||||||
|
}
|
||||||
Generated
+116
@@ -0,0 +1,116 @@
|
|||||||
|
{
|
||||||
|
"db_name": "SQLite",
|
||||||
|
"query": "\n SELECT\n id, model, workspace_id, request_id, updated_at, created_at, url, status,\n status_reason, content_length, body_path, elapsed, elapsed_headers, error,\n version, remote_addr,\n headers AS \"headers!: sqlx::types::Json<Vec<HttpResponseHeader>>\"\n FROM http_responses\n WHERE workspace_id = ?\n ORDER BY created_at DESC\n ",
|
||||||
|
"describe": {
|
||||||
|
"columns": [
|
||||||
|
{
|
||||||
|
"name": "id",
|
||||||
|
"ordinal": 0,
|
||||||
|
"type_info": "Text"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "model",
|
||||||
|
"ordinal": 1,
|
||||||
|
"type_info": "Text"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "workspace_id",
|
||||||
|
"ordinal": 2,
|
||||||
|
"type_info": "Text"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "request_id",
|
||||||
|
"ordinal": 3,
|
||||||
|
"type_info": "Text"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "updated_at",
|
||||||
|
"ordinal": 4,
|
||||||
|
"type_info": "Datetime"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "created_at",
|
||||||
|
"ordinal": 5,
|
||||||
|
"type_info": "Datetime"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "url",
|
||||||
|
"ordinal": 6,
|
||||||
|
"type_info": "Text"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "status",
|
||||||
|
"ordinal": 7,
|
||||||
|
"type_info": "Int64"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "status_reason",
|
||||||
|
"ordinal": 8,
|
||||||
|
"type_info": "Text"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "content_length",
|
||||||
|
"ordinal": 9,
|
||||||
|
"type_info": "Int64"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "body_path",
|
||||||
|
"ordinal": 10,
|
||||||
|
"type_info": "Text"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "elapsed",
|
||||||
|
"ordinal": 11,
|
||||||
|
"type_info": "Int64"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "elapsed_headers",
|
||||||
|
"ordinal": 12,
|
||||||
|
"type_info": "Int64"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "error",
|
||||||
|
"ordinal": 13,
|
||||||
|
"type_info": "Text"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "version",
|
||||||
|
"ordinal": 14,
|
||||||
|
"type_info": "Text"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "remote_addr",
|
||||||
|
"ordinal": 15,
|
||||||
|
"type_info": "Text"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "headers!: sqlx::types::Json<Vec<HttpResponseHeader>>",
|
||||||
|
"ordinal": 16,
|
||||||
|
"type_info": "Text"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"parameters": {
|
||||||
|
"Right": 1
|
||||||
|
},
|
||||||
|
"nullable": [
|
||||||
|
false,
|
||||||
|
false,
|
||||||
|
false,
|
||||||
|
false,
|
||||||
|
false,
|
||||||
|
false,
|
||||||
|
false,
|
||||||
|
false,
|
||||||
|
true,
|
||||||
|
true,
|
||||||
|
true,
|
||||||
|
false,
|
||||||
|
false,
|
||||||
|
true,
|
||||||
|
true,
|
||||||
|
true,
|
||||||
|
false
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"hash": "d5e087caa163a0c7bfbbadf07eccb80105501cf5baab706aa6792dfe90af8fc9"
|
||||||
|
}
|
||||||
Generated
+12
@@ -0,0 +1,12 @@
|
|||||||
|
{
|
||||||
|
"db_name": "SQLite",
|
||||||
|
"query": "\n INSERT INTO key_values (namespace, key, value)\n VALUES (?, ?, ?) ON CONFLICT DO UPDATE SET\n updated_at = CURRENT_TIMESTAMP,\n value = excluded.value\n ",
|
||||||
|
"describe": {
|
||||||
|
"columns": [],
|
||||||
|
"parameters": {
|
||||||
|
"Right": 3
|
||||||
|
},
|
||||||
|
"nullable": []
|
||||||
|
},
|
||||||
|
"hash": "d80c09497771e3641022e73ec6c6a87e73a551f88a948a5445d754922b82b50b"
|
||||||
|
}
|
||||||
Generated
+98
@@ -0,0 +1,98 @@
|
|||||||
|
{
|
||||||
|
"db_name": "SQLite",
|
||||||
|
"query": "\n SELECT\n id, model, created_at, updated_at, theme, appearance,\n theme_dark, theme_light, update_channel,\n interface_font_size, interface_scale, editor_font_size, editor_soft_wrap,\n open_workspace_new_window\n FROM settings\n WHERE id = 'default'\n ",
|
||||||
|
"describe": {
|
||||||
|
"columns": [
|
||||||
|
{
|
||||||
|
"name": "id",
|
||||||
|
"ordinal": 0,
|
||||||
|
"type_info": "Text"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "model",
|
||||||
|
"ordinal": 1,
|
||||||
|
"type_info": "Text"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "created_at",
|
||||||
|
"ordinal": 2,
|
||||||
|
"type_info": "Datetime"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "updated_at",
|
||||||
|
"ordinal": 3,
|
||||||
|
"type_info": "Datetime"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "theme",
|
||||||
|
"ordinal": 4,
|
||||||
|
"type_info": "Text"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "appearance",
|
||||||
|
"ordinal": 5,
|
||||||
|
"type_info": "Text"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "theme_dark",
|
||||||
|
"ordinal": 6,
|
||||||
|
"type_info": "Text"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "theme_light",
|
||||||
|
"ordinal": 7,
|
||||||
|
"type_info": "Text"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "update_channel",
|
||||||
|
"ordinal": 8,
|
||||||
|
"type_info": "Text"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "interface_font_size",
|
||||||
|
"ordinal": 9,
|
||||||
|
"type_info": "Int64"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "interface_scale",
|
||||||
|
"ordinal": 10,
|
||||||
|
"type_info": "Int64"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "editor_font_size",
|
||||||
|
"ordinal": 11,
|
||||||
|
"type_info": "Int64"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "editor_soft_wrap",
|
||||||
|
"ordinal": 12,
|
||||||
|
"type_info": "Bool"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "open_workspace_new_window",
|
||||||
|
"ordinal": 13,
|
||||||
|
"type_info": "Bool"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"parameters": {
|
||||||
|
"Right": 0
|
||||||
|
},
|
||||||
|
"nullable": [
|
||||||
|
false,
|
||||||
|
false,
|
||||||
|
false,
|
||||||
|
false,
|
||||||
|
false,
|
||||||
|
false,
|
||||||
|
false,
|
||||||
|
false,
|
||||||
|
false,
|
||||||
|
false,
|
||||||
|
false,
|
||||||
|
false,
|
||||||
|
false,
|
||||||
|
true
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"hash": "daa61066517df649e7c80a8ce407839ad502e8e5e43aa8c02e049865acbbae75"
|
||||||
|
}
|
||||||
Generated
+104
@@ -0,0 +1,104 @@
|
|||||||
|
{
|
||||||
|
"db_name": "SQLite",
|
||||||
|
"query": "\n SELECT\n id, model, workspace_id, folder_id, created_at, updated_at, name, sort_priority,\n url, service, method, message, authentication_type,\n authentication AS \"authentication!: Json<HashMap<String, JsonValue>>\",\n metadata AS \"metadata!: sqlx::types::Json<Vec<GrpcMetadataEntry>>\"\n FROM grpc_requests\n WHERE id = ?\n ",
|
||||||
|
"describe": {
|
||||||
|
"columns": [
|
||||||
|
{
|
||||||
|
"name": "id",
|
||||||
|
"ordinal": 0,
|
||||||
|
"type_info": "Text"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "model",
|
||||||
|
"ordinal": 1,
|
||||||
|
"type_info": "Text"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "workspace_id",
|
||||||
|
"ordinal": 2,
|
||||||
|
"type_info": "Text"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "folder_id",
|
||||||
|
"ordinal": 3,
|
||||||
|
"type_info": "Text"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "created_at",
|
||||||
|
"ordinal": 4,
|
||||||
|
"type_info": "Datetime"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "updated_at",
|
||||||
|
"ordinal": 5,
|
||||||
|
"type_info": "Datetime"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "name",
|
||||||
|
"ordinal": 6,
|
||||||
|
"type_info": "Text"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "sort_priority",
|
||||||
|
"ordinal": 7,
|
||||||
|
"type_info": "Float"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "url",
|
||||||
|
"ordinal": 8,
|
||||||
|
"type_info": "Text"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "service",
|
||||||
|
"ordinal": 9,
|
||||||
|
"type_info": "Text"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "method",
|
||||||
|
"ordinal": 10,
|
||||||
|
"type_info": "Text"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "message",
|
||||||
|
"ordinal": 11,
|
||||||
|
"type_info": "Text"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "authentication_type",
|
||||||
|
"ordinal": 12,
|
||||||
|
"type_info": "Text"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "authentication!: Json<HashMap<String, JsonValue>>",
|
||||||
|
"ordinal": 13,
|
||||||
|
"type_info": "Text"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "metadata!: sqlx::types::Json<Vec<GrpcMetadataEntry>>",
|
||||||
|
"ordinal": 14,
|
||||||
|
"type_info": "Text"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"parameters": {
|
||||||
|
"Right": 1
|
||||||
|
},
|
||||||
|
"nullable": [
|
||||||
|
false,
|
||||||
|
false,
|
||||||
|
false,
|
||||||
|
true,
|
||||||
|
false,
|
||||||
|
false,
|
||||||
|
false,
|
||||||
|
false,
|
||||||
|
false,
|
||||||
|
true,
|
||||||
|
true,
|
||||||
|
false,
|
||||||
|
true,
|
||||||
|
false,
|
||||||
|
false
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"hash": "e1cdba43bd938772631263966a9bee263923c387f4864917f36a04043bec4857"
|
||||||
|
}
|
||||||
Generated
+110
@@ -0,0 +1,110 @@
|
|||||||
|
{
|
||||||
|
"db_name": "SQLite",
|
||||||
|
"query": "\n SELECT\n id, model, workspace_id, folder_id, created_at, updated_at, name, url,\n url_parameters AS \"url_parameters!: sqlx::types::Json<Vec<HttpUrlParameter>>\",\n method, body_type, authentication_type, sort_priority,\n body AS \"body!: Json<HashMap<String, JsonValue>>\",\n authentication AS \"authentication!: Json<HashMap<String, JsonValue>>\",\n headers AS \"headers!: sqlx::types::Json<Vec<HttpRequestHeader>>\"\n FROM http_requests\n WHERE workspace_id = ?\n ",
|
||||||
|
"describe": {
|
||||||
|
"columns": [
|
||||||
|
{
|
||||||
|
"name": "id",
|
||||||
|
"ordinal": 0,
|
||||||
|
"type_info": "Text"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "model",
|
||||||
|
"ordinal": 1,
|
||||||
|
"type_info": "Text"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "workspace_id",
|
||||||
|
"ordinal": 2,
|
||||||
|
"type_info": "Text"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "folder_id",
|
||||||
|
"ordinal": 3,
|
||||||
|
"type_info": "Text"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "created_at",
|
||||||
|
"ordinal": 4,
|
||||||
|
"type_info": "Datetime"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "updated_at",
|
||||||
|
"ordinal": 5,
|
||||||
|
"type_info": "Datetime"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "name",
|
||||||
|
"ordinal": 6,
|
||||||
|
"type_info": "Text"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "url",
|
||||||
|
"ordinal": 7,
|
||||||
|
"type_info": "Text"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "url_parameters!: sqlx::types::Json<Vec<HttpUrlParameter>>",
|
||||||
|
"ordinal": 8,
|
||||||
|
"type_info": "Text"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "method",
|
||||||
|
"ordinal": 9,
|
||||||
|
"type_info": "Text"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "body_type",
|
||||||
|
"ordinal": 10,
|
||||||
|
"type_info": "Text"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "authentication_type",
|
||||||
|
"ordinal": 11,
|
||||||
|
"type_info": "Text"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "sort_priority",
|
||||||
|
"ordinal": 12,
|
||||||
|
"type_info": "Float"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "body!: Json<HashMap<String, JsonValue>>",
|
||||||
|
"ordinal": 13,
|
||||||
|
"type_info": "Text"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "authentication!: Json<HashMap<String, JsonValue>>",
|
||||||
|
"ordinal": 14,
|
||||||
|
"type_info": "Text"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "headers!: sqlx::types::Json<Vec<HttpRequestHeader>>",
|
||||||
|
"ordinal": 15,
|
||||||
|
"type_info": "Text"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"parameters": {
|
||||||
|
"Right": 1
|
||||||
|
},
|
||||||
|
"nullable": [
|
||||||
|
false,
|
||||||
|
false,
|
||||||
|
false,
|
||||||
|
true,
|
||||||
|
false,
|
||||||
|
false,
|
||||||
|
false,
|
||||||
|
false,
|
||||||
|
false,
|
||||||
|
false,
|
||||||
|
true,
|
||||||
|
true,
|
||||||
|
false,
|
||||||
|
false,
|
||||||
|
false,
|
||||||
|
false
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"hash": "e61c0dddb3e86d271cb9399faa4e4443342796cb72bdd43a821fae2994ae8e2f"
|
||||||
|
}
|
||||||
Generated
+12
@@ -0,0 +1,12 @@
|
|||||||
|
{
|
||||||
|
"db_name": "SQLite",
|
||||||
|
"query": "\n UPDATE http_responses SET (\n elapsed, elapsed_headers, url, status, status_reason, content_length, body_path,\n error, headers, version, remote_addr, updated_at\n ) = (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, CURRENT_TIMESTAMP) WHERE id = ?;\n ",
|
||||||
|
"describe": {
|
||||||
|
"columns": [],
|
||||||
|
"parameters": {
|
||||||
|
"Right": 12
|
||||||
|
},
|
||||||
|
"nullable": []
|
||||||
|
},
|
||||||
|
"hash": "e7124f5570076bfd65985744f48d8e12cf29d6d243fffdd62ade2ab70c7bddda"
|
||||||
|
}
|
||||||
Generated
+56
@@ -0,0 +1,56 @@
|
|||||||
|
{
|
||||||
|
"db_name": "SQLite",
|
||||||
|
"query": "\n SELECT\n id, model, created_at, updated_at, workspace_id, name,\n cookies AS \"cookies!: sqlx::types::Json<Vec<JsonValue>>\"\n FROM cookie_jars WHERE id = ?\n ",
|
||||||
|
"describe": {
|
||||||
|
"columns": [
|
||||||
|
{
|
||||||
|
"name": "id",
|
||||||
|
"ordinal": 0,
|
||||||
|
"type_info": "Text"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "model",
|
||||||
|
"ordinal": 1,
|
||||||
|
"type_info": "Text"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "created_at",
|
||||||
|
"ordinal": 2,
|
||||||
|
"type_info": "Datetime"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "updated_at",
|
||||||
|
"ordinal": 3,
|
||||||
|
"type_info": "Datetime"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "workspace_id",
|
||||||
|
"ordinal": 4,
|
||||||
|
"type_info": "Text"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "name",
|
||||||
|
"ordinal": 5,
|
||||||
|
"type_info": "Text"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "cookies!: sqlx::types::Json<Vec<JsonValue>>",
|
||||||
|
"ordinal": 6,
|
||||||
|
"type_info": "Text"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"parameters": {
|
||||||
|
"Right": 1
|
||||||
|
},
|
||||||
|
"nullable": [
|
||||||
|
false,
|
||||||
|
false,
|
||||||
|
false,
|
||||||
|
false,
|
||||||
|
false,
|
||||||
|
false,
|
||||||
|
false
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"hash": "f5f20f3b37d932617499a0da50997edad59e4f5998b15c50ed6eae2e97064068"
|
||||||
|
}
|
||||||
Generated
+12
@@ -0,0 +1,12 @@
|
|||||||
|
{
|
||||||
|
"db_name": "SQLite",
|
||||||
|
"query": "\n DELETE FROM grpc_requests\n WHERE id = ?\n ",
|
||||||
|
"describe": {
|
||||||
|
"columns": [],
|
||||||
|
"parameters": {
|
||||||
|
"Right": 1
|
||||||
|
},
|
||||||
|
"nullable": []
|
||||||
|
},
|
||||||
|
"hash": "fe0652396bc30d926cf99083651c1cbd668bcf00ebe1a5f36616700c84972b39"
|
||||||
|
}
|
||||||
Generated
+4773
-1715
File diff suppressed because it is too large
Load Diff
+50
-26
@@ -1,34 +1,58 @@
|
|||||||
|
workspace = { members = ["grpc", "templates", "tauri-plugin-plugin-runtime"] }
|
||||||
|
|
||||||
[package]
|
[package]
|
||||||
name = "tauri-app"
|
name = "yaak-app"
|
||||||
version = "0.0.0"
|
version = "0.0.0"
|
||||||
description = "A Tauri App"
|
|
||||||
authors = ["you"]
|
|
||||||
license = ""
|
|
||||||
repository = ""
|
|
||||||
edition = "2021"
|
edition = "2021"
|
||||||
|
|
||||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
# Produce a library for mobile support
|
||||||
|
[lib]
|
||||||
|
name = "tauri_app_lib"
|
||||||
|
crate-type = ["staticlib", "cdylib", "lib"]
|
||||||
|
|
||||||
|
[profile.release]
|
||||||
|
strip = true # Automatically strip symbols from the binary.
|
||||||
|
|
||||||
[build-dependencies]
|
[build-dependencies]
|
||||||
tauri-build = { version = "1.2", features = [] }
|
tauri-build = { version = "2.0.0-beta", features = [] }
|
||||||
|
|
||||||
|
[target.'cfg(target_os = "macos")'.dependencies]
|
||||||
|
objc = "0.2.7"
|
||||||
|
cocoa = "0.25.0"
|
||||||
|
|
||||||
|
[target.'cfg(target_os = "linux")'.dependencies]
|
||||||
|
openssl-sys = { version = "0.9", features = ["vendored"] } # For Ubuntu installation to work
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
serde_json = { version = "1.0" }
|
grpc = { path = "./grpc" }
|
||||||
serde = { version = "1.0", features = ["derive"] }
|
templates = { path = "./templates" }
|
||||||
tauri = { version = "1.2", features = ["config-toml", "devtools", "shell-open", "system-tray", "window-start-dragging"] }
|
plugin_runtime = { path = "tauri-plugin-plugin-runtime" }
|
||||||
http = { version = "0.2.8" }
|
anyhow = "1.0.86"
|
||||||
reqwest = { version = "0.11.14", features = ["json"] }
|
base64 = "0.22.0"
|
||||||
tokio = { version = "1.25.0", features = ["full"] }
|
chrono = { version = "0.4.31", features = ["serde"] }
|
||||||
futures = { version = "0.3.26" }
|
datetime = "0.5.2"
|
||||||
deno_core = { version = "0.171.0" }
|
hex_color = "3.0.0"
|
||||||
deno_ast = { version = "0.24.0", features = ["transpiling"] }
|
http = "1"
|
||||||
objc = { version = "0.2.7" }
|
log = "0.4.21"
|
||||||
cocoa = { version = "0.24.1" }
|
rand = "0.8.5"
|
||||||
|
regex = "1.10.2"
|
||||||
[features]
|
reqwest = { version = "0.12.4", features = ["multipart", "cookies", "gzip", "brotli", "deflate", "json", "native-tls-alpn"] }
|
||||||
# by default Tauri runs in production mode
|
reqwest_cookie_store = "0.8.0"
|
||||||
# when `tauri dev` runs it is executed with `cargo run --no-default-features` if `devPath` is an URL
|
serde = { version = "1.0.198", features = ["derive"] }
|
||||||
default = ["custom-protocol"]
|
serde_json = { version = "1.0.116", features = ["raw_value"] }
|
||||||
# this feature is used used for production builds where `devPath` points to the filesystem
|
serde_yaml = "0.9.34"
|
||||||
# DO NOT remove this
|
sqlx = { version = "0.7.4", features = ["sqlite", "runtime-tokio-rustls", "json", "chrono", "time"] }
|
||||||
custom-protocol = ["tauri/custom-protocol"]
|
tauri = { version = "2.0.0-beta", features = ["devtools", "protocol-asset"] }
|
||||||
|
tauri-plugin-clipboard-manager = "2.1.0-beta"
|
||||||
|
tauri-plugin-dialog = "2.0.0-beta"
|
||||||
|
tauri-plugin-fs = "2.0.0-beta"
|
||||||
|
tauri-plugin-log = { version = "2.0.0-beta", features = ["colored"] }
|
||||||
|
tauri-plugin-os = "2.0.0-beta"
|
||||||
|
tauri-plugin-shell = "2.0.0-beta"
|
||||||
|
tauri-plugin-updater = "2.0.0-beta"
|
||||||
|
tauri-plugin-window-state = "2.0.0-beta"
|
||||||
|
tokio = { version = "1.36.0", features = ["sync"] }
|
||||||
|
tokio-stream = "0.1.15"
|
||||||
|
uuid = "1.7.0"
|
||||||
|
thiserror = "1.0.61"
|
||||||
|
mime_guess = "2.0.5"
|
||||||
|
|||||||
+1
-1
@@ -1,3 +1,3 @@
|
|||||||
fn main() {
|
fn main() {
|
||||||
tauri_build::build()
|
tauri_build::build()
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,46 @@
|
|||||||
|
{
|
||||||
|
"$schema": "../gen/schemas/capabilities.json",
|
||||||
|
"identifier": "main",
|
||||||
|
"description": "Main permissions",
|
||||||
|
"local": true,
|
||||||
|
"windows": [
|
||||||
|
"*"
|
||||||
|
],
|
||||||
|
"permissions": [
|
||||||
|
"os:allow-os-type",
|
||||||
|
"event:allow-emit",
|
||||||
|
"clipboard-manager:allow-write-text",
|
||||||
|
"clipboard-manager:allow-read-text",
|
||||||
|
"dialog:allow-open",
|
||||||
|
"dialog:allow-save",
|
||||||
|
"event:allow-listen",
|
||||||
|
"event:allow-unlisten",
|
||||||
|
"fs:allow-read-file",
|
||||||
|
"fs:allow-read-text-file",
|
||||||
|
{
|
||||||
|
"identifier": "fs:scope",
|
||||||
|
"allow": [
|
||||||
|
{
|
||||||
|
"path": "$APPDATA"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"path": "$APPDATA/**"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"shell:allow-open",
|
||||||
|
"webview:allow-set-webview-zoom",
|
||||||
|
"window:allow-close",
|
||||||
|
"window:allow-is-fullscreen",
|
||||||
|
"window:allow-maximize",
|
||||||
|
"window:allow-minimize",
|
||||||
|
"window:allow-toggle-maximize",
|
||||||
|
"window:allow-set-decorations",
|
||||||
|
"window:allow-set-title",
|
||||||
|
"window:allow-start-dragging",
|
||||||
|
"window:allow-unmaximize",
|
||||||
|
"window:allow-theme",
|
||||||
|
"clipboard-manager:allow-read-text",
|
||||||
|
"clipboard-manager:allow-write-text"
|
||||||
|
]
|
||||||
|
}
|
||||||
File diff suppressed because one or more lines are too long
@@ -0,0 +1 @@
|
|||||||
|
{"main":{"identifier":"main","description":"Main permissions","local":true,"windows":["*"],"permissions":["os:allow-os-type","event:allow-emit","clipboard-manager:allow-write-text","clipboard-manager:allow-read-text","dialog:allow-open","dialog:allow-save","event:allow-listen","event:allow-unlisten","fs:allow-read-file","fs:allow-read-text-file",{"identifier":"fs:scope","allow":[{"path":"$APPDATA"},{"path":"$APPDATA/**"}]},"shell:allow-open","webview:allow-set-webview-zoom","window:allow-close","window:allow-is-fullscreen","window:allow-maximize","window:allow-minimize","window:allow-toggle-maximize","window:allow-set-decorations","window:allow-set-title","window:allow-start-dragging","window:allow-unmaximize","window:allow-theme","clipboard-manager:allow-read-text","clipboard-manager:allow-write-text"]}}
|
||||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,24 @@
|
|||||||
|
[package]
|
||||||
|
name = "grpc"
|
||||||
|
version = "0.1.0"
|
||||||
|
edition = "2021"
|
||||||
|
|
||||||
|
[dependencies]
|
||||||
|
tonic = "0.10.2"
|
||||||
|
prost = "0.12"
|
||||||
|
tokio = { version = "1.0", features = ["macros", "rt-multi-thread", "fs"] }
|
||||||
|
tonic-reflection = "0.10.2"
|
||||||
|
tokio-stream = "0.1.14"
|
||||||
|
prost-types = "0.12.3"
|
||||||
|
serde = { version = "1.0.196", features = ["derive"] }
|
||||||
|
serde_json = "1.0.113"
|
||||||
|
prost-reflect = { version = "0.12.0", features = ["serde", "derive"] }
|
||||||
|
log = "0.4.20"
|
||||||
|
anyhow = "1.0.79"
|
||||||
|
hyper = { version = "0.14" }
|
||||||
|
hyper-rustls = { version = "0.24.0", features = ["http2"] }
|
||||||
|
uuid = { version = "1.7.0", features = ["v4"] }
|
||||||
|
tauri = { version = "2.0.0-beta" }
|
||||||
|
tauri-plugin-shell = "2.0.0-beta"
|
||||||
|
md5 = "0.7.0"
|
||||||
|
dunce = "1.0.4"
|
||||||
@@ -0,0 +1,52 @@
|
|||||||
|
use prost_reflect::prost::Message;
|
||||||
|
use prost_reflect::{DynamicMessage, MethodDescriptor};
|
||||||
|
use tonic::codec::{Codec, DecodeBuf, Decoder, EncodeBuf, Encoder};
|
||||||
|
use tonic::Status;
|
||||||
|
|
||||||
|
#[derive(Clone)]
|
||||||
|
pub struct DynamicCodec(MethodDescriptor);
|
||||||
|
|
||||||
|
impl DynamicCodec {
|
||||||
|
#[allow(dead_code)]
|
||||||
|
pub fn new(md: MethodDescriptor) -> Self {
|
||||||
|
Self(md)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Codec for DynamicCodec {
|
||||||
|
type Encode = DynamicMessage;
|
||||||
|
type Decode = DynamicMessage;
|
||||||
|
type Encoder = Self;
|
||||||
|
type Decoder = Self;
|
||||||
|
|
||||||
|
fn encoder(&mut self) -> Self::Encoder {
|
||||||
|
self.clone()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn decoder(&mut self) -> Self::Decoder {
|
||||||
|
self.clone()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Encoder for DynamicCodec {
|
||||||
|
type Item = DynamicMessage;
|
||||||
|
type Error = Status;
|
||||||
|
|
||||||
|
fn encode(&mut self, item: Self::Item, dst: &mut EncodeBuf<'_>) -> Result<(), Self::Error> {
|
||||||
|
item.encode(dst)
|
||||||
|
.expect("buffer is too small to decode this message");
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Decoder for DynamicCodec {
|
||||||
|
type Item = DynamicMessage;
|
||||||
|
type Error = Status;
|
||||||
|
|
||||||
|
fn decode(&mut self, src: &mut DecodeBuf<'_>) -> Result<Option<Self::Item>, Self::Error> {
|
||||||
|
let mut msg = DynamicMessage::new(self.0.output());
|
||||||
|
msg.merge(src)
|
||||||
|
.map_err(|err| Status::internal(err.to_string()))?;
|
||||||
|
Ok(Some(msg))
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,179 @@
|
|||||||
|
use prost_reflect::{DescriptorPool, MessageDescriptor};
|
||||||
|
use prost_types::field_descriptor_proto;
|
||||||
|
use serde::{Deserialize, Serialize};
|
||||||
|
use std::collections::HashMap;
|
||||||
|
|
||||||
|
#[derive(Default, Serialize, Deserialize)]
|
||||||
|
#[serde(default, rename_all = "camelCase")]
|
||||||
|
pub struct JsonSchemaEntry {
|
||||||
|
#[serde(skip_serializing_if = "Option::is_none")]
|
||||||
|
title: Option<String>,
|
||||||
|
|
||||||
|
#[serde(rename = "type")]
|
||||||
|
type_: JsonType,
|
||||||
|
|
||||||
|
#[serde(skip_serializing_if = "Option::is_none")]
|
||||||
|
description: Option<String>,
|
||||||
|
|
||||||
|
#[serde(skip_serializing_if = "Option::is_none")]
|
||||||
|
properties: Option<HashMap<String, JsonSchemaEntry>>,
|
||||||
|
|
||||||
|
#[serde(rename = "enum", skip_serializing_if = "Option::is_none")]
|
||||||
|
enum_: Option<Vec<String>>,
|
||||||
|
|
||||||
|
/// Don't allow any other properties in the object
|
||||||
|
additional_properties: bool,
|
||||||
|
|
||||||
|
/// Set all properties to required
|
||||||
|
#[serde(skip_serializing_if = "Option::is_none")]
|
||||||
|
required: Option<Vec<String>>,
|
||||||
|
|
||||||
|
#[serde(skip_serializing_if = "Option::is_none")]
|
||||||
|
items: Option<Box<JsonSchemaEntry>>,
|
||||||
|
}
|
||||||
|
|
||||||
|
enum JsonType {
|
||||||
|
String,
|
||||||
|
Number,
|
||||||
|
Object,
|
||||||
|
Array,
|
||||||
|
Boolean,
|
||||||
|
Null,
|
||||||
|
_UNKNOWN,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Default for JsonType {
|
||||||
|
fn default() -> Self {
|
||||||
|
JsonType::_UNKNOWN
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl serde::Serialize for JsonType {
|
||||||
|
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
|
||||||
|
where
|
||||||
|
S: serde::Serializer,
|
||||||
|
{
|
||||||
|
match self {
|
||||||
|
JsonType::String => serializer.serialize_str("string"),
|
||||||
|
JsonType::Number => serializer.serialize_str("number"),
|
||||||
|
JsonType::Object => serializer.serialize_str("object"),
|
||||||
|
JsonType::Array => serializer.serialize_str("array"),
|
||||||
|
JsonType::Boolean => serializer.serialize_str("boolean"),
|
||||||
|
JsonType::Null => serializer.serialize_str("null"),
|
||||||
|
JsonType::_UNKNOWN => serializer.serialize_str("unknown"),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'de> serde::Deserialize<'de> for JsonType {
|
||||||
|
fn deserialize<D>(deserializer: D) -> Result<JsonType, D::Error>
|
||||||
|
where
|
||||||
|
D: serde::Deserializer<'de>,
|
||||||
|
{
|
||||||
|
let s = String::deserialize(deserializer)?;
|
||||||
|
match s.as_str() {
|
||||||
|
"string" => Ok(JsonType::String),
|
||||||
|
"number" => Ok(JsonType::Number),
|
||||||
|
"object" => Ok(JsonType::Object),
|
||||||
|
"array" => Ok(JsonType::Array),
|
||||||
|
"boolean" => Ok(JsonType::Boolean),
|
||||||
|
"null" => Ok(JsonType::Null),
|
||||||
|
_ => Ok(JsonType::_UNKNOWN),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn message_to_json_schema(
|
||||||
|
pool: &DescriptorPool,
|
||||||
|
message: MessageDescriptor,
|
||||||
|
) -> JsonSchemaEntry {
|
||||||
|
let mut schema = JsonSchemaEntry {
|
||||||
|
title: Some(message.name().to_string()),
|
||||||
|
type_: JsonType::Object, // Messages are objects
|
||||||
|
..Default::default()
|
||||||
|
};
|
||||||
|
|
||||||
|
let mut properties = HashMap::new();
|
||||||
|
message.fields().for_each(|f| match f.kind() {
|
||||||
|
prost_reflect::Kind::Message(m) => {
|
||||||
|
properties.insert(f.name().to_string(), message_to_json_schema(pool, m));
|
||||||
|
}
|
||||||
|
prost_reflect::Kind::Enum(e) => {
|
||||||
|
properties.insert(
|
||||||
|
f.name().to_string(),
|
||||||
|
JsonSchemaEntry {
|
||||||
|
type_: map_proto_type_to_json_type(f.field_descriptor_proto().r#type()),
|
||||||
|
enum_: Some(e.values().map(|v| v.name().to_string()).collect::<Vec<_>>()),
|
||||||
|
..Default::default()
|
||||||
|
},
|
||||||
|
);
|
||||||
|
}
|
||||||
|
_ => {
|
||||||
|
// TODO: Handle repeated label
|
||||||
|
match f.field_descriptor_proto().label() {
|
||||||
|
field_descriptor_proto::Label::Repeated => {
|
||||||
|
// TODO: Handle more complex repeated types. This just handles primitives for now
|
||||||
|
properties.insert(
|
||||||
|
f.name().to_string(),
|
||||||
|
JsonSchemaEntry {
|
||||||
|
type_: JsonType::Array,
|
||||||
|
items: Some(Box::new(JsonSchemaEntry {
|
||||||
|
type_: map_proto_type_to_json_type(
|
||||||
|
f.field_descriptor_proto().r#type(),
|
||||||
|
),
|
||||||
|
..Default::default()
|
||||||
|
})),
|
||||||
|
..Default::default()
|
||||||
|
},
|
||||||
|
);
|
||||||
|
}
|
||||||
|
_ => {
|
||||||
|
// Regular JSON field
|
||||||
|
properties.insert(
|
||||||
|
f.name().to_string(),
|
||||||
|
JsonSchemaEntry {
|
||||||
|
type_: map_proto_type_to_json_type(f.field_descriptor_proto().r#type()),
|
||||||
|
..Default::default()
|
||||||
|
},
|
||||||
|
);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
schema.properties = Some(properties);
|
||||||
|
|
||||||
|
// All proto 3 fields are optional, so maybe we could
|
||||||
|
// make this a setting?
|
||||||
|
// schema.required = Some(
|
||||||
|
// message
|
||||||
|
// .fields()
|
||||||
|
// .map(|f| f.name().to_string())
|
||||||
|
// .collect::<Vec<_>>(),
|
||||||
|
// );
|
||||||
|
|
||||||
|
schema
|
||||||
|
}
|
||||||
|
|
||||||
|
fn map_proto_type_to_json_type(proto_type: field_descriptor_proto::Type) -> JsonType {
|
||||||
|
match proto_type {
|
||||||
|
field_descriptor_proto::Type::Double => JsonType::Number,
|
||||||
|
field_descriptor_proto::Type::Float => JsonType::Number,
|
||||||
|
field_descriptor_proto::Type::Int64 => JsonType::Number,
|
||||||
|
field_descriptor_proto::Type::Uint64 => JsonType::Number,
|
||||||
|
field_descriptor_proto::Type::Int32 => JsonType::Number,
|
||||||
|
field_descriptor_proto::Type::Fixed64 => JsonType::Number,
|
||||||
|
field_descriptor_proto::Type::Fixed32 => JsonType::Number,
|
||||||
|
field_descriptor_proto::Type::Bool => JsonType::Boolean,
|
||||||
|
field_descriptor_proto::Type::String => JsonType::String,
|
||||||
|
field_descriptor_proto::Type::Group => JsonType::_UNKNOWN,
|
||||||
|
field_descriptor_proto::Type::Message => JsonType::Object,
|
||||||
|
field_descriptor_proto::Type::Bytes => JsonType::String,
|
||||||
|
field_descriptor_proto::Type::Uint32 => JsonType::Number,
|
||||||
|
field_descriptor_proto::Type::Enum => JsonType::String,
|
||||||
|
field_descriptor_proto::Type::Sfixed32 => JsonType::Number,
|
||||||
|
field_descriptor_proto::Type::Sfixed64 => JsonType::Number,
|
||||||
|
field_descriptor_proto::Type::Sint32 => JsonType::Number,
|
||||||
|
field_descriptor_proto::Type::Sint64 => JsonType::Number,
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,52 @@
|
|||||||
|
use prost_reflect::{DynamicMessage, MethodDescriptor, SerializeOptions};
|
||||||
|
use serde::{Deserialize, Serialize};
|
||||||
|
use serde_json::Deserializer;
|
||||||
|
|
||||||
|
mod codec;
|
||||||
|
mod json_schema;
|
||||||
|
pub mod manager;
|
||||||
|
mod proto;
|
||||||
|
|
||||||
|
pub use tonic::metadata::*;
|
||||||
|
pub use tonic::Code;
|
||||||
|
|
||||||
|
pub fn serialize_options() -> SerializeOptions {
|
||||||
|
SerializeOptions::new().skip_default_fields(false)
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Serialize, Deserialize, Debug, Default)]
|
||||||
|
#[serde(default, rename_all = "camelCase")]
|
||||||
|
pub struct ServiceDefinition {
|
||||||
|
pub name: String,
|
||||||
|
pub methods: Vec<MethodDefinition>,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Serialize, Deserialize, Debug, Default)]
|
||||||
|
#[serde(default, rename_all = "camelCase")]
|
||||||
|
pub struct MethodDefinition {
|
||||||
|
pub name: String,
|
||||||
|
pub schema: String,
|
||||||
|
pub client_streaming: bool,
|
||||||
|
pub server_streaming: bool,
|
||||||
|
}
|
||||||
|
|
||||||
|
static SERIALIZE_OPTIONS: &'static SerializeOptions = &SerializeOptions::new()
|
||||||
|
.skip_default_fields(false)
|
||||||
|
.stringify_64_bit_integers(false);
|
||||||
|
|
||||||
|
pub fn serialize_message(msg: &DynamicMessage) -> Result<String, String> {
|
||||||
|
let mut buf = Vec::new();
|
||||||
|
let mut se = serde_json::Serializer::pretty(&mut buf);
|
||||||
|
msg.serialize_with_options(&mut se, SERIALIZE_OPTIONS)
|
||||||
|
.map_err(|e| e.to_string())?;
|
||||||
|
let s = String::from_utf8(buf).expect("serde_json to emit valid utf8");
|
||||||
|
Ok(s)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn deserialize_message(msg: &str, method: MethodDescriptor) -> Result<DynamicMessage, String> {
|
||||||
|
let mut deserializer = Deserializer::from_str(&msg);
|
||||||
|
let req_message = DynamicMessage::deserialize(method.input(), &mut deserializer)
|
||||||
|
.map_err(|e| e.to_string())?;
|
||||||
|
deserializer.end().map_err(|e| e.to_string())?;
|
||||||
|
Ok(req_message)
|
||||||
|
}
|
||||||
@@ -0,0 +1,304 @@
|
|||||||
|
use std::collections::HashMap;
|
||||||
|
use std::path::PathBuf;
|
||||||
|
use std::str::FromStr;
|
||||||
|
|
||||||
|
use hyper::client::HttpConnector;
|
||||||
|
use hyper::Client;
|
||||||
|
use hyper_rustls::HttpsConnector;
|
||||||
|
pub use prost_reflect::DynamicMessage;
|
||||||
|
use prost_reflect::{DescriptorPool, MethodDescriptor, ServiceDescriptor};
|
||||||
|
use serde_json::Deserializer;
|
||||||
|
use tauri::AppHandle;
|
||||||
|
use tokio_stream::wrappers::ReceiverStream;
|
||||||
|
use tonic::body::BoxBody;
|
||||||
|
use tonic::metadata::{MetadataKey, MetadataValue};
|
||||||
|
use tonic::transport::Uri;
|
||||||
|
use tonic::{IntoRequest, IntoStreamingRequest, Request, Response, Status, Streaming};
|
||||||
|
|
||||||
|
use crate::codec::DynamicCodec;
|
||||||
|
use crate::proto::{
|
||||||
|
fill_pool_from_files, fill_pool_from_reflection, get_transport, method_desc_to_path,
|
||||||
|
};
|
||||||
|
use crate::{json_schema, MethodDefinition, ServiceDefinition};
|
||||||
|
|
||||||
|
#[derive(Clone)]
|
||||||
|
pub struct GrpcConnection {
|
||||||
|
pool: DescriptorPool,
|
||||||
|
conn: Client<HttpsConnector<HttpConnector>, BoxBody>,
|
||||||
|
pub uri: Uri,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Default)]
|
||||||
|
pub struct StreamError {
|
||||||
|
pub message: String,
|
||||||
|
pub status: Option<Status>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<String> for StreamError {
|
||||||
|
fn from(value: String) -> Self {
|
||||||
|
StreamError {
|
||||||
|
message: value.to_string(),
|
||||||
|
status: None,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<Status> for StreamError {
|
||||||
|
fn from(s: Status) -> Self {
|
||||||
|
StreamError {
|
||||||
|
message: s.message().to_string(),
|
||||||
|
status: Some(s),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl GrpcConnection {
|
||||||
|
pub fn service(&self, service: &str) -> Result<ServiceDescriptor, String> {
|
||||||
|
let service = self
|
||||||
|
.pool
|
||||||
|
.get_service_by_name(service)
|
||||||
|
.ok_or("Failed to find service")?;
|
||||||
|
Ok(service)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn method(&self, service: &str, method: &str) -> Result<MethodDescriptor, String> {
|
||||||
|
let service = self.service(service)?;
|
||||||
|
let method = service
|
||||||
|
.methods()
|
||||||
|
.find(|m| m.name() == method)
|
||||||
|
.ok_or("Failed to find method")?;
|
||||||
|
Ok(method)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub async fn unary(
|
||||||
|
&self,
|
||||||
|
service: &str,
|
||||||
|
method: &str,
|
||||||
|
message: &str,
|
||||||
|
metadata: HashMap<String, String>,
|
||||||
|
) -> Result<Response<DynamicMessage>, StreamError> {
|
||||||
|
let method = &self.method(&service, &method)?;
|
||||||
|
let input_message = method.input();
|
||||||
|
|
||||||
|
let mut deserializer = Deserializer::from_str(message);
|
||||||
|
let req_message = DynamicMessage::deserialize(input_message, &mut deserializer)
|
||||||
|
.map_err(|e| e.to_string())?;
|
||||||
|
deserializer.end().unwrap();
|
||||||
|
|
||||||
|
let mut client = tonic::client::Grpc::with_origin(self.conn.clone(), self.uri.clone());
|
||||||
|
|
||||||
|
let mut req = req_message.into_request();
|
||||||
|
decorate_req(metadata, &mut req).map_err(|e| e.to_string())?;
|
||||||
|
|
||||||
|
let path = method_desc_to_path(method);
|
||||||
|
let codec = DynamicCodec::new(method.clone());
|
||||||
|
client.ready().await.unwrap();
|
||||||
|
|
||||||
|
Ok(client.unary(req, path, codec).await?)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub async fn streaming(
|
||||||
|
&self,
|
||||||
|
service: &str,
|
||||||
|
method: &str,
|
||||||
|
stream: ReceiverStream<DynamicMessage>,
|
||||||
|
metadata: HashMap<String, String>,
|
||||||
|
) -> Result<Response<Streaming<DynamicMessage>>, StreamError> {
|
||||||
|
let method = &self.method(&service, &method)?;
|
||||||
|
let mut client = tonic::client::Grpc::with_origin(self.conn.clone(), self.uri.clone());
|
||||||
|
|
||||||
|
let mut req = stream.into_streaming_request();
|
||||||
|
|
||||||
|
decorate_req(metadata, &mut req).map_err(|e| e.to_string())?;
|
||||||
|
|
||||||
|
let path = method_desc_to_path(method);
|
||||||
|
let codec = DynamicCodec::new(method.clone());
|
||||||
|
client.ready().await.map_err(|e| e.to_string())?;
|
||||||
|
Ok(client.streaming(req, path, codec).await?)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub async fn client_streaming(
|
||||||
|
&self,
|
||||||
|
service: &str,
|
||||||
|
method: &str,
|
||||||
|
stream: ReceiverStream<DynamicMessage>,
|
||||||
|
metadata: HashMap<String, String>,
|
||||||
|
) -> Result<Response<DynamicMessage>, StreamError> {
|
||||||
|
let method = &self.method(&service, &method)?;
|
||||||
|
let mut client = tonic::client::Grpc::with_origin(self.conn.clone(), self.uri.clone());
|
||||||
|
let mut req = stream.into_streaming_request();
|
||||||
|
decorate_req(metadata, &mut req).map_err(|e| e.to_string())?;
|
||||||
|
|
||||||
|
let path = method_desc_to_path(method);
|
||||||
|
let codec = DynamicCodec::new(method.clone());
|
||||||
|
client.ready().await.unwrap();
|
||||||
|
client
|
||||||
|
.client_streaming(req, path, codec)
|
||||||
|
.await
|
||||||
|
.map_err(|e| StreamError {
|
||||||
|
message: e.message().to_string(),
|
||||||
|
status: Some(e),
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
pub async fn server_streaming(
|
||||||
|
&self,
|
||||||
|
service: &str,
|
||||||
|
method: &str,
|
||||||
|
message: &str,
|
||||||
|
metadata: HashMap<String, String>,
|
||||||
|
) -> Result<Response<Streaming<DynamicMessage>>, StreamError> {
|
||||||
|
let method = &self.method(&service, &method)?;
|
||||||
|
let input_message = method.input();
|
||||||
|
|
||||||
|
let mut deserializer = Deserializer::from_str(message);
|
||||||
|
let req_message = DynamicMessage::deserialize(input_message, &mut deserializer)
|
||||||
|
.map_err(|e| e.to_string())?;
|
||||||
|
deserializer.end().unwrap();
|
||||||
|
|
||||||
|
let mut client = tonic::client::Grpc::with_origin(self.conn.clone(), self.uri.clone());
|
||||||
|
|
||||||
|
let mut req = req_message.into_request();
|
||||||
|
decorate_req(metadata, &mut req).map_err(|e| e.to_string())?;
|
||||||
|
|
||||||
|
let path = method_desc_to_path(method);
|
||||||
|
let codec = DynamicCodec::new(method.clone());
|
||||||
|
client.ready().await.map_err(|e| e.to_string())?;
|
||||||
|
Ok(client.server_streaming(req, path, codec).await?)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct GrpcHandle {
|
||||||
|
app_handle: AppHandle,
|
||||||
|
pools: HashMap<String, DescriptorPool>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl GrpcHandle {
|
||||||
|
pub fn new(app_handle: &AppHandle) -> Self {
|
||||||
|
let pools = HashMap::new();
|
||||||
|
Self {
|
||||||
|
pools,
|
||||||
|
app_handle: app_handle.clone(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl GrpcHandle {
|
||||||
|
pub async fn reflect(
|
||||||
|
&mut self,
|
||||||
|
id: &str,
|
||||||
|
uri: &str,
|
||||||
|
proto_files: &Vec<PathBuf>,
|
||||||
|
) -> Result<(), String> {
|
||||||
|
let pool = if proto_files.is_empty() {
|
||||||
|
let full_uri = uri_from_str(uri)?;
|
||||||
|
fill_pool_from_reflection(&full_uri).await
|
||||||
|
} else {
|
||||||
|
fill_pool_from_files(&self.app_handle, proto_files).await
|
||||||
|
}?;
|
||||||
|
|
||||||
|
self.pools
|
||||||
|
.insert(make_pool_key(id, uri, proto_files), pool.clone());
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
pub async fn services(
|
||||||
|
&mut self,
|
||||||
|
id: &str,
|
||||||
|
uri: &str,
|
||||||
|
proto_files: &Vec<PathBuf>,
|
||||||
|
) -> Result<Vec<ServiceDefinition>, String> {
|
||||||
|
// Ensure reflection is up-to-date
|
||||||
|
self.reflect(id, uri, proto_files).await?;
|
||||||
|
|
||||||
|
let pool = self
|
||||||
|
.get_pool(id, uri, proto_files)
|
||||||
|
.ok_or("Failed to get pool".to_string())?;
|
||||||
|
Ok(self.services_from_pool(&pool))
|
||||||
|
}
|
||||||
|
|
||||||
|
fn services_from_pool(&self, pool: &DescriptorPool) -> Vec<ServiceDefinition> {
|
||||||
|
pool.services()
|
||||||
|
.map(|s| {
|
||||||
|
let mut def = ServiceDefinition {
|
||||||
|
name: s.full_name().to_string(),
|
||||||
|
methods: vec![],
|
||||||
|
};
|
||||||
|
for method in s.methods() {
|
||||||
|
let input_message = method.input();
|
||||||
|
def.methods.push(MethodDefinition {
|
||||||
|
name: method.name().to_string(),
|
||||||
|
server_streaming: method.is_server_streaming(),
|
||||||
|
client_streaming: method.is_client_streaming(),
|
||||||
|
schema: serde_json::to_string_pretty(&json_schema::message_to_json_schema(
|
||||||
|
&pool,
|
||||||
|
input_message,
|
||||||
|
))
|
||||||
|
.unwrap(),
|
||||||
|
})
|
||||||
|
}
|
||||||
|
def
|
||||||
|
})
|
||||||
|
.collect::<Vec<_>>()
|
||||||
|
}
|
||||||
|
|
||||||
|
pub async fn connect(
|
||||||
|
&mut self,
|
||||||
|
id: &str,
|
||||||
|
uri: &str,
|
||||||
|
proto_files: &Vec<PathBuf>,
|
||||||
|
) -> Result<GrpcConnection, String> {
|
||||||
|
self.reflect(id, uri, proto_files).await?;
|
||||||
|
let pool = self
|
||||||
|
.get_pool(id, uri, proto_files)
|
||||||
|
.ok_or("Failed to get pool")?;
|
||||||
|
|
||||||
|
let uri = uri_from_str(uri)?;
|
||||||
|
let conn = get_transport();
|
||||||
|
let connection = GrpcConnection {
|
||||||
|
pool: pool.clone(),
|
||||||
|
conn,
|
||||||
|
uri,
|
||||||
|
};
|
||||||
|
Ok(connection)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn get_pool(&self, id: &str, uri: &str, proto_files: &Vec<PathBuf>) -> Option<&DescriptorPool> {
|
||||||
|
self.pools.get(make_pool_key(id, uri, proto_files).as_str())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn decorate_req<T>(metadata: HashMap<String, String>, req: &mut Request<T>) -> Result<(), String> {
|
||||||
|
for (k, v) in metadata {
|
||||||
|
req.metadata_mut().insert(
|
||||||
|
MetadataKey::from_str(k.as_str()).map_err(|e| e.to_string())?,
|
||||||
|
MetadataValue::from_str(v.as_str()).map_err(|e| e.to_string())?,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
fn uri_from_str(uri_str: &str) -> Result<Uri, String> {
|
||||||
|
match Uri::from_str(uri_str) {
|
||||||
|
Ok(uri) => Ok(uri),
|
||||||
|
Err(err) => {
|
||||||
|
// Uri::from_str basically only returns "invalid format" so we add more context here
|
||||||
|
Err(format!("Failed to parse URL, {}", err.to_string()))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn make_pool_key(id: &str, uri: &str, proto_files: &Vec<PathBuf>) -> String {
|
||||||
|
let pool_key = format!(
|
||||||
|
"{}::{}::{}",
|
||||||
|
id,
|
||||||
|
uri,
|
||||||
|
proto_files
|
||||||
|
.iter()
|
||||||
|
.map(|p| p.to_string_lossy().to_string())
|
||||||
|
.collect::<Vec<String>>()
|
||||||
|
.join(":")
|
||||||
|
);
|
||||||
|
|
||||||
|
format!("{:x}", md5::compute(pool_key))
|
||||||
|
}
|
||||||
@@ -0,0 +1,252 @@
|
|||||||
|
use std::env::temp_dir;
|
||||||
|
use std::ops::Deref;
|
||||||
|
use std::path::PathBuf;
|
||||||
|
use std::str::FromStr;
|
||||||
|
|
||||||
|
use anyhow::anyhow;
|
||||||
|
use hyper::client::HttpConnector;
|
||||||
|
use hyper::Client;
|
||||||
|
use hyper_rustls::{HttpsConnector, HttpsConnectorBuilder};
|
||||||
|
use log::{debug, warn};
|
||||||
|
use prost::Message;
|
||||||
|
use prost_reflect::{DescriptorPool, MethodDescriptor};
|
||||||
|
use prost_types::{FileDescriptorProto, FileDescriptorSet};
|
||||||
|
use tauri::path::BaseDirectory;
|
||||||
|
use tauri::{AppHandle, Manager};
|
||||||
|
use tauri_plugin_shell::ShellExt;
|
||||||
|
use tokio::fs;
|
||||||
|
use tokio_stream::StreamExt;
|
||||||
|
use tonic::body::BoxBody;
|
||||||
|
use tonic::codegen::http::uri::PathAndQuery;
|
||||||
|
use tonic::transport::Uri;
|
||||||
|
use tonic::Request;
|
||||||
|
use tonic_reflection::pb::server_reflection_client::ServerReflectionClient;
|
||||||
|
use tonic_reflection::pb::server_reflection_request::MessageRequest;
|
||||||
|
use tonic_reflection::pb::server_reflection_response::MessageResponse;
|
||||||
|
use tonic_reflection::pb::ServerReflectionRequest;
|
||||||
|
|
||||||
|
pub async fn fill_pool_from_files(
|
||||||
|
app_handle: &AppHandle,
|
||||||
|
paths: &Vec<PathBuf>,
|
||||||
|
) -> Result<DescriptorPool, String> {
|
||||||
|
let mut pool = DescriptorPool::new();
|
||||||
|
let random_file_name = format!("{}.desc", uuid::Uuid::new_v4());
|
||||||
|
let desc_path = temp_dir().join(random_file_name);
|
||||||
|
let global_import_dir = app_handle
|
||||||
|
.path()
|
||||||
|
.resolve("protoc-include", BaseDirectory::Resource)
|
||||||
|
.expect("failed to resolve protoc include directory");
|
||||||
|
|
||||||
|
// HACK: Remove UNC prefix for Windows paths
|
||||||
|
let global_import_dir = dunce::simplified(global_import_dir.as_path())
|
||||||
|
.to_string_lossy()
|
||||||
|
.to_string();
|
||||||
|
let desc_path = dunce::simplified(desc_path.as_path());
|
||||||
|
|
||||||
|
let mut args = vec![
|
||||||
|
"--include_imports".to_string(),
|
||||||
|
"--include_source_info".to_string(),
|
||||||
|
"-I".to_string(),
|
||||||
|
global_import_dir,
|
||||||
|
"-o".to_string(),
|
||||||
|
desc_path.to_string_lossy().to_string(),
|
||||||
|
];
|
||||||
|
|
||||||
|
for p in paths {
|
||||||
|
if p.as_path().exists() {
|
||||||
|
args.push(p.to_string_lossy().to_string());
|
||||||
|
} else {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
let parent = p.as_path().parent();
|
||||||
|
if let Some(parent_path) = parent {
|
||||||
|
args.push("-I".to_string());
|
||||||
|
args.push(parent_path.to_string_lossy().to_string());
|
||||||
|
args.push("-I".to_string());
|
||||||
|
args.push(parent_path.parent().unwrap().to_string_lossy().to_string());
|
||||||
|
} else {
|
||||||
|
debug!("ignoring {:?} since it does not exist.", parent)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
let out = app_handle
|
||||||
|
.shell()
|
||||||
|
.sidecar("yaakprotoc")
|
||||||
|
.expect("yaakprotoc not found")
|
||||||
|
.args(args)
|
||||||
|
.output()
|
||||||
|
.await
|
||||||
|
.expect("yaakprotoc failed to run");
|
||||||
|
|
||||||
|
if !out.status.success() {
|
||||||
|
return Err(format!(
|
||||||
|
"protoc failed with status {}: {}",
|
||||||
|
out.status.code().unwrap(),
|
||||||
|
String::from_utf8_lossy(out.stderr.as_slice())
|
||||||
|
));
|
||||||
|
}
|
||||||
|
|
||||||
|
let bytes = fs::read(desc_path).await.map_err(|e| e.to_string())?;
|
||||||
|
let fdp = FileDescriptorSet::decode(bytes.deref()).map_err(|e| e.to_string())?;
|
||||||
|
pool.add_file_descriptor_set(fdp)
|
||||||
|
.map_err(|e| e.to_string())?;
|
||||||
|
|
||||||
|
fs::remove_file(desc_path)
|
||||||
|
.await
|
||||||
|
.map_err(|e| e.to_string())?;
|
||||||
|
|
||||||
|
Ok(pool)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub async fn fill_pool_from_reflection(uri: &Uri) -> Result<DescriptorPool, String> {
|
||||||
|
let mut pool = DescriptorPool::new();
|
||||||
|
let mut client = ServerReflectionClient::with_origin(get_transport(), uri.clone());
|
||||||
|
|
||||||
|
for service in list_services(&mut client).await? {
|
||||||
|
if service == "grpc.reflection.v1alpha.ServerReflection" {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
file_descriptor_set_from_service_name(&service, &mut pool, &mut client).await;
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(pool)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn get_transport() -> Client<HttpsConnector<HttpConnector>, BoxBody> {
|
||||||
|
let connector = HttpsConnectorBuilder::new().with_native_roots();
|
||||||
|
let connector = connector.https_or_http().enable_http2().wrap_connector({
|
||||||
|
let mut http_connector = HttpConnector::new();
|
||||||
|
http_connector.enforce_http(false);
|
||||||
|
http_connector
|
||||||
|
});
|
||||||
|
Client::builder()
|
||||||
|
.pool_max_idle_per_host(0)
|
||||||
|
.http2_only(true)
|
||||||
|
.build(connector)
|
||||||
|
}
|
||||||
|
|
||||||
|
async fn list_services(
|
||||||
|
reflect_client: &mut ServerReflectionClient<Client<HttpsConnector<HttpConnector>, BoxBody>>,
|
||||||
|
) -> Result<Vec<String>, String> {
|
||||||
|
let response =
|
||||||
|
send_reflection_request(reflect_client, MessageRequest::ListServices("".into())).await?;
|
||||||
|
|
||||||
|
let list_services_response = match response {
|
||||||
|
MessageResponse::ListServicesResponse(resp) => resp,
|
||||||
|
_ => panic!("Expected a ListServicesResponse variant"),
|
||||||
|
};
|
||||||
|
|
||||||
|
Ok(list_services_response
|
||||||
|
.service
|
||||||
|
.iter()
|
||||||
|
.map(|s| s.name.clone())
|
||||||
|
.collect::<Vec<_>>())
|
||||||
|
}
|
||||||
|
|
||||||
|
async fn file_descriptor_set_from_service_name(
|
||||||
|
service_name: &str,
|
||||||
|
pool: &mut DescriptorPool,
|
||||||
|
client: &mut ServerReflectionClient<Client<HttpsConnector<HttpConnector>, BoxBody>>,
|
||||||
|
) {
|
||||||
|
let response = match send_reflection_request(
|
||||||
|
client,
|
||||||
|
MessageRequest::FileContainingSymbol(service_name.into()),
|
||||||
|
)
|
||||||
|
.await
|
||||||
|
{
|
||||||
|
Ok(resp) => resp,
|
||||||
|
Err(e) => {
|
||||||
|
warn!(
|
||||||
|
"Error fetching file descriptor for service {}: {}",
|
||||||
|
service_name, e
|
||||||
|
);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
let file_descriptor_response = match response {
|
||||||
|
MessageResponse::FileDescriptorResponse(resp) => resp,
|
||||||
|
_ => panic!("Expected a FileDescriptorResponse variant"),
|
||||||
|
};
|
||||||
|
|
||||||
|
for fd in file_descriptor_response.file_descriptor_proto {
|
||||||
|
let fdp = FileDescriptorProto::decode(fd.deref()).unwrap();
|
||||||
|
|
||||||
|
// Add deps first or else we'll get an error
|
||||||
|
for dep_name in fdp.clone().dependency {
|
||||||
|
file_descriptor_set_by_filename(&dep_name, pool, client).await;
|
||||||
|
}
|
||||||
|
|
||||||
|
pool.add_file_descriptor_proto(fdp)
|
||||||
|
.expect("add file descriptor proto");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async fn file_descriptor_set_by_filename(
|
||||||
|
filename: &str,
|
||||||
|
pool: &mut DescriptorPool,
|
||||||
|
client: &mut ServerReflectionClient<Client<HttpsConnector<HttpConnector>, BoxBody>>,
|
||||||
|
) {
|
||||||
|
// We already fetched this file
|
||||||
|
if let Some(_) = pool.get_file_by_name(filename) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
let response =
|
||||||
|
send_reflection_request(client, MessageRequest::FileByFilename(filename.into())).await;
|
||||||
|
let file_descriptor_response = match response {
|
||||||
|
Ok(MessageResponse::FileDescriptorResponse(resp)) => resp,
|
||||||
|
Ok(_) => {
|
||||||
|
panic!("Expected a FileDescriptorResponse variant")
|
||||||
|
}
|
||||||
|
Err(e) => {
|
||||||
|
warn!("Error fetching file descriptor for {}: {}", filename, e);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
for fd in file_descriptor_response.file_descriptor_proto {
|
||||||
|
let fdp = FileDescriptorProto::decode(fd.deref()).unwrap();
|
||||||
|
pool.add_file_descriptor_proto(fdp)
|
||||||
|
.expect("add file descriptor proto");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async fn send_reflection_request(
|
||||||
|
client: &mut ServerReflectionClient<Client<HttpsConnector<HttpConnector>, BoxBody>>,
|
||||||
|
message: MessageRequest,
|
||||||
|
) -> Result<MessageResponse, String> {
|
||||||
|
let reflection_request = ServerReflectionRequest {
|
||||||
|
host: "".into(), // Doesn't matter
|
||||||
|
message_request: Some(message),
|
||||||
|
};
|
||||||
|
|
||||||
|
let request = Request::new(tokio_stream::once(reflection_request));
|
||||||
|
|
||||||
|
client
|
||||||
|
.server_reflection_info(request)
|
||||||
|
.await
|
||||||
|
.map_err(|e| match e.code() {
|
||||||
|
tonic::Code::Unavailable => "Failed to connect to endpoint".to_string(),
|
||||||
|
tonic::Code::Unauthenticated => "Authentication failed".to_string(),
|
||||||
|
tonic::Code::DeadlineExceeded => "Deadline exceeded".to_string(),
|
||||||
|
_ => e.to_string(),
|
||||||
|
})?
|
||||||
|
.into_inner()
|
||||||
|
.next()
|
||||||
|
.await
|
||||||
|
.expect("steamed response")
|
||||||
|
.map_err(|e| e.to_string())?
|
||||||
|
.message_response
|
||||||
|
.ok_or("No reflection response".to_string())
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn method_desc_to_path(md: &MethodDescriptor) -> PathAndQuery {
|
||||||
|
let full_name = md.full_name();
|
||||||
|
let (namespace, method_name) = full_name
|
||||||
|
.rsplit_once('.')
|
||||||
|
.ok_or_else(|| anyhow!("invalid method path"))
|
||||||
|
.expect("invalid method path");
|
||||||
|
PathAndQuery::from_str(&format!("/{}/{}", namespace, method_name)).expect("invalid method path")
|
||||||
|
}
|
||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user