diff --git a/.env b/.env new file mode 100644 index 0000000..8b1e5d6 --- /dev/null +++ b/.env @@ -0,0 +1 @@ +DATABASE_URL=postgresql://atopile:uD153pMqpr9o@192.168.3.22:5430/atopile-jlcpcb \ No newline at end of file diff --git a/Cargo.lock b/Cargo.lock index bd40636..11b1d62 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -75,6 +75,63 @@ dependencies = [ "libc", ] +[[package]] +name = "ansi_term" +version = "0.12.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d52a9bb7ec0cf484c551830a7ce27bd20d67eac647e1befb56b0be4ee39a55d2" +dependencies = [ + "winapi", +] + +[[package]] +name = "anstream" +version = "0.6.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "96b09b5178381e0874812a9b157f7fe84982617e48f71f4e3235482775e5b540" +dependencies = [ + "anstyle", + "anstyle-parse", + "anstyle-query", + "anstyle-wincon", + "colorchoice", + "utf8parse", +] + +[[package]] +name = "anstyle" +version = "1.0.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8901269c6307e8d93993578286ac0edf7f195079ffff5ebdeea6a59ffb7e36bc" + +[[package]] +name = "anstyle-parse" +version = "0.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c75ac65da39e5fe5ab759307499ddad880d724eed2f6ce5b5e8a26f4f387928c" +dependencies = [ + "utf8parse", +] + +[[package]] +name = "anstyle-query" +version = "1.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e28923312444cdd728e4738b3f9c9cac739500909bb3d3c94b43551b16517648" +dependencies = [ + "windows-sys 0.52.0", +] + +[[package]] +name = "anstyle-wincon" +version = "3.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1cd54b81ec8d6180e24654d0b371ad22fc3dd083b6ff8ba325b72e00c87660a7" +dependencies = [ + "anstyle", + "windows-sys 0.52.0", +] + [[package]] name = "argminmax" version = "0.6.1" @@ -138,14 +195,28 @@ version = "0.15.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9ae037714f313c1353189ead58ef9eec30a8e8dc101b2622d461418fd59e28a9" +[[package]] +name = "atomic-write-file" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "edcdbedc2236483ab103a53415653d6b4442ea6141baf1ffa85df29635e88436" +dependencies = [ + "nix", + "rand", +] + [[package]] name = "atopile-jlc-parts" -version = "0.2.3" +version = "0.3.0" dependencies = [ "axum", + "clap 4.5.1", + "dotenv", + "dotenvy", "polars", "serde", "serde_json", + "sqlx", "tokio", "tower-http", "tracing", @@ -156,6 +227,17 @@ dependencies = [ "uuid", ] +[[package]] +name = "atty" +version = "0.2.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d9b39be18770d11421cdb1b9947a45dd3f37e93092cbf377614828a319d5fee8" +dependencies = [ + "hermit-abi 0.1.19", + "libc", + "winapi", +] + [[package]] name = "autocfg" version = "1.1.0" @@ -238,6 +320,12 @@ version = "0.21.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9d297deb1925b89f2ccc13d7635fa0714f12c87adce1c75356b39ca9b7178567" +[[package]] +name = "base64ct" +version = "1.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8c3c1a368f70d6cf7302d78f8f7093da241fb8e8807c05cc9e51a125895a6d5b" + [[package]] name = "bitflags" version = "1.3.2" @@ -249,6 +337,9 @@ name = "bitflags" version = "2.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ed570934406eb16438a4e976b1b4500774099c13b8cb96eec99f620f05090ddf" +dependencies = [ + "serde", +] [[package]] name = "block-buffer" @@ -368,6 +459,67 @@ dependencies = [ "phf_codegen", ] +[[package]] +name = "clap" +version = "2.34.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a0610544180c38b88101fecf2dd634b174a62eef6946f84dfc6a7127512b381c" +dependencies = [ + "ansi_term", + "atty", + "bitflags 1.3.2", + "strsim 0.8.0", + "textwrap", + "unicode-width", + "vec_map", +] + +[[package]] +name = "clap" +version = "4.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c918d541ef2913577a0f9566e9ce27cb35b6df072075769e0b26cb5a554520da" +dependencies = [ + "clap_builder", + "clap_derive", +] + +[[package]] +name = "clap_builder" +version = "4.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9f3e7391dad68afb0c2ede1bf619f579a3dc9c2ec67f089baa397123a2f3d1eb" +dependencies = [ + "anstream", + "anstyle", + "clap_lex", + "strsim 0.11.0", +] + +[[package]] +name = "clap_derive" +version = "4.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "307bc0538d5f0f83b8248db3087aa92fe504e4691294d0c96c0eabc33f47ba47" +dependencies = [ + "heck", + "proc-macro2", + "quote", + "syn 2.0.48", +] + +[[package]] +name = "clap_lex" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "98cc8fbded0c607b7ba9dd60cd98df59af97e84d24e49c8557331cfc26d301ce" + +[[package]] +name = "colorchoice" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "acbf1af155f9b9ef647e42cdc158db4b64a1b61f743629225fde6f3e0be2a7c7" + [[package]] name = "comfy-table" version = "7.1.0" @@ -380,6 +532,12 @@ dependencies = [ "unicode-width", ] +[[package]] +name = "const-oid" +version = "0.9.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c2459377285ad874054d797f3ccebf984978aa39129f6eafde5cdc8315b612f8" + [[package]] name = "core-foundation-sys" version = "0.8.6" @@ -395,6 +553,21 @@ dependencies = [ "libc", ] +[[package]] +name = "crc" +version = "3.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "86ec7a15cbe22e59248fc7eadb1907dab5ba09372595da4d73dd805ed4417dfe" +dependencies = [ + "crc-catalog", +] + +[[package]] +name = "crc-catalog" +version = "2.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "19d374276b40fb8bbdee95aef7c7fa6b5316ec764510eb64b8dd0e2ed0d7e7f5" + [[package]] name = "crc32fast" version = "1.3.2" @@ -479,6 +652,26 @@ dependencies = [ "typenum", ] +[[package]] +name = "der" +version = "0.7.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fffa369a668c8af7dbf8b5e56c9f744fbd399949ed171606040001947de40b1c" +dependencies = [ + "const-oid", + "pem-rfc7468", + "zeroize", +] + +[[package]] +name = "deranged" +version = "0.3.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b42b6fa04a440b495c8b04d0e71b707c585f83cb9cb28cf8cd0d976c315e31b4" +dependencies = [ + "powerfmt", +] + [[package]] name = "digest" version = "0.10.7" @@ -486,9 +679,26 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9ed9a281f7bc9b7576e61468ba615a66a5c8cfdff42420a70aa82701a3b1e292" dependencies = [ "block-buffer", + "const-oid", "crypto-common", + "subtle", +] + +[[package]] +name = "dotenv" +version = "0.15.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "77c90badedccf4105eca100756a0b1289e191f6fcbdadd3cee1d2f614f97da8f" +dependencies = [ + "clap 2.34.0", ] +[[package]] +name = "dotenvy" +version = "0.15.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1aaf95b3e5c8f23aa320147307562d361db0ae0d51242340f558153b4eb2439b" + [[package]] name = "dyn-clone" version = "1.0.16" @@ -500,6 +710,9 @@ name = "either" version = "1.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "11157ac094ffbdde99aa67b23417ebdd801842852b500e395a45a9c0aac03e4a" +dependencies = [ + "serde", +] [[package]] name = "enum_dispatch" @@ -519,12 +732,39 @@ version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5443807d6dff69373d433ab9ef5378ad8df50ca6298caf15de6e52e24aaf54d5" +[[package]] +name = "errno" +version = "0.3.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a258e46cdc063eb8519c00b9fc845fc47bcfca4130e2f08e88665ceda8474245" +dependencies = [ + "libc", + "windows-sys 0.52.0", +] + +[[package]] +name = "etcetera" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "136d1b5283a1ab77bd9257427ffd09d8667ced0570b6f938942bc7568ed5b943" +dependencies = [ + "cfg-if", + "home", + "windows-sys 0.48.0", +] + [[package]] name = "ethnum" version = "1.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b90ca2580b73ab6a1f724b76ca11ab632df820fd6040c336200d2c1df7b3c82c" +[[package]] +name = "event-listener" +version = "2.5.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0206175f82b8d6bf6652ff7d71a1e27fd2e4efde587fd368662814d6ec1d9ce0" + [[package]] name = "fallible-streaming-iterator" version = "0.1.9" @@ -537,6 +777,18 @@ version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "95765f67b4b18863968b4a1bd5bb576f732b29a4a28c7cd84c09fa3e2875f33c" +[[package]] +name = "fastrand" +version = "2.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "25cbce373ec4653f1a01a31e8a5e5ec0c622dc27ff9c4e6606eefef5cbbed4a5" + +[[package]] +name = "finl_unicode" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8fcfdc7a0362c9f4444381a9e697c79d435fe65b52a37466fc2c1184cee9edc6" + [[package]] name = "flate2" version = "1.0.28" @@ -547,6 +799,17 @@ dependencies = [ "miniz_oxide", ] +[[package]] +name = "flume" +version = "0.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "55ac459de2512911e4b674ce33cf20befaba382d05b62b008afc1c8b57cbf181" +dependencies = [ + "futures-core", + "futures-sink", + "spin 0.9.8", +] + [[package]] name = "fnv" version = "1.0.7" @@ -610,6 +873,17 @@ dependencies = [ "futures-util", ] +[[package]] +name = "futures-intrusive" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1d930c203dd0b6ff06e0201a4a2fe9149b43c684fd4420555b26d21b1a02956f" +dependencies = [ + "futures-core", + "lock_api", + "parking_lot", +] + [[package]] name = "futures-io" version = "0.3.30" @@ -722,11 +996,32 @@ dependencies = [ "rayon", ] +[[package]] +name = "hashlink" +version = "0.8.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e8094feaf31ff591f651a2664fb9cfd92bba7a60ce3197265e9482ebe753c8f7" +dependencies = [ + "hashbrown", +] + [[package]] name = "heck" version = "0.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "95505c38b4572b2d910cecb0281560f54b440a19336cbbcb27bf6ce6adc6f5a8" +dependencies = [ + "unicode-segmentation", +] + +[[package]] +name = "hermit-abi" +version = "0.1.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "62b467343b94ba476dcb2500d242dadbb39557df889310ac77c5d99100aaac33" +dependencies = [ + "libc", +] [[package]] name = "hermit-abi" @@ -740,6 +1035,24 @@ version = "0.4.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7f24254aa9a54b5c858eaee2f5bccdb46aaf0e486a595ed5fd8f86ba55232a70" +[[package]] +name = "hkdf" +version = "0.12.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7b5f8eb2ad728638ea2c7d47a21db23b7b58a72ed6a38256b8a1849f15fbbdf7" +dependencies = [ + "hmac", +] + +[[package]] +name = "hmac" +version = "0.12.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6c49c37c09c17a53d937dfbb742eb3a961d65a994e6bcdcf37e7399d0cc8ab5e" +dependencies = [ + "digest", +] + [[package]] name = "home" version = "0.5.9" @@ -853,6 +1166,16 @@ dependencies = [ "cc", ] +[[package]] +name = "idna" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "634d9b1461af396cad843f47fdba5597a4f9e6ddd4bfb6ff5d85028c25cb12f6" +dependencies = [ + "unicode-bidi", + "unicode-normalization", +] + [[package]] name = "indexmap" version = "2.2.2" @@ -864,6 +1187,15 @@ dependencies = [ "serde", ] +[[package]] +name = "itertools" +version = "0.12.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ba291022dbbd398a455acf126c1e341954079855bc60dfdda641363bd6922569" +dependencies = [ + "either", +] + [[package]] name = "itoa" version = "1.0.10" @@ -899,6 +1231,9 @@ name = "lazy_static" version = "1.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" +dependencies = [ + "spin 0.5.2", +] [[package]] name = "libc" @@ -912,6 +1247,23 @@ version = "0.2.8" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4ec2a862134d2a7d32d7983ddcdd1c4923530833c9f2ea1a44fc5fa473989058" +[[package]] +name = "libsqlite3-sys" +version = "0.27.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cf4e226dcd58b4be396f7bd3c20da8fdee2911400705297ba7d2d7cc2c30f716" +dependencies = [ + "cc", + "pkg-config", + "vcpkg", +] + +[[package]] +name = "linux-raw-sys" +version = "0.4.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "01cda141df6706de531b6c46c3a33ecca755538219bd484262fa09410c13539c" + [[package]] name = "lock_api" version = "0.4.11" @@ -963,6 +1315,16 @@ version = "0.7.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0e7465ac9959cc2b1404e8e2367b43684a6d13790fe23056cc8c6c5a6b7bcb94" +[[package]] +name = "md-5" +version = "0.10.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d89e7ee0cfbedfc4da3340218492196241d89eefb6dab27de5df917a6d2e78cf" +dependencies = [ + "cfg-if", + "digest", +] + [[package]] name = "memchr" version = "2.7.1" @@ -994,6 +1356,12 @@ dependencies = [ "unicase", ] +[[package]] +name = "minimal-lexical" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "68354c5c6bd36d73ff3feceb05efa59b6acb7626617f4962be322a825e61f79a" + [[package]] name = "miniz_oxide" version = "0.7.2" @@ -1036,6 +1404,27 @@ dependencies = [ "target-features", ] +[[package]] +name = "nix" +version = "0.27.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2eb04e9c688eff1c89d72b407f168cf79bb9e867a9d3323ed6c01519eb9cc053" +dependencies = [ + "bitflags 2.4.2", + "cfg-if", + "libc", +] + +[[package]] +name = "nom" +version = "7.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d273983c5a657a70a3e8f2a01329822f3b8c8172b73826411a55751e404a0a4a" +dependencies = [ + "memchr", + "minimal-lexical", +] + [[package]] name = "now" version = "0.1.3" @@ -1065,22 +1454,65 @@ dependencies = [ ] [[package]] -name = "num-traits" -version = "0.2.18" +name = "num-bigint-dig" +version = "0.8.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "da0df0e5185db44f69b44f26786fe401b6c293d1907744beaa7fa62b2e5a517a" +checksum = "dc84195820f291c7697304f3cbdadd1cb7199c0efc917ff5eafd71225c136151" dependencies = [ - "autocfg", + "byteorder", + "lazy_static", "libm", + "num-integer", + "num-iter", + "num-traits", + "rand", + "smallvec", + "zeroize", ] [[package]] -name = "num_cpus" -version = "1.16.0" +name = "num-conv" +version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4161fcb6d602d4d2081af7c3a45852d875a03dd337a6bfdd6e06407b61342a43" +checksum = "51d515d32fb182ee37cda2ccdcb92950d6a3c2893aa280e540671c2cd0f3b1d9" + +[[package]] +name = "num-integer" +version = "0.1.46" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7969661fd2958a5cb096e56c8e1ad0444ac2bbcd0061bd28660485a44879858f" dependencies = [ - "hermit-abi", + "num-traits", +] + +[[package]] +name = "num-iter" +version = "0.1.44" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d869c01cc0c455284163fd0092f1f93835385ccab5a98a0dcc497b2f8bf055a9" +dependencies = [ + "autocfg", + "num-integer", + "num-traits", +] + +[[package]] +name = "num-traits" +version = "0.2.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "da0df0e5185db44f69b44f26786fe401b6c293d1907744beaa7fa62b2e5a517a" +dependencies = [ + "autocfg", + "libm", +] + +[[package]] +name = "num_cpus" +version = "1.16.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4161fcb6d602d4d2081af7c3a45852d875a03dd337a6bfdd6e06407b61342a43" +dependencies = [ + "hermit-abi 0.3.5", "libc", ] @@ -1147,6 +1579,21 @@ dependencies = [ "regex", ] +[[package]] +name = "paste" +version = "1.0.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "de3145af08024dea9fa9914f381a17b8fc6034dfb00f3a84013f7ff43f29ed4c" + +[[package]] +name = "pem-rfc7468" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "88b39c9bfcfc231068454382784bb460aae594343fb030d46e9f50a645418412" +dependencies = [ + "base64ct", +] + [[package]] name = "percent-encoding" version = "2.3.1" @@ -1223,6 +1670,27 @@ version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184" +[[package]] +name = "pkcs1" +version = "0.7.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c8ffb9f10fa047879315e6625af03c164b16962a5368d724ed16323b68ace47f" +dependencies = [ + "der", + "pkcs8", + "spki", +] + +[[package]] +name = "pkcs8" +version = "0.10.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f950b2377845cebe5cf8b5165cb3cc1a5e0fa5cfa3e1f7f55707d8fd82e0a7b7" +dependencies = [ + "der", + "spki", +] + [[package]] name = "pkg-config" version = "0.3.29" @@ -1590,6 +2058,12 @@ dependencies = [ "version_check", ] +[[package]] +name = "powerfmt" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "439ee305def115ba05938db6eb1644ff94165c5ab5e9420d1c1bcedbba909391" + [[package]] name = "ppv-lite86" version = "0.2.17" @@ -1751,6 +2225,41 @@ version = "0.8.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c08c74e62047bb2de4ff487b251e4a92e24f48745648451635cec7d591162d9f" +[[package]] +name = "ring" +version = "0.17.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c17fa4cb658e3583423e915b9f3acc01cceaee1860e33d59ebae66adc3a2dc0d" +dependencies = [ + "cc", + "cfg-if", + "getrandom", + "libc", + "spin 0.9.8", + "untrusted", + "windows-sys 0.52.0", +] + +[[package]] +name = "rsa" +version = "0.9.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5d0e5124fcb30e76a7e79bfee683a2746db83784b86289f6251b54b7950a0dfc" +dependencies = [ + "const-oid", + "digest", + "num-bigint-dig", + "num-integer", + "num-traits", + "pkcs1", + "pkcs8", + "rand_core", + "signature", + "spki", + "subtle", + "zeroize", +] + [[package]] name = "rust-embed" version = "8.2.0" @@ -1791,6 +2300,49 @@ version = "0.1.23" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d626bb9dae77e28219937af045c257c28bfd3f69333c512553507f5f9798cb76" +[[package]] +name = "rustix" +version = "0.38.31" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6ea3e1a662af26cd7a3ba09c0297a31af215563ecf42817c98df621387f4e949" +dependencies = [ + "bitflags 2.4.2", + "errno", + "libc", + "linux-raw-sys", + "windows-sys 0.52.0", +] + +[[package]] +name = "rustls" +version = "0.21.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f9d5a6813c0759e4609cd494e8e725babae6a2ca7b62a5536a13daaec6fcb7ba" +dependencies = [ + "ring", + "rustls-webpki", + "sct", +] + +[[package]] +name = "rustls-pemfile" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1c74cae0a4cf6ccbbf5f359f08efdf8ee7e1dc532573bf0db71968cb56b1448c" +dependencies = [ + "base64", +] + +[[package]] +name = "rustls-webpki" +version = "0.101.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8b6275d1ee7a1cd780b64aca7726599a1dbc893b1e64144529e55c3c2f745765" +dependencies = [ + "ring", + "untrusted", +] + [[package]] name = "rustversion" version = "1.0.14" @@ -1818,6 +2370,16 @@ version = "1.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49" +[[package]] +name = "sct" +version = "0.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "da046153aa2352493d6cb7da4b6e5c0c057d8a1d0a9aa8560baffdd945acd414" +dependencies = [ + "ring", + "untrusted", +] + [[package]] name = "seq-macro" version = "0.3.5" @@ -1877,6 +2439,17 @@ dependencies = [ "serde", ] +[[package]] +name = "sha1" +version = "0.10.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e3bf829a2d51ab4a5ddf1352d8470c140cadc8301b2ae1789db023f01cedd6ba" +dependencies = [ + "cfg-if", + "cpufeatures", + "digest", +] + [[package]] name = "sha2" version = "0.10.8" @@ -1906,6 +2479,16 @@ dependencies = [ "libc", ] +[[package]] +name = "signature" +version = "2.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "77549399552de45a898a580c1b41d445bf730df867cc44e6c0233bbc4b8329de" +dependencies = [ + "digest", + "rand_core", +] + [[package]] name = "simdutf8" version = "0.1.4" @@ -1960,6 +2543,42 @@ dependencies = [ "windows-sys 0.48.0", ] +[[package]] +name = "spin" +version = "0.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6e63cff320ae2c57904679ba7cb63280a3dc4613885beafb148ee7bf9aa9042d" + +[[package]] +name = "spin" +version = "0.9.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6980e8d7511241f8acf4aebddbb1ff938df5eebe98691418c4468d0b72a96a67" +dependencies = [ + "lock_api", +] + +[[package]] +name = "spki" +version = "0.7.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d91ed6c858b01f942cd56b37a94b3e0a1798290327d1236e4d9cf4eaca44d29d" +dependencies = [ + "base64ct", + "der", +] + +[[package]] +name = "sqlformat" +version = "0.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ce81b7bd7c4493975347ef60d8c7e8b742d4694f4c49f93e0a12ea263938176c" +dependencies = [ + "itertools", + "nom", + "unicode_categories", +] + [[package]] name = "sqlparser" version = "0.39.0" @@ -1969,6 +2588,214 @@ dependencies = [ "log", ] +[[package]] +name = "sqlx" +version = "0.7.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dba03c279da73694ef99763320dea58b51095dfe87d001b1d4b5fe78ba8763cf" +dependencies = [ + "sqlx-core", + "sqlx-macros", + "sqlx-mysql", + "sqlx-postgres", + "sqlx-sqlite", +] + +[[package]] +name = "sqlx-core" +version = "0.7.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d84b0a3c3739e220d94b3239fd69fb1f74bc36e16643423bd99de3b43c21bfbd" +dependencies = [ + "ahash", + "atoi", + "byteorder", + "bytes", + "crc", + "crossbeam-queue", + "dotenvy", + "either", + "event-listener", + "futures-channel", + "futures-core", + "futures-intrusive", + "futures-io", + "futures-util", + "hashlink", + "hex", + "indexmap", + "log", + "memchr", + "once_cell", + "paste", + "percent-encoding", + "rustls", + "rustls-pemfile", + "serde", + "serde_json", + "sha2", + "smallvec", + "sqlformat", + "thiserror", + "time", + "tokio", + "tokio-stream", + "tracing", + "url", + "uuid", + "webpki-roots", +] + +[[package]] +name = "sqlx-macros" +version = "0.7.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "89961c00dc4d7dffb7aee214964b065072bff69e36ddb9e2c107541f75e4f2a5" +dependencies = [ + "proc-macro2", + "quote", + "sqlx-core", + "sqlx-macros-core", + "syn 1.0.109", +] + +[[package]] +name = "sqlx-macros-core" +version = "0.7.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d0bd4519486723648186a08785143599760f7cc81c52334a55d6a83ea1e20841" +dependencies = [ + "atomic-write-file", + "dotenvy", + "either", + "heck", + "hex", + "once_cell", + "proc-macro2", + "quote", + "serde", + "serde_json", + "sha2", + "sqlx-core", + "sqlx-mysql", + "sqlx-postgres", + "sqlx-sqlite", + "syn 1.0.109", + "tempfile", + "tokio", + "url", +] + +[[package]] +name = "sqlx-mysql" +version = "0.7.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e37195395df71fd068f6e2082247891bc11e3289624bbc776a0cdfa1ca7f1ea4" +dependencies = [ + "atoi", + "base64", + "bitflags 2.4.2", + "byteorder", + "bytes", + "crc", + "digest", + "dotenvy", + "either", + "futures-channel", + "futures-core", + "futures-io", + "futures-util", + "generic-array", + "hex", + "hkdf", + "hmac", + "itoa", + "log", + "md-5", + "memchr", + "once_cell", + "percent-encoding", + "rand", + "rsa", + "serde", + "sha1", + "sha2", + "smallvec", + "sqlx-core", + "stringprep", + "thiserror", + "time", + "tracing", + "uuid", + "whoami", +] + +[[package]] +name = "sqlx-postgres" +version = "0.7.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d6ac0ac3b7ccd10cc96c7ab29791a7dd236bd94021f31eec7ba3d46a74aa1c24" +dependencies = [ + "atoi", + "base64", + "bitflags 2.4.2", + "byteorder", + "crc", + "dotenvy", + "etcetera", + "futures-channel", + "futures-core", + "futures-io", + "futures-util", + "hex", + "hkdf", + "hmac", + "home", + "itoa", + "log", + "md-5", + "memchr", + "once_cell", + "rand", + "serde", + "serde_json", + "sha1", + "sha2", + "smallvec", + "sqlx-core", + "stringprep", + "thiserror", + "time", + "tracing", + "uuid", + "whoami", +] + +[[package]] +name = "sqlx-sqlite" +version = "0.7.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "210976b7d948c7ba9fced8ca835b11cbb2d677c59c79de41ac0d397e14547490" +dependencies = [ + "atoi", + "flume", + "futures-channel", + "futures-core", + "futures-executor", + "futures-intrusive", + "futures-util", + "libsqlite3-sys", + "log", + "percent-encoding", + "serde", + "sqlx-core", + "time", + "tracing", + "url", + "urlencoding", + "uuid", +] + [[package]] name = "static_assertions" version = "1.1.0" @@ -1996,6 +2823,29 @@ version = "0.2.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "fe895eb47f22e2ddd4dabc02bce419d2e643c8e3b585c78158b349195bc24d82" +[[package]] +name = "stringprep" +version = "0.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bb41d74e231a107a1b4ee36bd1214b11285b77768d2e3824aedafa988fd36ee6" +dependencies = [ + "finl_unicode", + "unicode-bidi", + "unicode-normalization", +] + +[[package]] +name = "strsim" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8ea5119cdb4c55b55d432abb513a0429384878c15dde60cc77b1c99de1a95a6a" + +[[package]] +name = "strsim" +version = "0.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5ee073c9e4cd00e28217186dbe12796d692868f432bf2e97ee73bed0c56dfa01" + [[package]] name = "strum" version = "0.25.0" @@ -2015,6 +2865,12 @@ dependencies = [ "syn 2.0.48", ] +[[package]] +name = "subtle" +version = "2.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "81cdd64d312baedb58e21336b31bc043b77e01cc99033ce76ef539f78e965ebc" + [[package]] name = "syn" version = "1.0.109" @@ -2063,6 +2919,27 @@ version = "0.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "cfb5fa503293557c5158bd215fdc225695e567a77e453f5d4452a50a193969bd" +[[package]] +name = "tempfile" +version = "3.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a365e8cd18e44762ef95d87f284f4b5cd04107fec2ff3052bd6a3e6069669e67" +dependencies = [ + "cfg-if", + "fastrand", + "rustix", + "windows-sys 0.52.0", +] + +[[package]] +name = "textwrap" +version = "0.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d326610f408c7a4eb6f51c37c330e496b08506c9457c9d34287ecc38809fb060" +dependencies = [ + "unicode-width", +] + [[package]] name = "thiserror" version = "1.0.56" @@ -2093,6 +2970,52 @@ dependencies = [ "once_cell", ] +[[package]] +name = "time" +version = "0.3.34" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c8248b6521bb14bc45b4067159b9b6ad792e2d6d754d6c41fb50e29fefe38749" +dependencies = [ + "deranged", + "itoa", + "num-conv", + "powerfmt", + "serde", + "time-core", + "time-macros", +] + +[[package]] +name = "time-core" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ef927ca75afb808a4d64dd374f00a2adf8d0fcff8e7b184af886c3c87ec4a3f3" + +[[package]] +name = "time-macros" +version = "0.2.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7ba3a3ef41e6672a2f0f001392bb5dcd3ff0a9992d618ca761a11c3121547774" +dependencies = [ + "num-conv", + "time-core", +] + +[[package]] +name = "tinyvec" +version = "1.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "87cc5ceb3875bb20c2890005a4e226a4651264a5c75edb2421b52861a0a0cb50" +dependencies = [ + "tinyvec_macros", +] + +[[package]] +name = "tinyvec_macros" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20" + [[package]] name = "tokio" version = "1.36.0" @@ -2123,6 +3046,17 @@ dependencies = [ "syn 2.0.48", ] +[[package]] +name = "tokio-stream" +version = "0.1.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "397c988d37662c7dda6d2208364a706264bf3d6138b11d436cbac0ad38832842" +dependencies = [ + "futures-core", + "pin-project-lite", + "tokio", +] + [[package]] name = "tokio-util" version = "0.7.10" @@ -2259,12 +3193,27 @@ dependencies = [ "version_check", ] +[[package]] +name = "unicode-bidi" +version = "0.3.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "08f95100a766bf4f8f28f90d77e0a5461bbdb219042e7679bebe79004fed8d75" + [[package]] name = "unicode-ident" version = "1.0.12" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3354b9ac3fae1ff6755cb6db53683adb661634f67557942dea4facebec0fee4b" +[[package]] +name = "unicode-normalization" +version = "0.1.23" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a56d1686db2308d901306f92a263857ef59ea39678a5458e7cb17f01415101f5" +dependencies = [ + "tinyvec", +] + [[package]] name = "unicode-reverse" version = "1.0.8" @@ -2286,6 +3235,41 @@ version = "0.1.11" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e51733f11c9c4f72aa0c160008246859e340b00807569a0da0e7a1079b27ba85" +[[package]] +name = "unicode_categories" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "39ec24b3121d976906ece63c9daad25b85969647682eee313cb5779fdd69e14e" + +[[package]] +name = "untrusted" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8ecb6da28b8a351d773b68d5825ac39017e680750f980f3a1a85cd8dd28a47c1" + +[[package]] +name = "url" +version = "2.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "31e6302e3bb753d46e83516cae55ae196fc0c309407cf11ab35cc51a4c2a4633" +dependencies = [ + "form_urlencoded", + "idna", + "percent-encoding", +] + +[[package]] +name = "urlencoding" +version = "2.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "daf8dba3b7eb870caf1ddeed7bc9d2a049f3cfdfae7cb521b087cc33ae4c49da" + +[[package]] +name = "utf8parse" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "711b9620af191e0cdc7468a8d14e709c3dcdb115b36f838e601583af800a370a" + [[package]] name = "utoipa" version = "4.2.0" @@ -2373,6 +3357,18 @@ version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "830b7e5d4d90034032940e4ace0d9a9a057e7a45cd94e6c007832e39edb82f6d" +[[package]] +name = "vcpkg" +version = "0.2.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "accd4ea62f7bb7a82fe23066fb0957d48ef677f6eeb8215f372f52e48bb32426" + +[[package]] +name = "vec_map" +version = "0.8.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f1bddf1187be692e79c5ffeab891132dfb0f236ed36a43c7ed39f1165ee20191" + [[package]] name = "version_check" version = "0.9.4" @@ -2449,6 +3445,18 @@ version = "0.2.91" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4f186bd2dcf04330886ce82d6f33dd75a7bfcf69ecf5763b89fcde53b6ac9838" +[[package]] +name = "webpki-roots" +version = "0.25.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5f20c57d8d7db6d3b86154206ae5d8fba62dd39573114de97c2cb0578251f8e1" + +[[package]] +name = "whoami" +version = "1.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "22fc3756b8a9133049b26c7f61ab35416c130e8c09b660f5b3958b446f52cc50" + [[package]] name = "winapi" version = "0.3.9" @@ -2657,6 +3665,12 @@ dependencies = [ "syn 2.0.48", ] +[[package]] +name = "zeroize" +version = "1.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "525b4ec142c6b68a2d10f01f7bbf6755599ca3f81ea53b8431b7dd348f5fdb2d" + [[package]] name = "zip" version = "0.6.6" diff --git a/Cargo.toml b/Cargo.toml index f436a3e..0e94705 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "atopile-jlc-parts" -version = "0.2.3" +version = "0.3.0" edition = "2021" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html @@ -18,3 +18,7 @@ polars = { version = "0.37.0", features = ["parquet", "lazy", "object", "streami uuid = { version = "1.7.0", features = ["v4"] } tracing = "0.1.40" tower-http = { version = "0.5.1", features = ["trace"] } +sqlx = { version = "0.7.3", features = ["runtime-tokio-rustls", "postgres", "macros", "time", "json", "uuid"] } +clap = { version = "4.5.1", features = ["derive", "env"] } +dotenvy = "0.15.7" +dotenv = { version = "0.15.0", features = ["clap"] } diff --git a/README.md b/README.md index a43bf06..daf921b 100644 --- a/README.md +++ b/README.md @@ -6,7 +6,14 @@ Alternative backend to the official Atopile component search-engine. ## Tech stack Rust, Axum, Pola.rs, Docker +# Launch the APP +``` +cargo run -- -d postgresql://atopile:@192.168.3.22:5430/atopile-jlcpcb +``` + + ## Install + Compiling h2 v0.4.2 Building the docker image will take +/- 10 minutes depending on your hardware. Clone this repository to your local computer and run: diff --git a/src/jlc/v1/jlc_endpoint.rs b/src/jlc/v1/jlc_endpoint.rs index a4dc269..5340908 100644 --- a/src/jlc/v1/jlc_endpoint.rs +++ b/src/jlc/v1/jlc_endpoint.rs @@ -4,6 +4,8 @@ use axum::extract::State; use axum::http::StatusCode; use axum::response::Json; use axum::response::Response; +use axum::Extension; +use sqlx::PgPool; use super::jlc_models::*; use super::jlc_part_finder::*; @@ -18,14 +20,13 @@ responses( ) )] pub async fn part_request( - // this argument tells axum to parse the request body - // as JSON into a `CreateUser` type + Extension(pool): Extension, State(state): State, Json(payload): Json, ) -> (StatusCode, Response) { // insert your application logic here - let part_response = find_part(state.polars_df.clone(), payload); + let part_response = find_part(pool, payload).await; if part_response.is_err() { return ( diff --git a/src/jlc/v1/jlc_models.rs b/src/jlc/v1/jlc_models.rs index 3e73711..338b0b1 100644 --- a/src/jlc/v1/jlc_models.rs +++ b/src/jlc/v1/jlc_models.rs @@ -26,7 +26,7 @@ pub struct JLCValue { pub nominal: f64, pub tolerance: f64, #[serde(rename = "tolerance_pct")] - pub tolerance_pct: f64, + pub tolerance_pct: Option, } // LEGACY Response Models diff --git a/src/jlc/v1/jlc_part_finder.rs b/src/jlc/v1/jlc_part_finder.rs index a2e29e8..290b29a 100644 --- a/src/jlc/v1/jlc_part_finder.rs +++ b/src/jlc/v1/jlc_part_finder.rs @@ -1,4 +1,5 @@ use polars::prelude::*; +use sqlx::PgPool; use uuid::Uuid; use crate::jlc::v1::jlc_models::*; @@ -6,107 +7,91 @@ use crate::jlc::v1::jlc_searchers::jlc_find_capacitor::find_capacitor; use crate::jlc::v1::jlc_searchers::jlc_find_inductor::find_inductor; use crate::jlc::v1::jlc_searchers::jlc_find_resistor::find_resistor; -#[derive(Debug, Clone)] -struct Component { - lcsc: String, - category_id: i64, - mfr: String, - package: String, - joints: i64, - manufacturer_id: i64, - basic: i64, - description: String, - datasheet: String, - stock: i64, - price: String, - last_update: i64, - flag: i64, - last_on_stock: i64, - preferred: i64, - resistance: Option, - inductance: Option, - capacitance: Option, - dielectric: Option, +#[derive(Debug, Clone, sqlx::FromRow)] +pub struct Component { + pub id: i64, + pub lcsc: String, + pub category_id: i64, + pub mfr: Option, + pub package: Option, + pub joints: i64, + pub manufacturer: String, + pub basic: bool, + pub description: Option, + pub datasheet: Option, + pub stock: i64, + pub price: Option, + pub last_update: sqlx::types::time::PrimitiveDateTime, + pub resistance: Option, + pub inductance: Option, + pub capacitance: Option, + pub dielectric: Option, + pub current: Option, + pub voltage: Option, } -pub fn find_part(polars_df: LazyFrame, request: JLCPartRequest) -> Result { +pub async fn find_part(pool: PgPool, request: JLCPartRequest) -> Result { tracing::info!("Searching JLC part: {:?}", request); if request.type_field == "resistor".to_string() { - let option_resistor_df = find_resistor(polars_df, request.clone()); - if option_resistor_df.is_none() { + let option_resistor_vec = find_resistor(pool, request.clone()).await; + if option_resistor_vec.is_err() { return Err("No resistor found".to_string()); } else { - let (df, jlc_value) = option_resistor_df.unwrap(); - return Ok(df_to_jlcpb_part_response(request, df, jlc_value)); + let (component_vec, jlc_value) = option_resistor_vec.unwrap(); + if component_vec.len() == 0 { + return Err("No resistor found".to_string()); + } + return Ok(component_vec_to_jlcpb_part_response(request, component_vec, jlc_value)); } + } else if request.type_field == "capacitor".to_string() { - let option_capacitor_df = find_capacitor(polars_df, request.clone()); - if option_capacitor_df.is_none() { + let option_capacitor_vec = find_capacitor(pool, request.clone()).await; + if option_capacitor_vec.is_err() { return Err("No capacitor found".to_string()); } else { - let (df, jlc_value) = option_capacitor_df.unwrap(); - return Ok(df_to_jlcpb_part_response(request, df, jlc_value)); + let (component_vec, jlc_value) = option_capacitor_vec.unwrap(); + if component_vec.len() == 0 { + return Err("No capacitor found".to_string()); + } + return Ok(component_vec_to_jlcpb_part_response(request, component_vec, jlc_value)); } } else if request.type_field == "inductor".to_string() { - let option_inductor_df = find_inductor(polars_df, request.clone()); - if option_inductor_df.is_none() { + let option_inductor_vec = find_inductor(pool, request.clone()).await; + if option_inductor_vec.is_err() { return Err("No inductor found".to_string()); } else { - let (df, jlc_value) = option_inductor_df.unwrap(); - return Ok(df_to_jlcpb_part_response(request, df, jlc_value)); + let (component_vec, jlc_value) = option_inductor_vec.unwrap(); + if component_vec.len() == 0 { + return Err("No inductor found".to_string()); + } + return Ok(component_vec_to_jlcpb_part_response(request, component_vec, jlc_value)); } - } else { + } + else { Err("Unsupported part type".to_string()) } } -pub fn df_to_jlcpb_part_response( +pub fn component_vec_to_jlcpb_part_response( request: JLCPartRequest, - df: DataFrame, + components: Vec, jlc_value: JLCValue, ) -> JLCPartResponse { - // select first value of every column - let df_first = df.get_row(0).unwrap(); - let component = Component { - lcsc: df_first.0.get(0).unwrap().to_string(), - category_id: df_first.0.get(1).unwrap().try_extract().unwrap(), - mfr: df_first.0.get(2).unwrap().to_string(), - package: df_first.0.get(3).unwrap().to_string(), - joints: df_first.0.get(4).unwrap().try_extract().unwrap(), - manufacturer_id: df_first.0.get(5).unwrap().try_extract().unwrap(), - basic: df_first.0.get(6).unwrap().try_extract().unwrap(), - description: df_first.0.get(7).unwrap().to_string(), - datasheet: df_first.0.get(8).unwrap().to_string(), - stock: df_first.0.get(9).unwrap().try_extract().unwrap(), - price: df_first.0.get(10).unwrap().to_string(), - last_update: df_first.0.get(11).unwrap().try_extract().unwrap(), - flag: df_first.0.get(12).unwrap().try_extract().unwrap(), - last_on_stock: df_first.0.get(13).unwrap().try_extract().unwrap(), - preferred: df_first.0.get(14).unwrap().try_extract().unwrap(), - resistance: df_first.0.get(15).unwrap().try_extract().ok(), - inductance: df_first.0.get(16).unwrap().try_extract().ok(), - capacitance: df_first.0.get(17).unwrap().try_extract().ok(), - dielectric: df_first - .0 - .get(18) - .unwrap() - .to_string() - .replace("\"", "") - .parse() - .ok(), - }; + // return first element of components vector + let component = components.get(0).unwrap(); + // kicad_footprint is R + package for resistors and C + package for capacitors let kicad_footprint = match request.type_field.as_str() { - "resistor" => format!("R{}", &component.package), - "capacitor" => format!("C{}", &component.package), + "resistor" => format!("R{}", &component.package.clone().unwrap_or("".to_string())), + "capacitor" => format!("C{}", &component.package.clone().unwrap_or("".to_string())), "inductor" => "L".to_string(), _ => "".to_string(), }; - let lcsc_id = format!("C{}", &component.lcsc.replace("\"", "")); + let lcsc_id = component.lcsc.clone(); let best_component = BestComponent { - dielectric: component.dielectric, - basic_part: component.basic == 1, - description: component.description.replace("\"", ""), + dielectric: component.dielectric.clone(), + basic_part: component.basic, + description: component.description.clone().unwrap_or("".to_string()), type_field: request.type_field, uuid: Uuid::new_v4().to_string(), value: jlc_value, @@ -122,11 +107,11 @@ pub fn df_to_jlcpb_part_response( footprint: Footprint { kicad: kicad_footprint.replace("\"", ""), }, - mpn: component.mfr.replace("\"", ""), - datasheet: component.datasheet.replace("\"", ""), - category: "".to_string(), // not really needed right now + mpn: component.mfr.clone().unwrap_or("".to_string()), + datasheet: component.datasheet.clone().unwrap_or("".to_string()), + category: "Resistors".to_string(), // not really needed right now lcsc_id: lcsc_id, - package: component.package.replace("\"", ""), + package: component.package.clone().unwrap_or("".to_string()), footprint_data: FootprintData { kicad: "standard-library".to_string(), }, @@ -134,4 +119,5 @@ pub fn df_to_jlcpb_part_response( JLCPartResponse { best_component: best_component, } + } diff --git a/src/jlc/v1/jlc_searchers/jlc_find_capacitor.rs b/src/jlc/v1/jlc_searchers/jlc_find_capacitor.rs index 7efd9bd..8525d6e 100644 --- a/src/jlc/v1/jlc_searchers/jlc_find_capacitor.rs +++ b/src/jlc/v1/jlc_searchers/jlc_find_capacitor.rs @@ -1,71 +1,75 @@ -use polars::prelude::*; +use sqlx::PgPool; -use super::sort_dataframe; use crate::jlc::v1::jlc_models::*; +use crate::jlc::v1::jlc_part_finder::Component; -pub fn find_capacitor( - components_df: LazyFrame, +pub async fn find_capacitor( + pool: PgPool, request: JLCPartRequest, -) -> Option<(DataFrame, JLCValue)> { - // filter components_df on category_id = 27 (capacitors) - let mut components_df = components_df - .filter(col("category_id").eq(lit(27))) - .collect() - .unwrap() - .lazy(); +) -> Result<(Vec, JLCValue), sqlx::Error> { + // get + let capacitor_category_id: (i32,) = sqlx::query_as("SELECT id FROM categories WHERE name = 'Capacitors' and subcategory_name = 'Multilayer Ceramic Capacitors MLCC - SMD/SMT'") + .fetch_one(&pool).await?; // value conversion - let (farad_multiplier, _farad_string) = match request.value.unit.as_str() { - "pF" | "picofarad" => (1.0, "pF"), - "nF" | "nanofarad" => (1e3, "nF"), - "μF" | "uF" | "microfarad" => (1e6, "μF"), - "mF" | "millifarad" => (1e9, "mF"), - "kF" | "kilofarad" => (1e15, "kF"), - "MF" | "megafarad" => (1e18, "MF"), - "F" | "farad" => (1e12, "F"), - _ => return None, + let farad_string = request.value.unit.to_string(); + let (farad_value, farad_max, farad_min) = match farad_string.as_str() { + "pF" | "picofarad" => ( + request.value.nominal, + request.value.nominal * (1.0 + request.value.tolerance_pct.unwrap_or(0.0) / 100.0), + request.value.nominal * (1.0 - request.value.tolerance_pct.unwrap_or(0.0) / 100.0), + ), + "nF" | "nanofarad" => ( + request.value.nominal * 1e3, + request.value.nominal * 1e3 * (1.0 + request.value.tolerance_pct.unwrap_or(0.0) / 100.0), + request.value.nominal * 1e3 * (1.0 - request.value.tolerance_pct.unwrap_or(0.0) / 100.0), + ), + "μF" | "uF" | "microfarad" => ( + request.value.nominal * 1e6, + request.value.nominal * 1e6 * (1.0 + request.value.tolerance_pct.unwrap_or(0.0) / 100.0), + request.value.nominal * 1e6 * (1.0 - request.value.tolerance_pct.unwrap_or(0.0) / 100.0), + ), + "mF" | "millifarad" => ( + request.value.nominal * 1e9, + request.value.nominal * 1e9 * (1.0 + request.value.tolerance_pct.unwrap_or(0.0) / 100.0), + request.value.nominal * 1e9 * (1.0 - request.value.tolerance_pct.unwrap_or(0.0) / 100.0), + ), + "F" | "farad" => ( + request.value.nominal * 1e12, + request.value.nominal * 1e12 * (1.0 + request.value.tolerance_pct.unwrap_or(0.0) / 100.0), + request.value.nominal * 1e12 * (1.0 - request.value.tolerance_pct.unwrap_or(0.0) / 100.0), + ), + _ => return Err(sqlx::Error::RowNotFound), }; - let farad_value = (request.value.nominal * farad_multiplier).round(); - let farad_max = farad_value + farad_value * request.value.tolerance_pct / 100.0; - let farad_min = farad_value - farad_value * request.value.tolerance_pct / 100.0; - let jlc_farad_value = JLCValue { unit: "F".to_string(), - min_val: farad_min * 1e-12, - max_val: farad_max * 1e-12, - nominal: farad_value * 1e-12, + min_val: farad_min, + max_val: farad_max, + nominal: farad_value, tolerance: request.value.tolerance, - tolerance_pct: request.value.tolerance_pct, + tolerance_pct: Some(request.value.tolerance_pct.unwrap_or(0.0)), }; // if request.package is not None, filter components_df on package = request.package if request.package.is_some() { - components_df = components_df.filter(col("package").eq(lit(request.package.unwrap()))); - } - - // filter components_df on capacitance = farad_value - let components_df_eq = components_df - .clone() - .filter(col("capacitance").eq(lit(farad_value))); - - let df_eq = components_df_eq.collect().unwrap(); - if df_eq.height() >= 1 { - let df_eq_sorted = sort_dataframe(df_eq); - return Some((df_eq_sorted, jlc_farad_value)); + let mut matching_parts: Vec = sqlx::query_as!( + Component, + r#"SELECT id as "id!", lcsc as "lcsc!", category_id as "category_id!", mfr as "mfr?", package as "package?", joints as "joints!", manufacturer as "manufacturer!", basic as "basic!", description as "description?", datasheet as "datasheet?", stock as "stock!", price as "price?", last_update as "last_update!", capacitance as "capacitance?", inductance, resistance, dielectric as "dielectric?", current, voltage FROM parts WHERE category_id = $1 and capacitance between $2 and $3 and package = $4 ORDER BY basic DESC LIMIT 100"#, + capacitor_category_id.0, + farad_min, + farad_max, + request.package.unwrap() + ).fetch_all(&pool).await?; + return Ok((matching_parts, jlc_farad_value)); + } else { + let mut matching_parts: Vec = sqlx::query_as!( + Component, + r#"SELECT id as "id!", lcsc as "lcsc!", category_id as "category_id!", mfr as "mfr?", package as "package?", joints as "joints!", manufacturer as "manufacturer!", basic as "basic!", description as "description?", datasheet as "datasheet?", stock as "stock!", price as "price?", last_update as "last_update!", capacitance as "capacitance?", inductance, resistance, dielectric as "dielectric?", current, voltage FROM parts WHERE category_id = $1 and capacitance between $2 and $3 ORDER BY basic DESC LIMIT 100"#, + capacitor_category_id.0, + farad_min, + farad_max + ).fetch_all(&pool).await?; + return Ok((matching_parts, jlc_farad_value)); } - - // filter components_df on capacitance > farad_min and capacitance < farad_max - let components_df_range = components_df.filter( - col("capacitance") - .gt(lit(farad_min)) - .and(col("capacitance").lt(lit(farad_max))), - ); - let df_range = components_df_range.collect().unwrap(); - if df_range.height() >= 1 { - let df_range_sorted = sort_dataframe(df_range); - return Some((df_range_sorted, jlc_farad_value)); - } - - None -} +} \ No newline at end of file diff --git a/src/jlc/v1/jlc_searchers/jlc_find_inductor.rs b/src/jlc/v1/jlc_searchers/jlc_find_inductor.rs index f8c71fd..13dc5c8 100644 --- a/src/jlc/v1/jlc_searchers/jlc_find_inductor.rs +++ b/src/jlc/v1/jlc_searchers/jlc_find_inductor.rs @@ -1,73 +1,85 @@ -use polars::prelude::*; +use sqlx::PgPool; -use super::sort_dataframe; use crate::jlc::v1::jlc_models::*; +use crate::jlc::v1::jlc_part_finder::Component; -// inductors use Henry as unit (H) -pub fn find_inductor( - components_df: LazyFrame, +pub async fn find_inductor( + pool: PgPool, request: JLCPartRequest, -) -> Option<(DataFrame, JLCValue)> { - // filter components_df on category_id = 12 (inductors) - let mut components_df = components_df - .filter(col("category_id").eq(lit(12))) - .collect() - .unwrap() - .lazy(); +) -> Result<(Vec, JLCValue), sqlx::Error> { + // get + let inductor_category_id: (i32,) = sqlx::query_as("SELECT id FROM categories WHERE name = 'Inductors/Coils/Transformers' and subcategory_name = 'Inductors (SMD)'") + .fetch_one(&pool).await?; // value conversion - let (henry_multiplier, _henry_string) = match request.value.unit.as_str() { - "pH" | "picohenry" => (1.0, "pH"), - "nH" | "nanohenry" => (1e3, "nH"), - "μH" | "uH" | "microhenry" => (1e6, "μH"), - "mH" | "millihenry" => (1e9, "mH"), - "kH" | "kilohenry" => (1e15, "kH"), - "MH" | "megahenry" => (1e18, "MH"), - "H" | "henry" => (1e12, "H"), - _ => return None, + let henry_string = request.value.unit.to_string(); + let (henry_value, henry_max, henry_min) = match henry_string.as_str() { + "pH" | "picohenry" => ( + request.value.nominal, + request.value.nominal * (1.0 + request.value.tolerance_pct.unwrap_or(0.0) / 100.0), + request.value.nominal * (1.0 - request.value.tolerance_pct.unwrap_or(0.0) / 100.0), + ), + "nH" | "nanohenry" => ( + request.value.nominal * 1e3, + request.value.nominal * 1e3 * (1.0 + request.value.tolerance_pct.unwrap_or(0.0) / 100.0), + request.value.nominal * 1e3 * (1.0 - request.value.tolerance_pct.unwrap_or(0.0) / 100.0), + ), + "μH" | "uH" | "microhenry" => ( + request.value.nominal * 1e6, + request.value.nominal * 1e6 * (1.0 + request.value.tolerance_pct.unwrap_or(0.0) / 100.0), + request.value.nominal * 1e6 * (1.0 - request.value.tolerance_pct.unwrap_or(0.0) / 100.0), + ), + "mH" | "millihenry" => ( + request.value.nominal * 1e9, + request.value.nominal * 1e9 * (1.0 + request.value.tolerance_pct.unwrap_or(0.0) / 100.0), + request.value.nominal * 1e9 * (1.0 - request.value.tolerance_pct.unwrap_or(0.0) / 100.0), + ), + "kH" | "kilohenry" => ( + request.value.nominal * 1e15, + request.value.nominal * 1e15 * (1.0 + request.value.tolerance_pct.unwrap_or(0.0) / 100.0), + request.value.nominal * 1e15 * (1.0 - request.value.tolerance_pct.unwrap_or(0.0) / 100.0), + ), + "MH" | "megahenry" => ( + request.value.nominal * 1e18, + request.value.nominal * 1e18 * (1.0 + request.value.tolerance_pct.unwrap_or(0.0) / 100.0), + request.value.nominal * 1e18 * (1.0 - request.value.tolerance_pct.unwrap_or(0.0) / 100.0), + ), + "H" | "henry" => ( + request.value.nominal * 1e12, + request.value.nominal * 1e12 * (1.0 + request.value.tolerance_pct.unwrap_or(0.0) / 100.0), + request.value.nominal * 1e12 * (1.0 - request.value.tolerance_pct.unwrap_or(0.0) / 100.0), + ), + _ => return Err(sqlx::Error::RowNotFound), }; - let henry_value = (request.value.nominal * henry_multiplier).round(); - let henry_max = henry_value + henry_value * request.value.tolerance_pct / 100.0; - let henry_min = henry_value - henry_value * request.value.tolerance_pct / 100.0; - let jlc_henry_value = JLCValue { unit: "H".to_string(), - min_val: henry_min * 1e-12, - max_val: henry_max * 1e-12, - nominal: henry_value * 1e-12, + min_val: henry_min, + max_val: henry_max, + nominal: henry_value, tolerance: request.value.tolerance, - tolerance_pct: request.value.tolerance_pct, + tolerance_pct: Some(request.value.tolerance_pct.unwrap_or(0.0)), }; // if request.package is not None, filter components_df on package = request.package if request.package.is_some() { - components_df = components_df.filter(col("package").eq(lit(request.package.unwrap()))); - } - - // filter components_df on inductance = henry_value - let components_df_eq = components_df - .clone() - .filter(col("inductance").eq(lit(henry_value))); - - let df_eq = components_df_eq.collect().unwrap(); - if df_eq.height() >= 1 { - let df_eq_sorted = sort_dataframe(df_eq); - return Some((df_eq_sorted, jlc_henry_value)); + let mut matching_parts: Vec = sqlx::query_as!( + Component, + r#"SELECT id as "id!", lcsc as "lcsc!", category_id as "category_id!", mfr as "mfr?", package as "package?", joints as "joints!", manufacturer as "manufacturer!", basic as "basic!", description as "description?", datasheet as "datasheet?", stock as "stock!", price as "price?", last_update as "last_update!", inductance as "inductance?", capacitance, resistance, dielectric as "dielectric?", current, voltage FROM parts WHERE category_id = $1 and inductance between $2 and $3 and package = $4 ORDER BY basic DESC LIMIT 100"#, + inductor_category_id.0, + henry_min, + henry_max, + request.package.unwrap() + ).fetch_all(&pool).await?; + return Ok((matching_parts, jlc_henry_value)); + } else { + let mut matching_parts: Vec = sqlx::query_as!( + Component, + r#"SELECT id as "id!", lcsc as "lcsc!", category_id as "category_id!", mfr as "mfr?", package as "package?", joints as "joints!", manufacturer as "manufacturer!", basic as "basic!", description as "description?", datasheet as "datasheet?", stock as "stock!", price as "price?", last_update as "last_update!", inductance as "inductance?", capacitance, resistance, dielectric as "dielectric?", current, voltage FROM parts WHERE category_id = $1 and inductance between $2 and $3 ORDER BY basic DESC LIMIT 100"#, + inductor_category_id.0, + henry_min, + henry_max + ).fetch_all(&pool).await?; + return Ok((matching_parts, jlc_henry_value)); } - - // filter components_df on inductance > henry_min and inductance < henry_max - let components_df_range = components_df.filter( - col("inductance") - .gt(lit(henry_min)) - .and(col("inductance").lt(lit(henry_max))), - ); - - let df_range = components_df_range.collect().unwrap(); - if df_range.height() >= 1 { - let df_range_sorted = sort_dataframe(df_range); - return Some((df_range_sorted, jlc_henry_value)); - } - - None -} +} \ No newline at end of file diff --git a/src/jlc/v1/jlc_searchers/jlc_find_resistor.rs b/src/jlc/v1/jlc_searchers/jlc_find_resistor.rs index e6eebf4..57c7c56 100644 --- a/src/jlc/v1/jlc_searchers/jlc_find_resistor.rs +++ b/src/jlc/v1/jlc_searchers/jlc_find_resistor.rs @@ -1,65 +1,62 @@ -use polars::prelude::*; +use sqlx::PgPool; -use super::sort_dataframe; use crate::jlc::v1::jlc_models::*; +use crate::jlc::v1::jlc_part_finder::Component; -pub fn find_resistor( - components_df: LazyFrame, +pub async fn find_resistor( + pool: PgPool, request: JLCPartRequest, -) -> Option<(DataFrame, JLCValue)> { - // filter components_df on category_id = 46 - let mut components_df = components_df - .filter(col("category_id").eq(lit(46))) - .collect() - .unwrap() - .lazy(); +) -> Result<(Vec, JLCValue), sqlx::Error> { + // get + let resistor_category_id: (i32,) = sqlx::query_as("SELECT id FROM categories WHERE name = 'Resistors' and subcategory_name = 'Chip Resistor - Surface Mount'") + .fetch_one(&pool).await?; // value conversion let ohm_string = request.value.unit.to_string(); let (ohm_value, ohm_max, ohm_min, _ohm_multiplier) = match ohm_string.as_str() { "pΩ" | "picoohm" => ( request.value.nominal * 1e-12, - request.value.nominal * 1e-12 * (1.0 + request.value.tolerance_pct / 100.0), - request.value.nominal * 1e-12 * (1.0 - request.value.tolerance_pct / 100.0), + request.value.nominal * 1e-12 * (1.0 + request.value.tolerance_pct.unwrap_or(0.0) / 100.0), + request.value.nominal * 1e-12 * (1.0 - request.value.tolerance_pct.unwrap_or(0.0) / 100.0), 1e-12, ), "nΩ" | "nanoohm" => ( request.value.nominal * 1e-9, - request.value.nominal * 1e-9 * (1.0 + request.value.tolerance_pct / 100.0), - request.value.nominal * 1e-9 * (1.0 - request.value.tolerance_pct / 100.0), + request.value.nominal * 1e-9 * (1.0 + request.value.tolerance_pct.unwrap_or(0.0) / 100.0), + request.value.nominal * 1e-9 * (1.0 - request.value.tolerance_pct.unwrap_or(0.0) / 100.0), 1e-9, ), "μΩ" | "uΩ" | "microohm" => ( request.value.nominal * 1e-6, - request.value.nominal * 1e-6 * (1.0 + request.value.tolerance_pct / 100.0), - request.value.nominal * 1e-6 * (1.0 - request.value.tolerance_pct / 100.0), + request.value.nominal * 1e-6 * (1.0 + request.value.tolerance_pct.unwrap_or(0.0) / 100.0), + request.value.nominal * 1e-6 * (1.0 - request.value.tolerance_pct.unwrap_or(0.0) / 100.0), 1e-6, ), "mΩ" | "milliohm" => ( request.value.nominal * 1e-3, - request.value.nominal * 1e-3 * (1.0 + request.value.tolerance_pct / 100.0), - request.value.nominal * 1e-3 * (1.0 - request.value.tolerance_pct / 100.0), + request.value.nominal * 1e-3 * (1.0 + request.value.tolerance_pct.unwrap_or(0.0) / 100.0), + request.value.nominal * 1e-3 * (1.0 - request.value.tolerance_pct.unwrap_or(0.0) / 100.0), 1e-3, ), "kΩ" | "kiloohm" => ( request.value.nominal * 1e3, - request.value.nominal * 1e3 * (1.0 + request.value.tolerance_pct / 100.0), - request.value.nominal * 1e3 * (1.0 - request.value.tolerance_pct / 100.0), + request.value.nominal * 1e3 * (1.0 + request.value.tolerance_pct.unwrap_or(0.0) / 100.0), + request.value.nominal * 1e3 * (1.0 - request.value.tolerance_pct.unwrap_or(0.0) / 100.0), 1e3, ), "MΩ" | "megaohm" => ( request.value.nominal * 1e6, - request.value.nominal * 1e6 * (1.0 + request.value.tolerance_pct / 100.0), - request.value.nominal * 1e6 * (1.0 - request.value.tolerance_pct / 100.0), + request.value.nominal * 1e6 * (1.0 + request.value.tolerance_pct.unwrap_or(0.0) / 100.0), + request.value.nominal * 1e6 * (1.0 - request.value.tolerance_pct.unwrap_or(0.0) / 100.0), 1e6, ), "Ω" | "ohm" => ( request.value.nominal, - request.value.nominal * (1.0 + request.value.tolerance_pct / 100.0), - request.value.nominal * (1.0 - request.value.tolerance_pct / 100.0), + request.value.nominal * (1.0 + request.value.tolerance_pct.unwrap_or(0.0) / 100.0), + request.value.nominal * (1.0 - request.value.tolerance_pct.unwrap_or(0.0) / 100.0), 1.0, ), - _ => return None, + _ => return Err(sqlx::Error::RowNotFound), }; let jlc_ohm_value = JLCValue { @@ -68,37 +65,28 @@ pub fn find_resistor( max_val: ohm_max * 1e-12, nominal: ohm_value * 1e-12, tolerance: request.value.tolerance, - tolerance_pct: request.value.tolerance_pct, + tolerance_pct: Some(request.value.tolerance_pct.unwrap_or(0.0)), }; // if request.package is not None, filter components_df on package = request.package if request.package.is_some() { - components_df = components_df.filter(col("package").eq(lit(request.package.unwrap()))); + let mut matching_parts: Vec = sqlx::query_as!( + Component, + r#"SELECT id as "id!", lcsc as "lcsc!", category_id as "category_id!", mfr as "mfr?", package as "package?", joints as "joints!", manufacturer as "manufacturer!", basic as "basic!", description as "description?", datasheet as "datasheet?", stock as "stock!", price as "price?", last_update as "last_update!", resistance as "resistance?", inductance, capacitance, dielectric as "dielectric?", current, voltage FROM parts WHERE category_id = $1 and resistance between $2 and $3 and package = $4 ORDER BY basic DESC LIMIT 100"#, + resistor_category_id.0, + ohm_min, + ohm_max, + request.package.unwrap() + ).fetch_all(&pool).await?; + return Ok((matching_parts, jlc_ohm_value)); + } else { + let mut matching_parts: Vec = sqlx::query_as!( + Component, + r#"SELECT id as "id!", lcsc as "lcsc!", category_id as "category_id!", mfr as "mfr?", package as "package?", joints as "joints!", manufacturer as "manufacturer!", basic as "basic!", description as "description?", datasheet as "datasheet?", stock as "stock!", price as "price?", last_update as "last_update!", resistance as "resistance?", inductance, capacitance, dielectric as "dielectric?", current, voltage FROM parts WHERE category_id = $1 and resistance between $2 and $3 ORDER BY basic DESC LIMIT 100"#, + resistor_category_id.0, + ohm_min, + ohm_max + ).fetch_all(&pool).await?; + return Ok((matching_parts, jlc_ohm_value)); } - - // filter components_df on resistance = ohm_value - let components_df_eq = components_df - .clone() - .filter(col("resistance").eq(lit(ohm_value))); - - let df_eq = components_df_eq.clone().collect().unwrap(); - if df_eq.height() >= 1 { - let df_eq_sorted = sort_dataframe(df_eq); - return Some((df_eq_sorted, jlc_ohm_value)); - } - - // filter components_df on resistance > ohm_min and resistance < ohm_max - let components_df_range: LazyFrame = components_df.filter( - col("resistance") - .gt(lit(ohm_min)) - .and(col("resistance").lt(lit(ohm_max))), - ); - - let df_range = components_df_range.collect().unwrap(); - if df_range.height() >= 1 { - let df_range_sorted = sort_dataframe(df_range); - return Some((df_range_sorted, jlc_ohm_value)); - } - - None } diff --git a/src/main.rs b/src/main.rs index 38bafc8..4a593c5 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,16 +1,29 @@ use std::time::Duration; -use axum::{http::Request, http::Response, Router}; +use axum::{http::{Request, Response}, Extension, Router}; use polars::prelude::*; +use sqlx::postgres::PgPoolOptions; use tower_http::trace::TraceLayer; use tracing::{info_span, Span}; use tracing_subscriber::prelude::*; use utoipa::OpenApi; use utoipa_swagger_ui::SwaggerUi; use utoipauto::utoipauto; +use clap::Parser; +use dotenv::dotenv; pub mod jlc; + +/// Simple program to greet a person +#[derive(Parser, Debug)] +#[command(version, about, long_about = None)] +struct Args { + /// DB_URI + #[arg(short, long, env)] + database_url: String, +} + #[utoipauto] #[derive(OpenApi)] #[openapi(info(title = "JLCPCB Part Selector API", version = "1.0.0"))] @@ -26,9 +39,14 @@ pub struct AppState { #[tokio::main] async fn main() { + // load .env file + dotenv().ok(); + // initialize tracing let _filter = "atopile-jlc-parts=debug"; + let args = Args::parse(); + // initialize tracing tracing_subscriber::registry() // .with(fmt::layer()) @@ -47,11 +65,19 @@ async fn main() { .unwrap(), }; + // set up connection pool + let pool_extension = PgPoolOptions::new() + .max_connections(40) + .connect(args.database_url.as_str()) + .await + .expect("unable to open db connection"); + // build our application with a route let app = Router::new() .merge(SwaggerUi::new("/docs").url("/docs/openapi.json", ApiDoc::openapi())) .with_state(app_state.clone()) .nest("/jlc", jlc::router().with_state(app_state)) + .layer(Extension(pool_extension)) .layer( TraceLayer::new_for_http() .make_span_with(|_request: &Request<_>| info_span!("http_request"))