Compare commits
46 Commits
7a22b52c91
...
dev
| Author | SHA1 | Date | |
|---|---|---|---|
| c35726bf5c | |||
| e82208fc5e | |||
| 9bdca3317c | |||
| 61abd44328 | |||
| acb9876d9b | |||
| 10d88f53eb | |||
| bba0aa2ee4 | |||
| b7773ec02a | |||
| b9dd6e3ae2 | |||
| f940bcdc9d | |||
| 2ae3c8ba59 | |||
| 97b9c4db4a | |||
| d8eddafcae | |||
| 58b58424ab | |||
| 72d52d9256 | |||
| 5dfece09b7 | |||
| 97eb73c6d1 | |||
| bb6d523abb | |||
| 09d3a7041a | |||
| 132e8d0146 | |||
| d0a0d08902 | |||
| 208cd615af | |||
| e82ef76316 | |||
| 4db4eea2d1 | |||
| edcfff6cc6 | |||
| 61860c759e | |||
| 08c9b3404f | |||
| 93ed2e9ee8 | |||
| fb9ee15bda | |||
| 76bc0db3dd | |||
| 2e5de34cb5 | |||
| 07e47e64ae | |||
| 73eb70538e | |||
| 8b8c9acb69 | |||
| cb3ab668d8 | |||
| f6654067f5 | |||
| 532a722763 | |||
| 38d1043606 | |||
| 18daca904e | |||
| e833c48cc8 | |||
| 0bd217c727 | |||
| 74974323f0 | |||
| f3c4c26ef9 | |||
| 74bcd6e805 | |||
| eb2c34c557 | |||
| 808e3d84ef |
@@ -8,7 +8,8 @@
|
||||
{ "type": "refactor", "section": "🛠️ Code Refactor" },
|
||||
{ "type": "perf", "hidden": false, "section": "🚀 Performance" },
|
||||
{ "type": "test", "section": "📝 Testing Code" },
|
||||
{"type": "ci", "section": "📈 Project changes"}
|
||||
{ "type": "ci", "hidden": false, "section": "📈 Project changes" },
|
||||
{ "type": "build", "hidden": true, "section": "📈 Project Builds" }
|
||||
],
|
||||
"commitUrlFormat": "https://git.tuffraid.net/cowch/lstV2/commits/{{hash}}",
|
||||
"compareUrlFormat": "https://git.tuffraid.net/cowch/lstV2/compare/{{previousTag}}...{{currentTag}}",
|
||||
|
||||
26
.vscode/settings.json
vendored
Normal file
26
.vscode/settings.json
vendored
Normal file
@@ -0,0 +1,26 @@
|
||||
{
|
||||
"editor.defaultFormatter": "esbenp.prettier-vscode",
|
||||
|
||||
"editor.formatOnSave": true,
|
||||
"[javascript]": {
|
||||
"editor.formatOnSave": true
|
||||
},
|
||||
"[javascriptreact]": {
|
||||
"editor.formatOnSave": true
|
||||
},
|
||||
"[typescript]": {
|
||||
"editor.formatOnSave": true
|
||||
},
|
||||
"[typescriptreact]": {
|
||||
"editor.formatOnSave": true
|
||||
},
|
||||
"[json]": {
|
||||
"editor.formatOnSave": true
|
||||
},
|
||||
"[graphql]": {
|
||||
"editor.formatOnSave": true
|
||||
},
|
||||
"[handlebars]": {
|
||||
"editor.formatOnSave": true
|
||||
}
|
||||
}
|
||||
125
CHANGELOG.md
125
CHANGELOG.md
@@ -1,5 +1,130 @@
|
||||
# All CHanges to LST can be found below.
|
||||
|
||||
## [2.9.0](https://git.tuffraid.net/cowch/lstV2/compare/v2.8.0...v2.9.0) (2025-03-23)
|
||||
|
||||
|
||||
### 📈 Project changes
|
||||
|
||||
* **frontend:** added ocme as a proxy in the dev ([eb2c34c](https://git.tuffraid.net/cowch/lstV2/commits/eb2c34c557b72c3387b70addac30a4d8291402d4))
|
||||
|
||||
|
||||
### 📚 Documentation
|
||||
|
||||
* **install:** added more env params and an install install stuff ([09d3a70](https://git.tuffraid.net/cowch/lstV2/commits/09d3a7041a18283a5add86ea845a8d7249522769))
|
||||
* **install:** removed the super secret key ([357c118](https://git.tuffraid.net/cowch/lstV2/commits/357c1183964be0f3c02207c24bc8f83347282211))
|
||||
* **logs:** changes how logs are put into the db they will be there name vs key ([18daca9](https://git.tuffraid.net/cowch/lstV2/commits/18daca904e0305371c6128988b48d54e3aec9a2a))
|
||||
* **migration:** added more documents on the install md ([0bd217c](https://git.tuffraid.net/cowch/lstV2/commits/0bd217c727d726d62ddf06a0e44e95c4606361cf))
|
||||
|
||||
|
||||
### 📝 Testing Code
|
||||
|
||||
* **ocme:** cycle count intital improvements ([7a22b52](https://git.tuffraid.net/cowch/lstV2/commits/7a22b52c916335c748598b82e78819c325bb8c4c))
|
||||
* **ocp dash:** more work on the dashboard ([f3c4c26](https://git.tuffraid.net/cowch/lstV2/commits/f3c4c26ef957e6fe359a77f139ad36cdacefb8ef))
|
||||
* **ocp:** more work on the dashboard ([8324fff](https://git.tuffraid.net/cowch/lstV2/commits/8324fffeb664bff3751ffc26e988a4a506b658a9))
|
||||
* **returnres:** tryed to make a standard return res but will come back to this later ([58b5842](https://git.tuffraid.net/cowch/lstV2/commits/58b58424abbf98feec0c5442a59f4d055bbd1811))
|
||||
* **rfid:** more work on the rfid service ([21c3749](https://git.tuffraid.net/cowch/lstV2/commits/21c374903b5cba56ced44b7eb2066ee902fc7bc3))
|
||||
* **server:** start/stop/restart buttons added. comment [#14](https://git.tuffraid.net/cowch/lstV2/issues/14) ([76bc0db](https://git.tuffraid.net/cowch/lstV2/commits/76bc0db3dd9c48b69e4f6f571181a1f07c48bdeb))
|
||||
* **streaming logs:** more test but failed again ([08c9b34](https://git.tuffraid.net/cowch/lstV2/commits/08c9b3404f548a167464445ec2f19288a092b0dc))
|
||||
* **streaming logs:** test for streaming logs ([73eb705](https://git.tuffraid.net/cowch/lstV2/commits/73eb70538e36601cf436aaba244f99d5bd873d34))
|
||||
* **streaming logs:** will come back to this later this is killing me inside ([97eb73c](https://git.tuffraid.net/cowch/lstV2/commits/97eb73c6d1aef747ef98f5f666fe47622795746f))
|
||||
* **streaming:** more streaming test ([4db4eea](https://git.tuffraid.net/cowch/lstV2/commits/4db4eea2d12e37809879e96ed4279d6e23e83acc))
|
||||
* **streaming:** more testing on streaming the lofs ([e82ef76](https://git.tuffraid.net/cowch/lstV2/commits/e82ef76316f0562b57124eb977c86fd2c6a3f332))
|
||||
|
||||
|
||||
### 🌟 Enhancements
|
||||
|
||||
* **admincheck:** this check is so we dont use stuff on the wrong servers ([3d08398](https://git.tuffraid.net/cowch/lstV2/commits/3d083986aed528c2f881d6f673c0be03b8986c0b))
|
||||
* **auth:** add, update were added for adm account in backend only ([d8eddaf](https://git.tuffraid.net/cowch/lstV2/commits/d8eddafcaea9141e9413a122a320649c7dd325e5))
|
||||
* **auth:** remove all old localstorage if no session ([8fb06c7](https://git.tuffraid.net/cowch/lstV2/commits/8fb06c71d370a27697628077474a261596b567e0))
|
||||
* **db:** logs, manualprints added ([0914b53](https://git.tuffraid.net/cowch/lstV2/commits/0914b5334119fa705eedddc6c9e8303cb82da551))
|
||||
* **installer:** added a check for lstv2 already installed ([4696835](https://git.tuffraid.net/cowch/lstV2/commits/4696835c6557c2eae3be6a292144493be9d98f67))
|
||||
* **logger:** logger service created with its endpoints ([7ec5c5b](https://git.tuffraid.net/cowch/lstV2/commits/7ec5c5beb0a9b02e8b8761908ee75ac2cfd317ee))
|
||||
* **logger:** streaming logs works server side not frontend for now ([e833c48](https://git.tuffraid.net/cowch/lstV2/commits/e833c48cc8f68af40888ea161100e02f6ad19604))
|
||||
* **lst:** added in delay global function ([7497432](https://git.tuffraid.net/cowch/lstV2/commits/74974323f0a7bd7c2eaa22024b7a8e91db2868e2))
|
||||
* **lst:** added prettier config so we have the same formatting across all computers ([132e8d0](https://git.tuffraid.net/cowch/lstV2/commits/132e8d0146318fa9deb673bbcabf0d80c2a6d39f))
|
||||
* **ocme:** added in ocme service so we can utlize 2 ports ([ae7e3fd](https://git.tuffraid.net/cowch/lstV2/commits/ae7e3fd54e5c256fb82e68f2e935e3b914e43d13))
|
||||
* **ocme:** cycle count implemeneted ([74bcd6e](https://git.tuffraid.net/cowch/lstV2/commits/74bcd6e805c34e181f0c48310a799daf3afaee66))
|
||||
* **ocmeserver:** the server was just migrated so it can be upgraded to lstv2 ([e258aae](https://git.tuffraid.net/cowch/lstV2/commits/e258aaead9a56cc4de36c17ed60b0bdaa91019cb))
|
||||
* **ocp:** added in service plus manual print log ([7165c95](https://git.tuffraid.net/cowch/lstV2/commits/7165c959b9d5b37c0d4b01cb3f5bc27b40cec71d))
|
||||
* **ports:** added in production port if in production ([121bed5](https://git.tuffraid.net/cowch/lstV2/commits/121bed59fda04b2ad134feb0895428515a1c56d8))
|
||||
* **scripts:** made moving scripts more proper ([d0a0d08](https://git.tuffraid.net/cowch/lstV2/commits/d0a0d0890255acf890ba402386847b19566c92df))
|
||||
* **serverdata:** added in huston, sherman. and corrected contact info in westbend ([4908d66](https://git.tuffraid.net/cowch/lstV2/commits/4908d6644a392395e660d382536c0fd31e3d0647))
|
||||
* **server:** ocpService and loggerService added ([2d3f308](https://git.tuffraid.net/cowch/lstV2/commits/2d3f30887744bddfe22dc764188cf727a5e476df))
|
||||
* **servers:** added dayton in ([bbd7a17](https://git.tuffraid.net/cowch/lstV2/commits/bbd7a17144e1e1a0faa192139cb1539c2f1ecc5c))
|
||||
* **settings:** added in setting store ([1cd1d3a](https://git.tuffraid.net/cowch/lstV2/commits/1cd1d3a3e9e1ec1bf16ac2552caf24aa299959bf))
|
||||
* **settings:** more seed settings ([e597968](https://git.tuffraid.net/cowch/lstV2/commits/e597968777e88289d361fdc01ec683a1f4c80192))
|
||||
* **trycatch:** added in theo's try catch to reduce the code and love it ([72d52d9](https://git.tuffraid.net/cowch/lstV2/commits/72d52d925677eeeac6d158028114201862b6e2a2))
|
||||
|
||||
|
||||
### 🛠️ Code Refactor
|
||||
|
||||
* **auth:** added in correct bycrptjs ([208cd61](https://git.tuffraid.net/cowch/lstV2/commits/208cd615af8250686745aa5b6779706ae267e423))
|
||||
* **auth:** moved prod back to server as we run 2 instances during migration ([7a15b16](https://git.tuffraid.net/cowch/lstV2/commits/7a15b160ac2393cd66a932e598ffaa5aeda5812f))
|
||||
* **consume materail:** get token from localstorage as the store isnt wokring properly ([354f326](https://git.tuffraid.net/cowch/lstV2/commits/354f3260a55b53bfb461a37db9d64550bacbfe04))
|
||||
* **frontend:** added date-fns into the frontend ([bba0aa2](https://git.tuffraid.net/cowch/lstV2/commits/bba0aa2ee4e9b9be1db184da894ce6e96fd2e38f))
|
||||
* **login:** removed all the data from teh login dropdown as it could cause issues ([5dfece0](https://git.tuffraid.net/cowch/lstV2/commits/5dfece09b7285dda96875bbc740df803d816b92a))
|
||||
* **login:** removed roles from the login to shrink the jwt ([c9aa41a](https://git.tuffraid.net/cowch/lstV2/commits/c9aa41ab0099b7a05d50d9a981cf7e8a42a04733))
|
||||
* **production:** changes ocp to viewwer ([ab5af4d](https://git.tuffraid.net/cowch/lstV2/commits/ab5af4deacbeaf1ed93c6231fb98b187f7540ca4))
|
||||
* **server query:** bumped the refresh from 500ms to 2500ms ([866b6d5](https://git.tuffraid.net/cowch/lstV2/commits/866b6d5120810252b089580d341f3fb1b62e951a))
|
||||
* **serverdata:** remapped the server list to all be on the E drive and deactivated ([8b8c9ac](https://git.tuffraid.net/cowch/lstV2/commits/8b8c9acb6969b63f157ea95b7d61923bf4bb4eae))
|
||||
* **server:** removed the websocket wrapper going wiht normal ws ([bb6d523](https://git.tuffraid.net/cowch/lstV2/commits/bb6d523abbd3c9423eddbaab96e297b4850e2aa8))
|
||||
* **settings:** refactored the admincheck so we can reuse it ([ca0ba7f](https://git.tuffraid.net/cowch/lstV2/commits/ca0ba7fe59f7e19d0de4924a419cce461de4b7a1))
|
||||
* **settings:** removed the need to login to get the settings ([5945ace](https://git.tuffraid.net/cowch/lstV2/commits/5945ace9f259f6ef418c1621c246982b5b572dc1))
|
||||
* **settings:** used the common response function created ([316b27e](https://git.tuffraid.net/cowch/lstV2/commits/316b27e3e011a0c0b4ce88ea579290807b8927c5))
|
||||
* **stores:** added in axios ([3b8f180](https://git.tuffraid.net/cowch/lstV2/commits/3b8f18093ead2a988b2b19d1e8f25db6eaeaaee8))
|
||||
* **view access:** if role [] then allow them to see it ([e17b8e7](https://git.tuffraid.net/cowch/lstV2/commits/e17b8e7bbe94c25c1bd3414b1db31191c87553d6))
|
||||
|
||||
|
||||
### 🐛 Bug fixes
|
||||
|
||||
* **auth:** added in the correct function for days between logins ([ed11b2b](https://git.tuffraid.net/cowch/lstV2/commits/ed11b2b26ff80fde9f94615f740eb5152b16744d))
|
||||
* **auth:** fixed the getaccess to be getuseraccess as it was orignally ([b9dd6e3](https://git.tuffraid.net/cowch/lstV2/commits/b9dd6e3ae2f5c158dd4827ae0c9db2c6747c57e1))
|
||||
* **calendar:** this component had a bug and needed a lib update ([93ed2e9](https://git.tuffraid.net/cowch/lstV2/commits/93ed2e9ee8c98edd6a8c47d6e7a0caf6a8e93278))
|
||||
* **consume material:** when we consumed material the button was never reenabled ([07e47e6](https://git.tuffraid.net/cowch/lstV2/commits/07e47e64ae2f4ddd325a2fdb34c82143c9adf84b)), closes [#15](https://git.tuffraid.net/cowch/lstV2/issues/15)
|
||||
* **frontend:** removed unwanted import ([10d88f5](https://git.tuffraid.net/cowch/lstV2/commits/10d88f53ebaf670c9f6b3ca59cbbaf4d88f26b9f))
|
||||
* **loginform:** removed the console log that was left by accident ([2ae3c8b](https://git.tuffraid.net/cowch/lstV2/commits/2ae3c8ba5916b5249135b86b374ac1bf32837478))
|
||||
* **login:** if we have a wrong password or username we didnt properly error instead we crashed ([2e5de34](https://git.tuffraid.net/cowch/lstV2/commits/2e5de34cb50c79cd60e038492b2397eee69def11))
|
||||
* **scaler:** fix due to update ([edcfff6](https://git.tuffraid.net/cowch/lstV2/commits/edcfff6cc6cf81e56b5532f0876383659b951a5d))
|
||||
* **serverlist:** corrected the time by removing teh Z at the end of the time ([f940bcd](https://git.tuffraid.net/cowch/lstV2/commits/f940bcdc9df2d3e9989d49feae88036a6f8c7013))
|
||||
* **sqlserver:** if we already have a connection just return we dont want to try a second time ([b7773ec](https://git.tuffraid.net/cowch/lstV2/commits/b7773ec02aa26c01530723dc146e0c9f4dae41d3))
|
||||
|
||||
|
||||
### 📝 Chore
|
||||
|
||||
* **builds:** bummped lstv1 build ([739e6bb](https://git.tuffraid.net/cowch/lstV2/commits/739e6bbe9fa48fae682f9931a2c8bcb763feb636))
|
||||
* bump build number to 20 ([0975f4e](https://git.tuffraid.net/cowch/lstV2/commits/0975f4e499a8a2aec0662352cb4496299292d4ea))
|
||||
* bump build number to 21 ([4e885ce](https://git.tuffraid.net/cowch/lstV2/commits/4e885ce74c02ee1fd95a93402d1d32ecf357b1cb))
|
||||
* bump build number to 22 ([43ca16d](https://git.tuffraid.net/cowch/lstV2/commits/43ca16dc807b9fa3496498e90a871568f0e5f54c))
|
||||
* bump build number to 23 ([bff0e77](https://git.tuffraid.net/cowch/lstV2/commits/bff0e77766b49c72d77fa55cfaab2d347a1a75dc))
|
||||
* bump build number to 24 ([f4433f4](https://git.tuffraid.net/cowch/lstV2/commits/f4433f41926dab72a239fc585ddd1e14acb80c7e))
|
||||
* bump build number to 25 ([f1979f0](https://git.tuffraid.net/cowch/lstV2/commits/f1979f0fc914f3b94bad1816cd405a6431d1ba4a))
|
||||
* bump build number to 26 ([491de26](https://git.tuffraid.net/cowch/lstV2/commits/491de26a0bbe6dfca9e1cb068991789c29a09ac0))
|
||||
* bump build number to 27 ([26ea8d5](https://git.tuffraid.net/cowch/lstV2/commits/26ea8d5e89bb1b44ceb6b205da3ad158c603fca0))
|
||||
* bump build number to 28 ([1e02d4f](https://git.tuffraid.net/cowch/lstV2/commits/1e02d4fa4fc1a007634da49fe2697d63c89cba18))
|
||||
* bump build number to 29 ([9796947](https://git.tuffraid.net/cowch/lstV2/commits/9796947db5443c8b5678d7502037458d680e4018))
|
||||
* bump build number to 30 ([4a48dd2](https://git.tuffraid.net/cowch/lstV2/commits/4a48dd2bb57064953ef6e192c76b91bb844a24de))
|
||||
* bump build number to 31 ([227e2aa](https://git.tuffraid.net/cowch/lstV2/commits/227e2aa00c2a3e5526e0347c76676de345dfea5d))
|
||||
* bump build number to 32 ([f035e6f](https://git.tuffraid.net/cowch/lstV2/commits/f035e6f14a9e2123a10010d4f515f78f0c222599))
|
||||
* bump build number to 33 ([03aa7e5](https://git.tuffraid.net/cowch/lstV2/commits/03aa7e5aeee39b1b390b4da2019f44459487e0a0))
|
||||
* bump build number to 34 ([f4c44fb](https://git.tuffraid.net/cowch/lstV2/commits/f4c44fb02ba857890af66a2747381ef1c3def25b))
|
||||
* bump build number to 35 ([8b72a1b](https://git.tuffraid.net/cowch/lstV2/commits/8b72a1b47e715f4146e586e9fdd6abcabd97743d))
|
||||
* bump build number to 36 ([8a143fb](https://git.tuffraid.net/cowch/lstV2/commits/8a143fbb19d2270b0139a7a4edbce745c477b6b1))
|
||||
* bump build number to 37 ([b0634d9](https://git.tuffraid.net/cowch/lstV2/commits/b0634d9427f6fff3a239680204b5e6daf6163e37))
|
||||
* bump build number to 38 ([751b9d5](https://git.tuffraid.net/cowch/lstV2/commits/751b9d5701cf7e81641f154a02041869e1b80c49))
|
||||
* bump build number to 39 ([6dd5f4b](https://git.tuffraid.net/cowch/lstV2/commits/6dd5f4b61f3a27779980cf14915c4394256eae20))
|
||||
* bump build number to 40 ([d98a659](https://git.tuffraid.net/cowch/lstV2/commits/d98a6592628f36c654039ccea25db163ddf15e8c))
|
||||
* bump build number to 41 ([807a4ca](https://git.tuffraid.net/cowch/lstV2/commits/807a4ca6993b5dfa82a45aaf44a2d661c3e03428))
|
||||
* bump build number to 42 ([196ea00](https://git.tuffraid.net/cowch/lstV2/commits/196ea009720a65c520f5626658ac7885a41796cb))
|
||||
* bump build number to 43 ([34b80cf](https://git.tuffraid.net/cowch/lstV2/commits/34b80cf2368228b70cd6a79d44ba0f95b5c5941a))
|
||||
* bump build number to 44 ([808e3d8](https://git.tuffraid.net/cowch/lstV2/commits/808e3d84efa0889077a12cbf8e28df794a51f2bc))
|
||||
* bump build number to 45 ([38d1043](https://git.tuffraid.net/cowch/lstV2/commits/38d10436069d3db1612a622d9b9e0c7aec04f6dd))
|
||||
* bump build number to 46 ([532a722](https://git.tuffraid.net/cowch/lstV2/commits/532a7227631cf67664ca41133330d8cfa59f429b))
|
||||
* bump build number to 47 ([f665406](https://git.tuffraid.net/cowch/lstV2/commits/f6654067f5f01c3ee4855f0cbe07593f13263ce7))
|
||||
* bump build number to 48 ([97b9c4d](https://git.tuffraid.net/cowch/lstV2/commits/97b9c4db4a67faf68edae4dc1217b28f87d003e8))
|
||||
* bump build number to 49 ([acb9876](https://git.tuffraid.net/cowch/lstV2/commits/acb9876d9b715894481d31d9bb104e54561710d0))
|
||||
* **pkg updates:** updated all pkgs ([fb9ee15](https://git.tuffraid.net/cowch/lstV2/commits/fb9ee15bda89257815012023ed5543ef55b5f379))
|
||||
* **updatescript:** added in so we can do a full install with an env creation for old ([cb3ab66](https://git.tuffraid.net/cowch/lstV2/commits/cb3ab668d866ea9e3428e548d9065a9681174e82))
|
||||
|
||||
## [2.8.0](https://git.tuffraid.net/cowch/lstV2/compare/v2.7.0...v2.8.0) (2025-03-16)
|
||||
|
||||
|
||||
|
||||
2
database/migrations/0025_amusing_sugar_man.sql
Normal file
2
database/migrations/0025_amusing_sugar_man.sql
Normal file
@@ -0,0 +1,2 @@
|
||||
DROP TABLE "apiHits" CASCADE;--> statement-breakpoint
|
||||
DROP TABLE "eom" CASCADE;
|
||||
1056
database/migrations/meta/0025_snapshot.json
Normal file
1056
database/migrations/meta/0025_snapshot.json
Normal file
File diff suppressed because it is too large
Load Diff
@@ -176,6 +176,13 @@
|
||||
"when": 1742408812383,
|
||||
"tag": "0024_curved_venom",
|
||||
"breakpoints": true
|
||||
},
|
||||
{
|
||||
"idx": 25,
|
||||
"version": "7",
|
||||
"when": 1742655504936,
|
||||
"tag": "0025_amusing_sugar_man",
|
||||
"breakpoints": true
|
||||
}
|
||||
]
|
||||
}
|
||||
785
frontend/package-lock.json
generated
785
frontend/package-lock.json
generated
File diff suppressed because it is too large
Load Diff
@@ -12,7 +12,7 @@
|
||||
"checkupdates": "npm-check-updates"
|
||||
},
|
||||
"dependencies": {
|
||||
"@hookform/resolvers": "^4.1.2",
|
||||
"@hookform/resolvers": "^4.1.3",
|
||||
"@radix-ui/react-avatar": "^1.1.3",
|
||||
"@radix-ui/react-checkbox": "^1.1.4",
|
||||
"@radix-ui/react-collapsible": "^1.1.3",
|
||||
@@ -25,46 +25,47 @@
|
||||
"@radix-ui/react-slot": "^1.1.2",
|
||||
"@radix-ui/react-tabs": "^1.1.3",
|
||||
"@radix-ui/react-tooltip": "^1.1.8",
|
||||
"@tailwindcss/vite": "^4.0.9",
|
||||
"@tanstack/react-query": "^5.66.9",
|
||||
"@tanstack/react-router": "^1.111.11",
|
||||
"@tailwindcss/vite": "^4.0.15",
|
||||
"@tanstack/react-query": "^5.69.0",
|
||||
"@tanstack/react-router": "^1.114.27",
|
||||
"@tanstack/react-table": "^8.21.2",
|
||||
"class-variance-authority": "^0.7.1",
|
||||
"clsx": "^2.1.1",
|
||||
"date-fns": "^4.1.0",
|
||||
"date-fns-tz": "^3.2.0",
|
||||
"dotenv": "^16.4.7",
|
||||
"hono": "^4.7.2",
|
||||
"hono": "^4.7.5",
|
||||
"js-cookie": "^3.0.5",
|
||||
"jsonwebtoken": "^9.0.2",
|
||||
"lucide-react": "^0.476.0",
|
||||
"next-themes": "^0.4.4",
|
||||
"npm-check-updates": "^17.1.15",
|
||||
"lucide-react": "^0.483.0",
|
||||
"next-themes": "^0.4.6",
|
||||
"npm-check-updates": "^17.1.16",
|
||||
"react": "^19.0.0",
|
||||
"react-day-picker": "^8.10.1",
|
||||
"react-dom": "^19.0.0",
|
||||
"react-grid-layout": "^1.5.0",
|
||||
"react-grid-layout": "^1.5.1",
|
||||
"react-hook-form": "^7.54.2",
|
||||
"sonner": "^2.0.1",
|
||||
"tailwind-merge": "^3.0.2",
|
||||
"tailwindcss": "^4.0.9",
|
||||
"tailwindcss": "^4.0.15",
|
||||
"tailwindcss-animate": "^1.0.7",
|
||||
"zod": "^3.24.2",
|
||||
"zustand": "^5.0.3"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@eslint/js": "^9.21.0",
|
||||
"@tanstack/router-devtools": "^1.106.0",
|
||||
"@tanstack/router-plugin": "^1.106.0",
|
||||
"@types/react": "^19.0.10",
|
||||
"@eslint/js": "^9.23.0",
|
||||
"@tanstack/router-devtools": "^1.114.27",
|
||||
"@tanstack/router-plugin": "^1.114.27",
|
||||
"@types/react": "^19.0.12",
|
||||
"@types/react-dom": "^19.0.4",
|
||||
"@types/react-grid-layout": "^1.3.5",
|
||||
"@vitejs/plugin-react-swc": "^3.8.0",
|
||||
"eslint": "^9.21.0",
|
||||
"eslint-plugin-react-hooks": "^5.0.0",
|
||||
"@vitejs/plugin-react-swc": "^3.8.1",
|
||||
"eslint": "^9.23.0",
|
||||
"eslint-plugin-react-hooks": "^5.2.0",
|
||||
"eslint-plugin-react-refresh": "^0.4.19",
|
||||
"globals": "^15.15.0",
|
||||
"typescript": "~5.7.2",
|
||||
"typescript-eslint": "^8.24.1",
|
||||
"vite": "^6.2.0"
|
||||
"globals": "^16.0.0",
|
||||
"typescript": "~5.8.2",
|
||||
"typescript-eslint": "^8.27.0",
|
||||
"vite": "^6.2.2"
|
||||
}
|
||||
}
|
||||
|
||||
22
frontend/src/components/admin/servers/RestartServer.tsx
Normal file
22
frontend/src/components/admin/servers/RestartServer.tsx
Normal file
@@ -0,0 +1,22 @@
|
||||
import {Button} from "@/components/ui/button";
|
||||
import {Tooltip, TooltipContent, TooltipProvider, TooltipTrigger} from "@/components/ui/tooltip";
|
||||
import {RotateCcw} from "lucide-react";
|
||||
|
||||
export default function RestartServer() {
|
||||
return (
|
||||
<div>
|
||||
<TooltipProvider>
|
||||
<Tooltip>
|
||||
<TooltipTrigger asChild>
|
||||
<Button variant={"outline"} size={"icon"}>
|
||||
<RotateCcw />
|
||||
</Button>
|
||||
</TooltipTrigger>
|
||||
<TooltipContent>
|
||||
<p>Restart Server ... Needs added still</p>
|
||||
</TooltipContent>
|
||||
</Tooltip>
|
||||
</TooltipProvider>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
@@ -1,7 +1,13 @@
|
||||
import { LstCard } from "@/components/extendedUI/LstCard";
|
||||
|
||||
import { Skeleton } from "@/components/ui/skeleton";
|
||||
import {Table, TableBody, TableCell, TableHead, TableHeader, TableRow} from "@/components/ui/table";
|
||||
import {
|
||||
Table,
|
||||
TableBody,
|
||||
TableCell,
|
||||
TableHead,
|
||||
TableHeader,
|
||||
TableRow,
|
||||
} from "@/components/ui/table";
|
||||
import { useSessionStore } from "@/lib/store/sessionStore";
|
||||
import { useModuleStore } from "@/lib/store/useModuleStore";
|
||||
import { getServers } from "@/utils/querys/servers";
|
||||
@@ -10,6 +16,9 @@ import {useRouter} from "@tanstack/react-router";
|
||||
import { format } from "date-fns";
|
||||
import UpdateServer from "./UpdateServer";
|
||||
import { adminUrlCheck } from "@/utils/adminUrlCheck";
|
||||
import RestartServer from "./RestartServer";
|
||||
import StopServer from "./StopServer";
|
||||
import StartServer from "./StartServer";
|
||||
|
||||
export type Servers = {
|
||||
server_id?: string;
|
||||
@@ -29,7 +38,8 @@ export default function ServerPage() {
|
||||
const { data, isError, error, isLoading } = useQuery(getServers(token ?? ""));
|
||||
|
||||
const adminModule = modules.filter((n) => n.name === "admin");
|
||||
const userLevel = user?.roles?.filter((r) => r.module_id === adminModule[0].module_id) || [];
|
||||
const userLevel =
|
||||
user?.roles?.filter((r) => r.module_id === adminModule[0].module_id) || [];
|
||||
|
||||
if (!adminModule[0]?.roles?.includes(userLevel[0]?.role)) {
|
||||
router.navigate({ to: "/" });
|
||||
@@ -38,6 +48,8 @@ export default function ServerPage() {
|
||||
if (isError) {
|
||||
return <div>{JSON.stringify(error)}</div>;
|
||||
}
|
||||
|
||||
console.log(data);
|
||||
return (
|
||||
<LstCard className="m-2 flex place-content-center w-dvh">
|
||||
<Table>
|
||||
@@ -76,20 +88,35 @@ export default function ServerPage() {
|
||||
</>
|
||||
) : (
|
||||
<TableBody>
|
||||
{data?.map((server: Servers) => (
|
||||
{data?.map((server: Servers) => {
|
||||
const strippedDate = server.lastUpdated.replace("Z", ""); // Remove Z
|
||||
const formattedDate = format(strippedDate, "MM/dd/yyyy hh:mm a");
|
||||
return (
|
||||
<TableRow key={server.server_id}>
|
||||
<TableCell className="font-medium">{server.sName}</TableCell>
|
||||
<TableCell className="font-medium">{server.serverDNS}</TableCell>
|
||||
<TableCell className="font-medium">{server.plantToken}</TableCell>
|
||||
<TableCell className="font-medium">{server.idAddress}</TableCell>
|
||||
<TableCell className="font-medium">
|
||||
{format(server.lastUpdated, "MM/dd/yyyy hh:mm")}
|
||||
{server.serverDNS}
|
||||
</TableCell>
|
||||
<TableCell className="font-medium">
|
||||
{adminUrlCheck() && <UpdateServer server={server} token={token as string} />}
|
||||
{server.plantToken}
|
||||
</TableCell>
|
||||
<TableCell className="font-medium">
|
||||
{server.idAddress}
|
||||
</TableCell>
|
||||
<TableCell className="font-medium">{formattedDate}</TableCell>
|
||||
<TableCell className="font-medium">
|
||||
{adminUrlCheck() && (
|
||||
<div className="flex flex-row">
|
||||
<UpdateServer server={server} token={token as string} />
|
||||
<StartServer />
|
||||
<StopServer />
|
||||
<RestartServer />
|
||||
</div>
|
||||
)}
|
||||
</TableCell>
|
||||
</TableRow>
|
||||
))}
|
||||
);
|
||||
})}
|
||||
</TableBody>
|
||||
)}
|
||||
</Table>
|
||||
|
||||
22
frontend/src/components/admin/servers/StartServer.tsx
Normal file
22
frontend/src/components/admin/servers/StartServer.tsx
Normal file
@@ -0,0 +1,22 @@
|
||||
import {Button} from "@/components/ui/button";
|
||||
import {Tooltip, TooltipContent, TooltipProvider, TooltipTrigger} from "@/components/ui/tooltip";
|
||||
import {Play} from "lucide-react";
|
||||
|
||||
export default function StartServer() {
|
||||
return (
|
||||
<div>
|
||||
<TooltipProvider>
|
||||
<Tooltip>
|
||||
<TooltipTrigger asChild>
|
||||
<Button variant={"outline"} size={"icon"}>
|
||||
<Play />
|
||||
</Button>
|
||||
</TooltipTrigger>
|
||||
<TooltipContent>
|
||||
<p>Start Server ... Needs added still</p>
|
||||
</TooltipContent>
|
||||
</Tooltip>
|
||||
</TooltipProvider>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
22
frontend/src/components/admin/servers/StopServer.tsx
Normal file
22
frontend/src/components/admin/servers/StopServer.tsx
Normal file
@@ -0,0 +1,22 @@
|
||||
import {Button} from "@/components/ui/button";
|
||||
import {Tooltip, TooltipContent, TooltipProvider, TooltipTrigger} from "@/components/ui/tooltip";
|
||||
import {Octagon} from "lucide-react";
|
||||
|
||||
export default function StopServer() {
|
||||
return (
|
||||
<div>
|
||||
<TooltipProvider>
|
||||
<Tooltip>
|
||||
<TooltipTrigger asChild>
|
||||
<Button variant={"outline"} size={"icon"}>
|
||||
<Octagon />
|
||||
</Button>
|
||||
</TooltipTrigger>
|
||||
<TooltipContent>
|
||||
<p>Stop Server ... Needs added still</p>
|
||||
</TooltipContent>
|
||||
</Tooltip>
|
||||
</TooltipProvider>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
@@ -5,6 +5,7 @@ import {Servers} from "./ServerPage";
|
||||
import {useQuery} from "@tanstack/react-query";
|
||||
import {getSettings} from "@/utils/querys/settings";
|
||||
import axios from "axios";
|
||||
import {Tooltip, TooltipContent, TooltipProvider, TooltipTrigger} from "@/components/ui/tooltip";
|
||||
|
||||
export default function UpdateServer({server, token}: {server: Servers; token: string}) {
|
||||
const {data} = useQuery(getSettings(token ?? ""));
|
||||
@@ -33,9 +34,18 @@ export default function UpdateServer({server, token}: {server: Servers; token: s
|
||||
};
|
||||
return (
|
||||
<div>
|
||||
<TooltipProvider>
|
||||
<Tooltip>
|
||||
<TooltipTrigger asChild>
|
||||
<Button variant={"outline"} size={"icon"} onClick={upgrade} disabled={server.isUpgrading}>
|
||||
<CircleFadingArrowUp />
|
||||
</Button>
|
||||
</TooltipTrigger>
|
||||
<TooltipContent>
|
||||
<p>Update {server.sName}</p>
|
||||
</TooltipContent>
|
||||
</Tooltip>
|
||||
</TooltipProvider>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -54,19 +54,30 @@ const LoginForm = () => {
|
||||
headers: {
|
||||
"Content-Type": "application/json",
|
||||
},
|
||||
body: JSON.stringify({username: value.username, password: value.password}),
|
||||
body: JSON.stringify({
|
||||
username: value.username,
|
||||
password: value.password,
|
||||
}),
|
||||
});
|
||||
|
||||
const data = await response.json();
|
||||
|
||||
// Store token in localStorage
|
||||
// localStorage.setItem("auth_token", data.data.token);
|
||||
if (data.success) {
|
||||
const prod = btoa(`${value.username.toLowerCase()}:${value.password}`);
|
||||
const prodUser = { ...data.user, prod: prod };
|
||||
|
||||
setSession(prodUser, data.token);
|
||||
toast.success(`You are logged in as ${data.user.username}`);
|
||||
router.navigate({ to: "/" });
|
||||
}
|
||||
|
||||
if (!data.success) {
|
||||
toast.error(`${data.message}`);
|
||||
}
|
||||
|
||||
//console.log(data);
|
||||
} catch (err) {
|
||||
toast.error("Invalid credentials");
|
||||
}
|
||||
@@ -92,7 +103,11 @@ const LoginForm = () => {
|
||||
className={errors.username ? "border-red-500" : ""}
|
||||
aria-invalid={!!errors.username}
|
||||
/>
|
||||
{errors.username && <p className="text-red-500 text-sm mt-1">{errors.username.message}</p>}
|
||||
{errors.username && (
|
||||
<p className="text-red-500 text-sm mt-1">
|
||||
{errors.username.message}
|
||||
</p>
|
||||
)}
|
||||
</div>
|
||||
<div>
|
||||
<>
|
||||
@@ -105,7 +120,11 @@ const LoginForm = () => {
|
||||
className={errors.password ? "border-red-500" : ""}
|
||||
aria-invalid={!!errors.password}
|
||||
/>
|
||||
{errors.password && <p className="text-red-500 text-sm mt-1">{errors.password.message}</p>}
|
||||
{errors.password && (
|
||||
<p className="text-red-500 text-sm mt-1">
|
||||
{errors.password.message}
|
||||
</p>
|
||||
)}
|
||||
</>
|
||||
</div>
|
||||
<div className="flex justify-between pt-2">
|
||||
|
||||
@@ -16,24 +16,25 @@ export default function ConsumeMaterial() {
|
||||
const {token} = useSessionStore();
|
||||
|
||||
const handleConsume = async (data: any) => {
|
||||
setSubmitting(!submitting);
|
||||
setSubmitting(true);
|
||||
try {
|
||||
const result = await axios.post(`/api/logistics/consume`, data, {
|
||||
headers: {Authorization: `Bearer ${token}`},
|
||||
});
|
||||
if (result.data.success) {
|
||||
toast.success(result.data.message);
|
||||
setSubmitting(!submitting);
|
||||
setSubmitting(false);
|
||||
reset();
|
||||
}
|
||||
if (!result.data.success) {
|
||||
//console.log(result.data);
|
||||
setSubmitting(!submitting);
|
||||
setSubmitting(false);
|
||||
|
||||
toast.error(result.data.message);
|
||||
}
|
||||
} catch (error: any) {
|
||||
//console.log(error);
|
||||
setSubmitting(!submitting);
|
||||
setSubmitting(false);
|
||||
if (error.status === 401) {
|
||||
toast.error("Unauthorized to do this task.");
|
||||
} else {
|
||||
|
||||
@@ -1,22 +1,71 @@
|
||||
import {LstCard} from "../extendedUI/LstCard";
|
||||
import {CardContent, CardHeader} from "../ui/card";
|
||||
import {Skeleton} from "../ui/skeleton";
|
||||
/**
|
||||
* we will do a very sloppy way for this just keep fetching the logs we spent to much time on this :()
|
||||
*/
|
||||
|
||||
export default function CycleCountLog() {
|
||||
return (
|
||||
<LstCard className="w-48">
|
||||
<CardHeader className="flex justify-center">
|
||||
<span>Cycle Count logs</span>
|
||||
</CardHeader>
|
||||
<CardContent>
|
||||
{Array(10)
|
||||
.fill(0)
|
||||
.map((_, i) => (
|
||||
<div key={i}>
|
||||
<Skeleton className="m-2 h-4" />
|
||||
</div>
|
||||
))}
|
||||
</CardContent>
|
||||
</LstCard>
|
||||
);
|
||||
}
|
||||
// //import {useEffect, useState} from "react";
|
||||
// import {LstCard} from "../extendedUI/LstCard";
|
||||
// import {CardContent, CardHeader} from "../ui/card";
|
||||
// import {Skeleton} from "../ui/skeleton";
|
||||
// import {Button} from "../ui/button";
|
||||
// import {toast} from "sonner";
|
||||
// import {useEffect} from "react";
|
||||
|
||||
// export default function CycleCountLog() {
|
||||
// //const [logs, setLogs] = useState([]);
|
||||
// //const [streaming, setStreaming] = useState(false); // Track if streaming is active
|
||||
|
||||
// useEffect(() => {
|
||||
// // Start streaming when the button is clicked
|
||||
// let es;
|
||||
|
||||
// const url = `http://localhost:4000/api/logger/logs/stream?service=ocme-count&level=info`;
|
||||
|
||||
// es = new EventSource(url);
|
||||
// es.onopen = () => console.log(">>> Connection opened!");
|
||||
// es.onerror = (e) => console.log("ERROR!", e);
|
||||
// es.onmessage = (e) => {
|
||||
// const data = JSON.parse(e.data);
|
||||
|
||||
// console.log(e);
|
||||
// console.log(data);
|
||||
// switch (data.type) {
|
||||
// case "time-update":
|
||||
// console.log(data);
|
||||
// break;
|
||||
// case "error":
|
||||
// console.log(data);
|
||||
// break;
|
||||
// case "done":
|
||||
// console.log(data);
|
||||
// es.close(); // Close the connection when done
|
||||
|
||||
// break;
|
||||
// default:
|
||||
// break;
|
||||
// }
|
||||
// };
|
||||
|
||||
// return () => es.close();
|
||||
// }, []);
|
||||
|
||||
// // const handleStartStreaming = () => {
|
||||
// // setStreaming(true); // Start streaming when button is clicked
|
||||
// // };
|
||||
// return (
|
||||
// <LstCard className="w-48">
|
||||
// <CardHeader className="flex justify-center">
|
||||
// <span>Cycle Count logs</span>
|
||||
// </CardHeader>
|
||||
// <CardContent>
|
||||
// {Array(10)
|
||||
// .fill(0)
|
||||
// .map((_, i) => (
|
||||
// <div key={i}>
|
||||
// <Skeleton className="m-2 h-4" />
|
||||
// </div>
|
||||
// ))}
|
||||
// </CardContent>
|
||||
// <Button onClick={() => toast.success("SOmething")}>Start Stream</Button>
|
||||
// </LstCard>
|
||||
// );
|
||||
// }
|
||||
|
||||
@@ -4,21 +4,89 @@ import {Button} from "../ui/button";
|
||||
import {Input} from "../ui/input";
|
||||
import {Table, TableBody, TableCell, TableHead, TableHeader, TableRow} from "../ui/table";
|
||||
import {Skeleton} from "../ui/skeleton";
|
||||
import CycleCountLog from "./CycleCountLog";
|
||||
//import CycleCountLog from "./CycleCountLog";
|
||||
import {Select, SelectContent, SelectItem, SelectTrigger, SelectValue} from "../ui/select";
|
||||
import {Controller, useForm} from "react-hook-form";
|
||||
import axios from "axios";
|
||||
import {useState} from "react";
|
||||
|
||||
export default function OcmeCycleCount() {
|
||||
const token = localStorage.getItem("auth_token");
|
||||
const [data, setData] = useState([]);
|
||||
const [counting, setCounting] = useState(false);
|
||||
const {
|
||||
register,
|
||||
handleSubmit,
|
||||
//watch,
|
||||
formState: {errors},
|
||||
reset,
|
||||
control,
|
||||
} = useForm();
|
||||
|
||||
const onSubmit = async (data: any) => {
|
||||
setData([]);
|
||||
setCounting(true);
|
||||
toast.success(`Cycle count started`);
|
||||
try {
|
||||
const res = await axios.post("/ocme/api/v1/cyclecount", data, {
|
||||
headers: {Authorization: `Bearer ${token}`},
|
||||
});
|
||||
toast.success(res.data.message);
|
||||
setData(res.data.data);
|
||||
setCounting(false);
|
||||
reset();
|
||||
} catch (error) {
|
||||
toast.error("There was an error cycle counting");
|
||||
setCounting(false);
|
||||
reset();
|
||||
}
|
||||
};
|
||||
return (
|
||||
<div className="flex flex-row w-fill">
|
||||
<div className="flex flex-row w-screen">
|
||||
<div className="m-2 w-5/6">
|
||||
<LstCard>
|
||||
<p className="ml-2">Please enter the name or laneID you want to cycle count.</p>
|
||||
<div>
|
||||
<form>
|
||||
<form onSubmit={handleSubmit(onSubmit)}>
|
||||
<div className="flex justify-between">
|
||||
<div className="m-2">
|
||||
<Input placeholder="enter lane: L064" />
|
||||
<div className="m-2 flex flex-row">
|
||||
<Input
|
||||
placeholder="enter lane: L064"
|
||||
className={errors.lane ? "border-red-500" : ""}
|
||||
aria-invalid={!!errors.lane}
|
||||
{...register("lane", {
|
||||
required: true,
|
||||
minLength: {
|
||||
value: 3,
|
||||
message: "The lane is too short!",
|
||||
},
|
||||
})}
|
||||
/>
|
||||
<div className="ml-2">
|
||||
<Controller
|
||||
control={control}
|
||||
name="laneType"
|
||||
defaultValue={""}
|
||||
render={({
|
||||
field: {onChange},
|
||||
fieldState: {},
|
||||
//formState,
|
||||
}) => (
|
||||
<Select onValueChange={onChange}>
|
||||
<SelectTrigger className="w-[180px]">
|
||||
<SelectValue placeholder="Select name or id" />
|
||||
</SelectTrigger>
|
||||
<SelectContent>
|
||||
<SelectItem value="name">Name</SelectItem>
|
||||
<SelectItem value="laneId">Lane ID</SelectItem>
|
||||
</SelectContent>
|
||||
</Select>
|
||||
)}
|
||||
/>
|
||||
</div>
|
||||
<Button className="m-2" onClick={() => toast.success("Cycle Count completed")}>
|
||||
CycleCount
|
||||
</div>
|
||||
<Button className="m-2" type="submit" disabled={counting}>
|
||||
{counting ? <span>Counting...</span> : <span>CycleCount</span>}
|
||||
</Button>
|
||||
</div>
|
||||
</form>
|
||||
@@ -37,6 +105,7 @@ export default function OcmeCycleCount() {
|
||||
<TableHead>Result</TableHead>
|
||||
</TableRow>
|
||||
</TableHeader>
|
||||
{data.length === 0 ? (
|
||||
<TableBody>
|
||||
{Array(10)
|
||||
.fill(0)
|
||||
@@ -69,13 +138,48 @@ export default function OcmeCycleCount() {
|
||||
</TableRow>
|
||||
))}
|
||||
</TableBody>
|
||||
) : (
|
||||
<>
|
||||
{data.map((i: any) => {
|
||||
let classname = ``;
|
||||
if (i.info === "Quality Check Required") {
|
||||
classname = `bg-red-500`;
|
||||
}
|
||||
if (i.info === "Sent to Inv") {
|
||||
classname = `bg-amber-700`;
|
||||
}
|
||||
return (
|
||||
<TableRow key={i.runningNumber}>
|
||||
<TableCell className={`font-medium ${classname}`}>
|
||||
{i.alpla_laneID}
|
||||
</TableCell>
|
||||
<TableCell className={`font-medium ${classname}`}>
|
||||
{i.alpla_laneDescription}
|
||||
</TableCell>
|
||||
<TableCell className={`font-medium ${classname}`}>
|
||||
{i.Article}
|
||||
</TableCell>
|
||||
<TableCell className={`font-medium ${classname}`}>
|
||||
{i.alpla_laneDescription}
|
||||
</TableCell>
|
||||
<TableCell className={`font-medium ${classname}`}>
|
||||
{i.runningNumber}
|
||||
</TableCell>
|
||||
<TableCell className={`font-medium ${classname}`}>{i.ocme}</TableCell>
|
||||
<TableCell className={`font-medium ${classname}`}>{i.stock}</TableCell>
|
||||
<TableCell className={`font-medium ${classname}`}>{i.info}</TableCell>
|
||||
</TableRow>
|
||||
);
|
||||
})}
|
||||
</>
|
||||
)}
|
||||
</Table>
|
||||
</div>
|
||||
</LstCard>
|
||||
</div>
|
||||
<div className="m-2">
|
||||
{/* <div className="m-2">
|
||||
<CycleCountLog />
|
||||
</div>
|
||||
</div> */}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import {LstCard} from "@/components/extendedUI/LstCard";
|
||||
import {CardHeader} from "@/components/ui/card";
|
||||
|
||||
import {Skeleton} from "@/components/ui/skeleton";
|
||||
import {Table, TableBody, TableCell, TableHead, TableHeader, TableRow} from "@/components/ui/table";
|
||||
// import {useSessionStore} from "@/lib/store/sessionStore";
|
||||
@@ -17,7 +17,7 @@ const labelLogs = [
|
||||
//{key: "reprint", label: "Reprint"}, // removing the reprint button for now until repritning is working as intended
|
||||
];
|
||||
export default function LabelLog() {
|
||||
const {data, isError, error, isLoading} = useQuery(getlabels("4"));
|
||||
const {data, isError, isLoading} = useQuery(getlabels("4"));
|
||||
//const {user} = useSessionStore();
|
||||
//const {settings} = useSettingStore();
|
||||
//const server = settings.filter((n) => n.name === "server")[0]?.value || "";
|
||||
@@ -26,10 +26,42 @@ export default function LabelLog() {
|
||||
|
||||
if (isError) {
|
||||
return (
|
||||
<div>
|
||||
<div className="m-2 p-2 min-h-2/5">
|
||||
<LstCard>
|
||||
<CardHeader>There was an error loading the lots</CardHeader>
|
||||
{JSON.stringify(error)}
|
||||
<p className="text-center">Labels for the last 2 hours</p>
|
||||
<Table>
|
||||
<TableHeader>
|
||||
<TableRow>
|
||||
{labelLogs.map((l) => (
|
||||
<TableHead key={l.key}>{l.label}</TableHead>
|
||||
))}
|
||||
</TableRow>
|
||||
</TableHeader>
|
||||
|
||||
<TableBody>
|
||||
{Array(7)
|
||||
.fill(0)
|
||||
.map((_, i) => (
|
||||
<TableRow key={i}>
|
||||
<TableCell className="font-medium">
|
||||
<Skeleton className="h-4" />
|
||||
</TableCell>
|
||||
<TableCell>
|
||||
<Skeleton className="h-4" />
|
||||
</TableCell>
|
||||
<TableCell>
|
||||
<Skeleton className="h-4" />
|
||||
</TableCell>
|
||||
<TableCell>
|
||||
<Skeleton className="h-4" />
|
||||
</TableCell>
|
||||
<TableCell>
|
||||
<Skeleton className="h-4" />
|
||||
</TableCell>
|
||||
</TableRow>
|
||||
))}
|
||||
</TableBody>
|
||||
</Table>
|
||||
</LstCard>
|
||||
</div>
|
||||
);
|
||||
@@ -37,6 +69,7 @@ export default function LabelLog() {
|
||||
|
||||
return (
|
||||
<LstCard className="m-2 p-2 min-h-2/5">
|
||||
<p className="text-center">Labels for the last 2 hours</p>
|
||||
<Table>
|
||||
<TableHeader>
|
||||
<TableRow>
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import {LstCard} from "@/components/extendedUI/LstCard";
|
||||
import {CardHeader} from "@/components/ui/card";
|
||||
|
||||
import {Skeleton} from "@/components/ui/skeleton";
|
||||
import {Table, TableBody, TableCell, TableHead, TableHeader, TableRow} from "@/components/ui/table";
|
||||
import {useSessionStore} from "@/lib/store/sessionStore";
|
||||
@@ -57,7 +57,7 @@ let lotColumns = [
|
||||
// },
|
||||
];
|
||||
export default function Lots() {
|
||||
const {data, isError, error, isLoading} = useQuery(getlots());
|
||||
const {data, isError, isLoading} = useQuery(getlots());
|
||||
const {user} = useSessionStore();
|
||||
const {settings} = useSettingStore();
|
||||
const server = settings.filter((n) => n.name === "server")[0]?.value || "";
|
||||
@@ -82,10 +82,54 @@ export default function Lots() {
|
||||
|
||||
if (isError) {
|
||||
return (
|
||||
<div>
|
||||
<div className="m-2 p-2 min-h-2/5">
|
||||
<LstCard>
|
||||
<CardHeader>There was an error loading the lots</CardHeader>
|
||||
{JSON.stringify(error)}
|
||||
<p className="text-center">Current Assigned lots</p>
|
||||
<Table>
|
||||
<TableHeader>
|
||||
<TableRow>
|
||||
{lotColumns.map((l) => (
|
||||
<TableHead key={l.key}>{l.label}</TableHead>
|
||||
))}
|
||||
</TableRow>
|
||||
</TableHeader>
|
||||
|
||||
<TableBody>
|
||||
{Array(10)
|
||||
.fill(0)
|
||||
.map((_, i) => (
|
||||
<TableRow key={i}>
|
||||
<TableCell className="font-medium">
|
||||
<Skeleton className="h-4" />
|
||||
</TableCell>
|
||||
<TableCell>
|
||||
<Skeleton className="h-4" />
|
||||
</TableCell>
|
||||
<TableCell>
|
||||
<Skeleton className="h-4" />
|
||||
</TableCell>
|
||||
<TableCell>
|
||||
<Skeleton className="h-4" />
|
||||
</TableCell>
|
||||
<TableCell>
|
||||
<Skeleton className="h-4" />
|
||||
</TableCell>
|
||||
<TableCell>
|
||||
<Skeleton className="h-4" />
|
||||
</TableCell>
|
||||
<TableCell>
|
||||
<Skeleton className="h-4" />
|
||||
</TableCell>
|
||||
<TableCell>
|
||||
<Skeleton className="h-4" />
|
||||
</TableCell>
|
||||
<TableCell>
|
||||
<Skeleton className="h-4" />
|
||||
</TableCell>
|
||||
</TableRow>
|
||||
))}
|
||||
</TableBody>
|
||||
</Table>
|
||||
</LstCard>
|
||||
</div>
|
||||
);
|
||||
@@ -93,6 +137,7 @@ export default function Lots() {
|
||||
|
||||
return (
|
||||
<LstCard className="m-2 p-2 min-h-2/5">
|
||||
<p className="text-center">Current Assigned lots</p>
|
||||
<Table>
|
||||
<TableHeader>
|
||||
<TableRow>
|
||||
|
||||
@@ -1,5 +1,52 @@
|
||||
import {LstCard} from "@/components/extendedUI/LstCard";
|
||||
import {Skeleton} from "@/components/ui/skeleton";
|
||||
import {Table, TableBody, TableCell, TableHead, TableHeader, TableRow} from "@/components/ui/table";
|
||||
|
||||
let printerCols = [
|
||||
{
|
||||
key: "status",
|
||||
label: "Status",
|
||||
},
|
||||
{
|
||||
key: "printer",
|
||||
label: "Printer",
|
||||
},
|
||||
{
|
||||
key: "statusMessage",
|
||||
label: "Status Message",
|
||||
},
|
||||
];
|
||||
export default function PrinterStatus() {
|
||||
return <LstCard className="m-2 p-2">Printer Status</LstCard>;
|
||||
return (
|
||||
<LstCard className="m-2 p-2">
|
||||
<p className="text-center">Printer Status</p>
|
||||
<Table>
|
||||
<TableHeader>
|
||||
<TableRow>
|
||||
{printerCols.map((l) => (
|
||||
<TableHead key={l.key}>{l.label}</TableHead>
|
||||
))}
|
||||
</TableRow>
|
||||
</TableHeader>
|
||||
|
||||
<TableBody>
|
||||
{Array(10)
|
||||
.fill(0)
|
||||
.map((_, i) => (
|
||||
<TableRow key={i}>
|
||||
<TableCell className="font-medium">
|
||||
<Skeleton className="h-4" />
|
||||
</TableCell>
|
||||
<TableCell>
|
||||
<Skeleton className="h-4" />
|
||||
</TableCell>
|
||||
<TableCell>
|
||||
<Skeleton className="h-4" />
|
||||
</TableCell>
|
||||
</TableRow>
|
||||
))}
|
||||
</TableBody>
|
||||
</Table>
|
||||
</LstCard>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -5,19 +5,20 @@ import { cva, type VariantProps } from "class-variance-authority"
|
||||
import { cn } from "@/lib/utils"
|
||||
|
||||
const buttonVariants = cva(
|
||||
"inline-flex items-center justify-center gap-2 whitespace-nowrap rounded-md text-sm font-medium transition-[color,box-shadow] disabled:pointer-events-none disabled:opacity-50 [&_svg]:pointer-events-none [&_svg:not([class*='size-'])]:size-4 [&_svg]:shrink-0 outline-none focus-visible:border-ring focus-visible:ring-ring/50 focus-visible:ring-[3px] aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 aria-invalid:border-destructive",
|
||||
"inline-flex items-center justify-center gap-2 whitespace-nowrap rounded-md text-sm font-medium transition-all disabled:pointer-events-none disabled:opacity-50 [&_svg]:pointer-events-none [&_svg:not([class*='size-'])]:size-4 shrink-0 [&_svg]:shrink-0 outline-none focus-visible:border-ring focus-visible:ring-ring/50 focus-visible:ring-[3px] aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 aria-invalid:border-destructive",
|
||||
{
|
||||
variants: {
|
||||
variant: {
|
||||
default:
|
||||
"bg-primary text-primary-foreground shadow-xs hover:bg-primary/90",
|
||||
destructive:
|
||||
"bg-destructive text-white shadow-xs hover:bg-destructive/90 focus-visible:ring-destructive/20 dark:focus-visible:ring-destructive/40",
|
||||
"bg-destructive text-white shadow-xs hover:bg-destructive/90 focus-visible:ring-destructive/20 dark:focus-visible:ring-destructive/40 dark:bg-destructive/60",
|
||||
outline:
|
||||
"border border-input bg-background shadow-xs hover:bg-accent hover:text-accent-foreground",
|
||||
"border bg-background shadow-xs hover:bg-accent hover:text-accent-foreground dark:bg-input/30 dark:border-input dark:hover:bg-input/50",
|
||||
secondary:
|
||||
"bg-secondary text-secondary-foreground shadow-xs hover:bg-secondary/80",
|
||||
ghost: "hover:bg-accent hover:text-accent-foreground",
|
||||
ghost:
|
||||
"hover:bg-accent hover:text-accent-foreground dark:hover:bg-accent/50",
|
||||
link: "text-primary underline-offset-4 hover:underline",
|
||||
},
|
||||
size: {
|
||||
|
||||
@@ -44,7 +44,7 @@ function TooltipContent({
|
||||
data-slot="tooltip-content"
|
||||
sideOffset={sideOffset}
|
||||
className={cn(
|
||||
"bg-primary text-primary-foreground animate-in fade-in-0 zoom-in-95 data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=closed]:zoom-out-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2 z-50 w-fit rounded-md px-3 py-1.5 text-xs text-balance",
|
||||
"bg-primary text-primary-foreground animate-in fade-in-0 zoom-in-95 data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=closed]:zoom-out-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2 z-50 w-fit origin-(--radix-tooltip-content-transform-origin) rounded-md px-3 py-1.5 text-xs text-balance",
|
||||
className
|
||||
)}
|
||||
{...props}
|
||||
|
||||
@@ -16,7 +16,7 @@ import {
|
||||
} from "../components/ui/dropdown-menu";
|
||||
import { SessionProvider } from "../components/providers/Providers";
|
||||
import { Toaster } from "sonner";
|
||||
import {Button} from "../components/ui/button";
|
||||
//import { Button } from "../components/ui/button";
|
||||
|
||||
import { useSessionStore } from "../lib/store/sessionStore";
|
||||
import { useSession } from "@/hooks/useSession";
|
||||
@@ -47,32 +47,35 @@ export const Route = createRootRoute({
|
||||
<DropdownMenu>
|
||||
<DropdownMenuTrigger>
|
||||
<Avatar>
|
||||
<AvatarImage src="https://github.com/shadcn.png" alt="@shadcn" />
|
||||
<AvatarImage
|
||||
src="https://github.com/shadcn.png"
|
||||
alt="@shadcn"
|
||||
/>
|
||||
<AvatarFallback>CN</AvatarFallback>
|
||||
</Avatar>
|
||||
</DropdownMenuTrigger>
|
||||
<DropdownMenuContent>
|
||||
<DropdownMenuLabel>Hello {user?.username}</DropdownMenuLabel>
|
||||
<DropdownMenuLabel>
|
||||
Hello {user?.username}
|
||||
</DropdownMenuLabel>
|
||||
<DropdownMenuSeparator />
|
||||
<DropdownMenuItem>Profile</DropdownMenuItem>
|
||||
{/* <DropdownMenuItem>Profile</DropdownMenuItem>
|
||||
<DropdownMenuItem>Billing</DropdownMenuItem>
|
||||
<DropdownMenuItem>Team</DropdownMenuItem>
|
||||
<DropdownMenuItem>Subscription</DropdownMenuItem>
|
||||
<DropdownMenuItem>Subscription</DropdownMenuItem> */}
|
||||
<hr className="solid"></hr>
|
||||
<DropdownMenuItem>
|
||||
<div className="m-auto mt-3">
|
||||
<Button onClick={() => logout()} variant="ghost">
|
||||
Logout
|
||||
</Button>
|
||||
<div className="m-auto">
|
||||
<button onClick={() => logout()}>Logout</button>
|
||||
</div>
|
||||
</DropdownMenuItem>
|
||||
</DropdownMenuContent>
|
||||
</DropdownMenu>
|
||||
</div>
|
||||
) : (
|
||||
<>
|
||||
<div>
|
||||
<Link to="/login">Login</Link>
|
||||
</>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
</nav>
|
||||
|
||||
@@ -18,7 +18,16 @@ export default defineConfig({
|
||||
},
|
||||
server: {
|
||||
proxy: {
|
||||
"/api": {target: `http://localhost:${Number(process.env.VITE_SERVER_PORT || 4400)}`, changeOrigin: true},
|
||||
"/api": {
|
||||
target: `http://localhost:${Number(process.env.VITE_SERVER_PORT || 4400)}`,
|
||||
changeOrigin: true,
|
||||
secure: false,
|
||||
},
|
||||
"/ocme": {
|
||||
target: `http://localhost:${Number(process.env.VITE_SERVER_PORT || 4400)}`,
|
||||
changeOrigin: true,
|
||||
secure: false,
|
||||
},
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
6245
package-lock.json
generated
6245
package-lock.json
generated
File diff suppressed because it is too large
Load Diff
96
package.json
96
package.json
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "lstv2",
|
||||
"version": "2.8.0",
|
||||
"version": "2.9.0",
|
||||
"type": "module",
|
||||
"scripts": {
|
||||
"dev": "concurrently -n \"server,frontend\" -c \"#007755,#2f6da3\" \"npm run dev:server\" \"cd frontend && npm run dev\"",
|
||||
@@ -9,8 +9,10 @@
|
||||
"dev:dbgen": " drizzle-kit generate --config=drizzle-dev.config.ts",
|
||||
"dev:dbmigrate": " drizzle-kit migrate --config=drizzle-dev.config.ts",
|
||||
"build": "npm run build:server && npm run build:frontend",
|
||||
"build:server": "rimraf build && tsc --build && xcopy server\\scripts dist\\server\\scripts /E /I /Y && xcopy server\\services\\server\\utils\\serverData.json dist\\server\\services\\server\\utils /E /I /Y ",
|
||||
"build:server": "rimraf dist && tsc --build && npm run copy:scripts",
|
||||
"build:frontend": "cd frontend && npm run build",
|
||||
"copy:scripts": "tsx server/scripts/copyScripts.ts",
|
||||
"copy:servers": "xcopy server\\services\\server\\utils\\serverData.json dist\\server\\services\\server\\utils /E /I /Y",
|
||||
"start": "set NODE_ENV=production && npm run start:server",
|
||||
"start:server": "dotenvx run -f .env -- node dist/server/index.js",
|
||||
"db:generate": "npx drizzle-kit generate",
|
||||
@@ -22,50 +24,7 @@
|
||||
"prodBuild": "npm run v1Build && powershell -ExecutionPolicy Bypass -File server/scripts/build.ps1 -dir \"C:\\Users\\matthes01\\Documents\\lstv2\" && npm run zipServer",
|
||||
"commit": "cz",
|
||||
"prodinstall": "npm i --omit=dev && npm run db:migrate",
|
||||
"checkupdates": "npm-check-updates"
|
||||
},
|
||||
"dependencies": {
|
||||
"@dotenvx/dotenvx": "^1.38.3",
|
||||
"@hono/node-server": "^1.13.8",
|
||||
"@hono/zod-openapi": "^0.18.4",
|
||||
"@scalar/hono-api-reference": "^0.5.175",
|
||||
"@types/jsonwebtoken": "^9.0.8",
|
||||
"adm-zip": "^0.5.16",
|
||||
"axios": "^1.7.9",
|
||||
"bcrypt": "^5.1.1",
|
||||
"compression": "^1.8.0",
|
||||
"cookie": "^1.0.2",
|
||||
"date-fns": "^4.1.0",
|
||||
"dotenv": "^16.4.7",
|
||||
"drizzle-kit": "^0.30.4",
|
||||
"drizzle-orm": "^0.39.3",
|
||||
"drizzle-zod": "^0.7.0",
|
||||
"fast-xml-parser": "^5.0.9",
|
||||
"jsonwebtoken": "^9.0.2",
|
||||
"mssql": "^11.0.1",
|
||||
"nodemailer": "^6.10.0",
|
||||
"nodemailer-express-handlebars": "^7.0.0",
|
||||
"pg": "^8.13.3",
|
||||
"pino": "^9.6.0",
|
||||
"pino-abstract-transport": "^2.0.0",
|
||||
"pino-pretty": "^13.0.0",
|
||||
"postgres": "^3.4.5",
|
||||
"zod": "^3.24.2"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/adm-zip": "^0.5.7",
|
||||
"@types/bcrypt": "^5.0.2",
|
||||
"@types/js-cookie": "^3.0.6",
|
||||
"@types/mssql": "^9.1.7",
|
||||
"@types/node": "^22.13.5",
|
||||
"@types/pg": "^8.11.11",
|
||||
"concurrently": "^8.2.0",
|
||||
"cz-conventional-changelog": "^3.3.0",
|
||||
"dotenv": "^16.3.1",
|
||||
"rimraf": "^6.0.1",
|
||||
"standard-version": "^9.5.0",
|
||||
"tsx": "^4.7.1",
|
||||
"typescript": "~5.7.3"
|
||||
"checkupdates": "npx npm-check-updates"
|
||||
},
|
||||
"config": {
|
||||
"commitizen": {
|
||||
@@ -73,7 +32,50 @@
|
||||
}
|
||||
},
|
||||
"admConfig": {
|
||||
"build": 43,
|
||||
"build": 50,
|
||||
"oldBuild": "backend-0.1.3.zip"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/adm-zip": "^0.5.7",
|
||||
"@types/bcrypt": "^5.0.2",
|
||||
"@types/fs-extra": "^11.0.4",
|
||||
"@types/js-cookie": "^3.0.6",
|
||||
"@types/mssql": "^9.1.7",
|
||||
"@types/node": "^22.13.11",
|
||||
"@types/pg": "^8.11.11",
|
||||
"@types/ws": "^8.18.0",
|
||||
"concurrently": "^9.1.2",
|
||||
"cz-conventional-changelog": "^3.3.0",
|
||||
"drizzle-kit": "^0.30.5",
|
||||
"fs-extra": "^11.3.0",
|
||||
"standard-version": "^9.5.0",
|
||||
"tsx": "^4.19.3",
|
||||
"typescript": "^5.8.2"
|
||||
},
|
||||
"dependencies": {
|
||||
"@dotenvx/dotenvx": "^1.39.0",
|
||||
"@hono/node-server": "^1.14.0",
|
||||
"@hono/zod-openapi": "^0.19.2",
|
||||
"@scalar/hono-api-reference": "^0.7.2",
|
||||
"@types/jsonwebtoken": "^9.0.9",
|
||||
"adm-zip": "^0.5.16",
|
||||
"axios": "^1.8.4",
|
||||
"bcryptjs": "^3.0.2",
|
||||
"date-fns": "^4.1.0",
|
||||
"drizzle-orm": "^0.41.0",
|
||||
"drizzle-zod": "^0.7.0",
|
||||
"fast-xml-parser": "^5.0.9",
|
||||
"jsonwebtoken": "^9.0.2",
|
||||
"mssql": "^11.0.1",
|
||||
"nodemailer": "^6.10.0",
|
||||
"nodemailer-express-handlebars": "^7.0.0",
|
||||
"pg": "^8.14.1",
|
||||
"pino": "^9.6.0",
|
||||
"pino-abstract-transport": "^2.0.0",
|
||||
"pino-pretty": "^13.0.0",
|
||||
"postgres": "^3.4.5",
|
||||
"rimraf": "^6.0.1",
|
||||
"ws": "^8.18.1",
|
||||
"zod": "^3.24.2"
|
||||
}
|
||||
}
|
||||
3
server/globalUtils/delay.ts
Normal file
3
server/globalUtils/delay.ts
Normal file
@@ -0,0 +1,3 @@
|
||||
export const delay = (ms: number) => {
|
||||
return new Promise((resolve) => setTimeout(resolve, ms));
|
||||
};
|
||||
29
server/globalUtils/routeDefs/returnRes.ts
Normal file
29
server/globalUtils/routeDefs/returnRes.ts
Normal file
@@ -0,0 +1,29 @@
|
||||
import type { Context } from "hono";
|
||||
|
||||
export type ReturnRes<T> =
|
||||
| { success: true; message: string; data: T }
|
||||
| { success: false; message: string; error: any };
|
||||
|
||||
export const returnRes = <T>(
|
||||
success: boolean,
|
||||
message: string,
|
||||
data: T | null = null
|
||||
): ReturnRes<T> => {
|
||||
/**
|
||||
* just a simple return to reduce the typing and make sure we are always consitant with our returns.
|
||||
*
|
||||
* data can be an error as well.
|
||||
*/
|
||||
return success
|
||||
? { success, message, data: data as T }
|
||||
: { success, message, error: data ?? "An unknown error occurred" };
|
||||
};
|
||||
|
||||
// export const returnApi = (c:Context,success: boolean, message: string, data?: any, code: number)=>{
|
||||
// /**
|
||||
// * just a simple return to reduce the typing and make sure we are always consitant with our returns.
|
||||
// *
|
||||
// * data can be an error as well.
|
||||
// */
|
||||
// return c.json({success, message, data}, code);
|
||||
// }
|
||||
24
server/globalUtils/tryCatch.ts
Normal file
24
server/globalUtils/tryCatch.ts
Normal file
@@ -0,0 +1,24 @@
|
||||
// Types for the result object with discriminated union
|
||||
type Success<T> = {
|
||||
data: T;
|
||||
error: null;
|
||||
};
|
||||
|
||||
type Failure<E> = {
|
||||
data: null;
|
||||
error: E;
|
||||
};
|
||||
|
||||
type Result<T, E = Error> = Success<T> | Failure<E>;
|
||||
|
||||
// Main wrapper function
|
||||
export async function tryCatch<T, E = Error>(
|
||||
promise: Promise<T>
|
||||
): Promise<Result<T, E>> {
|
||||
try {
|
||||
const data = await promise;
|
||||
return { data, error: null };
|
||||
} catch (error) {
|
||||
return { data: null, error: error as E };
|
||||
}
|
||||
}
|
||||
@@ -6,7 +6,7 @@ import {serveStatic} from "@hono/node-server/serve-static";
|
||||
import { logger } from "hono/logger";
|
||||
import { cors } from "hono/cors";
|
||||
import { createLog } from "./services/logger/logger.js";
|
||||
|
||||
import { WebSocketServer } from "ws";
|
||||
// custom routes
|
||||
import scalar from "./services/general/route/scalar.js";
|
||||
import system from "./services/server/systemServer.js";
|
||||
@@ -21,7 +21,7 @@ import loggerService from "./services/logger/loggerService.js";
|
||||
import ocpService from "./services/ocp/ocpService.js";
|
||||
import { db } from "../database/dbclient.js";
|
||||
import { settings } from "../database/schema/settings.js";
|
||||
import {count, eq} from "drizzle-orm";
|
||||
import { count } from "drizzle-orm";
|
||||
|
||||
// create the main prodlogin here
|
||||
const username = "lst_user";
|
||||
@@ -30,7 +30,10 @@ export const lstAuth = btoa(`${username}:${password}`);
|
||||
|
||||
// checking to make sure we have the settings intialized
|
||||
const serverIntialized = await db.select({ count: count() }).from(settings);
|
||||
export const installed = serverIntialized[0].count === 0 && process.env.NODE_ENV !== "development" ? false : true;
|
||||
export const installed =
|
||||
serverIntialized[0].count === 0 && process.env.NODE_ENV !== "development"
|
||||
? false
|
||||
: true;
|
||||
createLog("info", "LST", "server", `Server is installed: ${installed}`);
|
||||
|
||||
const app = new OpenAPIHono({ strict: false });
|
||||
@@ -43,7 +46,7 @@ app.use(
|
||||
origin: "*", // Allow all origins
|
||||
allowHeaders: ["Content-Type", "Authorization", "X-Requested-With"],
|
||||
allowMethods: ["GET", "POST", "PUT", "DELETE", "OPTIONS", "PATCH"],
|
||||
exposeHeaders: ["Content-Length", "X-Kuma-Revision"],
|
||||
//exposeHeaders: ["Content-Length", "X-Kuma-Revision"],
|
||||
credentials: true, // Allow credentials if needed
|
||||
maxAge: 600,
|
||||
})
|
||||
@@ -146,9 +149,14 @@ process.on("uncaughtException", async (err) => {
|
||||
process.on("beforeExit", async () => {
|
||||
console.log("Process is about to exit...");
|
||||
//await closePool();
|
||||
process.exit(0);
|
||||
});
|
||||
|
||||
const port = process.env.NODE_ENV === "development" ? process.env.VITE_SERVER_PORT : process.env.PROD_PORT;
|
||||
const port =
|
||||
process.env.NODE_ENV === "development"
|
||||
? process.env.VITE_SERVER_PORT
|
||||
: process.env.PROD_PORT;
|
||||
|
||||
serve(
|
||||
{
|
||||
fetch: app.fetch,
|
||||
@@ -156,7 +164,12 @@ serve(
|
||||
hostname: "0.0.0.0",
|
||||
},
|
||||
(info) => {
|
||||
createLog("info", "LST", "server", `Server is running on http://${info.address}:${info.port}`);
|
||||
createLog(
|
||||
"info",
|
||||
"LST",
|
||||
"server",
|
||||
`Server is running on http://${info.address}:${info.port}`
|
||||
);
|
||||
}
|
||||
);
|
||||
|
||||
|
||||
65
server/scripts/copyScripts.ts
Normal file
65
server/scripts/copyScripts.ts
Normal file
@@ -0,0 +1,65 @@
|
||||
import fs from "fs-extra";
|
||||
import path from "path";
|
||||
import { fileURLToPath } from "url";
|
||||
|
||||
// Get the current directory of the module
|
||||
const __filename = fileURLToPath(import.meta.url);
|
||||
const __dirname = path.dirname(__filename);
|
||||
|
||||
const sourceDir = path.join(__dirname, "/");
|
||||
const destDir = path.join("./", "dist", "server", "scripts");
|
||||
|
||||
// Copy only .ps1 files
|
||||
fs.readdir(sourceDir)
|
||||
.then((files) => {
|
||||
files.forEach((file) => {
|
||||
if (path.extname(file) === ".ps1") {
|
||||
const sourceFile = path.join(sourceDir, file);
|
||||
const destFile = path.join(destDir, file);
|
||||
|
||||
// Copy each .ps1 file
|
||||
fs.copy(sourceFile, destFile)
|
||||
.then(() => {
|
||||
console.log(`Copied: ${file}`);
|
||||
})
|
||||
.catch((err) => {
|
||||
console.error(`Error copying file: ${file}`, err);
|
||||
});
|
||||
}
|
||||
});
|
||||
})
|
||||
.catch((err) => {
|
||||
console.error("Error reading source directory:", err);
|
||||
});
|
||||
|
||||
// Paths for source and destination of serverData.json
|
||||
const sourceFile = path.join(
|
||||
"./",
|
||||
"server",
|
||||
"services",
|
||||
"server",
|
||||
"utils",
|
||||
"serverData.json"
|
||||
);
|
||||
const serverDataDest = path.join(
|
||||
"./",
|
||||
"dist",
|
||||
"server",
|
||||
"services",
|
||||
"server",
|
||||
"utils"
|
||||
);
|
||||
const destFile = path.join(serverDataDest, "serverData.json");
|
||||
|
||||
// Ensure the destination directory exists
|
||||
fs.ensureDir(destDir)
|
||||
.then(() => {
|
||||
// Copy the serverData.json file
|
||||
return fs.copy(sourceFile, destFile);
|
||||
})
|
||||
.then(() => {
|
||||
console.log("serverData.json copied successfully!");
|
||||
})
|
||||
.catch((err) => {
|
||||
console.error("Error copying serverData.json:", err);
|
||||
});
|
||||
@@ -1,37 +1,56 @@
|
||||
# Install
|
||||
|
||||
## Files needed to be downloaded before install.
|
||||
|
||||
### To run the server
|
||||
* [PostgresSQL](https://www.postgresql.org/download/windows/) - current version using is 17
|
||||
* [NodeJS](https://nodejs.org)
|
||||
* [NSSM](https://nssm.cc/)
|
||||
|
||||
- [PostgresSQL](https://www.postgresql.org/download/windows/) - current version using is 17
|
||||
- [NodeJS](https://nodejs.org)
|
||||
- [NSSM](https://nssm.cc/)
|
||||
|
||||
### To manage the server
|
||||
* [VSCODE](https://code.visualstudio.com/)
|
||||
* [Postman](https://www.postman.com/downloads/)
|
||||
|
||||
- [VSCODE](https://code.visualstudio.com/)
|
||||
- [Postman](https://www.postman.com/downloads/)
|
||||
|
||||
## Creating directories needed
|
||||
* Create a new folder where we will host the server files.
|
||||
* Copy the nssm.exe into this folder
|
||||
* Copy the build files to the server (only needed for intial install).
|
||||
* This will house all the compiles and minified files needed to start the server up, this includes the frontend.
|
||||
* Save the nssm.exe into this folder as well, this will be used to control the service.
|
||||
|
||||
- Create a new folder where we will host the server files.
|
||||
- Copy the nssm.exe into this folder
|
||||
- Copy the build files to the server (only needed for intial install).
|
||||
- This will house all the compiles and minified files needed to start the server up, this includes the frontend.
|
||||
- Save the nssm.exe into this folder as well, this will be used to control the service.
|
||||
|
||||
## Do the intial install
|
||||
|
||||
### DB instal setup
|
||||
|
||||
1. Install postgres
|
||||
2. Open pgAdmin
|
||||
3. create a new Database named lst_db
|
||||
|
||||
### Intial server setup
|
||||
|
||||
1. Open VSCode and navigate to the folder where you extracted the files.
|
||||
2. Click trusted when it pops up.
|
||||
3. Open a terminal window inside vscode.
|
||||
4. Run the install script this will install all dependaceys needed as well as do all the database migrations
|
||||
|
||||
```bash
|
||||
npm run prodinstall
|
||||
```
|
||||
|
||||
Next we want to do an intial build for the db
|
||||
|
||||
```bash
|
||||
npm run build
|
||||
```
|
||||
|
||||
### Create the .env file
|
||||
|
||||
In the root of the folder create a new .env file
|
||||
add in the below and change each setting area that says change me to something that suits your needs
|
||||
|
||||
```env
|
||||
# PORTS
|
||||
# To keep it all simple we will pass VITE to the ports that are used on both sides.
|
||||
@@ -39,7 +58,9 @@ VITE_SERVER_PORT=4400
|
||||
|
||||
# logLevel
|
||||
LOG_LEVEL=debug
|
||||
|
||||
PROD_PORT=4000
|
||||
# DUE to lstv1 we need 3000
|
||||
SEC_PORT=3000
|
||||
# Auth stuff
|
||||
SALTING=12
|
||||
SECRET=CHANGEME
|
||||
@@ -64,62 +85,80 @@ MAXLOTS=3
|
||||
```
|
||||
|
||||
### Run the start command to get all the basic settings and modules installed
|
||||
|
||||
1. Run the below
|
||||
|
||||
```bash
|
||||
npm start
|
||||
```
|
||||
|
||||
This command will start up the server and seed the database.
|
||||
* Settings will be set here.
|
||||
* All modules will be added.
|
||||
|
||||
- Settings will be set here.
|
||||
- All modules will be added.
|
||||
|
||||
2. Press CTRL + C to stop the server.
|
||||
3. Reopen postgres and review the settings make the changes to match the server your going to be running in.
|
||||
* Change the server
|
||||
* change the dbServer
|
||||
* change plantToken
|
||||
* then the remaining settings confirm if you need on or want to leave as default.
|
||||
- Change the server
|
||||
- change the dbServer
|
||||
- change plantToken
|
||||
- then the remaining settings confirm if you need on or want to leave as default.
|
||||
|
||||
### Creating first user.
|
||||
|
||||
1. Start the server back up.
|
||||
|
||||
```bash
|
||||
npm start
|
||||
```
|
||||
|
||||
2. Open http://[SERVER]:[PORT]/api/docs or postman and create a user.
|
||||
* Please do not try to manually enter a new user this is due to how the password is hashed, as well as setting systemAdmin for the first user.
|
||||
* Change the server and port to what you changed in the DB.
|
||||
- Please do not try to manually enter a new user this is due to how the password is hashed, as well as setting systemAdmin for the first user.
|
||||
- Change the server and port to what you changed in the DB.
|
||||
3. Stop the server again with CTRL + C.
|
||||
|
||||
### Running as a serivice.
|
||||
|
||||
You want to CD into the scripts folder.
|
||||
|
||||
```bash
|
||||
cd .\dist\server\scripts\
|
||||
```
|
||||
|
||||
Next use the example command below to get the service up and running.
|
||||
* Options legend
|
||||
* serviceName = not recommended to change to reduce issues with the update process
|
||||
* option = use install for the install, but you can use this script later to stop, start, restart the service.
|
||||
* appPath = where did you extract the server files
|
||||
* description = no need to change this unless you want it to be something else
|
||||
* command = do not change this unless you know what your doing and really need to change this.
|
||||
|
||||
- Options legend
|
||||
- serviceName = not recommended to change to reduce issues with the update process
|
||||
- option = use install for the install, but you can use this script later to stop, start, restart the service.
|
||||
- appPath = where did you extract the server files
|
||||
- description = no need to change this unless you want it to be something else
|
||||
- command = do not change this unless you know what your doing and really need to change this.
|
||||
|
||||
```powershell
|
||||
.\services.ps1 -serviceName "LSTV2" -option "install" -appPath "E:\LST\lstV2" -description "Logistics Support Tool V2" -command "run start"
|
||||
```
|
||||
|
||||
# Migrating From V1 to V2
|
||||
|
||||
## User migration
|
||||
|
||||
1. Open the sqlite db and export to sql the users table
|
||||
2. OPen the sql in notepad++ or your editor of choice and change the query to be similar to below.
|
||||
* we only need to have save the username, role, email, password
|
||||
- we only need to have save the username, role, email, password
|
||||
|
||||
An example new query will look like
|
||||
* Below is how it looks when exported from sqlite
|
||||
|
||||
- Below is how it looks when exported from sqlite
|
||||
|
||||
```sql
|
||||
INSERT INTO "User" ("id", "username", "email", "role", "password", "passwordToken", "tokenExpire", "active", "pinCode", "lastLogin", "add_user", "add_date", "upd_user", "upd_date") VALUES
|
||||
(1, 'matthes01', 'blake.matthes@alpla.com', 'admin', 'JDJiJDEMUJEdGtL', NULL, NULL, '1', NULL, '1721075647687', 'LST_System', '1721075647687', 'LST_System', '1721075647687');
|
||||
```
|
||||
|
||||
The way we want to put recreate the query to work with the new db
|
||||
* Below example
|
||||
|
||||
- Below example
|
||||
|
||||
```sql
|
||||
INSERT INTO "users" ("username", "email", "role", "password") VALUES
|
||||
('matthes01','blake.matthes@alpla.com','admin','JDJiJDE1FuNFpkYlk4NGdHUXpEMzlHR1BD'),
|
||||
@@ -127,4 +166,12 @@ INSERT INTO "users" ("username", "email", "role", "password") VALUES
|
||||
('brandon001','brandon.harry@alpla.com','manager','wdm1RSXJlZnJDYTZP');
|
||||
;
|
||||
```
|
||||
* You could have many users and just add like above with the identical info from the db
|
||||
|
||||
- You could have many users and just add like above with the identical info from the db
|
||||
|
||||
## Running v1 along Side V2 for the interm
|
||||
|
||||
- change v2 prod port to 4000 in the env and db
|
||||
- change v1 env to 4400 in the env. and in the db you will need to change the auth server to 4000 and the serverPort to 4400
|
||||
|
||||
This will change so that v2 is the main server now, this is needed for ocme mainly.
|
||||
|
||||
@@ -204,12 +204,185 @@ $plantFunness = {
|
||||
###########################################################
|
||||
# Old system still active until we have everything off it
|
||||
###########################################################
|
||||
|
||||
###########################################################
|
||||
# Frontend env
|
||||
###########################################################
|
||||
|
||||
Write-Host "Creating the env file in the front end"
|
||||
$envContentTemplatef = @"
|
||||
NEXTAUTH_SECRET= "12348fssad5sdg2f2354afvfw34"
|
||||
NEXTAUTH_URL_INTERNAL= "http://localhost:3000"
|
||||
NEXTAUTH_URL="{url}"
|
||||
API_KEY= "E3ECD3619A943B98C6F33E3322362"
|
||||
"@
|
||||
|
||||
try {
|
||||
$url = "http://$($token)vms006:3000"
|
||||
|
||||
if ($token -eq "usiow2") {
|
||||
$url = "http://usiow1vms006:3001"
|
||||
}
|
||||
|
||||
if ($token -in @("test1", "test2", "test3")) {
|
||||
$url = "http://usmcd1vms036:3000"
|
||||
}
|
||||
|
||||
# Replace {url} with the actual $url
|
||||
$envContentf = $envContentTemplatef -replace "{url}", $url
|
||||
|
||||
# Define the path where the .env file should be created
|
||||
$envFilePathf = $obslst + "\apps\frontend\.env"
|
||||
Write-Host "Final URL: $url"
|
||||
# Write the content to the .env file
|
||||
$envContentf | Out-File -FilePath $envFilePathf -Encoding UTF8 -Force
|
||||
|
||||
# Optional: Verify the file was created
|
||||
if (Test-Path $envFilePathf) {
|
||||
Write-Host "`.env` file created successfully on $env:COMPUTERNAME at $envFilePathf"
|
||||
} else {
|
||||
Write-Host "Failed to create `.env` file on $env:COMPUTERNAME"
|
||||
}
|
||||
|
||||
} catch {
|
||||
Write-Host "Error: Failed to create `.env` file on $server - $_"
|
||||
}
|
||||
|
||||
###########################################################
|
||||
# DB env
|
||||
###########################################################
|
||||
|
||||
Write-Host "Creating the env file in the front end"
|
||||
$envContentTemplateb = @"
|
||||
DATABASE_URL="file:E:\LST\db\{dbLink}.db"
|
||||
"@
|
||||
|
||||
try {
|
||||
|
||||
$dbLink = "lstBackendDB"
|
||||
|
||||
if ($token -eq "usiow2") {
|
||||
$dbLink = "lstBackendDB_2"
|
||||
}
|
||||
|
||||
if ($token -in @("test1", "test2", "test3")) {
|
||||
$dbLink = "lstBackendDB"
|
||||
}
|
||||
|
||||
# Replace {url} with the actual $url
|
||||
$envContentb = $envContentTemplateb -replace "{dbLink}", $dbLink
|
||||
|
||||
# Define the path where the .env file should be created
|
||||
$envFilePathb = $obslst + "\packages\database\.env"
|
||||
|
||||
# Write the content to the .env file
|
||||
$envContentb | Out-File -FilePath $envFilePathb -Encoding UTF8 -Force
|
||||
|
||||
# Optional: Verify the file was created
|
||||
if (Test-Path $envFilePathb) {
|
||||
Write-Host "`.env` file created successfully on $env:COMPUTERNAME at $envFilePathb"
|
||||
} else {
|
||||
Write-Host "Failed to create `.env` file on $env:COMPUTERNAME"
|
||||
}
|
||||
|
||||
} catch {
|
||||
Write-Host "Error: Failed to create `.env` file on $server - $_"
|
||||
}
|
||||
|
||||
###########################################################
|
||||
# backend env
|
||||
###########################################################
|
||||
|
||||
Write-Host "Creating the env file in the front end"
|
||||
$envContentTemplated = @"
|
||||
# Server env
|
||||
NODE_ENV = production
|
||||
# server apiKey
|
||||
API_KEY = E3ECD3619A943B98C6F33E3322362
|
||||
# Prisma DB link
|
||||
DATABASE_URL="file:E:\LST\db\{dbLink}.db"
|
||||
# if you still want the db in the same folder as the server install you need to do like the example below else use the relevent link
|
||||
DATEBASE_LOC="E:\LST\db\{dbLink}.db"
|
||||
DATABASE_BACKUP_LOC="E:\LST\backups"
|
||||
# Server port
|
||||
GATEWAY_PORT={gatewayport}
|
||||
AUTH_PORT=4100
|
||||
SYSTEM_APP_PORT={systemport}
|
||||
OCME_PORT={ocme}
|
||||
|
||||
# This should me removed once we have the entire app broke out to its own apps
|
||||
OLD_APP_PORT={appPort}
|
||||
|
||||
# Logging
|
||||
LOG_LEVEL = info
|
||||
LOG_LOC ="E:\\LST\\logs"
|
||||
|
||||
# authentication
|
||||
SALTING = 12
|
||||
SECRET = E3ECD3619A943B98C6F33E3322362
|
||||
JWT_SECRET = 12348fssad5sdg2f2354afvfw34
|
||||
JWT_EXPIRES_TIME = 1h
|
||||
|
||||
# cookie time is in min please take this into consideration when creating all the times
|
||||
COOKIE_EXPIRES_TIME = 60
|
||||
|
||||
# password token reset in mintues
|
||||
RESET_TOKEN = 330
|
||||
"@
|
||||
|
||||
try {
|
||||
|
||||
$dbLink = "lstBackendDB"
|
||||
$gatewayport = "4400"
|
||||
$systemport = "4200"
|
||||
$ocmeport = "4300"
|
||||
$appport = "4900"
|
||||
|
||||
if ($token -eq "usiow2") {
|
||||
$dbLink = "lstBackendDB_2"
|
||||
$gatewayport = "4401"
|
||||
$systemport = "4201"
|
||||
$ocmeport = "4301"
|
||||
$appport = "4901"
|
||||
}
|
||||
|
||||
if ($token -in @("test1", "test2", "test3")) {
|
||||
$dbLink = "lstBackendDB"
|
||||
}
|
||||
|
||||
#
|
||||
$port1 = $envContentTemplated -replace "{gatewayport}", $gatewayport
|
||||
$port2 = $port1 -replace "{systemport}", $systemport
|
||||
$port3 = $port2 -replace "{ocme}", $ocmeport
|
||||
$port4 = $port3 -replace "{appPort}", $appport
|
||||
$envContentd = $port4 -replace "{dbLink}", $dbLink
|
||||
|
||||
|
||||
# Define the path where the .env file should be created
|
||||
$envFilePathd = $obslst + "\.env"
|
||||
|
||||
# Write the content to the .env file
|
||||
$envContentd | Out-File -FilePath $envFilePathd -Encoding UTF8 -Force
|
||||
|
||||
# Optional: Verify the file was created
|
||||
if (Test-Path $envFilePathd) {
|
||||
Write-Host "`.env` file created successfully on $env:COMPUTERNAME at $envFilePathd"
|
||||
} else {
|
||||
Write-Host "Failed to create `.env` file on $env:COMPUTERNAME"
|
||||
}
|
||||
|
||||
} catch {
|
||||
Write-Host "Error: Failed to create `.env` file on $server - $_"
|
||||
}
|
||||
|
||||
|
||||
Write-Host "Running install on obs server."
|
||||
Set-Location $obslst
|
||||
npm run newinstall # --omit=dev
|
||||
Write-Host "Update the frontend"
|
||||
npm run install:front
|
||||
npm run install:ui
|
||||
npm run install:db
|
||||
|
||||
Write-Host "Running db updates"
|
||||
npm run db:migrate
|
||||
|
||||
@@ -90,15 +90,32 @@ const updateBuildNumber = (appLock: string) => {
|
||||
// Write the updated data back
|
||||
fs.writeFileSync(packagePath, JSON.stringify(pkgJson, null, 2), "utf8");
|
||||
|
||||
createLog("info", "lst", "zipUpBuild", `Build number updated to: ${pkgJson.admConfig.build}`);
|
||||
createLog(
|
||||
"info",
|
||||
"lst",
|
||||
"zipUpBuild",
|
||||
`Build number updated to: ${pkgJson.admConfig.build}`
|
||||
);
|
||||
// Auto-commit changes
|
||||
execSync("git add package.json");
|
||||
execSync(`git commit -m "chore: bump build number to ${pkgJson.admConfig.build}"`);
|
||||
execSync(
|
||||
`git commit -m "build: bump build number to ${pkgJson.admConfig.build}"`
|
||||
);
|
||||
} else {
|
||||
createLog("error", "lst", "zipUpBuild", "admConfig.build is missing or not a number");
|
||||
createLog(
|
||||
"error",
|
||||
"lst",
|
||||
"zipUpBuild",
|
||||
"admConfig.build is missing or not a number"
|
||||
);
|
||||
}
|
||||
} catch (error) {
|
||||
createLog("error", "lst", "zipUpBuild", `Error updating build number: ${error}`);
|
||||
createLog(
|
||||
"error",
|
||||
"lst",
|
||||
"zipUpBuild",
|
||||
`Error updating build number: ${error}`
|
||||
);
|
||||
}
|
||||
};
|
||||
|
||||
@@ -113,10 +130,18 @@ export const createZip = async (appLock: string) => {
|
||||
addToZip(zip, srcPath, srcPath);
|
||||
|
||||
// Write the zip file to disk
|
||||
const outputZipPath = path.join(destPath, `${app.name}-${app.version}-${app.admConfig.build}.zip`);
|
||||
const outputZipPath = path.join(
|
||||
destPath,
|
||||
`${app.name}-${app.version}-${app.admConfig.build}.zip`
|
||||
);
|
||||
zip.writeZip(outputZipPath);
|
||||
|
||||
createLog("info", "lst", "zipUpBuild", `Zip file created at ${outputZipPath}`);
|
||||
createLog(
|
||||
"info",
|
||||
"lst",
|
||||
"zipUpBuild",
|
||||
`Zip file created at ${outputZipPath}`
|
||||
);
|
||||
updateBuildNumber(appLock);
|
||||
|
||||
// only keep the last 5 builds for the type we have.
|
||||
@@ -130,7 +155,12 @@ export const createZip = async (appLock: string) => {
|
||||
}))
|
||||
.sort((a, b) => a.time - b.time); // Sort by modification time (oldest first)
|
||||
|
||||
createLog("info", "lst", "zipUpBuild", `app Files (sorted by time):", ${JSON.stringify(appFiles)}`);
|
||||
createLog(
|
||||
"info",
|
||||
"lst",
|
||||
"zipUpBuild",
|
||||
`app Files (sorted by time):", ${JSON.stringify(appFiles)}`
|
||||
);
|
||||
|
||||
if (appFiles.length > 5) {
|
||||
appFiles.slice(0, -5).forEach((file) => {
|
||||
@@ -139,14 +169,24 @@ export const createZip = async (appLock: string) => {
|
||||
fs.unlinkSync(filePath);
|
||||
createLog("info", "lst", "zipUpBuild", `Deleted: ${file.name}`);
|
||||
} catch (error: any) {
|
||||
createLog("error", "lst", "zipUpBuild", `Failed to delete ${file.name}: ${error.message}`);
|
||||
createLog(
|
||||
"error",
|
||||
"lst",
|
||||
"zipUpBuild",
|
||||
`Failed to delete ${file.name}: ${error.message}`
|
||||
);
|
||||
}
|
||||
});
|
||||
} else {
|
||||
createLog("info", "lst", "zipUpBuild", "No files to delete.");
|
||||
}
|
||||
} catch (error: any) {
|
||||
createLog("error", "lst", "zipUpBuild", `Error reading directory or deleting files:", ${error.message}`);
|
||||
createLog(
|
||||
"error",
|
||||
"lst",
|
||||
"zipUpBuild",
|
||||
`Error reading directory or deleting files:", ${error.message}`
|
||||
);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@@ -1,13 +1,14 @@
|
||||
import { OpenAPIHono } from "@hono/zod-openapi";
|
||||
import {authMiddleware} from "./middleware/authMiddleware.js";
|
||||
|
||||
import login from "./routes/login.js";
|
||||
import register from "./routes/register.js";
|
||||
import session from "./routes/session.js";
|
||||
import getAccess from "./routes/userRoles/getUserRoles.js";
|
||||
import setAccess from "./routes/userRoles/setUserRoles.js";
|
||||
import getAccess from "./routes/user/getUserRoles.js";
|
||||
import setAccess from "./routes/userAdmin/setUserRoles.js";
|
||||
import profile from "./routes/user/profileUpdate.js";
|
||||
import { areRolesIn } from "./utils/roleCheck.js";
|
||||
import createUser from "./routes/userAdmin/createUser.js";
|
||||
import allUsers from "./routes/userAdmin/getUsers.js";
|
||||
import updateUser from "./routes/userAdmin/updateUser.js";
|
||||
|
||||
const app = new OpenAPIHono();
|
||||
|
||||
@@ -16,15 +17,21 @@ setTimeout(() => {
|
||||
areRolesIn();
|
||||
}, 5000);
|
||||
|
||||
app.route("auth/login", login);
|
||||
app.route("auth/register", register);
|
||||
app.route("auth/session", session);
|
||||
const routes = [
|
||||
login,
|
||||
register,
|
||||
session,
|
||||
profile,
|
||||
getAccess,
|
||||
setAccess,
|
||||
createUser,
|
||||
allUsers,
|
||||
updateUser,
|
||||
] as const;
|
||||
|
||||
// required to login
|
||||
/* User area just needs to be logged in to enter here */
|
||||
app.route("auth/profileupdate", profile);
|
||||
// app.route("/server", modules);
|
||||
const appRoutes = routes.forEach((route) => {
|
||||
app.route("/auth", route);
|
||||
});
|
||||
|
||||
/* will need to increase to make sure the person coming here has the correct permissions */
|
||||
app.route("auth/getuseraccess", getAccess);
|
||||
app.route("auth/setuseraccess", setAccess);
|
||||
export default app;
|
||||
|
||||
24
server/services/auth/controllers/userAdmin/getUsers.ts
Normal file
24
server/services/auth/controllers/userAdmin/getUsers.ts
Normal file
@@ -0,0 +1,24 @@
|
||||
import { db } from "../../../../../database/dbclient.js";
|
||||
import { users } from "../../../../../database/schema/users.js";
|
||||
import { returnRes } from "../../../../globalUtils/routeDefs/returnRes.js";
|
||||
import { tryCatch } from "../../../../globalUtils/tryCatch.js";
|
||||
import { createLog } from "../../../logger/logger.js";
|
||||
|
||||
export const getAllUsers = async () => {
|
||||
/**
|
||||
* returns all users that are in lst
|
||||
*/
|
||||
createLog("info", "apiAuthedRoute", "auth", "Get all users");
|
||||
const { data, error } = await tryCatch(db.select().from(users));
|
||||
|
||||
if (error) {
|
||||
returnRes(
|
||||
false,
|
||||
"There was an error getting users",
|
||||
new Error("No user exists.")
|
||||
);
|
||||
}
|
||||
|
||||
returnRes(true, "All users.", data);
|
||||
return { success: true, message: "All users", data };
|
||||
};
|
||||
68
server/services/auth/controllers/userAdmin/updateUserAdm.ts
Normal file
68
server/services/auth/controllers/userAdmin/updateUserAdm.ts
Normal file
@@ -0,0 +1,68 @@
|
||||
import { eq } from "drizzle-orm";
|
||||
import { db } from "../../../../../database/dbclient.js";
|
||||
import { users } from "../../../../../database/schema/users.js";
|
||||
import { tryCatch } from "../../../../globalUtils/tryCatch.js";
|
||||
import type { User } from "../../../../types/users.js";
|
||||
import { createPassword } from "../../utils/createPassword.js";
|
||||
import { createLog } from "../../../logger/logger.js";
|
||||
|
||||
export const updateUserADM = async (userData: User) => {
|
||||
/**
|
||||
* The user model will need to be passed over so we can update per the request on the user.
|
||||
* password, username, email.
|
||||
*/
|
||||
|
||||
createLog(
|
||||
"info",
|
||||
"apiAuthedRoute",
|
||||
"auth",
|
||||
`${userData.user_id} is being updated.`
|
||||
);
|
||||
// get the orignal user info
|
||||
const { data: user, error: userError } = await tryCatch(
|
||||
db.select().from(users).where(eq(users.user_id, userData.user_id!))
|
||||
);
|
||||
|
||||
if (userError) {
|
||||
return {
|
||||
success: false,
|
||||
message: "There was an error getting the user",
|
||||
userError,
|
||||
};
|
||||
}
|
||||
if (user?.length === 0) {
|
||||
return {
|
||||
success: false,
|
||||
message:
|
||||
"The user you are looking for has either been deleted or dose not exist.",
|
||||
};
|
||||
}
|
||||
const upd_user = user as User;
|
||||
const password: string = userData.password
|
||||
? await createPassword(userData.password!)
|
||||
: upd_user.password!;
|
||||
const data = {
|
||||
username: userData.username ? userData.username : upd_user?.username,
|
||||
password: password,
|
||||
email: userData.email ? userData.email : upd_user.email,
|
||||
};
|
||||
|
||||
// term ? ilike(posts.title, term) : undefined
|
||||
const { data: updData, error: updError } = await tryCatch(
|
||||
db.update(users).set(data).where(eq(users.user_id, userData.user_id!))
|
||||
);
|
||||
|
||||
if (updError) {
|
||||
return {
|
||||
success: false,
|
||||
message: "There was an error getting the user",
|
||||
updError,
|
||||
};
|
||||
}
|
||||
|
||||
return {
|
||||
success: true,
|
||||
message: `${userData.username} has been updated.`,
|
||||
updData,
|
||||
};
|
||||
};
|
||||
85
server/services/auth/middleware/roleCheck.ts
Normal file
85
server/services/auth/middleware/roleCheck.ts
Normal file
@@ -0,0 +1,85 @@
|
||||
import { createMiddleware } from "hono/factory";
|
||||
|
||||
import type { CustomJwtPayload } from "../../../types/jwtToken.js";
|
||||
import { verify } from "hono/jwt";
|
||||
import { db } from "../../../../database/dbclient.js";
|
||||
import { modules } from "../../../../database/schema/modules.js";
|
||||
import { and, eq } from "drizzle-orm";
|
||||
import { userRoles } from "../../../../database/schema/userRoles.js";
|
||||
import { tryCatch } from "../../../globalUtils/tryCatch.js";
|
||||
|
||||
const hasCorrectRole = (requiredRole: string[], module: string) =>
|
||||
createMiddleware(async (c, next) => {
|
||||
/**
|
||||
* We want to check to make sure you have the correct role to be here
|
||||
*/
|
||||
const authHeader = c.req.header("Authorization");
|
||||
|
||||
if (!authHeader || !authHeader.startsWith("Bearer ")) {
|
||||
return c.json({ error: "Unauthorized" }, 401);
|
||||
}
|
||||
|
||||
const token = authHeader.split(" ")[1];
|
||||
|
||||
// deal with token data
|
||||
const { data: tokenData, error: tokenError } = await tryCatch(
|
||||
verify(token, process.env.JWT_SECRET!)
|
||||
);
|
||||
|
||||
if (tokenError) {
|
||||
return c.json({ error: "Invalid token" }, 401);
|
||||
}
|
||||
|
||||
const customToken = tokenData as CustomJwtPayload;
|
||||
|
||||
// Get the module
|
||||
const { data: mod, error: modError } = await tryCatch(
|
||||
db.select().from(modules).where(eq(modules.name, module))
|
||||
);
|
||||
if (modError) {
|
||||
console.log(modError);
|
||||
return;
|
||||
}
|
||||
|
||||
if (mod.length === 0) {
|
||||
return c.json({ error: "You have entered an invalid module name" }, 403);
|
||||
}
|
||||
|
||||
// check if the user has the role needed to get into this module
|
||||
const { data: userRole, error: userRoleError } = await tryCatch(
|
||||
db
|
||||
.select()
|
||||
.from(userRoles)
|
||||
.where(
|
||||
and(
|
||||
eq(userRoles.module_id, mod[0].module_id),
|
||||
eq(userRoles.user_id, customToken.user?.user_id!)
|
||||
)
|
||||
)
|
||||
);
|
||||
|
||||
if (userRoleError) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!userRole) {
|
||||
return c.json(
|
||||
{
|
||||
error:
|
||||
"The module you are trying to access is not active or is invalid.",
|
||||
},
|
||||
403
|
||||
);
|
||||
}
|
||||
|
||||
if (!requiredRole.includes(userRole[0]?.role)) {
|
||||
return c.json(
|
||||
{ error: "You do not have access to this part of the app." },
|
||||
403
|
||||
);
|
||||
}
|
||||
|
||||
await next();
|
||||
});
|
||||
|
||||
export default hasCorrectRole;
|
||||
@@ -16,7 +16,7 @@ const route = createRoute({
|
||||
summary: "Login as user",
|
||||
description: "Login as a user to get a JWT token",
|
||||
method: "post",
|
||||
path: "/",
|
||||
path: "/login",
|
||||
request: {
|
||||
body: {
|
||||
content: {
|
||||
@@ -42,7 +42,9 @@ const route = createRoute({
|
||||
"application/json": {
|
||||
schema: z.object({
|
||||
success: z.boolean().openapi({ example: false }),
|
||||
message: z.string().openapi({example: "Username and password required"}),
|
||||
message: z
|
||||
.string()
|
||||
.openapi({ example: "Username and password required" }),
|
||||
}),
|
||||
},
|
||||
},
|
||||
@@ -53,7 +55,9 @@ const route = createRoute({
|
||||
"application/json": {
|
||||
schema: z.object({
|
||||
success: z.boolean().openapi({ example: false }),
|
||||
message: z.string().openapi({example: "Username and password required"}),
|
||||
message: z
|
||||
.string()
|
||||
.openapi({ example: "Username and password required" }),
|
||||
}),
|
||||
},
|
||||
},
|
||||
@@ -81,7 +85,10 @@ app.openapi(route, async (c) => {
|
||||
// Set the JWT as an HTTP-only cookie
|
||||
//c.header("Set-Cookie", `auth_token=${token}; HttpOnly; Secure; Path=/; SameSite=None; Max-Age=3600`);
|
||||
|
||||
return c.json({success: true, message: "Login successful", user, token}, 200);
|
||||
return c.json(
|
||||
{ success: true, message: "Login successful", user, token },
|
||||
200
|
||||
);
|
||||
} catch (err) {
|
||||
return c.json({ success: false, message: "Incorrect Credentials" }, 401);
|
||||
}
|
||||
|
||||
@@ -13,8 +13,12 @@ const UserSchema = z.object({
|
||||
password: z
|
||||
.string()
|
||||
.min(6, { message: "Passwords must be longer than 3 characters" })
|
||||
.regex(/[A-Z]/, {message: "Password must contain at least one uppercase letter"})
|
||||
.regex(/[\W_]/, {message: "Password must contain at least one special character"})
|
||||
.regex(/[A-Z]/, {
|
||||
message: "Password must contain at least one uppercase letter",
|
||||
})
|
||||
.regex(/[\W_]/, {
|
||||
message: "Password must contain at least one special character",
|
||||
})
|
||||
.openapi({ example: "Password1!" }),
|
||||
});
|
||||
|
||||
@@ -30,7 +34,7 @@ app.openapi(
|
||||
tags: ["Auth"],
|
||||
summary: "Register a new user",
|
||||
method: "post",
|
||||
path: "/",
|
||||
path: "/register",
|
||||
request: {
|
||||
body: {
|
||||
content: {
|
||||
@@ -48,7 +52,9 @@ app.openapi(
|
||||
"application/json": {
|
||||
schema: z.object({
|
||||
success: z.boolean().openapi({ example: false }),
|
||||
message: z.string().openapi({example: "Invalid credentials passed"}),
|
||||
message: z
|
||||
.string()
|
||||
.openapi({ example: "Invalid credentials passed" }),
|
||||
}),
|
||||
},
|
||||
},
|
||||
@@ -80,7 +86,14 @@ app.openapi(
|
||||
try {
|
||||
const register = await registerUser(username, password, email);
|
||||
|
||||
return c.json({success: register.success, message: register.message, user: register?.user}, 200);
|
||||
return c.json(
|
||||
{
|
||||
success: register.success,
|
||||
message: register.message,
|
||||
user: register?.user,
|
||||
},
|
||||
200
|
||||
);
|
||||
} catch (error) {
|
||||
console.log(error);
|
||||
return c.json(
|
||||
|
||||
@@ -18,8 +18,12 @@ const UserSchema = z.object({
|
||||
password: z
|
||||
.string()
|
||||
.min(6, { message: "Passwords must be longer than 3 characters" })
|
||||
.regex(/[A-Z]/, {message: "Password must contain at least one uppercase letter"})
|
||||
.regex(/[\W_]/, {message: "Password must contain at least one special character"})
|
||||
.regex(/[A-Z]/, {
|
||||
message: "Password must contain at least one uppercase letter",
|
||||
})
|
||||
.regex(/[\W_]/, {
|
||||
message: "Password must contain at least one special character",
|
||||
})
|
||||
.openapi({ example: "Password1!" }),
|
||||
});
|
||||
|
||||
@@ -29,7 +33,7 @@ session.openapi(
|
||||
summary: "Checks a user session based on there token",
|
||||
description: "Can post there via Authentiaction header or cookies",
|
||||
method: "get",
|
||||
path: "/",
|
||||
path: "/session",
|
||||
middleware: authMiddleware,
|
||||
// request: {
|
||||
// body: {
|
||||
@@ -44,7 +48,11 @@ session.openapi(
|
||||
"application/json": {
|
||||
schema: z.object({
|
||||
data: z.object({
|
||||
token: z.string().openapi({example: "sdkjhgsldkvhdakl;jvhs;adkjfhvds.kvnsad;ovhads"}),
|
||||
token: z
|
||||
.string()
|
||||
.openapi({
|
||||
example: "sdkjhgsldkvhdakl;jvhs;adkjfhvds.kvnsad;ovhads",
|
||||
}),
|
||||
// user: z.object({
|
||||
// user_id: z.string().openapi({example: "04316c86-f086-4cc6-b3d4-cca164a26f3f"}),
|
||||
// username: z.string().openapi({example: "smith"}),
|
||||
@@ -72,7 +80,10 @@ session.openapi(
|
||||
const authHeader = c.req.header("Authorization");
|
||||
|
||||
if (authHeader?.includes("Basic")) {
|
||||
return c.json({message: "You are a Basic user! Please login to get a token"}, 401);
|
||||
return c.json(
|
||||
{ message: "You are a Basic user! Please login to get a token" },
|
||||
401
|
||||
);
|
||||
}
|
||||
|
||||
if (!authHeader) {
|
||||
@@ -85,7 +96,9 @@ session.openapi(
|
||||
const payload = await verify(token, process.env.JWT_SECRET!);
|
||||
|
||||
// If it's valid, return a new token
|
||||
const newToken = sign({user: payload.user}, secret, {expiresIn: expiresIn * 60});
|
||||
const newToken = sign({ user: payload.user }, secret, {
|
||||
expiresIn: expiresIn * 60,
|
||||
});
|
||||
|
||||
return c.json({ data: { token: newToken, user: payload.user } }, 200);
|
||||
} catch (error) {
|
||||
|
||||
59
server/services/auth/routes/user/getUserRoles.ts
Normal file
59
server/services/auth/routes/user/getUserRoles.ts
Normal file
@@ -0,0 +1,59 @@
|
||||
import { z, createRoute, OpenAPIHono } from "@hono/zod-openapi";
|
||||
import jwt from "jsonwebtoken";
|
||||
import type { CustomJwtPayload } from "../../../../types/jwtToken.js";
|
||||
import { authMiddleware } from "../../middleware/authMiddleware.js";
|
||||
import { roleCheck } from "../../controllers/userRoles/getUserAccess.js";
|
||||
|
||||
const { verify } = jwt;
|
||||
const app = new OpenAPIHono();
|
||||
|
||||
const responseSchema = z.object({
|
||||
message: z.string().optional().openapi({ example: "User Created" }),
|
||||
});
|
||||
|
||||
app.openapi(
|
||||
createRoute({
|
||||
tags: ["auth:user"],
|
||||
summary: "returns the users access",
|
||||
method: "get",
|
||||
path: "/getuseraccess",
|
||||
middleware: [authMiddleware],
|
||||
responses: {
|
||||
200: {
|
||||
content: { "application/json": { schema: responseSchema } },
|
||||
description: "Retrieve the user",
|
||||
},
|
||||
},
|
||||
}),
|
||||
async (c) => {
|
||||
// apit hit
|
||||
//apiHit(c, { endpoint: "api/auth/getUserRoles" });
|
||||
const authHeader = c.req.header("Authorization");
|
||||
const token = authHeader?.split("Bearer ")[1] || "";
|
||||
try {
|
||||
const secret = process.env.JWT_SECRET!;
|
||||
if (!secret) {
|
||||
throw new Error("JWT_SECRET is not defined in environment variables");
|
||||
}
|
||||
|
||||
const payload = verify(token, secret) as CustomJwtPayload;
|
||||
|
||||
const canAccess = await roleCheck(payload.user?.user_id);
|
||||
|
||||
return c.json(
|
||||
{
|
||||
sucess: true,
|
||||
message: `User ${payload.user?.username} can access`,
|
||||
data: canAccess,
|
||||
},
|
||||
200
|
||||
);
|
||||
} catch (error) {
|
||||
console.log(error);
|
||||
}
|
||||
|
||||
return c.json({ message: "UserRoles coming over" });
|
||||
}
|
||||
);
|
||||
|
||||
export default app;
|
||||
@@ -10,17 +10,21 @@ const UserSchema = z.object({
|
||||
password: z
|
||||
.string()
|
||||
.min(6, { message: "Passwords must be longer than 3 characters" })
|
||||
.regex(/[A-Z]/, {message: "Password must contain at least one uppercase letter"})
|
||||
.regex(/[\W_]/, {message: "Password must contain at least one special character"})
|
||||
.regex(/[A-Z]/, {
|
||||
message: "Password must contain at least one uppercase letter",
|
||||
})
|
||||
.regex(/[\W_]/, {
|
||||
message: "Password must contain at least one special character",
|
||||
})
|
||||
.openapi({ example: "Password1!" }),
|
||||
});
|
||||
app.openapi(
|
||||
createRoute({
|
||||
tags: ["User"],
|
||||
tags: ["auth:user"],
|
||||
summary: "Updates a users Profile",
|
||||
description: "Currently you can only update your password over the API",
|
||||
method: "post",
|
||||
path: "/",
|
||||
path: "/profile",
|
||||
middleware: authMiddleware,
|
||||
request: {
|
||||
body: {
|
||||
@@ -34,7 +38,10 @@ app.openapi(
|
||||
content: {
|
||||
"application/json": {
|
||||
schema: z.object({
|
||||
message: z.string().optional().openapi({example: "User Profile has been updated"}),
|
||||
message: z
|
||||
.string()
|
||||
.optional()
|
||||
.openapi({ example: "User Profile has been updated" }),
|
||||
}),
|
||||
},
|
||||
},
|
||||
@@ -43,7 +50,12 @@ app.openapi(
|
||||
401: {
|
||||
content: {
|
||||
"application/json": {
|
||||
schema: z.object({message: z.string().optional().openapi({example: "Unauthenticated"})}),
|
||||
schema: z.object({
|
||||
message: z
|
||||
.string()
|
||||
.optional()
|
||||
.openapi({ example: "Unauthenticated" }),
|
||||
}),
|
||||
},
|
||||
},
|
||||
description: "Unauthorized",
|
||||
@@ -51,7 +63,12 @@ app.openapi(
|
||||
500: {
|
||||
content: {
|
||||
"application/json": {
|
||||
schema: z.object({message: z.string().optional().openapi({example: "Internal Server error"})}),
|
||||
schema: z.object({
|
||||
message: z
|
||||
.string()
|
||||
.optional()
|
||||
.openapi({ example: "Internal Server error" }),
|
||||
}),
|
||||
},
|
||||
},
|
||||
description: "Internal Server Error",
|
||||
@@ -63,7 +80,10 @@ app.openapi(
|
||||
const authHeader = c.req.header("Authorization");
|
||||
|
||||
if (authHeader?.includes("Basic")) {
|
||||
return c.json({message: "You are a Basic user! Please login to get a token"}, 401);
|
||||
return c.json(
|
||||
{ message: "You are a Basic user! Please login to get a token" },
|
||||
401
|
||||
);
|
||||
}
|
||||
|
||||
if (!authHeader) {
|
||||
@@ -77,7 +97,12 @@ app.openapi(
|
||||
const payload = await verify(token, process.env.JWT_SECRET!);
|
||||
user = payload.user;
|
||||
} catch (error) {
|
||||
createLog("error", "lst", "auth", "Failed session check, user must be logged out");
|
||||
createLog(
|
||||
"error",
|
||||
"lst",
|
||||
"auth",
|
||||
"Failed session check, user must be logged out"
|
||||
);
|
||||
return c.json({ message: "Unauthorized" }, 401);
|
||||
}
|
||||
|
||||
|
||||
115
server/services/auth/routes/userAdmin/createUser.ts
Normal file
115
server/services/auth/routes/userAdmin/createUser.ts
Normal file
@@ -0,0 +1,115 @@
|
||||
import { z, createRoute, OpenAPIHono } from "@hono/zod-openapi";
|
||||
import { registerUser } from "../../controllers/register.js";
|
||||
import { authMiddleware } from "../../middleware/authMiddleware.js";
|
||||
import hasCorrectRole from "../../middleware/roleCheck.js";
|
||||
|
||||
const app = new OpenAPIHono();
|
||||
|
||||
const UserSchema = z.object({
|
||||
username: z
|
||||
.string()
|
||||
.regex(/^[a-zA-Z0-9_]{3,30}$/)
|
||||
.openapi({ example: "smith034" }),
|
||||
email: z.string().email().openapi({ example: "smith@example.com" }),
|
||||
password: z
|
||||
.string()
|
||||
.min(6, { message: "Passwords must be longer than 3 characters" })
|
||||
.regex(/[A-Z]/, {
|
||||
message: "Password must contain at least one uppercase letter",
|
||||
})
|
||||
.regex(/[\W_]/, {
|
||||
message: "Password must contain at least one special character",
|
||||
})
|
||||
.openapi({ example: "Password1!" }),
|
||||
});
|
||||
|
||||
type User = z.infer<typeof UserSchema>;
|
||||
|
||||
const responseSchema = z.object({
|
||||
success: z.boolean().optional().openapi({ example: true }),
|
||||
message: z.string().optional().openapi({ example: "User Created" }),
|
||||
});
|
||||
|
||||
app.openapi(
|
||||
createRoute({
|
||||
tags: ["Auth:admin"],
|
||||
summary: "Creates user",
|
||||
method: "post",
|
||||
path: "/",
|
||||
middleware: [
|
||||
authMiddleware,
|
||||
hasCorrectRole(["admin", "systemAdmin"], "admin"),
|
||||
],
|
||||
request: {
|
||||
body: {
|
||||
content: {
|
||||
"application/json": { schema: UserSchema },
|
||||
},
|
||||
},
|
||||
},
|
||||
responses: {
|
||||
200: {
|
||||
content: { "application/json": { schema: responseSchema } },
|
||||
description: "Retrieve the user",
|
||||
},
|
||||
400: {
|
||||
content: {
|
||||
"application/json": {
|
||||
schema: z.object({
|
||||
success: z.boolean().openapi({ example: false }),
|
||||
message: z
|
||||
.string()
|
||||
.openapi({ example: "Invalid credentials passed" }),
|
||||
}),
|
||||
},
|
||||
},
|
||||
description: "Retrieve the user",
|
||||
},
|
||||
},
|
||||
}),
|
||||
async (c) => {
|
||||
// apit hit
|
||||
//apiHit(c, {endpoint: "api/auth/register"});
|
||||
let { username, email, password } = await c.req.json();
|
||||
|
||||
if (!username || !email || !password) {
|
||||
return c.json({ success: false, message: "Credentials missing" }, 400);
|
||||
}
|
||||
|
||||
// some usernames that should be ignored
|
||||
const badActors = ["admin", "root"];
|
||||
if (badActors.includes(username)) {
|
||||
return c.json(
|
||||
{
|
||||
success: false,
|
||||
message: `${username} is not a valid name to be registerd please try again`,
|
||||
},
|
||||
400
|
||||
);
|
||||
}
|
||||
|
||||
try {
|
||||
const register = await registerUser(username, password, email);
|
||||
|
||||
return c.json(
|
||||
{
|
||||
success: register.success,
|
||||
message: register.message,
|
||||
user: register?.user,
|
||||
},
|
||||
200
|
||||
);
|
||||
} catch (error) {
|
||||
console.log(error);
|
||||
return c.json(
|
||||
{
|
||||
success: false,
|
||||
message: `${username} already exists please login or reset password, if you feel this is an error please contact your admin.`,
|
||||
},
|
||||
400
|
||||
);
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
export default app;
|
||||
35
server/services/auth/routes/userAdmin/getUsers.ts
Normal file
35
server/services/auth/routes/userAdmin/getUsers.ts
Normal file
@@ -0,0 +1,35 @@
|
||||
import { z, createRoute, OpenAPIHono } from "@hono/zod-openapi";
|
||||
|
||||
import { responses } from "../../../../globalUtils/routeDefs/responses.js";
|
||||
|
||||
import { getAllUsers } from "../../controllers/userAdmin/getUsers.js";
|
||||
import { authMiddleware } from "../../middleware/authMiddleware.js";
|
||||
import hasCorrectRole from "../../middleware/roleCheck.js";
|
||||
|
||||
const app = new OpenAPIHono();
|
||||
|
||||
app.openapi(
|
||||
createRoute({
|
||||
tags: ["Auth:admin"],
|
||||
summary: "Gets Users",
|
||||
method: "get",
|
||||
path: "/allusers",
|
||||
middleware: [
|
||||
authMiddleware,
|
||||
hasCorrectRole(["admin", "systemAdmin"], "admin"),
|
||||
],
|
||||
responses: responses(),
|
||||
}),
|
||||
async (c) => {
|
||||
// apit hit
|
||||
//apiHit(c, {endpoint: "api/auth/register"});
|
||||
const allUsers: any = await getAllUsers();
|
||||
return c.json({
|
||||
success: allUsers?.success,
|
||||
message: allUsers?.message,
|
||||
data: allUsers?.data,
|
||||
});
|
||||
}
|
||||
);
|
||||
|
||||
export default app;
|
||||
71
server/services/auth/routes/userAdmin/setUserRoles.ts
Normal file
71
server/services/auth/routes/userAdmin/setUserRoles.ts
Normal file
@@ -0,0 +1,71 @@
|
||||
import { createRoute, OpenAPIHono, z } from "@hono/zod-openapi";
|
||||
import { setUserAccess } from "../../controllers/userRoles/setUserRoles.js";
|
||||
import { apiHit } from "../../../../globalUtils/apiHits.js";
|
||||
import { apiReturn } from "../../../../globalUtils/apiReturn.js";
|
||||
import { authMiddleware } from "../../middleware/authMiddleware.js";
|
||||
import hasCorrectRole from "../../middleware/roleCheck.js";
|
||||
import { responses } from "../../../../globalUtils/routeDefs/responses.js";
|
||||
|
||||
const app = new OpenAPIHono();
|
||||
|
||||
const responseSchema = z.object({
|
||||
success: z.boolean().openapi({ example: true }),
|
||||
message: z.string().optional().openapi({ example: "user access" }),
|
||||
data: z.array(z.object({})).optional().openapi({ example: [] }),
|
||||
});
|
||||
|
||||
const UserAccess = z.object({
|
||||
username: z
|
||||
.string()
|
||||
.regex(/^[a-zA-Z0-9_]{3,30}$/)
|
||||
.openapi({ example: "smith034" }),
|
||||
module: z.string().openapi({ example: "production" }),
|
||||
role: z.string().openapi({ example: "viewer" }),
|
||||
override: z.string().optional().openapi({ example: "secretString" }),
|
||||
});
|
||||
|
||||
app.openapi(
|
||||
createRoute({
|
||||
tags: ["Auth:admin"],
|
||||
summary: "Sets Users access",
|
||||
method: "post",
|
||||
path: "/setuseraccess",
|
||||
middleware: [
|
||||
authMiddleware,
|
||||
hasCorrectRole(["admin", "systemAdmin"], "admin"),
|
||||
],
|
||||
description: "When logged in you will be able to grant new permissions",
|
||||
request: {
|
||||
body: {
|
||||
content: {
|
||||
"application/json": { schema: UserAccess },
|
||||
},
|
||||
},
|
||||
},
|
||||
responses: responses(),
|
||||
}),
|
||||
async (c) => {
|
||||
//apiHit(c, { endpoint: "api/auth/setUserRoles" });
|
||||
const { username, module, role, override } = await c.req.json();
|
||||
try {
|
||||
const access = await setUserAccess(username, module, role, override);
|
||||
//return apiReturn(c, true, access?.message, access?.data, 200);
|
||||
return c.json(
|
||||
{ success: access.success, message: access.message, data: access.data },
|
||||
200
|
||||
);
|
||||
} catch (error) {
|
||||
console.log(error);
|
||||
//return apiReturn(c, false, "Error in setting the user access", error, 400);
|
||||
return c.json(
|
||||
{
|
||||
success: false,
|
||||
message: "Error in setting the user access",
|
||||
data: error,
|
||||
},
|
||||
400
|
||||
);
|
||||
}
|
||||
}
|
||||
);
|
||||
export default app;
|
||||
91
server/services/auth/routes/userAdmin/updateUser.ts
Normal file
91
server/services/auth/routes/userAdmin/updateUser.ts
Normal file
@@ -0,0 +1,91 @@
|
||||
import { createRoute, OpenAPIHono, z } from "@hono/zod-openapi";
|
||||
import { setUserAccess } from "../../controllers/userRoles/setUserRoles.js";
|
||||
import { apiHit } from "../../../../globalUtils/apiHits.js";
|
||||
import { apiReturn } from "../../../../globalUtils/apiReturn.js";
|
||||
import { authMiddleware } from "../../middleware/authMiddleware.js";
|
||||
import hasCorrectRole from "../../middleware/roleCheck.js";
|
||||
import { responses } from "../../../../globalUtils/routeDefs/responses.js";
|
||||
import { updateUserADM } from "../../controllers/userAdmin/updateUserAdm.js";
|
||||
|
||||
const app = new OpenAPIHono();
|
||||
|
||||
const responseSchema = z.object({
|
||||
success: z.boolean().openapi({ example: true }),
|
||||
message: z.string().optional().openapi({ example: "user access" }),
|
||||
data: z.array(z.object({})).optional().openapi({ example: [] }),
|
||||
});
|
||||
|
||||
const UserAccess = z.object({
|
||||
user_id: z.string().openapi({ example: "users UUID" }),
|
||||
username: z
|
||||
.string()
|
||||
.regex(/^[a-zA-Z0-9_]{3,30}$/)
|
||||
.optional()
|
||||
.openapi({ example: "smith034" }),
|
||||
email: z
|
||||
.string()
|
||||
.email()
|
||||
.optional()
|
||||
.openapi({ example: "smith@example.com" }),
|
||||
password: z
|
||||
.string()
|
||||
.min(6, { message: "Passwords must be longer than 3 characters" })
|
||||
.regex(/[A-Z]/, {
|
||||
message: "Password must contain at least one uppercase letter",
|
||||
})
|
||||
.regex(/[\W_]/, {
|
||||
message: "Password must contain at least one special character",
|
||||
})
|
||||
.optional()
|
||||
.openapi({ example: "Password1!" }),
|
||||
});
|
||||
|
||||
app.openapi(
|
||||
createRoute({
|
||||
tags: ["Auth:admin"],
|
||||
summary: "updates a specific user",
|
||||
method: "post",
|
||||
path: "/updateuser",
|
||||
middleware: [
|
||||
authMiddleware,
|
||||
hasCorrectRole(["admin", "systemAdmin"], "admin"),
|
||||
],
|
||||
//description: "When logged in you will be able to grant new permissions",
|
||||
request: {
|
||||
body: {
|
||||
content: {
|
||||
"application/json": { schema: UserAccess },
|
||||
},
|
||||
},
|
||||
},
|
||||
responses: responses(),
|
||||
}),
|
||||
async (c) => {
|
||||
//apiHit(c, { endpoint: "api/auth/setUserRoles" });
|
||||
const userData = await c.req.json();
|
||||
try {
|
||||
const userUPD: any = await updateUserADM(userData);
|
||||
//return apiReturn(c, true, access?.message, access?.data, 200);
|
||||
return c.json(
|
||||
{
|
||||
success: userUPD.success,
|
||||
message: userUPD.message,
|
||||
data: userUPD.data,
|
||||
},
|
||||
200
|
||||
);
|
||||
} catch (error) {
|
||||
console.log(error);
|
||||
//return apiReturn(c, false, "Error in setting the user access", error, 400);
|
||||
return c.json(
|
||||
{
|
||||
success: false,
|
||||
message: "Error in setting the user access",
|
||||
data: error,
|
||||
},
|
||||
400
|
||||
);
|
||||
}
|
||||
}
|
||||
);
|
||||
export default app;
|
||||
@@ -1,53 +0,0 @@
|
||||
import {z, createRoute, OpenAPIHono} from "@hono/zod-openapi";
|
||||
import {apiHit} from "../../../../globalUtils/apiHits.js";
|
||||
import jwt from "jsonwebtoken";
|
||||
import {roleCheck} from "../../controllers/userRoles/getUserAccess.js";
|
||||
import type {CustomJwtPayload} from "../../../../types/jwtToken.js";
|
||||
import {authMiddleware} from "../../middleware/authMiddleware.js";
|
||||
|
||||
const {verify} = jwt;
|
||||
const app = new OpenAPIHono();
|
||||
|
||||
const responseSchema = z.object({
|
||||
message: z.string().optional().openapi({example: "User Created"}),
|
||||
});
|
||||
|
||||
app.openapi(
|
||||
createRoute({
|
||||
tags: ["Auth"],
|
||||
summary: "Returns the useraccess table",
|
||||
method: "get",
|
||||
path: "/",
|
||||
middleware: authMiddleware,
|
||||
responses: {
|
||||
200: {
|
||||
content: {"application/json": {schema: responseSchema}},
|
||||
description: "Retrieve the user",
|
||||
},
|
||||
},
|
||||
}),
|
||||
async (c) => {
|
||||
// apit hit
|
||||
apiHit(c, {endpoint: "api/auth/getUserRoles"});
|
||||
const authHeader = c.req.header("Authorization");
|
||||
const token = authHeader?.split("Bearer ")[1] || "";
|
||||
try {
|
||||
const secret = process.env.JWT_SECRET!;
|
||||
if (!secret) {
|
||||
throw new Error("JWT_SECRET is not defined in environment variables");
|
||||
}
|
||||
|
||||
const payload = verify(token, secret) as CustomJwtPayload;
|
||||
|
||||
const canAccess = await roleCheck(payload.user?.user_id);
|
||||
|
||||
return c.json({sucess: true, message: `User ${payload.user?.username} can access`, data: canAccess}, 200);
|
||||
} catch (error) {
|
||||
console.log(error);
|
||||
}
|
||||
|
||||
return c.json({message: "UserRoles coming over"});
|
||||
}
|
||||
);
|
||||
|
||||
export default app;
|
||||
@@ -1,65 +0,0 @@
|
||||
import {createRoute, OpenAPIHono, z} from "@hono/zod-openapi";
|
||||
import {setUserAccess} from "../../controllers/userRoles/setUserRoles.js";
|
||||
import {apiHit} from "../../../../globalUtils/apiHits.js";
|
||||
import {apiReturn} from "../../../../globalUtils/apiReturn.js";
|
||||
import {authMiddleware} from "../../middleware/authMiddleware.js";
|
||||
|
||||
const app = new OpenAPIHono();
|
||||
|
||||
const responseSchema = z.object({
|
||||
success: z.boolean().openapi({example: true}),
|
||||
message: z.string().optional().openapi({example: "user access"}),
|
||||
data: z.array(z.object({})).optional().openapi({example: []}),
|
||||
});
|
||||
|
||||
const UserAccess = z.object({
|
||||
username: z
|
||||
.string()
|
||||
.regex(/^[a-zA-Z0-9_]{3,30}$/)
|
||||
.openapi({example: "smith034"}),
|
||||
module: z.string().openapi({example: "production"}),
|
||||
role: z.string().openapi({example: "viewer"}),
|
||||
override: z.string().optional().openapi({example: "secretString"}),
|
||||
});
|
||||
|
||||
app.openapi(
|
||||
createRoute({
|
||||
tags: ["Auth"],
|
||||
summary: "Sets Users access",
|
||||
method: "post",
|
||||
path: "/",
|
||||
middleware: authMiddleware,
|
||||
description: "When logged in you will be able to grant new permissions",
|
||||
request: {
|
||||
body: {
|
||||
content: {
|
||||
"application/json": {schema: UserAccess},
|
||||
},
|
||||
},
|
||||
},
|
||||
responses: {
|
||||
200: {
|
||||
content: {"application/json": {schema: responseSchema}},
|
||||
description: "Retrieve the user",
|
||||
},
|
||||
400: {
|
||||
content: {"application/json": {schema: responseSchema}},
|
||||
description: "Failed to get user access",
|
||||
},
|
||||
},
|
||||
}),
|
||||
async (c) => {
|
||||
apiHit(c, {endpoint: "api/auth/setUserRoles"});
|
||||
const {username, module, role, override} = await c.req.json();
|
||||
try {
|
||||
const access = await setUserAccess(username, module, role, override);
|
||||
//return apiReturn(c, true, access?.message, access?.data, 200);
|
||||
return c.json({success: access.success, message: access.message, data: access.data}, 200);
|
||||
} catch (error) {
|
||||
console.log(error);
|
||||
//return apiReturn(c, false, "Error in setting the user access", error, 400);
|
||||
return c.json({success: false, message: "Error in setting the user access", data: error}, 400);
|
||||
}
|
||||
}
|
||||
);
|
||||
export default app;
|
||||
@@ -1,6 +1,8 @@
|
||||
import bcrypt from "bcrypt";
|
||||
|
||||
export const checkPassword = async (currentPassword: string, dbPassword: string) => {
|
||||
import bcrypt from "bcryptjs";
|
||||
export const checkPassword = async (
|
||||
currentPassword: string,
|
||||
dbPassword: string
|
||||
) => {
|
||||
let decyptPass = "";
|
||||
try {
|
||||
decyptPass = atob(dbPassword);
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import bcrypt from "bcrypt";
|
||||
import bcrypt from "bcryptjs";
|
||||
|
||||
export const createPassword = async (password: string) => {
|
||||
// encypt password
|
||||
|
||||
@@ -55,9 +55,9 @@ app.get(
|
||||
"nsurlsession",
|
||||
"undici",
|
||||
],
|
||||
spec: {
|
||||
|
||||
url: "/api/ref",
|
||||
},
|
||||
|
||||
baseServerURL: "https://scalar.com",
|
||||
servers: [
|
||||
{
|
||||
|
||||
29
server/services/logger/controller/streamLogs.ts
Normal file
29
server/services/logger/controller/streamLogs.ts
Normal file
@@ -0,0 +1,29 @@
|
||||
import type {Context} from "hono";
|
||||
import {db} from "../../../../database/dbclient.js";
|
||||
import {and, eq, gt} from "drizzle-orm";
|
||||
import {streamSSE, streamText} from "hono/streaming";
|
||||
import {logs} from "../../../../database/schema/logs.js";
|
||||
|
||||
export async function streamLogs(c: Context) {
|
||||
let id = 0;
|
||||
let running = true;
|
||||
// c.header("Content-Type", "text/event-stream");
|
||||
// c.header("Cache-Control", "no-cache");
|
||||
// c.header("Connection", "keep-alive");
|
||||
|
||||
const getLogs = async () => {};
|
||||
return streamSSE(c, async (stream) => {
|
||||
while (running) {
|
||||
const message = `It is ${new Date().toISOString()}`;
|
||||
await stream.writeSSE({
|
||||
data: message,
|
||||
event: "time-update",
|
||||
id: String(id++),
|
||||
});
|
||||
await stream.sleep(1000);
|
||||
if (id === 5) {
|
||||
running = false;
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
@@ -8,6 +8,15 @@ type Log = {
|
||||
level: string;
|
||||
msg: string;
|
||||
};
|
||||
|
||||
const pinoLogLevels: any = {
|
||||
10: "trace",
|
||||
20: "debug",
|
||||
30: "info",
|
||||
40: "warn",
|
||||
50: "error",
|
||||
60: "fatal",
|
||||
};
|
||||
// Create a custom transport function
|
||||
export default async function (log: Log) {
|
||||
//const {username, service, level, msg, ...extra} = log;
|
||||
@@ -15,8 +24,11 @@ export default async function (log: Log) {
|
||||
return build(async function (source) {
|
||||
for await (let obj of source) {
|
||||
// Insert log entry into the PostgreSQL database using Drizzle ORM
|
||||
|
||||
// convert to the name to make it more easy to find later :P
|
||||
const levelName = pinoLogLevels[obj.level] || "unknown";
|
||||
await db.insert(logs).values({
|
||||
level: obj.level,
|
||||
level: levelName,
|
||||
username: obj?.username.toLowerCase(),
|
||||
service: obj?.service.toLowerCase(),
|
||||
message: obj.msg,
|
||||
|
||||
@@ -7,10 +7,11 @@ import {settings} from "../../../database/schema/settings.js";
|
||||
import {logCleanup} from "./controller/logCleanup.js";
|
||||
import createNewLog from "./routes/createLog.js";
|
||||
import getLogs from "./routes/getLogs.js";
|
||||
import stream from "./routes/streamLogs.js";
|
||||
|
||||
const app = new OpenAPIHono();
|
||||
|
||||
const routes = [clearLog, createNewLog, getLogs] as const;
|
||||
const routes = [clearLog, createNewLog, getLogs, stream] as const;
|
||||
const setting = await db.select().from(settings);
|
||||
|
||||
const appRoutes = routes.forEach((route) => {
|
||||
|
||||
51
server/services/logger/routes/streamLogs.ts
Normal file
51
server/services/logger/routes/streamLogs.ts
Normal file
@@ -0,0 +1,51 @@
|
||||
// an external way to creating logs
|
||||
//@ts-nocheck
|
||||
import {createRoute, OpenAPIHono, z} from "@hono/zod-openapi";
|
||||
import {apiHit} from "../../../globalUtils/apiHits.js";
|
||||
import {responses} from "../../../globalUtils/routeDefs/responses.js";
|
||||
import {createLog} from "../logger.js";
|
||||
import {getLogs} from "../controller/getLogs.js";
|
||||
import {streamLogs} from "../controller/streamLogs.js";
|
||||
import {streamSSE} from "hono/streaming";
|
||||
|
||||
const app = new OpenAPIHono({strict: false});
|
||||
|
||||
app.openapi(
|
||||
createRoute({
|
||||
tags: ["server:logger"],
|
||||
summary: "Streams the logs to the frontend.",
|
||||
method: "get",
|
||||
path: "/logs/stream",
|
||||
description: "This should only be used on the event you need to monitor logs.",
|
||||
|
||||
responses: {
|
||||
200: {
|
||||
content: {
|
||||
"application/json": {schema: z.object({message: z.string().optional()})},
|
||||
},
|
||||
description: "Response message",
|
||||
},
|
||||
},
|
||||
}),
|
||||
async (c) => {
|
||||
apiHit(c, {endpoint: `api/logger/logs`});
|
||||
c.header("Content-Type", "text/event-stream");
|
||||
c.header("Cache-Control", "no-cache");
|
||||
c.header("Connection", "keep-alive");
|
||||
return streamSSE(c, async (stream) => {
|
||||
let id = 0;
|
||||
const encoder = new TextEncoder();
|
||||
while (true) {
|
||||
const message = `It is ${new Date().toISOString()}`;
|
||||
await stream.writeSSE({
|
||||
data: message,
|
||||
event: "time-update",
|
||||
id: String(id++),
|
||||
});
|
||||
encoder.encode(`data: ${JSON.stringify({type: "progress", data: id})}\n\n`);
|
||||
await stream.sleep(1000);
|
||||
}
|
||||
});
|
||||
}
|
||||
);
|
||||
export default app;
|
||||
@@ -1,6 +1,7 @@
|
||||
import type {User} from "../../../types/users.js";
|
||||
import {alplaStockInv} from "./cycleCount/alplaStockInventory.js";
|
||||
import {emptyCount} from "./cycleCount/emptyCycleCount.js";
|
||||
import {fullLaneCount} from "./cycleCount/fullLaneCycleCount.js";
|
||||
import {ocmeInv} from "./cycleCount/ocmeInventory.js";
|
||||
|
||||
export const prepareLane = "https://usday1prod.alpla.net/application/public/v1.1/Warehousing/PrepareLaneForInventory";
|
||||
@@ -8,7 +9,7 @@ export const openLane = "https://usday1prod.alpla.net/application/public/v1.0/Wa
|
||||
export const closeLane = "https://usday1prod.alpla.net/application/public/v1.0/Warehousing/InventoryClose";
|
||||
export const releaseLane = "https://usday1prod.alpla.net/application/public/v1.1/Warehousing/ReleaseLaneFromInventory";
|
||||
export const scannerID = 500;
|
||||
export const cycleCount = async (lane: string, user: User) => {
|
||||
export const cycleCount = async (lane: any, user: User) => {
|
||||
/**
|
||||
* We will get the inventory from both systems and merge them together, intert it into our db then do the cycle count and update each item
|
||||
* one it dose it.
|
||||
@@ -21,7 +22,7 @@ export const cycleCount = async (lane: string, user: User) => {
|
||||
const alplaStock = await alplaStockInv(ocme[0].alpla_laneID);
|
||||
|
||||
// create a new array that has the merge happen.
|
||||
const mergeOcmeData = ocme.map((d) => {
|
||||
const mergeOcmeData = ocme.map((d: any) => {
|
||||
// check if its in the ocme array we add it
|
||||
const inStock = alplaStock.filter((r: any) => r.runningNumber === d.runningNumber);
|
||||
//console.log(inStock);
|
||||
@@ -52,9 +53,10 @@ export const cycleCount = async (lane: string, user: User) => {
|
||||
// determine what type of count we are doing.
|
||||
if (ocme.length === 0) {
|
||||
// do empty count
|
||||
await emptyCount(user, lane);
|
||||
await emptyCount(user, ocme[0].alpla_laneID);
|
||||
} else {
|
||||
// do the full lane inv
|
||||
await fullLaneCount(user, ocme[0].alpla_laneID, ocme);
|
||||
}
|
||||
|
||||
// store in the db so we have a record.... for later when we fully randomize and automate this.
|
||||
|
||||
@@ -0,0 +1,126 @@
|
||||
// full lane count
|
||||
import axios from "axios";
|
||||
import {delay} from "../../../../globalUtils/delay.js";
|
||||
import {createLog} from "../../../logger/logger.js";
|
||||
import {openLane, prepareLane, scannerID} from "../cycleCount.js";
|
||||
import type {User} from "../../../../types/users.js";
|
||||
|
||||
let delayTime = 100;
|
||||
|
||||
export const fullLaneCount = async (user: User, lane: string, ocmeLanes: any) => {
|
||||
// prepare the lane.
|
||||
try {
|
||||
const openlane = await axios({
|
||||
method: "POST",
|
||||
url: prepareLane,
|
||||
headers: {
|
||||
Authorization: `Basic ${user.prod}`,
|
||||
"Content-Type": "application/json",
|
||||
},
|
||||
data: {
|
||||
scannerId: scannerID,
|
||||
laneId: lane,
|
||||
},
|
||||
});
|
||||
|
||||
createLog("info", user.username!, "ocme-count", openlane.data.message);
|
||||
try {
|
||||
const open = await axios({
|
||||
method: "POST",
|
||||
url: openLane,
|
||||
headers: {
|
||||
Authorization: `Basic ${user.prod}`,
|
||||
"Content-Type": "application/json",
|
||||
},
|
||||
data: {
|
||||
scannerId: scannerID,
|
||||
laneId: lane,
|
||||
},
|
||||
});
|
||||
|
||||
createLog("info", user.username!, "ocme-count", open.data.Message);
|
||||
} catch (error) {
|
||||
console.log(error);
|
||||
}
|
||||
} catch (error) {
|
||||
console.log(error);
|
||||
}
|
||||
|
||||
// do the inv
|
||||
|
||||
for (let i = 0; i < ocmeLanes.length; i++) {
|
||||
const count = {
|
||||
scannerId: scannerID,
|
||||
sscc: ocmeLanes[i].sscc,
|
||||
};
|
||||
//createLog("cyclecounting", "info", `Processing running: ${ocmeLanes[i].runningNumber}`);
|
||||
await delay(delayTime);
|
||||
|
||||
try {
|
||||
const openLane = await axios({
|
||||
method: "POST",
|
||||
url: "https://usday1prod.alpla.net/application/public/v1.0/Warehousing/InventoryCount",
|
||||
headers: {
|
||||
Authorization: `Basic ${user.prod}`,
|
||||
"Content-Type": "application/json",
|
||||
},
|
||||
data: count,
|
||||
});
|
||||
|
||||
createLog(
|
||||
"info",
|
||||
user.username!,
|
||||
"ocme-count",
|
||||
`${openLane.data.Message} on running: ${ocmeLanes[i].runningNumber}`
|
||||
);
|
||||
await delay(delayTime);
|
||||
} catch (error) {
|
||||
createLog("error", user.username!, "ocme-count", `${error}`);
|
||||
}
|
||||
}
|
||||
|
||||
// close the count
|
||||
// close the order
|
||||
try {
|
||||
const openLane = await axios({
|
||||
method: "POST",
|
||||
url: "https://usday1prod.alpla.net/application/public/v1.0/Warehousing/InventoryClose",
|
||||
headers: {
|
||||
Authorization: `Basic ${user.prod}`,
|
||||
"Content-Type": "application/json",
|
||||
},
|
||||
data: {
|
||||
scannerId: scannerID,
|
||||
laneId: lane,
|
||||
},
|
||||
});
|
||||
|
||||
createLog("info", user.username!, "ocme-count", openLane.data.Message);
|
||||
|
||||
if (openLane.data.Result === 0) {
|
||||
//release the lane
|
||||
//----------------------------------------------------
|
||||
try {
|
||||
const openLane = await axios({
|
||||
method: "POST",
|
||||
url: "https://usday1prod.alpla.net/application/public/v1.1/Warehousing/ReleaseLaneFromInventory",
|
||||
headers: {
|
||||
Authorization: `Basic ${user.prod}`,
|
||||
"Content-Type": "application/json",
|
||||
},
|
||||
data: {
|
||||
laneId: lane,
|
||||
},
|
||||
});
|
||||
|
||||
createLog("info", user.username!, "ocme-count", openLane.data.message);
|
||||
} catch (error) {
|
||||
createLog("error", user.username!, "ocme-count", `${error}`);
|
||||
}
|
||||
}
|
||||
} catch (error) {
|
||||
createLog("error", user.username!, "ocme-count", `${error}`);
|
||||
}
|
||||
|
||||
return {success: true, message: `Lane completed`};
|
||||
};
|
||||
|
||||
@@ -1,284 +1,16 @@
|
||||
import axios from "axios";
|
||||
const data = [
|
||||
{
|
||||
ocme_laneLevelID: "P3F36PZ1PN1",
|
||||
alpla_laneID: "30285 ",
|
||||
alpla_laneDescription: "L064",
|
||||
Article: "146",
|
||||
description: "HDPE Trigger 16oz White",
|
||||
sscc: "090103830005256402",
|
||||
runningNumber: "525640",
|
||||
},
|
||||
{
|
||||
ocme_laneLevelID: "P3F36PZ1PN2",
|
||||
alpla_laneID: "30285 ",
|
||||
alpla_laneDescription: "L064",
|
||||
Article: "146",
|
||||
description: "HDPE Trigger 16oz White",
|
||||
sscc: "090103830005402649",
|
||||
runningNumber: "540264",
|
||||
},
|
||||
{
|
||||
ocme_laneLevelID: "P3F36PZ1PN3",
|
||||
alpla_laneID: "30285 ",
|
||||
alpla_laneDescription: "L064",
|
||||
Article: "146",
|
||||
description: "HDPE Trigger 16oz White",
|
||||
sscc: "090103830005312559",
|
||||
runningNumber: "531255",
|
||||
},
|
||||
{
|
||||
ocme_laneLevelID: "P3F36PZ1PN4",
|
||||
alpla_laneID: "30285 ",
|
||||
alpla_laneDescription: "L064",
|
||||
Article: "146",
|
||||
description: "HDPE Trigger 16oz White",
|
||||
sscc: "090103830005312658",
|
||||
runningNumber: "531265",
|
||||
},
|
||||
{
|
||||
ocme_laneLevelID: "P3F36PZ2PN1",
|
||||
alpla_laneID: "30285 ",
|
||||
alpla_laneDescription: "L064",
|
||||
Article: "146",
|
||||
description: "HDPE Trigger 16oz White",
|
||||
sscc: "090103830005404186",
|
||||
runningNumber: "540418",
|
||||
},
|
||||
{
|
||||
ocme_laneLevelID: "P3F36PZ2PN2",
|
||||
alpla_laneID: "30285 ",
|
||||
alpla_laneDescription: "L064",
|
||||
Article: "146",
|
||||
description: "HDPE Trigger 16oz White",
|
||||
sscc: "090103830005404193",
|
||||
runningNumber: "540419",
|
||||
},
|
||||
{
|
||||
ocme_laneLevelID: "P3F36PZ2PN3",
|
||||
alpla_laneID: "30285 ",
|
||||
alpla_laneDescription: "L064",
|
||||
Article: "146",
|
||||
description: "HDPE Trigger 16oz White",
|
||||
sscc: "090103830005404155",
|
||||
runningNumber: "540415",
|
||||
},
|
||||
{
|
||||
ocme_laneLevelID: "P3F36PZ2PN4",
|
||||
alpla_laneID: "30285 ",
|
||||
alpla_laneDescription: "L064",
|
||||
Article: "146",
|
||||
description: "HDPE Trigger 16oz White",
|
||||
sscc: "090103830005404230",
|
||||
runningNumber: "540423",
|
||||
},
|
||||
{
|
||||
ocme_laneLevelID: "P3F36PZ3PN1",
|
||||
alpla_laneID: "30285 ",
|
||||
alpla_laneDescription: "L064",
|
||||
Article: "146",
|
||||
description: "HDPE Trigger 16oz White",
|
||||
sscc: "090103830005306589",
|
||||
runningNumber: "530658",
|
||||
},
|
||||
{
|
||||
ocme_laneLevelID: "P3F36PZ3PN2",
|
||||
alpla_laneID: "30285 ",
|
||||
alpla_laneDescription: "L064",
|
||||
Article: "164",
|
||||
description: "HDPE Trigger 16oz Orange",
|
||||
sscc: "090103830005408634",
|
||||
runningNumber: "540841",
|
||||
},
|
||||
{
|
||||
ocme_laneLevelID: "P3F36PZ3PN3",
|
||||
alpla_laneID: "30285 ",
|
||||
alpla_laneDescription: "L064",
|
||||
Article: "164",
|
||||
description: "HDPE Trigger 16oz Orange",
|
||||
sscc: "090103830005836888",
|
||||
runningNumber: "583688",
|
||||
},
|
||||
{
|
||||
ocme_laneLevelID: "P3F36PZ3PN4",
|
||||
alpla_laneID: "30285 ",
|
||||
alpla_laneDescription: "L064",
|
||||
Article: "164",
|
||||
description: "HDPE Trigger 16oz Orange",
|
||||
sscc: "090103830005836871",
|
||||
runningNumber: "583687",
|
||||
},
|
||||
{
|
||||
ocme_laneLevelID: "P3F36PZ4PN1",
|
||||
alpla_laneID: "30285 ",
|
||||
alpla_laneDescription: "L064",
|
||||
Article: "164",
|
||||
description: "HDPE Trigger 16oz Orange",
|
||||
sscc: "090103830005845279",
|
||||
runningNumber: "584527",
|
||||
},
|
||||
{
|
||||
ocme_laneLevelID: "P3F36PZ4PN2",
|
||||
alpla_laneID: "30285 ",
|
||||
alpla_laneDescription: "L064",
|
||||
Article: "164",
|
||||
description: "HDPE Trigger 16oz Orange",
|
||||
sscc: "090103830005845231",
|
||||
runningNumber: "584523",
|
||||
},
|
||||
{
|
||||
ocme_laneLevelID: "P3F36PZ4PN3",
|
||||
alpla_laneID: "30285 ",
|
||||
alpla_laneDescription: "L064",
|
||||
Article: "164",
|
||||
description: "HDPE Trigger 16oz Orange",
|
||||
sscc: "090103830005845170",
|
||||
runningNumber: "584517",
|
||||
},
|
||||
{
|
||||
ocme_laneLevelID: "P3F36PZ4PN4",
|
||||
alpla_laneID: "30285 ",
|
||||
alpla_laneDescription: "L064",
|
||||
Article: "164",
|
||||
description: "HDPE Trigger 16oz Orange",
|
||||
sscc: "090103830005845156",
|
||||
runningNumber: "584515",
|
||||
},
|
||||
{
|
||||
ocme_laneLevelID: "P3F36PZ5PN1",
|
||||
alpla_laneID: "30285 ",
|
||||
alpla_laneDescription: "L064",
|
||||
Article: "164",
|
||||
description: "HDPE Trigger 16oz Orange",
|
||||
sscc: "090103830005870325",
|
||||
runningNumber: "587032",
|
||||
},
|
||||
{
|
||||
ocme_laneLevelID: "P3F36PZ5PN2",
|
||||
alpla_laneID: "30285 ",
|
||||
alpla_laneDescription: "L064",
|
||||
Article: "164",
|
||||
description: "HDPE Trigger 16oz Orange",
|
||||
sscc: "090103830005871490",
|
||||
runningNumber: "587149",
|
||||
},
|
||||
{
|
||||
ocme_laneLevelID: "P3F36PZ5PN3",
|
||||
alpla_laneID: "30285 ",
|
||||
alpla_laneDescription: "L064",
|
||||
Article: "164",
|
||||
description: "HDPE Trigger 16oz Orange",
|
||||
sscc: "090103830005851782",
|
||||
runningNumber: "585178",
|
||||
},
|
||||
{
|
||||
ocme_laneLevelID: "P3F36PZ5PN4",
|
||||
alpla_laneID: "30285 ",
|
||||
alpla_laneDescription: "L064",
|
||||
Article: "164",
|
||||
description: "HDPE Trigger 16oz Orange",
|
||||
sscc: "090103830005855339",
|
||||
runningNumber: "585533",
|
||||
},
|
||||
{
|
||||
ocme_laneLevelID: "P3F36PZ6PN1",
|
||||
alpla_laneID: "30285 ",
|
||||
alpla_laneDescription: "L064",
|
||||
Article: "164",
|
||||
description: "HDPE Trigger 16oz Orange",
|
||||
sscc: "090103830005867660",
|
||||
runningNumber: "586766",
|
||||
},
|
||||
{
|
||||
ocme_laneLevelID: "P3F36PZ6PN2",
|
||||
alpla_laneID: "30285 ",
|
||||
alpla_laneDescription: "L064",
|
||||
Article: "164",
|
||||
description: "HDPE Trigger 16oz Orange",
|
||||
sscc: "090103830005867622",
|
||||
runningNumber: "586762",
|
||||
},
|
||||
{
|
||||
ocme_laneLevelID: "P3F36PZ6PN3",
|
||||
alpla_laneID: "30285 ",
|
||||
alpla_laneDescription: "L064",
|
||||
Article: "164",
|
||||
description: "HDPE Trigger 16oz Orange",
|
||||
sscc: "090103830005865871",
|
||||
runningNumber: "586587",
|
||||
},
|
||||
{
|
||||
ocme_laneLevelID: "P3F36PZ6PN4",
|
||||
alpla_laneID: "30285 ",
|
||||
alpla_laneDescription: "L064",
|
||||
Article: "164",
|
||||
description: "HDPE Trigger 16oz Orange",
|
||||
sscc: "090103830005865895",
|
||||
runningNumber: "586589",
|
||||
},
|
||||
{
|
||||
ocme_laneLevelID: "P3F36PZ7PN1",
|
||||
alpla_laneID: "30285 ",
|
||||
alpla_laneDescription: "L064",
|
||||
Article: "164",
|
||||
description: "HDPE Trigger 16oz Orange",
|
||||
sscc: "090103830005866052",
|
||||
runningNumber: "586605",
|
||||
},
|
||||
{
|
||||
ocme_laneLevelID: "P3F36PZ7PN2",
|
||||
alpla_laneID: "30285 ",
|
||||
alpla_laneDescription: "L064",
|
||||
Article: "164",
|
||||
description: "HDPE Trigger 16oz Orange",
|
||||
sscc: "090103830005865970",
|
||||
runningNumber: "586597",
|
||||
},
|
||||
{
|
||||
ocme_laneLevelID: "P3F36PZ7PN3",
|
||||
alpla_laneID: "30285 ",
|
||||
alpla_laneDescription: "L064",
|
||||
Article: "164",
|
||||
description: "HDPE Trigger 16oz Orange",
|
||||
sscc: "090103830005877089",
|
||||
runningNumber: "587708",
|
||||
},
|
||||
{
|
||||
ocme_laneLevelID: "P3F36PZ8PN1",
|
||||
alpla_laneID: "30285 ",
|
||||
alpla_laneDescription: "L064",
|
||||
Article: "164",
|
||||
description: "HDPE Trigger 16oz Orange",
|
||||
sscc: "090103830005844975",
|
||||
runningNumber: "584497",
|
||||
},
|
||||
{
|
||||
ocme_laneLevelID: "P3F36PZ8PN2",
|
||||
alpla_laneID: "30285 ",
|
||||
alpla_laneDescription: "L064",
|
||||
Article: "164",
|
||||
description: "HDPE Trigger 16oz Orange",
|
||||
sscc: "090103830005844944",
|
||||
runningNumber: "584494",
|
||||
},
|
||||
{
|
||||
ocme_laneLevelID: "P3F36PZ8PN3",
|
||||
alpla_laneID: "30285 ",
|
||||
alpla_laneDescription: "L064",
|
||||
Article: "164",
|
||||
description: "HDPE Trigger 16oz Orange",
|
||||
sscc: "090103830005844890",
|
||||
runningNumber: "584489",
|
||||
},
|
||||
];
|
||||
export const ocmeInv = async (lane: string) => {
|
||||
try {
|
||||
const res = await axios.post("http://usday1vms010:3250/api/v1/getLaneData", {lane: lane});
|
||||
console.log(res.data);
|
||||
|
||||
return data;
|
||||
export const ocmeInv = async (data: any) => {
|
||||
try {
|
||||
const res = await axios.post(
|
||||
"http://usday1vms010:3250/api/v1/getLaneData",
|
||||
{lane: data.lane, laneType: data.laneType},
|
||||
{headers: {"Content-Type": "application/json", Connection: "keep-alive"}}
|
||||
);
|
||||
// console.log(res.data.data);
|
||||
|
||||
return res.data.data;
|
||||
} catch (error: any) {
|
||||
console.log(error.code);
|
||||
return data;
|
||||
}
|
||||
};
|
||||
|
||||
@@ -12,7 +12,14 @@
|
||||
|
||||
// // add the lane in so we dont crash
|
||||
// if(req.body.lane){
|
||||
// if(data.laneType === "laneID"){
|
||||
// get the mapped lane id
|
||||
// where alpla_laneID = 30286
|
||||
// filterdOCMELane = ocmeInventory.replaceAll("where alpla_laneDescription = '[lane]'", `where alpla_laneID = ${data.lane}`)
|
||||
|
||||
// } else {
|
||||
// filterdOCMELane = ocmeInventory.replaceAll('[lane]', data.lane)
|
||||
// }
|
||||
// // get lanes
|
||||
// const laneData = await runQuery(filterdOCMELane, 'Getting current ocme lanes linked')
|
||||
// res.status(200).json({success: true,message: `All current lanes from the ocme system.`, totalpallets: laneData.length,data: laneData})
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"servers": [
|
||||
{
|
||||
"sName": "test",
|
||||
"sName": "Test",
|
||||
"serverDNS": "usmcd1vms036",
|
||||
"plantToken": "test3",
|
||||
"idAdress": "10.193.0.56",
|
||||
@@ -33,9 +33,9 @@
|
||||
"contactPhone": "6366970253",
|
||||
"customerTiAcc": "ALPL01BETHINT",
|
||||
"lstServerPort": "4000",
|
||||
"active": false,
|
||||
"active": true,
|
||||
"serverLoc": "E:\\LST\\lstv2",
|
||||
"oldVersion": "C:\\Users\\adm_matthes01\\Desktop\\lst_backend",
|
||||
"oldVersion": "E:\\LST\\lst_backend",
|
||||
"shippingHours": "[{\"early\": \"06:30\", \"late\": \"23:00\"}]",
|
||||
"tiPostTime": "[{\"from\": \"24\", \"to\": \"24\"}]",
|
||||
"otherSettings": [{"specialInstructions": "something for ti"}]
|
||||
@@ -53,9 +53,9 @@
|
||||
"contactPhone": "6366970253",
|
||||
"customerTiAcc": "ALPL01HOUSINT",
|
||||
"lstServerPort": "4000",
|
||||
"active": true,
|
||||
"active": false,
|
||||
"serverLoc": "E:\\LST\\lstv2",
|
||||
"oldVersion": "C:\\Users\\adm_matthes01\\Desktop\\lst_backend",
|
||||
"oldVersion": "E:\\LST\\lst_backend",
|
||||
"shippingHours": "[{\"early\": \"06:30\", \"late\": \"23:00\"}]",
|
||||
"tiPostTime": "[{\"from\": \"24\", \"to\": \"24\"}]",
|
||||
"otherSettings": [{"specialInstructions": "something for ti"}]
|
||||
@@ -75,7 +75,7 @@
|
||||
"lstServerPort": "4000",
|
||||
"active": true,
|
||||
"serverLoc": "E:\\LST\\lstv2",
|
||||
"oldVersion": "C:\\Users\\adm_matthes01\\Desktop\\lst_backend",
|
||||
"oldVersion": "E:\\LST\\lst_backend",
|
||||
"shippingHours": "[{\"early\": \"06:30\", \"late\": \"23:00\"}]",
|
||||
"tiPostTime": "[{\"from\": \"24\", \"to\": \"24\"}]",
|
||||
"otherSettings": [{"specialInstructions": "something for ti"}]
|
||||
@@ -95,7 +95,7 @@
|
||||
"lstServerPort": "4001",
|
||||
"active": false,
|
||||
"serverLoc": "E:\\LST\\lstv2",
|
||||
"oldVersion": "D:\\lst\\lst_backend_2",
|
||||
"oldVersion": "E:\\LST\\lst_backend_2",
|
||||
"shippingHours": "[{\"early\": \"06:30\", \"late\": \"23:00\"}]",
|
||||
"tiPostTime": "[{\"from\": \"24\", \"to\": \"24\"}]",
|
||||
"otherSettings": [{"specialInstructions": "something for ti"}]
|
||||
@@ -115,7 +115,7 @@
|
||||
"lstServerPort": "4000",
|
||||
"active": false,
|
||||
"serverLoc": "E:\\LST\\lstv2",
|
||||
"oldVersion": "C:\\Users\\adm_matthes01\\Desktop\\lst_backend",
|
||||
"oldVersion": "E:\\LST\\lst_backend",
|
||||
"shippingHours": "[{\"early\": \"06:30\", \"late\": \"23:00\"}]",
|
||||
"tiPostTime": "[{\"from\": \"24\", \"to\": \"24\"}]",
|
||||
"otherSettings": [{"specialInstructions": "something for ti"}]
|
||||
@@ -133,9 +133,9 @@
|
||||
"contactPhone": "6366970253",
|
||||
"customerTiAcc": "ALPL01BG2INT",
|
||||
"lstServerPort": "4000",
|
||||
"active": true,
|
||||
"active": false,
|
||||
"serverLoc": "E:\\LST\\lstv2",
|
||||
"oldVersion": "C:\\Users\\adm_matthes01\\Desktop\\lst_backend",
|
||||
"oldVersion": "E:\\LST\\lst_backend",
|
||||
"shippingHours": "[{\"early\": \"06:30\", \"late\": \"23:00\"}]",
|
||||
"tiPostTime": "[{\"from\": \"24\", \"to\": \"24\"}]",
|
||||
"otherSettings": [{"specialInstructions": "something for ti"}]
|
||||
@@ -153,9 +153,9 @@
|
||||
"contactPhone": "6366970253",
|
||||
"customerTiAcc": "ALPL01MCDINT",
|
||||
"lstServerPort": "4000",
|
||||
"active": true,
|
||||
"active": false,
|
||||
"serverLoc": "E:\\LST\\lstv2",
|
||||
"oldVersion": "C:\\Users\\adm_matthes01\\Desktop\\lst_backend",
|
||||
"oldVersion": "E:\\LST\\lst_backend",
|
||||
"shippingHours": "[{\"early\": \"06:30\", \"late\": \"23:00\"}]",
|
||||
"tiPostTime": "[{\"from\": \"24\", \"to\": \"24\"}]",
|
||||
"otherSettings": [{"specialInstructions": "something for ti"}]
|
||||
@@ -195,7 +195,7 @@
|
||||
"lstServerPort": "4000",
|
||||
"active": false,
|
||||
"serverLoc": "E:\\LST\\lstv2",
|
||||
"oldVersion": "C:\\Users\\adm_matthes01\\Desktop\\lst_backend",
|
||||
"oldVersion": "E:\\LST\\lst_backend",
|
||||
"shippingHours": "[{\"early\": \"06:30\", \"late\": \"23:00\"}]",
|
||||
"tiPostTime": "[{\"from\": \"24\", \"to\": \"24\"}]",
|
||||
"otherSettings": [{"specialInstructions": "something for ti"}]
|
||||
@@ -215,7 +215,7 @@
|
||||
"lstServerPort": "4000",
|
||||
"active": false,
|
||||
"serverLoc": "E:\\LST\\lstv2",
|
||||
"oldVersion": "C:\\Users\\adm_matthes01\\Desktop\\lst_backend",
|
||||
"oldVersion": "E:\\LST\\lst_backend",
|
||||
"shippingHours": "[{\"early\": \"06:30\", \"late\": \"23:00\"}]",
|
||||
"tiPostTime": "[{\"from\": \"24\", \"to\": \"24\"}]",
|
||||
"otherSettings": [{"specialInstructions": "something for ti"}]
|
||||
@@ -235,7 +235,7 @@
|
||||
"lstServerPort": "4000",
|
||||
"active": false,
|
||||
"serverLoc": "E:\\LST\\lstv2",
|
||||
"oldVersion": "C:\\Users\\adm_matthes01\\Desktop\\lst_backend",
|
||||
"oldVersion": "E:\\LST\\lst_backend",
|
||||
"shippingHours": "[{\"early\": \"06:30\", \"late\": \"23:00\"}]",
|
||||
"tiPostTime": "[{\"from\": \"24\", \"to\": \"24\"}]",
|
||||
"otherSettings": [{"specialInstructions": "something for ti"}]
|
||||
@@ -255,7 +255,7 @@
|
||||
"lstServerPort": "4000",
|
||||
"active": false,
|
||||
"serverLoc": "E:\\LST\\lstv2",
|
||||
"oldVersion": "C:\\Users\\adm_matthes01\\Desktop\\lst_backend",
|
||||
"oldVersion": "E:\\LST\\lst_backend",
|
||||
"shippingHours": "[{\"early\": \"06:30\", \"late\": \"23:00\"}]",
|
||||
"tiPostTime": "[{\"from\": \"24\", \"to\": \"24\"}]",
|
||||
"otherSettings": [{"specialInstructions": "something for ti"}]
|
||||
@@ -275,7 +275,7 @@
|
||||
"lstServerPort": "4000",
|
||||
"active": false,
|
||||
"serverLoc": "E:\\LST\\lstv2",
|
||||
"oldVersion": "D:\\LST\\lst_backend",
|
||||
"oldVersion": "E:\\LST\\lst_backend",
|
||||
"shippingHours": "[{\"early\": \"06:30\", \"late\": \"23:00\"}]",
|
||||
"tiPostTime": "[{\"from\": \"24\", \"to\": \"24\"}]",
|
||||
"otherSettings": [{"specialInstructions": "something for ti"}]
|
||||
@@ -293,9 +293,9 @@
|
||||
"contactPhone": "6366970253",
|
||||
"customerTiAcc": "ALPL01SHERMANINT",
|
||||
"lstServerPort": "4000",
|
||||
"active": true,
|
||||
"active": false,
|
||||
"serverLoc": "E:\\LST\\lstv2",
|
||||
"oldVersion": "C:\\Users\\adm_matthes01\\Desktop\\lst_backend",
|
||||
"oldVersion": "E:\\LST\\lst_backend",
|
||||
"shippingHours": "[{\"early\": \"06:30\", \"late\": \"23:00\"}]",
|
||||
"tiPostTime": "[{\"from\": \"24\", \"to\": \"24\"}]",
|
||||
"otherSettings": [{"specialInstructions": "something for ti"}]
|
||||
@@ -313,9 +313,9 @@
|
||||
"contactPhone": "262-808-4211",
|
||||
"customerTiAcc": "ALPL01WBINT",
|
||||
"lstServerPort": "4000",
|
||||
"active": true,
|
||||
"active": false,
|
||||
"serverLoc": "E:\\LST\\lstv2",
|
||||
"oldVersion": "C:\\Users\\adm_matthes01\\Desktop\\lst_backend",
|
||||
"oldVersion": "E:\\LST\\lst_backend",
|
||||
"shippingHours": "[{\"early\": \"06:30\", \"late\": \"23:00\"}]",
|
||||
"tiPostTime": "[{\"from\": \"24\", \"to\": \"24\"}]",
|
||||
"otherSettings": [{"specialInstructions": "something for ti", "active": false}]
|
||||
|
||||
@@ -40,6 +40,7 @@ export const serversCheckPoint = async () => {
|
||||
contactPhone: servers[i].contactPhone,
|
||||
shippingHours: servers[i].shippingHours,
|
||||
customerTiAcc: servers[i].customerTiAcc,
|
||||
oldVersion: servers[i].oldVersion,
|
||||
tiPostTime: servers[i].tiPostTime,
|
||||
otherSettings: servers[i].otherSettings,
|
||||
},
|
||||
|
||||
@@ -11,26 +11,57 @@ let pool: any;
|
||||
let connected: boolean = false;
|
||||
export const initializeProdPool = async () => {
|
||||
if (!installed) {
|
||||
createLog("info", "lst", "sqlProd", "The server was not installed will reconnect in 5 seconds");
|
||||
createLog(
|
||||
"info",
|
||||
"lst",
|
||||
"sqlProd",
|
||||
"The server was not installed will reconnect in 5 seconds"
|
||||
);
|
||||
setTimeout(() => {
|
||||
initializeProdPool();
|
||||
}, 5 * 1000);
|
||||
|
||||
return { success: false, message: "The server is not installed." };
|
||||
}
|
||||
const dbServer = await db.select().from(settings).where(eq(settings.name, "dbServer"));
|
||||
const dbServer = await db
|
||||
.select()
|
||||
.from(settings)
|
||||
.where(eq(settings.name, "dbServer"));
|
||||
const serverUp = await checkHostnamePort(`${dbServer[0].value}:1433`);
|
||||
|
||||
if (!serverUp) {
|
||||
createLog("error", "lst", "server", `The sql ${dbServer[0].value} is not reachable`);
|
||||
return {success: false, message: `The sql ${dbServer[0].value} is not reachable`};
|
||||
createLog(
|
||||
"error",
|
||||
"lst",
|
||||
"server",
|
||||
`The sql ${dbServer[0].value} is not reachable`
|
||||
);
|
||||
return {
|
||||
success: false,
|
||||
message: `The sql ${dbServer[0].value} is not reachable`,
|
||||
};
|
||||
}
|
||||
|
||||
// make sure the server is not set to localhost this will prevent some weird issues later but can be localhost on the dev
|
||||
const serverLoc = await db.select().from(settings).where(eq(settings.name, "dbServer"));
|
||||
if (serverLoc[0].value === "localhost" && process.env.NODE_ENV !== "development") {
|
||||
createLog("error", "lst", "sqlProd", "The server is set to localhost, and you are not in development mode.");
|
||||
return {success: false, message: "The server is set to localhost, and you are not in development mode."};
|
||||
const serverLoc = await db
|
||||
.select()
|
||||
.from(settings)
|
||||
.where(eq(settings.name, "dbServer"));
|
||||
if (
|
||||
serverLoc[0].value === "localhost" &&
|
||||
process.env.NODE_ENV !== "development"
|
||||
) {
|
||||
createLog(
|
||||
"error",
|
||||
"lst",
|
||||
"sqlProd",
|
||||
"The server is set to localhost, and you are not in development mode."
|
||||
);
|
||||
return {
|
||||
success: false,
|
||||
message:
|
||||
"The server is set to localhost, and you are not in development mode.",
|
||||
};
|
||||
}
|
||||
|
||||
// if you were restarting from the endpoint you get this lovely error
|
||||
@@ -42,27 +73,54 @@ export const initializeProdPool = async () => {
|
||||
const config = await prodSqlConfig();
|
||||
pool = await sql.connect(config!);
|
||||
|
||||
createLog("info", "lst", "sqlProd", `Connected to ${config?.server}, and looking at ${config?.database}`);
|
||||
createLog(
|
||||
"info",
|
||||
"lst",
|
||||
"sqlProd",
|
||||
`Connected to ${config?.server}, and looking at ${config?.database}`
|
||||
);
|
||||
connected = true;
|
||||
return {success: true, message: "The sql server connection has been closed"};
|
||||
} catch (error) {
|
||||
createLog("error", "lst", "sqlProd", `${JSON.stringify(error)}, "There was an error connecting to the pool."`);
|
||||
throw new Error("There was an error closing the sql connection");
|
||||
}
|
||||
return {
|
||||
success: true,
|
||||
message: "The sql server connection has been closed",
|
||||
};
|
||||
|
||||
export const closePool = async () => {
|
||||
try {
|
||||
await pool.close();
|
||||
createLog("info", "lst", "sqlProd", "Connection pool closed");
|
||||
connected = false;
|
||||
return {success: true, message: "The sql server connection has been closed"};
|
||||
} catch (error) {
|
||||
createLog(
|
||||
"error",
|
||||
"lst",
|
||||
"sqlProd",
|
||||
`${JSON.stringify(error)}, "There was an error closing the sql connection"`
|
||||
`${JSON.stringify(error)}, "There was an error connecting to the pool."`
|
||||
);
|
||||
throw new Error("There was an error closing the sql connection");
|
||||
}
|
||||
};
|
||||
|
||||
export const closePool = async () => {
|
||||
if (!connected) {
|
||||
createLog(
|
||||
"error",
|
||||
"lst",
|
||||
"sqlProd",
|
||||
"There is no connection a connection."
|
||||
);
|
||||
return { success: false, message: "There is already a connection." };
|
||||
}
|
||||
try {
|
||||
await pool.close();
|
||||
createLog("info", "lst", "sqlProd", "Connection pool closed");
|
||||
connected = false;
|
||||
return {
|
||||
success: true,
|
||||
message: "The sql server connection has been closed",
|
||||
};
|
||||
} catch (error) {
|
||||
createLog(
|
||||
"error",
|
||||
"lst",
|
||||
"sqlProd",
|
||||
`${JSON.stringify(
|
||||
error
|
||||
)}, "There was an error closing the sql connection"`
|
||||
);
|
||||
throw new Error("There was an error closing the sql connection");
|
||||
}
|
||||
@@ -72,22 +130,44 @@ export async function query(queryToRun: string, name: string) {
|
||||
/**
|
||||
* Just an extra catch incase someone tried to run a query while we were not connected to the server or sql server
|
||||
*/
|
||||
const dbServer = await db.select().from(settings).where(eq(settings.name, "dbServer"));
|
||||
const dbServer = await db
|
||||
.select()
|
||||
.from(settings)
|
||||
.where(eq(settings.name, "dbServer"));
|
||||
const serverUp = await checkHostnamePort(`${dbServer[0].value}:1433`);
|
||||
|
||||
if (!serverUp) {
|
||||
createLog("error", "lst", "server", `The sql ${dbServer[0].value} is not reachable`);
|
||||
return {success: false, message: `The sql ${dbServer[0].value} is not reachable`};
|
||||
createLog(
|
||||
"error",
|
||||
"lst",
|
||||
"server",
|
||||
`The sql ${dbServer[0].value} is not reachable`
|
||||
);
|
||||
return {
|
||||
success: false,
|
||||
message: `The sql ${dbServer[0].value} is not reachable`,
|
||||
};
|
||||
}
|
||||
|
||||
if (!connected) {
|
||||
createLog("error", "lst", "server", `The sql ${dbServer[0].value} is not connected`);
|
||||
return {success: false, message: `The sql ${dbServer[0].value} is not not connected`};
|
||||
createLog(
|
||||
"error",
|
||||
"lst",
|
||||
"server",
|
||||
`The sql ${dbServer[0].value} is not connected`
|
||||
);
|
||||
return {
|
||||
success: false,
|
||||
message: `The sql ${dbServer[0].value} is not not connected`,
|
||||
};
|
||||
}
|
||||
/**
|
||||
* We no longer need to send over the plant token change as we do it inside the query function.
|
||||
*/
|
||||
const plantToken = await db.select().from(settings).where(eq(settings.name, "plantToken"));
|
||||
const plantToken = await db
|
||||
.select()
|
||||
.from(settings)
|
||||
.where(eq(settings.name, "plantToken"));
|
||||
const query = queryToRun.replaceAll("test1", plantToken[0].value);
|
||||
|
||||
try {
|
||||
@@ -96,12 +176,19 @@ export async function query(queryToRun: string, name: string) {
|
||||
return result.recordset;
|
||||
} catch (error: any) {
|
||||
if (error.code === "ETIMEOUT") {
|
||||
createLog("error", "lst", "sqlProd", `${JSON.stringify(error)}, ${name} did not run due to a timeout.`);
|
||||
createLog(
|
||||
"error",
|
||||
"lst",
|
||||
"sqlProd",
|
||||
`${JSON.stringify(error)}, ${name} did not run due to a timeout.`
|
||||
);
|
||||
throw new Error(`${name} query did not run due to a timeout.`);
|
||||
}
|
||||
|
||||
if (error.code === "EREQUEST") {
|
||||
throw new Error(`${name} encoutnered an error ${error.originalError.info.message}`);
|
||||
throw new Error(
|
||||
`${name} encoutnered an error ${error.originalError.info.message}`
|
||||
);
|
||||
}
|
||||
|
||||
//console.log(error.originalError.info.message);
|
||||
|
||||
@@ -7,4 +7,5 @@ export type User = {
|
||||
roles?: Roles[];
|
||||
role?: string;
|
||||
prod?: string;
|
||||
password?: string;
|
||||
};
|
||||
|
||||
@@ -15,6 +15,6 @@
|
||||
"esModuleInterop": true,
|
||||
"resolveJsonModule": true
|
||||
},
|
||||
|
||||
"include": ["server", "scripts/**/*.ts"],
|
||||
"exclude": ["node_modules", "frontend", "dist", "testFiles"]
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user