mirror of
https://github.com/KevinMidboe/planetposen-backend.git
synced 2025-10-29 16:30:13 +00:00
Logger, utils and typescript interfaces, types and enums
This commit is contained in:
51
src/config/configuration.js
Normal file
51
src/config/configuration.js
Normal file
@@ -0,0 +1,51 @@
|
||||
const path = require("path");
|
||||
const Field = require("./field.js");
|
||||
|
||||
let instance = null;
|
||||
|
||||
class Config {
|
||||
constructor() {
|
||||
this.location = Config.determineLocation();
|
||||
this.fields = require(`${this.location}`);
|
||||
}
|
||||
|
||||
static getInstance() {
|
||||
if (instance == null) {
|
||||
instance = new Config();
|
||||
}
|
||||
return instance;
|
||||
}
|
||||
|
||||
static determineLocation() {
|
||||
if (process.env.NODE_ENV === "production")
|
||||
return path.join(__dirname, "../../config/env/production.json");
|
||||
return path.join(__dirname, "../../config/env/development.json");
|
||||
}
|
||||
|
||||
get(section, option) {
|
||||
if (
|
||||
this.fields[section] === undefined ||
|
||||
this.fields[section][option] === undefined
|
||||
) {
|
||||
throw new Error(`Field "${section} => ${option}" does not exist.`);
|
||||
}
|
||||
|
||||
const field = new Field(this.fields[section][option]);
|
||||
|
||||
if (field.value === "") {
|
||||
const envField =
|
||||
process.env[[section.toUpperCase(), option.toUpperCase()].join("_")];
|
||||
if (envField !== undefined && envField.length !== 0) {
|
||||
return envField;
|
||||
}
|
||||
}
|
||||
|
||||
if (field.value === undefined) {
|
||||
throw new Error(`${section} => ${option} is empty.`);
|
||||
}
|
||||
|
||||
return field.value;
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = Config;
|
||||
15
src/config/environmentVariables.js
Normal file
15
src/config/environmentVariables.js
Normal file
@@ -0,0 +1,15 @@
|
||||
class EnvironmentVariables {
|
||||
constructor(variables) {
|
||||
this.variables = variables || process.env;
|
||||
}
|
||||
|
||||
get(variable) {
|
||||
return this.variables[variable];
|
||||
}
|
||||
|
||||
has(variable) {
|
||||
return this.get(variable) !== undefined;
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = EnvironmentVariables;
|
||||
53
src/config/field.js
Normal file
53
src/config/field.js
Normal file
@@ -0,0 +1,53 @@
|
||||
const Filters = require("./filters.js");
|
||||
const EnvironmentVariables = require("./environmentVariables.js");
|
||||
|
||||
class Field {
|
||||
constructor(rawValue, environmentVariables) {
|
||||
this.rawValue = rawValue;
|
||||
this.filters = new Filters(rawValue);
|
||||
this.valueWithoutFilters = this.filters.removeFiltersFromValue();
|
||||
this.environmentVariables = new EnvironmentVariables(environmentVariables);
|
||||
}
|
||||
|
||||
get value() {
|
||||
if (this.filters.isEmpty()) {
|
||||
return this.valueWithoutFilters;
|
||||
}
|
||||
|
||||
if (this.filters.has("base64") && !this.filters.has("env")) {
|
||||
return Field.base64Decode(this.valueWithoutFilters);
|
||||
}
|
||||
|
||||
if (
|
||||
this.environmentVariables.has(this.valueWithoutFilters) &&
|
||||
this.environmentVariables.get(this.valueWithoutFilters) === ""
|
||||
) {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
if (!this.filters.has("base64") && this.filters.has("env")) {
|
||||
if (this.environmentVariables.has(this.valueWithoutFilters)) {
|
||||
return this.environmentVariables.get(this.valueWithoutFilters);
|
||||
}
|
||||
return undefined;
|
||||
}
|
||||
|
||||
if (this.filters.has("env") && this.filters.has("base64")) {
|
||||
if (this.environmentVariables.has(this.valueWithoutFilters)) {
|
||||
const encodedEnvironmentVariable = this.environmentVariables.get(
|
||||
this.valueWithoutFilters
|
||||
);
|
||||
return Field.base64Decode(encodedEnvironmentVariable);
|
||||
}
|
||||
return undefined;
|
||||
}
|
||||
|
||||
return this.valueWithoutFilters;
|
||||
}
|
||||
|
||||
static base64Decode(string) {
|
||||
return new Buffer(string, "base64").toString("utf-8");
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = Field;
|
||||
34
src/config/filters.js
Normal file
34
src/config/filters.js
Normal file
@@ -0,0 +1,34 @@
|
||||
class Filters {
|
||||
constructor(value) {
|
||||
this.value = value;
|
||||
this.delimiter = "|";
|
||||
}
|
||||
|
||||
get filters() {
|
||||
return this.value.split(this.delimiter).slice(0, -1);
|
||||
}
|
||||
|
||||
isEmpty() {
|
||||
return !this.hasValidType() || this.value.length === 0;
|
||||
}
|
||||
|
||||
has(filter) {
|
||||
return this.filters.includes(filter);
|
||||
}
|
||||
|
||||
hasValidType() {
|
||||
return typeof this.value === "string";
|
||||
}
|
||||
|
||||
removeFiltersFromValue() {
|
||||
if (this.hasValidType() === false) {
|
||||
return this.value;
|
||||
}
|
||||
|
||||
let filtersCombined = this.filters.join(this.delimiter);
|
||||
filtersCombined += this.filters.length >= 1 ? this.delimiter : "";
|
||||
return this.value.replace(filtersCombined, "");
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = Filters;
|
||||
24
src/enums/generic.js
Normal file
24
src/enums/generic.js
Normal file
@@ -0,0 +1,24 @@
|
||||
const GENERIC_STATUS_CODES = {
|
||||
NON_EXISTANT: "NON_EXISTANT",
|
||||
NOT_STARTED: "NOT_STARTED",
|
||||
RESERVED: "RESERVED",
|
||||
RESERVE_FAILED: "RESERVE_FAILED",
|
||||
PARTIALLY_CAPTURED: "PARTIALLY_CAPTURED",
|
||||
CAPTURED: "CAPTURED",
|
||||
INITIATED: "INITIATED",
|
||||
CONFIRMED: "CONFIRMED",
|
||||
COMPLETED: "COMPLETED",
|
||||
CANCELLED: "CANCELLED",
|
||||
CANCELLED_CONFLICTING: "CANCELLED_CONFLICTING",
|
||||
CANCEL_REQUESTED: "CANCEL_REQUESTED",
|
||||
FAILED: "FAILED",
|
||||
REFUNDED: "REFUNDED",
|
||||
REJECTED: "REJECTED",
|
||||
TIMED_OUT_REJECT: "TIMED_OUT_REJECT",
|
||||
REFUNDED_PARTIAL: "REFUNDED_PARTIAL",
|
||||
REFUND_REQUESTED: "REFUND_REQUESTED",
|
||||
};
|
||||
|
||||
module.exports = {
|
||||
GENERIC_STATUS_CODES,
|
||||
};
|
||||
9
src/enums/order.js
Normal file
9
src/enums/order.js
Normal file
@@ -0,0 +1,9 @@
|
||||
const { GENERIC_STATUS_CODES } = require(`./generic`);
|
||||
|
||||
const ORDER_STATUS_CODES = {
|
||||
...GENERIC_STATUS_CODES,
|
||||
};
|
||||
|
||||
module.exports = {
|
||||
ORDER_STATUS_CODES,
|
||||
};
|
||||
9
src/enums/vipps.js
Normal file
9
src/enums/vipps.js
Normal file
@@ -0,0 +1,9 @@
|
||||
const { GENERIC_STATUS_CODES } = require(`./generic`);
|
||||
|
||||
const VIPPS_STATUS_CODES = {
|
||||
...GENERIC_STATUS_CODES,
|
||||
};
|
||||
|
||||
module.exports = {
|
||||
VIPPS_STATUS_CODES,
|
||||
};
|
||||
28
src/errors/index.js
Normal file
28
src/errors/index.js
Normal file
@@ -0,0 +1,28 @@
|
||||
const WAGO_ERROR_STATUS_CODES = {
|
||||
CONFLICTING_ORDER_RESERVATION: {
|
||||
status: "CONFLICTING_ORDER_RESERVATION",
|
||||
message:
|
||||
"An order for this product has been already reserved, before this order that is being processed.",
|
||||
},
|
||||
UNKNOWN_ERROR: {
|
||||
status: "UNKNOWN_ERROR",
|
||||
message: "An unknown error has occured",
|
||||
},
|
||||
NO_CAPTURED_PAYMENTS: {
|
||||
status: "NO_CAPTURED_PAYMENTS",
|
||||
message: "No captured payments has been found for this order.",
|
||||
},
|
||||
};
|
||||
|
||||
class WagoError extends Error {
|
||||
constructor(error = WAGO_ERROR_STATUS_CODES.UNKNOWN_ERROR) {
|
||||
super(error.message);
|
||||
|
||||
this.error = error;
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
WagoError,
|
||||
WAGO_ERROR_STATUS_CODES,
|
||||
};
|
||||
15
src/interfaces/ICart.ts
Normal file
15
src/interfaces/ICart.ts
Normal file
@@ -0,0 +1,15 @@
|
||||
export default interface ICart {
|
||||
client_id: string;
|
||||
cart_id: number;
|
||||
lineitem_id: number;
|
||||
quantity: number;
|
||||
sku_id: number;
|
||||
size: string;
|
||||
price: number;
|
||||
product_no: number;
|
||||
name: string;
|
||||
description: string;
|
||||
subtext: string;
|
||||
image: string;
|
||||
primary_color: string;
|
||||
}
|
||||
9
src/interfaces/ICustomer.ts
Normal file
9
src/interfaces/ICustomer.ts
Normal file
@@ -0,0 +1,9 @@
|
||||
export default interface ICustomer {
|
||||
city: string;
|
||||
customer_no?: string;
|
||||
email: string;
|
||||
first_name: string;
|
||||
last_name: string;
|
||||
street_address: string;
|
||||
zip_code: number;
|
||||
}
|
||||
7
src/interfaces/IDeliveryAddress.ts
Normal file
7
src/interfaces/IDeliveryAddress.ts
Normal file
@@ -0,0 +1,7 @@
|
||||
export default interface IDeliveryAddress {
|
||||
firstName: string;
|
||||
lastName: string;
|
||||
address: string;
|
||||
zipCode: string;
|
||||
city: string;
|
||||
}
|
||||
61
src/interfaces/IOrder.ts
Normal file
61
src/interfaces/IOrder.ts
Normal file
@@ -0,0 +1,61 @@
|
||||
// import type IProduct from './IProduct';
|
||||
// import type BadgeType from './BadgeType';
|
||||
import type ICustomer from "./ICustomer";
|
||||
|
||||
export interface IStripePayment {
|
||||
amount: number;
|
||||
currency: string;
|
||||
}
|
||||
|
||||
export interface IOrderSummary {
|
||||
created: Date;
|
||||
email: string;
|
||||
first_name: string;
|
||||
last_name: string;
|
||||
order_id: string;
|
||||
order_sum: number;
|
||||
status: string;
|
||||
}
|
||||
|
||||
export interface IOrder {
|
||||
customer: ICustomer;
|
||||
lineItems: ILineItem[];
|
||||
orderid: string;
|
||||
shipping: IShipping;
|
||||
status: string;
|
||||
updated?: Date;
|
||||
created?: Date;
|
||||
}
|
||||
|
||||
export interface ILineItem {
|
||||
sku_id: number;
|
||||
image: string;
|
||||
name: string;
|
||||
price: number;
|
||||
quantity: number;
|
||||
size: string;
|
||||
}
|
||||
|
||||
export interface IShipping {
|
||||
company: string;
|
||||
tracking_code: string;
|
||||
tracking_link: string;
|
||||
user_notified: null;
|
||||
}
|
||||
|
||||
export interface IOrdersLineitem {
|
||||
orders_lineitem_id: string;
|
||||
order_id: string;
|
||||
product_no: number;
|
||||
product_sku_no: number;
|
||||
quantity: number;
|
||||
created?: Date;
|
||||
updated?: Date;
|
||||
}
|
||||
|
||||
export interface ITracking {
|
||||
orderId: string;
|
||||
trackingCode: string;
|
||||
trackingCompany: string;
|
||||
trackingLink: string;
|
||||
}
|
||||
25
src/interfaces/IProduct.ts
Normal file
25
src/interfaces/IProduct.ts
Normal file
@@ -0,0 +1,25 @@
|
||||
export interface IProduct {
|
||||
product_no: number;
|
||||
name: string;
|
||||
subtext?: string;
|
||||
description?: string;
|
||||
image?: string;
|
||||
variation_count?: string;
|
||||
sum_stock?: number;
|
||||
updated?: Date;
|
||||
created?: Date;
|
||||
}
|
||||
|
||||
export interface IProductSku {
|
||||
sku_id: number;
|
||||
price: number;
|
||||
size: number;
|
||||
stock: number;
|
||||
default_price: boolean;
|
||||
updated?: Date;
|
||||
created?: Date;
|
||||
}
|
||||
|
||||
export interface IProductWithSkus extends IProduct {
|
||||
variations: IProductSku[] | number;
|
||||
}
|
||||
61
src/logger.ts
Normal file
61
src/logger.ts
Normal file
@@ -0,0 +1,61 @@
|
||||
import winston from "winston";
|
||||
import ecsFormat from "@elastic/ecs-winston-format";
|
||||
import httpContext from "express-http-context";
|
||||
|
||||
const logLevel = "debug";
|
||||
// const logLevel = 'trace';
|
||||
|
||||
const customLevels = {
|
||||
levels: {
|
||||
fatal: 0,
|
||||
error: 1,
|
||||
warning: 2,
|
||||
info: 3,
|
||||
debug: 4,
|
||||
trace: 5,
|
||||
},
|
||||
colors: {
|
||||
trace: "blue",
|
||||
debug: "white",
|
||||
info: "green",
|
||||
warning: "yellow",
|
||||
error: "red",
|
||||
fatal: "red",
|
||||
},
|
||||
};
|
||||
|
||||
const appendPlanetId = winston.format((log) => {
|
||||
log.planetId = httpContext.get("planetId");
|
||||
return log;
|
||||
});
|
||||
|
||||
const appName = winston.format((log) => {
|
||||
log.application = "planetposen-backend";
|
||||
return log;
|
||||
});
|
||||
|
||||
const logger = winston.createLogger({
|
||||
level: logLevel,
|
||||
levels: customLevels.levels,
|
||||
transports: [
|
||||
new winston.transports.File({
|
||||
filename: "./logs/all-logs.log",
|
||||
format: winston.format.combine(appendPlanetId(), appName(), ecsFormat()),
|
||||
}),
|
||||
],
|
||||
});
|
||||
|
||||
winston.addColors(customLevels.colors);
|
||||
|
||||
if (process.env.NODE_ENV !== "production") {
|
||||
logger.add(
|
||||
new winston.transports.Console({
|
||||
format: winston.format.combine(
|
||||
winston.format.colorize(),
|
||||
winston.format.simple()
|
||||
),
|
||||
})
|
||||
);
|
||||
}
|
||||
|
||||
export default logger;
|
||||
11
src/types/global.d.ts
vendored
Normal file
11
src/types/global.d.ts
vendored
Normal file
@@ -0,0 +1,11 @@
|
||||
declare global {
|
||||
interface NodeJS {
|
||||
__base: string;
|
||||
__dirname: string;
|
||||
__enums: string;
|
||||
__middleware: string;
|
||||
__controllers: string;
|
||||
}
|
||||
}
|
||||
|
||||
export {};
|
||||
4
src/utils/formValidation.ts
Normal file
4
src/utils/formValidation.ts
Normal file
@@ -0,0 +1,4 @@
|
||||
export function validEmail(email: string): boolean {
|
||||
const emailRegex = /(?:[a-z0-9!#$%&'*+/=?^_`{|}~-]+(?:\.[a-z0-9!#$%&'*+/=?^_`{|}~-]+)*|"(?:[\x01-\x08\x0b\x0c\x0e-\x1f\x21\x23-\x5b\x5d-\x7f]|\\[\x01-\x09\x0b\x0c\x0e-\x7f])*")@(?:(?:[a-z0-9](?:[a-z0-9-]*[a-z0-9])?\.)+[a-z0-9](?:[a-z0-9-]*[a-z0-9])?|\[(?:(?:(2(5[0-5]|[0-4][0-9])|1[0-9][0-9]|[1-9]?[0-9]))\.){3}(?:(2(5[0-5]|[0-4][0-9])|1[0-9][0-9]|[1-9]?[0-9])|[a-z0-9-]*[a-z0-9]:(?:[\x01-\x08\x0b\x0c\x0e-\x1f\x21-\x5a\x53-\x7f]|\\[\x01-\x09\x0b\x0c\x0e-\x7f])+)\])/;
|
||||
return emailRegex.test(email);
|
||||
}
|
||||
10
src/utils/generateUUID.ts
Normal file
10
src/utils/generateUUID.ts
Normal file
@@ -0,0 +1,10 @@
|
||||
const hex = "0123456789abcdef";
|
||||
|
||||
export default function generateClientId(len = 22) {
|
||||
let output = "";
|
||||
for (let i = 0; i < len; ++i) {
|
||||
output += hex.charAt(Math.floor(Math.random() * hex.length));
|
||||
}
|
||||
|
||||
return output;
|
||||
}
|
||||
Reference in New Issue
Block a user