mirror of
https://github.com/mountain-loop/yaak.git
synced 2026-07-20 19:51:18 +02:00
Compare commits
985 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| d586ec5fb4 | |||
| ad8a4933da | |||
| 499d0b09ba | |||
| ac1181c1b4 | |||
| b9671781d3 | |||
| 42fd7cb21e | |||
| fe9f765c1d | |||
| 087a1e5ea1 | |||
| 6e156497da | |||
| 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 |
+2
-3
@@ -1,6 +1,5 @@
|
|||||||
node_modules/
|
node_modules/
|
||||||
dist/
|
dist/
|
||||||
.eslintrc.cjs
|
|
||||||
.prettierrc.cjs
|
.prettierrc.cjs
|
||||||
src-web/postcss.config.cjs
|
.eslintrc.cjs
|
||||||
src-web/vite.config.ts
|
env.d.ts
|
||||||
|
|||||||
+25
-37
@@ -1,49 +1,37 @@
|
|||||||
module.exports = {
|
module.exports = {
|
||||||
extends: [
|
extends: [
|
||||||
'eslint:recommended',
|
"eslint:recommended",
|
||||||
'plugin:react/recommended',
|
"plugin:react/recommended",
|
||||||
'plugin:react-hooks/recommended',
|
"plugin:react-hooks/recommended",
|
||||||
'plugin:import/recommended',
|
"plugin:import/recommended",
|
||||||
'plugin:jsx-a11y/recommended',
|
"plugin:jsx-a11y/recommended",
|
||||||
'plugin:@typescript-eslint/recommended',
|
"plugin:@typescript-eslint/recommended",
|
||||||
'eslint-config-prettier',
|
"eslint-config-prettier"
|
||||||
],
|
],
|
||||||
plugins: ['react-refresh'],
|
parser: "@typescript-eslint/parser",
|
||||||
parser: '@typescript-eslint/parser',
|
|
||||||
parserOptions: {
|
parserOptions: {
|
||||||
project: ['./tsconfig.json'],
|
project: ["./tsconfig.json"]
|
||||||
},
|
},
|
||||||
ignorePatterns: [
|
ignorePatterns: ["scripts/**/*", "plugin-runtime/**/*", "src-tauri/**/*", "plugins/**/*"],
|
||||||
'scripts/**/*',
|
|
||||||
'packages/plugin-runtime/**/*',
|
|
||||||
'packages/plugin-runtime-types/**/*',
|
|
||||||
'src-tauri/**/*',
|
|
||||||
'src-web/tailwind.config.cjs',
|
|
||||||
'src-web/vite.config.ts',
|
|
||||||
],
|
|
||||||
settings: {
|
settings: {
|
||||||
react: {
|
react: {
|
||||||
version: 'detect',
|
version: "detect"
|
||||||
},
|
},
|
||||||
'import/resolver': {
|
"import/resolver": {
|
||||||
node: {
|
node: {
|
||||||
paths: ['src-web'],
|
paths: ["src-web"],
|
||||||
extensions: ['.ts', '.tsx'],
|
extensions: [".ts", ".tsx"]
|
||||||
},
|
}
|
||||||
},
|
}
|
||||||
},
|
},
|
||||||
rules: {
|
rules: {
|
||||||
'react-refresh/only-export-components': 'error',
|
"jsx-a11y/no-autofocus": "off",
|
||||||
'jsx-a11y/no-autofocus': 'off',
|
"react/react-in-jsx-scope": "off",
|
||||||
'react/react-in-jsx-scope': 'off',
|
"import/no-unresolved": "off",
|
||||||
'import/no-unresolved': 'off',
|
"@typescript-eslint/consistent-type-imports": ["error", {
|
||||||
'@typescript-eslint/consistent-type-imports': [
|
prefer: "type-imports",
|
||||||
'error',
|
disallowTypeAnnotations: true,
|
||||||
{
|
fixStyle: "separate-type-imports"
|
||||||
prefer: 'type-imports',
|
}]
|
||||||
disallowTypeAnnotations: true,
|
}
|
||||||
fixStyle: 'separate-type-imports',
|
|
||||||
},
|
|
||||||
],
|
|
||||||
},
|
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -1,2 +0,0 @@
|
|||||||
src-tauri/vendored/**/* linguist-generated=true
|
|
||||||
src-tauri/gen/schemas/**/* linguist-generated=true
|
|
||||||
@@ -1,38 +0,0 @@
|
|||||||
---
|
|
||||||
name: Bug report
|
|
||||||
about: Create a report to help us improve
|
|
||||||
title: ''
|
|
||||||
labels: ''
|
|
||||||
assignees: ''
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
**Describe the bug**
|
|
||||||
A clear and concise description of what the bug is.
|
|
||||||
|
|
||||||
**To Reproduce**
|
|
||||||
Steps to reproduce the behavior:
|
|
||||||
1. Go to '...'
|
|
||||||
2. Click on '....'
|
|
||||||
3. Scroll down to '....'
|
|
||||||
4. See error
|
|
||||||
|
|
||||||
**Expected behavior**
|
|
||||||
A clear and concise description of what you expected to happen.
|
|
||||||
|
|
||||||
**Screenshots**
|
|
||||||
If applicable, add screenshots to help explain your problem.
|
|
||||||
|
|
||||||
**Desktop (please complete the following information):**
|
|
||||||
- OS: [e.g. iOS]
|
|
||||||
- Browser [e.g. chrome, safari]
|
|
||||||
- Version [e.g. 22]
|
|
||||||
|
|
||||||
**Smartphone (please complete the following information):**
|
|
||||||
- Device: [e.g. iPhone6]
|
|
||||||
- OS: [e.g. iOS8.1]
|
|
||||||
- Browser [e.g. stock browser, safari]
|
|
||||||
- Version [e.g. 22]
|
|
||||||
|
|
||||||
**Additional context**
|
|
||||||
Add any other context about the problem here.
|
|
||||||
@@ -1,5 +0,0 @@
|
|||||||
blank_issues_enabled: false
|
|
||||||
contact_links:
|
|
||||||
- name: Bugs, Feedback, Feature Requests, and Questions
|
|
||||||
url: https://feedback.yaak.app
|
|
||||||
about: "Please report to Yaak's public feedback board. Issues will be created and linked here when applicable."
|
|
||||||
@@ -16,20 +16,19 @@ jobs:
|
|||||||
fail-fast: false
|
fail-fast: false
|
||||||
matrix:
|
matrix:
|
||||||
include:
|
include:
|
||||||
- platform: 'macos-latest' # for Arm-based Macs (M1 and above).
|
- platform: 'macos-latest' # for Arm-based macs (M1 and above).
|
||||||
args: '--target aarch64-apple-darwin'
|
args: '--target aarch64-apple-darwin'
|
||||||
yaak_arch: 'arm64'
|
yaak_arch: 'arm64'
|
||||||
- platform: 'macos-latest' # for Intel-based Macs.
|
- platform: 'macos-latest' # for Intel-based macs.
|
||||||
args: '--target x86_64-apple-darwin'
|
args: '--target x86_64-apple-darwin'
|
||||||
yaak_arch: 'x64'
|
yaak_arch: 'x64'
|
||||||
- platform: 'ubuntu-22.04'
|
- platform: 'ubuntu-22.04' # for Tauri v1, you could replace this with ubuntu-20.04.
|
||||||
args: ''
|
args: ''
|
||||||
yaak_arch: 'x64'
|
yaak_arch: 'x64'
|
||||||
- platform: 'windows-latest'
|
- platform: 'windows-latest'
|
||||||
args: ''
|
args: ''
|
||||||
yaak_arch: 'x64'
|
yaak_arch: 'x64'
|
||||||
runs-on: ${{ matrix.platform }}
|
runs-on: ${{ matrix.platform }}
|
||||||
timeout-minutes: 40
|
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout yaakapp/app
|
- name: Checkout yaakapp/app
|
||||||
uses: actions/checkout@v4
|
uses: actions/checkout@v4
|
||||||
@@ -37,7 +36,11 @@ jobs:
|
|||||||
- name: Setup Node
|
- name: Setup Node
|
||||||
uses: actions/setup-node@v4
|
uses: actions/setup-node@v4
|
||||||
with:
|
with:
|
||||||
node-version: 22
|
node-version: 20
|
||||||
|
|
||||||
|
- uses: actions/setup-go@v5
|
||||||
|
with:
|
||||||
|
go-version: '1.22'
|
||||||
|
|
||||||
- name: install Rust stable
|
- name: install Rust stable
|
||||||
uses: dtolnay/rust-toolchain@stable
|
uses: dtolnay/rust-toolchain@stable
|
||||||
@@ -53,7 +56,7 @@ jobs:
|
|||||||
~/.cargo/registry/index/
|
~/.cargo/registry/index/
|
||||||
~/.cargo/registry/cache/
|
~/.cargo/registry/cache/
|
||||||
~/.cargo/git/db/
|
~/.cargo/git/db/
|
||||||
src-tauri/target/
|
target/
|
||||||
key: ${{ runner.os }}-cargo-${{ hashFiles('**/Cargo.lock') }}
|
key: ${{ runner.os }}-cargo-${{ hashFiles('**/Cargo.lock') }}
|
||||||
restore-keys: ${{ runner.os }}-cargo-
|
restore-keys: ${{ runner.os }}-cargo-
|
||||||
|
|
||||||
@@ -63,22 +66,22 @@ jobs:
|
|||||||
sudo apt-get update
|
sudo apt-get update
|
||||||
sudo apt-get install -y libwebkit2gtk-4.1-dev libappindicator3-dev librsvg2-dev patchelf
|
sudo apt-get install -y libwebkit2gtk-4.1-dev libappindicator3-dev librsvg2-dev patchelf
|
||||||
|
|
||||||
- name: install dependencies (windows only)
|
- name: Install Node dependencies
|
||||||
if: matrix.platform == 'windows-latest'
|
run: |
|
||||||
run: cargo install --force trusted-signing-cli
|
npm ci
|
||||||
|
|
||||||
- name: Install NPM Dependencies
|
- name: Install plugin-runtime Node dependencies
|
||||||
|
working-directory: plugin-runtime
|
||||||
run: |
|
run: |
|
||||||
npm ci
|
npm ci
|
||||||
npm install @yaakapp/cli
|
|
||||||
|
|
||||||
- name: Install Protoc for plugin-runtime
|
- name: Install Protoc for plugin-runtime
|
||||||
uses: arduino/setup-protoc@v3
|
uses: arduino/setup-protoc@v3
|
||||||
with:
|
with:
|
||||||
repo-token: ${{ secrets.GITHUB_TOKEN }}
|
repo-token: ${{ secrets.GITHUB_TOKEN }}
|
||||||
|
|
||||||
- name: Run JS build
|
- name: Install yaak CLI
|
||||||
run: npm run build
|
run: go install github.com/yaakapp/yaakcli@latest
|
||||||
|
|
||||||
- name: Run lint
|
- name: Run lint
|
||||||
run: npm run lint
|
run: npm run lint
|
||||||
@@ -98,28 +101,20 @@ jobs:
|
|||||||
env:
|
env:
|
||||||
YAAK_PLUGINS_DIR: ${{ env.YAAK_PLUGINS_DIR }}
|
YAAK_PLUGINS_DIR: ${{ env.YAAK_PLUGINS_DIR }}
|
||||||
YAAK_TARGET_ARCH: ${{ matrix.yaak_arch }}
|
YAAK_TARGET_ARCH: ${{ matrix.yaak_arch }}
|
||||||
|
|
||||||
ENABLE_CODE_SIGNING: ${{ secrets.APPLE_CERTIFICATE }}
|
|
||||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||||
TAURI_SIGNING_PRIVATE_KEY: ${{ secrets.TAURI_PRIVATE_KEY }}
|
TAURI_SIGNING_PRIVATE_KEY: ${{ secrets.TAURI_PRIVATE_KEY }}
|
||||||
TAURI_SIGNING_PRIVATE_KEY_PASSWORD: ${{ secrets.TAURI_KEY_PASSWORD }}
|
TAURI_SIGNING_PRIVATE_KEY_PASSWORD: ${{ secrets.TAURI_KEY_PASSWORD }}
|
||||||
|
ENABLE_CODE_SIGNING: ${{ secrets.APPLE_CERTIFICATE }}
|
||||||
# Apple signing stuff
|
APPLE_CERTIFICATE: ${{ secrets.APPLE_CERTIFICATE }}
|
||||||
APPLE_CERTIFICATE: ${{ matrix.platform == 'macos-latest' && secrets.APPLE_CERTIFICATE }}
|
APPLE_CERTIFICATE_PASSWORD: ${{ secrets.APPLE_CERTIFICATE_PASSWORD }}
|
||||||
APPLE_CERTIFICATE_PASSWORD: ${{ matrix.platform == 'macos-latest' && secrets.APPLE_CERTIFICATE_PASSWORD }}
|
APPLE_SIGNING_IDENTITY: ${{ secrets.APPLE_SIGNING_IDENTITY }}
|
||||||
APPLE_ID: ${{ matrix.platform == 'macos-latest' && secrets.APPLE_ID }}
|
APPLE_ID: ${{ secrets.APPLE_ID }}
|
||||||
APPLE_PASSWORD: ${{ matrix.platform == 'macos-latest' && secrets.APPLE_PASSWORD }}
|
APPLE_TEAM_ID: ${{ secrets.APPLE_TEAM_ID }}
|
||||||
APPLE_SIGNING_IDENTITY: ${{ matrix.platform == 'macos-latest' && secrets.APPLE_SIGNING_IDENTITY }}
|
APPLE_PASSWORD: ${{ secrets.APPLE_PASSWORD }}
|
||||||
APPLE_TEAM_ID: ${{ matrix.platform == 'macos-latest' && secrets.APPLE_TEAM_ID }}
|
|
||||||
|
|
||||||
# Windows signing stuff
|
|
||||||
AZURE_CLIENT_ID: ${{ matrix.platform == 'windows-latest' && secrets.AZURE_CLIENT_ID }}
|
|
||||||
AZURE_CLIENT_SECRET: ${{ matrix.platform == 'windows-latest' && secrets.AZURE_CLIENT_SECRET }}
|
|
||||||
AZURE_TENANT_ID: ${{ matrix.platform == 'windows-latest' && secrets.AZURE_TENANT_ID }}
|
|
||||||
with:
|
with:
|
||||||
tagName: 'v__VERSION__'
|
tagName: 'v__VERSION__'
|
||||||
releaseName: 'Release __VERSION__'
|
releaseName: 'Release __VERSION__'
|
||||||
releaseBody: '[Changelog __VERSION__](https://yaak.app/blog/__VERSION__)'
|
releaseBody: 'https://yaak.app/changelog/__VERSION__'
|
||||||
releaseDraft: true
|
releaseDraft: true
|
||||||
prerelease: false
|
prerelease: false
|
||||||
args: ${{ matrix.args }}
|
args: ${{ matrix.args }}
|
||||||
|
|||||||
@@ -0,0 +1 @@
|
|||||||
|
_
|
||||||
Executable
+4
@@ -0,0 +1,4 @@
|
|||||||
|
#!/bin/sh
|
||||||
|
. "$(dirname "$0")/_/husky.sh"
|
||||||
|
|
||||||
|
npx lint-staged
|
||||||
@@ -0,0 +1,8 @@
|
|||||||
|
module.exports = {
|
||||||
|
"trailingComma": "all",
|
||||||
|
"tabWidth": 2,
|
||||||
|
"semi": true,
|
||||||
|
"singleQuote": true,
|
||||||
|
"printWidth": 100,
|
||||||
|
"bracketSpacing": true
|
||||||
|
}
|
||||||
@@ -1,8 +0,0 @@
|
|||||||
export default {
|
|
||||||
"trailingComma": "all",
|
|
||||||
"tabWidth": 2,
|
|
||||||
"semi": true,
|
|
||||||
"singleQuote": true,
|
|
||||||
"printWidth": 100,
|
|
||||||
"bracketSpacing": true
|
|
||||||
}
|
|
||||||
@@ -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"
|
||||||
|
}
|
||||||
@@ -1,62 +0,0 @@
|
|||||||
# Developer Setup
|
|
||||||
|
|
||||||
Yaak is a combined Node.js and Rust monorepo. It is a [Tauri](https://tauri.app) project, so
|
|
||||||
uses Rust and HTML/CSS/JS for the main application but there is also a plugin system powered
|
|
||||||
by a Node.js sidecar that communicates to the app over gRPC.
|
|
||||||
|
|
||||||
Because of the moving parts, there are a few setup steps required before development can
|
|
||||||
begin.
|
|
||||||
|
|
||||||
## Prerequisites
|
|
||||||
|
|
||||||
Make sure you have the following tools installed:
|
|
||||||
|
|
||||||
- [Node.js](https://nodejs.org/en/download/package-manager)
|
|
||||||
- [Rust](https://www.rust-lang.org/tools/install)
|
|
||||||
|
|
||||||
Check the installations with the following commands:
|
|
||||||
|
|
||||||
```shell
|
|
||||||
node -v
|
|
||||||
npm -v
|
|
||||||
rustc --version
|
|
||||||
```
|
|
||||||
|
|
||||||
Install the NPM dependencies:
|
|
||||||
|
|
||||||
```shell
|
|
||||||
npm install
|
|
||||||
```
|
|
||||||
|
|
||||||
Run the `bootstrap` command to do some initial setup:
|
|
||||||
|
|
||||||
```shell
|
|
||||||
npm run bootstrap
|
|
||||||
```
|
|
||||||
|
|
||||||
_NOTE: Run with `YAAK_PLUGINS_DIR=<Path to yaakapp/plugins>` to re-build bundled plugins_
|
|
||||||
|
|
||||||
## Run the App
|
|
||||||
|
|
||||||
After bootstrapping, start the app in development mode:
|
|
||||||
|
|
||||||
```shell
|
|
||||||
npm start
|
|
||||||
```
|
|
||||||
|
|
||||||
_NOTE: If working on bundled plugins, run with `YAAK_PLUGINS_DIR=<Path to yaakapp/plugins>`_
|
|
||||||
|
|
||||||
## SQLite Migrations
|
|
||||||
|
|
||||||
New migrations can be created from the `src-tauri/` directory:
|
|
||||||
|
|
||||||
```shell
|
|
||||||
cd src-tauri
|
|
||||||
sqlx migrate add migration-name
|
|
||||||
```
|
|
||||||
|
|
||||||
Run the app to apply the migrations.
|
|
||||||
|
|
||||||
If nothing happens, try `cargo clean` and run the app again.
|
|
||||||
|
|
||||||
_Note: Development builds use a separate database location from production builds._
|
|
||||||
@@ -1,21 +0,0 @@
|
|||||||
MIT License
|
|
||||||
|
|
||||||
Copyright (c) 2024 Yaak
|
|
||||||
|
|
||||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
||||||
of this software and associated documentation files (the "Software"), to deal
|
|
||||||
in the Software without restriction, including without limitation the rights
|
|
||||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
||||||
copies of the Software, and to permit persons to whom the Software is
|
|
||||||
furnished to do so, subject to the following conditions:
|
|
||||||
|
|
||||||
The above copyright notice and this permission notice shall be included in all
|
|
||||||
copies or substantial portions of the Software.
|
|
||||||
|
|
||||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
||||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
||||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
||||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
||||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
||||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
||||||
SOFTWARE.
|
|
||||||
@@ -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,37 +1,16 @@
|
|||||||
# Yaak API Client
|
# Yaak Network Toolkit
|
||||||
|
|
||||||
Yaak is a desktop API client for interacting with REST, GraphQL, Server Sent Events (SSE), WebSocket, and gRPC
|
The most fun you'll ever have working with APIs.
|
||||||
APIs. It's built using [Tauri](https://tauri.app), Rust, and ReactJS.
|
|
||||||
|
|
||||||

|
## Common Commands
|
||||||
|
|
||||||
## Feature Overview
|
```sh
|
||||||
|
# Start dev app
|
||||||
|
npm run tauri-dev
|
||||||
|
|
||||||
- 🪂 Import data from Postman, Insomnia, OpenAPI, Swagger, or Curl.<br/>
|
# Migration commands
|
||||||
- 📤 Send requests via REST, GraphQL, Server Sent Events (SSE), WebSockets, or gRPC.<br/>
|
cd src-tauri
|
||||||
- 🔐 Automatically authorize requests with OAuth 2.0, JWT tokens, Basic Auth, and more.<br/>
|
cargo sqlx migrate add ${MIGRATION_NAME}
|
||||||
- 🔎 Filter response bodies using JSONPath or XPath queries.<br/>
|
cargo sqlx migrate run --database-url 'sqlite://db.sqlite?mode=rw'
|
||||||
- ⛓️ Chain together multiple requests to dynamically reference values.<br/>
|
cargo sqlx prepare --database-url 'sqlite://db.sqlite'
|
||||||
- 📂 Organize requests into workspaces and nested folders.<br/>
|
```
|
||||||
- 🧮 Use environment variables to easily switch between Prod and Dev.<br/>
|
|
||||||
- 🏷️ Send dynamic values like UUIDs or timestamps using template tags.<br/>
|
|
||||||
- 🎨 Choose from many of the included themes, or make your own.<br/>
|
|
||||||
- 💽 Mirror workspace data to a directory for integration with Git or Dropbox.<br/>
|
|
||||||
- 📜 View response history for each request.<br/>
|
|
||||||
- 🔌 Create your own plugins for authentication, template tags, and more!<br/>
|
|
||||||
- 🛜 Configure a proxy to access firewall-blocked APIs
|
|
||||||
|
|
||||||
## Feedback and Bug Reports
|
|
||||||
|
|
||||||
All feedback, bug reports, questions, and feature requests should be reported to
|
|
||||||
[feedback.yaak.app](https://feedback.yaak.app).
|
|
||||||
|
|
||||||
## Community Projects
|
|
||||||
|
|
||||||
- [`yaak2postman`](https://github.com/BiteCraft/yaak2postman) CLI for converting Yaak data
|
|
||||||
exports to Postman-compatible collections
|
|
||||||
|
|
||||||
## Contribution Policy
|
|
||||||
|
|
||||||
Yaak is open source, but only accepting contributions for bug fixes. To get started,
|
|
||||||
visit [`DEVELOPMENT.md`](DEVELOPMENT.md) for tips on setting up your environment.
|
|
||||||
|
|||||||
Binary file not shown.
|
Before Width: | Height: | Size: 31 KiB After Width: | Height: | Size: 31 KiB |
|
Before Width: | Height: | Size: 356 KiB After Width: | Height: | Size: 356 KiB |
Binary file not shown.
@@ -4,7 +4,7 @@
|
|||||||
<meta charset="UTF-8"/>
|
<meta charset="UTF-8"/>
|
||||||
<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>Yaak App</title>
|
||||||
<!-- <script src="http://localhost:8097"></script>-->
|
<script src="http://localhost:8097"></script>
|
||||||
|
|
||||||
<!-- Certain elements like webview (and maybe <select>?) will use background
|
<!-- Certain elements like webview (and maybe <select>?) will use background
|
||||||
color depending on document background color-->
|
color depending on document background color-->
|
||||||
@@ -26,8 +26,6 @@
|
|||||||
<div id="cm-portal" class="cm-portal"></div>
|
<div id="cm-portal" class="cm-portal"></div>
|
||||||
<div id="react-portal"></div>
|
<div id="react-portal"></div>
|
||||||
<div id="radix-portal" class="cm-portal"></div>
|
<div id="radix-portal" class="cm-portal"></div>
|
||||||
<script type="module" src="/theme.ts"></script>
|
<script type="module" src="/src-web/main.tsx"></script>
|
||||||
<script type="module" src="/font-size.ts"></script>
|
|
||||||
<script type="module" src="/main.tsx"></script>
|
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
Generated
+2564
-6430
File diff suppressed because it is too large
Load Diff
+102
-41
@@ -2,52 +2,113 @@
|
|||||||
"name": "yaak-app",
|
"name": "yaak-app",
|
||||||
"private": true,
|
"private": true,
|
||||||
"version": "0.0.0",
|
"version": "0.0.0",
|
||||||
"repository": {
|
"type": "module",
|
||||||
"type": "git",
|
|
||||||
"url": "git+https://github.com/mountain-loop/yaak.git"
|
|
||||||
},
|
|
||||||
"workspaces": [
|
|
||||||
"packages/plugin-runtime",
|
|
||||||
"packages/plugin-runtime-types",
|
|
||||||
"packages/common-lib",
|
|
||||||
"src-tauri/yaak-license",
|
|
||||||
"src-tauri/yaak-git",
|
|
||||||
"src-tauri/yaak-models",
|
|
||||||
"src-tauri/yaak-plugins",
|
|
||||||
"src-tauri/yaak-sse",
|
|
||||||
"src-tauri/yaak-sync",
|
|
||||||
"src-tauri/yaak-templates",
|
|
||||||
"src-tauri/yaak-ws",
|
|
||||||
"src-web"
|
|
||||||
],
|
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"start": "npm run app-dev",
|
"start": "npm run tauri-dev:desktop",
|
||||||
"app-build": "tauri build",
|
"tauri-dev:desktop": "tauri dev --no-watch --config ./src-tauri/tauri-dev.conf.json",
|
||||||
"app-dev": "tauri dev --no-watch --config ./src-tauri/tauri-dev.conf.json",
|
"tauri-dev:ios": "tauri ios dev --force-ip-prompt --config ./src-tauri/tauri-dev.conf.json",
|
||||||
"build": "npm run --workspaces --if-present build",
|
"tauri-build": "tauri build",
|
||||||
"bootstrap": "run-p bootstrap:* && npm run --workspaces --if-present bootstrap",
|
|
||||||
"bootstrap:vendor-node": "node scripts/vendor-node.cjs",
|
|
||||||
"bootstrap:vendor-plugins": "node scripts/vendor-plugins.cjs",
|
|
||||||
"bootstrap:vendor-protoc": "node scripts/vendor-protoc.cjs",
|
|
||||||
"lint": "npm run --workspaces --if-present lint",
|
|
||||||
"replace-version": "node scripts/replace-version.cjs",
|
|
||||||
"tauri": "tauri",
|
"tauri": "tauri",
|
||||||
"tauri-before-build": "npm run bootstrap && npm run --workspaces --if-present build",
|
"dev:js": "vite dev",
|
||||||
"tauri-before-dev": "npm run --workspaces --if-present 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": {
|
||||||
|
"@codemirror/commands": "^6.2.1",
|
||||||
|
"@codemirror/lang-javascript": "^6.2.2",
|
||||||
|
"@codemirror/lang-json": "^6.0.1",
|
||||||
|
"@codemirror/lang-xml": "^6.0.2",
|
||||||
|
"@codemirror/language": "^6.6.0",
|
||||||
|
"@codemirror/search": "^6.2.3",
|
||||||
|
"@lezer/generator": "^1.2.2",
|
||||||
|
"@lezer/highlight": "^1.1.3",
|
||||||
|
"@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.15",
|
||||||
|
"@tauri-apps/plugin-clipboard-manager": "^2.1.0-beta.5",
|
||||||
|
"@tauri-apps/plugin-dialog": "^2.0.0-beta.7",
|
||||||
|
"@tauri-apps/plugin-fs": "^2.0.0-beta.7",
|
||||||
|
"@tauri-apps/plugin-os": "^2.0.0-beta.7",
|
||||||
|
"@tauri-apps/plugin-shell": "^2.0.0-beta.8",
|
||||||
|
"buffer": "^6.0.3",
|
||||||
|
"classnames": "^2.3.2",
|
||||||
|
"cm6-graphql": "^0.0.9",
|
||||||
|
"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": {
|
"devDependencies": {
|
||||||
"@tauri-apps/cli": "^2.2.7",
|
"@tailwindcss/nesting": "^0.0.0-insiders.565cd3e",
|
||||||
"@typescript-eslint/eslint-plugin": "^8.18.1",
|
"@tanstack/react-query-devtools": "^5.45.1",
|
||||||
"@typescript-eslint/parser": "^8.18.1",
|
"@tauri-apps/cli": "^2.0.0-beta.22",
|
||||||
"eslint": "^8",
|
"@types/node": "^18.7.10",
|
||||||
"eslint-config-prettier": "^8",
|
"@types/papaparse": "^5.3.7",
|
||||||
"eslint-plugin-import": "^2.31.0",
|
"@types/parse-color": "^1.0.1",
|
||||||
"eslint-plugin-jsx-a11y": "^6.10.2",
|
"@types/parse-json": "^4.0.0",
|
||||||
"eslint-plugin-react": "^7.37.2",
|
"@types/react": "^18.0.31",
|
||||||
"eslint-plugin-react-hooks": "^5.1.0",
|
"@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",
|
||||||
|
"decompress": "^4.2.1",
|
||||||
|
"eslint": "^8.34.0",
|
||||||
|
"eslint-config-prettier": "^8.6.0",
|
||||||
|
"eslint-plugin-import": "^2.27.5",
|
||||||
|
"eslint-plugin-jsx-a11y": "^6.7.1",
|
||||||
|
"eslint-plugin-react": "^7.32.2",
|
||||||
|
"eslint-plugin-react-hooks": "^4.6.0",
|
||||||
|
"husky": "^8.0.3",
|
||||||
|
"internal-ip": "^8.0.0",
|
||||||
|
"lint-staged": "^15.0.2",
|
||||||
"nodejs-file-downloader": "^4.13.0",
|
"nodejs-file-downloader": "^4.13.0",
|
||||||
"npm-run-all": "^4.1.5",
|
"npm-run-all": "^4.1.5",
|
||||||
"prettier": "^3.4.2",
|
"postcss": "^8.4.21",
|
||||||
"typescript": "^5.7.2"
|
"postcss-nesting": "^11.2.1",
|
||||||
|
"prettier": "^2.8.4",
|
||||||
|
"react-devtools": "^4.27.2",
|
||||||
|
"rimraf": "^5.0.7",
|
||||||
|
"tailwindcss": "^3.2.7",
|
||||||
|
"typescript": "^5.4.5",
|
||||||
|
"vite": "^5.0.0",
|
||||||
|
"vite-plugin-static-copy": "^1.0.5",
|
||||||
|
"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"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,20 +0,0 @@
|
|||||||
export function formatSize(bytes: number): string {
|
|
||||||
let num;
|
|
||||||
let unit;
|
|
||||||
|
|
||||||
if (bytes > 1000 * 1000 * 1000) {
|
|
||||||
num = bytes / 1000 / 1000 / 1000;
|
|
||||||
unit = 'GB';
|
|
||||||
} else if (bytes > 1000 * 1000) {
|
|
||||||
num = bytes / 1000 / 1000;
|
|
||||||
unit = 'MB';
|
|
||||||
} else if (bytes > 1000) {
|
|
||||||
num = bytes / 1000;
|
|
||||||
unit = 'KB';
|
|
||||||
} else {
|
|
||||||
num = bytes;
|
|
||||||
unit = 'B';
|
|
||||||
}
|
|
||||||
|
|
||||||
return `${Math.round(num * 10) / 10} ${unit}`;
|
|
||||||
}
|
|
||||||
@@ -1 +0,0 @@
|
|||||||
export * from './debounce';
|
|
||||||
@@ -1,6 +0,0 @@
|
|||||||
{
|
|
||||||
"name": "@yaakapp-internal/lib",
|
|
||||||
"private": true,
|
|
||||||
"version": "1.0.0",
|
|
||||||
"main": "index.ts"
|
|
||||||
}
|
|
||||||
-47
@@ -1,47 +0,0 @@
|
|||||||
{
|
|
||||||
"name": "@yaakapp/api",
|
|
||||||
"version": "0.1.17",
|
|
||||||
"lockfileVersion": 3,
|
|
||||||
"requires": true,
|
|
||||||
"packages": {
|
|
||||||
"": {
|
|
||||||
"name": "@yaakapp/api",
|
|
||||||
"version": "0.1.17",
|
|
||||||
"dependencies": {
|
|
||||||
"@types/node": "^22.5.4"
|
|
||||||
},
|
|
||||||
"devDependencies": {
|
|
||||||
"typescript": "^5.6.2"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/@types/node": {
|
|
||||||
"version": "22.5.4",
|
|
||||||
"resolved": "https://registry.npmjs.org/@types/node/-/node-22.5.4.tgz",
|
|
||||||
"integrity": "sha512-FDuKUJQm/ju9fT/SeX/6+gBzoPzlVCzfzmGkwKvRHQVxi4BntVbyIwf6a4Xn62mrvndLiml6z/UBXIdEVjQLXg==",
|
|
||||||
"license": "MIT",
|
|
||||||
"dependencies": {
|
|
||||||
"undici-types": "~6.19.2"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/typescript": {
|
|
||||||
"version": "5.6.2",
|
|
||||||
"resolved": "https://registry.npmjs.org/typescript/-/typescript-5.6.2.tgz",
|
|
||||||
"integrity": "sha512-NW8ByodCSNCwZeghjN3o+JX5OFH0Ojg6sadjEKY4huZ52TqbJTJnDo5+Tw98lSy63NZvi4n+ez5m2u5d4PkZyw==",
|
|
||||||
"dev": true,
|
|
||||||
"license": "Apache-2.0",
|
|
||||||
"bin": {
|
|
||||||
"tsc": "bin/tsc",
|
|
||||||
"tsserver": "bin/tsserver"
|
|
||||||
},
|
|
||||||
"engines": {
|
|
||||||
"node": ">=14.17"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/undici-types": {
|
|
||||||
"version": "6.19.8",
|
|
||||||
"resolved": "https://registry.npmjs.org/undici-types/-/undici-types-6.19.8.tgz",
|
|
||||||
"integrity": "sha512-ve2KP6f/JnbPBFyobGHuerC9g1FYGn/F8n1LWTwNxCEzd6IfqTwUQcNXgEtmmQ6DlRrC1hrSrBnCZPokRrDHjw==",
|
|
||||||
"license": "MIT"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,27 +0,0 @@
|
|||||||
{
|
|
||||||
"name": "@yaakapp/api",
|
|
||||||
"version": "0.5.0",
|
|
||||||
"main": "lib/index.js",
|
|
||||||
"typings": "./lib/index.d.ts",
|
|
||||||
"files": [
|
|
||||||
"lib/**/*"
|
|
||||||
],
|
|
||||||
"scripts": {
|
|
||||||
"bootstrap": "npm run build",
|
|
||||||
"build": "run-s build:copy-types build:tsc",
|
|
||||||
"build:tsc": "tsc",
|
|
||||||
"build:copy-types": "run-p build:copy-types:*",
|
|
||||||
"build:copy-types:root": "cpy --flat ../../src-tauri/yaak-plugins/bindings/*.ts ./src/bindings",
|
|
||||||
"build:copy-types:next": "cpy --flat ../../src-tauri/yaak-plugins/bindings/serde_json/*.ts ./src/bindings/serde_json",
|
|
||||||
"publish": "npm publish",
|
|
||||||
"prepublishOnly": "npm run build"
|
|
||||||
},
|
|
||||||
"dependencies": {
|
|
||||||
"@types/node": "^22.5.4"
|
|
||||||
},
|
|
||||||
"devDependencies": {
|
|
||||||
"cpy-cli": "^5.0.0",
|
|
||||||
"npm-run-all": "^4.1.5",
|
|
||||||
"typescript": "^5.6.2"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,406 +0,0 @@
|
|||||||
// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually.
|
|
||||||
import type { Environment } from "./gen_models.js";
|
|
||||||
import type { Folder } from "./gen_models.js";
|
|
||||||
import type { GrpcRequest } from "./gen_models.js";
|
|
||||||
import type { HttpRequest } from "./gen_models.js";
|
|
||||||
import type { HttpResponse } from "./gen_models.js";
|
|
||||||
import type { JsonValue } from "./serde_json/JsonValue.js";
|
|
||||||
import type { WebsocketRequest } from "./gen_models.js";
|
|
||||||
import type { Workspace } from "./gen_models.js";
|
|
||||||
|
|
||||||
export type BootRequest = { dir: string, watch: boolean, };
|
|
||||||
|
|
||||||
export type BootResponse = { name: string, version: string, };
|
|
||||||
|
|
||||||
export type CallHttpAuthenticationActionArgs = { contextId: string, values: { [key in string]?: JsonPrimitive }, };
|
|
||||||
|
|
||||||
export type CallHttpAuthenticationActionRequest = { index: number, pluginRefId: string, args: CallHttpAuthenticationActionArgs, };
|
|
||||||
|
|
||||||
export type CallHttpAuthenticationRequest = { contextId: string, values: { [key in string]?: JsonPrimitive }, method: string, url: string, headers: Array<HttpHeader>, };
|
|
||||||
|
|
||||||
export type CallHttpAuthenticationResponse = {
|
|
||||||
/**
|
|
||||||
* HTTP headers to add to the request. Existing headers will be replaced, while
|
|
||||||
* new headers will be added.
|
|
||||||
*/
|
|
||||||
setHeaders: Array<HttpHeader>, };
|
|
||||||
|
|
||||||
export type CallHttpRequestActionArgs = { httpRequest: HttpRequest, };
|
|
||||||
|
|
||||||
export type CallHttpRequestActionRequest = { index: number, pluginRefId: string, args: CallHttpRequestActionArgs, };
|
|
||||||
|
|
||||||
export type CallTemplateFunctionArgs = { purpose: RenderPurpose, values: { [key in string]?: string }, };
|
|
||||||
|
|
||||||
export type CallTemplateFunctionRequest = { name: string, args: CallTemplateFunctionArgs, };
|
|
||||||
|
|
||||||
export type CallTemplateFunctionResponse = { value: string | null, };
|
|
||||||
|
|
||||||
export type CloseWindowRequest = { label: string, };
|
|
||||||
|
|
||||||
export type Color = "primary" | "secondary" | "info" | "success" | "notice" | "warning" | "danger";
|
|
||||||
|
|
||||||
export type CompletionOptionType = "constant" | "variable";
|
|
||||||
|
|
||||||
export type Content = { "type": "text", content: string, } | { "type": "markdown", content: string, };
|
|
||||||
|
|
||||||
export type CopyTextRequest = { text: string, };
|
|
||||||
|
|
||||||
export type DeleteKeyValueRequest = { key: string, };
|
|
||||||
|
|
||||||
export type DeleteKeyValueResponse = { deleted: boolean, };
|
|
||||||
|
|
||||||
export type EditorLanguage = "text" | "javascript" | "json" | "html" | "xml" | "graphql" | "markdown";
|
|
||||||
|
|
||||||
export type EmptyPayload = {};
|
|
||||||
|
|
||||||
export type ErrorResponse = { error: string, };
|
|
||||||
|
|
||||||
export type ExportHttpRequestRequest = { httpRequest: HttpRequest, };
|
|
||||||
|
|
||||||
export type ExportHttpRequestResponse = { content: string, };
|
|
||||||
|
|
||||||
export type FileFilter = { name: string,
|
|
||||||
/**
|
|
||||||
* File extensions to require
|
|
||||||
*/
|
|
||||||
extensions: Array<string>, };
|
|
||||||
|
|
||||||
export type FilterRequest = { content: string, filter: string, };
|
|
||||||
|
|
||||||
export type FilterResponse = { content: string, };
|
|
||||||
|
|
||||||
export type FindHttpResponsesRequest = { requestId: string, limit?: number, };
|
|
||||||
|
|
||||||
export type FindHttpResponsesResponse = { httpResponses: Array<HttpResponse>, };
|
|
||||||
|
|
||||||
export type FormInput = { "type": "text" } & FormInputText | { "type": "editor" } & FormInputEditor | { "type": "select" } & FormInputSelect | { "type": "checkbox" } & FormInputCheckbox | { "type": "file" } & FormInputFile | { "type": "http_request" } & FormInputHttpRequest | { "type": "accordion" } & FormInputAccordion | { "type": "banner" } & FormInputBanner | { "type": "markdown" } & FormInputMarkdown;
|
|
||||||
|
|
||||||
export type FormInputAccordion = { label: string, inputs?: Array<FormInput>, hidden?: boolean, };
|
|
||||||
|
|
||||||
export type FormInputBanner = { inputs?: Array<FormInput>, hidden?: boolean, color?: Color, };
|
|
||||||
|
|
||||||
export type FormInputBase = {
|
|
||||||
/**
|
|
||||||
* The name of the input. The value will be stored at this object attribute in the resulting data
|
|
||||||
*/
|
|
||||||
name: string,
|
|
||||||
/**
|
|
||||||
* Whether this input is visible for the given configuration. Use this to
|
|
||||||
* make branching forms.
|
|
||||||
*/
|
|
||||||
hidden?: boolean,
|
|
||||||
/**
|
|
||||||
* Whether the user must fill in the argument
|
|
||||||
*/
|
|
||||||
optional?: boolean,
|
|
||||||
/**
|
|
||||||
* The label of the input
|
|
||||||
*/
|
|
||||||
label?: string,
|
|
||||||
/**
|
|
||||||
* Visually hide the label of the input
|
|
||||||
*/
|
|
||||||
hideLabel?: boolean,
|
|
||||||
/**
|
|
||||||
* The default value
|
|
||||||
*/
|
|
||||||
defaultValue?: string, disabled?: boolean, };
|
|
||||||
|
|
||||||
export type FormInputCheckbox = {
|
|
||||||
/**
|
|
||||||
* The name of the input. The value will be stored at this object attribute in the resulting data
|
|
||||||
*/
|
|
||||||
name: string,
|
|
||||||
/**
|
|
||||||
* Whether this input is visible for the given configuration. Use this to
|
|
||||||
* make branching forms.
|
|
||||||
*/
|
|
||||||
hidden?: boolean,
|
|
||||||
/**
|
|
||||||
* Whether the user must fill in the argument
|
|
||||||
*/
|
|
||||||
optional?: boolean,
|
|
||||||
/**
|
|
||||||
* The label of the input
|
|
||||||
*/
|
|
||||||
label?: string,
|
|
||||||
/**
|
|
||||||
* Visually hide the label of the input
|
|
||||||
*/
|
|
||||||
hideLabel?: boolean,
|
|
||||||
/**
|
|
||||||
* The default value
|
|
||||||
*/
|
|
||||||
defaultValue?: string, disabled?: boolean, };
|
|
||||||
|
|
||||||
export type FormInputEditor = {
|
|
||||||
/**
|
|
||||||
* Placeholder for the text input
|
|
||||||
*/
|
|
||||||
placeholder?: string | null,
|
|
||||||
/**
|
|
||||||
* Don't show the editor gutter (line numbers, folds, etc.)
|
|
||||||
*/
|
|
||||||
hideGutter?: boolean,
|
|
||||||
/**
|
|
||||||
* Language for syntax highlighting
|
|
||||||
*/
|
|
||||||
language?: EditorLanguage, readOnly?: boolean, completionOptions?: Array<GenericCompletionOption>,
|
|
||||||
/**
|
|
||||||
* The name of the input. The value will be stored at this object attribute in the resulting data
|
|
||||||
*/
|
|
||||||
name: string,
|
|
||||||
/**
|
|
||||||
* Whether this input is visible for the given configuration. Use this to
|
|
||||||
* make branching forms.
|
|
||||||
*/
|
|
||||||
hidden?: boolean,
|
|
||||||
/**
|
|
||||||
* Whether the user must fill in the argument
|
|
||||||
*/
|
|
||||||
optional?: boolean,
|
|
||||||
/**
|
|
||||||
* The label of the input
|
|
||||||
*/
|
|
||||||
label?: string,
|
|
||||||
/**
|
|
||||||
* Visually hide the label of the input
|
|
||||||
*/
|
|
||||||
hideLabel?: boolean,
|
|
||||||
/**
|
|
||||||
* The default value
|
|
||||||
*/
|
|
||||||
defaultValue?: string, disabled?: boolean, };
|
|
||||||
|
|
||||||
export type FormInputFile = {
|
|
||||||
/**
|
|
||||||
* The title of the file selection window
|
|
||||||
*/
|
|
||||||
title: string,
|
|
||||||
/**
|
|
||||||
* Allow selecting multiple files
|
|
||||||
*/
|
|
||||||
multiple?: boolean, directory?: boolean, defaultPath?: string, filters?: Array<FileFilter>,
|
|
||||||
/**
|
|
||||||
* The name of the input. The value will be stored at this object attribute in the resulting data
|
|
||||||
*/
|
|
||||||
name: string,
|
|
||||||
/**
|
|
||||||
* Whether this input is visible for the given configuration. Use this to
|
|
||||||
* make branching forms.
|
|
||||||
*/
|
|
||||||
hidden?: boolean,
|
|
||||||
/**
|
|
||||||
* Whether the user must fill in the argument
|
|
||||||
*/
|
|
||||||
optional?: boolean,
|
|
||||||
/**
|
|
||||||
* The label of the input
|
|
||||||
*/
|
|
||||||
label?: string,
|
|
||||||
/**
|
|
||||||
* Visually hide the label of the input
|
|
||||||
*/
|
|
||||||
hideLabel?: boolean,
|
|
||||||
/**
|
|
||||||
* The default value
|
|
||||||
*/
|
|
||||||
defaultValue?: string, disabled?: boolean, };
|
|
||||||
|
|
||||||
export type FormInputHttpRequest = {
|
|
||||||
/**
|
|
||||||
* The name of the input. The value will be stored at this object attribute in the resulting data
|
|
||||||
*/
|
|
||||||
name: string,
|
|
||||||
/**
|
|
||||||
* Whether this input is visible for the given configuration. Use this to
|
|
||||||
* make branching forms.
|
|
||||||
*/
|
|
||||||
hidden?: boolean,
|
|
||||||
/**
|
|
||||||
* Whether the user must fill in the argument
|
|
||||||
*/
|
|
||||||
optional?: boolean,
|
|
||||||
/**
|
|
||||||
* The label of the input
|
|
||||||
*/
|
|
||||||
label?: string,
|
|
||||||
/**
|
|
||||||
* Visually hide the label of the input
|
|
||||||
*/
|
|
||||||
hideLabel?: boolean,
|
|
||||||
/**
|
|
||||||
* The default value
|
|
||||||
*/
|
|
||||||
defaultValue?: string, disabled?: boolean, };
|
|
||||||
|
|
||||||
export type FormInputMarkdown = { content: string, hidden?: boolean, };
|
|
||||||
|
|
||||||
export type FormInputSelect = {
|
|
||||||
/**
|
|
||||||
* The options that will be available in the select input
|
|
||||||
*/
|
|
||||||
options: Array<FormInputSelectOption>,
|
|
||||||
/**
|
|
||||||
* The name of the input. The value will be stored at this object attribute in the resulting data
|
|
||||||
*/
|
|
||||||
name: string,
|
|
||||||
/**
|
|
||||||
* Whether this input is visible for the given configuration. Use this to
|
|
||||||
* make branching forms.
|
|
||||||
*/
|
|
||||||
hidden?: boolean,
|
|
||||||
/**
|
|
||||||
* Whether the user must fill in the argument
|
|
||||||
*/
|
|
||||||
optional?: boolean,
|
|
||||||
/**
|
|
||||||
* The label of the input
|
|
||||||
*/
|
|
||||||
label?: string,
|
|
||||||
/**
|
|
||||||
* Visually hide the label of the input
|
|
||||||
*/
|
|
||||||
hideLabel?: boolean,
|
|
||||||
/**
|
|
||||||
* The default value
|
|
||||||
*/
|
|
||||||
defaultValue?: string, disabled?: boolean, };
|
|
||||||
|
|
||||||
export type FormInputSelectOption = { label: string, value: string, };
|
|
||||||
|
|
||||||
export type FormInputText = {
|
|
||||||
/**
|
|
||||||
* Placeholder for the text input
|
|
||||||
*/
|
|
||||||
placeholder?: string | null,
|
|
||||||
/**
|
|
||||||
* Placeholder for the text input
|
|
||||||
*/
|
|
||||||
password?: boolean,
|
|
||||||
/**
|
|
||||||
* Whether to allow newlines in the input, like a <textarea/>
|
|
||||||
*/
|
|
||||||
multiLine?: boolean, completionOptions?: Array<GenericCompletionOption>,
|
|
||||||
/**
|
|
||||||
* The name of the input. The value will be stored at this object attribute in the resulting data
|
|
||||||
*/
|
|
||||||
name: string,
|
|
||||||
/**
|
|
||||||
* Whether this input is visible for the given configuration. Use this to
|
|
||||||
* make branching forms.
|
|
||||||
*/
|
|
||||||
hidden?: boolean,
|
|
||||||
/**
|
|
||||||
* Whether the user must fill in the argument
|
|
||||||
*/
|
|
||||||
optional?: boolean,
|
|
||||||
/**
|
|
||||||
* The label of the input
|
|
||||||
*/
|
|
||||||
label?: string,
|
|
||||||
/**
|
|
||||||
* Visually hide the label of the input
|
|
||||||
*/
|
|
||||||
hideLabel?: boolean,
|
|
||||||
/**
|
|
||||||
* The default value
|
|
||||||
*/
|
|
||||||
defaultValue?: string, disabled?: boolean, };
|
|
||||||
|
|
||||||
export type GenericCompletionOption = { label: string, detail?: string, info?: string, type?: CompletionOptionType, boost?: number, };
|
|
||||||
|
|
||||||
export type GetHttpAuthenticationConfigRequest = { contextId: string, values: { [key in string]?: JsonPrimitive }, };
|
|
||||||
|
|
||||||
export type GetHttpAuthenticationConfigResponse = { args: Array<FormInput>, pluginRefId: string, actions?: Array<HttpAuthenticationAction>, };
|
|
||||||
|
|
||||||
export type GetHttpAuthenticationSummaryResponse = { name: string, label: string, shortLabel: string, };
|
|
||||||
|
|
||||||
export type GetHttpRequestActionsRequest = Record<string, never>;
|
|
||||||
|
|
||||||
export type GetHttpRequestActionsResponse = { actions: Array<HttpRequestAction>, pluginRefId: string, };
|
|
||||||
|
|
||||||
export type GetHttpRequestByIdRequest = { id: string, };
|
|
||||||
|
|
||||||
export type GetHttpRequestByIdResponse = { httpRequest: HttpRequest | null, };
|
|
||||||
|
|
||||||
export type GetKeyValueRequest = { key: string, };
|
|
||||||
|
|
||||||
export type GetKeyValueResponse = { value?: string, };
|
|
||||||
|
|
||||||
export type GetTemplateFunctionsResponse = { functions: Array<TemplateFunction>, pluginRefId: string, };
|
|
||||||
|
|
||||||
export type HttpAuthenticationAction = { label: string, icon?: Icon, };
|
|
||||||
|
|
||||||
export type HttpHeader = { name: string, value: string, };
|
|
||||||
|
|
||||||
export type HttpRequestAction = { label: string, icon?: Icon, };
|
|
||||||
|
|
||||||
export type Icon = "alert_triangle" | "check" | "check_circle" | "chevron_down" | "copy" | "info" | "pin" | "search" | "trash" | "_unknown";
|
|
||||||
|
|
||||||
export type ImportRequest = { content: string, };
|
|
||||||
|
|
||||||
export type ImportResources = { workspaces: Array<Workspace>, environments: Array<Environment>, folders: Array<Folder>, httpRequests: Array<HttpRequest>, grpcRequests: Array<GrpcRequest>, websocketRequests: Array<WebsocketRequest>, };
|
|
||||||
|
|
||||||
export type ImportResponse = { resources: ImportResources, };
|
|
||||||
|
|
||||||
export type InternalEvent = { id: string, pluginRefId: string, pluginName: string, replyId: string | null, windowContext: WindowContext, payload: InternalEventPayload, };
|
|
||||||
|
|
||||||
export type InternalEventPayload = { "type": "boot_request" } & BootRequest | { "type": "boot_response" } & BootResponse | { "type": "reload_request" } & EmptyPayload | { "type": "reload_response" } & EmptyPayload | { "type": "terminate_request" } | { "type": "terminate_response" } | { "type": "import_request" } & ImportRequest | { "type": "import_response" } & ImportResponse | { "type": "filter_request" } & FilterRequest | { "type": "filter_response" } & FilterResponse | { "type": "export_http_request_request" } & ExportHttpRequestRequest | { "type": "export_http_request_response" } & ExportHttpRequestResponse | { "type": "send_http_request_request" } & SendHttpRequestRequest | { "type": "send_http_request_response" } & SendHttpRequestResponse | { "type": "get_http_request_actions_request" } & EmptyPayload | { "type": "get_http_request_actions_response" } & GetHttpRequestActionsResponse | { "type": "call_http_request_action_request" } & CallHttpRequestActionRequest | { "type": "get_template_functions_request" } | { "type": "get_template_functions_response" } & GetTemplateFunctionsResponse | { "type": "call_template_function_request" } & CallTemplateFunctionRequest | { "type": "call_template_function_response" } & CallTemplateFunctionResponse | { "type": "get_http_authentication_summary_request" } & EmptyPayload | { "type": "get_http_authentication_summary_response" } & GetHttpAuthenticationSummaryResponse | { "type": "get_http_authentication_config_request" } & GetHttpAuthenticationConfigRequest | { "type": "get_http_authentication_config_response" } & GetHttpAuthenticationConfigResponse | { "type": "call_http_authentication_request" } & CallHttpAuthenticationRequest | { "type": "call_http_authentication_response" } & CallHttpAuthenticationResponse | { "type": "call_http_authentication_action_request" } & CallHttpAuthenticationActionRequest | { "type": "call_http_authentication_action_response" } & EmptyPayload | { "type": "copy_text_request" } & CopyTextRequest | { "type": "copy_text_response" } & EmptyPayload | { "type": "render_http_request_request" } & RenderHttpRequestRequest | { "type": "render_http_request_response" } & RenderHttpRequestResponse | { "type": "get_key_value_request" } & GetKeyValueRequest | { "type": "get_key_value_response" } & GetKeyValueResponse | { "type": "set_key_value_request" } & SetKeyValueRequest | { "type": "set_key_value_response" } & SetKeyValueResponse | { "type": "delete_key_value_request" } & DeleteKeyValueRequest | { "type": "delete_key_value_response" } & DeleteKeyValueResponse | { "type": "open_window_request" } & OpenWindowRequest | { "type": "window_navigate_event" } & WindowNavigateEvent | { "type": "window_close_event" } | { "type": "close_window_request" } & CloseWindowRequest | { "type": "template_render_request" } & TemplateRenderRequest | { "type": "template_render_response" } & TemplateRenderResponse | { "type": "show_toast_request" } & ShowToastRequest | { "type": "show_toast_response" } & EmptyPayload | { "type": "prompt_text_request" } & PromptTextRequest | { "type": "prompt_text_response" } & PromptTextResponse | { "type": "get_http_request_by_id_request" } & GetHttpRequestByIdRequest | { "type": "get_http_request_by_id_response" } & GetHttpRequestByIdResponse | { "type": "find_http_responses_request" } & FindHttpResponsesRequest | { "type": "find_http_responses_response" } & FindHttpResponsesResponse | { "type": "empty_response" } & EmptyPayload | { "type": "error_response" } & ErrorResponse;
|
|
||||||
|
|
||||||
export type JsonPrimitive = string | number | boolean | null;
|
|
||||||
|
|
||||||
export type OpenWindowRequest = { url: string,
|
|
||||||
/**
|
|
||||||
* Label for the window. If not provided, a random one will be generated.
|
|
||||||
*/
|
|
||||||
label: string, title?: string, size?: WindowSize, dataDirKey?: string, };
|
|
||||||
|
|
||||||
export type PromptTextRequest = { id: string, title: string, label: string, description?: string, defaultValue?: string, placeholder?: string,
|
|
||||||
/**
|
|
||||||
* Text to add to the confirmation button
|
|
||||||
*/
|
|
||||||
confirmText?: string,
|
|
||||||
/**
|
|
||||||
* Text to add to the cancel button
|
|
||||||
*/
|
|
||||||
cancelText?: string,
|
|
||||||
/**
|
|
||||||
* Require the user to enter a non-empty value
|
|
||||||
*/
|
|
||||||
required?: boolean, };
|
|
||||||
|
|
||||||
export type PromptTextResponse = { value: string | null, };
|
|
||||||
|
|
||||||
export type RenderHttpRequestRequest = { httpRequest: HttpRequest, purpose: RenderPurpose, };
|
|
||||||
|
|
||||||
export type RenderHttpRequestResponse = { httpRequest: HttpRequest, };
|
|
||||||
|
|
||||||
export type RenderPurpose = "send" | "preview";
|
|
||||||
|
|
||||||
export type SendHttpRequestRequest = { httpRequest: Partial<HttpRequest>, };
|
|
||||||
|
|
||||||
export type SendHttpRequestResponse = { httpResponse: HttpResponse, };
|
|
||||||
|
|
||||||
export type SetKeyValueRequest = { key: string, value: string, };
|
|
||||||
|
|
||||||
export type SetKeyValueResponse = {};
|
|
||||||
|
|
||||||
export type ShowToastRequest = { message: string, color?: Color, icon?: Icon, };
|
|
||||||
|
|
||||||
export type TemplateFunction = { name: string, description?: string,
|
|
||||||
/**
|
|
||||||
* Also support alternative names. This is useful for not breaking existing
|
|
||||||
* tags when changing the `name` property
|
|
||||||
*/
|
|
||||||
aliases?: Array<string>, args: Array<FormInput>, };
|
|
||||||
|
|
||||||
export type TemplateRenderRequest = { data: JsonValue, purpose: RenderPurpose, };
|
|
||||||
|
|
||||||
export type TemplateRenderResponse = { data: JsonValue, };
|
|
||||||
|
|
||||||
export type WindowContext = { "type": "none" } | { "type": "label", label: string, };
|
|
||||||
|
|
||||||
export type WindowNavigateEvent = { url: string, };
|
|
||||||
|
|
||||||
export type WindowSize = { width: number, height: number, };
|
|
||||||
@@ -1,27 +0,0 @@
|
|||||||
// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually.
|
|
||||||
|
|
||||||
export type Environment = { model: "environment", id: string, workspaceId: string, environmentId: string | null, createdAt: string, updatedAt: string, name: string, variables: Array<EnvironmentVariable>, };
|
|
||||||
|
|
||||||
export type EnvironmentVariable = { enabled?: boolean, name: string, value: string, id?: string, };
|
|
||||||
|
|
||||||
export type Folder = { model: "folder", id: string, createdAt: string, updatedAt: string, workspaceId: string, folderId: string | null, name: string, description: string, sortPriority: number, };
|
|
||||||
|
|
||||||
export type GrpcMetadataEntry = { enabled?: boolean, name: string, value: string, id?: string, };
|
|
||||||
|
|
||||||
export type GrpcRequest = { model: "grpc_request", id: string, createdAt: string, updatedAt: string, workspaceId: string, folderId: string | null, authenticationType: string | null, authentication: Record<string, any>, description: string, message: string, metadata: Array<GrpcMetadataEntry>, method: string | null, name: string, service: string | null, sortPriority: number, url: string, };
|
|
||||||
|
|
||||||
export type HttpRequest = { model: "http_request", id: string, createdAt: string, updatedAt: string, workspaceId: string, folderId: string | null, authentication: Record<string, any>, authenticationType: string | null, body: Record<string, any>, bodyType: string | null, description: string, headers: Array<HttpRequestHeader>, method: string, name: string, sortPriority: number, url: string, urlParameters: Array<HttpUrlParameter>, };
|
|
||||||
|
|
||||||
export type HttpRequestHeader = { enabled?: boolean, name: string, value: string, id?: string, };
|
|
||||||
|
|
||||||
export type HttpResponse = { model: "http_response", id: string, createdAt: string, updatedAt: string, workspaceId: string, requestId: string, bodyPath: string | null, contentLength: number | null, elapsed: number, elapsedHeaders: number, error: string | null, headers: Array<HttpResponseHeader>, remoteAddr: string | null, status: number, statusReason: string | null, state: HttpResponseState, url: string, version: string | null, };
|
|
||||||
|
|
||||||
export type HttpResponseHeader = { name: string, value: string, };
|
|
||||||
|
|
||||||
export type HttpResponseState = "initialized" | "connected" | "closed";
|
|
||||||
|
|
||||||
export type HttpUrlParameter = { enabled?: boolean, name: string, value: string, id?: string, };
|
|
||||||
|
|
||||||
export type WebsocketRequest = { model: "websocket_request", id: string, createdAt: string, updatedAt: string, workspaceId: string, folderId: string | null, authentication: Record<string, any>, authenticationType: string | null, description: string, headers: Array<HttpRequestHeader>, message: string, name: string, sortPriority: number, url: string, urlParameters: Array<HttpUrlParameter>, };
|
|
||||||
|
|
||||||
export type Workspace = { model: "workspace", id: string, createdAt: string, updatedAt: string, name: string, description: string, settingValidateCertificates: boolean, settingFollowRedirects: boolean, settingRequestTimeout: number, };
|
|
||||||
@@ -1,3 +0,0 @@
|
|||||||
// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually.
|
|
||||||
|
|
||||||
export type JsonValue = number | string | Array<JsonValue> | { [key in string]?: JsonValue };
|
|
||||||
@@ -1,2 +0,0 @@
|
|||||||
export type AtLeast<T, K extends keyof T> = Partial<T> & Pick<T, K>;
|
|
||||||
export type MaybePromise<T> = Promise<T> | T;
|
|
||||||
@@ -1,5 +0,0 @@
|
|||||||
export type * from './plugins';
|
|
||||||
export type * from './themes';
|
|
||||||
|
|
||||||
export * from './bindings/gen_models';
|
|
||||||
export * from './bindings/gen_events';
|
|
||||||
@@ -1,29 +0,0 @@
|
|||||||
import {
|
|
||||||
CallHttpAuthenticationActionArgs,
|
|
||||||
CallHttpAuthenticationRequest,
|
|
||||||
CallHttpAuthenticationResponse,
|
|
||||||
FormInput,
|
|
||||||
GetHttpAuthenticationConfigRequest,
|
|
||||||
GetHttpAuthenticationSummaryResponse,
|
|
||||||
HttpAuthenticationAction,
|
|
||||||
} from '../bindings/gen_events';
|
|
||||||
import { MaybePromise } from '../helpers';
|
|
||||||
import { Context } from './Context';
|
|
||||||
|
|
||||||
type DynamicFormInput = FormInput & {
|
|
||||||
dynamic(
|
|
||||||
ctx: Context,
|
|
||||||
args: GetHttpAuthenticationConfigRequest,
|
|
||||||
): MaybePromise<Partial<FormInput> | undefined | null>;
|
|
||||||
};
|
|
||||||
|
|
||||||
export type AuthenticationPlugin = GetHttpAuthenticationSummaryResponse & {
|
|
||||||
args: (FormInput | DynamicFormInput)[];
|
|
||||||
onApply(
|
|
||||||
ctx: Context,
|
|
||||||
args: CallHttpAuthenticationRequest,
|
|
||||||
): MaybePromise<CallHttpAuthenticationResponse>;
|
|
||||||
actions?: (HttpAuthenticationAction & {
|
|
||||||
onSelect(ctx: Context, args: CallHttpAuthenticationActionArgs): Promise<void> | void;
|
|
||||||
})[];
|
|
||||||
};
|
|
||||||
@@ -1,52 +0,0 @@
|
|||||||
import type {
|
|
||||||
FindHttpResponsesRequest,
|
|
||||||
FindHttpResponsesResponse,
|
|
||||||
GetHttpRequestByIdRequest,
|
|
||||||
GetHttpRequestByIdResponse,
|
|
||||||
OpenWindowRequest,
|
|
||||||
PromptTextRequest,
|
|
||||||
PromptTextResponse,
|
|
||||||
RenderHttpRequestRequest,
|
|
||||||
RenderHttpRequestResponse,
|
|
||||||
SendHttpRequestRequest,
|
|
||||||
SendHttpRequestResponse,
|
|
||||||
ShowToastRequest,
|
|
||||||
TemplateRenderRequest,
|
|
||||||
TemplateRenderResponse,
|
|
||||||
} from '../bindings/gen_events.ts';
|
|
||||||
|
|
||||||
export interface Context {
|
|
||||||
clipboard: {
|
|
||||||
copyText(text: string): Promise<void>;
|
|
||||||
};
|
|
||||||
toast: {
|
|
||||||
show(args: ShowToastRequest): Promise<void>;
|
|
||||||
};
|
|
||||||
prompt: {
|
|
||||||
text(args: PromptTextRequest): Promise<PromptTextResponse['value']>;
|
|
||||||
};
|
|
||||||
store: {
|
|
||||||
set<T>(key: string, value: T): Promise<void>;
|
|
||||||
get<T>(key: string): Promise<T | undefined>;
|
|
||||||
delete(key: string): Promise<boolean>;
|
|
||||||
};
|
|
||||||
window: {
|
|
||||||
openUrl(
|
|
||||||
args: OpenWindowRequest & {
|
|
||||||
onNavigate?: (args: { url: string }) => void;
|
|
||||||
onClose: () => void;
|
|
||||||
},
|
|
||||||
): Promise<{ close: () => void }>;
|
|
||||||
};
|
|
||||||
httpRequest: {
|
|
||||||
send(args: SendHttpRequestRequest): Promise<SendHttpRequestResponse['httpResponse']>;
|
|
||||||
getById(args: GetHttpRequestByIdRequest): Promise<GetHttpRequestByIdResponse['httpRequest']>;
|
|
||||||
render(args: RenderHttpRequestRequest): Promise<RenderHttpRequestResponse['httpRequest']>;
|
|
||||||
};
|
|
||||||
httpResponse: {
|
|
||||||
find(args: FindHttpResponsesRequest): Promise<FindHttpResponsesResponse['httpResponses']>;
|
|
||||||
};
|
|
||||||
templates: {
|
|
||||||
render(args: TemplateRenderRequest): Promise<TemplateRenderResponse['data']>;
|
|
||||||
};
|
|
||||||
}
|
|
||||||
@@ -1,12 +0,0 @@
|
|||||||
import type { Context } from './Context';
|
|
||||||
|
|
||||||
export type FilterPluginResponse = { filtered: string };
|
|
||||||
|
|
||||||
export type FilterPlugin = {
|
|
||||||
name: string;
|
|
||||||
description?: string;
|
|
||||||
onFilter(
|
|
||||||
ctx: Context,
|
|
||||||
args: { payload: string; filter: string; mimeType: string },
|
|
||||||
): Promise<FilterPluginResponse> | FilterPluginResponse;
|
|
||||||
};
|
|
||||||
@@ -1,6 +0,0 @@
|
|||||||
import type { CallHttpRequestActionArgs, HttpRequestAction } from '../bindings/gen_events';
|
|
||||||
import type { Context } from './Context';
|
|
||||||
|
|
||||||
export type HttpRequestActionPlugin = HttpRequestAction & {
|
|
||||||
onSelect(ctx: Context, args: CallHttpRequestActionArgs): Promise<void> | void;
|
|
||||||
};
|
|
||||||
@@ -1,19 +0,0 @@
|
|||||||
import { Environment, Folder, GrpcRequest, HttpRequest, Workspace } from '../bindings/gen_models';
|
|
||||||
import type { AtLeast } from '../helpers';
|
|
||||||
import type { Context } from './Context';
|
|
||||||
|
|
||||||
type ImportPluginResponse = null | {
|
|
||||||
resources: {
|
|
||||||
workspaces: AtLeast<Workspace, 'name' | 'id' | 'model'>[];
|
|
||||||
environments: AtLeast<Environment, 'name' | 'id' | 'model' | 'workspaceId'>[];
|
|
||||||
folders: AtLeast<Folder, 'name' | 'id' | 'model' | 'workspaceId'>[];
|
|
||||||
httpRequests: AtLeast<HttpRequest, 'name' | 'id' | 'model' | 'workspaceId'>[];
|
|
||||||
grpcRequests: AtLeast<GrpcRequest, 'name' | 'id' | 'model' | 'workspaceId'>[];
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
export type ImporterPlugin = {
|
|
||||||
name: string;
|
|
||||||
description?: string;
|
|
||||||
onImport(ctx: Context, args: { text: string }): Promise<ImportPluginResponse>;
|
|
||||||
};
|
|
||||||
@@ -1,12 +0,0 @@
|
|||||||
import {
|
|
||||||
CallTemplateFunctionArgs,
|
|
||||||
TemplateFunction,
|
|
||||||
} from "../bindings/gen_events";
|
|
||||||
import { Context } from "./Context";
|
|
||||||
|
|
||||||
export type TemplateFunctionPlugin = TemplateFunction & {
|
|
||||||
onRender(
|
|
||||||
ctx: Context,
|
|
||||||
args: CallTemplateFunctionArgs,
|
|
||||||
): Promise<string | null>;
|
|
||||||
};
|
|
||||||
@@ -1,8 +0,0 @@
|
|||||||
import { Index } from "../themes";
|
|
||||||
import { Context } from "./Context";
|
|
||||||
|
|
||||||
export type ThemePlugin = {
|
|
||||||
name: string;
|
|
||||||
description?: string;
|
|
||||||
getTheme(ctx: Context, fileContents: string): Promise<Index>;
|
|
||||||
};
|
|
||||||
@@ -1,20 +0,0 @@
|
|||||||
import { AuthenticationPlugin } from './AuthenticationPlugin';
|
|
||||||
import type { FilterPlugin } from './FilterPlugin';
|
|
||||||
import type { HttpRequestActionPlugin } from './HttpRequestActionPlugin';
|
|
||||||
import type { ImporterPlugin } from './ImporterPlugin';
|
|
||||||
import type { TemplateFunctionPlugin } from './TemplateFunctionPlugin';
|
|
||||||
import type { ThemePlugin } from './ThemePlugin';
|
|
||||||
|
|
||||||
export type { Context } from './Context';
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The global structure of a Yaak plugin
|
|
||||||
*/
|
|
||||||
export type PluginDefinition = {
|
|
||||||
importer?: ImporterPlugin;
|
|
||||||
theme?: ThemePlugin;
|
|
||||||
filter?: FilterPlugin;
|
|
||||||
authentication?: AuthenticationPlugin;
|
|
||||||
httpRequestActions?: HttpRequestActionPlugin[];
|
|
||||||
templateFunctions?: TemplateFunctionPlugin[];
|
|
||||||
};
|
|
||||||
@@ -1,44 +0,0 @@
|
|||||||
export type Colors = {
|
|
||||||
surface: string;
|
|
||||||
surfaceHighlight?: string;
|
|
||||||
surfaceActive?: string;
|
|
||||||
|
|
||||||
text: string;
|
|
||||||
textSubtle?: string;
|
|
||||||
textSubtlest?: string;
|
|
||||||
|
|
||||||
border?: string;
|
|
||||||
borderSubtle?: string;
|
|
||||||
borderFocus?: string;
|
|
||||||
|
|
||||||
shadow?: string;
|
|
||||||
backdrop?: string;
|
|
||||||
selection?: string;
|
|
||||||
|
|
||||||
primary?: string;
|
|
||||||
secondary?: string;
|
|
||||||
info?: string;
|
|
||||||
success?: string;
|
|
||||||
notice?: string;
|
|
||||||
warning?: string;
|
|
||||||
danger?: string;
|
|
||||||
};
|
|
||||||
|
|
||||||
export type Index = Colors & {
|
|
||||||
id: string;
|
|
||||||
name: string;
|
|
||||||
components?: Partial<{
|
|
||||||
dialog: Partial<Colors>;
|
|
||||||
menu: Partial<Colors>;
|
|
||||||
toast: Partial<Colors>;
|
|
||||||
sidebar: Partial<Colors>;
|
|
||||||
responsePane: Partial<Colors>;
|
|
||||||
appHeader: Partial<Colors>;
|
|
||||||
button: Partial<Colors>;
|
|
||||||
banner: Partial<Colors>;
|
|
||||||
placeholder: Partial<Colors>;
|
|
||||||
urlBar: Partial<Colors>;
|
|
||||||
editor: Partial<Colors>;
|
|
||||||
input: Partial<Colors>;
|
|
||||||
}>;
|
|
||||||
};
|
|
||||||
@@ -1,15 +0,0 @@
|
|||||||
{
|
|
||||||
"compilerOptions": {
|
|
||||||
"module": "node16",
|
|
||||||
"target": "es6",
|
|
||||||
"lib": ["es2021"],
|
|
||||||
"declaration": true,
|
|
||||||
"declarationDir": "./lib",
|
|
||||||
"outDir": "./lib",
|
|
||||||
"strict": true,
|
|
||||||
"types": ["node"]
|
|
||||||
},
|
|
||||||
"files": [
|
|
||||||
"src/index.ts"
|
|
||||||
]
|
|
||||||
}
|
|
||||||
-10
@@ -1,10 +0,0 @@
|
|||||||
{
|
|
||||||
"name": "@yaakapp-internal/plugin-runtime",
|
|
||||||
"lockfileVersion": 3,
|
|
||||||
"requires": true,
|
|
||||||
"packages": {
|
|
||||||
"": {
|
|
||||||
"name": "@yaakapp-internal/plugin-runtime"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,14 +0,0 @@
|
|||||||
{
|
|
||||||
"name": "@yaakapp-internal/plugin-runtime",
|
|
||||||
"scripts": {
|
|
||||||
"bootstrap": "npm run build",
|
|
||||||
"build": "run-p build:*",
|
|
||||||
"build:main": "esbuild src/index.ts --bundle --platform=node --outfile=../../src-tauri/vendored/plugin-runtime/index.cjs"
|
|
||||||
},
|
|
||||||
"dependencies": {
|
|
||||||
"ws": "^8.18.0"
|
|
||||||
},
|
|
||||||
"devDependencies": {
|
|
||||||
"@types/ws": "^8.5.13"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,19 +0,0 @@
|
|||||||
import type { InternalEvent } from '@yaakapp/api';
|
|
||||||
|
|
||||||
export class EventChannel {
|
|
||||||
#listeners = new Set<(event: InternalEvent) => void>();
|
|
||||||
|
|
||||||
emit(e: InternalEvent) {
|
|
||||||
for (const l of this.#listeners) {
|
|
||||||
l(e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
listen(cb: (e: InternalEvent) => void) {
|
|
||||||
this.#listeners.add(cb);
|
|
||||||
}
|
|
||||||
|
|
||||||
unlisten(cb: (e: InternalEvent) => void) {
|
|
||||||
this.#listeners.delete(cb);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,28 +0,0 @@
|
|||||||
import type { BootRequest, InternalEvent } from '@yaakapp/api';
|
|
||||||
import type { EventChannel } from './EventChannel';
|
|
||||||
import { PluginInstance, PluginWorkerData } from './PluginInstance';
|
|
||||||
|
|
||||||
export class PluginHandle {
|
|
||||||
#instance: PluginInstance;
|
|
||||||
|
|
||||||
constructor(
|
|
||||||
readonly pluginRefId: string,
|
|
||||||
readonly bootRequest: BootRequest,
|
|
||||||
readonly pluginToAppEvents: EventChannel,
|
|
||||||
) {
|
|
||||||
const workerData: PluginWorkerData = {
|
|
||||||
pluginRefId: this.pluginRefId,
|
|
||||||
bootRequest: this.bootRequest,
|
|
||||||
};
|
|
||||||
this.#instance = new PluginInstance(workerData, pluginToAppEvents);
|
|
||||||
console.log('Created plugin worker for ', this.bootRequest.dir);
|
|
||||||
}
|
|
||||||
|
|
||||||
sendToWorker(event: InternalEvent) {
|
|
||||||
this.#instance.postMessage(event);
|
|
||||||
}
|
|
||||||
|
|
||||||
terminate() {
|
|
||||||
this.#instance.terminate();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,597 +0,0 @@
|
|||||||
import type {
|
|
||||||
BootRequest,
|
|
||||||
Context,
|
|
||||||
DeleteKeyValueResponse,
|
|
||||||
FindHttpResponsesResponse,
|
|
||||||
FormInput,
|
|
||||||
GetHttpRequestByIdResponse,
|
|
||||||
GetKeyValueResponse,
|
|
||||||
HttpAuthenticationAction,
|
|
||||||
HttpRequestAction,
|
|
||||||
InternalEvent,
|
|
||||||
InternalEventPayload,
|
|
||||||
JsonPrimitive,
|
|
||||||
PluginDefinition,
|
|
||||||
PromptTextResponse,
|
|
||||||
RenderHttpRequestResponse,
|
|
||||||
SendHttpRequestResponse,
|
|
||||||
TemplateFunction,
|
|
||||||
TemplateRenderResponse,
|
|
||||||
WindowContext,
|
|
||||||
} from '@yaakapp/api';
|
|
||||||
import console from 'node:console';
|
|
||||||
import { readFileSync, type Stats, statSync, watch } from 'node:fs';
|
|
||||||
import path from 'node:path';
|
|
||||||
// import util from 'node:util';
|
|
||||||
import { EventChannel } from './EventChannel';
|
|
||||||
// import { interceptStdout } from './interceptStdout';
|
|
||||||
import { migrateTemplateFunctionSelectOptions } from './migrations';
|
|
||||||
|
|
||||||
export interface PluginWorkerData {
|
|
||||||
bootRequest: BootRequest;
|
|
||||||
pluginRefId: string;
|
|
||||||
}
|
|
||||||
|
|
||||||
export class PluginInstance {
|
|
||||||
#workerData: PluginWorkerData;
|
|
||||||
#mod: PluginDefinition;
|
|
||||||
#pkg: { name?: string; version?: string };
|
|
||||||
#pluginToAppEvents: EventChannel;
|
|
||||||
#appToPluginEvents: EventChannel;
|
|
||||||
|
|
||||||
constructor(workerData: PluginWorkerData, pluginEvents: EventChannel) {
|
|
||||||
this.#workerData = workerData;
|
|
||||||
this.#pluginToAppEvents = pluginEvents;
|
|
||||||
this.#appToPluginEvents = new EventChannel();
|
|
||||||
|
|
||||||
// Forward incoming events to onMessage()
|
|
||||||
this.#appToPluginEvents.listen(async event => {
|
|
||||||
await this.#onMessage(event);
|
|
||||||
})
|
|
||||||
|
|
||||||
// Reload plugin if the JS or package.json changes
|
|
||||||
const windowContextNone: WindowContext = { type: 'none' };
|
|
||||||
const fileChangeCallback = async () => {
|
|
||||||
this.#importModule();
|
|
||||||
return this.#sendPayload(windowContextNone, { type: 'reload_response' }, null);
|
|
||||||
};
|
|
||||||
|
|
||||||
if (this.#workerData.bootRequest.watch) {
|
|
||||||
watchFile(this.#pathMod(), fileChangeCallback);
|
|
||||||
watchFile(this.#pathPkg(), fileChangeCallback);
|
|
||||||
}
|
|
||||||
|
|
||||||
this.#mod = {};
|
|
||||||
this.#pkg = JSON.parse(readFileSync(this.#pathPkg(), 'utf8'));
|
|
||||||
|
|
||||||
// TODO: Re-implement this now that we're not using workers
|
|
||||||
// prefixStdout(`[plugin][${this.#pkg.name}] %s`);
|
|
||||||
|
|
||||||
this.#importModule();
|
|
||||||
}
|
|
||||||
|
|
||||||
postMessage(event: InternalEvent) {
|
|
||||||
this.#appToPluginEvents.emit(event);
|
|
||||||
}
|
|
||||||
|
|
||||||
terminate() {
|
|
||||||
this.#unimportModule();
|
|
||||||
}
|
|
||||||
|
|
||||||
async #onMessage(event: InternalEvent) {
|
|
||||||
const ctx = this.#newCtx(event);
|
|
||||||
|
|
||||||
const { windowContext, payload, id: replyId } = event;
|
|
||||||
try {
|
|
||||||
if (payload.type === 'boot_request') {
|
|
||||||
// console.log('Plugin initialized', pkg.name, { capabilities, enableWatch });
|
|
||||||
const payload: InternalEventPayload = {
|
|
||||||
type: 'boot_response',
|
|
||||||
name: this.#pkg.name ?? 'unknown',
|
|
||||||
version: this.#pkg.version ?? '0.0.1',
|
|
||||||
};
|
|
||||||
this.#sendPayload(windowContext, payload, replyId);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (payload.type === 'terminate_request') {
|
|
||||||
const payload: InternalEventPayload = {
|
|
||||||
type: 'terminate_response',
|
|
||||||
};
|
|
||||||
this.#sendPayload(windowContext, payload, replyId);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (
|
|
||||||
payload.type === 'import_request' &&
|
|
||||||
typeof this.#mod?.importer?.onImport === 'function'
|
|
||||||
) {
|
|
||||||
const reply = await this.#mod.importer.onImport(ctx, {
|
|
||||||
text: payload.content,
|
|
||||||
});
|
|
||||||
if (reply != null) {
|
|
||||||
const replyPayload: InternalEventPayload = {
|
|
||||||
type: 'import_response',
|
|
||||||
// deno-lint-ignore no-explicit-any
|
|
||||||
resources: reply.resources as any,
|
|
||||||
};
|
|
||||||
this.#sendPayload(windowContext, replyPayload, replyId);
|
|
||||||
return;
|
|
||||||
} else {
|
|
||||||
// Continue, to send back an empty reply
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (payload.type === 'filter_request' && typeof this.#mod?.filter?.onFilter === 'function') {
|
|
||||||
const reply = await this.#mod.filter.onFilter(ctx, {
|
|
||||||
filter: payload.filter,
|
|
||||||
payload: payload.content,
|
|
||||||
mimeType: payload.type,
|
|
||||||
});
|
|
||||||
const replyPayload: InternalEventPayload = {
|
|
||||||
type: 'filter_response',
|
|
||||||
content: reply.filtered,
|
|
||||||
};
|
|
||||||
this.#sendPayload(windowContext, replyPayload, replyId);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (
|
|
||||||
payload.type === 'get_http_request_actions_request' &&
|
|
||||||
Array.isArray(this.#mod?.httpRequestActions)
|
|
||||||
) {
|
|
||||||
const reply: HttpRequestAction[] = this.#mod.httpRequestActions.map((a) => ({
|
|
||||||
...a,
|
|
||||||
// Add everything except onSelect
|
|
||||||
onSelect: undefined,
|
|
||||||
}));
|
|
||||||
const replyPayload: InternalEventPayload = {
|
|
||||||
type: 'get_http_request_actions_response',
|
|
||||||
pluginRefId: this.#workerData.pluginRefId,
|
|
||||||
actions: reply,
|
|
||||||
};
|
|
||||||
this.#sendPayload(windowContext, replyPayload, replyId);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (
|
|
||||||
payload.type === 'get_template_functions_request' &&
|
|
||||||
Array.isArray(this.#mod?.templateFunctions)
|
|
||||||
) {
|
|
||||||
const reply: TemplateFunction[] = this.#mod.templateFunctions.map((templateFunction) => {
|
|
||||||
return {
|
|
||||||
...migrateTemplateFunctionSelectOptions(templateFunction),
|
|
||||||
// Add everything except render
|
|
||||||
onRender: undefined,
|
|
||||||
};
|
|
||||||
});
|
|
||||||
const replyPayload: InternalEventPayload = {
|
|
||||||
type: 'get_template_functions_response',
|
|
||||||
pluginRefId: this.#workerData.pluginRefId,
|
|
||||||
functions: reply,
|
|
||||||
};
|
|
||||||
this.#sendPayload(windowContext, replyPayload, replyId);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (payload.type === 'get_http_authentication_summary_request' && this.#mod?.authentication) {
|
|
||||||
const { name, shortLabel, label } = this.#mod.authentication;
|
|
||||||
const replyPayload: InternalEventPayload = {
|
|
||||||
type: 'get_http_authentication_summary_response',
|
|
||||||
name,
|
|
||||||
label,
|
|
||||||
shortLabel,
|
|
||||||
};
|
|
||||||
|
|
||||||
this.#sendPayload(windowContext, replyPayload, replyId);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (payload.type === 'get_http_authentication_config_request' && this.#mod?.authentication) {
|
|
||||||
const { args, actions } = this.#mod.authentication;
|
|
||||||
const resolvedArgs: FormInput[] = [];
|
|
||||||
for (let i = 0; i < args.length; i++) {
|
|
||||||
let v = args[i];
|
|
||||||
if ('dynamic' in v) {
|
|
||||||
const dynamicAttrs = await v.dynamic(ctx, payload);
|
|
||||||
const { dynamic, ...other } = v;
|
|
||||||
resolvedArgs.push({ ...other, ...dynamicAttrs } as FormInput);
|
|
||||||
} else {
|
|
||||||
resolvedArgs.push(v);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
const resolvedActions: HttpAuthenticationAction[] = [];
|
|
||||||
for (const { onSelect, ...action } of actions ?? []) {
|
|
||||||
resolvedActions.push(action);
|
|
||||||
}
|
|
||||||
|
|
||||||
const replyPayload: InternalEventPayload = {
|
|
||||||
type: 'get_http_authentication_config_response',
|
|
||||||
args: resolvedArgs,
|
|
||||||
actions: resolvedActions,
|
|
||||||
pluginRefId: this.#workerData.pluginRefId,
|
|
||||||
};
|
|
||||||
|
|
||||||
this.#sendPayload(windowContext, replyPayload, replyId);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (payload.type === 'call_http_authentication_request' && this.#mod?.authentication) {
|
|
||||||
const auth = this.#mod.authentication;
|
|
||||||
if (typeof auth?.onApply === 'function') {
|
|
||||||
applyFormInputDefaults(auth.args, payload.values);
|
|
||||||
const result = await auth.onApply(ctx, payload);
|
|
||||||
this.#sendPayload(
|
|
||||||
windowContext,
|
|
||||||
{
|
|
||||||
type: 'call_http_authentication_response',
|
|
||||||
setHeaders: result.setHeaders,
|
|
||||||
},
|
|
||||||
replyId,
|
|
||||||
);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (
|
|
||||||
payload.type === 'call_http_authentication_action_request' &&
|
|
||||||
this.#mod.authentication != null
|
|
||||||
) {
|
|
||||||
const action = this.#mod.authentication.actions?.[payload.index];
|
|
||||||
if (typeof action?.onSelect === 'function') {
|
|
||||||
await action.onSelect(ctx, payload.args);
|
|
||||||
this.#sendEmpty(windowContext, replyId);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (
|
|
||||||
payload.type === 'call_http_request_action_request' &&
|
|
||||||
Array.isArray(this.#mod.httpRequestActions)
|
|
||||||
) {
|
|
||||||
const action = this.#mod.httpRequestActions[payload.index];
|
|
||||||
if (typeof action?.onSelect === 'function') {
|
|
||||||
await action.onSelect(ctx, payload.args);
|
|
||||||
this.#sendEmpty(windowContext, replyId);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (
|
|
||||||
payload.type === 'call_template_function_request' &&
|
|
||||||
Array.isArray(this.#mod?.templateFunctions)
|
|
||||||
) {
|
|
||||||
const action = this.#mod.templateFunctions.find((a) => a.name === payload.name);
|
|
||||||
if (typeof action?.onRender === 'function') {
|
|
||||||
applyFormInputDefaults(action.args, payload.args.values);
|
|
||||||
const result = await action.onRender(ctx, payload.args);
|
|
||||||
this.#sendPayload(
|
|
||||||
windowContext,
|
|
||||||
{
|
|
||||||
type: 'call_template_function_response',
|
|
||||||
value: result ?? null,
|
|
||||||
},
|
|
||||||
replyId,
|
|
||||||
);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (payload.type === 'reload_request') {
|
|
||||||
this.#importModule();
|
|
||||||
}
|
|
||||||
} catch (err) {
|
|
||||||
console.log('Plugin call threw exception', payload.type, err);
|
|
||||||
this.#sendPayload(
|
|
||||||
windowContext,
|
|
||||||
{
|
|
||||||
type: 'error_response',
|
|
||||||
error: `${err}`,
|
|
||||||
},
|
|
||||||
replyId,
|
|
||||||
);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// No matches, so send back an empty response so the caller doesn't block forever
|
|
||||||
this.#sendEmpty(windowContext, replyId);
|
|
||||||
}
|
|
||||||
|
|
||||||
#pathMod() {
|
|
||||||
return path.posix.join(this.#workerData.bootRequest.dir, 'build', 'index.js');
|
|
||||||
}
|
|
||||||
|
|
||||||
#pathPkg() {
|
|
||||||
return path.join(this.#workerData.bootRequest.dir, 'package.json');
|
|
||||||
}
|
|
||||||
|
|
||||||
#unimportModule() {
|
|
||||||
const id = require.resolve(this.#pathMod());
|
|
||||||
delete require.cache[id];
|
|
||||||
}
|
|
||||||
|
|
||||||
#importModule() {
|
|
||||||
const id = require.resolve(this.#pathMod());
|
|
||||||
delete require.cache[id];
|
|
||||||
this.#mod = require(id).plugin;
|
|
||||||
}
|
|
||||||
|
|
||||||
#buildEventToSend(
|
|
||||||
windowContext: WindowContext,
|
|
||||||
payload: InternalEventPayload,
|
|
||||||
replyId: string | null = null,
|
|
||||||
): InternalEvent {
|
|
||||||
return {
|
|
||||||
pluginRefId: this.#workerData.pluginRefId,
|
|
||||||
pluginName: path.basename(this.#workerData.bootRequest.dir),
|
|
||||||
id: genId(),
|
|
||||||
replyId,
|
|
||||||
payload,
|
|
||||||
windowContext,
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
#sendPayload(
|
|
||||||
windowContext: WindowContext,
|
|
||||||
payload: InternalEventPayload,
|
|
||||||
replyId: string | null,
|
|
||||||
): string {
|
|
||||||
const event = this.#buildEventToSend(windowContext, payload, replyId);
|
|
||||||
this.#sendEvent(event);
|
|
||||||
return event.id;
|
|
||||||
}
|
|
||||||
|
|
||||||
#sendEvent(event: InternalEvent) {
|
|
||||||
// if (event.payload.type !== 'empty_response') {
|
|
||||||
// console.log('Sending event to app', this.#pkg.name, event.id, event.payload.type);
|
|
||||||
// }
|
|
||||||
this.#pluginToAppEvents.emit(event);
|
|
||||||
}
|
|
||||||
|
|
||||||
#sendEmpty(windowContext: WindowContext, replyId: string | null = null): string {
|
|
||||||
return this.#sendPayload(windowContext, { type: 'empty_response' }, replyId);
|
|
||||||
}
|
|
||||||
|
|
||||||
#sendAndWaitForReply<T extends Omit<InternalEventPayload, 'type'>>(
|
|
||||||
windowContext: WindowContext,
|
|
||||||
payload: InternalEventPayload,
|
|
||||||
): Promise<T> {
|
|
||||||
// 1. Build event to send
|
|
||||||
const eventToSend = this.#buildEventToSend(windowContext, payload, null);
|
|
||||||
|
|
||||||
// 2. Spawn listener in background
|
|
||||||
const promise = new Promise<T>((resolve) => {
|
|
||||||
const cb = (event: InternalEvent) => {
|
|
||||||
if (event.replyId === eventToSend.id) {
|
|
||||||
this.#appToPluginEvents.unlisten(cb); // Unlisten, now that we're done
|
|
||||||
const { type: _, ...payload } = event.payload;
|
|
||||||
resolve(payload as T);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
this.#appToPluginEvents.listen(cb);
|
|
||||||
});
|
|
||||||
|
|
||||||
// 3. Send the event after we start listening (to prevent race)
|
|
||||||
this.#sendEvent(eventToSend);
|
|
||||||
|
|
||||||
// 4. Return the listener promise
|
|
||||||
return promise as unknown as Promise<T>;
|
|
||||||
}
|
|
||||||
|
|
||||||
#sendAndListenForEvents(
|
|
||||||
windowContext: WindowContext,
|
|
||||||
payload: InternalEventPayload,
|
|
||||||
onEvent: (event: InternalEventPayload) => void,
|
|
||||||
): void {
|
|
||||||
// 1. Build event to send
|
|
||||||
const eventToSend = this.#buildEventToSend(windowContext, payload, null);
|
|
||||||
|
|
||||||
// 2. Listen for replies in the background
|
|
||||||
this.#appToPluginEvents.listen((event: InternalEvent) => {
|
|
||||||
if (event.replyId === eventToSend.id) {
|
|
||||||
onEvent(event.payload);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
// 3. Send the event after we start listening (to prevent race)
|
|
||||||
this.#sendEvent(eventToSend);
|
|
||||||
}
|
|
||||||
|
|
||||||
#newCtx(event: InternalEvent): Context {
|
|
||||||
return {
|
|
||||||
clipboard: {
|
|
||||||
copyText: async (text) => {
|
|
||||||
await this.#sendAndWaitForReply(event.windowContext, {
|
|
||||||
type: 'copy_text_request',
|
|
||||||
text,
|
|
||||||
});
|
|
||||||
},
|
|
||||||
},
|
|
||||||
toast: {
|
|
||||||
show: async (args) => {
|
|
||||||
await this.#sendAndWaitForReply(event.windowContext, {
|
|
||||||
type: 'show_toast_request',
|
|
||||||
...args,
|
|
||||||
});
|
|
||||||
},
|
|
||||||
},
|
|
||||||
window: {
|
|
||||||
openUrl: async ({ onNavigate, onClose, ...args }) => {
|
|
||||||
args.label = args.label || `${Math.random()}`;
|
|
||||||
const payload: InternalEventPayload = { type: 'open_window_request', ...args };
|
|
||||||
const onEvent = (event: InternalEventPayload) => {
|
|
||||||
if (event.type === 'window_navigate_event') {
|
|
||||||
onNavigate?.(event);
|
|
||||||
} else if (event.type === 'window_close_event') {
|
|
||||||
onClose?.();
|
|
||||||
}
|
|
||||||
};
|
|
||||||
this.#sendAndListenForEvents(event.windowContext, payload, onEvent);
|
|
||||||
return {
|
|
||||||
close: () => {
|
|
||||||
const closePayload: InternalEventPayload = {
|
|
||||||
type: 'close_window_request',
|
|
||||||
label: args.label,
|
|
||||||
};
|
|
||||||
this.#sendPayload(event.windowContext, closePayload, null);
|
|
||||||
},
|
|
||||||
};
|
|
||||||
},
|
|
||||||
},
|
|
||||||
prompt: {
|
|
||||||
text: async (args) => {
|
|
||||||
const reply: PromptTextResponse = await this.#sendAndWaitForReply(event.windowContext, {
|
|
||||||
type: 'prompt_text_request',
|
|
||||||
...args,
|
|
||||||
});
|
|
||||||
return reply.value;
|
|
||||||
},
|
|
||||||
},
|
|
||||||
httpResponse: {
|
|
||||||
find: async (args) => {
|
|
||||||
const payload = {
|
|
||||||
type: 'find_http_responses_request',
|
|
||||||
...args,
|
|
||||||
} as const;
|
|
||||||
const { httpResponses } = await this.#sendAndWaitForReply<FindHttpResponsesResponse>(
|
|
||||||
event.windowContext,
|
|
||||||
payload,
|
|
||||||
);
|
|
||||||
return httpResponses;
|
|
||||||
},
|
|
||||||
},
|
|
||||||
httpRequest: {
|
|
||||||
getById: async (args) => {
|
|
||||||
const payload = {
|
|
||||||
type: 'get_http_request_by_id_request',
|
|
||||||
...args,
|
|
||||||
} as const;
|
|
||||||
const { httpRequest } = await this.#sendAndWaitForReply<GetHttpRequestByIdResponse>(
|
|
||||||
event.windowContext,
|
|
||||||
payload,
|
|
||||||
);
|
|
||||||
return httpRequest;
|
|
||||||
},
|
|
||||||
send: async (args) => {
|
|
||||||
const payload = {
|
|
||||||
type: 'send_http_request_request',
|
|
||||||
...args,
|
|
||||||
} as const;
|
|
||||||
const { httpResponse } = await this.#sendAndWaitForReply<SendHttpRequestResponse>(
|
|
||||||
event.windowContext,
|
|
||||||
payload,
|
|
||||||
);
|
|
||||||
return httpResponse;
|
|
||||||
},
|
|
||||||
render: async (args) => {
|
|
||||||
const payload = {
|
|
||||||
type: 'render_http_request_request',
|
|
||||||
...args,
|
|
||||||
} as const;
|
|
||||||
const { httpRequest } = await this.#sendAndWaitForReply<RenderHttpRequestResponse>(
|
|
||||||
event.windowContext,
|
|
||||||
payload,
|
|
||||||
);
|
|
||||||
return httpRequest;
|
|
||||||
},
|
|
||||||
},
|
|
||||||
templates: {
|
|
||||||
/**
|
|
||||||
* Invoke Yaak's template engine to render a value. If the value is a nested type
|
|
||||||
* (eg. object), it will be recursively rendered.
|
|
||||||
*/
|
|
||||||
render: async (args) => {
|
|
||||||
const payload = { type: 'template_render_request', ...args } as const;
|
|
||||||
const result = await this.#sendAndWaitForReply<TemplateRenderResponse>(
|
|
||||||
event.windowContext,
|
|
||||||
payload,
|
|
||||||
);
|
|
||||||
return result.data;
|
|
||||||
},
|
|
||||||
},
|
|
||||||
store: {
|
|
||||||
get: async <T>(key: string) => {
|
|
||||||
const payload = { type: 'get_key_value_request', key } as const;
|
|
||||||
const result = await this.#sendAndWaitForReply<GetKeyValueResponse>(
|
|
||||||
event.windowContext,
|
|
||||||
payload,
|
|
||||||
);
|
|
||||||
return result.value ? (JSON.parse(result.value) as T) : undefined;
|
|
||||||
},
|
|
||||||
set: async <T>(key: string, value: T) => {
|
|
||||||
const valueStr = JSON.stringify(value);
|
|
||||||
const payload: InternalEventPayload = {
|
|
||||||
type: 'set_key_value_request',
|
|
||||||
key,
|
|
||||||
value: valueStr,
|
|
||||||
};
|
|
||||||
await this.#sendAndWaitForReply<GetKeyValueResponse>(event.windowContext, payload);
|
|
||||||
},
|
|
||||||
delete: async (key: string) => {
|
|
||||||
const payload = { type: 'delete_key_value_request', key } as const;
|
|
||||||
const result = await this.#sendAndWaitForReply<DeleteKeyValueResponse>(
|
|
||||||
event.windowContext,
|
|
||||||
payload,
|
|
||||||
);
|
|
||||||
return result.deleted;
|
|
||||||
},
|
|
||||||
},
|
|
||||||
};
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function genId(len = 5): string {
|
|
||||||
const alphabet = '01234567890abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ';
|
|
||||||
let id = '';
|
|
||||||
for (let i = 0; i < len; i++) {
|
|
||||||
id += alphabet[Math.floor(Math.random() * alphabet.length)];
|
|
||||||
}
|
|
||||||
return id;
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Recursively apply form input defaults to a set of values */
|
|
||||||
function applyFormInputDefaults(
|
|
||||||
inputs: FormInput[],
|
|
||||||
values: { [p: string]: JsonPrimitive | undefined },
|
|
||||||
) {
|
|
||||||
for (const input of inputs) {
|
|
||||||
if ('inputs' in input) {
|
|
||||||
applyFormInputDefaults(input.inputs ?? [], values);
|
|
||||||
} else if ('defaultValue' in input && values[input.name] === undefined) {
|
|
||||||
values[input.name] = input.defaultValue;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
const watchedFiles: Record<string, Stats> = {};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Watch a file and trigger callback on change.
|
|
||||||
*
|
|
||||||
* We also track the stat for each file because fs.watch() will
|
|
||||||
* trigger a "change" event when the access date changes
|
|
||||||
*/
|
|
||||||
function watchFile(filepath: string, cb: (filepath: string) => void) {
|
|
||||||
watch(filepath, () => {
|
|
||||||
const stat = statSync(filepath);
|
|
||||||
if (stat.mtimeMs !== watchedFiles[filepath]?.mtimeMs) {
|
|
||||||
cb(filepath);
|
|
||||||
}
|
|
||||||
watchedFiles[filepath] = stat;
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
// function prefixStdout(s: string) {
|
|
||||||
// if (!s.includes('%s')) {
|
|
||||||
// throw new Error('Console prefix must contain a "%s" replacer');
|
|
||||||
// }
|
|
||||||
// interceptStdout((text: string) => {
|
|
||||||
// const lines = text.split(/\n/);
|
|
||||||
// let newText = '';
|
|
||||||
// for (let i = 0; i < lines.length; i++) {
|
|
||||||
// if (lines[i] == '') continue;
|
|
||||||
// newText += util.format(s, lines[i]) + '\n';
|
|
||||||
// }
|
|
||||||
// return newText.trimEnd();
|
|
||||||
// });
|
|
||||||
// }
|
|
||||||
@@ -1,55 +0,0 @@
|
|||||||
import type { InternalEvent } from '@yaakapp/api';
|
|
||||||
import { EventChannel } from './EventChannel';
|
|
||||||
import { PluginHandle } from './PluginHandle';
|
|
||||||
import WebSocket from 'ws';
|
|
||||||
|
|
||||||
const port = process.env.PORT;
|
|
||||||
if (!port) {
|
|
||||||
throw new Error('Plugin runtime missing PORT')
|
|
||||||
}
|
|
||||||
|
|
||||||
const pluginToAppEvents = new EventChannel();
|
|
||||||
const plugins: Record<string, PluginHandle> = {};
|
|
||||||
|
|
||||||
const ws = new WebSocket(`ws://localhost:${port}`);
|
|
||||||
|
|
||||||
ws.on('message', async (e: Buffer) => {
|
|
||||||
try {
|
|
||||||
await handleIncoming(e.toString());
|
|
||||||
} catch (err) {
|
|
||||||
console.log('Failed to handle incoming plugin event', err);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
ws.on('open', () => console.log('Plugin runtime connected to websocket'));
|
|
||||||
ws.on('error', (err: any) => console.error('Plugin runtime websocket error', err));
|
|
||||||
ws.on('close', (code: number) => console.log('Plugin runtime websocket closed', code));
|
|
||||||
|
|
||||||
// Listen for incoming events from plugins
|
|
||||||
pluginToAppEvents.listen((e) => {
|
|
||||||
const eventStr = JSON.stringify(e);
|
|
||||||
ws.send(eventStr);
|
|
||||||
});
|
|
||||||
|
|
||||||
async function handleIncoming(msg: string) {
|
|
||||||
const pluginEvent: InternalEvent = JSON.parse(msg);
|
|
||||||
// Handle special event to bootstrap plugin
|
|
||||||
if (pluginEvent.payload.type === 'boot_request') {
|
|
||||||
const plugin = new PluginHandle(pluginEvent.pluginRefId, pluginEvent.payload, pluginToAppEvents);
|
|
||||||
plugins[pluginEvent.pluginRefId] = plugin;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Once booted, forward all events to the plugin worker
|
|
||||||
const plugin = plugins[pluginEvent.pluginRefId];
|
|
||||||
if (!plugin) {
|
|
||||||
console.warn('Failed to get plugin for event by', pluginEvent.pluginRefId);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (pluginEvent.payload.type === 'terminate_request') {
|
|
||||||
plugin.terminate();
|
|
||||||
console.log('Terminated plugin worker', pluginEvent.pluginRefId);
|
|
||||||
delete plugins[pluginEvent.pluginRefId];
|
|
||||||
}
|
|
||||||
|
|
||||||
plugin.sendToWorker(pluginEvent);
|
|
||||||
}
|
|
||||||
@@ -1,37 +0,0 @@
|
|||||||
import process from "node:process";
|
|
||||||
|
|
||||||
export function interceptStdout(
|
|
||||||
intercept: (text: string) => string,
|
|
||||||
) {
|
|
||||||
const old_stdout_write = process.stdout.write;
|
|
||||||
const old_stderr_write = process.stderr.write;
|
|
||||||
|
|
||||||
process.stdout.write = (function (write) {
|
|
||||||
return function (text: string) {
|
|
||||||
arguments[0] = interceptor(text, intercept);
|
|
||||||
// deno-lint-ignore no-explicit-any
|
|
||||||
write.apply(process.stdout, arguments as any);
|
|
||||||
return true;
|
|
||||||
};
|
|
||||||
})(process.stdout.write);
|
|
||||||
|
|
||||||
process.stderr.write = (function (write) {
|
|
||||||
return function (text: string) {
|
|
||||||
arguments[0] = interceptor(text, intercept);
|
|
||||||
// deno-lint-ignore no-explicit-any
|
|
||||||
write.apply(process.stderr, arguments as any);
|
|
||||||
return true;
|
|
||||||
};
|
|
||||||
})(process.stderr.write);
|
|
||||||
|
|
||||||
// puts back to original
|
|
||||||
return function unhook() {
|
|
||||||
process.stdout.write = old_stdout_write;
|
|
||||||
process.stderr.write = old_stderr_write;
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
function interceptor(text: string, fn: (text: string) => string) {
|
|
||||||
return fn(text).replace(/\n$/, "") +
|
|
||||||
(fn(text) && /\n$/.test(text) ? "\n" : "");
|
|
||||||
}
|
|
||||||
@@ -1,18 +0,0 @@
|
|||||||
import { TemplateFunction } from '@yaakapp/api';
|
|
||||||
|
|
||||||
export function migrateTemplateFunctionSelectOptions(f: TemplateFunction): TemplateFunction {
|
|
||||||
const migratedArgs = f.args.map((a) => {
|
|
||||||
if (a.type === 'select') {
|
|
||||||
a.options = a.options.map((o) => ({
|
|
||||||
...o,
|
|
||||||
label: o.label || (o as any).name,
|
|
||||||
}));
|
|
||||||
}
|
|
||||||
return a;
|
|
||||||
});
|
|
||||||
|
|
||||||
return {
|
|
||||||
...f,
|
|
||||||
args: migratedArgs,
|
|
||||||
};
|
|
||||||
}
|
|
||||||
@@ -1,2 +1,3 @@
|
|||||||
lib
|
build
|
||||||
node_modules
|
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));
|
||||||
|
}
|
||||||
@@ -7,11 +7,11 @@
|
|||||||
"target": "es2021",
|
"target": "es2021",
|
||||||
"lib": ["es2021"],
|
"lib": ["es2021"],
|
||||||
"noImplicitAny": false,
|
"noImplicitAny": false,
|
||||||
"moduleResolution": "node16",
|
"moduleResolution": "node",
|
||||||
"resolveJsonModule": true,
|
|
||||||
"sourceMap": true,
|
"sourceMap": true,
|
||||||
"outDir": "build",
|
"outDir": "dist",
|
||||||
"baseUrl": ".",
|
"baseUrl": ".",
|
||||||
|
"skipLibCheck": true,
|
||||||
"paths": {
|
"paths": {
|
||||||
"*": [
|
"*": [
|
||||||
"node_modules/*",
|
"node_modules/*",
|
||||||
@@ -20,6 +20,6 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"include": [
|
"include": [
|
||||||
"src"
|
"src/**/*"
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
@@ -3,9 +3,30 @@ syntax = "proto3";
|
|||||||
package yaak.plugins.runtime;
|
package yaak.plugins.runtime;
|
||||||
|
|
||||||
service PluginRuntime {
|
service PluginRuntime {
|
||||||
rpc EventStream (stream EventStreamEvent) returns (stream EventStreamEvent);
|
rpc hookImport (HookImportRequest) returns (HookResponse);
|
||||||
|
rpc hookExport (HookExportRequest) returns (HookResponse);
|
||||||
|
rpc hookResponseFilter (HookResponseFilterRequest) returns (HookResponse);
|
||||||
}
|
}
|
||||||
|
|
||||||
message EventStreamEvent {
|
message PluginInfo {
|
||||||
string event = 1;
|
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,7 +1 @@
|
|||||||
edition = "2018"
|
edition = "2018"
|
||||||
|
|
||||||
# Widths
|
|
||||||
chain_width = 100
|
|
||||||
max_width = 100
|
|
||||||
single_line_if_else_max_width = 100
|
|
||||||
fn_call_width = 100
|
|
||||||
|
|||||||
@@ -1 +0,0 @@
|
|||||||
tmp-*
|
|
||||||
+15
-29
@@ -1,10 +1,10 @@
|
|||||||
const path = require('node:path');
|
const path = require('node:path');
|
||||||
const decompress = require('decompress');
|
const decompress = require('decompress');
|
||||||
const Downloader = require('nodejs-file-downloader');
|
const Downloader = require("nodejs-file-downloader");
|
||||||
const { rmSync, cpSync, mkdirSync, existsSync } = require('node:fs');
|
const {rmSync, cpSync, mkdirSync, existsSync} = require("node:fs");
|
||||||
const { execSync } = require('node:child_process');
|
const {execSync} = require("node:child_process");
|
||||||
|
|
||||||
const NODE_VERSION = 'v22.9.0';
|
const NODE_VERSION = 'v22.5.1';
|
||||||
|
|
||||||
// `${process.platform}_${process.arch}`
|
// `${process.platform}_${process.arch}`
|
||||||
const MAC_ARM = 'darwin_arm64';
|
const MAC_ARM = 'darwin_arm64';
|
||||||
@@ -39,26 +39,20 @@ const destDir = path.join(__dirname, `..`, 'src-tauri', 'vendored', 'node');
|
|||||||
const binDest = path.join(destDir, DST_BIN_MAP[key]);
|
const binDest = path.join(destDir, DST_BIN_MAP[key]);
|
||||||
console.log(`Vendoring NodeJS ${NODE_VERSION} for ${key}`);
|
console.log(`Vendoring NodeJS ${NODE_VERSION} for ${key}`);
|
||||||
|
|
||||||
if (existsSync(binDest) && tryExecSync(`${binDest} --version`).trim() === NODE_VERSION) {
|
if (existsSync(binDest) && execSync(`${binDest} --version`).toString('utf-8').trim() === NODE_VERSION) {
|
||||||
console.log('NodeJS already vendored');
|
console.log("NodeJS already vendored");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
rmSync(destDir, { recursive: true, force: true });
|
rmSync(destDir, {recursive: true, force: true});
|
||||||
mkdirSync(destDir, { recursive: true });
|
mkdirSync(destDir, {recursive: true});
|
||||||
|
|
||||||
const url = URL_MAP[key];
|
|
||||||
const tmpDir = path.join(__dirname, 'tmp-node');
|
|
||||||
rmSync(tmpDir, { recursive: true, force: true });
|
|
||||||
|
|
||||||
(async function () {
|
(async function () {
|
||||||
|
const url = URL_MAP[key];
|
||||||
|
const tmpDir = path.join(__dirname, 'tmp', Date.now().toString());
|
||||||
|
|
||||||
// Download GitHub release artifact
|
// Download GitHub release artifact
|
||||||
console.log('Downloading NodeJS at', url);
|
const {filePath} = await new Downloader({url, directory: tmpDir,}).download();
|
||||||
const { filePath } = await new Downloader({
|
|
||||||
url,
|
|
||||||
directory: tmpDir,
|
|
||||||
timeout: 1000 * 60 * 2,
|
|
||||||
}).download();
|
|
||||||
|
|
||||||
// Decompress to the same directory
|
// Decompress to the same directory
|
||||||
await decompress(filePath, tmpDir, {});
|
await decompress(filePath, tmpDir, {});
|
||||||
@@ -66,18 +60,10 @@ rmSync(tmpDir, { recursive: true, force: true });
|
|||||||
// Copy binary
|
// Copy binary
|
||||||
const binSrc = path.join(tmpDir, SRC_BIN_MAP[key]);
|
const binSrc = path.join(tmpDir, SRC_BIN_MAP[key]);
|
||||||
cpSync(binSrc, binDest);
|
cpSync(binSrc, binDest);
|
||||||
rmSync(tmpDir, { recursive: true, force: true });
|
rmSync(tmpDir, {recursive: true, force: true});
|
||||||
|
|
||||||
console.log('Downloaded NodeJS to', binDest);
|
console.log("Downloaded NodeJS to", binDest);
|
||||||
})().catch((err) => {
|
})().catch(err => {
|
||||||
console.log('Script failed:', err);
|
console.log('Script failed:', err);
|
||||||
process.exit(1);
|
process.exit(1);
|
||||||
});
|
});
|
||||||
|
|
||||||
function tryExecSync(cmd) {
|
|
||||||
try {
|
|
||||||
return execSync(cmd).toString('utf-8');
|
|
||||||
} catch (_) {
|
|
||||||
return '';
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -1,16 +1,16 @@
|
|||||||
const { readdirSync, cpSync } = require('node:fs');
|
const {readdirSync, cpSync} = require("node:fs");
|
||||||
const path = require('node:path');
|
const path = require("node:path");
|
||||||
const { execSync } = require('node:child_process');
|
const {execSync} = require("node:child_process");
|
||||||
const pluginsDir = process.env.YAAK_PLUGINS_DIR;
|
const pluginsDir = process.env.YAAK_PLUGINS_DIR;
|
||||||
if (!pluginsDir) {
|
if (!pluginsDir) {
|
||||||
console.log('Skipping bundled plugins build because YAAK_PLUGINS_DIR is not set');
|
console.log("YAAK_PLUGINS_DIR is not set");
|
||||||
return;
|
process.exit(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
console.log('Installing Yaak plugins dependencies', pluginsDir);
|
console.log('Installing Yaak plugins dependencies', pluginsDir);
|
||||||
execSync('npm ci', { cwd: pluginsDir });
|
execSync('npm ci', {cwd: pluginsDir});
|
||||||
console.log('Building Yaak plugins', pluginsDir);
|
console.log('Building Yaak plugins', pluginsDir);
|
||||||
execSync('npm run build', { cwd: pluginsDir });
|
execSync('npm run build', {cwd: pluginsDir});
|
||||||
|
|
||||||
console.log('Copying Yaak plugins to', pluginsDir);
|
console.log('Copying Yaak plugins to', pluginsDir);
|
||||||
|
|
||||||
|
|||||||
+21
-43
@@ -1,10 +1,7 @@
|
|||||||
const decompress = require('decompress');
|
const decompress = require('decompress');
|
||||||
const Downloader = require('nodejs-file-downloader');
|
const Downloader = require("nodejs-file-downloader");
|
||||||
const path = require('node:path');
|
const path = require("node:path");
|
||||||
const { rmSync, mkdirSync, cpSync, existsSync, statSync, chmodSync } = require('node:fs');
|
const {rmSync, mkdirSync, cpSync} = require("node:fs");
|
||||||
const { execSync } = require('node:child_process');
|
|
||||||
|
|
||||||
const VERSION = '28.3';
|
|
||||||
|
|
||||||
// `${process.platform}_${process.arch}`
|
// `${process.platform}_${process.arch}`
|
||||||
const MAC_ARM = 'darwin_arm64';
|
const MAC_ARM = 'darwin_arm64';
|
||||||
@@ -13,10 +10,10 @@ const LNX_X64 = 'linux_x64';
|
|||||||
const WIN_X64 = 'win32_x64';
|
const WIN_X64 = 'win32_x64';
|
||||||
|
|
||||||
const URL_MAP = {
|
const URL_MAP = {
|
||||||
[MAC_ARM]: `https://github.com/protocolbuffers/protobuf/releases/download/v${VERSION}/protoc-${VERSION}-osx-aarch_64.zip`,
|
[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/v${VERSION}/protoc-${VERSION}-osx-x86_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/v${VERSION}/protoc-${VERSION}-linux-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/v${VERSION}/protoc-${VERSION}-win64.zip`,
|
[WIN_X64]: 'https://github.com/protocolbuffers/protobuf/releases/download/v27.2/protoc-27.2-win64.zip',
|
||||||
};
|
};
|
||||||
|
|
||||||
const SRC_BIN_MAP = {
|
const SRC_BIN_MAP = {
|
||||||
@@ -34,51 +31,32 @@ const DST_BIN_MAP = {
|
|||||||
};
|
};
|
||||||
|
|
||||||
const dstDir = path.join(__dirname, `..`, 'src-tauri', 'vendored', 'protoc');
|
const dstDir = path.join(__dirname, `..`, 'src-tauri', 'vendored', 'protoc');
|
||||||
const key = `${process.platform}_${process.env.YAAK_TARGET_ARCH ?? process.arch}`;
|
rmSync(dstDir, {recursive: true, force: true});
|
||||||
console.log(`Vendoring protoc ${VERSION} for ${key}`);
|
mkdirSync(dstDir, {recursive: true});
|
||||||
|
|
||||||
const url = URL_MAP[key];
|
|
||||||
const tmpDir = path.join(__dirname, 'tmp-protoc');
|
|
||||||
const binSrc = path.join(tmpDir, SRC_BIN_MAP[key]);
|
|
||||||
const binDst = path.join(dstDir, DST_BIN_MAP[key]);
|
|
||||||
|
|
||||||
if (existsSync(binDst) && tryExecSync(`${binDst} --version`).trim().includes(VERSION)) {
|
|
||||||
console.log('Protoc already vendored');
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
rmSync(tmpDir, { recursive: true, force: true });
|
|
||||||
rmSync(dstDir, { recursive: true, force: true });
|
|
||||||
mkdirSync(dstDir, { recursive: true });
|
|
||||||
|
|
||||||
(async function () {
|
(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
|
// Download GitHub release artifact
|
||||||
const { filePath } = await new Downloader({ url, directory: tmpDir }).download();
|
const {filePath} = await new Downloader({url, directory: tmpDir,}).download();
|
||||||
|
|
||||||
// Decompress to the same directory
|
// Decompress to the same directory
|
||||||
await decompress(filePath, tmpDir, {});
|
await decompress(filePath, tmpDir, {});
|
||||||
|
|
||||||
// Copy binary
|
// Copy binary
|
||||||
|
const binSrc = path.join(tmpDir, SRC_BIN_MAP[key]);
|
||||||
|
const binDst = path.join(dstDir, DST_BIN_MAP[key]);
|
||||||
cpSync(binSrc, binDst);
|
cpSync(binSrc, binDst);
|
||||||
|
|
||||||
// Copy other files
|
// Copy other files
|
||||||
const includeSrc = path.join(tmpDir, 'include');
|
const includeSrc = path.join(tmpDir, 'include');
|
||||||
const includeDst = path.join(dstDir, 'include');
|
const includeDst = path.join(dstDir, 'include');
|
||||||
cpSync(includeSrc, includeDst, { recursive: true });
|
cpSync(includeSrc, includeDst, {recursive: true});
|
||||||
rmSync(tmpDir, { recursive: true, force: true });
|
|
||||||
|
|
||||||
// Make binary writable, so we can sign it during release
|
rmSync(tmpDir, {recursive: true, force: true});
|
||||||
const stat = statSync(binDst);
|
|
||||||
const newMode = stat.mode | 0o200;
|
|
||||||
chmodSync(binDst, newMode);
|
|
||||||
|
|
||||||
console.log('Downloaded protoc to', binDst);
|
console.log("Downloaded protoc to", binDst);
|
||||||
})().catch((err) => console.log('Script failed:', err));
|
})().catch(err => console.log('Script failed:', err));
|
||||||
|
|
||||||
function tryExecSync(cmd) {
|
|
||||||
try {
|
|
||||||
return execSync(cmd).toString('utf-8');
|
|
||||||
} catch (_) {
|
|
||||||
return '';
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -1,6 +1,5 @@
|
|||||||
# Generated by Cargo
|
# Generated by Cargo
|
||||||
# will have compiled files and executables
|
# will have compiled files and executables
|
||||||
target/
|
/target/
|
||||||
|
|
||||||
vendored/*
|
vendored
|
||||||
!vendored/plugins
|
|
||||||
|
|||||||
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"
|
||||||
|
}
|
||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user