feat(lstv2 move): moved lstv2 into this app to keep them combined and easier to maintain

This commit is contained in:
2025-09-19 22:22:05 -05:00
parent caf2315191
commit e4477402ad
847 changed files with 165801 additions and 0 deletions

View File

@@ -0,0 +1,35 @@
param (
[string]$dir,
[string]$app
)
# dir is the location of the root folder.
# Store the original directory
$originalDir = Get-Location
Write-Host $originalDir
# Check if the directory is provided
if (-not $dir) {
Write-Host "Error: Directory parameter is required."
exit 1
}
# Check if the directory exists
if (-not (Test-Path $dir)) {
Write-Host "Error: Directory '$dir' does not exist."
exit 1
}
# Navigate to the directory
Set-Location -Path $dir
# Run npm run build
Write-Host "Running 'npm run build' in directory: $dir"
npm run build
Write-Host "Build completed successfully."
# Restore the original directory
Set-Location -Path $originalDir
exit 0

View 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);
});

View File

@@ -0,0 +1,61 @@
param(
[string]$IncludesFile = ".includes",
[string]$Destination = "C:\Users\matthes01\Documents\lst\lstV2",
[string]$BaseDir = "C:\Users\matthes01\Documents\lst"
)
# .\copy-includes.ps1 will run with defaults
# .\copy-includes.ps1 -IncludesFile ".\mylist.txt" -Destination "D:\build\lstV2" will override defaults
if (-Not (Test-Path $IncludesFile)) {
Write-Error "Includes file not found: $IncludesFile"
exit 1
}
# Ensure destination exists
if (!(Test-Path -Path $Destination)) {
New-Item -ItemType Directory -Path $Destination | Out-Null
Write-Host "Folder created: $Destination"
}
# Empty the destination folder
Get-ChildItem -Path $Destination -Recurse -Force | Remove-Item -Recurse -Force
# If BaseDir wasnt explicitly passed in, use IncludesFile directory
if (-not $PSBoundParameters.ContainsKey('BaseDir')) {
$BaseDir = Split-Path -Parent (Resolve-Path $IncludesFile)
}
# Read includes list (ignore blank lines & comments)
$items = Get-Content $IncludesFile |
ForEach-Object { $_.Trim() } |
Where-Object { $_ -and -not $_.StartsWith("#") }
foreach ($item in $items) {
if ([System.IO.Path]::IsPathRooted($item)) {
# Absolute path (rare case)
$sourcePath = $item
$relative = Split-Path $item -Leaf # just take folder/file name
} else {
# Relative to BaseDir
$sourcePath = Join-Path $BaseDir $item
$relative = $item # keep full relative path e.g. "frontend\dist"
}
if (-Not (Test-Path $sourcePath)) {
Write-Warning "Skipping missing path: $sourcePath"
continue
}
# Destination path should preserve the relative structure
$targetPath = Join-Path $Destination $relative
# Ensure the parent folder exists
$targetDir = Split-Path $targetPath -Parent
if (-not (Test-Path $targetDir)) {
New-Item -ItemType Directory -Path $targetDir -Force | Out-Null
}
Write-Host "Copying $sourcePath -> $targetPath" -ForegroundColor Cyan
Copy-Item -Path $sourcePath -Destination $targetPath -Recurse -Force
}

View File

