feat(lstv2 move): moved lstv2 into this app to keep them combined and easier to maintain
This commit is contained in:
74
lstV2/server/globalUtils/apiHits.ts
Normal file
74
lstV2/server/globalUtils/apiHits.ts
Normal file
@@ -0,0 +1,74 @@
|
||||
import type { Context } from "hono";
|
||||
import { z, ZodError } from "zod";
|
||||
import { getConnInfo } from "@hono/node-server/conninfo";
|
||||
import { tryCatch } from "./tryCatch.js";
|
||||
import { db } from "../../database/dbclient.js";
|
||||
import { apiHits } from "../../database/schema/apiHits.js";
|
||||
import { sql } from "drizzle-orm";
|
||||
|
||||
// Define the request body schema
|
||||
const requestSchema = z.object({
|
||||
ip: z.string().optional(),
|
||||
endpoint: z.string(),
|
||||
action: z.string().optional(),
|
||||
lastBody: z.array(z.object({})).or(z.object({})).optional(),
|
||||
stats: z.string().optional(),
|
||||
});
|
||||
|
||||
type ApiHitData = z.infer<typeof requestSchema>;
|
||||
|
||||
export const apiHit = async (
|
||||
c: Context,
|
||||
data: ApiHitData
|
||||
): Promise<{ success: boolean; data?: ApiHitData; errors?: any[] }> => {
|
||||
const info = getConnInfo(c);
|
||||
// console.log(`Your remote address is ${info.remote.address}`);
|
||||
try {
|
||||
// Extract IP from request headers or connection info
|
||||
const forwarded = c.req.header("host");
|
||||
|
||||
//console.log(forwarded);
|
||||
// Validate the data
|
||||
const checkData = {
|
||||
ip: info.remote.address!,
|
||||
endpoint: data?.endpoint,
|
||||
lastBody: data?.lastBody,
|
||||
action: data?.action,
|
||||
//stats: data?.stats,
|
||||
};
|
||||
const validatedData = requestSchema.parse(checkData);
|
||||
|
||||
const { data: apitHitData, error } = await tryCatch(
|
||||
db
|
||||
.insert(apiHits)
|
||||
.values(checkData)
|
||||
.onConflictDoUpdate({
|
||||
target: [apiHits.endpoint, apiHits.ip],
|
||||
set: {
|
||||
stats: sql`${apiHits.stats} + 1`,
|
||||
lastBody: data?.lastBody,
|
||||
action: data?.action,
|
||||
upd_date: sql`NOW()`,
|
||||
},
|
||||
})
|
||||
);
|
||||
|
||||
if (error) {
|
||||
console.log(error);
|
||||
}
|
||||
// Proceed with the validated data
|
||||
return { success: true, data: validatedData };
|
||||
} catch (error) {
|
||||
// Explicitly check if the error is an instance of ZodError
|
||||
if (error instanceof ZodError) {
|
||||
console.log({ success: false, errors: error.errors });
|
||||
return { success: false, errors: error.errors };
|
||||
}
|
||||
|
||||
// Catch other unexpected errors
|
||||
return {
|
||||
success: false,
|
||||
errors: [{ message: "An unknown error occurred" }],
|
||||
};
|
||||
}
|
||||
};
|
||||
15
lstV2/server/globalUtils/apiReturn.ts
Normal file
15
lstV2/server/globalUtils/apiReturn.ts
Normal file
@@ -0,0 +1,15 @@
|
||||
import type {Context} from "hono";
|
||||
import type {ContentfulStatusCode} from "hono/utils/http-status";
|
||||
|
||||
export const apiReturn = async (
|
||||
c: Context,
|
||||
success: boolean,
|
||||
message: string,
|
||||
data: any,
|
||||
code: ContentfulStatusCode
|
||||
): Promise<Response> => {
|
||||
/**
|
||||
* This is just a global return function to reduce constacnt typing the same thing lol
|
||||
*/
|
||||
return c.json({success, message, data}, code);
|
||||
};
|
||||
15
lstV2/server/globalUtils/appInfo.ts
Normal file
15
lstV2/server/globalUtils/appInfo.ts
Normal file
@@ -0,0 +1,15 @@
|
||||
import path from "path";
|
||||
import {createLog} from "../services/logger/logger.js";
|
||||
import fs from "fs";
|
||||
|
||||
export const getAppInfo = async (appLock: string) => {
|
||||
try {
|
||||
const packagePath = path.join(appLock, "package.json");
|
||||
const packageJson = JSON.parse(fs.readFileSync(packagePath, "utf-8"));
|
||||
//const version = packageJson.version;
|
||||
return packageJson;
|
||||
} catch (error) {
|
||||
createLog("error", "lst", "zipUpBuild", `Error in getting the version: ${error}`);
|
||||
return error;
|
||||
}
|
||||
};
|
||||
67
lstV2/server/globalUtils/createSSCC.ts
Normal file
67
lstV2/server/globalUtils/createSSCC.ts
Normal file
@@ -0,0 +1,67 @@
|
||||
import { query } from "../services/sqlServer/prodSqlServer.js";
|
||||
import { plantInfo } from "../services/sqlServer/querys/dataMart/plantInfo.js";
|
||||
import { createLog } from "../services/logger/logger.js";
|
||||
import { getSettings } from "../services/server/controller/settings/getSettings.js";
|
||||
|
||||
export const createSSCC = async (runningNumber: number) => {
|
||||
// get the token
|
||||
|
||||
let serverSettings = (await getSettings()) as any;
|
||||
const plantToken = serverSettings?.filter(
|
||||
(n: any) => n.name === "plantToken"
|
||||
);
|
||||
// const plantToken = await db
|
||||
// .select()
|
||||
// .from(settings)
|
||||
// .where(eq(settings.name, "plantToken"));
|
||||
let global: any = []; // get from plant address in basis enter the entire string here.
|
||||
|
||||
try {
|
||||
const res: any = await query(
|
||||
plantInfo.replaceAll("[token]", plantToken[0].value),
|
||||
"plantInfo"
|
||||
);
|
||||
global = res.data;
|
||||
} catch (error) {
|
||||
createLog(
|
||||
"error",
|
||||
"lst",
|
||||
"globalUtils",
|
||||
`There was an error getting the GLN: Error: ${error}`
|
||||
);
|
||||
}
|
||||
|
||||
// create the sscc without the check diget and make sure we have it all correct
|
||||
|
||||
let step1SSCC =
|
||||
global[0].gln.toString().slice(0, 7).padStart(10, "0") +
|
||||
runningNumber.toString().padStart(9, "0");
|
||||
|
||||
let sum = 0;
|
||||
for (let i = 0; i < step1SSCC.length; i++) {
|
||||
let digit = parseInt(step1SSCC[i], 10);
|
||||
if (i % 2 === 0) {
|
||||
// Even index in 0-based index system means odd position in 1-based index system
|
||||
sum += digit * 3;
|
||||
} else {
|
||||
sum += digit;
|
||||
}
|
||||
}
|
||||
let checkDigit = (10 - (sum % 10)) % 10;
|
||||
|
||||
// make sure the check digit is never 10
|
||||
|
||||
// let checkDigit = 10 - ((oddSum * 3 + evenSum) % 10) === 10 ? 0 : (oddSum * 3 + evenSum) % 10;
|
||||
|
||||
// return the true sscc
|
||||
let sscc = step1SSCC + checkDigit;
|
||||
// console.log(step1SSCC);
|
||||
// console.log(checkDigit);
|
||||
return sscc.padStart(20, "0");
|
||||
};
|
||||
|
||||
// let rn = 518475;
|
||||
|
||||
// console.log(`Creating sscc`);
|
||||
// let sscc = await createSSCC(rn);
|
||||
// console.log(sscc);
|
||||
44
lstV2/server/globalUtils/createUrl.ts
Normal file
44
lstV2/server/globalUtils/createUrl.ts
Normal file
@@ -0,0 +1,44 @@
|
||||
import { eq } from "drizzle-orm";
|
||||
import { db } from "../../database/dbclient.js";
|
||||
|
||||
import { getSettings } from "../services/server/controller/settings/getSettings.js";
|
||||
|
||||
// create the test server stuff
|
||||
const testServers = [
|
||||
{ token: "test1", port: 8940 },
|
||||
{ token: "test2", port: 8941 },
|
||||
{ token: "test3", port: 8942 },
|
||||
];
|
||||
|
||||
export const prodEndpointCreation = async (endpoint: string) => {
|
||||
let url = "";
|
||||
//get the plant token
|
||||
let serverSettings = await getSettings();
|
||||
const plantToken = serverSettings?.filter((n) => n.name === "plantToken");
|
||||
// await db
|
||||
// .select()
|
||||
// .from(settings)
|
||||
// .where(eq(settings.name, "plantToken"));
|
||||
|
||||
// check if we are a test server
|
||||
const testServer = testServers.some(
|
||||
(server) => server.token === plantToken[0]?.value
|
||||
);
|
||||
const server = serverSettings?.filter((n) => n.name === "dbServer");
|
||||
// await db
|
||||
// .select()
|
||||
// .from(settings)
|
||||
// .where(eq(settings.name, "dbServer"));
|
||||
|
||||
if (testServer) {
|
||||
//filter out what testserver we are
|
||||
const test = testServers.filter((t) => t.token === plantToken[0].value);
|
||||
// "https://usmcd1vms036.alpla.net:8942/application/public/v1.0/DemandManagement/ORDERS"
|
||||
// "https://usmcd1vms036.alpla.net:8492/application/public/v1.0/DemandManagement/ORDERS"
|
||||
url = `https://${server[0]?.value}.alpla.net:${test[0]?.port}/application${endpoint}`;
|
||||
return url;
|
||||
} else {
|
||||
url = `https://${plantToken[0]?.value}prod.alpla.net/application${endpoint}`;
|
||||
return url;
|
||||
}
|
||||
};
|
||||
23
lstV2/server/globalUtils/dbCleanUp/labelCleanUp.ts
Normal file
23
lstV2/server/globalUtils/dbCleanUp/labelCleanUp.ts
Normal file
@@ -0,0 +1,23 @@
|
||||
import { lt } from "drizzle-orm";
|
||||
import { db } from "../../../database/dbclient.js";
|
||||
import { prodlabels } from "../../../database/schema/prodLabels.js";
|
||||
import { addDays } from "date-fns";
|
||||
import { createLog } from "../../services/logger/logger.js";
|
||||
|
||||
export const deleteLabels = async () => {
|
||||
/**
|
||||
* Deletes labels older than 90 days from lst... all label data can be found in alpla prod.
|
||||
*/
|
||||
try {
|
||||
await db
|
||||
.delete(prodlabels)
|
||||
.where(lt(prodlabels.upd_date, addDays(new Date(Date.now()), -90)));
|
||||
} catch (error) {
|
||||
createLog(
|
||||
"error",
|
||||
"labeling",
|
||||
"ocp",
|
||||
`Error deleting labels older than 90 days`
|
||||
);
|
||||
}
|
||||
};
|
||||
3
lstV2/server/globalUtils/delay.ts
Normal file
3
lstV2/server/globalUtils/delay.ts
Normal file
@@ -0,0 +1,3 @@
|
||||
export const delay = (ms: number) => {
|
||||
return new Promise((resolve) => setTimeout(resolve, ms));
|
||||
};
|
||||
69
lstV2/server/globalUtils/freightClass.ts
Normal file
69
lstV2/server/globalUtils/freightClass.ts
Normal file
@@ -0,0 +1,69 @@
|
||||
export const freightClass = (
|
||||
weight: number,
|
||||
length: number,
|
||||
width: number,
|
||||
height: number
|
||||
) => {
|
||||
// mm to in conversion
|
||||
const convertMM = 25.4;
|
||||
|
||||
const convertKG = 2.20462;
|
||||
// Inputs
|
||||
const weightPounds = weight * convertKG;
|
||||
const lengthInches = length / convertMM;
|
||||
const widthInches = width / convertMM;
|
||||
const heightInches = height / convertMM;
|
||||
|
||||
// Calculate volume in cubic inches
|
||||
const volumeCubicInches = lengthInches * widthInches * heightInches;
|
||||
|
||||
// Convert cubic inches to cubic feet
|
||||
const volumeCubicFeet = volumeCubicInches / 1728;
|
||||
|
||||
// Calculate density
|
||||
const density = weightPounds / volumeCubicFeet;
|
||||
|
||||
// Determine freight class
|
||||
let freightClass;
|
||||
|
||||
if (density >= 50) {
|
||||
freightClass = 50;
|
||||
} else if (density >= 35) {
|
||||
freightClass = 55;
|
||||
} else if (density >= 30) {
|
||||
freightClass = 60;
|
||||
} else if (density >= 22.5) {
|
||||
freightClass = 65;
|
||||
} else if (density >= 15) {
|
||||
freightClass = 70;
|
||||
} else if (density >= 13.5) {
|
||||
freightClass = 77.5;
|
||||
} else if (density >= 12) {
|
||||
freightClass = 85;
|
||||
} else if (density >= 10.5) {
|
||||
freightClass = 92.5;
|
||||
} else if (density >= 9) {
|
||||
freightClass = 100;
|
||||
} else if (density >= 8) {
|
||||
freightClass = 110;
|
||||
} else if (density >= 7) {
|
||||
freightClass = 125;
|
||||
} else if (density >= 6) {
|
||||
freightClass = 150;
|
||||
} else if (density >= 5) {
|
||||
freightClass = 175;
|
||||
} else if (density >= 4) {
|
||||
freightClass = 200;
|
||||
} else if (density >= 3) {
|
||||
freightClass = 250;
|
||||
} else if (density >= 2) {
|
||||
freightClass = 300;
|
||||
} else if (density >= 1) {
|
||||
freightClass = 400;
|
||||
} else {
|
||||
freightClass = 500;
|
||||
}
|
||||
|
||||
// Output the freight class
|
||||
return freightClass;
|
||||
};
|
||||
12
lstV2/server/globalUtils/greetingEmail.ts
Normal file
12
lstV2/server/globalUtils/greetingEmail.ts
Normal file
@@ -0,0 +1,12 @@
|
||||
import { getHours } from "date-fns";
|
||||
export const greetingStuff = async (date = new Date()) => {
|
||||
const hour = getHours(date);
|
||||
|
||||
if (hour < 12) {
|
||||
return "Good morning";
|
||||
} else if (hour < 18) {
|
||||
return "Good afternoon";
|
||||
} else {
|
||||
return "Good evening";
|
||||
}
|
||||
};
|
||||
65
lstV2/server/globalUtils/pingServer.ts
Normal file
65
lstV2/server/globalUtils/pingServer.ts
Normal file
@@ -0,0 +1,65 @@
|
||||
import dns from "dns";
|
||||
import net from "net";
|
||||
|
||||
// Usage example
|
||||
//const hostnamePort = "example.com:80"; // Replace with your hostname:port
|
||||
//checkHostnamePort(hostnamePort);
|
||||
|
||||
// Function to resolve a hostname to an IP address
|
||||
export function resolveHostname(hostname: string) {
|
||||
return new Promise((resolve, reject) => {
|
||||
dns.lookup(hostname, (err, address) => {
|
||||
if (err) {
|
||||
reject(err);
|
||||
} else {
|
||||
resolve(address);
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
// Function to check if a port is open
|
||||
export function checkPort(ip: string, port: number): Promise<boolean> {
|
||||
return new Promise((resolve, reject) => {
|
||||
const socket = new net.Socket();
|
||||
|
||||
socket.setTimeout(2000); // Set a timeout for the connection attempt
|
||||
|
||||
socket.on("connect", () => {
|
||||
socket.destroy(); // Close the connection
|
||||
resolve(true); // Port is open
|
||||
});
|
||||
|
||||
socket.on("timeout", () => {
|
||||
socket.destroy(); // Close the connection
|
||||
reject(new Error("Connection timed out")); // Port is not reachable
|
||||
});
|
||||
|
||||
socket.on("error", (err: any) => {
|
||||
reject(new Error(`Unknown error: ${err}`)); // Handle non-Error types
|
||||
});
|
||||
|
||||
socket.connect(port, ip);
|
||||
});
|
||||
}
|
||||
|
||||
// Main function to check hostname:port
|
||||
export async function checkHostnamePort(hostnamePort: string): Promise<boolean> {
|
||||
try {
|
||||
// Split the input into hostname and port
|
||||
const [hostname, port] = hostnamePort.split(":");
|
||||
if (!hostname || !port) {
|
||||
return false; // Invalid format
|
||||
}
|
||||
|
||||
// Resolve the hostname to an IP address
|
||||
const ip = (await resolveHostname(hostname)) as string;
|
||||
|
||||
// Check if the port is open
|
||||
const portCheck = await checkPort(ip, parseInt(port, 10));
|
||||
|
||||
return true; // Hostname:port is reachable
|
||||
} catch (err) {
|
||||
return false; // Any error means the hostname:port is not reachable
|
||||
}
|
||||
}
|
||||
77
lstV2/server/globalUtils/rateLimiter.ts
Normal file
77
lstV2/server/globalUtils/rateLimiter.ts
Normal file
@@ -0,0 +1,77 @@
|
||||
import { Hono } from "hono";
|
||||
import { type Context, type Next } from "hono";
|
||||
|
||||
const app = new Hono();
|
||||
|
||||
// --- In-Memory Store for Rate Limits ---
|
||||
// This Map will store when each user/key last accessed a rate-limited endpoint.
|
||||
// Key: string (e.g., 'ip_address' or 'user_id_endpoint')
|
||||
// Value: number (timestamp of last access in milliseconds)
|
||||
const rateLimitStore = new Map<string, number>();
|
||||
|
||||
// --- Configuration ---
|
||||
const FIFTEEN_MINUTES_MS = 5 * 60 * 1000; // 15 minutes in milliseconds
|
||||
|
||||
// --- Rate Limiting Middleware ---
|
||||
export const simpleRateLimit = async (c: Context, next: Next) => {
|
||||
// 1. Define a unique key for the rate limit
|
||||
// For simplicity, we'll use a placeholder for user identification.
|
||||
// In a real app:
|
||||
// - If unauthenticated: Use c.req.header('x-forwarded-for') or c.req.ip (if configured/available)
|
||||
// - If authenticated: Get user ID from c.req.user or similar after authentication middleware
|
||||
const userIdentifier = c.req.header("x-forwarded-for") || "anonymous_user"; // Basic IP-like identifier
|
||||
|
||||
// You can also make the key specific to the route to have different limits per route
|
||||
const routeKey = `${userIdentifier}:${c.req.path}`;
|
||||
|
||||
const now = Date.now();
|
||||
const lastAccessTime = rateLimitStore.get(routeKey);
|
||||
|
||||
if (lastAccessTime) {
|
||||
const timeElapsed = now - lastAccessTime;
|
||||
|
||||
if (timeElapsed < FIFTEEN_MINUTES_MS) {
|
||||
// Limit exceeded
|
||||
const timeRemainingMs = FIFTEEN_MINUTES_MS - timeElapsed;
|
||||
const timeRemainingSeconds = Math.ceil(timeRemainingMs / 1000);
|
||||
|
||||
c.status(429); // HTTP 429: Too Many Requests
|
||||
return c.json({
|
||||
error: "Too Many Requests",
|
||||
message: `Please wait ${timeRemainingSeconds} seconds before trying again.`,
|
||||
retryAfter: timeRemainingSeconds, // Standard header for rate limiting clients
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
// If no previous access, or the 15 minutes have passed, allow the request
|
||||
// and update the last access time.
|
||||
rateLimitStore.set(routeKey, now);
|
||||
|
||||
// Continue to the next middleware or route handler
|
||||
await next();
|
||||
};
|
||||
|
||||
// --- Apply the Middleware to Specific Routes ---
|
||||
|
||||
app.get("/", (c) => {
|
||||
return c.text("Welcome! This is a public endpoint.");
|
||||
});
|
||||
|
||||
// This endpoint will be rate-limited
|
||||
app.get("/privileged", simpleRateLimit, (c) => {
|
||||
return c.text("You successfully accessed the privileged endpoint!");
|
||||
});
|
||||
|
||||
// Another rate-limited endpoint
|
||||
app.post("/submit-data", simpleRateLimit, async (c) => {
|
||||
// In a real app, you'd process form data or JSON here
|
||||
return c.text("Data submitted successfully (rate-limited).");
|
||||
});
|
||||
|
||||
// Example of an endpoint that is NOT rate-limited
|
||||
app.get("/health", (c) => {
|
||||
return c.text("Server is healthy!");
|
||||
});
|
||||
|
||||
export default app;
|
||||
8
lstV2/server/globalUtils/routeDefs/options.ts
Normal file
8
lstV2/server/globalUtils/routeDefs/options.ts
Normal file
@@ -0,0 +1,8 @@
|
||||
export const apiOptions = () => {
|
||||
return {
|
||||
tags: ["rfid"],
|
||||
summary: "Add new reader",
|
||||
method: "post",
|
||||
path: "/addreader",
|
||||
};
|
||||
};
|
||||
45
lstV2/server/globalUtils/routeDefs/responses.ts
Normal file
45
lstV2/server/globalUtils/routeDefs/responses.ts
Normal file
@@ -0,0 +1,45 @@
|
||||
import {z} from "@hono/zod-openapi";
|
||||
|
||||
const responseSchema = z.object({
|
||||
success: z.boolean().openapi({example: true}),
|
||||
message: z.string().optional(),
|
||||
data: z
|
||||
.array(z.object({}).optional())
|
||||
.optional()
|
||||
.openapi({example: [{data: "hi"}]}),
|
||||
});
|
||||
|
||||
export const responses = () => {
|
||||
return {
|
||||
200: {
|
||||
content: {
|
||||
"application/json": {schema: responseSchema},
|
||||
},
|
||||
description: "Response message",
|
||||
},
|
||||
400: {
|
||||
content: {
|
||||
"application/json": {
|
||||
schema: z.object({message: z.string().optional().openapi({example: "Internal Server error"})}),
|
||||
},
|
||||
},
|
||||
description: "Internal Server Error",
|
||||
},
|
||||
401: {
|
||||
content: {
|
||||
"application/json": {
|
||||
schema: z.object({message: z.string().optional().openapi({example: "Unauthenticated"})}),
|
||||
},
|
||||
},
|
||||
description: "Unauthorized",
|
||||
},
|
||||
500: {
|
||||
content: {
|
||||
"application/json": {
|
||||
schema: z.object({message: z.string().optional().openapi({example: "Internal Server error"})}),
|
||||
},
|
||||
},
|
||||
description: "Internal Server Error",
|
||||
},
|
||||
};
|
||||
};
|
||||
49
lstV2/server/globalUtils/routeDefs/returnRes.ts
Normal file
49
lstV2/server/globalUtils/routeDefs/returnRes.ts
Normal file
@@ -0,0 +1,49 @@
|
||||
import { createLog } from "../../services/logger/logger.js";
|
||||
|
||||
export function returnRes<T>(
|
||||
success: true,
|
||||
message: string,
|
||||
service: string,
|
||||
user: string,
|
||||
level: "info" | "error",
|
||||
data: T
|
||||
): { success: true; message: string; data: T };
|
||||
|
||||
export function returnRes<T>(
|
||||
success: false,
|
||||
message: string,
|
||||
service: string,
|
||||
user: string,
|
||||
level: "info" | "error",
|
||||
data?: T
|
||||
): { success: false; message: string; error: T | string };
|
||||
|
||||
export function returnRes<T>(
|
||||
success: boolean,
|
||||
message: string,
|
||||
service: string,
|
||||
user: string,
|
||||
level: "info" | "error",
|
||||
data?: T
|
||||
) {
|
||||
createLog(level, user, service, message);
|
||||
|
||||
if (success) {
|
||||
return { success: true, message, data: data as T };
|
||||
} else {
|
||||
return {
|
||||
success: false,
|
||||
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);
|
||||
// }
|
||||
92
lstV2/server/globalUtils/runProdApi.ts
Normal file
92
lstV2/server/globalUtils/runProdApi.ts
Normal file
@@ -0,0 +1,92 @@
|
||||
import axios from "axios";
|
||||
import { prodEndpointCreation } from "./createUrl.js";
|
||||
import { tryCatch } from "./tryCatch.js";
|
||||
import { createLog } from "../services/logger/logger.js";
|
||||
|
||||
type bodyData = any;
|
||||
|
||||
type Data = {
|
||||
endpoint: string;
|
||||
data: bodyData[];
|
||||
};
|
||||
export const runProdApi = async (data: Data) => {
|
||||
/**
|
||||
* Detachs a silo
|
||||
*/
|
||||
|
||||
let url = await prodEndpointCreation(data.endpoint);
|
||||
|
||||
const { data: d, error } = await tryCatch(
|
||||
axios.post(url, data.data[0], {
|
||||
headers: {
|
||||
"X-API-Key": process.env.TEC_API_KEY || "",
|
||||
"Content-Type": "application/json",
|
||||
},
|
||||
})
|
||||
);
|
||||
|
||||
let e = error as any;
|
||||
if (e) {
|
||||
//console.log(e.response);
|
||||
if (e.status === 401) {
|
||||
createLog(
|
||||
"error",
|
||||
"lst",
|
||||
"logistics",
|
||||
`Not autorized: ${JSON.stringify(e.response?.data)}`
|
||||
);
|
||||
const data = {
|
||||
success: false,
|
||||
message: `Not autorized: ${JSON.stringify(e.response?.data)}`,
|
||||
data: {
|
||||
status: e.response?.status,
|
||||
statusText: e.response?.statusText,
|
||||
data: e.response?.data,
|
||||
},
|
||||
};
|
||||
return data;
|
||||
} else {
|
||||
createLog(
|
||||
"error",
|
||||
"lst",
|
||||
"logistics",
|
||||
`There was an error processing the endpoint: ${JSON.stringify(
|
||||
e.response?.data
|
||||
)}`
|
||||
);
|
||||
return {
|
||||
success: false,
|
||||
message: `There was an error processing the endpoint: ${JSON.stringify(
|
||||
e.response?.data
|
||||
)}`,
|
||||
data: {
|
||||
status: e.response?.status,
|
||||
statusText: e.response?.statusText,
|
||||
data: e.response?.data,
|
||||
},
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
if (d?.status !== 200) {
|
||||
return {
|
||||
success: false,
|
||||
message: "Error processing endpoint",
|
||||
data: {
|
||||
status: d?.status,
|
||||
statusText: d?.statusText,
|
||||
data: d?.data,
|
||||
},
|
||||
};
|
||||
} else {
|
||||
return {
|
||||
success: true,
|
||||
message: "Endpoint was processed",
|
||||
data: {
|
||||
status: d.status,
|
||||
statusText: d.statusText,
|
||||
data: d.data,
|
||||
},
|
||||
};
|
||||
}
|
||||
};
|
||||
11
lstV2/server/globalUtils/singleUseKey.ts
Normal file
11
lstV2/server/globalUtils/singleUseKey.ts
Normal file
@@ -0,0 +1,11 @@
|
||||
import crypto from "crypto";
|
||||
|
||||
export const generateOneTimeKey = async (length = 32) => {
|
||||
const chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
|
||||
let key = "";
|
||||
const bytes = crypto.randomBytes(length);
|
||||
for (let i = 0; i < length; i++) {
|
||||
key += chars[bytes[i] % chars.length];
|
||||
}
|
||||
return key.match(/.{1,4}/g)!.join("-"); // group by 4 chars
|
||||
};
|
||||
13
lstV2/server/globalUtils/timeZoneFix.ts
Normal file
13
lstV2/server/globalUtils/timeZoneFix.ts
Normal file
@@ -0,0 +1,13 @@
|
||||
import { addHours } from "date-fns";
|
||||
|
||||
export const timeZoneFix = () => {
|
||||
/**
|
||||
* Returns iso date based on current timezone.
|
||||
*/
|
||||
const rawDate = new Date(Date.now()).toISOString();
|
||||
const offsetMinutes = new Date().getTimezoneOffset(); // in minutes
|
||||
const offsetHours =
|
||||
-offsetMinutes / 60 >= 0 ? offsetMinutes / 60 : -offsetMinutes / 60;
|
||||
|
||||
return addHours(rawDate, offsetHours).toISOString();
|
||||
};
|
||||
24
lstV2/server/globalUtils/tryCatch.ts
Normal file
24
lstV2/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 };
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user