diff --git a/Pipfile b/Pipfile deleted file mode 100644 index 93bb396..0000000 --- a/Pipfile +++ /dev/null @@ -1,14 +0,0 @@ -[[source]] -url = "https://pypi.org/simple" -verify_ssl = true -name = "pypi" - -[packages] -atproto = "==0.0.65" -typer = "==0.21.1" -pytest = "*" - -[dev-packages] - -[requires] -python_version = "3.14" diff --git a/Pipfile.lock b/Pipfile.lock deleted file mode 100644 index 48834ed..0000000 --- a/Pipfile.lock +++ /dev/null @@ -1,666 +0,0 @@ -{ - "_meta": { - "hash": { - "sha256": "60e3e4849fadc75bda934e7f5a78b3a88203e1e0b20e0058faf9e737b7c8f0c1" - }, - "pipfile-spec": 6, - "requires": { - "python_version": "3.14" - }, - "sources": [ - { - "name": "pypi", - "url": "https://pypi.org/simple", - "verify_ssl": true - } - ] - }, - "default": { - "annotated-types": { - "hashes": [ - "sha256:1f02e8b43a8fbbc3f3e0d4f0f4bfc8131bcb4eebe8849b8e5c773f3a1c582a53", - "sha256:aff07c09a53a08bc8cfccb9c85b05f1aa9a2a6f23728d790723543408344ce89" - ], - "markers": "python_version >= '3.8'", - "version": "==0.7.0" - }, - "anyio": { - "hashes": [ - "sha256:08b310f9e24a9594186fd75b4f73f4a4152069e3853f1ed8bfbf58369f4ad708", - "sha256:334b70e641fd2221c1505b3890c69882fe4a2df910cba14d97019b90b24439dc" - ], - "markers": "python_version >= '3.10'", - "version": "==4.13.0" - }, - "atproto": { - "hashes": [ - "sha256:027c6ed98746a9e6f1bb24bc18db84b80b386037709ff3af9ef927dce3dd4938", - "sha256:ea53dea57454c9e56318b5d25ceb35854d60ba238b38b0e5ca79aa1a2df85846" - ], - "index": "pypi", - "markers": "python_version < '3.15' and python_version >= '3.9'", - "version": "==0.0.65" - }, - "certifi": { - "hashes": [ - "sha256:027692e4402ad994f1c42e52a4997a9763c646b73e4096e4d5d6db8af1d6f0fa", - "sha256:e887ab5cee78ea814d3472169153c2d12cd43b14bd03329a39a9c6e2e80bfba7" - ], - "markers": "python_version >= '3.7'", - "version": "==2026.2.25" - }, - "cffi": { - "hashes": [ - "sha256:00bdf7acc5f795150faa6957054fbbca2439db2f775ce831222b66f192f03beb", - "sha256:07b271772c100085dd28b74fa0cd81c8fb1a3ba18b21e03d7c27f3436a10606b", - "sha256:087067fa8953339c723661eda6b54bc98c5625757ea62e95eb4898ad5e776e9f", - "sha256:0a1527a803f0a659de1af2e1fd700213caba79377e27e4693648c2923da066f9", - "sha256:0cf2d91ecc3fcc0625c2c530fe004f82c110405f101548512cce44322fa8ac44", - "sha256:0f6084a0ea23d05d20c3edcda20c3d006f9b6f3fefeac38f59262e10cef47ee2", - "sha256:12873ca6cb9b0f0d3a0da705d6086fe911591737a59f28b7936bdfed27c0d47c", - "sha256:19f705ada2530c1167abacb171925dd886168931e0a7b78f5bffcae5c6b5be75", - "sha256:1cd13c99ce269b3ed80b417dcd591415d3372bcac067009b6e0f59c7d4015e65", - "sha256:1e3a615586f05fc4065a8b22b8152f0c1b00cdbc60596d187c2a74f9e3036e4e", - "sha256:1f72fb8906754ac8a2cc3f9f5aaa298070652a0ffae577e0ea9bd480dc3c931a", - "sha256:1fc9ea04857caf665289b7a75923f2c6ed559b8298a1b8c49e59f7dd95c8481e", - "sha256:203a48d1fb583fc7d78a4c6655692963b860a417c0528492a6bc21f1aaefab25", - "sha256:2081580ebb843f759b9f617314a24ed5738c51d2aee65d31e02f6f7a2b97707a", - "sha256:21d1152871b019407d8ac3985f6775c079416c282e431a4da6afe7aefd2bccbe", - "sha256:24b6f81f1983e6df8db3adc38562c83f7d4a0c36162885ec7f7b77c7dcbec97b", - "sha256:256f80b80ca3853f90c21b23ee78cd008713787b1b1e93eae9f3d6a7134abd91", - "sha256:28a3a209b96630bca57cce802da70c266eb08c6e97e5afd61a75611ee6c64592", - "sha256:2c8f814d84194c9ea681642fd164267891702542f028a15fc97d4674b6206187", - "sha256:2de9a304e27f7596cd03d16f1b7c72219bd944e99cc52b84d0145aefb07cbd3c", - "sha256:38100abb9d1b1435bc4cc340bb4489635dc2f0da7456590877030c9b3d40b0c1", - "sha256:3925dd22fa2b7699ed2617149842d2e6adde22b262fcbfada50e3d195e4b3a94", - "sha256:3e17ed538242334bf70832644a32a7aae3d83b57567f9fd60a26257e992b79ba", - "sha256:3e837e369566884707ddaf85fc1744b47575005c0a229de3327f8f9a20f4efeb", - "sha256:3f4d46d8b35698056ec29bca21546e1551a205058ae1a181d871e278b0b28165", - "sha256:44d1b5909021139fe36001ae048dbdde8214afa20200eda0f64c068cac5d5529", - "sha256:45d5e886156860dc35862657e1494b9bae8dfa63bf56796f2fb56e1679fc0bca", - "sha256:4647afc2f90d1ddd33441e5b0e85b16b12ddec4fca55f0d9671fef036ecca27c", - "sha256:4671d9dd5ec934cb9a73e7ee9676f9362aba54f7f34910956b84d727b0d73fb6", - "sha256:53f77cbe57044e88bbd5ed26ac1d0514d2acf0591dd6bb02a3ae37f76811b80c", - "sha256:5eda85d6d1879e692d546a078b44251cdd08dd1cfb98dfb77b670c97cee49ea0", - "sha256:5fed36fccc0612a53f1d4d9a816b50a36702c28a2aa880cb8a122b3466638743", - "sha256:61d028e90346df14fedc3d1e5441df818d095f3b87d286825dfcbd6459b7ef63", - "sha256:66f011380d0e49ed280c789fbd08ff0d40968ee7b665575489afa95c98196ab5", - "sha256:6824f87845e3396029f3820c206e459ccc91760e8fa24422f8b0c3d1731cbec5", - "sha256:6c6c373cfc5c83a975506110d17457138c8c63016b563cc9ed6e056a82f13ce4", - "sha256:6d02d6655b0e54f54c4ef0b94eb6be0607b70853c45ce98bd278dc7de718be5d", - "sha256:6d50360be4546678fc1b79ffe7a66265e28667840010348dd69a314145807a1b", - "sha256:730cacb21e1bdff3ce90babf007d0a0917cc3e6492f336c2f0134101e0944f93", - "sha256:737fe7d37e1a1bffe70bd5754ea763a62a066dc5913ca57e957824b72a85e205", - "sha256:74a03b9698e198d47562765773b4a8309919089150a0bb17d829ad7b44b60d27", - "sha256:7553fb2090d71822f02c629afe6042c299edf91ba1bf94951165613553984512", - "sha256:7a66c7204d8869299919db4d5069a82f1561581af12b11b3c9f48c584eb8743d", - "sha256:7cc09976e8b56f8cebd752f7113ad07752461f48a58cbba644139015ac24954c", - "sha256:81afed14892743bbe14dacb9e36d9e0e504cd204e0b165062c488942b9718037", - "sha256:8941aaadaf67246224cee8c3803777eed332a19d909b47e29c9842ef1e79ac26", - "sha256:89472c9762729b5ae1ad974b777416bfda4ac5642423fa93bd57a09204712322", - "sha256:8ea985900c5c95ce9db1745f7933eeef5d314f0565b27625d9a10ec9881e1bfb", - "sha256:8eca2a813c1cb7ad4fb74d368c2ffbbb4789d377ee5bb8df98373c2cc0dee76c", - "sha256:92b68146a71df78564e4ef48af17551a5ddd142e5190cdf2c5624d0c3ff5b2e8", - "sha256:9332088d75dc3241c702d852d4671613136d90fa6881da7d770a483fd05248b4", - "sha256:94698a9c5f91f9d138526b48fe26a199609544591f859c870d477351dc7b2414", - "sha256:9a67fc9e8eb39039280526379fb3a70023d77caec1852002b4da7e8b270c4dd9", - "sha256:9de40a7b0323d889cf8d23d1ef214f565ab154443c42737dfe52ff82cf857664", - "sha256:a05d0c237b3349096d3981b727493e22147f934b20f6f125a3eba8f994bec4a9", - "sha256:afb8db5439b81cf9c9d0c80404b60c3cc9c3add93e114dcae767f1477cb53775", - "sha256:b18a3ed7d5b3bd8d9ef7a8cb226502c6bf8308df1525e1cc676c3680e7176739", - "sha256:b1e74d11748e7e98e2f426ab176d4ed720a64412b6a15054378afdb71e0f37dc", - "sha256:b21e08af67b8a103c71a250401c78d5e0893beff75e28c53c98f4de42f774062", - "sha256:b4c854ef3adc177950a8dfc81a86f5115d2abd545751a304c5bcf2c2c7283cfe", - "sha256:b882b3df248017dba09d6b16defe9b5c407fe32fc7c65a9c69798e6175601be9", - "sha256:baf5215e0ab74c16e2dd324e8ec067ef59e41125d3eade2b863d294fd5035c92", - "sha256:c649e3a33450ec82378822b3dad03cc228b8f5963c0c12fc3b1e0ab940f768a5", - "sha256:c654de545946e0db659b3400168c9ad31b5d29593291482c43e3564effbcee13", - "sha256:c6638687455baf640e37344fe26d37c404db8b80d037c3d29f58fe8d1c3b194d", - "sha256:c8d3b5532fc71b7a77c09192b4a5a200ea992702734a2e9279a37f2478236f26", - "sha256:cb527a79772e5ef98fb1d700678fe031e353e765d1ca2d409c92263c6d43e09f", - "sha256:cf364028c016c03078a23b503f02058f1814320a56ad535686f90565636a9495", - "sha256:d48a880098c96020b02d5a1f7d9251308510ce8858940e6fa99ece33f610838b", - "sha256:d68b6cef7827e8641e8ef16f4494edda8b36104d79773a334beaa1e3521430f6", - "sha256:d9b29c1f0ae438d5ee9acb31cadee00a58c46cc9c0b2f9038c6b0b3470877a8c", - "sha256:d9b97165e8aed9272a6bb17c01e3cc5871a594a446ebedc996e2397a1c1ea8ef", - "sha256:da68248800ad6320861f129cd9c1bf96ca849a2771a59e0344e88681905916f5", - "sha256:da902562c3e9c550df360bfa53c035b2f241fed6d9aef119048073680ace4a18", - "sha256:dbd5c7a25a7cb98f5ca55d258b103a2054f859a46ae11aaf23134f9cc0d356ad", - "sha256:dd4f05f54a52fb558f1ba9f528228066954fee3ebe629fc1660d874d040ae5a3", - "sha256:de8dad4425a6ca6e4e5e297b27b5c824ecc7581910bf9aee86cb6835e6812aa7", - "sha256:e11e82b744887154b182fd3e7e8512418446501191994dbf9c9fc1f32cc8efd5", - "sha256:e6e73b9e02893c764e7e8d5bb5ce277f1a009cd5243f8228f75f842bf937c534", - "sha256:f73b96c41e3b2adedc34a7356e64c8eb96e03a3782b535e043a986276ce12a49", - "sha256:f93fd8e5c8c0a4aa1f424d6173f14a892044054871c771f8566e4008eaa359d2", - "sha256:fc33c5141b55ed366cfaad382df24fe7dcbc686de5be719b207bb248e3053dc5", - "sha256:fc7de24befaeae77ba923797c7c87834c73648a05a4bde34b3b7e5588973a453", - "sha256:fe562eb1a64e67dd297ccc4f5addea2501664954f2692b69a76449ec7913ecbf" - ], - "markers": "python_version >= '3.9'", - "version": "==2.0.0" - }, - "click": { - "hashes": [ - "sha256:12ff4785d337a1bb490bb7e9c2b1ee5da3112e94a8622f26a6c77f5d2fc6842a", - "sha256:981153a64e25f12d547d3426c367a4857371575ee7ad18df2a6183ab0545b2a6" - ], - "markers": "python_version >= '3.10'", - "version": "==8.3.1" - }, - "cryptography": { - "hashes": [ - "sha256:02fad249cb0e090b574e30b276a3da6a149e04ee2f049725b1f69e7b8351ec70", - "sha256:063b67749f338ca9c5a0b7fe438a52c25f9526b851e24e6c9310e7195aad3b4d", - "sha256:12cae594e9473bca1a7aceb90536060643128bb274fcea0fc459ab90f7d1ae7a", - "sha256:12f0fa16cc247b13c43d56d7b35287ff1569b5b1f4c5e87e92cc4fcc00cd10c0", - "sha256:22259338084d6ae497a19bae5d4c66b7ca1387d3264d1c2c0e72d9e9b6a77b97", - "sha256:26031f1e5ca62fcb9d1fcb34b2b60b390d1aacaa15dc8b895a9ed00968b97b30", - "sha256:27550628a518c5c6c903d84f637fbecf287f6cb9ced3804838a1295dc1fd0759", - "sha256:2b417edbe8877cda9022dde3a008e2deb50be9c407eef034aeeb3a8b11d9db3c", - "sha256:2ea0f37e9a9cf0df2952893ad145fd9627d326a59daec9b0802480fa3bcd2ead", - "sha256:2ef9e69886cbb137c2aef9772c2e7138dc581fad4fcbcf13cc181eb5a3ab6275", - "sha256:341359d6c9e68834e204ceaf25936dffeafea3829ab80e9503860dcc4f4dac58", - "sha256:380343e0653b1c9d7e1f55b52aaa2dbb2fdf2730088d48c43ca1c7c0abb7cc2f", - "sha256:3c21d92ed15e9cfc6eb64c1f5a0326db22ca9c2566ca46d845119b45b4400361", - "sha256:3dfa6567f2e9e4c5dceb8ccb5a708158a2a871052fa75c8b78cb0977063f1507", - "sha256:456b3215172aeefb9284550b162801d62f5f264a081049a3e94307fe20792cfa", - "sha256:4668298aef7cddeaf5c6ecc244c2302a2b8e40f384255505c22875eebb47888b", - "sha256:50575a76e2951fe7dbd1f56d181f8c5ceeeb075e9ff88e7ad997d2f42af06e7b", - "sha256:639301950939d844a9e1c4464d7e07f902fe9a7f6b215bb0d4f28584729935d8", - "sha256:64235194bad039a10bb6d2d930ab3323baaec67e2ce36215fd0952fad0930ca8", - "sha256:6617f67b1606dfd9fe4dbfa354a9508d4a6d37afe30306fe6c101b7ce3274b72", - "sha256:67177e8a9f421aa2d3a170c3e56eca4e0128883cf52a071a7cbf53297f18b175", - "sha256:6728c49e3b2c180ef26f8e9f0a883a2c585638db64cf265b49c9ba10652d430e", - "sha256:6739d56300662c468fddb0e5e291f9b4d084bead381667b9e654c7dd81705124", - "sha256:69cf0056d6947edc6e6760e5f17afe4bea06b56a9ac8a06de9d2bd6b532d4f3a", - "sha256:760997a4b950ff00d418398ad73fbc91aa2894b5c1db7ccb45b4f68b42a63b3c", - "sha256:79e865c642cfc5c0b3eb12af83c35c5aeff4fa5c672dc28c43721c2c9fdd2f0f", - "sha256:7e6142674f2a9291463e5e150090b95a8519b2fb6e6aaec8917dd8d094ce750d", - "sha256:7f417f034f91dcec1cb6c5c35b07cdbb2ef262557f701b4ecd803ee8cefed4f4", - "sha256:7f6690b6c55e9c5332c0b59b9c8a3fb232ebf059094c17f9019a51e9827df91c", - "sha256:8927ccfbe967c7df312ade694f987e7e9e22b2425976ddbf28271d7e58845290", - "sha256:8ce35b77aaf02f3b59c90b2c8a05c73bac12cea5b4e8f3fbece1f5fddea5f0ca", - "sha256:8e7304c4f4e9490e11efe56af6713983460ee0780f16c63f219984dab3af9d2d", - "sha256:90e5f0a7b3be5f40c3a0a0eafb32c681d8d2c181fc2a1bdabe9b3f611d9f6b1a", - "sha256:97c8115b27e19e592a05c45d0dd89c57f81f841cc9880e353e0d3bf25b2139ed", - "sha256:9a693028b9cbe51b5a1136232ee8f2bc242e4e19d456ded3fa7c86e43c713b4a", - "sha256:9a9c42a2723999a710445bc0d974e345c32adfd8d2fac6d8a251fa829ad31cfb", - "sha256:a3e84d5ec9ba01f8fd03802b2147ba77f0c8f2617b2aff254cedd551844209c8", - "sha256:aad75154a7ac9039936d50cf431719a2f8d4ed3d3c277ac03f3339ded1a5e707", - "sha256:b12c6b1e1651e42ab5de8b1e00dc3b6354fdfd778e7fa60541ddacc27cd21410", - "sha256:b928a3ca837c77a10e81a814a693f2295200adb3352395fad024559b7be7a736", - "sha256:bcb87663e1f7b075e48c3be3ecb5f0b46c8fc50b50a97cf264e7f60242dca3f2", - "sha256:c797e2517cb7880f8297e2c0f43bb910e91381339336f75d2c1c2cbf811b70b4", - "sha256:c89eb37fae9216985d8734c1afd172ba4927f5a05cfd9bf0e4863c6d5465b013", - "sha256:cdcd3edcbc5d55757e5f5f3d330dd00007ae463a7e7aa5bf132d1f22a4b62b19", - "sha256:d24c13369e856b94892a89ddf70b332e0b70ad4a5c43cf3e9cb71d6d7ffa1f7b", - "sha256:d4e4aadb7fc1f88687f47ca20bb7227981b03afaae69287029da08096853b738", - "sha256:d9528b535a6c4f8ff37847144b8986a9a143585f0540fbcb1a98115b543aa463", - "sha256:ed3775295fb91f70b4027aeba878d79b3e55c0b3e97eaa4de71f8f23a9f2eb77", - "sha256:ed418c37d095aeddf5336898a132fba01091f0ac5844e3e8018506f014b6d2c4" - ], - "markers": "python_version >= '3.8' and python_full_version not in '3.9.0, 3.9.1'", - "version": "==46.0.6" - }, - "dnspython": { - "hashes": [ - "sha256:01d9bbc4a2d76bf0db7c1f729812ded6d912bd318d3b1cf81d30c0f845dbf3af", - "sha256:181d3c6996452cb1189c4046c61599b84a5a86e099562ffde77d26984ff26d0f" - ], - "markers": "python_version >= '3.10'", - "version": "==2.8.0" - }, - "h11": { - "hashes": [ - "sha256:4e35b956cf45792e4caa5885e69fba00bdbc6ffafbfa020300e549b208ee5ff1", - "sha256:63cf8bbe7522de3bf65932fda1d9c2772064ffb3dae62d55932da54b31cb6c86" - ], - "markers": "python_version >= '3.8'", - "version": "==0.16.0" - }, - "httpcore": { - "hashes": [ - "sha256:2d400746a40668fc9dec9810239072b40b4484b640a8c38fd654a024c7a1bf55", - "sha256:6e34463af53fd2ab5d807f399a9b45ea31c3dfa2276f15a2c3f00afff6e176e8" - ], - "markers": "python_version >= '3.8'", - "version": "==1.0.9" - }, - "httpx": { - "hashes": [ - "sha256:75e98c5f16b0f35b567856f597f06ff2270a374470a5c2392242528e3e3e42fc", - "sha256:d909fcccc110f8c7faf814ca82a9a4d816bc5a6dbfea25d6591d6985b8ba59ad" - ], - "markers": "python_version >= '3.8'", - "version": "==0.28.1" - }, - "idna": { - "hashes": [ - "sha256:771a87f49d9defaf64091e6e6fe9c18d4833f140bd19464795bc32d966ca37ea", - "sha256:795dafcc9c04ed0c1fb032c2aa73654d8e8c5023a7df64a53f39190ada629902" - ], - "markers": "python_version >= '3.8'", - "version": "==3.11" - }, - "iniconfig": { - "hashes": [ - "sha256:c76315c77db068650d49c5b56314774a7804df16fee4402c1f19d6d15d8c4730", - "sha256:f631c04d2c48c52b84d0d0549c99ff3859c98df65b3101406327ecc7d53fbf12" - ], - "markers": "python_version >= '3.10'", - "version": "==2.3.0" - }, - "libipld": { - "hashes": [ - "sha256:02f00a19e6a557bfed2ce6911d541f96708d73ca457b709793885336adf91431", - "sha256:047d95641c95360adb6627447d6cbc048fcd9768f4a827078842d7d99cb79b77", - "sha256:06f766cec75f3d78339caa3ce3c6977e290e1a97f37e5f4ba358da2e77340196", - "sha256:071de5acf902e9a21d761572755afc8403cbaadd4b8199e7504ad52ee45b6b5e", - "sha256:082321d5ba84d9bb4e9f2577278040db2b4f624b131402735ea7eca13febedec", - "sha256:08261503b7307c6d9acbd3b2a221da9294b457204dcefce446f627893abb077e", - "sha256:08c8aadfebf9db9a547bd14ab4e5d438ee3f0a003eb4554bbecedaebbaaa0bbe", - "sha256:0dc2db1485703f7c6cf4ff9da0fe7a7d4ee883f92a35d68197c2294a3c3efd17", - "sha256:0fae0158971bf97aa6662e5f9cb5f497c35d5196336047ca4a9ebc6492b1f582", - "sha256:13cb6c68ec55a8802704241210cca44e09eaf4c0e9bd6823e191e56f7f038f05", - "sha256:1767f287c4137521f6b2dfa30583030b128174515dc4ddc481598b570de72ca4", - "sha256:196a8fcd86ae0c8096cea85ff308edf315d77fbb677ef3dd9eff0be9da526499", - "sha256:1a7de390a3eb897d3194f6c96067c21338fbe6e0fc1145ab6b51af276aa7a08e", - "sha256:1d791227d505a3aab9f5bc0df9baafacae825f9fd4cd01f157252efe15536b10", - "sha256:1d7f564d13a6983a20baef873a7966df28aa27a86ccc574456b4ebc7d31fdd2d", - "sha256:249b74fcd3ae8bb6d0c9b3e0ec23a75db60f7b40f8b07ef378dfc9227c921ef5", - "sha256:2ac45e3aef416fe2eccbe84e562d81714416790bfd0756a1aa49ba895d4c7010", - "sha256:2e8608367317210baa57caa89b504db05c1623d8418e5a94276bcf36059cef65", - "sha256:3344f30d47dcab9cba41dd8f2243874af91939e38e3c31f20d586383ca74296e", - "sha256:36be4ce9cb417eedec253eda9f55b92f29a35cbfcb24d108b496c72934fea7a2", - "sha256:36fe9cd1b5a75a315cab30091579242d05df39692f773f7d8221250503753e3a", - "sha256:37ea7cb7afb94277e4e095bcc0ae888ed4b6e0fe8082c41dccd6e9487ccfd729", - "sha256:3aa8ae124db8fe724199e7fd16c2bd72dcdd2f10572be28dcacf0eb7613af026", - "sha256:3dbed6b1f2559c4ba8b898043a96c763a16063a1810cc1378cfdc92bcbdbb7e6", - "sha256:3f033e98c9e95e8448c97bbc904271908076974d790a895abade2ae89433715e", - "sha256:4140f030eb3cfff17d04b9481f13aaed0b2910d1371fe7489394120ed1d09ae5", - "sha256:435643314f8a11d207c5e25536d3f6876a3efa337886faea7e5116e1d8b67bc6", - "sha256:4402e21ac3b5c754e1562b448175d35113fb39d7bb938dfa4e095a9629ebb8dd", - "sha256:4443d047fd1a9679534a87a6ee35c3a10793d4453801281341bb1e8390087c69", - "sha256:4446cae7584a446b58de66942f89f155d95c2cbfb9ad215af359086824d4e3b9", - "sha256:44ca1ba44cb801686557e9544d248e013a2d5d1ab9fed796f090bb0d51d8f4ef", - "sha256:4596509ef4c2f00df2d0914e8efc632e4eb84bf837e57a8f53036dcf4d0d3169", - "sha256:499345f7ce4ec6da1d35c4bf5c9f8aab9324f5c9e508db3065073fec2d4e4bde", - "sha256:5393886a7e387751904681ecfa7e5912471b46043f044baa041a2b4772e4f839", - "sha256:57ec5b9ffc608a438f41f359996982291382365c4a593b1bce30bbec7a63771a", - "sha256:5947e99b40e923170094a3313c9f3629c6ed475465ba95eadce6cdcf08f1f65a", - "sha256:5a50cbf5b3b73164fbb88169573ed3e824024c12fbc5f9efd87fb5c8f236ccc1", - "sha256:5c9f6e91da0f7dcdd3276eefe3f31b2ec659ed279f5e595e6f44efa337a18b2b", - "sha256:5e3e9be4bdeb90dbc537a53f8d06e8b2c703f4b7868f9316958e1bbde526a143", - "sha256:5f0929edbbd283a203e0a74d1794ad171cf4f5fc11453bddc366615c4b97043c", - "sha256:627035693460bae559d2e7f46bc577a27504d6e38e8715fcf9a8d905f6b1c72d", - "sha256:634d176664cf295360712157b5c5a83539da2f4416f3e0491340064d49e74fd8", - "sha256:63bc6858d73c324e29d74155bdb339e14330a88bb1a8cc8fdc295048337dca09", - "sha256:67c2e2a6604fe8b5aa8960c31989dfb84275693ba411d5139cdb87b2855bf009", - "sha256:6979074fd5bfeeda75653df39875f566fefc5d9f3bb6e786742f55d7a7f9bf38", - "sha256:6c2817982506d1ccda516da7d6cc2662b58a363fc84a163bea297ff61b789106", - "sha256:6f09281bebc3c4d397a58606663ee915290702db0323366f9f1bd30b8b4a3fc1", - "sha256:717c4630c4b1ad81c6896291cd93bcaca4ddc3f66412d81459e2641a505ec04a", - "sha256:72b59693a1ac0962ef24c660e8d34dc25c41a1f1da1da54badb7442a498fc9a4", - "sha256:76731ebebd824fa45e51cc85506b108aa5da7322e43864909895f1779e9e4b41", - "sha256:7b8e7100bffbe579b7c92a3c6a8852ce333e0de171e696a2063e1e39ec9cc50a", - "sha256:7e85ccd9136110e63943d95232b193c893e369c406273d235160e5cc4b39c9ce", - "sha256:829772d79337fc330c9c129295309d27c86785b78d947e3561e45ccfe67c519d", - "sha256:847d6f481f8e8e10347479490db824cc568689e7bc1a9f5e5aa67235494dcdf6", - "sha256:8494fe4235b053883209aa9c6a5d128f18efde7d6d0eceb51d2dcb029dffbc33", - "sha256:88ac549eb6c56287785ad20d0e7785d3e8b153b6a322fd5d7edf0e7fda2b182e", - "sha256:8be484f1dc5525453e17f07f02202180c708213f2b6ea06d3b9247a5702e0229", - "sha256:8d7cd1e7e88b0fbc8f4aa267bdea2d10452c9dd0e1aafa82a5e0751427f222b0", - "sha256:8db7127528af6393c02da6317a9188fb05dd13feb7557ec5be320208402f6537", - "sha256:908630dc28b16a517cf323293f0843f481b0872649cba7d4cfdbc6eb258f5674", - "sha256:91b02da059a6ae7f783efa826f640ab1ca5eb5dd370bfd3f41071693a363c4fb", - "sha256:95a2c4f507c88c01a797ec97ce10603bea684c03208227703e007485dc631971", - "sha256:981f870427c6f2ece983825b439c18718e5aaf8121a1659624e896ee905ab18e", - "sha256:9a1d84c630961cff188deaa2129c86d69f5779c8d02046fbe0c629ef162bc3df", - "sha256:9cb4e0cd56d66c2b751eef7288aba919a8a73f320c8f8b7060d522fdffb3cd5b", - "sha256:a48bc2f7845825143a36f6a305680823a2816488593024803064d0803e3cee35", - "sha256:a81fbf42a8edf094c7f8ebd77eb14d8cc7c3d6b3b51d786d47ecb4c6763da2fe", - "sha256:ad07c8574d59088ed8bcec7cd21544a50f51a324290e77b0b042a0e4c1ed1b07", - "sha256:ad6f8fd51a4472a8c2ae8e5c2b3fb274ea29876b9284d86456a203e41793952c", - "sha256:b040dab7eb04b0ff730e68840f40eb225c9f14e73ad21238b76c7b8ded3ad99d", - "sha256:b155c02626b194439f4b519a53985aedc8637ae56cf640ea6acf6172a37465de", - "sha256:b3404a11e7e7803f7bc87a819e694e2568828c1f13a5f7fce74d3240d5a07aba", - "sha256:b3d16a2d3588244702ea671373de2984e20d44936c9d6d457570e4d8b33dddcf", - "sha256:b438d42efc857768db97f2a5ca8114b933e73b827d91344ec9dac6734687f060", - "sha256:b69f2accac94f2599e4c012d9b53fa786863156d9a9401000edf148af81e5be5", - "sha256:bf0c82b53b595cd91c3920081acd73b287c5aeb81e756e6b1a636a10e01eaaa3", - "sha256:bf7f553e13916b67572c8ae8ea1b3227d709dfc4d98699a0451027174dc3739a", - "sha256:c17ae8593e33bbb3c377974cd046be03453e0a317b5c723b9375fc00491ac5dd", - "sha256:c1f3ed8f70b215a294b5c6830e91af48acde96b3c8a6cae13304291f8240b939", - "sha256:c4a0538187b8a2dfc9507d83ff6e9de150802f81c67d22c043e4036653ca048e", - "sha256:c8957b49c946d4ddd70f37bfe289494fab9088529db452f1cfcce31501369917", - "sha256:ca53a59670b113be3b57910c3132d003fd4571f2c83f75bbfc758f5ff3288708", - "sha256:d1549bfab54a1f422ec48d3141c9ec643444d8e80135b2a6e8ec8e109df05ff3", - "sha256:d5cd74d2e17435869c21400cb587e788785bf7f565897c0e651f82e69bc0da27", - "sha256:d689891c00251c22439ccfa4a445cee77cfa68b9e703fdf7ffe7abe4de56da86", - "sha256:d6ed1bbdd5380a23ca84d4460c65f46d85f12ca860ef801212806ffe5ad497fa", - "sha256:d9433e7c0ee73f30bc6849363660f8e7fda97fae5e3f0cf261e54af86dfa681d", - "sha256:d9f8849acfb2e13d10aa4e8095c6eb65db7f431d3a38c60760de0f0abebcd58d", - "sha256:e35a8735b8a4bdd09b9edfbf1ae36e9ba9a804de50c99352c9a06aa3da109a62", - "sha256:e52f5111d7d06838993d7c35256cb3e19143239c602cda177273788b0cb5ffc5", - "sha256:e7627f371682160cae818f817eb846bc8c267a5daa028748a7c73103d8df00eb", - "sha256:edbfe93ae92609436471a83a80219e3ab07d79496d39ef161d4111eb47ea8184", - "sha256:f11e053f954fe8efc37ee1d71ff3c20844551d1b2468388612876ecac500ccc3", - "sha256:f46179c722baf74c627c01c0bf85be7fcbde66bbf7c5f8c1bbb57bd3a17b861b", - "sha256:f78507f2f458239e4e7fe2f984c59c5f5060f1ec401e8f38cd2b59fc85d7d8fb", - "sha256:fa67924c14b481f3f2c3d8a173d755955c2363d889ffc78dadb8d6abcaa7fe3c", - "sha256:fd0877ef4a1bd6e42ba52659769b5b766583c67b3cfb4e7143f9d10b81fb7a74" - ], - "markers": "python_version >= '3.8'", - "version": "==3.3.2" - }, - "markdown-it-py": { - "hashes": [ - "sha256:87327c59b172c5011896038353a81343b6754500a08cd7a4973bb48c6d578147", - "sha256:cb0a2b4aa34f932c007117b194e945bd74e0ec24133ceb5bac59009cda1cb9f3" - ], - "markers": "python_version >= '3.10'", - "version": "==4.0.0" - }, - "mdurl": { - "hashes": [ - "sha256:84008a41e51615a49fc9966191ff91509e3c40b939176e643fd50a5c2196b8f8", - "sha256:bb413d29f5eea38f31dd4754dd7377d4465116fb207585f97bf925588687c1ba" - ], - "markers": "python_version >= '3.7'", - "version": "==0.1.2" - }, - "packaging": { - "hashes": [ - "sha256:00243ae351a257117b6a241061796684b084ed1c516a08c48a3f7e147a9d80b4", - "sha256:b36f1fef9334a5588b4166f8bcd26a14e521f2b55e6b9de3aaa80d3ff7a37529" - ], - "markers": "python_version >= '3.8'", - "version": "==26.0" - }, - "pluggy": { - "hashes": [ - "sha256:7dcc130b76258d33b90f61b658791dede3486c3e6bfb003ee5c9bfb396dd22f3", - "sha256:e920276dd6813095e9377c0bc5566d94c932c33b27a3e3945d8389c374dd4746" - ], - "markers": "python_version >= '3.9'", - "version": "==1.6.0" - }, - "pycparser": { - "hashes": [ - "sha256:600f49d217304a5902ac3c37e1281c9fe94e4d0489de643a9504c5cdfdfc6b29", - "sha256:b727414169a36b7d524c1c3e31839a521725078d7b2ff038656844266160a992" - ], - "markers": "python_version >= '3.10'", - "version": "==3.0" - }, - "pydantic": { - "hashes": [ - "sha256:4d351024c75c0f085a9febbb665ce8c0c6ec5d30e903bdb6394b7ede26aebb49", - "sha256:e561593fccf61e8a20fc46dfc2dfe075b8be7d0188df33f221ad1f0139180f9d" - ], - "markers": "python_version >= '3.9'", - "version": "==2.12.5" - }, - "pydantic-core": { - "hashes": [ - "sha256:0177272f88ab8312479336e1d777f6b124537d47f2123f89cb37e0accea97f90", - "sha256:01a3d0ab748ee531f4ea6c3e48ad9dac84ddba4b0d82291f87248f2f9de8d740", - "sha256:0384e2e1021894b1ff5a786dbf94771e2986ebe2869533874d7e43bc79c6f504", - "sha256:03b77d184b9eb40240ae9fd676ca364ce1085f203e1b1256f8ab9984dca80a84", - "sha256:03ca43e12fab6023fc79d28ca6b39b05f794ad08ec2feccc59a339b02f2b3d33", - "sha256:05a2c8852530ad2812cb7914dc61a1125dc4e06252ee98e5638a12da6cc6fb6c", - "sha256:070259a8818988b9a84a449a2a7337c7f430a22acc0859c6b110aa7212a6d9c0", - "sha256:08daa51ea16ad373ffd5e7606252cc32f07bc72b28284b6bc9c6df804816476e", - "sha256:0cbaad15cb0c90aa221d43c00e77bb33c93e8d36e0bf74760cd00e732d10a6a0", - "sha256:100baa204bb412b74fe285fb0f3a385256dad1d1879f0a5cb1499ed2e83d132a", - "sha256:112e305c3314f40c93998e567879e887a3160bb8689ef3d2c04b6cc62c33ac34", - "sha256:16f80f7abe3351f8ea6858914ddc8c77e02578544a0ebc15b4c2e1a0e813b0b2", - "sha256:1746d4a3d9a794cacae06a5eaaccb4b8643a131d45fbc9af23e353dc0a5ba5c3", - "sha256:1962293292865bca8e54702b08a4f26da73adc83dd1fcf26fbc875b35d81c815", - "sha256:1d1d9764366c73f996edd17abb6d9d7649a7eb690006ab6adbda117717099b14", - "sha256:1f8d33a7f4d5a7889e60dc39856d76d09333d8a6ed0f5f1190635cbec70ec4ba", - "sha256:22f0fb8c1c583a3b6f24df2470833b40207e907b90c928cc8d3594b76f874375", - "sha256:239edca560d05757817c13dc17c50766136d21f7cd0fac50295499ae24f90fdf", - "sha256:242a206cd0318f95cd21bdacff3fcc3aab23e79bba5cac3db5a841c9ef9c6963", - "sha256:25e1c2af0fce638d5f1988b686f3b3ea8cd7de5f244ca147c777769e798a9cd1", - "sha256:266fb4cbf5e3cbd0b53669a6d1b039c45e3ce651fd5442eff4d07c2cc8d66808", - "sha256:2782c870e99878c634505236d81e5443092fba820f0373997ff75f90f68cd553", - "sha256:287dad91cfb551c363dc62899a80e9e14da1f0e2b6ebde82c806612ca2a13ef1", - "sha256:29452c56df2ed968d18d7e21f4ab0ac55e71dc59524872f6fc57dcf4a3249ed2", - "sha256:299e0a22e7ae2b85c1a57f104538b2656e8ab1873511fd718a1c1c6f149b77b5", - "sha256:2a5e06546e19f24c6a96a129142a75cee553cc018ffee48a460059b1185f4470", - "sha256:2b761d210c9ea91feda40d25b4efe82a1707da2ef62901466a42492c028553a2", - "sha256:2c010c6ded393148374c0f6f0bf89d206bf3217f201faa0635dcd56bd1520f6b", - "sha256:2ff4321e56e879ee8d2a879501c8e469414d948f4aba74a2d4593184eb326660", - "sha256:3006c3dd9ba34b0c094c544c6006cc79e87d8612999f1a5d43b769b89181f23c", - "sha256:33cb885e759a705b426baada1fe68cbb0a2e68e34c5d0d0289a364cf01709093", - "sha256:346285d28e4c8017da95144c7f3acd42740d637ff41946af5ce6e5e420502dd5", - "sha256:34a64bc3441dc1213096a20fe27e8e128bd3ff89921706e83c0b1ac971276594", - "sha256:35b44f37a3199f771c3eaa53051bc8a70cd7b54f333531c59e29fd4db5d15008", - "sha256:378bec5c66998815d224c9ca994f1e14c0c21cb95d2f52b6021cc0b2a58f2a5a", - "sha256:3f37a19d7ebcdd20b96485056ba9e8b304e27d9904d233d7b1015db320e51f0a", - "sha256:3f84d5c1b4ab906093bdc1ff10484838aca54ef08de4afa9de0f5f14d69639cd", - "sha256:4009935984bd36bd2c774e13f9a09563ce8de4abaa7226f5108262fa3e637284", - "sha256:406bf18d345822d6c21366031003612b9c77b3e29ffdb0f612367352aab7d586", - "sha256:4819fa52133c9aa3c387b3328f25c1facc356491e6135b459f1de698ff64d869", - "sha256:482c982f814460eabe1d3bb0adfdc583387bd4691ef00b90575ca0d2b6fe2294", - "sha256:4bc36bbc0b7584de96561184ad7f012478987882ebf9f9c389b23f432ea3d90f", - "sha256:506d766a8727beef16b7adaeb8ee6217c64fc813646b424d0804d67c16eddb66", - "sha256:56121965f7a4dc965bff783d70b907ddf3d57f6eba29b6d2e5dabfaf07799c51", - "sha256:58133647260ea01e4d0500089a8c4f07bd7aa6ce109682b1426394988d8aaacc", - "sha256:5921a4d3ca3aee735d9fd163808f5e8dd6c6972101e4adbda9a4667908849b97", - "sha256:5a4e67afbc95fa5c34cf27d9089bca7fcab4e51e57278d710320a70b956d1b9a", - "sha256:5cb1b2f9742240e4bb26b652a5aeb840aa4b417c7748b6f8387927bc6e45e40d", - "sha256:62de39db01b8d593e45871af2af9e497295db8d73b085f6bfd0b18c83c70a8f9", - "sha256:634e8609e89ceecea15e2d61bc9ac3718caaaa71963717bf3c8f38bfde64242c", - "sha256:63510af5e38f8955b8ee5687740d6ebf7c2a0886d15a6d65c32814613681bc07", - "sha256:650ae77860b45cfa6e2cdafc42618ceafab3a2d9a3811fcfbd3bbf8ac3c40d36", - "sha256:6561e94ba9dacc9c61bce40e2d6bdc3bfaa0259d3ff36ace3b1e6901936d2e3e", - "sha256:65840751b72fbfd82c3c640cff9284545342a4f1eb1586ad0636955b261b0b05", - "sha256:6cb58b9c66f7e4179a2d5e0f849c48eff5c1fca560994d6eb6543abf955a149e", - "sha256:6f52298fbd394f9ed112d56f3d11aabd0d5bd27beb3084cc3d8ad069483b8941", - "sha256:707625ef0983fcfb461acfaf14de2067c5942c6bb0f3b4c99158bed6fedd3cf3", - "sha256:72f6c8b11857a856bcfa48c86f5368439f74453563f951e473514579d44aa612", - "sha256:753e230374206729bf0a807954bcc6c150d3743928a73faffee51ac6557a03c3", - "sha256:76d0819de158cd855d1cbb8fcafdf6f5cf1eb8e470abe056d5d161106e38062b", - "sha256:76ee27c6e9c7f16f47db7a94157112a2f3a00e958bc626e2f4ee8bec5c328fbe", - "sha256:77b63866ca88d804225eaa4af3e664c5faf3568cea95360d21f4725ab6e07146", - "sha256:79ec52ec461e99e13791ec6508c722742ad745571f234ea6255bed38c6480f11", - "sha256:7b93a4d08587e2b7e7882de461e82b6ed76d9026ce91ca7915e740ecc7855f60", - "sha256:7da7087d756b19037bc2c06edc6c170eeef3c3bafcb8f532ff17d64dc427adfd", - "sha256:7f3bf998340c6d4b0c9a2f02d6a400e51f123b59565d74dc60d252ce888c260b", - "sha256:80aa89cad80b32a912a65332f64a4450ed00966111b6615ca6816153d3585a8c", - "sha256:8566def80554c3faa0e65ac30ab0932b9e3a5cd7f8323764303d468e5c37595a", - "sha256:873e0d5b4fb9b89ef7c2d2a963ea7d02879d9da0da8d9d4933dee8ee86a8b460", - "sha256:88942d3a3dff3afc8288c21e565e476fc278902ae4d6d134f1eeda118cc830b1", - "sha256:8bfeaf8735be79f225f3fefab7f941c712aaca36f1128c9d7e2352ee1aa87bdf", - "sha256:8e7c86f27c585ef37c35e56a96363ab8de4e549a95512445b85c96d3e2f7c1bf", - "sha256:915c3d10f81bec3a74fbd4faebe8391013ba61e5a1a8d48c4455b923bdda7858", - "sha256:93e8740d7503eb008aa2df04d3b9735f845d43ae845e6dcd2be0b55a2da43cd2", - "sha256:941103c9be18ac8daf7b7adca8228f8ed6bb7a1849020f643b3a14d15b1924d9", - "sha256:97aeba56665b4c3235a0e52b2c2f5ae9cd071b8a8310ad27bddb3f7fb30e9aa2", - "sha256:a39455728aabd58ceabb03c90e12f71fd30fa69615760a075b9fec596456ccc3", - "sha256:a3a52f6156e73e7ccb0f8cced536adccb7042be67cb45f9562e12b319c119da6", - "sha256:a668ce24de96165bb239160b3d854943128f4334822900534f2fe947930e5770", - "sha256:a75dafbf87d6276ddc5b2bf6fae5254e3d0876b626eb24969a574fff9149ee5d", - "sha256:aabf5777b5c8ca26f7824cb4a120a740c9588ed58df9b2d196ce92fba42ff8dc", - "sha256:aec5cf2fd867b4ff45b9959f8b20ea3993fc93e63c7363fe6851424c8a7e7c23", - "sha256:b2379fa7ed44ddecb5bfe4e48577d752db9fc10be00a6b7446e9663ba143de26", - "sha256:b4ececa40ac28afa90871c2cc2b9ffd2ff0bf749380fbdf57d165fd23da353aa", - "sha256:b5819cd790dbf0c5eb9f82c73c16b39a65dd6dd4d1439dcdea7816ec9adddab8", - "sha256:b74557b16e390ec12dca509bce9264c3bbd128f8a2c376eaa68003d7f327276d", - "sha256:b80aa5095cd3109962a298ce14110ae16b8c1aece8b72f9dafe81cf597ad80b3", - "sha256:b93590ae81f7010dbe380cdeab6f515902ebcbefe0b9327cc4804d74e93ae69d", - "sha256:b96d5f26b05d03cc60f11a7761a5ded1741da411e7fe0909e27a5e6a0cb7b034", - "sha256:bd3d54f38609ff308209bd43acea66061494157703364ae40c951f83ba99a1a9", - "sha256:bfea2a5f0b4d8d43adf9d7b8bf019fb46fdd10a2e5cde477fbcb9d1fa08c68e1", - "sha256:c007fe8a43d43b3969e8469004e9845944f1a80e6acd47c150856bb87f230c56", - "sha256:c1df3d34aced70add6f867a8cf413e299177e0c22660cc767218373d0779487b", - "sha256:c23e27686783f60290e36827f9c626e63154b82b116d7fe9adba1fda36da706c", - "sha256:c8d8b4eb992936023be7dee581270af5c6e0697a8559895f527f5b7105ecd36a", - "sha256:c9e19dd6e28fdcaa5a1de679aec4141f691023916427ef9bae8584f9c2fb3b0e", - "sha256:d0d2568a8c11bf8225044aa94409e21da0cb09dcdafe9ecd10250b2baad531a9", - "sha256:d38548150c39b74aeeb0ce8ee1d8e82696f4a4e16ddc6de7b1d8823f7de4b9b5", - "sha256:d3a978c4f57a597908b7e697229d996d77a6d3c94901e9edee593adada95ce1a", - "sha256:d5160812ea7a8a2ffbe233d8da666880cad0cbaf5d4de74ae15c313213d62556", - "sha256:dc799088c08fa04e43144b164feb0c13f9a0bc40503f8df3e9fde58a3c0c101e", - "sha256:df3959765b553b9440adfd3c795617c352154e497a4eaf3752555cfb5da8fc49", - "sha256:dfa8a0c812ac681395907e71e1274819dec685fec28273a28905df579ef137e2", - "sha256:e25c479382d26a2a41b7ebea1043564a937db462816ea07afa8a44c0866d52f9", - "sha256:e4f4a984405e91527a0d62649ee21138f8e3d0ef103be488c1dc11a80d7f184b", - "sha256:e536c98a7626a98feb2d3eaf75944ef6f3dbee447e1f841eae16f2f0a72d8ddc", - "sha256:e56ba91f47764cc14f1daacd723e3e82d1a89d783f0f5afe9c364b8bb491ccdb", - "sha256:e672ba74fbc2dc8eea59fb6d4aed6845e6905fc2a8afe93175d94a83ba2a01a0", - "sha256:e7b576130c69225432866fe2f4a469a85a54ade141d96fd396dffcf607b558f8", - "sha256:e8465ab91a4bd96d36dde3263f06caa6a8a6019e4113f24dc753d79a8b3a3f82", - "sha256:e96cea19e34778f8d59fe40775a7a574d95816eb150850a85a7a4c8f4b94ac69", - "sha256:ece5c59f0ce7d001e017643d8d24da587ea1f74f6993467d85ae8a5ef9d4f42b", - "sha256:eceb81a8d74f9267ef4081e246ffd6d129da5d87e37a77c9bde550cb04870c1c", - "sha256:ed2e99c456e3fadd05c991f8f437ef902e00eedf34320ba2b0842bd1c3ca3a75", - "sha256:f0cd744688278965817fd0839c4a4116add48d23890d468bc436f78beb28abf5", - "sha256:f14f8f046c14563f8eb3f45f499cc658ab8d10072961e07225e507adb700e93f", - "sha256:f15489ba13d61f670dcc96772e733aad1a6f9c429cc27574c6cdaed82d0146ad", - "sha256:f31d95a179f8d64d90f6831d71fa93290893a33148d890ba15de25642c5d075b", - "sha256:f41a7489d32336dbf2199c8c0a215390a751c5b014c2c1c5366e817202e9cdf7", - "sha256:f41eb9797986d6ebac5e8edff36d5cef9de40def462311b3eb3eeded1431e425", - "sha256:f547144f2966e1e16ae626d8ce72b4cfa0caedc7fa28052001c94fb2fcaa1c52" - ], - "markers": "python_version >= '3.9'", - "version": "==2.41.5" - }, - "pygments": { - "hashes": [ - "sha256:636cb2477cec7f8952536970bc533bc43743542f70392ae026374600add5b887", - "sha256:86540386c03d588bb81d44bc3928634ff26449851e99741617ecb9037ee5ec0b" - ], - "markers": "python_version >= '3.8'", - "version": "==2.19.2" - }, - "pytest": { - "hashes": [ - "sha256:711ffd45bf766d5264d487b917733b453d917afd2b0ad65223959f59089f875b", - "sha256:75186651a92bd89611d1d9fc20f0b4345fd827c41ccd5c299a868a05d70edf11" - ], - "index": "pypi", - "markers": "python_version >= '3.10'", - "version": "==9.0.2" - }, - "rich": { - "hashes": [ - "sha256:793431c1f8619afa7d3b52b2cdec859562b950ea0d4b6b505397612db8d5362d", - "sha256:b8daa0b9e4eef54dd8cf7c86c03713f53241884e814f4e2f5fb342fe520f639b" - ], - "markers": "python_full_version >= '3.8.0'", - "version": "==14.3.3" - }, - "shellingham": { - "hashes": [ - "sha256:7ecfff8f2fd72616f7481040475a65b2bf8af90a56c89140852d1120324e8686", - "sha256:8dbca0739d487e5bd35ab3ca4b36e11c4078f3a234bfce294b0a0291363404de" - ], - "markers": "python_version >= '3.7'", - "version": "==1.5.4" - }, - "typer": { - "hashes": [ - "sha256:7985e89081c636b88d172c2ee0cfe33c253160994d47bdfdc302defd7d1f1d01", - "sha256:ea835607cd752343b6b2b7ce676893e5a0324082268b48f27aa058bdb7d2145d" - ], - "index": "pypi", - "markers": "python_version >= '3.9'", - "version": "==0.21.1" - }, - "typing-extensions": { - "hashes": [ - "sha256:0cea48d173cc12fa28ecabc3b837ea3cf6f38c6d1136f85cbaaf598984861466", - "sha256:f0fa19c6845758ab08074a0cfa8b7aecb71c999ca73d62883bc25cc018c4e548" - ], - "markers": "python_version >= '3.9'", - "version": "==4.15.0" - }, - "typing-inspection": { - "hashes": [ - "sha256:4ed1cacbdc298c220f1bd249ed5287caa16f34d44ef4e9c3d0cbad5b521545e7", - "sha256:ba561c48a67c5958007083d386c3295464928b01faa735ab8547c5692e87f464" - ], - "markers": "python_version >= '3.9'", - "version": "==0.4.2" - }, - "websockets": { - "hashes": [ - "sha256:0701bc3cfcb9164d04a14b149fd74be7347a530ad3bbf15ab2c678a2cd3dd9a2", - "sha256:0a34631031a8f05657e8e90903e656959234f3a04552259458aac0b0f9ae6fd9", - "sha256:0af68c55afbd5f07986df82831c7bff04846928ea8d1fd7f30052638788bc9b5", - "sha256:0c9e74d766f2818bb95f84c25be4dea09841ac0f734d1966f415e4edfc4ef1c3", - "sha256:0f3c1e2ab208db911594ae5b4f79addeb3501604a165019dd221c0bdcabe4db8", - "sha256:0fdfe3e2a29e4db3659dbd5bbf04560cea53dd9610273917799f1cde46aa725e", - "sha256:1009ee0c7739c08a0cd59de430d6de452a55e42d6b522de7aa15e6f67db0b8e1", - "sha256:1234d4ef35db82f5446dca8e35a7da7964d02c127b095e172e54397fb6a6c256", - "sha256:16b6c1b3e57799b9d38427dda63edcbe4926352c47cf88588c0be4ace18dac85", - "sha256:2034693ad3097d5355bfdacfffcbd3ef5694f9718ab7f29c29689a9eae841880", - "sha256:21c1fa28a6a7e3cbdc171c694398b6df4744613ce9b36b1a498e816787e28123", - "sha256:229cf1d3ca6c1804400b0a9790dc66528e08a6a1feec0d5040e8b9eb14422375", - "sha256:27ccee0071a0e75d22cb35849b1db43f2ecd3e161041ac1ee9d2352ddf72f065", - "sha256:363c6f671b761efcb30608d24925a382497c12c506b51661883c3e22337265ed", - "sha256:39c1fec2c11dc8d89bba6b2bf1556af381611a173ac2b511cf7231622058af41", - "sha256:3b1ac0d3e594bf121308112697cf4b32be538fb1444468fb0a6ae4feebc83411", - "sha256:3be571a8b5afed347da347bfcf27ba12b069d9d7f42cb8c7028b5e98bbb12597", - "sha256:3c714d2fc58b5ca3e285461a4cc0c9a66bd0e24c5da9911e30158286c9b5be7f", - "sha256:3d00075aa65772e7ce9e990cab3ff1de702aa09be3940d1dc88d5abf1ab8a09c", - "sha256:3e90baa811a5d73f3ca0bcbf32064d663ed81318ab225ee4f427ad4e26e5aff3", - "sha256:47819cea040f31d670cc8d324bb6435c6f133b8c7a19ec3d61634e62f8d8f9eb", - "sha256:47b099e1f4fbc95b701b6e85768e1fcdaf1630f3cbe4765fa216596f12310e2e", - "sha256:4a9fac8e469d04ce6c25bb2610dc535235bd4aa14996b4e6dbebf5e007eba5ee", - "sha256:4b826973a4a2ae47ba357e4e82fa44a463b8f168e1ca775ac64521442b19e87f", - "sha256:4c2529b320eb9e35af0fa3016c187dffb84a3ecc572bcee7c3ce302bfeba52bf", - "sha256:54479983bd5fb469c38f2f5c7e3a24f9a4e70594cd68cd1fa6b9340dadaff7cf", - "sha256:558d023b3df0bffe50a04e710bc87742de35060580a293c2a984299ed83bc4e4", - "sha256:5756779642579d902eed757b21b0164cd6fe338506a8083eb58af5c372e39d9a", - "sha256:592f1a9fe869c778694f0aa806ba0374e97648ab57936f092fd9d87f8bc03665", - "sha256:595b6c3969023ecf9041b2936ac3827e4623bfa3ccf007575f04c5a6aa318c22", - "sha256:5a939de6b7b4e18ca683218320fc67ea886038265fd1ed30173f5ce3f8e85675", - "sha256:5d54b09eba2bada6011aea5375542a157637b91029687eb4fdb2dab11059c1b4", - "sha256:5df592cd503496351d6dc14f7cdad49f268d8e618f80dce0cd5a36b93c3fc08d", - "sha256:5f4c04ead5aed67c8a1a20491d54cdfba5884507a48dd798ecaf13c74c4489f5", - "sha256:64dee438fed052b52e4f98f76c5790513235efaa1ef7f3f2192c392cd7c91b65", - "sha256:66dd88c918e3287efc22409d426c8f729688d89a0c587c88971a0faa2c2f3792", - "sha256:678999709e68425ae2593acf2e3ebcbcf2e69885a5ee78f9eb80e6e371f1bf57", - "sha256:67f2b6de947f8c757db2db9c71527933ad0019737ec374a8a6be9a956786aaf9", - "sha256:693f0192126df6c2327cce3baa7c06f2a117575e32ab2308f7f8216c29d9e2e3", - "sha256:746ee8dba912cd6fc889a8147168991d50ed70447bf18bcda7039f7d2e3d9151", - "sha256:756c56e867a90fb00177d530dca4b097dd753cde348448a1012ed6c5131f8b7d", - "sha256:76d1f20b1c7a2fa82367e04982e708723ba0e7b8d43aa643d3dcd404d74f1475", - "sha256:7f493881579c90fc262d9cdbaa05a6b54b3811c2f300766748db79f098db9940", - "sha256:823c248b690b2fd9303ba00c4f66cd5e2d8c3ba4aa968b2779be9532a4dad431", - "sha256:82544de02076bafba038ce055ee6412d68da13ab47f0c60cab827346de828dee", - "sha256:8dd8327c795b3e3f219760fa603dcae1dcc148172290a8ab15158cf85a953413", - "sha256:8fdc51055e6ff4adeb88d58a11042ec9a5eae317a0a53d12c062c8a8865909e8", - "sha256:a625e06551975f4b7ea7102bc43895b90742746797e2e14b70ed61c43a90f09b", - "sha256:abdc0c6c8c648b4805c5eacd131910d2a7f6455dfd3becab248ef108e89ab16a", - "sha256:ac017dd64572e5c3bd01939121e4d16cf30e5d7e110a119399cf3133b63ad054", - "sha256:ac1e5c9054fe23226fb11e05a6e630837f074174c4c2f0fe442996112a6de4fb", - "sha256:ac60e3b188ec7574cb761b08d50fcedf9d77f1530352db4eef1707fe9dee7205", - "sha256:b359ed09954d7c18bbc1680f380c7301f92c60bf924171629c5db97febb12f04", - "sha256:b7643a03db5c95c799b89b31c036d5f27eeb4d259c798e878d6937d71832b1e4", - "sha256:ba9e56e8ceeeedb2e080147ba85ffcd5cd0711b89576b83784d8605a7df455fa", - "sha256:c338ffa0520bdb12fbc527265235639fb76e7bc7faafbb93f6ba80d9c06578a9", - "sha256:cad21560da69f4ce7658ca2cb83138fb4cf695a2ba3e475e0559e05991aa8122", - "sha256:d08eb4c2b7d6c41da6ca0600c077e93f5adcfd979cd777d747e9ee624556da4b", - "sha256:d50fd1ee42388dcfb2b3676132c78116490976f1300da28eb629272d5d93e905", - "sha256:d591f8de75824cbb7acad4e05d2d710484f15f29d4a915092675ad3456f11770", - "sha256:d5f6b181bb38171a8ad1d6aa58a67a6aa9d4b38d0f8c5f496b9e42561dfc62fe", - "sha256:d63efaa0cd96cf0c5fe4d581521d9fa87744540d4bc999ae6e08595a1014b45b", - "sha256:d99e5546bf73dbad5bf3547174cd6cb8ba7273062a23808ffea025ecb1cf8562", - "sha256:e09473f095a819042ecb2ab9465aee615bd9c2028e4ef7d933600a8401c79561", - "sha256:e8b56bdcdb4505c8078cb6c7157d9811a85790f2f2b3632c7d1462ab5783d215", - "sha256:ee443ef070bb3b6ed74514f5efaa37a252af57c90eb33b956d35c8e9c10a1931", - "sha256:f29d80eb9a9263b8d109135351caf568cc3f80b9928bccde535c235de55c22d9", - "sha256:f7a866fbc1e97b5c617ee4116daaa09b722101d4a3c170c787450ba409f9736f", - "sha256:fcd5cf9e305d7b8338754470cf69cf81f420459dbae8a3b40cee57417f4614a7" - ], - "markers": "python_version >= '3.9'", - "version": "==15.0.1" - } - }, - "develop": {} -} diff --git a/README.md b/README.md index db307ef..28ffcb3 100644 --- a/README.md +++ b/README.md @@ -6,26 +6,20 @@ A bridge between ATProto (server-side) and GraphQL (client-side) for developing ``` git submodule update --init --recursive -pipenv install -``` - -**Testing:** - -``` -pipenv run python -m pytest +npm install ``` ## Schema Generation -The `schema/` folder contains scripts to generate a GraphQL schema from Lexicon. Standard ATProto definitions are initialized in the `deps/atproto` folder. +This folder contains scripts to generate a GraphQL schema from Lexicon. Standard ATProto definitions are initialized in the `deps/atproto` folder. Example usage: ``` -pipenv run python schema/generate_lexicon_schema.py \ +npx tsx src/generateLexiconSchema.ts \ app.bsky.actor.getProfile \ com.atproto.server.getSession \ - -o schema/schema-generated.graphql + -o schema-generated.graphql ``` This will generate schema definitions for the `getProfile` and `getSession` procedures and recursively import all their referenced types, e.g. @@ -73,20 +67,10 @@ This repo also contains a Rust GraphQL server that can bridge an exported schema ### Building ```bash -cd server -cargo run --release +npm run server ``` -The server will start on `http://localhost:8080` by default. - -### Environment Configuration - -Copy `.env.example` to `.env` and configure as needed for your deployment. - -| Variable | Default | Description | -|----------|---------|-------------| -| `HOST` | `0.0.0.0` | Host to bind the server to | -| `PORT` | `8080` | Port to listen on | +The server will start on `http://localhost:8000`. ## License diff --git a/js/package-lock.json b/package-lock.json similarity index 100% rename from js/package-lock.json rename to package-lock.json diff --git a/js/package.json b/package.json similarity index 100% rename from js/package.json rename to package.json diff --git a/js/public/index.html b/public/index.html similarity index 100% rename from js/public/index.html rename to public/index.html diff --git a/js/schema-generated.graphql b/schema-generated.graphql similarity index 100% rename from js/schema-generated.graphql rename to schema-generated.graphql diff --git a/schema/__init__.py b/schema/__init__.py deleted file mode 100644 index e69de29..0000000 diff --git a/schema/generate_lexicon_schema.py b/schema/generate_lexicon_schema.py deleted file mode 100644 index 57a7b46..0000000 --- a/schema/generate_lexicon_schema.py +++ /dev/null @@ -1,466 +0,0 @@ -"""Convert Lexicon definitions to GraphQL""" - -import os -import re -import sys -import traceback -from pathlib import Path -from typing import Annotated, TypeAlias - -from atproto_lexicon.models import ( - LexArray, - LexBlob, - LexDefinition, - LexObject, - LexPrimitive, - LexRef, - LexRefUnion, - LexRefVariant, - LexString, - LexXrpcQuery, -) -from atproto_lexicon.parser import lexicon_parse_file -from typer import Argument, Option, run - - -def normalize_type_name(s: str) -> str: - """ - Normalize type name to PascalCase - """ - # Convert to PascalCase - return s[0].upper() + s[1:] if s else s - - -class LexiconPath: - _segments: list[str] - - def __init__(self, path: str | None = None) -> None: - if path is None: - self._segments = [] - else: - self._segments = path.split(".") - - @property - def segments(self): - return self._segments[:] - - def dot_path(self): - return ".".join(self._segments) - - def file_path(self): - return "/".join(self._segments) - - -# Constants -BASE_DIR = os.path.dirname(os.path.abspath(__file__)) -LEXICON_DIR = os.path.join(BASE_DIR, "../deps/atproto/lexicons") - -TYPE_MAPPING = { - "string": "String", - "integer": "Int", - "number": "Float", - "boolean": "Boolean", - "bytes": "String", -} - -FORMAT_MAPPING = { - "did": "ID", - "handle": "ID", - "uri": "String", - "cid": "String", - "datetime": "String", - "date": "String", - "time": "String", - "at-identifier": "ID", -} - -SKIP_FIELDS = {"debug"} # Fields to skip in GraphQL output - - -def resolve_lexicon_path(lexicon_path: LexiconPath) -> str: - """ - Resolve a lexicon ID to its file path - """ - dir_parts = lexicon_path.segments - - # Construct path: app.bsky.actor.getProfile -> app/bsky/actor/getProfile.json - file_path = os.path.join(LEXICON_DIR, *dir_parts[:-1], f"{dir_parts[-1]}.json") - - if not os.path.exists(file_path): - raise FileNotFoundError(f"Lexicon file not found: {file_path}") - - return file_path - - -def normalize_reference(base: str, ref: str) -> str: - """ - Normalize a reference like '#profileViewDetailed' - """ - if "#" in base and ref[0] == "#": - return base.split("#")[0] + ref - elif "#" not in base and ref[0] == "#": - return base + ref - else: - return ref - - -def resolve_reference(ref: str) -> LexDefinition | None: - if "#" in ref: - lexicon_id, type_name = ref.split("#", 1) - else: - lexicon_id = ref - type_name = "main" - try: - lexicon_path = resolve_lexicon_path(LexiconPath(lexicon_id)) - - # Use structured parsing instead of JSON - lexicon_structured_data = lexicon_parse_file(lexicon_path) - - # Find the type definition in the structured data - if not lexicon_structured_data: - return None - - defs = lexicon_structured_data.defs - - # Check if the type_name is in defs directly (as dict key) - if type_name in defs: - return defs[type_name] - - return None - except Exception as e: - print(f"Warning: Could not resolve reference {ref}: {e}", file=sys.stderr) - return None - - -def lex_type_to_graphql_type( - base: str, - lex_type: LexRefVariant | LexPrimitive | LexBlob | LexObject | LexArray, - is_required: bool = False, -) -> str: - """ - Convert Lexicon type to GraphQL type - """ - if isinstance(lex_type, LexArray): - items_type = lex_type.items - item_type = lex_type_to_graphql_type(base, items_type, True) - output = f"[{item_type}]" - elif isinstance(lex_type, LexRef): - # For reference types, we use the type name directly - ref = normalize_reference(base, lex_type.ref) or "" - # Convert to GraphQL naming convention - camelCase to PascalCase - type_name = f"Lexicon_{ref.replace('#', '.').replace('.', '_')}" - output = type_name - elif isinstance(lex_type, LexString): - if lex_type.format in FORMAT_MAPPING: - output = FORMAT_MAPPING[lex_type.format] - else: - output = "String" - elif lex_type.type in TYPE_MAPPING: - output = TYPE_MAPPING[lex_type.type] - else: - output = "Unknown" - - nullable_indicator = "!" if is_required else "" - return f"{output}{nullable_indicator}" - - -TypeDef: TypeAlias = LexObject | LexString -TypeDefs: TypeAlias = dict[str, TypeDef] - - -def to_upper_snake_case(s: str) -> str: - return re.sub(r"[^a-zA-Z0-9]+", "_", s).upper() - - -def lex_object_definition_to_graphql(type_name: str, type_def: TypeDef) -> str: - """ - Convert a LexObject definition from lexicon to GraphQL - """ - - if isinstance(type_def, LexString): - # Enums - graphql_lines = [ - f"# {type_name}\nenum Lexicon_{type_name.replace('#', '_').replace('.', '_')} {{" - ] - - for field_name in type_def.known_values or []: - graphql_lines.append(f" {to_upper_snake_case(field_name)}") - else: - # Struct/object definitions - graphql_lines = [ - f"# {type_name}\ntype Lexicon_{type_name.replace('#', '_').replace('.', '_')} {{" - ] - - properties = type_def.properties - required_fields = set(type_def.required or []) - - for field_name, field_def in properties.items(): - # Skip debug field as per requirements - if field_name in SKIP_FIELDS: - continue - - # Skip ref unions(?) - if isinstance(field_def, LexRefUnion): - continue - - # Skip "unknown" fields - if field_def.type == "unknown": - continue - - is_required = field_name in required_fields - graphql_type = lex_type_to_graphql_type(type_name, field_def, is_required) - graphql_lines.append(f" {field_name}: {graphql_type}") - - graphql_lines.append("}") - return "\n".join(graphql_lines) - - -# Build the nested types from the outside in -# For app.bsky.actor.getProfile, we need: -# 1. type LexiconApp { bsky: LexiconAppBsky! } -# 2. type LexiconAppBsky { actor: LexiconAppBskyActor! } -# 3. type LexiconAppBskyActor { getProfile(...): ... } -def output_lexicon_namespaces( - namespaces: dict[str, str], root: LexiconPath -) -> list[str]: - lines: list[str] = [] - chunks: list[str] = [] - root_len = len(root.segments) - while len(namespaces): - lexicon_path = LexiconPath(next(iter(namespaces))) - if root_len == len(lexicon_path.segments) - 1: - # Done, output the type - lines.append(namespaces.pop(lexicon_path.dot_path())) - else: - next_segment = lexicon_path.segments[root_len] - next_path = ( - f"{root.dot_path()}.{next_segment}" if root_len > 0 else next_segment - ) - - group: dict[str, str] = dict() - for path in list(namespaces.keys()): - if path.startswith(f"{next_path}."): - group[path] = namespaces.pop(path) - chunks += output_lexicon_namespaces(group, LexiconPath(next_path)) - - lines.append( - f"{next_segment}: {'_'.join(['Lexicon'] + LexiconPath(next_path).segments)}!" - ) - - content = " " + "\n ".join(lines) - chunks.append(f"type {'_'.join(['Lexicon'] + root.segments)} {{\n{content}\n}}\n") - return chunks - - -def generate_lexicon_structure( - lexicon_path: LexiconPath, -) -> tuple[str, TypeDefs]: - """ - Generate the nested Lexicon structure for a lexicon endpoint - Returns (graphql_type, set(refs)) - """ - - method_name = lexicon_path.segments[-1] - - try: - # Structured parsing of the Lexicon .json file - lexicon_structured_data = lexicon_parse_file(resolve_lexicon_path(lexicon_path)) - - if not lexicon_structured_data: - return ("", dict()) - - defs = lexicon_structured_data.defs - main_def = defs["main"] - assert isinstance(main_def, LexXrpcQuery) - - # Build the method definition - referenced_types: set[str] = set() - object_definitions: TypeDefs = dict() - - # Add parameters as fields - method_fields: list[str] = [] - if main_def.parameters: - params = main_def.parameters - required_fields = params.required or [] - for field_name, field_def in params.properties.items(): - # Convert the structured field definition to dict for get_graphql_type - is_required = field_name in required_fields - graphql_type = lex_type_to_graphql_type( - lexicon_path.dot_path(), field_def, is_required - ) - method_fields.append(f"{field_name}: {graphql_type}") - - # Sweep up refs - if isinstance(field_def, LexRef): - referenced_types.add(field_def.ref) - - method_params = f"({', '.join(method_fields)})" if len(method_fields) else "" - - return_type = None - - if main_def.output: - output_schema = main_def.output.schema_ - if isinstance(output_schema, LexRef): - # Use the output type as return type - return_type = lex_type_to_graphql_type( - lexicon_path.dot_path(), output_schema - ) - - # Sweep up refs - referenced_types.add(output_schema.ref) - elif isinstance(output_schema, LexObject): - # Handle inline object definitions for return type - output_type = f"Lexicon_{'_'.join(lexicon_path.segments)}Output" - return_type = output_type - object_definitions[lexicon_path.dot_path() + "Output"] = output_schema - - # Resolve references - for ref in referenced_types: - ref = normalize_reference(lexicon_path.dot_path(), ref) - ref_def = resolve_reference(ref) - if isinstance(ref_def, TypeDef): - object_definitions[ref] = ref_def - - if return_type: - method_def = f"{method_name}{method_params}: {return_type}" - else: - method_def = f"{method_name}{method_params}" - - return (method_def, object_definitions) - except Exception as e: - print( - f"Error processing lexicon {'.'.join(lexicon_path.segments)}: {e}", - file=sys.stderr, - ) - traceback.print_exc() - return ("", dict()) - - -def generate_definitions(lexicon_ids: list[str]) -> list[str]: - chunks: list[str] = [] - lexicon_fields: dict[str, str] = dict() - object_definitions: TypeDefs = dict() - for lexicon_id in lexicon_ids: - lexicon_path = LexiconPath(lexicon_id) - - # Generate main lexicon structure - method_type, collected_object_definitions = generate_lexicon_structure( - lexicon_path - ) - lexicon_fields[lexicon_path.dot_path()] = method_type - object_definitions.update(collected_object_definitions) - - # Walk output types for more refs - final_definitions: TypeDefs = dict() - new_definitions: TypeDefs = dict() - while len(object_definitions): - for obj_name, obj_def in object_definitions.items(): - if isinstance(obj_def, LexObject): - for field_def in obj_def.properties.values(): - # Export refs - if isinstance(field_def, LexRef): - ref = normalize_reference(obj_name, field_def.ref) - ref_def = resolve_reference(ref) - if isinstance(ref_def, TypeDef): - new_definitions[ref] = ref_def - continue - elif isinstance(field_def, LexArray) and isinstance( - field_def.items, LexRef - ): - ref = normalize_reference(obj_name, field_def.items.ref) - ref_def = resolve_reference(ref) - if isinstance(ref_def, LexObject) or isinstance( - ref_def, LexString - ): - new_definitions[ref] = ref_def - continue - - final_definitions[obj_name] = obj_def - - # Reset object_definitions to only be ones we haven't seen yet. - object_definitions = dict() - for obj_key, obj_def in new_definitions.items(): - if obj_key not in final_definitions: - object_definitions[obj_key] = obj_def - object_definitions = final_definitions - - # Generate types for all output types - for name, type in object_definitions.items(): - chunks.append(lex_object_definition_to_graphql(name, type) + "\n\n") - - # Generate Lexicon structs iteratively. - chunks += output_lexicon_namespaces(lexicon_fields, LexiconPath()) - - return chunks - - -def read_schema_files(schema_files: list[str] | None) -> str: - """Read content from schema files or folders recursively.""" - if not schema_files: - return "" - - output = "" - for schema_file in schema_files: - path = Path(schema_file) - if path.is_file(): - # If it's a single file, read it - with open(str(path), "r") as f: - content = f.read() - output += "\n" + content + "\n" - elif path.is_dir(): - # If it's a directory, recursively read all .graphql files - for graphql_file in path.rglob("*.graphql"): - with open(str(graphql_file), "r") as f: - content = f.read() - output += "\n" + content + "\n" - return output - - -def main( - lexicon_ids: Annotated[ - list[str], - Argument( - ..., - help="List of lexicon identifiers to generate definitions for", - ), - ], - output: Annotated[ - str, - Option( - "--output", - "-o", - help="Output file path (default: stdout)", - ), - ], - append_schema: Annotated[ - list[str] | None, - Option( - "--append-schema", - "-a", - help="Additional GraphQL schema files or folders to append. Can be used multiple times.", - ), - ] = None, -) -> None: - """Generate GraphQL schema from lexicon_ids and source files.""" - - output_content: str = "" - - # Append additional schemas if provided via --append-schema - if append_schema: - additional_schemas = read_schema_files(append_schema) - output_content += additional_schemas - - # Append the new schema. - output_content += "\n\n".join(generate_definitions(lexicon_ids)) - - # Write to output file - if output: - output_path: str = output - with open(output_path, "w") as f: - _ = f.write(output_content) - else: - print(output) - - -if __name__ == "__main__": - run(main) diff --git a/server/.env.example b/server/.env.example deleted file mode 100644 index 77d2c9c..0000000 --- a/server/.env.example +++ /dev/null @@ -1,14 +0,0 @@ -# GraphQL Server Configuration -# Copy this file to .env and modify as needed - -# Server host (default: 0.0.0.0 for all interfaces) -HOST=0.0.0.0 - -# Server port (default: 8080) -PORT=8080 - -# Database connection string (if using database) -# DATABASE_URL=postgres://user:password@localhost:5432/mothball - -# Logging level (debug, info, warn, error) -# RUST_LOG=info diff --git a/server/.gitmodules b/server/.gitmodules deleted file mode 100644 index 9f56173..0000000 --- a/server/.gitmodules +++ /dev/null @@ -1,3 +0,0 @@ -[submodule "deps/atproto"] - path = deps/atproto - url = https://github.com/bluesky-social/atproto.git diff --git a/server/.rules b/server/.rules deleted file mode 100644 index a09e354..0000000 --- a/server/.rules +++ /dev/null @@ -1,6 +0,0 @@ -# Mothball (Backend) - -This repo is for Mothball, an app for selling items locally. - -- The repo is written in Rust. -- The primary frameworks are `axum` for powering the web server, `juniper` for powering the GraphQL engine. diff --git a/server/Cargo.lock b/server/Cargo.lock deleted file mode 100644 index ad89bfa..0000000 --- a/server/Cargo.lock +++ /dev/null @@ -1,1486 +0,0 @@ -# This file is automatically @generated by Cargo. -# It is not intended for manual editing. -version = 4 - -[[package]] -name = "android_system_properties" -version = "0.1.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "819e7219dbd41043ac279b19830f2efc897156490d7fd6ea916720117ee66311" -dependencies = [ - "libc", -] - -[[package]] -name = "arcstr" -version = "1.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "03918c3dbd7701a85c6b9887732e2921175f26c350b4563841d0958c21d57e6d" - -[[package]] -name = "async-trait" -version = "0.1.89" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9035ad2d096bed7955a320ee7e2230574d28fd3c3a0f186cbea1ff3c7eed5dbb" -dependencies = [ - "proc-macro2", - "quote", - "syn", -] - -[[package]] -name = "atomic-waker" -version = "1.1.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1505bd5d3d116872e7271a6d4e16d81d0c8570876c8de68093a09ac269d8aac0" - -[[package]] -name = "auto_enums" -version = "0.8.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9c170965892137a3a9aeb000b4524aa3cc022a310e709d848b6e1cdce4ab4781" -dependencies = [ - "derive_utils", - "proc-macro2", - "quote", - "syn", -] - -[[package]] -name = "autocfg" -version = "1.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c08606f8c3cbf4ce6ec8e28fb0014a2c086708fe954eaa885384a6165172e7e8" - -[[package]] -name = "axum" -version = "0.8.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5b098575ebe77cb6d14fc7f32749631a6e44edbef6b796f89b020e99ba20d425" -dependencies = [ - "axum-core", - "bytes", - "form_urlencoded", - "futures-util", - "http", - "http-body", - "http-body-util", - "hyper", - "hyper-util", - "itoa", - "matchit", - "memchr", - "mime", - "percent-encoding", - "pin-project-lite", - "serde_core", - "serde_json", - "serde_path_to_error", - "serde_urlencoded", - "sync_wrapper", - "tokio", - "tower", - "tower-layer", - "tower-service", - "tracing", -] - -[[package]] -name = "axum-core" -version = "0.5.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "59446ce19cd142f8833f856eb31f3eb097812d1479ab224f54d72428ca21ea22" -dependencies = [ - "bytes", - "futures-core", - "http", - "http-body", - "http-body-util", - "mime", - "pin-project-lite", - "sync_wrapper", - "tower-layer", - "tower-service", - "tracing", -] - -[[package]] -name = "bitflags" -version = "2.10.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "812e12b5285cc515a9c72a5c1d3b6d46a19dac5acfef5265968c166106e31dd3" - -[[package]] -name = "bumpalo" -version = "3.19.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5dd9dc738b7a8311c7ade152424974d8115f2cdad61e8dab8dac9f2362298510" - -[[package]] -name = "bytes" -version = "1.11.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b35204fbdc0b3f4446b89fc1ac2cf84a8a68971995d0bf2e925ec7cd960f9cb3" - -[[package]] -name = "castaway" -version = "0.2.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dec551ab6e7578819132c713a93c022a05d60159dc86e7a7050223577484c55a" -dependencies = [ - "rustversion", -] - -[[package]] -name = "cc" -version = "1.2.49" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "90583009037521a116abf44494efecd645ba48b6622457080f080b85544e2215" -dependencies = [ - "find-msvc-tools", - "shlex", -] - -[[package]] -name = "cfg-if" -version = "1.0.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9330f8b2ff13f34540b44e946ef35111825727b38d33286ef986142615121801" - -[[package]] -name = "chrono" -version = "0.4.42" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "145052bdd345b87320e369255277e3fb5152762ad123a901ef5c262dd38fe8d2" -dependencies = [ - "iana-time-zone", - "js-sys", - "num-traits", - "wasm-bindgen", - "windows-link", -] - -[[package]] -name = "compact_str" -version = "0.9.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3fdb1325a1cece981e8a296ab8f0f9b63ae357bd0784a9faaf548cc7b480707a" -dependencies = [ - "castaway", - "cfg-if", - "itoa", - "rustversion", - "ryu", - "static_assertions", -] - -[[package]] -name = "convert_case" -version = "0.10.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "633458d4ef8c78b72454de2d54fd6ab2e60f9e02be22f3c6104cdc8a4e0fceb9" -dependencies = [ - "unicode-segmentation", -] - -[[package]] -name = "core-foundation-sys" -version = "0.8.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "773648b94d0e5d620f64f280777445740e61fe701025087ec8b57f45c791888b" - -[[package]] -name = "derive_more" -version = "2.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "10b768e943bed7bf2cab53df09f4bc34bfd217cdb57d971e769874c9a6710618" -dependencies = [ - "derive_more-impl", -] - -[[package]] -name = "derive_more-impl" -version = "2.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6d286bfdaf75e988b4a78e013ecd79c581e06399ab53fbacd2d916c2f904f30b" -dependencies = [ - "convert_case", - "proc-macro2", - "quote", - "rustc_version", - "syn", - "unicode-xid", -] - -[[package]] -name = "derive_utils" -version = "0.15.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ccfae181bab5ab6c5478b2ccb69e4c68a02f8c3ec72f6616bfec9dbc599d2ee0" -dependencies = [ - "proc-macro2", - "quote", - "syn", -] - -[[package]] -name = "displaydoc" -version = "0.2.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "97369cbbc041bc366949bc74d34658d6cda5621039731c6310521892a3a20ae0" -dependencies = [ - "proc-macro2", - "quote", - "syn", -] - -[[package]] -name = "dotenv" -version = "0.15.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "77c90badedccf4105eca100756a0b1289e191f6fcbdadd3cee1d2f614f97da8f" - -[[package]] -name = "either" -version = "1.15.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "48c757948c5ede0e46177b7add2e67155f70e33c07fea8284df6576da70b3719" - -[[package]] -name = "equivalent" -version = "1.0.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "877a4ace8713b0bcf2a4e7eec82529c029f1d0619886d18145fea96c3ffe5c0f" - -[[package]] -name = "find-msvc-tools" -version = "0.1.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3a3076410a55c90011c298b04d0cfa770b00fa04e1e3c97d3f6c9de105a03844" - -[[package]] -name = "fnv" -version = "1.0.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1" - -[[package]] -name = "form_urlencoded" -version = "1.2.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cb4cb245038516f5f85277875cdaa4f7d2c9a0fa0468de06ed190163b1581fcf" -dependencies = [ - "percent-encoding", -] - -[[package]] -name = "futures" -version = "0.3.31" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "65bc07b1a8bc7c85c5f2e110c476c7389b4554ba72af57d8445ea63a576b0876" -dependencies = [ - "futures-channel", - "futures-core", - "futures-executor", - "futures-io", - "futures-sink", - "futures-task", - "futures-util", -] - -[[package]] -name = "futures-channel" -version = "0.3.31" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2dff15bf788c671c1934e366d07e30c1814a8ef514e1af724a602e8a2fbe1b10" -dependencies = [ - "futures-core", - "futures-sink", -] - -[[package]] -name = "futures-core" -version = "0.3.31" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "05f29059c0c2090612e8d742178b0580d2dc940c837851ad723096f87af6663e" - -[[package]] -name = "futures-executor" -version = "0.3.31" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1e28d1d997f585e54aebc3f97d39e72338912123a67330d723fdbb564d646c9f" -dependencies = [ - "futures-core", - "futures-task", - "futures-util", -] - -[[package]] -name = "futures-io" -version = "0.3.31" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9e5c1b78ca4aae1ac06c48a526a655760685149f0d465d21f37abfe57ce075c6" - -[[package]] -name = "futures-macro" -version = "0.3.31" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "162ee34ebcb7c64a8abebc059ce0fee27c2262618d7b60ed8faf72fef13c3650" -dependencies = [ - "proc-macro2", - "quote", - "syn", -] - -[[package]] -name = "futures-sink" -version = "0.3.31" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e575fab7d1e0dcb8d0c7bcf9a63ee213816ab51902e6d244a95819acacf1d4f7" - -[[package]] -name = "futures-task" -version = "0.3.31" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f90f7dce0722e95104fcb095585910c0977252f286e354b5e3bd38902cd99988" - -[[package]] -name = "futures-util" -version = "0.3.31" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9fa08315bb612088cc391249efdc3bc77536f16c91f6cf495e6fbe85b20a4a81" -dependencies = [ - "futures-channel", - "futures-core", - "futures-io", - "futures-macro", - "futures-sink", - "futures-task", - "memchr", - "pin-project-lite", - "pin-utils", - "slab", -] - -[[package]] -name = "getrandom" -version = "0.3.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "899def5c37c4fd7b2664648c28120ecec138e4d395b459e5ca34f9cce2dd77fd" -dependencies = [ - "cfg-if", - "libc", - "r-efi", - "wasip2", -] - -[[package]] -name = "hashbrown" -version = "0.16.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "841d1cc9bed7f9236f321df977030373f4a4163ae1a7dbfe1a51a2c1a51d9100" - -[[package]] -name = "http" -version = "1.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e3ba2a386d7f85a81f119ad7498ebe444d2e22c2af0b86b069416ace48b3311a" -dependencies = [ - "bytes", - "itoa", -] - -[[package]] -name = "http-body" -version = "1.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1efedce1fb8e6913f23e0c92de8e62cd5b772a67e7b3946df930a62566c93184" -dependencies = [ - "bytes", - "http", -] - -[[package]] -name = "http-body-util" -version = "0.1.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b021d93e26becf5dc7e1b75b1bed1fd93124b374ceb73f43d4d4eafec896a64a" -dependencies = [ - "bytes", - "futures-core", - "http", - "http-body", - "pin-project-lite", -] - -[[package]] -name = "httparse" -version = "1.10.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6dbf3de79e51f3d586ab4cb9d5c3e2c14aa28ed23d180cf89b4df0454a69cc87" - -[[package]] -name = "httpdate" -version = "1.0.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "df3b46402a9d5adb4c86a0cf463f42e19994e3ee891101b1841f30a545cb49a9" - -[[package]] -name = "hyper" -version = "1.8.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2ab2d4f250c3d7b1c9fcdff1cece94ea4e2dfbec68614f7b87cb205f24ca9d11" -dependencies = [ - "atomic-waker", - "bytes", - "futures-channel", - "futures-core", - "http", - "http-body", - "httparse", - "httpdate", - "itoa", - "pin-project-lite", - "pin-utils", - "smallvec", - "tokio", -] - -[[package]] -name = "hyper-util" -version = "0.1.19" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "727805d60e7938b76b826a6ef209eb70eaa1812794f9424d4a4e2d740662df5f" -dependencies = [ - "bytes", - "futures-core", - "http", - "http-body", - "hyper", - "pin-project-lite", - "tokio", - "tower-service", -] - -[[package]] -name = "iana-time-zone" -version = "0.1.64" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "33e57f83510bb73707521ebaffa789ec8caf86f9657cad665b092b581d40e9fb" -dependencies = [ - "android_system_properties", - "core-foundation-sys", - "iana-time-zone-haiku", - "js-sys", - "log", - "wasm-bindgen", - "windows-core", -] - -[[package]] -name = "iana-time-zone-haiku" -version = "0.1.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f31827a206f56af32e590ba56d5d2d085f558508192593743f16b2306495269f" -dependencies = [ - "cc", -] - -[[package]] -name = "icu_collections" -version = "2.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4c6b649701667bbe825c3b7e6388cb521c23d88644678e83c0c4d0a621a34b43" -dependencies = [ - "displaydoc", - "potential_utf", - "yoke", - "zerofrom", - "zerovec", -] - -[[package]] -name = "icu_locale_core" -version = "2.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "edba7861004dd3714265b4db54a3c390e880ab658fec5f7db895fae2046b5bb6" -dependencies = [ - "displaydoc", - "litemap", - "tinystr", - "writeable", - "zerovec", -] - -[[package]] -name = "icu_normalizer" -version = "2.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5f6c8828b67bf8908d82127b2054ea1b4427ff0230ee9141c54251934ab1b599" -dependencies = [ - "icu_collections", - "icu_normalizer_data", - "icu_properties", - "icu_provider", - "smallvec", - "zerovec", -] - -[[package]] -name = "icu_normalizer_data" -version = "2.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7aedcccd01fc5fe81e6b489c15b247b8b0690feb23304303a9e560f37efc560a" - -[[package]] -name = "icu_properties" -version = "2.1.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "020bfc02fe870ec3a66d93e677ccca0562506e5872c650f893269e08615d74ec" -dependencies = [ - "icu_collections", - "icu_locale_core", - "icu_properties_data", - "icu_provider", - "zerotrie", - "zerovec", -] - -[[package]] -name = "icu_properties_data" -version = "2.1.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "616c294cf8d725c6afcd8f55abc17c56464ef6211f9ed59cccffe534129c77af" - -[[package]] -name = "icu_provider" -version = "2.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "85962cf0ce02e1e0a629cc34e7ca3e373ce20dda4c4d7294bbd0bf1fdb59e614" -dependencies = [ - "displaydoc", - "icu_locale_core", - "writeable", - "yoke", - "zerofrom", - "zerotrie", - "zerovec", -] - -[[package]] -name = "idna" -version = "1.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3b0875f23caa03898994f6ddc501886a45c7d3d62d04d2d90788d47be1b1e4de" -dependencies = [ - "idna_adapter", - "smallvec", - "utf8_iter", -] - -[[package]] -name = "idna_adapter" -version = "1.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3acae9609540aa318d1bc588455225fb2085b9ed0c4f6bd0d9d5bcd86f1a0344" -dependencies = [ - "icu_normalizer", - "icu_properties", -] - -[[package]] -name = "indexmap" -version = "2.12.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0ad4bb2b565bca0645f4d68c5c9af97fba094e9791da685bf83cb5f3ce74acf2" -dependencies = [ - "equivalent", - "hashbrown", - "serde", - "serde_core", -] - -[[package]] -name = "itertools" -version = "0.14.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2b192c782037fadd9cfa75548310488aabdbf3d2da73885b31bd0abd03351285" -dependencies = [ - "either", -] - -[[package]] -name = "itoa" -version = "1.0.15" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4a5f13b858c8d314ee3e8f639011f7ccefe71f97f96e50151fb991f267928e2c" - -[[package]] -name = "js-sys" -version = "0.3.83" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "464a3709c7f55f1f721e5389aa6ea4e3bc6aba669353300af094b29ffbdde1d8" -dependencies = [ - "once_cell", - "wasm-bindgen", -] - -[[package]] -name = "juniper" -version = "0.17.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4feeb43439e89bc0cf5d86340374c828fc2b651de4750a970d6de5a4915a0d76" -dependencies = [ - "arcstr", - "async-trait", - "auto_enums", - "compact_str", - "derive_more", - "fnv", - "futures", - "indexmap", - "itertools", - "juniper_codegen", - "ref-cast", - "serde", - "static_assertions", -] - -[[package]] -name = "juniper_axum" -version = "0.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d749d056510f6d762ceca1ae6bb53d50fd77019e5be65fe4bf2eca305a18b8ba" -dependencies = [ - "axum", - "bytes", - "juniper", - "juniper_graphql_ws", - "serde", - "serde_json", -] - -[[package]] -name = "juniper_codegen" -version = "0.17.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8634f500d6d2ec5c91c115b83e15d998d9ea05645aaa43f7afec09e660c483ba" -dependencies = [ - "derive_more", - "proc-macro2", - "quote", - "syn", - "url", -] - -[[package]] -name = "juniper_graphql_ws" -version = "0.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "02f74a1d6d28f29edd4e72db014229efef9b3c3baa5cdf64ebc76b82ee146fa5" -dependencies = [ - "derive_more", - "juniper", - "juniper_subscriptions", - "serde", - "tokio", -] - -[[package]] -name = "juniper_subscriptions" -version = "0.18.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0aeaaedf8fe890b09a712224de8bf509477194fdeb35a39c32d8ada8ac754972" -dependencies = [ - "futures", - "juniper", -] - -[[package]] -name = "libc" -version = "0.2.178" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "37c93d8daa9d8a012fd8ab92f088405fb202ea0b6ab73ee2482ae66af4f42091" - -[[package]] -name = "litemap" -version = "0.8.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6373607a59f0be73a39b6fe456b8192fcc3585f602af20751600e974dd455e77" - -[[package]] -name = "lock_api" -version = "0.4.14" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "224399e74b87b5f3557511d98dff8b14089b3dadafcab6bb93eab67d3aace965" -dependencies = [ - "scopeguard", -] - -[[package]] -name = "log" -version = "0.4.29" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5e5032e24019045c762d3c0f28f5b6b8bbf38563a65908389bf7978758920897" - -[[package]] -name = "matchit" -version = "0.8.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "47e1ffaa40ddd1f3ed91f717a33c8c0ee23fff369e3aa8772b9605cc1d22f4c3" - -[[package]] -name = "memchr" -version = "2.7.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f52b00d39961fc5b2736ea853c9cc86238e165017a493d1d5c8eac6bdc4cc273" - -[[package]] -name = "mime" -version = "0.3.17" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6877bb514081ee2a7ff5ef9de3281f14a4dd4bceac4c09388074a6b5df8a139a" - -[[package]] -name = "mio" -version = "1.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a69bcab0ad47271a0234d9422b131806bf3968021e5dc9328caf2d4cd58557fc" -dependencies = [ - "libc", - "wasi", - "windows-sys 0.61.2", -] - -[[package]] -name = "mothball-server" -version = "0.1.0" -dependencies = [ - "axum", - "chrono", - "dotenv", - "juniper", - "juniper_axum", - "serde", - "serde_json", - "tokio", - "uuid", -] - -[[package]] -name = "num-traits" -version = "0.2.19" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "071dfc062690e90b734c0b2273ce72ad0ffa95f0c74596bc250dcfd960262841" -dependencies = [ - "autocfg", -] - -[[package]] -name = "once_cell" -version = "1.21.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "42f5e15c9953c5e4ccceeb2e7382a716482c34515315f7b03532b8b4e8393d2d" - -[[package]] -name = "parking_lot" -version = "0.12.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "93857453250e3077bd71ff98b6a65ea6621a19bb0f559a85248955ac12c45a1a" -dependencies = [ - "lock_api", - "parking_lot_core", -] - -[[package]] -name = "parking_lot_core" -version = "0.9.12" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2621685985a2ebf1c516881c026032ac7deafcda1a2c9b7850dc81e3dfcb64c1" -dependencies = [ - "cfg-if", - "libc", - "redox_syscall", - "smallvec", - "windows-link", -] - -[[package]] -name = "percent-encoding" -version = "2.3.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9b4f627cb1b25917193a259e49bdad08f671f8d9708acfd5fe0a8c1455d87220" - -[[package]] -name = "pin-project-lite" -version = "0.2.16" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3b3cff922bd51709b605d9ead9aa71031d81447142d828eb4a6eba76fe619f9b" - -[[package]] -name = "pin-utils" -version = "0.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184" - -[[package]] -name = "potential_utf" -version = "0.1.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b73949432f5e2a09657003c25bca5e19a0e9c84f8058ca374f49e0ebe605af77" -dependencies = [ - "zerovec", -] - -[[package]] -name = "proc-macro2" -version = "1.0.103" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5ee95bc4ef87b8d5ba32e8b7714ccc834865276eab0aed5c9958d00ec45f49e8" -dependencies = [ - "unicode-ident", -] - -[[package]] -name = "quote" -version = "1.0.42" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a338cc41d27e6cc6dce6cefc13a0729dfbb81c262b1f519331575dd80ef3067f" -dependencies = [ - "proc-macro2", -] - -[[package]] -name = "r-efi" -version = "5.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "69cdb34c158ceb288df11e18b4bd39de994f6657d83847bdffdbd7f346754b0f" - -[[package]] -name = "redox_syscall" -version = "0.5.18" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ed2bf2547551a7053d6fdfafda3f938979645c44812fbfcda098faae3f1a362d" -dependencies = [ - "bitflags", -] - -[[package]] -name = "ref-cast" -version = "1.0.25" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f354300ae66f76f1c85c5f84693f0ce81d747e2c3f21a45fef496d89c960bf7d" -dependencies = [ - "ref-cast-impl", -] - -[[package]] -name = "ref-cast-impl" -version = "1.0.25" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b7186006dcb21920990093f30e3dea63b7d6e977bf1256be20c3563a5db070da" -dependencies = [ - "proc-macro2", - "quote", - "syn", -] - -[[package]] -name = "rustc_version" -version = "0.4.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cfcb3a22ef46e85b45de6ee7e79d063319ebb6594faafcf1c225ea92ab6e9b92" -dependencies = [ - "semver", -] - -[[package]] -name = "rustversion" -version = "1.0.22" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b39cdef0fa800fc44525c84ccb54a029961a8215f9619753635a9c0d2538d46d" - -[[package]] -name = "ryu" -version = "1.0.20" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "28d3b2b1366ec20994f1fd18c3c594f05c5dd4bc44d8bb0c1c632c8d6829481f" - -[[package]] -name = "scopeguard" -version = "1.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49" - -[[package]] -name = "semver" -version = "1.0.27" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d767eb0aabc880b29956c35734170f26ed551a859dbd361d140cdbeca61ab1e2" - -[[package]] -name = "serde" -version = "1.0.228" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9a8e94ea7f378bd32cbbd37198a4a91436180c5bb472411e48b5ec2e2124ae9e" -dependencies = [ - "serde_core", - "serde_derive", -] - -[[package]] -name = "serde_core" -version = "1.0.228" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "41d385c7d4ca58e59fc732af25c3983b67ac852c1a25000afe1175de458b67ad" -dependencies = [ - "serde_derive", -] - -[[package]] -name = "serde_derive" -version = "1.0.228" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d540f220d3187173da220f885ab66608367b6574e925011a9353e4badda91d79" -dependencies = [ - "proc-macro2", - "quote", - "syn", -] - -[[package]] -name = "serde_json" -version = "1.0.145" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "402a6f66d8c709116cf22f558eab210f5a50187f702eb4d7e5ef38d9a7f1c79c" -dependencies = [ - "itoa", - "memchr", - "ryu", - "serde", - "serde_core", -] - -[[package]] -name = "serde_path_to_error" -version = "0.1.20" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "10a9ff822e371bb5403e391ecd83e182e0e77ba7f6fe0160b795797109d1b457" -dependencies = [ - "itoa", - "serde", - "serde_core", -] - -[[package]] -name = "serde_urlencoded" -version = "0.7.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d3491c14715ca2294c4d6a88f15e84739788c1d030eed8c110436aafdaa2f3fd" -dependencies = [ - "form_urlencoded", - "itoa", - "ryu", - "serde", -] - -[[package]] -name = "shlex" -version = "1.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64" - -[[package]] -name = "signal-hook-registry" -version = "1.4.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7664a098b8e616bdfcc2dc0e9ac44eb231eedf41db4e9fe95d8d32ec728dedad" -dependencies = [ - "libc", -] - -[[package]] -name = "slab" -version = "0.4.11" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7a2ae44ef20feb57a68b23d846850f861394c2e02dc425a50098ae8c90267589" - -[[package]] -name = "smallvec" -version = "1.15.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "67b1b7a3b5fe4f1376887184045fcf45c69e92af734b7aaddc05fb777b6fbd03" - -[[package]] -name = "socket2" -version = "0.6.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "17129e116933cf371d018bb80ae557e889637989d8638274fb25622827b03881" -dependencies = [ - "libc", - "windows-sys 0.60.2", -] - -[[package]] -name = "stable_deref_trait" -version = "1.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6ce2be8dc25455e1f91df71bfa12ad37d7af1092ae736f3a6cd0e37bc7810596" - -[[package]] -name = "static_assertions" -version = "1.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a2eb9349b6444b326872e140eb1cf5e7c522154d69e7a0ffb0fb81c06b37543f" - -[[package]] -name = "syn" -version = "2.0.111" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "390cc9a294ab71bdb1aa2e99d13be9c753cd2d7bd6560c77118597410c4d2e87" -dependencies = [ - "proc-macro2", - "quote", - "unicode-ident", -] - -[[package]] -name = "sync_wrapper" -version = "1.0.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0bf256ce5efdfa370213c1dabab5935a12e49f2c58d15e9eac2870d3b4f27263" - -[[package]] -name = "synstructure" -version = "0.13.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "728a70f3dbaf5bab7f0c4b1ac8d7ae5ea60a4b5549c8a5914361c99147a709d2" -dependencies = [ - "proc-macro2", - "quote", - "syn", -] - -[[package]] -name = "tinystr" -version = "0.8.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "42d3e9c45c09de15d06dd8acf5f4e0e399e85927b7f00711024eb7ae10fa4869" -dependencies = [ - "displaydoc", - "zerovec", -] - -[[package]] -name = "tokio" -version = "1.48.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ff360e02eab121e0bc37a2d3b4d4dc622e6eda3a8e5253d5435ecf5bd4c68408" -dependencies = [ - "bytes", - "libc", - "mio", - "parking_lot", - "pin-project-lite", - "signal-hook-registry", - "socket2", - "tokio-macros", - "windows-sys 0.61.2", -] - -[[package]] -name = "tokio-macros" -version = "2.6.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "af407857209536a95c8e56f8231ef2c2e2aff839b22e07a1ffcbc617e9db9fa5" -dependencies = [ - "proc-macro2", - "quote", - "syn", -] - -[[package]] -name = "tower" -version = "0.5.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d039ad9159c98b70ecfd540b2573b97f7f52c3e8d9f8ad57a24b916a536975f9" -dependencies = [ - "futures-core", - "futures-util", - "pin-project-lite", - "sync_wrapper", - "tokio", - "tower-layer", - "tower-service", - "tracing", -] - -[[package]] -name = "tower-layer" -version = "0.3.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "121c2a6cda46980bb0fcd1647ffaf6cd3fc79a013de288782836f6df9c48780e" - -[[package]] -name = "tower-service" -version = "0.3.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8df9b6e13f2d32c91b9bd719c00d1958837bc7dec474d94952798cc8e69eeec3" - -[[package]] -name = "tracing" -version = "0.1.44" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "63e71662fa4b2a2c3a26f570f037eb95bb1f85397f3cd8076caed2f026a6d100" -dependencies = [ - "log", - "pin-project-lite", - "tracing-core", -] - -[[package]] -name = "tracing-core" -version = "0.1.36" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "db97caf9d906fbde555dd62fa95ddba9eecfd14cb388e4f491a66d74cd5fb79a" -dependencies = [ - "once_cell", -] - -[[package]] -name = "unicode-ident" -version = "1.0.22" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9312f7c4f6ff9069b165498234ce8be658059c6728633667c526e27dc2cf1df5" - -[[package]] -name = "unicode-segmentation" -version = "1.12.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f6ccf251212114b54433ec949fd6a7841275f9ada20dddd2f29e9ceea4501493" - -[[package]] -name = "unicode-xid" -version = "0.2.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ebc1c04c71510c7f702b52b7c350734c9ff1295c464a03335b00bb84fc54f853" - -[[package]] -name = "url" -version = "2.5.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "08bc136a29a3d1758e07a9cca267be308aeebf5cfd5a10f3f67ab2097683ef5b" -dependencies = [ - "form_urlencoded", - "idna", - "percent-encoding", - "serde", -] - -[[package]] -name = "utf8_iter" -version = "1.0.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b6c140620e7ffbb22c2dee59cafe6084a59b5ffc27a8859a5f0d494b5d52b6be" - -[[package]] -name = "uuid" -version = "1.19.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e2e054861b4bd027cd373e18e8d8d8e6548085000e41290d95ce0c373a654b4a" -dependencies = [ - "getrandom", - "js-sys", - "wasm-bindgen", -] - -[[package]] -name = "wasi" -version = "0.11.1+wasi-snapshot-preview1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ccf3ec651a847eb01de73ccad15eb7d99f80485de043efb2f370cd654f4ea44b" - -[[package]] -name = "wasip2" -version = "1.0.1+wasi-0.2.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0562428422c63773dad2c345a1882263bbf4d65cf3f42e90921f787ef5ad58e7" -dependencies = [ - "wit-bindgen", -] - -[[package]] -name = "wasm-bindgen" -version = "0.2.106" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0d759f433fa64a2d763d1340820e46e111a7a5ab75f993d1852d70b03dbb80fd" -dependencies = [ - "cfg-if", - "once_cell", - "rustversion", - "wasm-bindgen-macro", - "wasm-bindgen-shared", -] - -[[package]] -name = "wasm-bindgen-macro" -version = "0.2.106" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "48cb0d2638f8baedbc542ed444afc0644a29166f1595371af4fecf8ce1e7eeb3" -dependencies = [ - "quote", - "wasm-bindgen-macro-support", -] - -[[package]] -name = "wasm-bindgen-macro-support" -version = "0.2.106" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cefb59d5cd5f92d9dcf80e4683949f15ca4b511f4ac0a6e14d4e1ac60c6ecd40" -dependencies = [ - "bumpalo", - "proc-macro2", - "quote", - "syn", - "wasm-bindgen-shared", -] - -[[package]] -name = "wasm-bindgen-shared" -version = "0.2.106" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cbc538057e648b67f72a982e708d485b2efa771e1ac05fec311f9f63e5800db4" -dependencies = [ - "unicode-ident", -] - -[[package]] -name = "windows-core" -version = "0.62.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b8e83a14d34d0623b51dce9581199302a221863196a1dde71a7663a4c2be9deb" -dependencies = [ - "windows-implement", - "windows-interface", - "windows-link", - "windows-result", - "windows-strings", -] - -[[package]] -name = "windows-implement" -version = "0.60.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "053e2e040ab57b9dc951b72c264860db7eb3b0200ba345b4e4c3b14f67855ddf" -dependencies = [ - "proc-macro2", - "quote", - "syn", -] - -[[package]] -name = "windows-interface" -version = "0.59.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3f316c4a2570ba26bbec722032c4099d8c8bc095efccdc15688708623367e358" -dependencies = [ - "proc-macro2", - "quote", - "syn", -] - -[[package]] -name = "windows-link" -version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f0805222e57f7521d6a62e36fa9163bc891acd422f971defe97d64e70d0a4fe5" - -[[package]] -name = "windows-result" -version = "0.4.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7781fa89eaf60850ac3d2da7af8e5242a5ea78d1a11c49bf2910bb5a73853eb5" -dependencies = [ - "windows-link", -] - -[[package]] -name = "windows-strings" -version = "0.5.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7837d08f69c77cf6b07689544538e017c1bfcf57e34b4c0ff58e6c2cd3b37091" -dependencies = [ - "windows-link", -] - -[[package]] -name = "windows-sys" -version = "0.60.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f2f500e4d28234f72040990ec9d39e3a6b950f9f22d3dba18416c35882612bcb" -dependencies = [ - "windows-targets", -] - -[[package]] -name = "windows-sys" -version = "0.61.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ae137229bcbd6cdf0f7b80a31df61766145077ddf49416a728b02cb3921ff3fc" -dependencies = [ - "windows-link", -] - -[[package]] -name = "windows-targets" -version = "0.53.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4945f9f551b88e0d65f3db0bc25c33b8acea4d9e41163edf90dcd0b19f9069f3" -dependencies = [ - "windows-link", - "windows_aarch64_gnullvm", - "windows_aarch64_msvc", - "windows_i686_gnu", - "windows_i686_gnullvm", - "windows_i686_msvc", - "windows_x86_64_gnu", - "windows_x86_64_gnullvm", - "windows_x86_64_msvc", -] - -[[package]] -name = "windows_aarch64_gnullvm" -version = "0.53.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a9d8416fa8b42f5c947f8482c43e7d89e73a173cead56d044f6a56104a6d1b53" - -[[package]] -name = "windows_aarch64_msvc" -version = "0.53.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b9d782e804c2f632e395708e99a94275910eb9100b2114651e04744e9b125006" - -[[package]] -name = "windows_i686_gnu" -version = "0.53.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "960e6da069d81e09becb0ca57a65220ddff016ff2d6af6a223cf372a506593a3" - -[[package]] -name = "windows_i686_gnullvm" -version = "0.53.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fa7359d10048f68ab8b09fa71c3daccfb0e9b559aed648a8f95469c27057180c" - -[[package]] -name = "windows_i686_msvc" -version = "0.53.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1e7ac75179f18232fe9c285163565a57ef8d3c89254a30685b57d83a38d326c2" - -[[package]] -name = "windows_x86_64_gnu" -version = "0.53.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9c3842cdd74a865a8066ab39c8a7a473c0778a3f29370b5fd6b4b9aa7df4a499" - -[[package]] -name = "windows_x86_64_gnullvm" -version = "0.53.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0ffa179e2d07eee8ad8f57493436566c7cc30ac536a3379fdf008f47f6bb7ae1" - -[[package]] -name = "windows_x86_64_msvc" -version = "0.53.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d6bbff5f0aada427a1e5a6da5f1f98158182f26556f345ac9e04d36d0ebed650" - -[[package]] -name = "wit-bindgen" -version = "0.46.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f17a85883d4e6d00e8a97c586de764dabcc06133f7f1d55dce5cdc070ad7fe59" - -[[package]] -name = "writeable" -version = "0.6.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9edde0db4769d2dc68579893f2306b26c6ecfbe0ef499b013d731b7b9247e0b9" - -[[package]] -name = "yoke" -version = "0.8.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "72d6e5c6afb84d73944e5cedb052c4680d5657337201555f9f2a16b7406d4954" -dependencies = [ - "stable_deref_trait", - "yoke-derive", - "zerofrom", -] - -[[package]] -name = "yoke-derive" -version = "0.8.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b659052874eb698efe5b9e8cf382204678a0086ebf46982b79d6ca3182927e5d" -dependencies = [ - "proc-macro2", - "quote", - "syn", - "synstructure", -] - -[[package]] -name = "zerofrom" -version = "0.1.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "50cc42e0333e05660c3587f3bf9d0478688e15d870fab3346451ce7f8c9fbea5" -dependencies = [ - "zerofrom-derive", -] - -[[package]] -name = "zerofrom-derive" -version = "0.1.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d71e5d6e06ab090c67b5e44993ec16b72dcbaabc526db883a360057678b48502" -dependencies = [ - "proc-macro2", - "quote", - "syn", - "synstructure", -] - -[[package]] -name = "zerotrie" -version = "0.2.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2a59c17a5562d507e4b54960e8569ebee33bee890c70aa3fe7b97e85a9fd7851" -dependencies = [ - "displaydoc", - "yoke", - "zerofrom", -] - -[[package]] -name = "zerovec" -version = "0.11.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6c28719294829477f525be0186d13efa9a3c602f7ec202ca9e353d310fb9a002" -dependencies = [ - "yoke", - "zerofrom", - "zerovec-derive", -] - -[[package]] -name = "zerovec-derive" -version = "0.11.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eadce39539ca5cb3985590102671f2567e659fca9666581ad3411d59207951f3" -dependencies = [ - "proc-macro2", - "quote", - "syn", -] diff --git a/server/Cargo.toml b/server/Cargo.toml deleted file mode 100644 index 5f70a0d..0000000 --- a/server/Cargo.toml +++ /dev/null @@ -1,15 +0,0 @@ -[package] -name = "mothball-server" -version = "0.1.0" -edition = "2021" - -[dependencies] -axum = "0.8" -juniper = "0.17" -juniper_axum = "0.3" -serde = { version = "1.0", features = ["derive"] } -serde_json = "1.0" -tokio = { version = "1.0", features = ["full"] } -dotenv = "0.15" -chrono = "0.4" -uuid = { version = "1.0", features = ["v4"] } diff --git a/server/Dockerfile b/server/Dockerfile deleted file mode 100644 index a76ae2c..0000000 --- a/server/Dockerfile +++ /dev/null @@ -1,35 +0,0 @@ -# Dockerfile for Mothball GraphQL Server -# Multi-stage build to keep the final image small - -# Stage 1: Build the Rust application -FROM rust:1.60-slim as builder - -WORKDIR /app - -# Copy the entire project -COPY . . - -# Build the application in release mode -RUN cargo build --release - -# Stage 2: Create the final lightweight image -FROM debian:bullseye-slim - -# Install only the essential dependencies -RUN apt-get update && \ - apt-get install -y ca-certificates && \ - rm -rf /var/lib/apt/lists/* - -WORKDIR /app - -# Copy the compiled binary from the builder stage -COPY --from=builder /app/target/release/mothball-server . - -# Copy environment variables and static files -COPY .env . - -# Expose the port the app runs on -EXPOSE 8080 - -# Command to run the application -CMD ["./mothball-server"] diff --git a/server/fly.toml b/server/fly.toml deleted file mode 100644 index 697a1f5..0000000 --- a/server/fly.toml +++ /dev/null @@ -1,23 +0,0 @@ -# fly.toml app configuration -# See https://fly.io/docs/reference/configuration/ for information about how to use this file. - -app = "mothball-server" -primary_region = "iad" - -[build] - dockerfile = "Dockerfile" - -[env] - PRIMARY_REGION = "iad" - -[http_service] - internal_port = 8080 - force_https = true - auto_stop_machines = true - auto_start_machines = true - min_machines_running = 1 - -[[vm]] - cpu_kind = "shared" - cpus = 1 - memory_mb = 1024 diff --git a/server/graphql/useInventoryQuery.json b/server/graphql/useInventoryQuery.json deleted file mode 100644 index 35932e0..0000000 --- a/server/graphql/useInventoryQuery.json +++ /dev/null @@ -1,58 +0,0 @@ -{ - "data": { - "inventory": [ - { - "id": "ikea-desk", - "title": "Large IKEA Desk - Spacious Workspace", - "cost": "20.00", - "images": [ - "https://www.ikea.com/us/en/images/products/linnmon-adils-desk-black-brown__0974302_pe812345_s5.jpg?f=xl" - ], - "description": "Specifications:\n\n- Dimensions: 79\" long tabletop\n- Color: Black-brown\n- Model: LINNMON with ADILS legs\n- Condition: Used, good overall state\n\nThis versatile desk has been a reliable workspace for multiple years. Ideal for various activities including:\n\n- Computer setup\n- Crafting\n- Project work\n- Organizational tasks\n\nSlight cosmetic wear, minor surface imperfections.\n\nPricing:\n\n- Retail replacement cost: Approximately $100\n- Selling price: $30\n\nFlexible payment options available.", - "location": "Portland, OR", - "condition": "Used - Good", - "category": "Furniture", - "posted_at": "2024-01-15" - }, - { - "id": "orbi-router", - "title": "Orbi Router", - "cost": "0", - "images": ["https://www.netgear.com/support/cloudimage/1/11/123573"], - "description": "This is an orbi wireless router. Normally it comes with satellites but\nthis one does not.", - "location": "Portland, OR", - "condition": "Used - Good", - "category": "Electronics", - "posted_at": "2024-01-18" - }, - { - "id": "arris-router", - "title": "Arris Router", - "cost": "10.00", - "images": [ - "https://m.media-amazon.com/images/I/71gmmM9G8CL._AC_SY879_.jpg" - ], - "description": "This is an Arris SURFBoard router.", - "location": "Portland, OR", - "condition": "Used - Good", - "category": "Electronics", - "posted_at": "2024-01-20" - }, - { - "id": "dell-soundbar", - "title": "Dell Stereo SoundBar - AC511M", - "cost": "10.00", - "images": [ - "https://m.media-amazon.com/images/I/71MiidZgcfL._AC_SX679_.jpg", - "https://m.media-amazon.com/images/I/71VKkGixWWL._AC_SX679_.jpg" - ], - "description": "- Until you hear it you'll hardly notice it's there Dell Stereo Soundbar can give you the sound you want without big speakers and Long cables.Total usb ports:1\n- USB powered the Dell Stereo Soundbar is simplicity itself Just Plug in to an available USB port on your monitor or laptop No extra software Installation No power cord No Batteries required\n- An included Soundbar mount offers Easy attachment to the monitor allowing you to enjoy clear Stereo sound without losing desk space", - "location": "Portland, OR", - "condition": "Used - Good", - "category": "Electronics", - "posted_at": "2024-01-22" - } - ] - }, - "errors": [] -} diff --git a/server/graphql/useMessagesQuery.json b/server/graphql/useMessagesQuery.json deleted file mode 100644 index 3365fbd..0000000 --- a/server/graphql/useMessagesQuery.json +++ /dev/null @@ -1,167 +0,0 @@ -{ - "data": { - "chats": [ - { - "id": "chat:1", - "sender": "John Doe", - "avatar": "JD", - "unread": true, - "messages": [ - { - "id": "chat:1:1", - "sender": "them", - "text": "Hi, I'm interested in your vintage lamp. Is it still available?", - "time": "2:30 PM" - }, - { - "id": "chat:1:2", - "sender": "me", - "text": "Yes, the vintage lamp is still available. Would you like more details about it?", - "time": "2:31 PM" - }, - { - "id": "chat:1:3", - "sender": "them", - "text": "Absolutely! How old is it and what's the condition?", - "time": "2:35 PM" - }, - { - "id": "chat:1:4", - "sender": "me", - "text": "The lamp is from the 1960s and in excellent condition. The base has a small chip but the shade is perfect.", - "time": "2:38 PM" - } - ] - }, - { - "id": "chat:2", - "sender": "Sarah Johnson", - "avatar": "SJ", - "unread": true, - "messages": [ - { - "id": "chat:2:1", - "sender": "them", - "text": "Can we negotiate the price on your records collection?", - "time": "1:15 PM" - }, - { - "id": "chat:2:2", - "sender": "me", - "text": "Of course! What price were you thinking?", - "time": "1:17 PM" - }, - { - "id": "chat:2:3", - "sender": "them", - "text": "I was thinking around $150 for the whole collection. Is that doable?", - "time": "1:20 PM" - }, - { - "id": "chat:2:4", - "sender": "me", - "text": "I could do $175, but that's my final offer. The records are in near mint condition.", - "time": "1:22 PM" - } - ] - }, - { - "id": "chat:3", - "sender": "Michael Brown", - "avatar": "MB", - "unread": false, - "messages": [ - { - "id": "chat:3:1", - "sender": "them", - "text": "Thanks for the vintage camera! Can we arrange pickup tomorrow?", - "time": "Yesterday" - }, - { - "id": "chat:3:2", - "sender": "me", - "text": "That sounds great! Would 2 PM work for you?", - "time": "Yesterday" - }, - { - "id": "chat:3:3", - "sender": "them", - "text": "Yes, 2 PM is perfect. What's your address?", - "time": "Yesterday" - }, - { - "id": "chat:3:4", - "sender": "me", - "text": "I'm at 123 Main Street, Apt 4B. Just ring the buzzer for Brown.", - "time": "Yesterday" - } - ] - }, - { - "id": "chat:4", - "sender": "Alex Wilson", - "avatar": "AW", - "unread": false, - "messages": [ - { - "id": "chat:4:1", - "sender": "them", - "text": "I'm looking for similar items like your sound system.", - "time": "Monday" - }, - { - "id": "chat:4:2", - "sender": "me", - "text": "What specifically are you looking for? I might know where to find similar items.", - "time": "Monday" - }, - { - "id": "chat:4:3", - "sender": "them", - "text": "Vinyl record players and mid-century modern speakers.", - "time": "Monday" - }, - { - "id": "chat:4:4", - "sender": "me", - "text": "I know a great shop downtown that specializes in exactly that. Want me to text you the address?", - "time": "Monday" - } - ] - }, - { - "id": "chat:5", - "sender": "Emily Davis", - "avatar": "ED", - "unread": false, - "messages": [ - { - "id": "chat:5:1", - "sender": "them", - "text": "Can you provide more details about your furniture pieces?", - "time": "Last week" - }, - { - "id": "chat:5:2", - "sender": "me", - "text": "Sure! The dining table is solid oak with a glass top, and the chairs are original mid-century design.", - "time": "Last week" - }, - { - "id": "chat:5:3", - "sender": "them", - "text": "Are the chairs comfortable? I have back problems so seating is important to me.", - "time": "Last week" - }, - { - "id": "chat:5:4", - "sender": "me", - "text": "Yes, they're very comfortable! The cushions are original and still in great shape. I can send you photos if you'd like.", - "time": "Last week" - } - ] - } - ] - }, - "errors": [] -} diff --git a/server/graphql/useProfileQuery.json b/server/graphql/useProfileQuery.json deleted file mode 100644 index 33aa987..0000000 --- a/server/graphql/useProfileQuery.json +++ /dev/null @@ -1,7 +0,0 @@ -{ - "data": { - }, - "errors": [ - {"description":"This query should not make it to the server!"} - ] -} diff --git a/server/src/main.rs b/server/src/main.rs deleted file mode 100644 index 0498792..0000000 --- a/server/src/main.rs +++ /dev/null @@ -1,206 +0,0 @@ -use axum::{ - response::Html, - routing::{get, on, MethodFilter}, - Extension, Router, -}; -use dotenv::dotenv; -use juniper::{graphql_object, EmptyMutation, EmptySubscription, RootNode}; -use juniper_axum::{graphiql, graphql}; -use serde::Deserialize; -use std::env; -use std::net::SocketAddr; -use std::sync::Arc; -use uuid::Uuid; - -// Define our GraphQL schema types -#[derive(juniper::GraphQLObject, Deserialize, Debug)] -struct Me { - id: String, -} - -#[derive(juniper::GraphQLObject, Deserialize, Debug)] -struct ProfileViewDetailed { - id: String, - did: String, - handle: String, - display_name: Option, - description: Option, - pronouns: Option, - website: Option, - avatar: Option, - banner: Option, - followers_count: Option, - follows_count: Option, - posts_count: Option, -} - -#[derive(juniper::GraphQLObject, Deserialize, Debug)] -struct InventoryItem { - id: String, - title: String, - cost: String, - images: Vec, - description: String, - location: Option, - condition: Option, - category: Option, - posted_at: String, -} - -#[derive(juniper::GraphQLEnum, Deserialize, Debug)] -enum Sender { - #[graphql(name = "them")] - #[serde(alias = "them")] - Them, - - #[graphql(name = "me")] - #[serde(alias = "me")] - Me, -} - -#[derive(juniper::GraphQLObject, Deserialize, Debug)] -struct Message { - id: String, - sender: Sender, - text: String, - time: String, -} - -#[derive(juniper::GraphQLObject, Deserialize, Debug)] -struct Chat { - id: String, - unread: bool, - sender: String, - avatar: Option, - messages: Vec, -} - -/** - * Inventory Placeholder Query - */ - -const USE_INVENTORY_QUERY: &'static str = include_str!("../graphql/useInventoryQuery.json"); - -#[derive(Deserialize, Debug)] -pub struct InventoryQueryRoot { - inventory: Vec, -} - -#[derive(Deserialize, Debug)] -pub struct InventoryQuery { - data: InventoryQueryRoot, -} - -/** - * Chat Placeholder Query - */ - -const USE_CHAT_QUERY: &'static str = include_str!("../graphql/useMessagesQuery.json"); - -#[derive(Deserialize, Debug)] -pub struct ChatQueryRoot { - chats: Vec, -} - -#[derive(Deserialize, Debug)] -pub struct ChatQuery { - data: ChatQueryRoot, -} - -/** - * Schema root - */ - -// Define our GraphQL schema queries -#[derive(Clone, Copy, Debug)] -pub struct Query; - -#[graphql_object] -impl Query { - async fn me(&self) -> Option { - Some(Me { - id: Uuid::new_v4().to_string(), - }) - } - - async fn profile_view_detailed(&self) -> Option { - Some(ProfileViewDetailed { - id: Uuid::new_v4().to_string(), - did: "did:example:123456789abcdefghi".to_string(), - handle: "testuser".to_string(), - display_name: Some("Test User".to_string()), - description: Some("Hello, I'm a test user!".to_string()), - pronouns: Some("they/them".to_string()), - website: Some("https://example.com".to_string()), - avatar: Some("https://example.com/avatar.jpg".to_string()), - banner: Some("https://example.com/banner.jpg".to_string()), - followers_count: Some(42), - follows_count: Some(15), - posts_count: Some(7), - }) - } - - async fn inventory(&self) -> Vec { - let a = serde_json::from_str(USE_INVENTORY_QUERY) - .map(|q: InventoryQuery| q.data.inventory) - .unwrap_or(vec![]); - dbg!(&serde_json::from_str::(USE_INVENTORY_QUERY).err()); - return a; - } - - async fn chats(&self) -> Vec { - let a = serde_json::from_str(USE_CHAT_QUERY) - .map(|q: ChatQuery| q.data.chats) - .unwrap_or(vec![]); - dbg!(&serde_json::from_str::(USE_CHAT_QUERY).err()); - return a; - } -} - -pub type Schema = RootNode; - -async fn homepage() -> Html { - Html( - "

