diff --git a/.gitignore b/.gitignore index b4b1be0..04eab77 100644 --- a/.gitignore +++ b/.gitignore @@ -1,6 +1,11 @@ # ---> Node testFiles builds +.includes +.buildNumber +temp +.scriptCreds +node-v24.14.0-x64.msi # Logs logs *.log diff --git a/backend/opendock/openDockRreleaseMonitor.utils.ts b/backend/opendock/openDockRreleaseMonitor.utils.ts index f8fe653..975cc06 100644 --- a/backend/opendock/openDockRreleaseMonitor.utils.ts +++ b/backend/opendock/openDockRreleaseMonitor.utils.ts @@ -1,10 +1,10 @@ import axios from "axios"; -import { settings } from "backend/db/schema/settings.schema.js"; import { addHours } from "date-fns"; import { formatInTimeZone } from "date-fns-tz"; import { eq, sql } from "drizzle-orm"; import { db } from "../db/db.controller.js"; import { opendockApt } from "../db/schema/opendock.schema.js"; +import { settings } from "../db/schema/settings.schema.js"; import { createLogger } from "../logger/logger.controller.js"; import { prodQuery } from "../prodSql/prodSqlQuery.controller.js"; import { @@ -80,9 +80,9 @@ const postRelease = async (release: Releases) => { : release.DeliveryState === 3 // this will consider finished and if a correction needs made to the bol we need to cancel and reactivate the order ? "Completed" : release.DeliveryState === 4 && "Completed", - userId: "2629b4f6-0003-472d-8b26-66a69ce5ac50", // this should be the carrierid - loadTypeId: "0aa7988e-b17b-4f10-acdd-3d029b44a773", // well get this and make it a default one - dockId: "00ba4386-ce5a-4dd1-9356-6e6d10a24609", // this the warehouse we want it in to start out + userId: process.env.DEFAULT_CARRIER, // this should be the carrierid + loadTypeId: process.env.DEFAULT_LOAD_TYPE, // well get this and make it a default one + dockId: process.env.DEFAULT_DOCK, // this the warehouse we want it in to start out refNumbers: [release.ReleaseNumber], refNumber: release.ReleaseNumber, start: release.DeliveryDate, diff --git a/backend/system/stats.route.ts b/backend/system/stats.route.ts index c953195..10e0f85 100644 --- a/backend/system/stats.route.ts +++ b/backend/system/stats.route.ts @@ -16,6 +16,7 @@ router.get("/", async (_, res) => { res.status(200).json({ status: "ok", uptime: process.uptime(), + nodeVersion: process.version, memoryUsage: `Heap: ${(used.heapUsed / 1024 / 1024).toFixed(2)} MB / RSS: ${( used.rss / 1024 / 1024 ).toFixed(2)} MB`, diff --git a/backend/system/system.routes.ts b/backend/system/system.routes.ts index 927f13e..6c22e65 100644 --- a/backend/system/system.routes.ts +++ b/backend/system/system.routes.ts @@ -1,5 +1,5 @@ -import { requireAuth } from "backend/middleware/auth.middleware.js"; import type { Express } from "express"; +import { requireAuth } from "../middleware/auth.middleware.js"; import getSettings from "./settings.route.js"; import updSetting from "./settingsUpdate.route.js"; import stats from "./stats.route.js"; diff --git a/brunoApi/auth/Login.bru b/brunoApi/auth/Login.bru index 06f5c05..d0e3410 100644 --- a/brunoApi/auth/Login.bru +++ b/brunoApi/auth/Login.bru @@ -5,7 +5,7 @@ meta { } post { - url: {{url}}/lst/api/authentication/login + url: {{url}}/api/authentication/login body: json auth: inherit } diff --git a/brunoApi/auth/Register.bru b/brunoApi/auth/Register.bru index f237003..19d34dd 100644 --- a/brunoApi/auth/Register.bru +++ b/brunoApi/auth/Register.bru @@ -5,16 +5,16 @@ meta { } post { - url: {{url}}/lst/api/authentication/register + url: {{url}}/authentication/register body: json auth: inherit } body:json { { - "username": "jane005", - "email": "jane@alpla.com", - "password": "superSecretPassword" + "username": "matthes01", + "email": "blake.matthes@alpla.com", + "password": "nova0511" } } diff --git a/brunoApi/datamart/Get queries.bru b/brunoApi/datamart/Get queries.bru index f0a788d..4622814 100644 --- a/brunoApi/datamart/Get queries.bru +++ b/brunoApi/datamart/Get queries.bru @@ -5,7 +5,7 @@ meta { } get { - url: {{url}}/lst/api/datamart + url: {{url}}/api/datamart body: none auth: inherit } diff --git a/brunoApi/datamart/Run Query.bru b/brunoApi/datamart/Run Query.bru index 38df4b6..99e0512 100644 --- a/brunoApi/datamart/Run Query.bru +++ b/brunoApi/datamart/Run Query.bru @@ -5,7 +5,7 @@ meta { } get { - url: {{url}}/lst/api/datamart/:name + url: {{url}}/api/datamart/:name body: none auth: inherit } diff --git a/brunoApi/environments/lstv3.bru b/brunoApi/environments/lstv3.bru index 6385759..81416f1 100644 --- a/brunoApi/environments/lstv3.bru +++ b/brunoApi/environments/lstv3.bru @@ -1,4 +1,4 @@ vars { - url: http://localhost:3000 + url: http://usmcd1vms036:3100 ~session_cookie: } diff --git a/brunoApi/opendock/GetApt.bru b/brunoApi/opendock/GetApt.bru index 1693a64..5631e7a 100644 --- a/brunoApi/opendock/GetApt.bru +++ b/brunoApi/opendock/GetApt.bru @@ -5,7 +5,7 @@ meta { } get { - url: {{url}}/lst/api/opendock + url: {{url}}/api/opendock body: none auth: inherit } diff --git a/brunoApi/prodSql/Sql Start.bru b/brunoApi/prodSql/Sql Start.bru index b11be38..2998557 100644 --- a/brunoApi/prodSql/Sql Start.bru +++ b/brunoApi/prodSql/Sql Start.bru @@ -5,11 +5,12 @@ meta { } post { - url: {{url}}/lst/api/system/prodsql/start + url: {{url}}/api/system/prodsql/start body: none auth: inherit } settings { encodeUrl: true + timeout: 0 } diff --git a/brunoApi/prodSql/Sql restart.bru b/brunoApi/prodSql/Sql restart.bru index 85defb3..fbd0b0b 100644 --- a/brunoApi/prodSql/Sql restart.bru +++ b/brunoApi/prodSql/Sql restart.bru @@ -5,7 +5,7 @@ meta { } post { - url: {{url}}/lst/api/system/prodsql/restart + url: {{url}}/api/system/prodsql/restart body: none auth: inherit } diff --git a/brunoApi/prodSql/Sql stop.bru b/brunoApi/prodSql/Sql stop.bru index 75c5e07..80d3a13 100644 --- a/brunoApi/prodSql/Sql stop.bru +++ b/brunoApi/prodSql/Sql stop.bru @@ -5,7 +5,7 @@ meta { } post { - url: {{url}}/lst/api/system/prodsql/stop + url: {{url}}/api/system/prodsql/stop body: none auth: inherit } diff --git a/brunoApi/system/Get Settings.bru b/brunoApi/system/Get Settings.bru index 01f912b..b9b8ec7 100644 --- a/brunoApi/system/Get Settings.bru +++ b/brunoApi/system/Get Settings.bru @@ -5,7 +5,7 @@ meta { } get { - url: {{url}}/lst/api/settings + url: {{url}}/api/settings body: none auth: inherit } diff --git a/brunoApi/system/Status.bru b/brunoApi/system/Status.bru index 89c0650..5dc64c2 100644 --- a/brunoApi/system/Status.bru +++ b/brunoApi/system/Status.bru @@ -5,7 +5,7 @@ meta { } get { - url: {{url}}/lst/api/stats + url: {{url}}/api/stats body: none auth: inherit } diff --git a/brunoApi/system/updateSetting.bru b/brunoApi/system/updateSetting.bru index fbe19c6..83675ee 100644 --- a/brunoApi/system/updateSetting.bru +++ b/brunoApi/system/updateSetting.bru @@ -5,7 +5,7 @@ meta { } patch { - url: {{url}}/lst/api/settings/opendock_sync + url: {{url}}/api/settings/opendock_sync body: json auth: inherit } diff --git a/brunoApi/utils/Active Jobs.bru b/brunoApi/utils/Active Jobs.bru index 463e04b..3c24e98 100644 --- a/brunoApi/utils/Active Jobs.bru +++ b/brunoApi/utils/Active Jobs.bru @@ -5,7 +5,7 @@ meta { } get { - url: {{url}}/lst/api/utils/croner + url: {{url}}/api/utils/croner body: none auth: inherit } diff --git a/brunoApi/utils/Change status.bru b/brunoApi/utils/Change job status.bru similarity index 73% rename from brunoApi/utils/Change status.bru rename to brunoApi/utils/Change job status.bru index 38d9d4c..c4ce9d8 100644 --- a/brunoApi/utils/Change status.bru +++ b/brunoApi/utils/Change job status.bru @@ -1,11 +1,11 @@ meta { - name: Change status + name: Change job status type: http seq: 2 } patch { - url: {{url}}/lst/api/utils/croner/stop + url: {{url}}/api/utils/croner/stop body: json auth: inherit } diff --git a/migrations/0015_neat_donald_blake.sql b/migrations/0015_neat_donald_blake.sql new file mode 100644 index 0000000..82320e2 --- /dev/null +++ b/migrations/0015_neat_donald_blake.sql @@ -0,0 +1,5 @@ +CREATE TABLE "stats" ( + "id" text PRIMARY KEY DEFAULT 'serverStats' NOT NULL, + "build" integer DEFAULT 1 NOT NULL, + "last_update" timestamp DEFAULT now() +); diff --git a/migrations/meta/0015_snapshot.json b/migrations/meta/0015_snapshot.json new file mode 100644 index 0000000..ac3b40e --- /dev/null +++ b/migrations/meta/0015_snapshot.json @@ -0,0 +1,1147 @@ +{ + "id": "cb45bbbc-6244-4883-858b-5e3b92026a9b", + "prevId": "07ac9d3e-db02-42f8-ba47-9e7ecabab07a", + "version": "7", + "dialect": "postgresql", + "tables": { + "public.job_audit_log": { + "name": "job_audit_log", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "uuid", + "primaryKey": true, + "notNull": true, + "default": "gen_random_uuid()" + }, + "job_name": { + "name": "job_name", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "start_at": { + "name": "start_at", + "type": "timestamp", + "primaryKey": false, + "notNull": false + }, + "finished_at": { + "name": "finished_at", + "type": "timestamp", + "primaryKey": false, + "notNull": false + }, + "duration_ms": { + "name": "duration_ms", + "type": "integer", + "primaryKey": false, + "notNull": false + }, + "status": { + "name": "status", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "error_message": { + "name": "error_message", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "error_stack": { + "name": "error_stack", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "meta_data": { + "name": "meta_data", + "type": "jsonb", + "primaryKey": false, + "notNull": false + }, + "created_at": { + "name": "created_at", + "type": "timestamp", + "primaryKey": false, + "notNull": false, + "default": "now()" + } + }, + "indexes": { + "idx_job_audit_logs_cleanup": { + "name": "idx_job_audit_logs_cleanup", + "columns": [ + { + "expression": "start_at", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": {}, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.account": { + "name": "account", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "account_id": { + "name": "account_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "provider_id": { + "name": "provider_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "user_id": { + "name": "user_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "access_token": { + "name": "access_token", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "refresh_token": { + "name": "refresh_token", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "id_token": { + "name": "id_token", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "access_token_expires_at": { + "name": "access_token_expires_at", + "type": "timestamp", + "primaryKey": false, + "notNull": false + }, + "refresh_token_expires_at": { + "name": "refresh_token_expires_at", + "type": "timestamp", + "primaryKey": false, + "notNull": false + }, + "scope": { + "name": "scope", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "password": { + "name": "password", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "created_at": { + "name": "created_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true + } + }, + "indexes": { + "account_userId_idx": { + "name": "account_userId_idx", + "columns": [ + { + "expression": "user_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "account_user_id_user_id_fk": { + "name": "account_user_id_user_id_fk", + "tableFrom": "account", + "tableTo": "user", + "columnsFrom": [ + "user_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.apikey": { + "name": "apikey", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "name": { + "name": "name", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "start": { + "name": "start", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "prefix": { + "name": "prefix", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "key": { + "name": "key", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "user_id": { + "name": "user_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "refill_interval": { + "name": "refill_interval", + "type": "integer", + "primaryKey": false, + "notNull": false + }, + "refill_amount": { + "name": "refill_amount", + "type": "integer", + "primaryKey": false, + "notNull": false + }, + "last_refill_at": { + "name": "last_refill_at", + "type": "timestamp", + "primaryKey": false, + "notNull": false + }, + "enabled": { + "name": "enabled", + "type": "boolean", + "primaryKey": false, + "notNull": false, + "default": true + }, + "rate_limit_enabled": { + "name": "rate_limit_enabled", + "type": "boolean", + "primaryKey": false, + "notNull": false, + "default": true + }, + "rate_limit_time_window": { + "name": "rate_limit_time_window", + "type": "integer", + "primaryKey": false, + "notNull": false, + "default": 86400000 + }, + "rate_limit_max": { + "name": "rate_limit_max", + "type": "integer", + "primaryKey": false, + "notNull": false, + "default": 10 + }, + "request_count": { + "name": "request_count", + "type": "integer", + "primaryKey": false, + "notNull": false, + "default": 0 + }, + "remaining": { + "name": "remaining", + "type": "integer", + "primaryKey": false, + "notNull": false + }, + "last_request": { + "name": "last_request", + "type": "timestamp", + "primaryKey": false, + "notNull": false + }, + "expires_at": { + "name": "expires_at", + "type": "timestamp", + "primaryKey": false, + "notNull": false + }, + "created_at": { + "name": "created_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true + }, + "permissions": { + "name": "permissions", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "metadata": { + "name": "metadata", + "type": "text", + "primaryKey": false, + "notNull": false + } + }, + "indexes": { + "apikey_key_idx": { + "name": "apikey_key_idx", + "columns": [ + { + "expression": "key", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "apikey_userId_idx": { + "name": "apikey_userId_idx", + "columns": [ + { + "expression": "user_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "apikey_user_id_user_id_fk": { + "name": "apikey_user_id_user_id_fk", + "tableFrom": "apikey", + "tableTo": "user", + "columnsFrom": [ + "user_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.jwks": { + "name": "jwks", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "public_key": { + "name": "public_key", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "private_key": { + "name": "private_key", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "created_at": { + "name": "created_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true + }, + "expires_at": { + "name": "expires_at", + "type": "timestamp", + "primaryKey": false, + "notNull": false + } + }, + "indexes": {}, + "foreignKeys": {}, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.session": { + "name": "session", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "expires_at": { + "name": "expires_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true + }, + "token": { + "name": "token", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "created_at": { + "name": "created_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true + }, + "ip_address": { + "name": "ip_address", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "user_agent": { + "name": "user_agent", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "user_id": { + "name": "user_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "impersonated_by": { + "name": "impersonated_by", + "type": "text", + "primaryKey": false, + "notNull": false + } + }, + "indexes": { + "session_userId_idx": { + "name": "session_userId_idx", + "columns": [ + { + "expression": "user_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "session_user_id_user_id_fk": { + "name": "session_user_id_user_id_fk", + "tableFrom": "session", + "tableTo": "user", + "columnsFrom": [ + "user_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": { + "session_token_unique": { + "name": "session_token_unique", + "nullsNotDistinct": false, + "columns": [ + "token" + ] + } + }, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.user": { + "name": "user", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "name": { + "name": "name", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "email": { + "name": "email", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "email_verified": { + "name": "email_verified", + "type": "boolean", + "primaryKey": false, + "notNull": true, + "default": false + }, + "image": { + "name": "image", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "created_at": { + "name": "created_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "role": { + "name": "role", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "banned": { + "name": "banned", + "type": "boolean", + "primaryKey": false, + "notNull": false, + "default": false + }, + "ban_reason": { + "name": "ban_reason", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "ban_expires": { + "name": "ban_expires", + "type": "timestamp", + "primaryKey": false, + "notNull": false + }, + "username": { + "name": "username", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "display_username": { + "name": "display_username", + "type": "text", + "primaryKey": false, + "notNull": false + } + }, + "indexes": {}, + "foreignKeys": {}, + "compositePrimaryKeys": {}, + "uniqueConstraints": { + "user_email_unique": { + "name": "user_email_unique", + "nullsNotDistinct": false, + "columns": [ + "email" + ] + }, + "user_username_unique": { + "name": "user_username_unique", + "nullsNotDistinct": false, + "columns": [ + "username" + ] + } + }, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.verification": { + "name": "verification", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "identifier": { + "name": "identifier", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "value": { + "name": "value", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "expires_at": { + "name": "expires_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true + }, + "created_at": { + "name": "created_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": { + "verification_identifier_idx": { + "name": "verification_identifier_idx", + "columns": [ + { + "expression": "identifier", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": {}, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.datamart": { + "name": "datamart", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "uuid", + "primaryKey": true, + "notNull": true, + "default": "gen_random_uuid()" + }, + "name": { + "name": "name", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "description": { + "name": "description", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "query": { + "name": "query", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "version": { + "name": "version", + "type": "integer", + "primaryKey": false, + "notNull": true, + "default": 1 + }, + "active": { + "name": "active", + "type": "boolean", + "primaryKey": false, + "notNull": false, + "default": true + }, + "options": { + "name": "options", + "type": "text", + "primaryKey": false, + "notNull": false, + "default": "''" + }, + "public_access": { + "name": "public_access", + "type": "boolean", + "primaryKey": false, + "notNull": false, + "default": false + }, + "add_date": { + "name": "add_date", + "type": "timestamp", + "primaryKey": false, + "notNull": false, + "default": "now()" + }, + "add_user": { + "name": "add_user", + "type": "text", + "primaryKey": false, + "notNull": false, + "default": "'lst-system'" + }, + "upd_date": { + "name": "upd_date", + "type": "timestamp", + "primaryKey": false, + "notNull": false, + "default": "now()" + }, + "upd_user": { + "name": "upd_user", + "type": "text", + "primaryKey": false, + "notNull": false, + "default": "'lst-system'" + } + }, + "indexes": {}, + "foreignKeys": {}, + "compositePrimaryKeys": {}, + "uniqueConstraints": { + "datamart_name_unique": { + "name": "datamart_name_unique", + "nullsNotDistinct": false, + "columns": [ + "name" + ] + } + }, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.logs": { + "name": "logs", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "uuid", + "primaryKey": true, + "notNull": true, + "default": "gen_random_uuid()" + }, + "level": { + "name": "level", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "module": { + "name": "module", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "subModule": { + "name": "subModule", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "message": { + "name": "message", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "stack": { + "name": "stack", + "type": "jsonb", + "primaryKey": false, + "notNull": false, + "default": "'[]'::jsonb" + }, + "checked": { + "name": "checked", + "type": "boolean", + "primaryKey": false, + "notNull": false, + "default": false + }, + "hostname": { + "name": "hostname", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "created_at": { + "name": "created_at", + "type": "timestamp", + "primaryKey": false, + "notNull": false, + "default": "now()" + } + }, + "indexes": {}, + "foreignKeys": {}, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.opendock_apt": { + "name": "opendock_apt", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "uuid", + "primaryKey": true, + "notNull": true, + "default": "gen_random_uuid()" + }, + "release": { + "name": "release", + "type": "integer", + "primaryKey": false, + "notNull": false + }, + "open_dock_apt_id": { + "name": "open_dock_apt_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "appointment": { + "name": "appointment", + "type": "jsonb", + "primaryKey": false, + "notNull": false, + "default": "'[]'::jsonb" + }, + "upd_date": { + "name": "upd_date", + "type": "timestamp", + "primaryKey": false, + "notNull": false, + "default": "now()" + }, + "created_at": { + "name": "created_at", + "type": "timestamp", + "primaryKey": false, + "notNull": false, + "default": "now()" + } + }, + "indexes": {}, + "foreignKeys": {}, + "compositePrimaryKeys": {}, + "uniqueConstraints": { + "opendock_apt_release_unique": { + "name": "opendock_apt_release_unique", + "nullsNotDistinct": false, + "columns": [ + "release" + ] + } + }, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.settings": { + "name": "settings", + "schema": "", + "columns": { + "settings_id": { + "name": "settings_id", + "type": "uuid", + "primaryKey": true, + "notNull": true, + "default": "gen_random_uuid()" + }, + "name": { + "name": "name", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "value": { + "name": "value", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "description": { + "name": "description", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "moduleName": { + "name": "moduleName", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "active": { + "name": "active", + "type": "boolean", + "primaryKey": false, + "notNull": false, + "default": true + }, + "roles": { + "name": "roles", + "type": "jsonb", + "primaryKey": false, + "notNull": true, + "default": "'[\"systemAdmin\"]'::jsonb" + }, + "settingType": { + "name": "settingType", + "type": "setting_type", + "typeSchema": "public", + "primaryKey": false, + "notNull": false + }, + "seed_version": { + "name": "seed_version", + "type": "integer", + "primaryKey": false, + "notNull": false, + "default": 1 + }, + "add_User": { + "name": "add_User", + "type": "text", + "primaryKey": false, + "notNull": true, + "default": "'LST_System'" + }, + "add_Date": { + "name": "add_Date", + "type": "timestamp", + "primaryKey": false, + "notNull": false, + "default": "now()" + }, + "upd_User": { + "name": "upd_User", + "type": "text", + "primaryKey": false, + "notNull": true, + "default": "'LST_System'" + }, + "upd_date": { + "name": "upd_date", + "type": "timestamp", + "primaryKey": false, + "notNull": false, + "default": "now()" + } + }, + "indexes": { + "name": { + "name": "name", + "columns": [ + { + "expression": "name", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": true, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": {}, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.stats": { + "name": "stats", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true, + "default": "'serverStats'" + }, + "build": { + "name": "build", + "type": "integer", + "primaryKey": false, + "notNull": true, + "default": 1 + }, + "last_update": { + "name": "last_update", + "type": "timestamp", + "primaryKey": false, + "notNull": false, + "default": "now()" + } + }, + "indexes": {}, + "foreignKeys": {}, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + } + }, + "enums": { + "public.setting_type": { + "name": "setting_type", + "schema": "public", + "values": [ + "feature", + "system", + "standard" + ] + } + }, + "schemas": {}, + "sequences": {}, + "roles": {}, + "policies": {}, + "views": {}, + "_meta": { + "columns": {}, + "schemas": {}, + "tables": {} + } +} \ No newline at end of file diff --git a/migrations/meta/_journal.json b/migrations/meta/_journal.json index c728143..4131f31 100644 --- a/migrations/meta/_journal.json +++ b/migrations/meta/_journal.json @@ -106,6 +106,13 @@ "when": 1772012229060, "tag": "0014_heavy_kitty_pryde", "breakpoints": true + }, + { + "idx": 15, + "version": "7", + "when": 1772415040979, + "tag": "0015_neat_donald_blake", + "breakpoints": true } ] } \ No newline at end of file diff --git a/package.json b/package.json index 48e6655..d2a5902 100644 --- a/package.json +++ b/package.json @@ -12,7 +12,7 @@ "dev:db:generate": "tsc && npx drizzle-kit generate --config=drizzle.config.ts", "build": "rimraf dist && npm run dev:db:generate && npm run dev:db:migrate && npm run build:app && npm run build:copySql", "build:app": "tsc", - "build:agent": "cd agent && tsc -p tsconfig.json", + "agent": "powershell -ExecutionPolicy Bypass -File scripts/agentController.ps1", "build:docker": "docker compose up --force-recreate --build -d", "build:copySql": "xcopy backend\\prodSql\\queries dist\\backend\\prodSql\\queries\\ /E /I /Y ", "lint": "tsc && biome lint", @@ -24,6 +24,7 @@ "version": "changeset version", "release": "dotenvx run -f .env -- npm run version && git push --follow-tags && node scripts/create-release.js", "specCheck": "node scripts/check-route-specs.mjs" + }, "workspaces": [ "backend", diff --git a/scripts/agentController.ps1 b/scripts/agentController.ps1 index c349c6c..6c9916a 100644 --- a/scripts/agentController.ps1 +++ b/scripts/agentController.ps1 @@ -1,17 +1,66 @@ +# param ( +# [string]$username, +# [string]$password +# ) + Set-StrictMode -Version Latest $ErrorActionPreference = "Stop" +# .\agentController.ps1 -username "blake" -password "blake" # config -$Servers = @("appserver1", "appserver2") # hostnames or IPs -$ServiceName = "MyAppService" # Windows service name (or pm2 process name logic) +$ServiceName = "LSTV3_app" $AppDir= "C:\Users\matthes01\Documents\lst_v3" -$RemoteTempZip = "C:\Windows\Temp\release.zip" -$RemoteReleasesRoot = "C:\App\releases" -$RemoteCurrent = "C:\App\current" +$KeepLast = 10 # how many builds do we want to keep. +$Servers = @( + [PSCustomObject]@{ + server = "uslim1vms006" + token = "uslim1" + loc = "E$\LST_V3" + }, + [PSCustomObject]@{ + server = "usmcd1vms036" + token = "uslim1" + loc = "E$\LST_V3" + } + #@{ server = "usmcd1vms036"; token = "test1"; loc = "E$\LST\lst_backend"; } + #@{ server = "usiow1vms036"; token = "test1"; loc = "E$\LST\lst_backend"; } + #@{ server = "usbet1vms006"; token = "usbet1";loc = "C$\Users\adm_matthes01\Desktop\lst_backend"; } + #@{ server = "usbow1vms006"; token = "usbow1"; loc = "C$\Users\adm_matthes01\Desktop\lst_backend" ; } + #@{ server = "usbow2vms006"; token = "usbow2"; loc = "C$\Users\adm_matthes01\Desktop\lst_backend" ; } + #@{ server = "usday1vms006"; token = "usday1"; loc = "E$\LST\lst_backend" ; } + #@{ server = "usflo1vms006"; token = "usflo1"; loc = "C$\Users\adm_matthes01\Desktop\lst_backend" ; } + #@{ server = "ushou1vms006"; token = "ushou1"; loc = "C$\Users\adm_matthes01\Desktop\lst_backend" ;} + #@{ server = "usiow1vms006"; token = "usiow1"; loc = "C$\Users\adm_matthes01\Desktop\lst_backend" ; } + #@{ server = "usiow1vms006"; token = "usiow2"; loc = "D$\lst\lst_backend_2" ; } + #@{ server = "usjci1vms006"; token = "usjci1"; loc = "D$\LST\lst_backend" ; } + #@{ server = "usksc1vms006"; token = "uskc1"; loc = "C$\Users\adm_matthes01\Desktop\lst_backend" ;} + #@{ server = "usmcd1vms006"; token = "usmcd1"; loc = "C$\Users\adm_matthes01\Desktop\lst_backend" ; } + #@{ server = "usshe1vms006"; token = "usshe1"; loc = "C$\Users\adm_matthes01\Desktop\lst_backend" ;} + #@{ server = "usslc1vms006"; token = "usslc1"; loc = "C$\Users\adm_matthes01\Desktop\lst_backend" ;} + #@{ server = "usstp1vms006"; token = "usstp1"; loc = "E$\LST\lst_backend" ; } + #@{ server = "usweb1vms006"; token = "usweb1"; loc = "C$\Users\adm_matthes01\Desktop\lst_backend" ;} + #@{ server = "usmar1vms006"; token = "test1"; loc = "E$\LST\lst_backend"; } + +) +#-------------------------------------------------- +# below this shouldn't really need to be messed with +#-------------------------------------------------- -#-------------------------------------------------- -# below this shouldnt really need to be messed with -#-------------------------------------------------- +# create the username and password to sign into the server and do the udpate stuff +$credFile = Join-Path $AppDir ".scriptCreds" +$credData = @{} + +Get-Content $credFile | ForEach-Object { + if ($_ -match "=") { + $key, $value = $_ -split "=", 2 + $credData[$key.Trim()] = $value.Trim() + } +} +$username = $credData["user"] +$password = $credData["password"] + +$securePass = ConvertTo-SecureString $password -AsPlainText -Force +$credentials = New-Object System.Management.Automation.PSCredential($username, $securePass) function Show-Menu { Clear-Host @@ -26,51 +75,320 @@ function Show-Menu { } function Select-Server { - param([string[]]$List) + param([object[]]$List) for ($i = 0; $i -lt $List.Count; $i++) { - Write-Host ("{0}. {1}" -f ($i+1), $List[$i]) + Write-Host ("{0}. {1}" -f ($i+1), $List[$i].server) } + Write-Host "$($List.Count + 1) All" + Write-Host "$($List.Count + 2) exit" + $sel = Read-Host "Select server by number" + + if ($sel -eq $List.Count + 1) { + return "all" + } + + if ($sel -eq $List.Count + 2) { + return $null + } if ($sel -match '^\d+$' -and [int]$sel -ge 1 -and [int]$sel -le $List.Count) { return $List[[int]$sel - 1] } else { Write-Host "Invalid selection" + Read-Host -Prompt "Press Enter to continue..." + Select-Server -List $Servers return $null } } +function Build-App { + try { + Push-Location $AppDir + Write-Host "Running: npm run build in $AppDir" + npm run build + Start-Sleep -Seconds 3 + Write-Host "Build completed successfully." + } + catch { + Write-Host "Build failed: $_" + throw + } + finally { + Pop-Location + } +} + +function Zip-App { + $BuildNumber = "1" + $buildFile = Join-Path $AppDir ".buildNumber" + + # validate we have a build file and create it if not there + if (-Not (Test-Path $buildfile)) { + Write-Error "File not found: $buildfile, creating it." + New-Item -Path $buildfile -ItemType File | Out-Null + $BuildNumber = "1" + Set-Content -Path $BuildFile -Value $BuildNumber + } + + #bump the build number + if (Test-Path $BuildFile) { + $content = Get-Content $BuildFile | Select-Object -First 1 + $num = $content.Trim() -as [int] # safe cast + + if ($num) { + $BuildNumber = $num + 1 + } else { + $BuildNumber = 1 + } + } + $BuildNumber = $BuildNumber.ToString() + Set-Content -Path $BuildFile -Value $BuildNumber + Write-Output "New Build Number: $BuildNumber" + + # get the include data + $Includes = Join-Path $AppDir ".includes" + if (-Not (Test-Path $Includes)) { + Write-Error "File not found: $Includes, exiting as we dont want to zip up the entire app." + exit 1 + } + + $BuildFolder = Join-Path $AppDir "builds" + + if (-Not (Test-Path $BuildFolder)) { + write-host "Build folder missing creating it" + New-Item -Path $BuildFolder -ItemType Directory | Out-Null + } + + # do the zip stuff + $itemsToZip = @() + Get-Content $Includes | ForEach-Object { + $relPath = $_.Trim() + if ($relPath -ne "") { + $fullPath = Join-Path $AppDir $relPath + if (Test-Path $fullPath) { + $itemsToZip += [PSCustomObject]@{ + FullPath = $fullPath + RelativePath = $relPath + } + } else { + Write-Warning "Path not found: $fullPath" + } + } + } + + if (-Not $itemsToZip) { + Write-Warning "No valid files or folders to zip." + return + } + + $zipFileName = Join-Path $BuildFolder "LSTV3-$BuildNumber.zip" + + if (Test-Path $zipFileName) { + Remove-Item $zipFileName + } + + $tempFolder = Join-Path $AppDir "temp\zip-temp-$BuildNumber" + if (Test-Path $tempFolder) { Remove-Item $tempFolder -Recurse -Force } + New-Item -Path $tempFolder -ItemType Directory | Out-Null + + foreach ($item in $itemsToZip) { + $dest = Join-Path $tempFolder $item.RelativePath + $destDir = Split-Path $dest + if (-Not (Test-Path $destDir)) { New-Item -Path $destDir -ItemType Directory | Out-Null } + + if ((Get-Item $item.FullPath).PSIsContainer) { + Copy-Item -Path $item.FullPath -Destination $dest -Recurse + } else { + Copy-Item -Path $item.FullPath -Destination $dest + } + } + + Compress-Archive -Path (Join-Path $tempFolder "*") -DestinationPath $zipFileName + + # Cleanup temp folder + Remove-Item $tempFolder -Recurse -Force + + Write-Output "Created zip: $zipFileName" + + #clean up builds to not get overwhelmed + + if (Test-Path $BuildFolder) { + # Get all zip files in build folder matching pattern + $zips = @(Get-ChildItem -Path $BuildFolder -Filter "LSTV3-*.zip" | + Sort-Object LastWriteTime -Descending) + + $toRemove = $zips | Select-Object -Skip $KeepLast + + foreach ($zip in $toRemove) { + Remove-Item $zip.FullName -Force + Write-Output "Removed old build: $($zip.Name)" + } + } + +} + +function Update-Server { + param ( + [string]$Destination, + [string]$Server, + [string]$Token + ) + $buildFile = Join-Path $AppDir ".buildNumber" + $BuildNumber = 1 + $BuildFolder = Join-Path $AppDir "builds" + + if (Test-Path $BuildFile) { + $content = Get-Content $BuildFile | Select-Object -First 1 + $num = $content.Trim() -as [int] # safe cast + + if ($num) { + $BuildNumber = $num + 1 + } + else { + $BuildNumber = 1 + } + } + + # Get The current Build we have zipped up + $BuildNumber = ([int]$BuildNumber - 1).ToString() + + + # copy the latest build over + Write-Host "Forcing the removal of the mapped drive." + Get-PSDrive -Name "z" -ErrorAction SilentlyContinue | Remove-PSDrive -Force + + try { + + New-PSDrive -Name "z" -PSProvider FileSystem -Root "\\$Server\$Destination" -Credential $credentials + + # Create the update folder if it doesn't exist + if (-not (Test-Path -Path "\\$Server\$Destination")) { + New-Item -ItemType Directory -Path "\\$Server\$Destination" -Force + } + + # Copying files to the server + Write-Host "Copying files to $($Server)" + $zipFile = Join-Path $BuildFolder "LSTV3-$BuildNumber.zip" + Copy-Item -Path $zipFile -Destination "z:\" -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 "Updating the app to LSTV3-$BuildNumber.zip" + # do the stop services, unzip, and restart service and pool + $AppUpdate = { + param ($Server, $Token, $Destination, $BuildFile) + + #convert everything to the server fun + $LocalPath = $Destination -replace '\$', ':' + $BuildFileLoc = "$LocalPath\$BuildFile" + + Write-Host "Updating the app to $($BuildFile)" + + Write-Host "Stopping the services to do the updates, pkgs and db changes." + $app_name = "LSTV3_app$(if ($Token -eq "usiow2") { "_2" })" + + # TODO: add in the iis reset later + + Write-Host "Stopping $($app_name)" + Stop-Service -DisplayName $app_name -Force + Start-Sleep -Seconds 1 + + Write-Host "Unzipping the folder..." + + try { + # Expand the archive + Expand-Archive -Path $BuildFileLoc -DestinationPath $LocalPath -Force + } + catch { + Write-Host "Error: $_" + exit 1 # Exit with a non-zero code if there's an error + } + + # Delete the zip file after extraction + Write-Host "Deleting the zip file..." + Remove-Item -Path $BuildFileLoc -Force + Start-Sleep -Seconds 1 + + try { + # do the install/update + Push-Location $LocalPath + Write-Host "Running install/update in: $LocalPath" + npm install + Start-Sleep -Seconds 3 + Write-Host "Install/update completed." + # do the migrations + Push-Location $LocalPath + Write-Host "Running migrations" + npm run dev:db:migrate + Start-Sleep -Seconds 3 + Write-Host "Migrations Completed." + } + catch { + Write-Host "Migration: $_" + } + finally { + Pop-Location + } + + + Write-Host "Starting $($app_name)" + Start-Service -DisplayName $app_name -ErrorAction Stop + Start-Sleep -Seconds 1 + + } + + Invoke-Command -ComputerName $Server -ScriptBlock $AppUpdate -ArgumentList $Server, $Token, $Destination, "LSTV3-$BuildNumber.zip" -Credential $credentials +} + do { Show-Menu $choice = Read-Host "Select an option" switch ($choice) { "1" { - try { - Push-Location $AppDir - Write-Host "Running: npm run build in $AppDir" - npm run build - - Write-Host "Build completed successfully." - Read-Host -Prompt "Press Enter to continue..." - } - catch { - Write-Host "Build failed: $_" - throw - } - finally { - Pop-Location - } + Build-App + Zip-App + Read-Host -Prompt "Press Enter to continue..." } "2" { $server = Select-Server -List $Servers - if ($null -ne $server) { - $zip = Read-Host "Path to zip (local)" - Deploy-ToServer -Server $server -ZipPath $zip + + if($server -eq "all") { + Write-Host "Updating all servers" + for ($i = 0; $i -lt $Servers.Count; $i++) { + Write-Host "Updating $($Servers[$i].server)" + Update-Server -Server $Servers[$i].server -Destination $Servers[$i].loc -Token $Servers[$i].token + Start-Sleep -Seconds 1 + } + Read-Host -Prompt "Press Enter to continue..." + } + + if ($server -ne "all") { + Write-Host "You selected $($server.server)" + # do the update to the server. + # copy to the server + Update-Server -Server $server.server -Destination $server.loc -Token $server.token + # stop service + # extract zip + # run update check + # run migration + # start service backup + + Read-Host -Prompt "Press Enter to continue..." } } "3" { Write-Host "Restart selected" - psql -h localhost -p 5433 -U adm_cowch -d lst_dev -c "SELECT count(*) FROM public.logs;" } "4" { Write-Host "Exiting..." diff --git a/scripts/services.ps1 b/scripts/services.ps1 index 16d1629..e550e10 100644 --- a/scripts/services.ps1 +++ b/scripts/services.ps1 @@ -6,5 +6,205 @@ param ( [string]$description, [string]$remote, [string]$server, + [string]$username, + [string]$admpass ) +# Example string to run with the parameters in it. +# .\scripts\services.ps1 -serviceName "LSTV3_app" -option "install" -appPath "E:\LST_V3" -description "Logistics Support Tool" -command "run start" + +$nssmPath = $AppPath + "\nssm.exe" +$npmPath = "C:\Program Files\nodejs\npm.cmd" # Path to npm.cmd + +if ($remote -eq "true") { + # Convert the plain-text password to a SecureString + $securePass = ConvertTo-SecureString $admpass -AsPlainText -Force + $credentials = New-Object System.Management.Automation.PSCredential($username, $securePass) + + # 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..." + if ($command.Contains(".exe")) { + + & $nssmPath install $serviceName $command + + $fullAppPath = $appPath + & $nssmPath set $serviceName AppDirectory $fullAppPath + } + else { + & $nssmPath install $serviceName $npmPath $command + & $nssmPath set $serviceName AppDirectory $appPath + } + + + & $nssmPath set $serviceName Description $description + & $nssmPath set $serviceName AppStdout "$($appPath)\logs\service.log" + & $nssmPath set $serviceName AppStderr "$($appPath)\logs\service-error.log" + #& $nssmPath set $serviceName DependOnService "MSSQLSERVER" + # 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 + + if ($command.Contains(".exe")) { + $fullAppPath = "$appPath\app" + & $nssmPath set $serviceName AppDirectory $fullAppPath + } + else { + & $nssmPath set $serviceName AppDirectory $appPath + } + + & $nssmPath set $serviceName Description $description + # & $nssmPath set $serviceName DependOnService "IISADMIN MSSQLSERVER" + # Set recovery options + sc.exe failure $serviceName reset= 0 actions= restart/5000/restart/5000/restart/5000 + Start-Sleep 4 + & $nssmPath start $serviceName + } + } +}