Initial content
This commit is contained in:
@@ -0,0 +1,14 @@
|
||||
"use strict";
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.getEnvironment = exports.Env = void 0;
|
||||
var Env;
|
||||
(function (Env) {
|
||||
Env["Development"] = "development";
|
||||
Env["Production"] = "production";
|
||||
})(Env || (exports.Env = Env = {}));
|
||||
const getEnvironment = () => {
|
||||
const env = process.env.NODE_ENV;
|
||||
return env === undefined || env === Env.Development
|
||||
? Env.Development : Env.Production;
|
||||
};
|
||||
exports.getEnvironment = getEnvironment;
|
||||
@@ -0,0 +1,37 @@
|
||||
"use strict";
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.Env = exports.getEnvironment = exports.getSecret = exports.getConfig = void 0;
|
||||
const fs_1 = require("fs");
|
||||
const environment_1 = require("./environment");
|
||||
Object.defineProperty(exports, "getEnvironment", { enumerable: true, get: function () { return environment_1.getEnvironment; } });
|
||||
Object.defineProperty(exports, "Env", { enumerable: true, get: function () { return environment_1.Env; } });
|
||||
const merge_1 = require("./merge");
|
||||
const dotenv_1 = require("dotenv");
|
||||
const file = process.env.SERVER_CONFIG ?? "server.config.json";
|
||||
const data = JSON.parse((0, fs_1.readFileSync)(file).toString());
|
||||
(0, dotenv_1.config)({
|
||||
path: (0, environment_1.getEnvironment)().toString() + ".env"
|
||||
});
|
||||
try {
|
||||
const envFile = (0, environment_1.getEnvironment)().toString() + "." + file;
|
||||
const envData = JSON.parse((0, fs_1.readFileSync)(envFile).toString());
|
||||
(0, merge_1.merge)(data, envData);
|
||||
}
|
||||
catch {
|
||||
// do nothing - file doesn't exist or isn't readable
|
||||
}
|
||||
const getConfig = (path, defaultVal = undefined) => {
|
||||
const paths = path.split(":");
|
||||
let val = data;
|
||||
paths.forEach(p => val = val[p]);
|
||||
return val ?? defaultVal;
|
||||
};
|
||||
exports.getConfig = getConfig;
|
||||
const getSecret = (name) => {
|
||||
const secret = process.env[name];
|
||||
if (secret === undefined) {
|
||||
throw new Error(`Undefined secret: ${name}`);
|
||||
}
|
||||
return secret;
|
||||
};
|
||||
exports.getSecret = getSecret;
|
||||
@@ -0,0 +1,20 @@
|
||||
"use strict";
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.merge = void 0;
|
||||
const merge = (target, source) => {
|
||||
Object.keys(source).forEach(key => {
|
||||
if (typeof source[key] === "object"
|
||||
&& !Array.isArray(source[key])) {
|
||||
if (Object.hasOwn(target, key)) {
|
||||
(0, exports.merge)(target[key], source[key]);
|
||||
}
|
||||
else {
|
||||
Object.assign(target, source[key]);
|
||||
}
|
||||
}
|
||||
else {
|
||||
target[key] = source[key];
|
||||
}
|
||||
});
|
||||
};
|
||||
exports.merge = merge;
|
||||
@@ -0,0 +1,20 @@
|
||||
"use strict";
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.merge = void 0;
|
||||
const merge = (target, source) => {
|
||||
Object.keys(source).forEach(key => {
|
||||
if (typeof source[key] === "object"
|
||||
&& !Array.isArray(source[key])) {
|
||||
if (Object.hasOwn(target, key)) {
|
||||
(0, exports.merge)(target[key], source[key]);
|
||||
}
|
||||
else {
|
||||
Object.assign(target, source[key]);
|
||||
}
|
||||
}
|
||||
else {
|
||||
target[key] = source[key];
|
||||
}
|
||||
});
|
||||
};
|
||||
exports.merge = merge;
|
||||
@@ -0,0 +1,17 @@
|
||||
"use strict";
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.getCartDetail = void 0;
|
||||
const _1 = require(".");
|
||||
const getCartDetail = async (cart) => {
|
||||
const ids = cart.lines.map(l => l.productId);
|
||||
const db_data = await _1.catalog_repository.getProductDetails(ids);
|
||||
const products = Object.fromEntries(db_data.map(p => [p.id, p]));
|
||||
const lines = cart.lines.map(line => ({
|
||||
product: products[line.productId],
|
||||
quantity: line.quantity,
|
||||
subtotal: products[line.productId].price * line.quantity
|
||||
}));
|
||||
const total = lines.reduce((total, line) => total + line.subtotal, 0);
|
||||
return { lines, total };
|
||||
};
|
||||
exports.getCartDetail = getCartDetail;
|
||||
@@ -0,0 +1,19 @@
|
||||
"use strict";
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.removeLine = exports.addLine = exports.createCart = void 0;
|
||||
const createCart = () => ({ lines: [] });
|
||||
exports.createCart = createCart;
|
||||
const addLine = (cart, productId, quantity) => {
|
||||
const line = cart.lines.find(l => l.productId == productId);
|
||||
if (line !== undefined) {
|
||||
line.quantity += quantity;
|
||||
}
|
||||
else {
|
||||
cart.lines.push({ productId, quantity });
|
||||
}
|
||||
};
|
||||
exports.addLine = addLine;
|
||||
const removeLine = (cart, productId) => {
|
||||
cart.lines = cart.lines.filter(l => l.productId !== productId);
|
||||
};
|
||||
exports.removeLine = removeLine;
|
||||
@@ -0,0 +1,2 @@
|
||||
"use strict";
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
@@ -0,0 +1,2 @@
|
||||
"use strict";
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
@@ -0,0 +1,5 @@
|
||||
"use strict";
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.catalog_repository = void 0;
|
||||
const orm_1 = require("./orm");
|
||||
exports.catalog_repository = new orm_1.CatalogRepoImpl();
|
||||
@@ -0,0 +1,38 @@
|
||||
"use strict";
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.BaseRepo = void 0;
|
||||
const sequelize_1 = require("sequelize");
|
||||
const config_1 = require("../../config");
|
||||
const models_1 = require("./models");
|
||||
const fs_1 = require("fs");
|
||||
const config = (0, config_1.getConfig)("catalog:orm_repo");
|
||||
const logging = config.logging
|
||||
? { logging: console.log, logQueryParameters: true }
|
||||
: { logging: false };
|
||||
class BaseRepo {
|
||||
sequelize;
|
||||
constructor() {
|
||||
this.sequelize = new sequelize_1.Sequelize({ ...config.settings, ...logging });
|
||||
this.initModelsAndDatabase();
|
||||
}
|
||||
async initModelsAndDatabase() {
|
||||
(0, models_1.initializeModels)(this.sequelize);
|
||||
if (config.reset_db) {
|
||||
await this.sequelize.drop();
|
||||
await this.sequelize.sync();
|
||||
await this.addSeedData();
|
||||
}
|
||||
else {
|
||||
await this.sequelize.sync();
|
||||
}
|
||||
}
|
||||
async addSeedData() {
|
||||
const data = JSON.parse((0, fs_1.readFileSync)(config.seed_file).toString());
|
||||
await this.sequelize.transaction(async (transaction) => {
|
||||
await models_1.SupplierModel.bulkCreate(data.suppliers, { transaction });
|
||||
await models_1.CategoryModel.bulkCreate(data.categories, { transaction });
|
||||
await models_1.ProductModel.bulkCreate(data.products, { transaction });
|
||||
});
|
||||
}
|
||||
}
|
||||
exports.BaseRepo = BaseRepo;
|
||||
@@ -0,0 +1,9 @@
|
||||
"use strict";
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.CatalogRepoImpl = void 0;
|
||||
const core_1 = require("./core");
|
||||
const queries_1 = require("./queries");
|
||||
const storage_1 = require("./storage");
|
||||
const RepoWithQueries = (0, queries_1.AddQueries)(core_1.BaseRepo);
|
||||
const CompleteRepo = (0, storage_1.AddStorage)(RepoWithQueries);
|
||||
exports.CatalogRepoImpl = CompleteRepo;
|
||||
+29
@@ -0,0 +1,29 @@
|
||||
"use strict";
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.initializeCatalogModels = void 0;
|
||||
const sequelize_1 = require("sequelize");
|
||||
const catalog_models_1 = require("./catalog_models");
|
||||
const primaryKey = {
|
||||
id: { type: sequelize_1.DataTypes.INTEGER, autoIncrement: true, primaryKey: true }
|
||||
};
|
||||
const initializeCatalogModels = (sequelize) => {
|
||||
catalog_models_1.ProductModel.init({
|
||||
...primaryKey,
|
||||
name: { type: sequelize_1.DataTypes.STRING },
|
||||
description: { type: sequelize_1.DataTypes.STRING },
|
||||
price: { type: sequelize_1.DataTypes.DECIMAL(10, 2) }
|
||||
}, { sequelize });
|
||||
catalog_models_1.CategoryModel.init({
|
||||
...primaryKey,
|
||||
name: { type: sequelize_1.DataTypes.STRING }
|
||||
}, { sequelize });
|
||||
catalog_models_1.SupplierModel.init({
|
||||
...primaryKey,
|
||||
name: { type: sequelize_1.DataTypes.STRING }
|
||||
}, { sequelize });
|
||||
catalog_models_1.ProductModel.belongsTo(catalog_models_1.CategoryModel, { foreignKey: "categoryId", as: "category" });
|
||||
catalog_models_1.ProductModel.belongsTo(catalog_models_1.SupplierModel, { foreignKey: "supplierId", as: "supplier" });
|
||||
catalog_models_1.CategoryModel.hasMany(catalog_models_1.ProductModel, { foreignKey: "categoryId", as: "products" });
|
||||
catalog_models_1.SupplierModel.hasMany(catalog_models_1.ProductModel, { foreignKey: "supplierId", as: "products" });
|
||||
};
|
||||
exports.initializeCatalogModels = initializeCatalogModels;
|
||||
@@ -0,0 +1,13 @@
|
||||
"use strict";
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.SupplierModel = exports.CategoryModel = exports.ProductModel = void 0;
|
||||
const sequelize_1 = require("sequelize");
|
||||
class ProductModel extends sequelize_1.Model {
|
||||
}
|
||||
exports.ProductModel = ProductModel;
|
||||
class CategoryModel extends sequelize_1.Model {
|
||||
}
|
||||
exports.CategoryModel = CategoryModel;
|
||||
class SupplierModel extends sequelize_1.Model {
|
||||
}
|
||||
exports.SupplierModel = SupplierModel;
|
||||
@@ -0,0 +1,12 @@
|
||||
"use strict";
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.initializeModels = exports.SupplierModel = exports.CategoryModel = exports.ProductModel = void 0;
|
||||
const catalog_helpers_1 = require("./catalog_helpers");
|
||||
var catalog_models_1 = require("./catalog_models");
|
||||
Object.defineProperty(exports, "ProductModel", { enumerable: true, get: function () { return catalog_models_1.ProductModel; } });
|
||||
Object.defineProperty(exports, "CategoryModel", { enumerable: true, get: function () { return catalog_models_1.CategoryModel; } });
|
||||
Object.defineProperty(exports, "SupplierModel", { enumerable: true, get: function () { return catalog_models_1.SupplierModel; } });
|
||||
const initializeModels = (sequelize) => {
|
||||
(0, catalog_helpers_1.initializeCatalogModels)(sequelize);
|
||||
};
|
||||
exports.initializeModels = initializeModels;
|
||||
@@ -0,0 +1,49 @@
|
||||
"use strict";
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.AddQueries = void 0;
|
||||
const models_1 = require("./models");
|
||||
const sequelize_1 = require("sequelize");
|
||||
function AddQueries(Base) {
|
||||
return class extends Base {
|
||||
async getProducts(params) {
|
||||
const opts = {};
|
||||
if (params?.page && params.pageSize) {
|
||||
opts.limit = params?.pageSize,
|
||||
opts.offset = (params.page - 1) * params.pageSize;
|
||||
}
|
||||
if (params?.searchTerm) {
|
||||
const searchOp = { [sequelize_1.Op.like]: "%" + params.searchTerm + "%" };
|
||||
opts.where = {
|
||||
[sequelize_1.Op.or]: { name: searchOp, description: searchOp }
|
||||
};
|
||||
}
|
||||
if (params?.category) {
|
||||
opts.where = {
|
||||
...opts.where, categoryId: params.category
|
||||
};
|
||||
}
|
||||
const result = await models_1.ProductModel.findAndCountAll({
|
||||
include: [
|
||||
{ model: models_1.SupplierModel, as: "supplier" },
|
||||
{ model: models_1.CategoryModel, as: "category" }
|
||||
],
|
||||
raw: true, nest: true,
|
||||
...opts
|
||||
});
|
||||
const categories = await this.getCategories();
|
||||
return { products: result.rows, totalCount: result.count, categories };
|
||||
}
|
||||
getCategories() {
|
||||
return models_1.CategoryModel.findAll({ raw: true, nest: true });
|
||||
}
|
||||
getSuppliers() {
|
||||
return models_1.SupplierModel.findAll({ raw: true, nest: true });
|
||||
}
|
||||
getProductDetails(ids) {
|
||||
return models_1.ProductModel.findAll({
|
||||
where: { id: { [sequelize_1.Op.in]: ids } }, raw: true, nest: true,
|
||||
});
|
||||
}
|
||||
};
|
||||
}
|
||||
exports.AddQueries = AddQueries;
|
||||
@@ -0,0 +1,37 @@
|
||||
"use strict";
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.AddStorage = void 0;
|
||||
const models_1 = require("./models");
|
||||
function AddStorage(Base) {
|
||||
return class extends Base {
|
||||
storeProduct(p) {
|
||||
return this.sequelize.transaction(async (transaction) => {
|
||||
if (p.category) {
|
||||
p.category = await this.storeCategory(p.category);
|
||||
}
|
||||
if (p.supplier) {
|
||||
p.supplier = await this.storeSupplier(p.supplier);
|
||||
}
|
||||
const [stored] = await models_1.ProductModel.upsert({
|
||||
id: p.id, name: p.name, description: p.description,
|
||||
price: p.price, categoryId: p.category?.id,
|
||||
supplierId: p.supplier?.id
|
||||
}, { transaction });
|
||||
return stored;
|
||||
});
|
||||
}
|
||||
async storeCategory(c, transaction) {
|
||||
const [stored] = await models_1.CategoryModel.upsert({
|
||||
id: c.id, name: c.name
|
||||
}, { transaction });
|
||||
return stored;
|
||||
}
|
||||
async storeSupplier(s, transaction) {
|
||||
const [stored] = await models_1.SupplierModel.upsert({
|
||||
id: s.id, name: s.name
|
||||
}, { transaction });
|
||||
return stored;
|
||||
}
|
||||
};
|
||||
}
|
||||
exports.AddStorage = AddStorage;
|
||||
@@ -0,0 +1,28 @@
|
||||
"use strict";
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.createErrorHandlers = void 0;
|
||||
const config_1 = require("./config");
|
||||
require("express-async-errors");
|
||||
const template400 = (0, config_1.getConfig)("errors:400");
|
||||
const template500 = (0, config_1.getConfig)("errors:500");
|
||||
const createErrorHandlers = (app) => {
|
||||
app.use((req, resp) => {
|
||||
resp.statusCode = 404;
|
||||
resp.render(template400);
|
||||
});
|
||||
const handler = (error, req, resp, next) => {
|
||||
console.log(error);
|
||||
if (resp.headersSent) {
|
||||
return next(error);
|
||||
}
|
||||
try {
|
||||
resp.statusCode = 500;
|
||||
resp.render(template500, { error });
|
||||
}
|
||||
catch (newErr) {
|
||||
next(error);
|
||||
}
|
||||
};
|
||||
app.use(handler);
|
||||
};
|
||||
exports.createErrorHandlers = createErrorHandlers;
|
||||
@@ -0,0 +1,5 @@
|
||||
"use strict";
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.countCartItems = void 0;
|
||||
const countCartItems = (cart) => cart.lines.reduce((total, line) => total + line.quantity, 0);
|
||||
exports.countCartItems = countCartItems;
|
||||
@@ -0,0 +1,70 @@
|
||||
"use strict";
|
||||
var __importDefault = (this && this.__importDefault) || function (mod) {
|
||||
return (mod && mod.__esModule) ? mod : { "default": mod };
|
||||
};
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.currency = exports.highlight = exports.categoryButtons = exports.pageSizeOptions = exports.pageButtons = exports.escapeUrl = exports.navigationUrl = void 0;
|
||||
const handlebars_1 = __importDefault(require("handlebars"));
|
||||
const querystring_1 = require("querystring");
|
||||
const querystring_2 = require("querystring");
|
||||
const getData = (options) => {
|
||||
return { ...options.data.root, ...options.hash };
|
||||
};
|
||||
const navigationUrl = (options) => {
|
||||
const { page, pageSize, category, searchTerm } = getData(options);
|
||||
return "/?" + (0, querystring_1.stringify)({ page, pageSize, category, searchTerm });
|
||||
};
|
||||
exports.navigationUrl = navigationUrl;
|
||||
const escapeUrl = (url) => (0, querystring_2.escape)(url);
|
||||
exports.escapeUrl = escapeUrl;
|
||||
const pageButtons = (options) => {
|
||||
const { page, pageCount } = getData(options);
|
||||
let output = "";
|
||||
for (let i = 1; i <= pageCount; i++) {
|
||||
output += options.fn({
|
||||
page, pageCount, index: i, selected: i === page
|
||||
});
|
||||
}
|
||||
return output;
|
||||
};
|
||||
exports.pageButtons = pageButtons;
|
||||
const pageSizeOptions = (options) => {
|
||||
const { pageSize } = getData(options);
|
||||
let output = "";
|
||||
[3, 6, 9].forEach(size => {
|
||||
output += options.fn({ size,
|
||||
selected: pageSize === size ? "selected" : "" });
|
||||
});
|
||||
return output;
|
||||
};
|
||||
exports.pageSizeOptions = pageSizeOptions;
|
||||
const categoryButtons = (options) => {
|
||||
const { category, categories } = getData(options);
|
||||
let output = "";
|
||||
for (let i = 0; i < categories.length; i++) {
|
||||
output += options.fn({
|
||||
id: categories[i].id,
|
||||
name: categories[i].name,
|
||||
selected: category === categories[i].id
|
||||
});
|
||||
}
|
||||
return output;
|
||||
};
|
||||
exports.categoryButtons = categoryButtons;
|
||||
const highlight = (value, options) => {
|
||||
const { searchTerm } = getData(options);
|
||||
if (searchTerm && searchTerm !== "") {
|
||||
const regexp = new RegExp(searchTerm, "ig");
|
||||
const mod = value.replaceAll(regexp, "<strong>$&</strong>");
|
||||
return new handlebars_1.default.SafeString(mod);
|
||||
}
|
||||
return value;
|
||||
};
|
||||
exports.highlight = highlight;
|
||||
const formatter = new Intl.NumberFormat("en-us", {
|
||||
style: "currency", currency: "USD"
|
||||
});
|
||||
const currency = (value) => {
|
||||
return formatter.format(value);
|
||||
};
|
||||
exports.currency = currency;
|
||||
@@ -0,0 +1,8 @@
|
||||
"use strict";
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.isDevelopment = void 0;
|
||||
const config_1 = require("../config");
|
||||
const isDevelopment = (value) => {
|
||||
return (0, config_1.getEnvironment)() === config_1.Env.Development;
|
||||
};
|
||||
exports.isDevelopment = isDevelopment;
|
||||
@@ -0,0 +1,42 @@
|
||||
"use strict";
|
||||
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
||||
if (k2 === undefined) k2 = k;
|
||||
var desc = Object.getOwnPropertyDescriptor(m, k);
|
||||
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
||||
desc = { enumerable: true, get: function() { return m[k]; } };
|
||||
}
|
||||
Object.defineProperty(o, k2, desc);
|
||||
}) : (function(o, m, k, k2) {
|
||||
if (k2 === undefined) k2 = k;
|
||||
o[k2] = m[k];
|
||||
}));
|
||||
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
||||
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
||||
}) : function(o, v) {
|
||||
o["default"] = v;
|
||||
});
|
||||
var __importStar = (this && this.__importStar) || function (mod) {
|
||||
if (mod && mod.__esModule) return mod;
|
||||
var result = {};
|
||||
if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
|
||||
__setModuleDefault(result, mod);
|
||||
return result;
|
||||
};
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.createTemplates = void 0;
|
||||
const config_1 = require("../config");
|
||||
const express_handlebars_1 = require("express-handlebars");
|
||||
const env_helpers = __importStar(require("./env"));
|
||||
const catalog_helpers = __importStar(require("./catalog_helpers"));
|
||||
const cart_helpers = __importStar(require("./cart_helpers"));
|
||||
const location = (0, config_1.getConfig)("templates:location");
|
||||
const config = (0, config_1.getConfig)("templates:config");
|
||||
const createTemplates = (app) => {
|
||||
app.set("views", location);
|
||||
app.engine("handlebars", (0, express_handlebars_1.engine)({
|
||||
...config,
|
||||
helpers: { ...env_helpers, ...catalog_helpers, ...cart_helpers }
|
||||
}));
|
||||
app.set("view engine", "handlebars");
|
||||
};
|
||||
exports.createTemplates = createTemplates;
|
||||
@@ -0,0 +1,61 @@
|
||||
"use strict";
|
||||
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
||||
if (k2 === undefined) k2 = k;
|
||||
var desc = Object.getOwnPropertyDescriptor(m, k);
|
||||
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
||||
desc = { enumerable: true, get: function() { return m[k]; } };
|
||||
}
|
||||
Object.defineProperty(o, k2, desc);
|
||||
}) : (function(o, m, k, k2) {
|
||||
if (k2 === undefined) k2 = k;
|
||||
o[k2] = m[k];
|
||||
}));
|
||||
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
||||
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
||||
}) : function(o, v) {
|
||||
o["default"] = v;
|
||||
});
|
||||
var __importStar = (this && this.__importStar) || function (mod) {
|
||||
if (mod && mod.__esModule) return mod;
|
||||
var result = {};
|
||||
if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
|
||||
__setModuleDefault(result, mod);
|
||||
return result;
|
||||
};
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.createCartRoutes = exports.createCartMiddleware = void 0;
|
||||
const querystring_1 = require("querystring");
|
||||
const cart_models_1 = require("../data/cart_models");
|
||||
const cart_helpers = __importStar(require("../data/cart_helpers"));
|
||||
const createCartMiddleware = (app) => {
|
||||
app.use((req, resp, next) => {
|
||||
resp.locals.cart = req.session.cart = req.session.cart ?? (0, cart_models_1.createCart)();
|
||||
next();
|
||||
});
|
||||
};
|
||||
exports.createCartMiddleware = createCartMiddleware;
|
||||
const createCartRoutes = (app) => {
|
||||
app.post("/cart", (req, resp) => {
|
||||
const productId = Number.parseInt(req.body.productId);
|
||||
if (isNaN(productId)) {
|
||||
throw new Error("ID must be an integer");
|
||||
}
|
||||
(0, cart_models_1.addLine)(req.session.cart, productId, 1);
|
||||
resp.redirect(`/cart?returnUrl=${(0, querystring_1.escape)(req.body.returnUrl ?? "/")}`);
|
||||
});
|
||||
app.get("/cart", async (req, resp) => {
|
||||
const cart = req.session.cart;
|
||||
resp.render("cart", {
|
||||
cart: await cart_helpers.getCartDetail(cart),
|
||||
returnUrl: (0, querystring_1.unescape)(req.query.returnUrl?.toString() ?? "/")
|
||||
});
|
||||
});
|
||||
app.post("/cart/remove", (req, resp) => {
|
||||
const id = Number.parseInt(req.body.id);
|
||||
if (!isNaN(id)) {
|
||||
(0, cart_models_1.removeLine)(req.session.cart, id);
|
||||
}
|
||||
resp.redirect(`/cart?returnUrl=${(0, querystring_1.escape)(req.body.returnUrl ?? "/")}`);
|
||||
});
|
||||
};
|
||||
exports.createCartRoutes = createCartRoutes;
|
||||
@@ -0,0 +1,19 @@
|
||||
"use strict";
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.createCatalogRoutes = void 0;
|
||||
const data_1 = require("../data");
|
||||
const createCatalogRoutes = (app) => {
|
||||
app.get("/", async (req, resp) => {
|
||||
const page = Number.parseInt(req.query.page?.toString() ?? "1");
|
||||
const pageSize = Number.parseInt(req.query.pageSize?.toString() ?? "3");
|
||||
const searchTerm = req.query.searchTerm?.toString();
|
||||
const category = Number.parseInt(req.query.category?.toString() ?? "");
|
||||
const res = await data_1.catalog_repository.getProducts({ page, pageSize,
|
||||
searchTerm, category });
|
||||
resp.render("index", { ...res, page, pageSize,
|
||||
pageCount: Math.ceil(res.totalCount / (pageSize ?? 1)),
|
||||
searchTerm, category, show_cart: true
|
||||
});
|
||||
});
|
||||
};
|
||||
exports.createCatalogRoutes = createCatalogRoutes;
|
||||
@@ -0,0 +1,11 @@
|
||||
"use strict";
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.createRoutes = void 0;
|
||||
const catalog_1 = require("./catalog");
|
||||
const cart_1 = require("./cart");
|
||||
const createRoutes = (app) => {
|
||||
(0, cart_1.createCartMiddleware)(app);
|
||||
(0, catalog_1.createCatalogRoutes)(app);
|
||||
(0, cart_1.createCartRoutes)(app);
|
||||
};
|
||||
exports.createRoutes = createRoutes;
|
||||
@@ -0,0 +1,26 @@
|
||||
"use strict";
|
||||
var __importDefault = (this && this.__importDefault) || function (mod) {
|
||||
return (mod && mod.__esModule) ? mod : { "default": mod };
|
||||
};
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
const http_1 = require("http");
|
||||
const express_1 = __importDefault(require("express"));
|
||||
const helmet_1 = __importDefault(require("helmet"));
|
||||
const config_1 = require("./config");
|
||||
const routes_1 = require("./routes");
|
||||
const helpers_1 = require("./helpers");
|
||||
const errors_1 = require("./errors");
|
||||
const sessions_1 = require("./sessions");
|
||||
const port = (0, config_1.getConfig)("http:port", 5000);
|
||||
const expressApp = (0, express_1.default)();
|
||||
expressApp.use((0, helmet_1.default)());
|
||||
expressApp.use(express_1.default.json());
|
||||
expressApp.use(express_1.default.urlencoded({ extended: true }));
|
||||
expressApp.use(express_1.default.static("node_modules/bootstrap/dist"));
|
||||
expressApp.use(express_1.default.static("node_modules/bootstrap-icons"));
|
||||
(0, helpers_1.createTemplates)(expressApp);
|
||||
(0, sessions_1.createSessions)(expressApp);
|
||||
(0, routes_1.createRoutes)(expressApp);
|
||||
(0, errors_1.createErrorHandlers)(expressApp);
|
||||
const server = (0, http_1.createServer)(expressApp);
|
||||
server.listen(port, () => console.log(`HTTP Server listening on port ${port}`));
|
||||
@@ -0,0 +1,36 @@
|
||||
"use strict";
|
||||
var __importDefault = (this && this.__importDefault) || function (mod) {
|
||||
return (mod && mod.__esModule) ? mod : { "default": mod };
|
||||
};
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.createSessions = void 0;
|
||||
const sequelize_1 = require("sequelize");
|
||||
const config_1 = require("./config");
|
||||
const express_session_1 = __importDefault(require("express-session"));
|
||||
const connect_session_sequelize_1 = __importDefault(require("connect-session-sequelize"));
|
||||
const config = (0, config_1.getConfig)("sessions");
|
||||
const secret = (0, config_1.getSecret)("COOKIE_SECRET");
|
||||
const logging = config.orm.logging
|
||||
? { logging: console.log, logQueryParameters: true }
|
||||
: { logging: false };
|
||||
const createSessions = (app) => {
|
||||
const sequelize = new sequelize_1.Sequelize({
|
||||
...config.orm.settings, ...logging
|
||||
});
|
||||
const store = new ((0, connect_session_sequelize_1.default)(express_session_1.default.Store))({
|
||||
db: sequelize
|
||||
});
|
||||
if (config.reset_db === true) {
|
||||
sequelize.drop().then(() => store.sync());
|
||||
}
|
||||
else {
|
||||
store.sync();
|
||||
}
|
||||
app.use((0, express_session_1.default)({
|
||||
secret, store,
|
||||
resave: true, saveUninitialized: false,
|
||||
cookie: { maxAge: config.maxAgeHrs * 60 * 60 * 1000,
|
||||
sameSite: "strict" }
|
||||
}));
|
||||
};
|
||||
exports.createSessions = createSessions;
|
||||
Reference in New Issue
Block a user