Mothball GraphQL API

\ -
Visit GraphiQL for the web-based IDE
\ -
Access the API directly at /graphql
\ - " - .to_string(), - ) -} - -#[tokio::main] -async fn main() { - dotenv().ok(); - - // Load environment variables - let host = env::var("HOST").unwrap_or_else(|_| "0.0.0.0".to_string()); - let port = env::var("PORT").unwrap_or_else(|_| "8080".to_string()); - - println!("Starting Mothball GraphQL server on {}:{}", host, port); - - let schema = Schema::new(Query, EmptyMutation::new(), EmptySubscription::new()); - - let app = Router::new() - .route( - "/graphql", - on( - MethodFilter::GET.or(MethodFilter::POST), - graphql::>, - ), - ) - .route("/graphiql", get(graphiql("/graphql", "/subscriptions"))) - .route("/", get(homepage)) - .layer(Extension(Arc::new(schema))); - - let addr = format!("{}:{}", host, port) - .parse::() - .expect("Invalid socket address"); - - let listener = tokio::net::TcpListener::bind(addr) - .await - .unwrap_or_else(|e| panic!("failed to listen on {addr}: {e}")); - axum::serve(listener, app) - .await - .unwrap_or_else(|e| panic!("failed to run `axum::serve`: {e}")); -} diff --git a/js/src/generateLexiconSchema.ts b/src/generateLexiconSchema.ts similarity index 100% rename from js/src/generateLexiconSchema.ts rename to src/generateLexiconSchema.ts diff --git a/js/src/server/server.js b/src/server/server.js similarity index 100% rename from js/src/server/server.js rename to src/server/server.js diff --git a/tests/conftest.py b/tests/conftest.py deleted file mode 100644 index 75d276a..0000000 --- a/tests/conftest.py +++ /dev/null @@ -1,13 +0,0 @@ -"""Test configuration and fixtures for the schema generation tests.""" - -import os -import sys -from pathlib import Path - -# Add the project root to the Python path so we can import modules -sys.path.insert(0, str(Path(__file__).parent.parent)) - - -def pytest_configure(config): - """Add custom markers if needed.""" - pass diff --git a/tests/test_schema_generation.py b/tests/test_schema_generation.py deleted file mode 100644 index 15d53d5..0000000 --- a/tests/test_schema_generation.py +++ /dev/null @@ -1,115 +0,0 @@ -"""Test for schema generation consistency.""" - -import os -import tempfile -from pathlib import Path -from typing import List - -from schema.generate_lexicon_schema import generate_definitions, main - -# Constant for the expected output file -EXPECTED_OUTPUT_FILE = "schema/schema-generated.graphql" - - -def test_schema_generation_consistency(): - """ - Test that running the generate_lexicon_schema.py script produces consistent output. - This test ensures that the generated schema doesn't change unexpectedly. - """ - # Expected lexicon IDs from the command line - lexicon_ids = ["app.bsky.actor.getProfile", "com.atproto.server.getSession"] - - # Generate the expected output using the function directly - generated_content = "\n\n".join(generate_definitions(lexicon_ids)) - - # Read the expected file if it exists - expected_file_path = Path(EXPECTED_OUTPUT_FILE) - if expected_file_path.exists(): - with open(expected_file_path, "r") as f: - expected_content = f.read() - - # Compare the generated content with the expected content - assert generated_content == expected_content, ( - "Generated schema content does not match the expected file. " - "This could mean the schema has changed or the test needs to be updated." - ) - - else: - # If the expected file doesn't exist, create it with the current output - with open(expected_file_path, "w") as f: - f.write(generated_content) - print(f"Created new expected output file: {expected_file_path}") - - -def test_main_function_output(): - """ - Test the main function by running it with the specified lexicon IDs - and verifying the output is consistent. - """ - # Expected lexicon IDs from the command line - lexicon_ids = ["app.bsky.actor.getProfile", "com.atproto.server.getSession"] - - # Create a temporary file for testing - with tempfile.NamedTemporaryFile( - mode="w", suffix=".graphql", delete=False - ) as tmp_file: - tmp_path = tmp_file.name - - try: - # Run the main function with the lexicon IDs and output to temp file - main(lexicon_ids=lexicon_ids, output=tmp_path, append_schema=None) - - # Read the generated content - with open(tmp_path, "r") as f: - generated_content = f.read() - - # Read the expected file if it exists - expected_file_path = Path(EXPECTED_OUTPUT_FILE) - if expected_file_path.exists(): - with open(expected_file_path, "r") as f: - expected_content = f.read() - - # Compare the generated content with the expected content - assert generated_content == expected_content, ( - "Generated schema content does not match the expected file. " - "This could mean the schema has changed or the test needs to be updated." - ) - else: - # If the expected file doesn't exist, create it with the current output - with open(expected_file_path, "w") as f: - f.write(generated_content) - print(f"Created new expected output file: {expected_file_path}") - - finally: - # Clean up the temporary file - if os.path.exists(tmp_path): - os.unlink(tmp_path) - - -def test_generate_definitions_function(): - """ - Test the generate_definitions function directly to ensure it produces consistent output. - """ - # Expected lexicon IDs from the command line - lexicon_ids = ["app.bsky.actor.getProfile", "com.atproto.server.getSession"] - - # Generate definitions using the function - generated_chunks = generate_definitions(lexicon_ids) - generated_content = "\n\n".join(generated_chunks) - - # Read the expected file if it exists - expected_file_path = Path(EXPECTED_OUTPUT_FILE) - if expected_file_path.exists(): - with open(expected_file_path, "r") as f: - expected_content = f.read() - - # Compare the generated content with the expected content - assert generated_content == expected_content, ( - "Generated schema content does not match the expected file. " - "This could mean the schema has changed or the test needs to be updated." - ) - else: - # If the expected file doesn't exist, create it with the current output - with open(expected_file_path, "w") as f: - f.write(generated_content) - print(f"Created new expected output file: {expected_file_path}") diff --git a/js/tsconfig.json b/tsconfig.json similarity index 100% rename from js/tsconfig.json rename to tsconfig.json