data endpoint for entity 90008 (aka. a website)
0
fork

Configure Feed

Select the types of activity you want to include in your feed.

replace skyware with atcute

dawn 25657ddd eea7033b

+219 -417
+48 -119
deno.lock
··· 1 1 { 2 2 "version": "5", 3 3 "specifiers": { 4 + "npm:@atcute/atproto@^3.1.11": "3.1.11", 5 + "npm:@atcute/bluesky@^3.3.3": "3.3.3", 6 + "npm:@atcute/client@^4.2.1": "4.2.1", 7 + "npm:@atcute/lexicons@^1.3.0": "1.3.0", 8 + "npm:@atcute/microcosm@^1.0.3": "1.0.3", 9 + "npm:@atcute/tid@^1.1.2": "1.1.2", 4 10 "npm:@darkvisitors/sdk@^1.6.0": "1.6.0", 5 11 "npm:@jsr/std__toml@1.0.11": "1.0.11", 6 12 "npm:@neodrag/svelte@^2.3.3": "2.3.3_svelte@5.46.1__acorn@8.15.0", 7 13 "npm:@rowanmanning/feed-parser@*": "2.1.1", 8 14 "npm:@rowanmanning/feed-parser@^2.1.1": "2.1.1", 9 - "npm:@skyware/bot@0.4": "0.4.0", 10 15 "npm:@sveltejs/adapter-node@^5.4.0": "5.4.0_@sveltejs+kit@2.49.4__@sveltejs+vite-plugin-svelte@6.2.4___svelte@5.46.1____acorn@8.15.0___vite@7.3.1____@types+node@25.0.6____picomatch@4.0.3___@types+node@25.0.6__svelte@5.46.1___acorn@8.15.0__typescript@5.9.3__vite@7.3.1___@types+node@25.0.6___picomatch@4.0.3__acorn@8.15.0__@types+node@25.0.6_rollup@4.53.3_@sveltejs+vite-plugin-svelte@6.2.4__svelte@5.46.1___acorn@8.15.0__vite@7.3.1___@types+node@25.0.6___picomatch@4.0.3__@types+node@25.0.6_svelte@5.46.1__acorn@8.15.0_typescript@5.9.3_vite@7.3.1__@types+node@25.0.6__picomatch@4.0.3_@types+node@25.0.6", 11 16 "npm:@sveltejs/kit@^2.49.4": "2.49.4_@sveltejs+vite-plugin-svelte@6.2.4__svelte@5.46.1___acorn@8.15.0__vite@7.3.1___@types+node@25.0.6___picomatch@4.0.3__@types+node@25.0.6_svelte@5.46.1__acorn@8.15.0_typescript@5.9.3_vite@7.3.1__@types+node@25.0.6__picomatch@4.0.3_acorn@8.15.0_@types+node@25.0.6", 12 17 "npm:@sveltejs/vite-plugin-svelte@^6.2.4": "6.2.4_svelte@5.46.1__acorn@8.15.0_vite@7.3.1__@types+node@25.0.6__picomatch@4.0.3_@types+node@25.0.6", ··· 53 58 "@alloc/quick-lru@5.2.0": { 54 59 "integrity": "sha512-UrcABB+4bUrFABwbluTIBErXwvbsU/V7TZWfmbgJfbkwiBuziS9gxdODUyuiecfdGQ85jglMW6juS3+z5TsKLw==" 55 60 }, 56 - "@atcute/atproto@3.1.9": { 57 - "integrity": "sha512-DyWwHCTdR4hY2BPNbLXgVmm7lI+fceOwWbE4LXbGvbvVtSn+ejSVFaAv01Ra3kWDha0whsOmbJL8JP0QPpf1+w==", 58 - "dependencies": [ 59 - "@atcute/lexicons" 60 - ] 61 - }, 62 - "@atcute/bluesky-richtext-builder@2.0.4": { 63 - "integrity": "sha512-ydA9VWBPsBE/gbu1vYbmh7AZ8FLfxp+LE4eH5GgOTCOxwhs7Mgy1oHrHY+Er6gu6PfdoUoGso0uI3Wl3ZF/Mxg==", 61 + "@atcute/atproto@3.1.11": { 62 + "integrity": "sha512-yh+ASvA+iHHQij6UeHEKp2+rwvFvQR8A6/5Dk/xvqDslIikWEFx9VlprNwm/clQIPl2bLuQg+LHS8uY9o5nFTA==", 64 63 "dependencies": [ 65 - "@atcute/bluesky", 66 64 "@atcute/lexicons" 67 65 ] 68 66 }, 69 - "@atcute/bluesky@3.2.11": { 70 - "integrity": "sha512-AboS6y4t+zaxIq7E4noue10csSpIuk/Uwo30/l6GgGBDPXrd7STw8Yb5nGZQP+TdG/uC8/c2mm7UnY65SDOh6A==", 67 + "@atcute/bluesky@3.3.3": { 68 + "integrity": "sha512-R1VyEmbvIUhub6ONnt7sm6FcRoKJISWf+I0qraXtk59KLmNCsJYMX8fLdIcdv5o1i9XtDg8/Um/wqLrl84IuFg==", 71 69 "dependencies": [ 72 70 "@atcute/atproto", 73 71 "@atcute/lexicons" 74 72 ] 75 73 }, 76 - "@atcute/car@3.1.3": { 77 - "integrity": "sha512-WJ13bAEt7TjDMVi09ubjLtvhdljbWInGm9Kfy7Y6NhrmiyC/aZYaA/zHX/bHI6xv1c/h3SQduWqxOr4ae49eqA==", 78 - "dependencies": [ 79 - "@atcute/cbor", 80 - "@atcute/cid", 81 - "@atcute/uint8array", 82 - "@atcute/varint", 83 - "yocto-queue@1.2.2" 84 - ] 85 - }, 86 - "@atcute/cbor@2.2.8": { 87 - "integrity": "sha512-UzOAN9BuN6JCXgn0ryV8qZuRJUDrNqrbLd6EFM8jc6RYssjRyGRxNy6RZ1NU/07Hd8Tq/0pz8+nQiMu5Zai5uw==", 88 - "dependencies": [ 89 - "@atcute/cid", 90 - "@atcute/multibase", 91 - "@atcute/uint8array" 92 - ] 93 - }, 94 - "@atcute/cid@2.2.6": { 95 - "integrity": "sha512-bTAHHbJ24p+E//V4KCS4xdmd39o211jJswvqQOevj7vk+5IYcgDLx1ryZWZ1sEPOo9x875li/kj5gpKL14RDwQ==", 96 - "dependencies": [ 97 - "@atcute/multibase", 98 - "@atcute/uint8array" 99 - ] 100 - }, 101 - "@atcute/client@4.1.0": { 102 - "integrity": "sha512-AYhSu3RSDA2VDkVGOmad320NRbUUUf5pCFWJcOzlk25YC/4kyzmMFfpzhf1jjjEcY+anNBXGGhav/kKB1evggQ==", 74 + "@atcute/client@4.2.1": { 75 + "integrity": "sha512-ZBFM2pW075JtgGFu5g7HHZBecrClhlcNH8GVP9Zz1aViWR+cjjBsTpeE63rJs+FCOHFYlirUyo5L8SGZ4kMINw==", 103 76 "dependencies": [ 104 77 "@atcute/identity", 105 78 "@atcute/lexicons" 106 79 ] 107 80 }, 108 - "@atcute/identity@1.1.3": { 109 - "integrity": "sha512-oIqPoI8TwWeQxvcLmFEZLdN2XdWcaLVtlm8pNk0E72As9HNzzD9pwKPrLr3rmTLRIoULPPFmq9iFNsTeCIU9ng==", 81 + "@atcute/identity@1.1.4": { 82 + "integrity": "sha512-RCw1IqflfuSYCxK5m0lZCm0UnvIzcUnuhngiBhJEJb9a9Mc2SEf1xP3H8N5r8pvEH1LoAYd6/zrvCNU+uy9esw==", 110 83 "dependencies": [ 111 84 "@atcute/lexicons", 112 85 "@badrap/valita" 113 86 ] 114 87 }, 115 - "@atcute/lexicons@1.2.5": { 116 - "integrity": "sha512-9yO9WdgxW8jZ7SbzUycH710z+JmsQ9W9n5S6i6eghYju32kkluFmgBeS47r8e8p2+Dv4DemS7o/3SUGsX9FR5Q==", 88 + "@atcute/lexicons@1.3.0": { 89 + "integrity": "sha512-Eq5y+9onnCXNVUlNiMf31beSXHKqptB7lUo/68YbhlmxdaR7ooywHmahya9goP5AsmlYEA1z+dRPXIDAa9O7cg==", 117 90 "dependencies": [ 91 + "@atcute/uint8array", 92 + "@atcute/util-text", 118 93 "@standard-schema/spec", 119 94 "esm-env" 120 95 ] 121 96 }, 122 - "@atcute/multibase@1.1.6": { 123 - "integrity": "sha512-HBxuCgYLKPPxETV0Rot4VP9e24vKl8JdzGCZOVsDaOXJgbRZoRIF67Lp0H/OgnJeH/Xpva8Z5ReoTNJE5dn3kg==", 97 + "@atcute/microcosm@1.0.3": { 98 + "integrity": "sha512-INgmCB17B/zoXc6gXRJ569eZPRGCIt21kmvoc8mBZngl+zmpcMhFbJSAZBa5d92Li5ugi9mOzLMFj6JPdltbNg==", 124 99 "dependencies": [ 125 - "@atcute/uint8array" 100 + "@atcute/lexicons" 126 101 ] 127 102 }, 128 - "@atcute/ozone@3.1.12": { 129 - "integrity": "sha512-YMsyZtEG6n3+JfU/2Hdl1niZ7mCS9qM3hfNV1ihGRkJniDAtGxcQDRa2wf0Gd9GrhoIaLhawl2wtcqZqyutpVg==", 103 + "@atcute/tid@1.1.2": { 104 + "integrity": "sha512-bmPuOX/TOfcm/vsK9vM98spjkcx2wgd9S2PeK5oLgEr8IbNRPq7iMCAPzOL1nu5XAW3LlkOYQEbYRcw5vcQ37w==", 130 105 "dependencies": [ 131 - "@atcute/atproto", 132 - "@atcute/bluesky", 133 - "@atcute/lexicons" 106 + "@atcute/time-ms" 134 107 ] 135 108 }, 136 - "@atcute/uint8array@1.0.5": { 137 - "integrity": "sha512-XLWWxoR2HNl2qU+FCr0rp1APwJXci7HnzbOQLxK55OaMNBXZ19+xNC5ii4QCsThsDxa4JS/JTzuiQLziITWf2Q==" 109 + "@atcute/time-ms@1.3.2": { 110 + "integrity": "sha512-F+qOyR9pO55g1d/QmN+Gr+fimoUQQLusdGSB6pjV0wW5KPILR4oQ4e2ZhWzqUbeHLAgWvgoTTMsMDdz62Xa2tg==" 138 111 }, 139 - "@atcute/varint@1.0.3": { 140 - "integrity": "sha512-fdvMPyBB+McDT+Ai5e9RwEbwYV4yjZ60S2Dn5PTjGqUyxvoCH1z42viuheDZRUDkmfQehXJTZ5az7dSozVNtog==" 112 + "@atcute/uint8array@1.1.1": { 113 + "integrity": "sha512-3LsC8XB8TKe9q/5hOA5sFuzGaIFdJZJNewC5OKa3o/eU6+K7JR6see9Zy2JbQERNVnRl11EzbNov1efgLMAs4g==" 114 + }, 115 + "@atcute/util-text@1.2.0": { 116 + "integrity": "sha512-b8WSh+Z7K601eUFFmTFj8QPKDO8Ic0VDDj63sdKzpkm+ySQKsYT5nXekViGqFVKbyKj1V5FyvZvgXad6/aI4QQ==", 117 + "dependencies": [ 118 + "unicode-segmenter" 119 + ] 141 120 }, 142 121 "@badrap/valita@0.4.6": { 143 122 "integrity": "sha512-4kdqcjyxo/8RQ8ayjms47HCWZIF5981oE5nIenbfThKDxWXtEHKipAOWlflpPJzZx9y/JWYQkp18Awr7VuepFg==" 144 123 }, 145 124 "@darkvisitors/sdk@1.6.0": { 146 - "integrity": "sha512-KfAO7Dzg/EGZGNRUVpjK8dBzOe9xQI2bXF9aq8JcEk8BiOIAn+e4Vf+ceVMhOBB8PkuLvRBnJwfADAYXNL0iFg==" 125 + "integrity": "sha512-KfAO7Dzg/EGZGNRUVpjK8dBzOe9xQI2bXF9aq8JcEk8BiOIAn+e4Vf+ceVMhOBB8PkuLvRBnJwfADAYXNL0iFg==", 126 + "deprecated": true 147 127 }, 148 128 "@emnapi/runtime@1.7.1": { 149 129 "integrity": "sha512-PVtJr5CmLwYAU9PZDMITZoR5iAOShYREoR45EyyLrbntV50mdePTgUn4AmOw90Ifcj+x2kRjdzr1HP3RrNiHGA==", ··· 779 759 "html-entities" 780 760 ] 781 761 }, 782 - "@skyware/bot@0.4.0": { 783 - "integrity": "sha512-xbodXxB0PRqOwaB/llbdX1sZ9wqIXZhTxwPl77XL9BAP5/SI1DbM0wvo7qwkmI4CBBakE6Hp7ZYj0pyYDb81Uw==", 784 - "dependencies": [ 785 - "@atcute/atproto", 786 - "@atcute/bluesky", 787 - "@atcute/bluesky-richtext-builder", 788 - "@atcute/client", 789 - "@atcute/lexicons", 790 - "@atcute/ozone", 791 - "quick-lru", 792 - "rate-limit-threshold" 793 - ], 794 - "optionalDependencies": [ 795 - "@skyware/firehose", 796 - "@skyware/jetstream" 797 - ] 798 - }, 799 - "@skyware/firehose@0.5.2": { 800 - "integrity": "sha512-Ayg/cF0BkakBNQVA51ClDka0+nC96WiARNrGElMQxfqbwao0PBaCXkunfr8qS4DWS3TqLnR6hA9mvm1vAYlxJQ==", 801 - "dependencies": [ 802 - "@atcute/car", 803 - "@atcute/cbor", 804 - "nanoevents" 805 - ] 806 - }, 807 - "@skyware/jetstream@0.2.5": { 808 - "integrity": "sha512-fM/zs03DLwqRyzZZJFWN20e76KrdqIp97Tlm8Cek+vxn96+tu5d/fx79V6H85L0QN6HvGiX2l9A8hWFqHvYlOA==", 809 - "dependencies": [ 810 - "@atcute/atproto", 811 - "@atcute/bluesky", 812 - "@atcute/lexicons", 813 - "partysocket", 814 - "tiny-emitter" 815 - ] 816 - }, 817 - "@standard-schema/spec@1.0.0": { 818 - "integrity": "sha512-m2bOd0f2RT9k8QJx1JN85cZYyH1RqFBdlwtkSlf4tBDYLCiiZnv1fIIwacK6cqwXavOydf0NPToMQgpKq+dVlA==" 762 + "@standard-schema/spec@1.1.0": { 763 + "integrity": "sha512-l2aFy5jALhniG5HgqrD6jXLi/rUWrKvqN/qJx6yoJsgKhblVd+iqqU4RCXavm/jPityDo5TCvKMnpjKnOriy0w==" 819 764 }, 820 765 "@sveltejs/acorn-typescript@1.0.7_acorn@8.15.0": { 821 766 "integrity": "sha512-znp1A/Y1Jj4l/Zy7PX5DZKBE0ZNY+5QBngiE21NJkfSTyzzC5iKNWOtwFXKtIrn7MXEFBck4jD95iBNkGjK92Q==", ··· 1459 1404 "esutils@2.0.3": { 1460 1405 "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==" 1461 1406 }, 1462 - "event-target-polyfill@0.0.4": { 1463 - "integrity": "sha512-Gs6RLjzlLRdT8X9ZipJdIZI/Y6/HhRLyq9RdDlCsnpxr/+Nn6bU2EFGuC94GjxqhM+Nmij2Vcq98yoHrU8uNFQ==" 1464 - }, 1465 1407 "fast-deep-equal@3.1.3": { 1466 1408 "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==" 1467 1409 }, ··· 1837 1779 "thenify-all" 1838 1780 ] 1839 1781 }, 1840 - "nanoevents@9.1.0": { 1841 - "integrity": "sha512-Jd0fILWG44a9luj8v5kED4WI+zfkkgwKyRQKItTtlPfEsh7Lznfi1kr8/iZ+XAIss4Qq5GqRB0qtWbaz9ceO/A==" 1842 - }, 1843 1782 "nanoid@3.3.11": { 1844 1783 "integrity": "sha512-N8SpfPUnUp1bK+PMYW8qSWdl9U+wwNWI4QKxOYDy9JAro3WMX7p2OeVRF9v+347pnakNevPmiHhNmZ2HbFA76w==", 1845 1784 "bin": true ··· 1892 1831 "p-limit@3.1.0": { 1893 1832 "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==", 1894 1833 "dependencies": [ 1895 - "yocto-queue@0.1.0" 1834 + "yocto-queue" 1896 1835 ] 1897 1836 }, 1898 1837 "p-locate@5.0.0": { ··· 1909 1848 }, 1910 1849 "parenthesis@3.1.8": { 1911 1850 "integrity": "sha512-KF/U8tk54BgQewkJPvB4s/US3VQY68BRDpH638+7O/n58TpnwiwnOtGIOsT2/i+M78s61BBpeC83STB88d8sqw==" 1912 - }, 1913 - "partysocket@1.1.6": { 1914 - "integrity": "sha512-LkEk8N9hMDDsDT0iDK0zuwUDFVrVMUXFXCeN3850Ng8wtjPqPBeJlwdeY6ROlJSEh3tPoTTasXoSBYH76y118w==", 1915 - "dependencies": [ 1916 - "event-target-polyfill" 1917 - ] 1918 1851 }, 1919 1852 "path-exists@4.0.0": { 1920 1853 "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==" ··· 2088 2021 "queue-microtask@1.2.3": { 2089 2022 "integrity": "sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==" 2090 2023 }, 2091 - "quick-lru@7.3.0": { 2092 - "integrity": "sha512-k9lSsjl36EJdK7I06v7APZCbyGT2vMTsYSRX1Q2nbYmnkBqgUhRkAuzH08Ciotteu/PLJmIF2+tti7o3C/ts2g==" 2093 - }, 2094 2024 "random@5.4.1": { 2095 2025 "integrity": "sha512-HtccRkYkAXCbj9bqsyGKGlicyeZ5AsQgs49fEuUO/BvrJ7WOQqXPjdg1CZrFjBkoT75ozrWlQXJ7TcXXLv2ISQ==" 2096 - }, 2097 - "rate-limit-threshold@0.1.5": { 2098 - "integrity": "sha512-75vpvXC/ZqQJrFDp0dVtfoXZi8kxQP2eBuxVYFvGDfnHhcgE+ZG870u4ItQhWQh54Y6nNwOaaq5g3AL9n27lTg==" 2099 2026 }, 2100 2027 "read-cache@1.0.0": { 2101 2028 "integrity": "sha512-Owdv/Ft7IjOgm/i0xvNDZ1LrRANRfew4b2prF3OWMQLxLfu3bS8FVhCsrSCMK4lR56Y9ya+AThoTpDCTxCmpRA==", ··· 2399 2326 "any-promise" 2400 2327 ] 2401 2328 }, 2402 - "tiny-emitter@2.1.0": { 2403 - "integrity": "sha512-NB6Dk1A9xgQPMoGqC5CVXn123gWyte215ONT5Pp5a0yt4nlEoO1ZWeCwpncaekPHXO60i47ihFnZPiRPjRMq4Q==" 2404 - }, 2405 2329 "tinyglobby@0.2.15_picomatch@4.0.3": { 2406 2330 "integrity": "sha512-j2Zq4NyQYG5XMST4cbs02Ak8iJUdxRM0XI5QyxXuZOzKOINmWurp3smXu3y5wDcJrptwpSjgXHzIQxR0omXljQ==", 2407 2331 "dependencies": [ ··· 2466 2390 }, 2467 2391 "undici-types@7.16.0": { 2468 2392 "integrity": "sha512-Zz+aZWSj8LE6zoxD+xrjh4VfkIG8Ya6LvYkZqtUQGJPZjYl53ypCaUwWqo7eI0x66KBGeRo+mlBEkMSeSZ38Nw==" 2393 + }, 2394 + "unicode-segmenter@0.14.5": { 2395 + "integrity": "sha512-jHGmj2LUuqDcX3hqY12Ql+uhUTn8huuxNZGq7GvtF6bSybzH3aFgedYu/KTzQStEgt1Ra2F3HxadNXsNjb3m3g==" 2469 2396 }, 2470 2397 "unist-util-is@4.1.0": { 2471 2398 "integrity": "sha512-ZOQSsnce92GrxSqlnEEseX0gi7GH9zTJZ0p9dtu87WRb/37mMPO2Ilx1s/t9vBHrFhbgweUwb+t7cIn5dxPhZg==" ··· 2563 2490 "yocto-queue@0.1.0": { 2564 2491 "integrity": "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==" 2565 2492 }, 2566 - "yocto-queue@1.2.2": { 2567 - "integrity": "sha512-4LCcse/U2MHZ63HAJVE+v71o7yOdIe4cZ70Wpf8D/IyjDKYQLV5GD46B+hSTjJsvV5PztjvHoU580EftxjDZFQ==" 2568 - }, 2569 2493 "zimmerframe@1.1.4": { 2570 2494 "integrity": "sha512-B58NGBEoc8Y9MWWCQGl/gq9xBCe4IiKM0a2x7GZdQKOW5Exr8S1W24J6OgM1njK8xCRGvAJIL/MxXHf6SkmQKQ==" 2571 2495 } ··· 2575 2499 "eunomia": { 2576 2500 "packageJson": { 2577 2501 "dependencies": [ 2502 + "npm:@atcute/atproto@^3.1.11", 2503 + "npm:@atcute/bluesky@^3.3.3", 2504 + "npm:@atcute/client@^4.2.1", 2505 + "npm:@atcute/lexicons@^1.3.0", 2506 + "npm:@atcute/microcosm@^1.0.3", 2507 + "npm:@atcute/tid@^1.1.2", 2578 2508 "npm:@darkvisitors/sdk@^1.6.0", 2579 2509 "npm:@jsr/std__toml@1.0.11", 2580 2510 "npm:@neodrag/svelte@^2.3.3", 2581 2511 "npm:@rowanmanning/feed-parser@^2.1.1", 2582 - "npm:@skyware/bot@0.4", 2583 2512 "npm:@sveltejs/adapter-node@^5.4.0", 2584 2513 "npm:@sveltejs/kit@^2.49.4", 2585 2514 "npm:@sveltejs/vite-plugin-svelte@^6.2.4",
+7 -2
eunomia/package.json
··· 37 37 }, 38 38 "type": "module", 39 39 "dependencies": { 40 + "@atcute/atproto": "^3.1.11", 41 + "@atcute/bluesky": "^3.3.3", 42 + "@atcute/client": "^4.2.1", 43 + "@atcute/lexicons": "^1.3.0", 44 + "@atcute/microcosm": "^1.0.3", 45 + "@atcute/tid": "^1.1.2", 40 46 "@darkvisitors/sdk": "^1.6.0", 41 47 "@neodrag/svelte": "^2.3.3", 42 48 "@rowanmanning/feed-parser": "^2.1.1", 43 - "@skyware/bot": "^0.4.0", 44 49 "@std/toml": "npm:@jsr/std__toml@1.0.11", 45 50 "@types/node-schedule": "^2.1.8", 46 51 "nanoid": "^5.1.6", ··· 62 67 "sharp", 63 68 "svelte-preprocess" 64 69 ] 65 - } 70 + }
+11 -6
eunomia/src/components/note.svelte
··· 1 1 <script module lang="ts"> 2 - import type { Post } from '@skyware/bot'; 2 + import type { Post } from '$lib/bluesky'; 3 3 4 4 export interface OutgoingLink { 5 5 name: string; ··· 28 28 return flattened; 29 29 }; 30 30 31 - export const noteFromBskyPost = (post: Post): NoteData => { 31 + export const noteFromBskyPost = ({ record: post, uri }: Post): NoteData => { 32 32 return { 33 33 content: post.text, 34 - published: post.createdAt.getTime(), 35 - outgoingLinks: [{ name: 'bsky', link: post.uri }], 34 + published: new Date(post.createdAt).getTime(), 35 + outgoingLinks: [{ name: 'bsky', link: uri }], 36 36 hasMedia: 37 - (post.embed?.isImages() || post.embed?.isVideo() || post.embed?.isRecordWithMedia()) ?? 37 + (post.embed?.$type === 'app.bsky.embed.images' || 38 + post.embed?.$type === 'app.bsky.embed.video' || 39 + post.embed?.$type === 'app.bsky.embed.recordWithMedia') ?? 38 40 false, 39 - hasQuote: (post.embed?.isRecord() || post.embed?.isRecordWithMedia()) ?? false 41 + hasQuote: 42 + (post.embed?.$type === 'app.bsky.embed.record' || 43 + post.embed?.$type === 'app.bsky.embed.recordWithMedia') ?? 44 + false 40 45 }; 41 46 }; 42 47 </script>
+3
eunomia/src/env.d.ts
··· 1 + /// <reference types="@atcute/bluesky" /> 2 + /// <reference types="@atcute/atproto" /> 3 + /// <reference types="@atcute/microcosm" />
+71 -25
eunomia/src/lib/bluesky.ts
··· 1 1 import { env } from '$env/dynamic/private'; 2 - import { Bot, type Post } from '@skyware/bot'; 2 + import { AppBskyFeedPost } from '@atcute/bluesky'; 3 + 4 + import { Client, CredentialManager, ok, simpleFetchHandler } from '@atcute/client'; 5 + import { parse, type CanonicalResourceUri, type Did } from '@atcute/lexicons'; 3 6 import { get, writable } from 'svelte/store'; 4 7 5 - const bskyClient = writable<null | Bot>(null); 8 + export const PDS_URL = 'https://gaze.systems'; 9 + export const IDENTIFIER = 'did:web:guestbook.gaze.systems'; 10 + 11 + const constellationClient = new Client({ 12 + handler: simpleFetchHandler({ service: 'https://constellation.microcosm.blue' }) 13 + }); 14 + const bskyClient = writable<null | Client>(null); 15 + 16 + export type Post = { 17 + record: AppBskyFeedPost.Main; 18 + uri: CanonicalResourceUri; 19 + }; 6 20 7 21 export const getBskyClient = async () => { 8 - let client = get(bskyClient); 9 - if (client === null) { 10 - client = await loginToBsky(); 11 - bskyClient.set(client); 22 + try { 23 + let client = get(bskyClient); 24 + if (client === null) { 25 + client = await loginToBsky(); 26 + bskyClient.set(client); 27 + } 28 + return client; 29 + } catch (e) { 30 + throw `cant login to bsky: ${e}`; 12 31 } 13 - return client; 14 32 }; 15 33 16 34 const loginToBsky = async () => { ··· 18 36 if (password === null) { 19 37 throw new Error('no password provided'); 20 38 } 21 - const bot = new Bot({ service: 'https://gaze.systems' }); 22 - await bot.login({ identifier: 'guestbook.gaze.systems', password }); 23 - return bot; 39 + const handler = new CredentialManager({ service: PDS_URL }); 40 + const rpc = new Client({ handler }); 41 + await handler.login({ identifier: IDENTIFIER, password }); 42 + return rpc; 24 43 }; 25 44 26 - export const getUserPosts = async ( 27 - did: string, 28 - count: number = 10, 29 - cursor: string | null = null 30 - ) => { 45 + export const getUserPosts = async (repo: Did, count: number = 10, cursor?: string) => { 31 46 const client = await getBskyClient(); 32 - let feedCursor: string | null | undefined = cursor; 33 47 const posts: Post[] = []; 34 48 // fetch requested amount of posts 35 - while (posts.length < count - 1 && (typeof feedCursor === 'string' || feedCursor === null)) { 36 - const feedData = await client.getUserPosts(did, { 37 - limit: count, 38 - filter: 'posts_no_replies', 39 - cursor: feedCursor === null ? undefined : feedCursor 40 - }); 41 - posts.push(...feedData.posts.filter((post) => post.author.did === did)); 42 - feedCursor = feedData.cursor; 49 + while (posts.length < count - 1 && cursor !== undefined) { 50 + const fetched = ok( 51 + await client.get('com.atproto.repo.listRecords', { 52 + params: { repo, collection: 'app.bsky.feed.post', cursor } 53 + }) 54 + ); 55 + for (const record of fetched.records) { 56 + const post = parse(AppBskyFeedPost.mainSchema, record.value); 57 + if (post.reply) continue; 58 + posts.push({ 59 + record: post, 60 + uri: record.uri as CanonicalResourceUri 61 + }); 62 + } 63 + cursor = fetched.cursor; 43 64 } 44 - return { posts, cursor: feedCursor === null ? undefined : feedCursor }; 65 + return { posts, cursor }; 45 66 }; 46 67 47 68 const lastPosts = writable<Post[]>([]); ··· 58 79 export const getLastPosts = () => { 59 80 return get(lastPosts); 60 81 }; 82 + 83 + export const getReplies = async (postUri: CanonicalResourceUri, forDid?: Did) => { 84 + const client = await getBskyClient(); 85 + // todo: do cursor stuff here later if it matters 86 + const backlinks = ok( 87 + await constellationClient.get('blue.microcosm.links.getBacklinks', { 88 + params: { 89 + did: forDid ? [forDid] : [], 90 + subject: postUri, 91 + source: 'app.bsky.feed.post:reply.parent.uri' 92 + } 93 + }) 94 + ); 95 + const replies: Post[] = []; 96 + for (const record of backlinks.records) { 97 + const fetched = ok( 98 + await client.get('com.atproto.repo.getRecord', { 99 + params: { repo: record.did, collection: record.collection, rkey: record.rkey } 100 + }) 101 + ); 102 + const post = parse(AppBskyFeedPost.mainSchema, fetched.value); 103 + replies.push({ record: post, uri: fetched.uri as CanonicalResourceUri }); 104 + } 105 + return replies; 106 + };
+27 -7
eunomia/src/routes/(site)/+layout.svelte
··· 114 114 <feComposite in="SourceGraphic" in2="a" operator="in" /> 115 115 <feMorphology operator="dilate" radius="5" /> 116 116 </filter> 117 - <filter id="dither" color-interpolation-filters="sRGB" x="0" y="0" width="100%" height="100%"> 117 + <filter 118 + id="dither" 119 + color-interpolation-filters="sRGB" 120 + x="0" 121 + y="0" 122 + width="100%" 123 + height="100%" 124 + > 118 125 <feImage 119 126 width="4" 120 127 height="4" ··· 213 220 /> 214 221 {/if} 215 222 {#if isResumePage && menuIdx === 2} 216 - <NavButton highlight name="resume" href="/resume.pdf" iconUri="/icons/about.webp" /> 223 + <NavButton 224 + highlight 225 + name="resume" 226 + href="/resume.pdf" 227 + iconUri="/icons/about.webp" 228 + /> 217 229 {/if} 218 230 {/each} 219 231 <div class="hidden md:block grow"></div> ··· 230 242 class="hover:underline" 231 243 href="https://stellophiliac.github.io/roboring/gazesys/previous">⮜</a 232 244 > 233 - <a class="hover:underline" href="https://stellophiliac.github.io/roboring">roboring</a> 245 + <a class="hover:underline" href="https://stellophiliac.github.io/roboring" 246 + >roboring</a 247 + > 234 248 <a 235 249 title="next site" 236 250 class="hover:underline" ··· 238 252 > 239 253 </div> 240 254 <div class="navbox"> 241 - <a title="previous site" class="hover:underline" href="https://xn--sr8hvo.ws/previous">⮜</a> 255 + <a 256 + title="previous site" 257 + class="hover:underline" 258 + href="https://xn--sr8hvo.ws/previous">⮜</a 259 + > 242 260 <a class="hover:underline" href="https://xn--sr8hvo.ws">indieweb</a> 243 261 <a title="next site" class="hover:underline" href="https://xn--sr8hvo.ws/next">⮞</a> 244 262 </div> ··· 265 283 using <span 266 284 class={data.ipv6 267 285 ? 'text-ralsei-green-light text-shadow-green' 268 - : 'text-red-500 text-shadow-red'}>{data.ipv6 ? 'ipv6' : 'ipv4'}</span 286 + : 'text-red-500 text-shadow-red'} 287 + >{data.ipv6 ? 'ipv6' : 'ipv4'}</span 269 288 > 270 289 </p> 271 290 </div> ··· 294 313 {/snippet} 295 314 <div class="navbox"> 296 315 <p> 297 - <span class="text-ralsei-green-light text-shadow-green">{data.recentVisitCount}</span> recent 298 - clicks 316 + <span class="text-ralsei-green-light text-shadow-green" 317 + >{data.recentVisitCount}</span 318 + > recent clicks 299 319 </p> 300 320 </div> 301 321 </Tooltip>
+40 -11
eunomia/src/routes/(site)/guestbook/+page.server.ts
··· 2 2 import { scopeCookies as _scopeCookies, fancyText } from '$lib'; 3 3 import { RetryAfterRateLimiter } from 'sveltekit-rate-limiter/server'; 4 4 import { PUBLIC_BASE_URL } from '$env/static/public'; 5 - import { getBskyClient, getUserPosts } from '$lib/bluesky.js'; 5 + import { getBskyClient, getReplies, getUserPosts, IDENTIFIER } from '$lib/bluesky.js'; 6 6 import { getVisitorId } from '$lib/visits'; 7 7 import { nanoid } from 'nanoid'; 8 8 import { noteFromBskyPost, type NoteData } from '$components/note.svelte'; 9 9 import { get, writable } from 'svelte/store'; 10 - import type { Post } from '@skyware/bot'; 10 + import type { Post } from '$lib/bluesky.js'; 11 11 import { useToken as checkApiToken, newToken } from '$lib/apiToken.js'; 12 + import type { AppBskyFeedPost, AppBskyFeedThreadgate } from '@atcute/bluesky'; 13 + import { now } from '@atcute/tid'; 14 + import { ok } from '@atcute/client'; 12 15 13 16 export const prerender = false; 14 17 ··· 28 31 29 32 export const _fetchEntries = async () => { 30 33 const newEntries: NoteData[] = []; 31 - const { posts } = await getUserPosts('did:web:guestbook.gaze.systems', 14); 34 + const { posts } = await getUserPosts(IDENTIFIER, 14); 32 35 const fetchPostReplies = async (post: Post) => { 33 - if ((post.replyCount ?? 0) === 0) return { post, replies: [] }; 34 - return { post, replies: await post.fetchChildren({ depth: 1, force: true }) }; 36 + const replies = await getReplies(post.uri, 'did:plc:dfl62fgb7wtjj3fcbb72naae'); 37 + return { post, replies }; 35 38 }; 36 39 const postsWithReplies = await Promise.all(posts.map(fetchPostReplies)); 37 40 for (const { post, replies } of postsWithReplies) { ··· 120 123 } 121 124 // post to guestbook account 122 125 const client = await getBskyClient(); 123 - await client.post( 124 - { 125 - text: content, 126 - threadgate: { allowMentioned: false, allowFollowing: true } 127 - }, 128 - { resolveFacets: false } 126 + const post: AppBskyFeedPost.Main = { 127 + $type: 'app.bsky.feed.post', 128 + createdAt: new Date().toUTCString(), 129 + text: content 130 + }; 131 + const postRkey = now(); 132 + const threadgate: AppBskyFeedThreadgate.Main = { 133 + $type: 'app.bsky.feed.threadgate', 134 + createdAt: new Date().toUTCString(), 135 + post: `at://${IDENTIFIER}/${post.$type}/${postRkey}`, 136 + allow: [{ $type: 'app.bsky.feed.threadgate#followingRule' }] 137 + }; 138 + // use applyWrites to make a post record and a threadgate record 139 + await ok( 140 + client.post('com.atproto.repo.applyWrites', { 141 + input: { 142 + repo: IDENTIFIER, 143 + writes: [ 144 + { 145 + $type: 'com.atproto.repo.applyWrites#create', 146 + collection: post.$type, 147 + value: post, 148 + rkey: postRkey 149 + }, 150 + { 151 + $type: 'com.atproto.repo.applyWrites#create', 152 + collection: 'app.bsky.feed.threadgate', 153 + value: threadgate 154 + } 155 + ] 156 + } 157 + }) 129 158 ); 130 159 try { 131 160 data.entries = await _fetchEntries();
+10 -241
flake.lock
··· 1 1 { 2 2 "nodes": { 3 - "crane": { 4 - "flake": false, 5 - "locked": { 6 - "lastModified": 1758758545, 7 - "narHash": "sha256-NU5WaEdfwF6i8faJ2Yh+jcK9vVFrofLcwlD/mP65JrI=", 8 - "owner": "ipetkov", 9 - "repo": "crane", 10 - "rev": "95d528a5f54eaba0d12102249ce42f4d01f4e364", 11 - "type": "github" 12 - }, 13 - "original": { 14 - "owner": "ipetkov", 15 - "ref": "v0.21.1", 16 - "repo": "crane", 17 - "type": "github" 18 - } 19 - }, 20 - "dream2nix": { 21 - "inputs": { 22 - "nixpkgs": [ 23 - "nci", 24 - "nixpkgs" 25 - ], 26 - "purescript-overlay": "purescript-overlay", 27 - "pyproject-nix": "pyproject-nix" 28 - }, 29 - "locked": { 30 - "lastModified": 1765953015, 31 - "narHash": "sha256-5FBZbbWR1Csp3Y2icfRkxMJw/a/5FGg8hCXej2//bbI=", 32 - "owner": "nix-community", 33 - "repo": "dream2nix", 34 - "rev": "69eb01fa0995e1e90add49d8ca5bcba213b0416f", 35 - "type": "github" 36 - }, 37 - "original": { 38 - "owner": "nix-community", 39 - "repo": "dream2nix", 40 - "type": "github" 41 - } 42 - }, 43 - "flake-compat": { 44 - "flake": false, 45 - "locked": { 46 - "lastModified": 1696426674, 47 - "narHash": "sha256-kvjfFW7WAETZlt09AgDn1MrtKzP7t90Vf7vypd3OL1U=", 48 - "owner": "edolstra", 49 - "repo": "flake-compat", 50 - "rev": "0f9255e01c2351cc7d116c072cb317785dd33b33", 51 - "type": "github" 52 - }, 53 - "original": { 54 - "owner": "edolstra", 55 - "repo": "flake-compat", 56 - "type": "github" 57 - } 58 - }, 59 - "mk-naked-shell": { 60 - "flake": false, 61 - "locked": { 62 - "lastModified": 1681286841, 63 - "narHash": "sha256-3XlJrwlR0nBiREnuogoa5i1b4+w/XPe0z8bbrJASw0g=", 64 - "owner": "90-008", 65 - "repo": "mk-naked-shell", 66 - "rev": "7612f828dd6f22b7fb332cc69440e839d7ffe6bd", 67 - "type": "github" 68 - }, 69 - "original": { 70 - "owner": "90-008", 71 - "repo": "mk-naked-shell", 72 - "type": "github" 73 - } 74 - }, 75 3 "naked-shell": { 76 4 "locked": { 77 5 "lastModified": 1681286841, ··· 87 15 "type": "github" 88 16 } 89 17 }, 90 - "nci": { 91 - "inputs": { 92 - "crane": "crane", 93 - "dream2nix": "dream2nix", 94 - "mk-naked-shell": "mk-naked-shell", 95 - "nixpkgs": [ 96 - "nixpkgs" 97 - ], 98 - "parts": "parts", 99 - "rust-overlay": "rust-overlay", 100 - "treefmt": "treefmt" 101 - }, 102 - "locked": { 103 - "lastModified": 1768371832, 104 - "narHash": "sha256-SXluvUhEehrcbQzwZkEl7MH96sLNLID6QiGDbTl1IYM=", 105 - "owner": "90-008", 106 - "repo": "nix-cargo-integration", 107 - "rev": "d7e924aa3279d8faa393c3380b05a232d55ba5e2", 108 - "type": "github" 109 - }, 110 - "original": { 111 - "owner": "90-008", 112 - "repo": "nix-cargo-integration", 113 - "type": "github" 114 - } 115 - }, 116 18 "nixpkgs": { 117 19 "locked": { 118 - "lastModified": 1768302833, 119 - "narHash": "sha256-h5bRFy9bco+8QcK7rGoOiqMxMbmn21moTACofNLRMP4=", 20 + "lastModified": 1776255774, 21 + "narHash": "sha256-psVTpH6PK3q1htMJpmdz1hLF5pQgEshu7gQWgKO6t6Y=", 120 22 "owner": "nixos", 121 23 "repo": "nixpkgs", 122 - "rev": "61db79b0c6b838d9894923920b612048e1201926", 24 + "rev": "566acc07c54dc807f91625bb286cb9b321b5f42a", 123 25 "type": "github" 124 26 }, 125 27 "original": { ··· 131 33 }, 132 34 "nixpkgs-lib": { 133 35 "locked": { 134 - "lastModified": 1765674936, 135 - "narHash": "sha256-k00uTP4JNfmejrCLJOwdObYC9jHRrr/5M/a/8L2EIdo=", 36 + "lastModified": 1774748309, 37 + "narHash": "sha256-+U7gF3qxzwD5TZuANzZPeJTZRHS29OFQgkQ2kiTJBIQ=", 136 38 "owner": "nix-community", 137 39 "repo": "nixpkgs.lib", 138 - "rev": "2075416fcb47225d9b68ac469a5c4801a9c4dd85", 40 + "rev": "333c4e0545a6da976206c74db8773a1645b5870a", 139 41 "type": "github" 140 42 }, 141 43 "original": { ··· 146 48 }, 147 49 "parts": { 148 50 "inputs": { 149 - "nixpkgs-lib": [ 150 - "nci", 151 - "nixpkgs" 152 - ] 153 - }, 154 - "locked": { 155 - "lastModified": 1768135262, 156 - "narHash": "sha256-PVvu7OqHBGWN16zSi6tEmPwwHQ4rLPU9Plvs8/1TUBY=", 157 - "owner": "hercules-ci", 158 - "repo": "flake-parts", 159 - "rev": "80daad04eddbbf5a4d883996a73f3f542fa437ac", 160 - "type": "github" 161 - }, 162 - "original": { 163 - "owner": "hercules-ci", 164 - "repo": "flake-parts", 165 - "type": "github" 166 - } 167 - }, 168 - "parts_2": { 169 - "inputs": { 170 51 "nixpkgs-lib": "nixpkgs-lib" 171 52 }, 172 53 "locked": { 173 - "lastModified": 1768135262, 174 - "narHash": "sha256-PVvu7OqHBGWN16zSi6tEmPwwHQ4rLPU9Plvs8/1TUBY=", 54 + "lastModified": 1775087534, 55 + "narHash": "sha256-91qqW8lhL7TLwgQWijoGBbiD4t7/q75KTi8NxjVmSmA=", 175 56 "owner": "hercules-ci", 176 57 "repo": "flake-parts", 177 - "rev": "80daad04eddbbf5a4d883996a73f3f542fa437ac", 58 + "rev": "3107b77cd68437b9a76194f0f7f9c55f2329ca5b", 178 59 "type": "github" 179 60 }, 180 61 "original": { ··· 183 64 "type": "github" 184 65 } 185 66 }, 186 - "purescript-overlay": { 187 - "inputs": { 188 - "flake-compat": "flake-compat", 189 - "nixpkgs": [ 190 - "nci", 191 - "dream2nix", 192 - "nixpkgs" 193 - ], 194 - "slimlock": "slimlock" 195 - }, 196 - "locked": { 197 - "lastModified": 1728546539, 198 - "narHash": "sha256-Sws7w0tlnjD+Bjck1nv29NjC5DbL6nH5auL9Ex9Iz2A=", 199 - "owner": "thomashoneyman", 200 - "repo": "purescript-overlay", 201 - "rev": "4ad4c15d07bd899d7346b331f377606631eb0ee4", 202 - "type": "github" 203 - }, 204 - "original": { 205 - "owner": "thomashoneyman", 206 - "repo": "purescript-overlay", 207 - "type": "github" 208 - } 209 - }, 210 - "pyproject-nix": { 211 - "inputs": { 212 - "nixpkgs": [ 213 - "nci", 214 - "dream2nix", 215 - "nixpkgs" 216 - ] 217 - }, 218 - "locked": { 219 - "lastModified": 1763017646, 220 - "narHash": "sha256-Z+R2lveIp6Skn1VPH3taQIuMhABg1IizJd8oVdmdHsQ=", 221 - "owner": "pyproject-nix", 222 - "repo": "pyproject.nix", 223 - "rev": "47bd6f296502842643078d66128f7b5e5370790c", 224 - "type": "github" 225 - }, 226 - "original": { 227 - "owner": "pyproject-nix", 228 - "repo": "pyproject.nix", 229 - "type": "github" 230 - } 231 - }, 232 67 "root": { 233 68 "inputs": { 234 69 "naked-shell": "naked-shell", 235 - "nci": "nci", 236 70 "nixpkgs": "nixpkgs", 237 - "parts": "parts_2" 238 - } 239 - }, 240 - "rust-overlay": { 241 - "inputs": { 242 - "nixpkgs": [ 243 - "nci", 244 - "nixpkgs" 245 - ] 246 - }, 247 - "locked": { 248 - "lastModified": 1768359079, 249 - "narHash": "sha256-a016mOfKconYrYo3fZLN6c2cnmqYYd44g2bUrBZAsQc=", 250 - "owner": "oxalica", 251 - "repo": "rust-overlay", 252 - "rev": "0357d1826057686637e41147545402cbbda420ce", 253 - "type": "github" 254 - }, 255 - "original": { 256 - "owner": "oxalica", 257 - "repo": "rust-overlay", 258 - "type": "github" 259 - } 260 - }, 261 - "slimlock": { 262 - "inputs": { 263 - "nixpkgs": [ 264 - "nci", 265 - "dream2nix", 266 - "purescript-overlay", 267 - "nixpkgs" 268 - ] 269 - }, 270 - "locked": { 271 - "lastModified": 1688756706, 272 - "narHash": "sha256-xzkkMv3neJJJ89zo3o2ojp7nFeaZc2G0fYwNXNJRFlo=", 273 - "owner": "thomashoneyman", 274 - "repo": "slimlock", 275 - "rev": "cf72723f59e2340d24881fd7bf61cb113b4c407c", 276 - "type": "github" 277 - }, 278 - "original": { 279 - "owner": "thomashoneyman", 280 - "repo": "slimlock", 281 - "type": "github" 282 - } 283 - }, 284 - "treefmt": { 285 - "inputs": { 286 - "nixpkgs": [ 287 - "nci", 288 - "nixpkgs" 289 - ] 290 - }, 291 - "locked": { 292 - "lastModified": 1768158989, 293 - "narHash": "sha256-67vyT1+xClLldnumAzCTBvU0jLZ1YBcf4vANRWP3+Ak=", 294 - "owner": "numtide", 295 - "repo": "treefmt-nix", 296 - "rev": "e96d59dff5c0d7fddb9d113ba108f03c3ef99eca", 297 - "type": "github" 298 - }, 299 - "original": { 300 - "owner": "numtide", 301 - "repo": "treefmt-nix", 302 - "type": "github" 71 + "parts": "parts" 303 72 } 304 73 } 305 74 },
+2 -6
flake.nix
··· 2 2 inputs.parts.url = "github:hercules-ci/flake-parts"; 3 3 inputs.nixpkgs.url = "github:nixos/nixpkgs/nixpkgs-unstable"; 4 4 inputs.naked-shell.url = "github:90-008/mk-naked-shell"; 5 - inputs.nci.url = "github:90-008/nix-cargo-integration"; 6 - inputs.nci.inputs.nixpkgs.follows = "nixpkgs"; 7 5 8 6 outputs = inp: 9 7 inp.parts.lib.mkFlake {inputs = inp;} { 10 8 systems = ["x86_64-linux"]; 11 9 imports = [ 12 10 inp.naked-shell.flakeModule 13 - # inp.nci.flakeModule 14 11 ]; 15 12 perSystem = { 16 13 lib, ··· 22 19 name = "eunomia-devshell"; 23 20 packages = with pkgs; [ 24 21 nodejs-slim_latest deno skia 25 - nodePackages.svelte-language-server 26 - nodePackages.typescript-language-server 27 - rustc rust-analyzer cargo wasm-pack wasm-bindgen-cli lld rustfmt binaryen 22 + svelte-language-server 23 + typescript-language-server 28 24 ]; 29 25 shellHook = '' 30 26 export PATH="$PATH:$PWD/node_modules/.bin"