@@ -0,0 +1,205 @@
# 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/)
### To manage the server
- [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.
## 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
PROD_PORT=4000
# To keep it all simple we will pass VITE to the ports that are used on both sides.
VITE_SERVER_PORT=4000
# logLevel
LOG_LEVEL=info
# Auth stuff
SALTING=12
SECRET=CHANGEME
JWT_SECRET=CHANGEME
JWT_REFRESH_SECRET=CHANGEME
# Expire info plus refresh change as needed
JWT_EXPIRES=60
JWT_REFRESH_THRESHOLD=30
JWT_ACCESS_EXPIRATION="1h"
JWT_REFRESH_EXPIRATION="7d"
# this code will need to be used when a user needs to have access to everything.
SECRETOVERRIDECODE="supersecretKey"
# Database url - please change the password if this is all you changed
DATABASE_URL="postgresql://postgres:PASSWORD@localhost:5432/lst_db"
# This is for usday1 restrictions with the lgvs and customer constraints.
FIFO=100
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.
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.
### 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.
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.
```powershell
.\services.ps1 -serviceName "LSTV2" -option "install" -appPath "E:\LST\lstV2" -description "Logistics Support Tool V2" -command "run start"
```
### Adding servers to the mix to update on from the front end
you will need to add your servers into the serverData.json.
when the server starts up it will look at this file and make changes as needed.
below is an example of the server
```JSON
{
"sName": "Kansas City",
"serverDNS": "usksc1vms006",
"plantToken": "usksc1",
"idAddress": "10.42.9.26",
"greatPlainsPlantCode": "85",
"streetAddress": "1800 E 94th St Suite 300",
"cityState": "Kansas City, MO",
"zipcode": "64131",
"contactEmail": "example@example.com",
"contactPhone": "555-555-5555",
"customerTiAcc": "ALPL01KCINT",
"lstServerPort": "4000",
"active": false,
"serverLoc": "E:\\LST\\lstv2",
"oldVersion": "E:\\LST\\lst_backend",
"shippingHours": "[{\"early\": \"06:30\", \"late\": \"23:00\"}]",
"tiPostTime": "[{\"from\": \"24\", \"to\": \"24\"}]",
"otherSettings": [{ "specialInstructions": "" }]
}
```
# 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
An example new query will look like
- 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
```sql
INSERT INTO "users" ("username", "email", "role", "password") VALUES
('matthes01','blake.matthes@alpla.com','admin','JDJiJDE1FuNFpkYlk4NGdHUXpEMzlHR1BD'),
('leland001','jordan.leland@alpla.com','manager','vekJhN1dIVVVZa3pxR1l0T2hX'),
('brandon001','brandon.harry@alpla.com','manager','wdm1RSXJlZnJDYTZP');
;
```
- 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.

View File

@@ -0,0 +1,191 @@
param (
[string]$serviceName,
[string]$option,
[string]$appPath,
[string]$command, # just the command like run start or what ever you have in npm.
[string]$description,
[string]$remote,
[string]$server,
[string]$username,
[string]$admpass
)
# Example string to run with the parameters in it.
# .\services.ps1 -serviceName "LSTV2" -option "install" -appPath "E:\LST\lstV2" -description "Logistics Support Tool V2" -command "run start"
$nssmPath = $AppPath + "\nssm.exe"
$npmPath = "C:\Program Files\nodejs\npm.cmd" # Path to npm.cmd
# Convert the plain-text password to a SecureString
$securePass = ConvertTo-SecureString $admpass -AsPlainText -Force
$credentials = New-Object System.Management.Automation.PSCredential($username, $securePass)
if($remote -eq "true"){
# if(-not $username -or -not $admpass){
# Write-host "Missing adm account info please try again."
# exit 1
# }
$plantFunness = {
param ($service, $processType, $location)
# Call your PowerShell script inside plantFunness
# & "$($location)\dist\server\scripts\services.ps1" -serviceName $service -option $processType -appPath $location
if (-not ([Security.Principal.WindowsPrincipal] [Security.Principal.WindowsIdentity]::GetCurrent()).IsInRole([Security.Principal.WindowsBuiltInRole] "Administrator")) {
Write-Host "Error: This script must be run as Administrator."
exit 1
}
if(-not $service -or -not $processType){
Write-host "The service name or option is missing please enter one of them and try again."
exit 1
}
if ($processType -eq "start"){
write-host "Starting $($service)."
Start-Service $service
}
if ($processType -eq "stop"){
write-host "Stoping $($service)."
Stop-Service $service
}
if ($processType -eq "restart"){
write-host "Stoping $($service) to be restarted"
Stop-Service $service
Start-Sleep 3 # so we give it enough time to fully stop
write-host "Starting $($service)"
Start-Service $service
}
if ($processType -eq "prodStop"){
if(-not $location){
Write-host "The path to the app is missing please add it in and try again."
exit 1
}
& $nssmPath stop $service
write-host "Removing $($service)"
#& $nssmPath remove $serviceName confirm
sc.exe config $service start= disabled
}
if ($processType -eq "prodStart"){
if(-not $location){
Write-host "The path to the app is missing please add it in and try again."
exit 1
}
& $nssmPath start $service
write-host "Removing $($service)"
#& $nssmPath remove $serviceName confirm
sc.exe config $service start= auto
}
}
Invoke-Command -ComputerName $server -ScriptBlock $plantFunness -ArgumentList $serviceName, $option, $appPath -Credential $credentials
} else {
if (-not ([Security.Principal.WindowsPrincipal] [Security.Principal.WindowsIdentity]::GetCurrent()).IsInRole([Security.Principal.WindowsBuiltInRole] "Administrator")) {
Write-Host "Error: This script must be run as Administrator."
exit 1
}
if(-not $serviceName -or -not $option){
Write-host "The service name or option is missing please enter one of them and try again."
exit 1
}
if ($option -eq "start"){
write-host "Starting $($serviceName)."
Start-Service $serviceName
}
if ($option -eq "stop"){
write-host "Stoping $($serviceName)."
Stop-Service $serviceName
}
if ($option -eq "restart"){
write-host "Stoping $($serviceName) to be restarted"
Stop-Service $serviceName
Start-Sleep 3 # so we give it enough time to fully stop
write-host "Starting $($serviceName)"
Start-Service $serviceName
}
if ($option -eq "delete"){
if(-not $appPath){
Write-host "The path to the app is missing please add it in and try again."
exit 1
}
& $nssmPath stop $serviceName
write-host "Removing $($serviceName)"
& $nssmPath remove $serviceName confirm
}
if ($option -eq "prodStop"){
if(-not $appPath){
Write-host "The path to the app is missing please add it in and try again."
exit 1
}
& $nssmPath stop $serviceName
write-host "Removing $($serviceName)"
#& $nssmPath remove $serviceName confirm
sc.exe config $serviceName start= disabled
}
if ($option -eq "prodStart"){
if(-not $appPath){
Write-host "The path to the app is missing please add it in and try again."
exit 1
}
& $nssmPath start $serviceName
write-host "Removing $($serviceName)"
#& $nssmPath remove $serviceName confirm
sc.exe config $serviceName start= auto
}
if($option -eq "install"){
if(-not $appPath -or -not $description -or -not $command){
Write-host "Please check all parameters are passed to install the app.."
exit 1
}
$service = Get-Service -Name $serviceName -ErrorAction SilentlyContinue
if(-not $service){
write-host $serviceName "is not installed we will install it now"
Write-Host "Installing $serviceName..."
& $nssmPath install $serviceName $npmPath $command
& $nssmPath set $serviceName AppDirectory $appPath
& $nssmPath set $serviceName Description $description
# Set recovery options
sc.exe failure $serviceName reset= 0 actions= restart/5000/restart/5000/restart/5000
& $nssmPath start $serviceName
}else{
write-host $serviceName "is already installed will push the updated info"
Write-Host "Updating $serviceName..."
& $nssmPath stop $serviceName
& $nssmPath set $serviceName AppDirectory $appPath
& $nssmPath set $serviceName Description $description
# Set recovery options
sc.exe failure $serviceName reset= 0 actions= restart/5000/restart/5000/restart/5000
Start-Sleep 4
& $nssmPath start $serviceName
}
}
}

View File

@@ -0,0 +1,453 @@
param (
[string]$server,
[string]$token,
[string]$location,
[string]$devFolder,
[string]$serverIP,
[string]$build,
[string]$type,
[string]$username,
[string]$admpass,
[string]$obslst,
[string]$obsBuild
)
# Convert the plain-text password to a SecureString
$securePass = ConvertTo-SecureString $admpass -AsPlainText -Force
$credentials = New-Object System.Management.Automation.PSCredential($username, $securePass)
# lets get the version of the app we are updating
$pkgFile = "$devFolder\package.json"
$package = Get-Content -Path $pkgFile -Raw | ConvertFrom-Json
$version = "$($package.version)-$($package.admConfig.build -1)"
# Checking to make sure the server is up and online
Write-Output "Checking if $($token) is online to update."
$pingResult = Test-Connection -ComputerName $serverIP -Count 2 -Quiet
if (-not $pingResult) {
Write-Output "Server $($server) $($serverIP) is NOT reachable. Exiting script."
exit 1 # Terminate the script with a non-zero exit code
}
Write-Output "Server $($server) ($serverIP) is online."
# get the file name we want to grab
$buildZip = "lstv2-$version.zip"
if (-Not (Test-Path -Path "$($build)\$($buildZip)")) {
Write-Host "Build is missing from the build folder."
Write-host $buildZip
exit
}
Write-Host "---------------Starting the update Process----------------------------------"
Write-Host "File to be copied over is $buildZip"
Write-Host "Coping files to $($server)"
$destination = "\\$($server)\$($location)" -replace ":", "$"
Write-Host $destination
Write-Host "Forcing the removal of the mapped drive."
Get-PSDrive -Name "z" -ErrorAction SilentlyContinue | Remove-PSDrive -Force
# Create a mapped drive with credentials using New-PSDrive for the current session
try {
New-PSDrive -Name "z" -PSProvider FileSystem -Root $destination -Credential $credentials
# Create the update folder if it doesn't exist
if (-not (Test-Path -Path $destination)) {
New-Item -ItemType Directory -Path $destination -Force
}
# Copying files to the server
Write-Host "Copying files to $($server)"
Copy-Item -Path "$($build)\$($buildZip)" -Destination "z:\" -Recurse -Force
Write-Host "Files copied to $($server)"
} catch {
Write-Host "Error: $_"
} finally {
# Remove the mapped drive after copying
if (Get-PSDrive -Name "z" -ErrorAction SilentlyContinue) {
Write-Host "Removing mapped drive..."
Remove-PSDrive -Name "z"
}
}
write-Host $extractedFolderPath = "$server\$location$(if ($token -eq "usiow2") { "_2" })"
# The script that runs inside the plant.
$plantFunness = {
param ($server, $token, $location, $buildFile, $buildLoc, $obslst, $obsBuild)
$localPath = $location -replace '\$', ':'
$serverFile = "$($localPath)\$buildFile"
$serverPath = "$($localPath)"
$appPath = $extractedFolderPath
$nssmPath = $serverPath + "\nssm.exe"
$npmPath = "C:\Program Files\nodejs\npm.cmd" # Path to npm.cmd
Write-Host "In the plant we go!!!!!"
######################################################################################
# Removing the fist and frontend folder to make sure we keep them the same and clean.
######################################################################################
# Delete the directories after extraction
Write-Host "Deleting Dist and Frontend..."
Set-Location $serverPath
npm run removeOld # --omit=dev
Write-Host "Unzipping the folder..."
$extractedFolderPath = $serverPath
# Extract the files to the build path
try {
# Expand the archive
Expand-Archive -Path $serverFile -DestinationPath $extractedFolderPath -Force
# Delete the zip file after extraction
Write-Host "Deleting the zip file..."
Remove-Item -Path $serverFile -Force
} catch {
Write-Host "Error: $_"
exit 1 # Exit with a non-zero code if there's an error
}
# Write-Host "-----------------------Dealing with LSTv1 Stuff ------------------------------------"
# try {
# # Expand the archive
# Expand-Archive -Path "$($localPath)\$($obsBuild)" -DestinationPath $obslst -Force
# # Delete the zip file after extraction
# Write-Host "Deleting the zip file..."
# Remove-Item -Path "$($localPath)\$($obsBuild)" -Force
# } catch {
# Write-Host "Error: $_"
# exit 1 # Exit with a non-zero code if there's an error
# }
# # for iowa 2 need to change the port config on the start up of nextjs server
# if($token -eq "usiow2"){
# $jsonPkgloc = "$($obslst)\apps\frontend\package.json"
# #read the file
# $jsonContent = Get-Content -Path $jsonPkgloc | ConvertFrom-Json
# #change the second we want to update
# $jsonContent.scripts.start = "next start -p 3001"
# # convert back to json
# $jsonContent | ConvertTo-Json | Set-Content -Path $jsonPkgloc
# }
############################################################################
Write-Host "Stopping the services to do the updates, pkgs and db changes."
#Write-Host "Stopping services to update"
$serviceGateway = "LST-Gateway$(if ($token -eq "usiow2") { "_2" })"
$serviceAuth = "LST-Auth$(if ($token -eq "usiow2") { "_2" })"
$serviceSystem = "LST-System$(if ($token -eq "usiow2") { "_2" })"
$serviceApp = "LST-App$(if ($token -eq "usiow2") { "_2" })"
$serviceFrontEnd = "LST-frontend$(if ($token -eq "usiow2") { "_2" })"
$serviceOcme = "LST-Ocme$(if ($token -eq "usiow2") { "_2" })"
$serviceLstV2 = "LSTV2$(if ($token -eq "usiow2") { "_2" })"
# if($token -eq "usday1"){
# Write-Host "Stopping $($serviceOcme)"
# Stop-Service -DisplayName $serviceOcme -Force
# }
# Write-Host "Stopping $($serviceGateway)"
# Stop-Service -DisplayName $serviceGateway -Force
# Start-Sleep -Seconds 1
# Write-Host "Stopping $($serviceAuth)"
# Stop-Service -DisplayName $serviceAuth -Force
# Start-Sleep -Seconds 1
# Write-Host "Stopping $($serviceSystem)"
# Stop-Service -DisplayName $serviceSystem -Force
# Start-Sleep -Seconds 1
# Write-Host "Stopping $($serviceApp)"
# Stop-Service -DisplayName $serviceApp -Force
# Start-Sleep -Seconds 1
# Write-Host "Stopping $($serviceFrontEnd)"
# Stop-Service -DisplayName $serviceFrontEnd -Force
# Start-Sleep -Seconds 1
Write-Host "Stopping $($serviceLstV2)"
Stop-Service -DisplayName $serviceLstV2 -Force
Start-Sleep -Seconds 1
#################################################################
# Service removoal and making sure we have the new version added
#################################################################
#################################################################
# Removing all the old services
#################################################################
Write-Host "Removing services that are no longer used."
& $nssmPath remove "LogisticsSupportTool" confirm
& $nssmPath remove $serviceAuth confirm
& $nssmPath remove $serviceGateway confirm
& $nssmPath remove $serviceSystem confirm
& $nssmPath remove $serviceApp confirm
& $nssmPath remove $serviceFrontEnd confirm
& $nssmPath remove $serviceOcme confirm
# & $nssmPath remove $serviceGateway confirm
# if($token -eq "usday1"){
# & $nssmPath remove $serviceOcme confirm
# }
Start-Sleep -Seconds 2
$service = Get-Service -Name $serviceLstV2 -ErrorAction SilentlyContinue
if(-not $service){
## adding in lstAdm
Write-Host "Adding $($serviceLstV2)... incase its missing."
$commandToRun = "run start"
$description = "logistics Support Tool"
& $nssmPath install $serviceLstV2 $npmPath $commandToRun
Write-Host "Setting the app directory"
& $nssmPath set $serviceLstV2 AppDirectory $appPath
Write-Host "Setting the description"
& $nssmPath set $serviceLstV2 Description $description
Write-Host "Setting recovery options"
# Set recovery options
sc.exe failure $serviceLstV2 reset= 0 actions= restart/5000/restart/5000/restart/5000
}
# Doing an install
Write-Host "Running the install to make sure everything is updated."
Set-Location $serverPath
npm run prodinstall # --omit=dev
Write-Host "Finished doing updates"
# Start-Sleep -Seconds 1
# Write-HOst "Running db migrations"
# npm run db:migrate
###########################################################
# 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 = "4400"
# if ($token -eq "usiow2") {
# $dbLink = "lstBackendDB_2"
# $gatewayport = "4401"
# $systemport = "4201"
# $ocmeport = "4301"
# $appport = "4401"
# }
# 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
# Start-Sleep -Seconds 1
# npm run db:gen
# Start-Sleep -Seconds 1
# Write-Host "incase a new default setting was added we want to add it in."
# npm run db:init
###########################################################
# Starting the services back up.
###########################################################
# Write-Host "Starting the services"
# Write-Host "Starting $($serviceSystem)"
# Start-Service -DisplayName $serviceSystem
# Start-Sleep -Seconds 1
# Write-Host "Starting $($serviceGateway)"
# Start-Service -DisplayName $serviceGateway
# Start-Sleep -Seconds 1
# Write-Host "Starting $($serviceAuth)"
# Start-Service -DisplayName $serviceAuth
# Start-Sleep -Seconds 1
# Write-Host "Starting $($serviceApp)"
# Start-Service -DisplayName $serviceApp
# Start-Sleep -Seconds 1
# Write-Host "Starting $($serviceFrontEnd)"
# Start-Service -DisplayName $serviceFrontEnd
# Start-Sleep -Seconds 1
Write-Host "Starting $( $serviceLstV2)"
Start-Service -DisplayName $serviceLstV2
Start-Sleep -Seconds 1
Write-Host "$($server) finished updating"
# if($token -eq "usday1"){
# Write-Host "Starting $($serviceOcme)"
# Start-Service -DisplayName $serviceOcme
# }
}
Invoke-Command -ComputerName $server -ScriptBlock $plantFunness -ArgumentList $server, $token, $location, $buildZip, $buildLoc, $obslst, $obsBuild -Credential $credentials

View File

@@ -0,0 +1,22 @@
# Define the array of folders
$folders = @(
"AlplaBasis",
"AlplaBudget",
"AlplaINVOICE",
"AlplaLabel",
"AlplaOrder",
"AlplaPlanning",
"AlplaPurchase",
"AlplaStock",
"PDF24",
"Module shortcuts"
)
# Set permissions using icacls
$permissions = "Everyone:(OI)(CI)F"
# Loop through each folder and set permissions
foreach ($folder in $folders) {
$folderPath = "C:\Sources\AlplaPROD\$folder"
icacls $folderPath /grant $permissions /t /c /q
}

View File

@@ -0,0 +1,219 @@
import { spawn } from "child_process";
import { getAppInfo } from "../globalUtils/appInfo.js";
import { db } from "../../database/dbclient.js";
import { serverData } from "../../database/schema/serverData.js";
import { eq, sql } from "drizzle-orm";
import { createLog } from "../services/logger/logger.js";
import { serverSettings } from "../services/server/controller/settings/getSettings.js";
type UpdateServerResponse = {
success: boolean;
message: string;
};
export const updateServer = async (
devApp: string,
server: string | null,
all?: boolean | null
): Promise<UpdateServerResponse> => {
const app = await getAppInfo(devApp);
const serverInfo = await db
.select()
.from(serverData)
.where(eq(serverData.plantToken, server?.toLowerCase() ?? ""));
if (serverInfo.length === 0) {
createLog(
"error",
"lst",
"serverUpdater",
`Looks like you are missing the plant token or have entered an incorrect one please try again.`
);
return {
success: false,
message:
"Looks like you are missing the plant token or have entered an incorrect one please try again.",
};
}
if (serverInfo[0].isUpgrading && !all) {
createLog(
"error",
"lst",
"serverUpdater",
`Looks like ${serverInfo[0].plantToken} is upgrading already you cant do this again.`
);
return {
success: false,
message: `Looks like ${serverInfo[0].plantToken} is upgrading already you cant do this again.`,
};
}
console.log(serverInfo);
const scriptPath = `${process.env.DEVFOLDER}\\server\\scripts\\update.ps1 `;
const args = [
"-NoProfile",
"-ExecutionPolicy",
"Bypass",
"-File",
scriptPath,
"-username",
process.env.ADMUSER, // needs moved to somewhere else.
"-admpass",
process.env.ADMPASSWORD, // needs moved to somewhere else.
"-devFolder",
process.env.DEVFOLDER,
"-server",
serverInfo[0].serverDNS,
"-serverIP",
serverInfo[0].idAddress,
"-token",
serverInfo[0].plantToken,
"-build",
`${process.env.DEVFOLDER}\\builds`,
"-location",
serverInfo[0].serverLoc,
"-obslst",
serverInfo[0].oldVersion,
"-obsBuild",
app.admConfig.oldBuild,
,
];
return new Promise(async (resolve, reject) => {
const process = spawn("powershell", args);
// change the server to upgradeing
await db
.update(serverData)
.set({ isUpgrading: true })
.where(eq(serverData.plantToken, server?.toLowerCase() ?? ""));
//let stdout = "";
//let stderr = "";
// Collect stdout data
process.stdout.on("data", (data) => {
const output = data.toString().trim();
createLog("info", "lst", "serverUpdater", `${output}`);
//onData(output);
});
// Collect stderr data
process.stderr.on("data", (data) => {
const output = data.toString().trim();
createLog("info", "lst", "serverUpdater", `${output}`);
//onData(output);
});
// Handle process close
process.on("close", async (code) => {
if (code === 0) {
// if (count >= servers) {
// //onClose(`Server completed with code: ${code}`);
// }
createLog("info", "lst", "serverUpdater", `${server}`);
//update the last build.
try {
await db
.update(serverData)
.set({ lastUpdated: sql`NOW()`, isUpgrading: false })
.where(
eq(
serverData.plantToken,
server?.toLowerCase() ?? ""
)
);
createLog(
"info",
"lst",
"serverUpdater",
`${server?.toLowerCase()}, has been updated and can now be used again.`
);
} catch (error) {
createLog(
"error",
"lst",
"serverUpdater",
`There was an error updating the last time the server was updated: ${error}`
);
}
resolve({
success: true,
message: `${server?.toLowerCase()}, has been updated and can now be used again.`,
});
} else {
const errorMessage = `Process exited with code ${code}`;
// if (count >= servers) {
// //onClose(code);
// }
reject({
success: false,
message: `${server?.toLowerCase()}, Has encounted an error while updating.`,
});
}
});
// Handle errors with the process itself
process.on("error", (error) => {
//onError(err.message);
createLog("error", "lst", "serverUpdater", `${error}`);
reject(error);
});
});
};
export async function processAllServers(devApp: string) {
const servers = await db.select().from(serverData);
//change all servers to be upgrading
await db.update(serverData).set({ isUpgrading: true });
createLog(
"info",
"lst",
"serverUpdater",
`Running the update on all servers`
);
let count = 1;
for (const server of servers) {
try {
const updateToServer = await updateServer(
devApp,
server.plantToken,
true
);
createLog(
"info",
"lst",
"serverUpdater",
`${server.sName} was updated.`
);
count = count + 1;
// return {
// success: true,
// message: `${server.sName} was updated.`,
// data: updateToServer,
// };
} catch (error: any) {
createLog(
"info",
"lst",
"serverUpdater",
`Error updating ${server.sName}: ${error.message}`
);
// return {
// success: false,
// message: `Error updating ${server.sName}: ${error.message}`,
// };
}
}
return {
success: true,
message: `All Servers are being updated this will take some time.`,
};
}

View File

@@ -0,0 +1,223 @@
import AdmZip from "adm-zip";
import path from "path";
import fs from "fs";
import { execSync } from "child_process";
import { createLog } from "../services/logger/logger.js";
import { getAppInfo } from "../globalUtils/appInfo.js";
// create the ignore list
const ignoreList = [
".git",
"builds",
"server",
"node_modules",
"apiDocsLSTV2",
"testFiles",
".env",
".gitignore",
".versionrc.json",
"drizzle-dev.config.ts",
"nssm.exe",
"postgresql-17.2-3-windows-x64.exe",
// front end ignore
"frontend/node_modules",
"fonrtend/.env",
"frontend/public",
"frontend/src",
"frontend/.gitignore",
"frontend/eslint.config.js",
"frontend/index.html",
"frontend/package.json",
"frontend/package-lock.json",
"frontend/README.md",
"frontend/tsconfig.json",
"frontend/tsconfig.app.json",
"frontend/tsconfig.node.json",
"frontend/vite.config.ts",
"frontend/components.json",
//misc files
"jsTesting",
"dotnetwrapper",
"prodBuild",
];
const shouldIgnore = (itemPath: any) => {
const normalizedItemPath = itemPath.replace(/\\/g, "/");
return ignoreList.some((ignorePattern) => {
const normalizedIgnorePatther = ignorePattern.replace(/\\/g, "/");
return (
normalizedItemPath === normalizedIgnorePatther ||
normalizedItemPath.startsWith(`${normalizedIgnorePatther}/`)
);
});
};
const addToZip = (zip: any, currentPath: string, rootPath: string) => {
const items = fs.readdirSync(currentPath);
items.forEach((item) => {
const itemPath = path.join(currentPath, item);
const relativePath = path.relative(rootPath, itemPath);
// Skip if the item is in the ignore list
if (shouldIgnore(relativePath)) {
createLog("info", "lst", "zipUpBuild", `Ignoring: ${relativePath}`);
return;
}
const stat = fs.statSync(itemPath);
if (stat.isDirectory()) {
// If it's a directory, recursively add its contents
addToZip(zip, itemPath, rootPath);
} else {
// If it's a file, add it to the zip with the preserved folder structure
zip.addLocalFile(itemPath, path.dirname(relativePath));
}
});
};
const updateBuildNumber = (appLock: string) => {
const packagePath = path.join(appLock, "package.json"); // Adjust path if necessary
try {
// Read package.json
const pkgData = fs.readFileSync(packagePath, "utf8");
const pkgJson = JSON.parse(pkgData);
// Ensure admConfig exists
if (pkgJson.admConfig && typeof pkgJson.admConfig.build === "number") {
// Increment the build number
pkgJson.admConfig.build += 1;
// 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}`
);
// Auto-commit changes
execSync("git add package.json");
execSync(
`git commit -m "ci(release): bump build number to ${pkgJson.admConfig.build}"`
);
} else {
createLog(
"error",
"lst",
"zipUpBuild",
"admConfig.build is missing or not a number"
);
}
} catch (error) {
createLog(
"error",
"lst",
"zipUpBuild",
`Error updating build number: ${error}`
);
}
};
export const createZip = async (appLock: string) => {
const app = await getAppInfo(appLock);
const zip = new AdmZip();
//dest path for this app... hard coded for meow will be in db later
const destPath = `${process.env.DEVFOLDER}\\builds`;
const srcPath = `${process.env.DEVFOLDER}`;
addToZip(zip, srcPath, srcPath);
// Write the zip file to disk
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}`
);
updateBuildNumber(appLock);
// only keep the last 5 builds for the type we have.
try {
const appFiles = fs
.readdirSync(destPath)
.filter((file) => file.startsWith(app.name)) // Ensure only backend files are matched
.map((file) => ({
name: file,
time: fs.statSync(path.join(destPath, file)).mtime.getTime(),
}))
.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)}`
);
if (appFiles.length > 20) {
appFiles.slice(0, -20).forEach((file) => {
const filePath = path.join(destPath, file.name);
try {
fs.unlinkSync(filePath);
createLog(
"info",
"lst",
"zipUpBuild",
`Deleted: ${file.name}`
);
} catch (error: any) {
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}`
);
}
};
//createZip("C:\\Users\\matthes01\\Documents\\lstv2");
// Only call `createZip` if the script is executed directly
if (process.argv.length > 2) {
const location = process.argv[2];
if (!location) {
createLog("error", "lst", "zipUpBuild", "Error: No location provided.");
process.exit(1);
} else {
createLog("info", "lst", "zipUpBuild", "Startiing the zip process.");
}
createZip(location);
} else {
createLog("error", "lst", "zipUpBuild", "Error: No location provided.");
}