gg-tools-kit 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (34) hide show
  1. package/README.md +0 -0
  2. package/dist/GGToolsKit.d.ts +8 -0
  3. package/dist/GGToolsKit.js +17 -0
  4. package/dist/containers/InitContainers.d.ts +7 -0
  5. package/dist/containers/InitContainers.js +27 -0
  6. package/dist/containers/ProtectionsContainer.d.ts +21 -0
  7. package/dist/containers/ProtectionsContainer.js +53 -0
  8. package/dist/containers/UtilsContainer.d.ts +32 -0
  9. package/dist/containers/UtilsContainer.js +96 -0
  10. package/dist/projFilesControl/InitProj.d.ts +8 -0
  11. package/dist/projFilesControl/InitProj.js +194 -0
  12. package/dist/projFilesControl/InstallSecondaryLibraries.d.ts +4 -0
  13. package/dist/projFilesControl/InstallSecondaryLibraries.js +26 -0
  14. package/dist/protections/Compression.d.ts +14 -0
  15. package/dist/protections/Compression.js +51 -0
  16. package/dist/protections/HelmetProtection.d.ts +6 -0
  17. package/dist/protections/HelmetProtection.js +38 -0
  18. package/dist/protections/Logger.d.ts +9 -0
  19. package/dist/protections/Logger.js +51 -0
  20. package/dist/protections/XSSProtection.d.ts +9 -0
  21. package/dist/protections/XSSProtection.js +63 -0
  22. package/dist/utils/Array.d.ts +10 -0
  23. package/dist/utils/Array.js +51 -0
  24. package/dist/utils/Audio.d.ts +6 -0
  25. package/dist/utils/Audio.js +77 -0
  26. package/dist/utils/Date.d.ts +4 -0
  27. package/dist/utils/Date.js +22 -0
  28. package/dist/utils/Files.d.ts +15 -0
  29. package/dist/utils/Files.js +120 -0
  30. package/dist/utils/RequestData.d.ts +15 -0
  31. package/dist/utils/RequestData.js +30 -0
  32. package/dist/utils/Vidoe.d.ts +4 -0
  33. package/dist/utils/Vidoe.js +28 -0
  34. package/package.json +41 -0
package/README.md ADDED
File without changes
@@ -0,0 +1,8 @@
1
+ import Init from "./containers/InitContainers";
2
+ import Protections from "./containers/ProtectionsContainer";
3
+ import Utils from "./containers/UtilsContainer";
4
+ export default class GGToolsKit {
5
+ static Init: typeof Init;
6
+ static Protections: typeof Protections;
7
+ static Utils: typeof Utils;
8
+ }
@@ -0,0 +1,17 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ const InitContainers_1 = __importDefault(require("./containers/InitContainers"));
7
+ const ProtectionsContainer_1 = __importDefault(require("./containers/ProtectionsContainer"));
8
+ const UtilsContainer_1 = __importDefault(require("./containers/UtilsContainer"));
9
+ class GGToolsKit {
10
+ }
11
+ // Initialization Container
12
+ GGToolsKit.Init = InitContainers_1.default;
13
+ // Protections Container
14
+ GGToolsKit.Protections = ProtectionsContainer_1.default;
15
+ // Utils Container
16
+ GGToolsKit.Utils = UtilsContainer_1.default;
17
+ exports.default = GGToolsKit;
@@ -0,0 +1,7 @@
1
+ export default class Init {
2
+ static initBackendProject(TypeScript?: boolean, projectPath?: string): void;
3
+ static installPackages(TypeScript?: boolean, projectPath?: string): void;
4
+ static createFullProject(TypeScript?: boolean, projectPath?: string): void;
5
+ static installAudioLibrary(): void;
6
+ static installVideoLibrary(): void;
7
+ }
@@ -0,0 +1,27 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ const InitProj_1 = __importDefault(require("../projFilesControl/InitProj"));
7
+ const InstallSecondaryLibraries_1 = __importDefault(require("../projFilesControl/InstallSecondaryLibraries"));
8
+ class Init {
9
+ // Project Initialization
10
+ static initBackendProject(TypeScript = false, projectPath = process.cwd()) {
11
+ return InitProj_1.default.initBackendProject(TypeScript, projectPath);
12
+ }
13
+ static installPackages(TypeScript = false, projectPath = process.cwd()) {
14
+ return InitProj_1.default.installPackages(TypeScript, projectPath);
15
+ }
16
+ static createFullProject(TypeScript = false, projectPath = process.cwd()) {
17
+ return InitProj_1.default.createFullProject(TypeScript, projectPath);
18
+ }
19
+ // Secondary Libraries Control
20
+ static installAudioLibrary() {
21
+ return InstallSecondaryLibraries_1.default.installAudioLibrary();
22
+ }
23
+ static installVideoLibrary() {
24
+ return InstallSecondaryLibraries_1.default.installVideoLibrary();
25
+ }
26
+ }
27
+ exports.default = Init;
@@ -0,0 +1,21 @@
1
+ import Compression from "../protections/Compression";
2
+ import HelmetProtection from "../protections/HelmetProtection";
3
+ import Logger from "../protections/Logger";
4
+ import XSSProtection from "../protections/XSSProtection";
5
+ export default class Protections {
6
+ compression: Compression;
7
+ helmet: HelmetProtection;
8
+ logger: Logger;
9
+ xss: XSSProtection;
10
+ constructor();
11
+ getAllMiddlewares(): import("express").RequestHandler<import("express-serve-static-core").ParamsDictionary, any, any, import("qs").ParsedQs, Record<string, any>>[];
12
+ configure(config: {
13
+ compression?: any;
14
+ helmet?: any;
15
+ logger?: {
16
+ format?: string;
17
+ filePath?: string;
18
+ };
19
+ xss?: any;
20
+ }): void;
21
+ }
@@ -0,0 +1,53 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ const Compression_1 = __importDefault(require("../protections/Compression"));
7
+ const HelmetProtection_1 = __importDefault(require("../protections/HelmetProtection"));
8
+ const Logger_1 = __importDefault(require("../protections/Logger"));
9
+ const XSSProtection_1 = __importDefault(require("../protections/XSSProtection"));
10
+ class Protections {
11
+ constructor() {
12
+ // Initialize all protection classes
13
+ this.compression = new Compression_1.default();
14
+ this.helmet = new HelmetProtection_1.default();
15
+ this.logger = new Logger_1.default("dev"); // default logger format
16
+ this.xss = new XSSProtection_1.default();
17
+ }
18
+ // Method to get all middlewares
19
+ getAllMiddlewares() {
20
+ return [
21
+ this.compression.init(),
22
+ this.helmet.getMiddleware(),
23
+ this.logger.getMiddleware(),
24
+ (req, res, next) => this.xss.cleanBody(req, res, next), // prevent losing "this"
25
+ ];
26
+ }
27
+ // Method to apply custom configuration
28
+ configure(config) {
29
+ // Compression
30
+ if (config.compression) {
31
+ this.compression.setOptions(config.compression);
32
+ }
33
+ // Helmet
34
+ if (config.helmet) {
35
+ this.helmet.setOptions(config.helmet);
36
+ }
37
+ // Logger
38
+ if (config.logger) {
39
+ const { format, filePath } = config.logger;
40
+ if (filePath) {
41
+ this.logger.setLogFile(filePath);
42
+ }
43
+ if (format) {
44
+ this.logger.setFormat(format);
45
+ }
46
+ }
47
+ // XSS
48
+ if (config.xss) {
49
+ this.xss.setOptions(config.xss);
50
+ }
51
+ }
52
+ }
53
+ exports.default = Protections;
@@ -0,0 +1,32 @@
1
+ import RequestData from "../utils/RequestData";
2
+ import { Request } from "express";
3
+ export default class Utils {
4
+ private static audio;
5
+ private static video;
6
+ private static file;
7
+ private static date;
8
+ static getAudioDuration(filePath: string): Promise<string>;
9
+ static getVideoDuration(filePath: string): Promise<string>;
10
+ static getFileSize(filePath: string, unit?: "B" | "b" | "KB" | "kb" | "MB" | "mb" | "GB" | "gb"): string;
11
+ static getFileExtension(filePath: string): string;
12
+ static isImageFile(filePath: string): boolean;
13
+ static isVideoFile(filePath: string): boolean;
14
+ static isAudioFile(filePath: string): boolean;
15
+ static isDocumentFile(filePath: string): boolean;
16
+ static isArchiveFile(filePath: string): boolean;
17
+ static today(separator?: string): string;
18
+ static nowTime(separator?: string): string;
19
+ static getRequestIp(req: Request): string;
20
+ static getRequestMethod(req: Request): string;
21
+ static getRequestApi(req: Request): string;
22
+ static getRequestUserAgent(req: Request): string;
23
+ static getReqInfos(req: Request): ReturnType<typeof RequestData.getReqInfos>;
24
+ static shuffleArray<T>(array: T[]): T[];
25
+ static removeDuplicatesFromArray<T>(array: T[]): T[];
26
+ static getRandomElement<T>(array: T[]): T | undefined;
27
+ static flattenArray<T>(array: T[][]): T[];
28
+ static maxFromArray(array: number[]): number | undefined;
29
+ static minFromArray(array: number[]): number | undefined;
30
+ static sumArray(array: number[]): number;
31
+ static averageArray(array: number[]): number | undefined;
32
+ }
@@ -0,0 +1,96 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ const Audio_1 = __importDefault(require("../utils/Audio"));
7
+ const Vidoe_1 = __importDefault(require("../utils/Vidoe"));
8
+ const Files_1 = __importDefault(require("../utils/Files"));
9
+ const Date_1 = __importDefault(require("../utils/Date"));
10
+ const RequestData_1 = __importDefault(require("../utils/RequestData"));
11
+ const Array_1 = __importDefault(require("../utils/Array"));
12
+ class Utils {
13
+ // Audio Utils
14
+ static getAudioDuration(filePath) {
15
+ return this.audio.getAudioDuration(filePath);
16
+ }
17
+ // Video Utils
18
+ static getVideoDuration(filePath) {
19
+ return this.video.getVideoDuration(filePath);
20
+ }
21
+ // File Utils
22
+ static getFileSize(filePath, unit = "KB") {
23
+ return this.file.getFileSize(filePath, unit);
24
+ }
25
+ static getFileExtension(filePath) {
26
+ return this.file.getFileExtension(filePath);
27
+ }
28
+ static isImageFile(filePath) {
29
+ return this.file.isImageFile(filePath);
30
+ }
31
+ static isVideoFile(filePath) {
32
+ return this.file.isVideoFile(filePath);
33
+ }
34
+ static isAudioFile(filePath) {
35
+ return this.file.isAudioFile(filePath);
36
+ }
37
+ static isDocumentFile(filePath) {
38
+ return this.file.isDocumentFile(filePath);
39
+ }
40
+ static isArchiveFile(filePath) {
41
+ return this.file.isArchiveFile(filePath);
42
+ }
43
+ // Date Utils
44
+ static today(separator = "/") {
45
+ return this.date.today(separator);
46
+ }
47
+ static nowTime(separator = ":") {
48
+ return this.date.nowTime(separator);
49
+ }
50
+ // RequestData Utils
51
+ static getRequestIp(req) {
52
+ return RequestData_1.default.getRequestIp(req);
53
+ }
54
+ static getRequestMethod(req) {
55
+ return RequestData_1.default.getRequestMethod(req);
56
+ }
57
+ static getRequestApi(req) {
58
+ return RequestData_1.default.getRequestApi(req);
59
+ }
60
+ static getRequestUserAgent(req) {
61
+ return RequestData_1.default.getRequestUserAgent(req);
62
+ }
63
+ static getReqInfos(req) {
64
+ return RequestData_1.default.getReqInfos(req);
65
+ }
66
+ // Array Utils
67
+ static shuffleArray(array) {
68
+ return Array_1.default.shuffle(array);
69
+ }
70
+ static removeDuplicatesFromArray(array) {
71
+ return Array_1.default.removeDuplicates(array);
72
+ }
73
+ static getRandomElement(array) {
74
+ return Array_1.default.getRandomElement(array);
75
+ }
76
+ static flattenArray(array) {
77
+ return Array_1.default.flatten(array);
78
+ }
79
+ static maxFromArray(array) {
80
+ return Array_1.default.max(array);
81
+ }
82
+ static minFromArray(array) {
83
+ return Array_1.default.min(array);
84
+ }
85
+ static sumArray(array) {
86
+ return Array_1.default.sum(array);
87
+ }
88
+ static averageArray(array) {
89
+ return Array_1.default.average(array);
90
+ }
91
+ }
92
+ Utils.audio = Audio_1.default;
93
+ Utils.video = Vidoe_1.default;
94
+ Utils.file = Files_1.default;
95
+ Utils.date = Date_1.default;
96
+ exports.default = Utils;
@@ -0,0 +1,8 @@
1
+ export default class InitProj {
2
+ static initBackendProject(TypeScript?: boolean, projectPath?: string): void;
3
+ private static createIndexFiles;
4
+ static installPackages(TypeScript?: boolean, projectPath?: string): void;
5
+ private static createTsConfig;
6
+ private static updatePackageJson;
7
+ static createFullProject(TypeScript?: boolean, projectPath?: string): void;
8
+ }
@@ -0,0 +1,194 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ const fs_1 = __importDefault(require("fs"));
7
+ const path_1 = __importDefault(require("path"));
8
+ const child_process_1 = require("child_process");
9
+ class InitProj {
10
+ // Initialize a backend project structure
11
+ static initBackendProject(TypeScript = false, projectPath = process.cwd()) {
12
+ const language = TypeScript
13
+ ? "typescript"
14
+ : "javascript";
15
+ try {
16
+ // Main src directory
17
+ const srcPath = path_1.default.join(projectPath, "src");
18
+ // Backend folders structure
19
+ const folders = [
20
+ "src",
21
+ "src/controllers",
22
+ "src/models",
23
+ "src/routes",
24
+ "src/middlewares",
25
+ "src/utils",
26
+ ];
27
+ // Create all folders
28
+ folders.forEach((folder) => {
29
+ const folderPath = path_1.default.join(projectPath, folder);
30
+ if (!fs_1.default.existsSync(folderPath)) {
31
+ fs_1.default.mkdirSync(folderPath, { recursive: true });
32
+ console.log(`✓ Created: ${folder}`);
33
+ }
34
+ else {
35
+ console.log(`🩸 Already exists: ${folder}`);
36
+ }
37
+ });
38
+ // Create index files for each folder
39
+ this.createIndexFiles(projectPath, language);
40
+ console.log(`\n✅ Backend project (${language.toUpperCase()}) created successfully!`);
41
+ }
42
+ catch (error) {
43
+ throw new Error(`Failed to initialize project: ${error.message}`);
44
+ }
45
+ }
46
+ // Create index files in main folders
47
+ static createIndexFiles(projectPath, language) {
48
+ const fileExtension = language === "typescript" ? "ts" : "js";
49
+ // TypeScript version
50
+ const tsContent = `import express from "express";
51
+
52
+ const app = express();
53
+ app.use(express.json());
54
+
55
+ app.get("/", (req, res) => {
56
+ res.json({ message: "Hello from Express + TypeScript!" });
57
+ });
58
+
59
+ app.listen(3000, () => console.log("Server running on port 3000"));
60
+ `;
61
+ // JavaScript version
62
+ const jsContent = `const express = require("express");
63
+
64
+ const app = express();
65
+ app.use(express.json());
66
+
67
+ app.get("/", (req, res) => {
68
+ res.json({ message: "Hello from Express + JavaScript!" });
69
+ });
70
+
71
+ app.listen(3000, () => console.log("Server running on port 3000"));
72
+ `;
73
+ const content = language === "typescript" ? tsContent : jsContent;
74
+ fs_1.default.writeFileSync(path_1.default.join(projectPath, "src", `index.${fileExtension}`), content);
75
+ }
76
+ // Install essential packages
77
+ static installPackages(TypeScript = false, projectPath = process.cwd()) {
78
+ try {
79
+ console.log("\n📦 Installing packages...\n");
80
+ // Core packages for both languages
81
+ const corePackages = [
82
+ "express",
83
+ "compression@1.7.4",
84
+ "helmet",
85
+ "morgan",
86
+ "xss",
87
+ "dotenv",
88
+ "cors",
89
+ ];
90
+ // TypeScript specific packages
91
+ const tsDevPackages = [
92
+ "@types/express",
93
+ "@types/compression",
94
+ "@types/morgan",
95
+ "@types/cors",
96
+ "@types/node",
97
+ "typescript",
98
+ "ts-node",
99
+ "ts-node-dev",
100
+ ];
101
+ // Install core packages
102
+ console.log("Installing core packages...");
103
+ (0, child_process_1.execSync)(`npm install ${corePackages.join(" ")}`, {
104
+ cwd: projectPath,
105
+ stdio: "inherit",
106
+ });
107
+ // Install TypeScript packages if needed
108
+ if (TypeScript) {
109
+ console.log("\nInstalling TypeScript packages...");
110
+ (0, child_process_1.execSync)(`npm install --save-dev ${tsDevPackages.join(" ")}`, {
111
+ cwd: projectPath,
112
+ stdio: "inherit",
113
+ });
114
+ // Create tsconfig.json
115
+ this.createTsConfig(projectPath);
116
+ }
117
+ // Update package.json
118
+ this.updatePackageJson(TypeScript, projectPath);
119
+ console.log("\n✅ All packages installed successfully!");
120
+ }
121
+ catch (error) {
122
+ throw new Error(`Failed to install packages: ${error.message}`);
123
+ }
124
+ }
125
+ // Create tsconfig.json for TypeScript projects
126
+ static createTsConfig(projectPath) {
127
+ const tsConfig = {
128
+ compilerOptions: {
129
+ target: "ES2020",
130
+ module: "commonjs",
131
+ lib: ["ES2020"],
132
+ outDir: "./dist",
133
+ rootDir: "./src",
134
+ strict: true,
135
+ esModuleInterop: true,
136
+ skipLibCheck: true,
137
+ forceConsistentCasingInFileNames: true,
138
+ resolveJsonModule: true,
139
+ moduleResolution: "node",
140
+ },
141
+ include: ["src/**/*"],
142
+ exclude: ["node_modules", "dist"],
143
+ };
144
+ fs_1.default.writeFileSync(path_1.default.join(projectPath, "tsconfig.json"), JSON.stringify(tsConfig, null, 2));
145
+ console.log("✓ Created tsconfig.json");
146
+ }
147
+ // Update package.json based on project type
148
+ static updatePackageJson(TypeScript, projectPath) {
149
+ const packageJsonPath = path_1.default.join(projectPath, "package.json");
150
+ if (!fs_1.default.existsSync(packageJsonPath)) {
151
+ console.log("⚠ package.json not found, skipping update");
152
+ return;
153
+ }
154
+ try {
155
+ const packageJson = JSON.parse(fs_1.default.readFileSync(packageJsonPath, "utf-8"));
156
+ if (TypeScript) {
157
+ // TypeScript project - remove type field or set to commonjs
158
+ delete packageJson.type;
159
+ // Add TypeScript scripts
160
+ packageJson.scripts = {
161
+ ...packageJson.scripts,
162
+ dev: "ts-node-dev --respawn --transpile-only src/index.ts",
163
+ build: "tsc",
164
+ start: "node dist/index.js",
165
+ };
166
+ }
167
+ else {
168
+ // JavaScript project - set type to module (ES6)
169
+ packageJson.type = "module";
170
+ // Add JavaScript scripts
171
+ packageJson.scripts = {
172
+ ...packageJson.scripts,
173
+ dev: "node src/index.js",
174
+ start: "node src/index.js",
175
+ };
176
+ }
177
+ fs_1.default.writeFileSync(packageJsonPath, JSON.stringify(packageJson, null, 2));
178
+ console.log(`✓ Updated package.json (type: ${TypeScript ? "TypeScript (no type field)" : "module"})`);
179
+ }
180
+ catch (error) {
181
+ console.error("❌ Failed to update package.json:", error.message);
182
+ }
183
+ }
184
+ // Create complete project (structure + packages)
185
+ static createFullProject(TypeScript = false, projectPath = process.cwd()) {
186
+ console.log("🚀 Creating full backend project...\n");
187
+ // Create structure
188
+ this.initBackendProject(TypeScript, projectPath);
189
+ // Install packages
190
+ this.installPackages(TypeScript, projectPath);
191
+ console.log("\n🎉 Project setup completed!");
192
+ }
193
+ }
194
+ exports.default = InitProj;
@@ -0,0 +1,4 @@
1
+ export default class ControlSecondaryLibraries {
2
+ static installAudioLibrary(): void;
3
+ static installVideoLibrary(): void;
4
+ }
@@ -0,0 +1,26 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ const child_process_1 = require("child_process");
4
+ class ControlSecondaryLibraries {
5
+ // Install audio library using npm
6
+ static installAudioLibrary() {
7
+ try {
8
+ (0, child_process_1.execSync)("npm install music-metadata", { stdio: "inherit" });
9
+ console.log("✓ Audio library installed successfully.");
10
+ }
11
+ catch (error) {
12
+ throw new Error(`Failed to install audio library: ${error.message}`);
13
+ }
14
+ }
15
+ // Install video library using npm
16
+ static installVideoLibrary() {
17
+ try {
18
+ (0, child_process_1.execSync)("npm install get-video-duration", { stdio: "inherit" });
19
+ console.log("✓ Video library installed successfully.");
20
+ }
21
+ catch (error) {
22
+ throw new Error(`Failed to install video library: ${error.message}`);
23
+ }
24
+ }
25
+ }
26
+ exports.default = ControlSecondaryLibraries;
@@ -0,0 +1,14 @@
1
+ interface InputCompressionOptions {
2
+ threshold?: number;
3
+ level?: number;
4
+ memLevel?: number;
5
+ chunkSize?: number;
6
+ [key: string]: any;
7
+ }
8
+ export default class Compression {
9
+ private options;
10
+ constructor(options?: InputCompressionOptions);
11
+ init(): import("express").RequestHandler<import("express-serve-static-core").ParamsDictionary, any, any, import("qs").ParsedQs, Record<string, any>>;
12
+ setOptions(options: InputCompressionOptions): void;
13
+ }
14
+ export {};
@@ -0,0 +1,51 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ const compression_1 = __importDefault(require("compression"));
7
+ class Compression {
8
+ constructor(options = {}) {
9
+ // Extract zlib-specific options
10
+ const { level, memLevel, chunkSize, ...restOptions } = options;
11
+ // Default compression options and user overrides
12
+ this.options = {
13
+ // Minimum response size in bytes to compress
14
+ threshold: 1024, // 1KB
15
+ zlib: {
16
+ // Compression level (0-9)
17
+ level: level ?? 6, // Default is 6
18
+ // Memory level (1-9)
19
+ memLevel: memLevel ?? 8, // Default is 8
20
+ // Size of the buffer for compression
21
+ chunkSize: chunkSize ?? 16384, // 16KB
22
+ },
23
+ // If user provides options, they will override defaults
24
+ ...restOptions,
25
+ };
26
+ }
27
+ // Middleware to apply compression
28
+ init() {
29
+ return (0, compression_1.default)(this.options);
30
+ }
31
+ // Method to update compression options
32
+ setOptions(options) {
33
+ // Extract zlib-specific options
34
+ const { level, memLevel, chunkSize, ...restOptions } = options;
35
+ // Build updated zlib options
36
+ const zlibOptions = { ...this.options.zlib };
37
+ if (level !== undefined)
38
+ zlibOptions.level = level;
39
+ if (memLevel !== undefined)
40
+ zlibOptions.memLevel = memLevel;
41
+ if (chunkSize !== undefined)
42
+ zlibOptions.chunkSize = chunkSize;
43
+ // Merge new options with existing ones
44
+ this.options = {
45
+ ...this.options,
46
+ ...restOptions,
47
+ zlib: zlibOptions,
48
+ };
49
+ }
50
+ }
51
+ exports.default = Compression;
@@ -0,0 +1,6 @@
1
+ export default class HelmetProtection {
2
+ private options;
3
+ constructor(options?: object);
4
+ setOptions(options: object): void;
5
+ getMiddleware(): (req: import("node:http").IncomingMessage, res: import("node:http").ServerResponse, next: (err?: unknown) => void) => void;
6
+ }
@@ -0,0 +1,38 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ const helmet_1 = __importDefault(require("helmet"));
7
+ class HelmetProtection {
8
+ constructor(options = {}) {
9
+ // Default Helmet options
10
+ this.options = {
11
+ frameguard: { action: "sameorigin" },
12
+ hsts: { maxAge: 31536000, includeSubDomains: true, preload: true },
13
+ referrerPolicy: { policy: "no-referrer" },
14
+ noSniff: true,
15
+ ieNoOpen: true,
16
+ hidePoweredBy: true,
17
+ crossOriginResourcePolicy: { policy: "cross-origin" },
18
+ crossOriginOpenerPolicy: { policy: "same-origin" },
19
+ contentSecurityPolicy: {
20
+ directives: {
21
+ "default-src": ["'self'"],
22
+ "img-src": ["'self'", "data:", process.env.FRONTEND_URL],
23
+ "media-src": ["'self'", "data:", process.env.FRONTEND_URL],
24
+ },
25
+ },
26
+ ...options, // If user provides options, they will override defaults
27
+ };
28
+ }
29
+ // Method to update Helmet options
30
+ setOptions(options) {
31
+ this.options = { ...this.options, ...options }; // Merge new options with existing ones
32
+ }
33
+ // Middleware to apply Helmet protection
34
+ getMiddleware() {
35
+ return (0, helmet_1.default)(this.options);
36
+ }
37
+ }
38
+ exports.default = HelmetProtection;
@@ -0,0 +1,9 @@
1
+ export default class Logger {
2
+ private format;
3
+ private stream;
4
+ constructor(format: string);
5
+ constructor(format: string, filePath: string);
6
+ getMiddleware(): (req: import("node:http").IncomingMessage, res: import("node:http").ServerResponse<import("node:http").IncomingMessage>, callback: (err?: Error) => void) => void;
7
+ setFormat(format: string): void;
8
+ setLogFile(filePath: string): void;
9
+ }
@@ -0,0 +1,51 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ const morgan_1 = __importDefault(require("morgan"));
7
+ const fs_1 = __importDefault(require("fs"));
8
+ const path_1 = __importDefault(require("path"));
9
+ class Logger {
10
+ constructor(format, filePath) {
11
+ this.format = format;
12
+ if (filePath) {
13
+ // convert path to full path
14
+ const fullPath = path_1.default.resolve(filePath);
15
+ // create a write stream (in append mode)
16
+ const accessLogStream = fs_1.default.createWriteStream(fullPath, { flags: "a" });
17
+ this.stream = {
18
+ write: (message) => {
19
+ accessLogStream.write(message);
20
+ },
21
+ };
22
+ }
23
+ else {
24
+ // Default to console
25
+ this.stream = {
26
+ write: (message) => {
27
+ process.stdout.write(message);
28
+ },
29
+ };
30
+ }
31
+ }
32
+ // Middleware to log requests
33
+ getMiddleware() {
34
+ return (0, morgan_1.default)(this.format, { stream: this.stream });
35
+ }
36
+ // Method to update log format
37
+ setFormat(format) {
38
+ this.format = format;
39
+ }
40
+ // Method to update log file path
41
+ setLogFile(filePath) {
42
+ const fullPath = path_1.default.resolve(filePath);
43
+ const accessLogStream = fs_1.default.createWriteStream(fullPath, { flags: "a" });
44
+ this.stream = {
45
+ write: (message) => {
46
+ accessLogStream.write(message);
47
+ },
48
+ };
49
+ }
50
+ }
51
+ exports.default = Logger;
@@ -0,0 +1,9 @@
1
+ import { IFilterXSSOptions } from "xss";
2
+ import { Request, Response, NextFunction } from "express";
3
+ export default class XSSProtection {
4
+ private filter;
5
+ constructor(options?: IFilterXSSOptions);
6
+ cleanBody: (req: Request, res: Response, next: NextFunction) => void;
7
+ cleanText(text: string): string;
8
+ setOptions(options?: IFilterXSSOptions): void;
9
+ }
@@ -0,0 +1,63 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || (function () {
19
+ var ownKeys = function(o) {
20
+ ownKeys = Object.getOwnPropertyNames || function (o) {
21
+ var ar = [];
22
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
23
+ return ar;
24
+ };
25
+ return ownKeys(o);
26
+ };
27
+ return function (mod) {
28
+ if (mod && mod.__esModule) return mod;
29
+ var result = {};
30
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
31
+ __setModuleDefault(result, mod);
32
+ return result;
33
+ };
34
+ })();
35
+ Object.defineProperty(exports, "__esModule", { value: true });
36
+ const xss_1 = __importStar(require("xss"));
37
+ class XSSProtection {
38
+ constructor(options = {}) {
39
+ // Middleware to clean request body
40
+ this.cleanBody = (req, res, next) => {
41
+ if (req.body) {
42
+ for (const key in req.body) {
43
+ // Only clean string fields
44
+ if (typeof req.body[key] === "string") {
45
+ req.body[key] = (0, xss_1.default)(req.body[key]);
46
+ }
47
+ }
48
+ }
49
+ next();
50
+ };
51
+ // Default XSS filter options can be set here
52
+ this.filter = new xss_1.FilterXSS(options);
53
+ }
54
+ // Method to clean arbitrary text
55
+ cleanText(text) {
56
+ return this.filter.process(text);
57
+ }
58
+ // Method to update XSS filter options
59
+ setOptions(options = {}) {
60
+ this.filter = new xss_1.FilterXSS(options);
61
+ }
62
+ }
63
+ exports.default = XSSProtection;
@@ -0,0 +1,10 @@
1
+ export default class ArrayUtils {
2
+ static shuffle<T>(array: T[]): T[];
3
+ static removeDuplicates<T>(array: T[]): T[];
4
+ static getRandomElement<T>(array: T[]): T | undefined;
5
+ static flatten<T>(array: T[][]): T[];
6
+ static max(array: number[]): number | undefined;
7
+ static min(array: number[]): number | undefined;
8
+ static sum(array: number[]): number;
9
+ static average(array: number[]): number | undefined;
10
+ }
@@ -0,0 +1,51 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ class ArrayUtils {
4
+ // Randomly rearranging the array elements
5
+ static shuffle(array) {
6
+ for (let i = array.length - 1; i >= 0; i--) {
7
+ const j = Math.floor(Math.random() * (i + 1));
8
+ [array[i], array[j]] = [array[j], array[i]];
9
+ }
10
+ return array;
11
+ }
12
+ // Remove duplicate elements from the array
13
+ static removeDuplicates(array) {
14
+ return [...new Set(array)];
15
+ }
16
+ // Get a random element from the array
17
+ static getRandomElement(array) {
18
+ if (array.length === 0)
19
+ return undefined;
20
+ const index = Math.floor(Math.random() * array.length);
21
+ return array[index];
22
+ }
23
+ // Flatten a nested array
24
+ static flatten(array) {
25
+ return array.reduce((acc, val) => acc.concat(val), []);
26
+ }
27
+ // Get the maximum value in a numeric array
28
+ static max(array) {
29
+ if (array.length === 0)
30
+ return undefined;
31
+ return Math.max(...array);
32
+ }
33
+ // Get the minimum value in a numeric array
34
+ static min(array) {
35
+ if (array.length === 0)
36
+ return undefined;
37
+ return Math.min(...array);
38
+ }
39
+ // Calculate the sum of a numeric array
40
+ static sum(array) {
41
+ return array.reduce((acc, val) => acc + val, 0);
42
+ }
43
+ // Calculate the average of a numeric array
44
+ static average(array) {
45
+ if (array.length === 0)
46
+ return undefined;
47
+ const sum = this.sum(array);
48
+ return sum / array.length;
49
+ }
50
+ }
51
+ exports.default = ArrayUtils;
@@ -0,0 +1,6 @@
1
+ export default class AudioUtils {
2
+ private static calculateAudioDuration;
3
+ private static formatDuration;
4
+ private static verifyFileType;
5
+ static getAudioDuration(filePath: string): Promise<string>;
6
+ }
@@ -0,0 +1,77 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || (function () {
19
+ var ownKeys = function(o) {
20
+ ownKeys = Object.getOwnPropertyNames || function (o) {
21
+ var ar = [];
22
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
23
+ return ar;
24
+ };
25
+ return ownKeys(o);
26
+ };
27
+ return function (mod) {
28
+ if (mod && mod.__esModule) return mod;
29
+ var result = {};
30
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
31
+ __setModuleDefault(result, mod);
32
+ return result;
33
+ };
34
+ })();
35
+ Object.defineProperty(exports, "__esModule", { value: true });
36
+ const musicMetadata = __importStar(require("music-metadata"));
37
+ class AudioUtils {
38
+ // Calculate the duration of the sound in seconds
39
+ static async calculateAudioDuration(filePath) {
40
+ try {
41
+ const metadata = await musicMetadata.parseFile(filePath);
42
+ return metadata.format.duration ?? 0;
43
+ }
44
+ catch (err) {
45
+ console.error("Error reading audio metadata:", err.message);
46
+ return 0;
47
+ }
48
+ }
49
+ // Length format as hh:mm:ss
50
+ static formatDuration(seconds) {
51
+ seconds = Math.floor(seconds);
52
+ const hrs = Math.floor(seconds / 3600);
53
+ const minutes = Math.floor((seconds % 3600) / 60);
54
+ const secs = seconds % 60;
55
+ const hh = hrs > 0 ? String(hrs).padStart(2, "0") + ":" : "";
56
+ const mm = String(minutes).padStart(2, "0");
57
+ const ss = String(secs).padStart(2, "0");
58
+ return hh + mm + ":" + ss;
59
+ }
60
+ // Verify supported file types
61
+ static async verifyFileType(filePath) {
62
+ if (!filePath.endsWith(".mp3") && !filePath.endsWith(".wav")) {
63
+ console.warn("File type not supported.");
64
+ return false;
65
+ }
66
+ return true;
67
+ }
68
+ // Get formatted duration
69
+ static async getAudioDuration(filePath) {
70
+ if (!(await this.verifyFileType(filePath))) {
71
+ return "00:00";
72
+ }
73
+ const seconds = await this.calculateAudioDuration(filePath);
74
+ return this.formatDuration(seconds);
75
+ }
76
+ }
77
+ exports.default = AudioUtils;
@@ -0,0 +1,4 @@
1
+ export default class DateUtils {
2
+ static today(separator?: string): string;
3
+ static nowTime(separator?: string): string;
4
+ }
@@ -0,0 +1,22 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ class DateUtils {
4
+ // Get current date in YYYY/MM/DD or other format
5
+ static today(separator = "/") {
6
+ const date = new Date();
7
+ const year = date.getFullYear();
8
+ const month = String(date.getMonth() + 1).padStart(2, "0");
9
+ const day = String(date.getDate()).padStart(2, "0");
10
+ return `${year}${separator}${month}${separator}${day}`;
11
+ }
12
+ // Get current time in HH:MM:SS or other format
13
+ static nowTime(separator = ":") {
14
+ const date = new Date();
15
+ const hours = `${date.getHours() < 12 ? "AM" : "PM"} ${String(date.getHours() % 12 || 12).padStart(2, "0")}`;
16
+ const minutes = String(date.getMinutes()).padStart(2, "0");
17
+ const seconds = String(date.getSeconds()).padStart(2, "0");
18
+ return `${hours}${separator}${minutes}${separator}${seconds}`;
19
+ }
20
+ ;
21
+ }
22
+ exports.default = DateUtils;
@@ -0,0 +1,15 @@
1
+ export default class FileUtils {
2
+ private static readonly imageExtensions;
3
+ private static readonly videoExtensions;
4
+ private static readonly audioExtensions;
5
+ private static readonly documentExtensions;
6
+ private static readonly archiveExtensions;
7
+ private static getRawSize;
8
+ static getFileSize(filePath: string, unit?: "B" | "b" | "KB" | "kb" | "MB" | "mb" | "GB" | "gb"): string;
9
+ static getFileExtension(filePath: string): string;
10
+ static isImageFile(filePath: string): boolean;
11
+ static isVideoFile(filePath: string): boolean;
12
+ static isAudioFile(filePath: string): boolean;
13
+ static isDocumentFile(filePath: string): boolean;
14
+ static isArchiveFile(filePath: string): boolean;
15
+ }
@@ -0,0 +1,120 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ const fs_1 = __importDefault(require("fs"));
7
+ const path_1 = __importDefault(require("path"));
8
+ class FileUtils {
9
+ // Get raw file size in bytes
10
+ static getRawSize(filePath) {
11
+ try {
12
+ const stats = fs_1.default.statSync(filePath);
13
+ return stats.size;
14
+ }
15
+ catch (err) {
16
+ throw new Error(`Error getting file size: ${err.message}`);
17
+ }
18
+ }
19
+ // Get size in defrined unit
20
+ static getFileSize(filePath, unit = "KB") {
21
+ const bytes = this.getRawSize(filePath);
22
+ switch (unit) {
23
+ case "B":
24
+ case "b":
25
+ return `${bytes} B`;
26
+ case "KB":
27
+ case "kb":
28
+ return `${(bytes / 1024).toFixed(2)} KB`;
29
+ case "MB":
30
+ case "mb":
31
+ return `${(bytes / (1024 * 1024)).toFixed(2)} MB`;
32
+ case "GB":
33
+ case "gb":
34
+ return `${(bytes / (1024 * 1024 * 1024)).toFixed(2)} GB`;
35
+ default:
36
+ return `${(bytes / 1024).toFixed(2)} KB`;
37
+ }
38
+ }
39
+ // Get file extension
40
+ static getFileExtension(filePath) {
41
+ return path_1.default.extname(filePath).slice(1);
42
+ }
43
+ // Check if file is an image
44
+ static isImageFile(filePath) {
45
+ const ext = this.getFileExtension(filePath).toLowerCase();
46
+ return this.imageExtensions.includes(ext);
47
+ }
48
+ // Check if file is a video
49
+ static isVideoFile(filePath) {
50
+ const ext = this.getFileExtension(filePath).toLowerCase();
51
+ return this.videoExtensions.includes(ext);
52
+ }
53
+ // Check if file is an audio
54
+ static isAudioFile(filePath) {
55
+ const ext = this.getFileExtension(filePath).toLowerCase();
56
+ return this.audioExtensions.includes(ext);
57
+ }
58
+ // Check if file is a document
59
+ static isDocumentFile(filePath) {
60
+ const ext = this.getFileExtension(filePath).toLowerCase();
61
+ return this.documentExtensions.includes(ext);
62
+ }
63
+ // Check if file is a compressed archive
64
+ static isArchiveFile(filePath) {
65
+ const ext = this.getFileExtension(filePath).toLowerCase();
66
+ return this.archiveExtensions.includes(ext);
67
+ }
68
+ }
69
+ // Supported image extensions
70
+ FileUtils.imageExtensions = [
71
+ "jpg",
72
+ "jpeg",
73
+ "png",
74
+ "gif",
75
+ "bmp",
76
+ "webp",
77
+ "tiff",
78
+ "svg",
79
+ ];
80
+ // Supported video extensions
81
+ FileUtils.videoExtensions = [
82
+ "mp4",
83
+ "avi",
84
+ "mov",
85
+ "wmv",
86
+ "flv",
87
+ "mkv",
88
+ "webm",
89
+ ];
90
+ // Supported audio extensions
91
+ FileUtils.audioExtensions = [
92
+ "mp3",
93
+ "wav",
94
+ "flac",
95
+ "aac",
96
+ "ogg",
97
+ "m4a",
98
+ ];
99
+ // Supported document extensions
100
+ FileUtils.documentExtensions = [
101
+ "pdf",
102
+ "doc",
103
+ "docx",
104
+ "xls",
105
+ "xlsx",
106
+ "ppt",
107
+ "pptx",
108
+ "txt",
109
+ "rtf",
110
+ ];
111
+ // Supported archive extensions
112
+ FileUtils.archiveExtensions = [
113
+ "zip",
114
+ "rar",
115
+ "7z",
116
+ "tar",
117
+ "gz",
118
+ "bz2",
119
+ ];
120
+ exports.default = FileUtils;
@@ -0,0 +1,15 @@
1
+ import { Request } from "express";
2
+ interface RequestInfo {
3
+ ip: string;
4
+ method: string;
5
+ api: string;
6
+ userAgent: string;
7
+ }
8
+ export default class RequestData {
9
+ static getRequestIp(req: Request): string;
10
+ static getRequestMethod(req: Request): string;
11
+ static getRequestApi(req: Request): string;
12
+ static getRequestUserAgent(req: Request): string;
13
+ static getReqInfos(req: Request): RequestInfo;
14
+ }
15
+ export {};
@@ -0,0 +1,30 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ class RequestData {
4
+ static getRequestIp(req) {
5
+ const forwarded = req.headers["x-forwarded-for"];
6
+ const forwardedIp = Array.isArray(forwarded)
7
+ ? forwarded[0]
8
+ : forwarded?.split(",")[0]?.trim();
9
+ return (forwardedIp ||
10
+ req.socket.remoteAddress?.replace(/^::ffff:/, "") ||
11
+ "Unknown");
12
+ }
13
+ static getRequestMethod(req) {
14
+ return req.method;
15
+ }
16
+ static getRequestApi(req) {
17
+ return req.originalUrl;
18
+ }
19
+ static getRequestUserAgent(req) {
20
+ return req.headers["user-agent"] || "Unknown";
21
+ }
22
+ static getReqInfos(req) {
23
+ const ip = this.getRequestIp(req);
24
+ const method = this.getRequestMethod(req);
25
+ const api = this.getRequestApi(req);
26
+ const userAgent = this.getRequestUserAgent(req);
27
+ return { ip, method, api, userAgent };
28
+ }
29
+ }
30
+ exports.default = RequestData;
@@ -0,0 +1,4 @@
1
+ export default class VideoUtils {
2
+ private static formatDuration;
3
+ static getVideoDuration(filePath: string): Promise<string>;
4
+ }
@@ -0,0 +1,28 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ const get_video_duration_1 = require("get-video-duration");
4
+ class VideoUtils {
5
+ // Format duration as hh:mm:ss
6
+ static formatDuration(seconds) {
7
+ seconds = Math.floor(seconds);
8
+ const hrs = Math.floor(seconds / 3600);
9
+ const mins = Math.floor((seconds % 3600) / 60);
10
+ const secs = seconds % 60;
11
+ const hh = hrs > 0 ? String(hrs).padStart(2, "0") + ":" : "";
12
+ const mm = String(mins).padStart(2, "0");
13
+ const ss = String(secs).padStart(2, "0");
14
+ return hh + mm + ":" + ss;
15
+ }
16
+ // Get formatted duration
17
+ static async getVideoDuration(filePath) {
18
+ try {
19
+ const seconds = await (0, get_video_duration_1.getVideoDurationInSeconds)(filePath);
20
+ return this.formatDuration(seconds);
21
+ }
22
+ catch (err) {
23
+ console.error("Error reading video metadata:", err.message);
24
+ return "00:00";
25
+ }
26
+ }
27
+ }
28
+ exports.default = VideoUtils;
package/package.json ADDED
@@ -0,0 +1,41 @@
1
+ {
2
+ "name": "gg-tools-kit",
3
+ "version": "1.0.0",
4
+ "description": "A Node.js toolkit for utilities and protections",
5
+ "main": "dist/GGToolsKit.js",
6
+ "types": "dist/GGToolsKit.d.ts",
7
+ "scripts": {
8
+ "dev": "ts-node-dev --respawn --transpile-only src/GGToolsKit.ts",
9
+ "build": "tsc",
10
+ "start": "node dist/GGToolsKit.js"
11
+ },
12
+ "keywords": [],
13
+ "author": "MohenedGG",
14
+ "license": "ISC",
15
+ "type": "commonjs",
16
+ "files": ["dist"],
17
+ "dependencies": {
18
+ "compression": "^1.7.4",
19
+ "cookie-parser": "^1.4.7",
20
+ "cors": "^2.8.5",
21
+ "dotenv": "^17.2.3",
22
+ "express": "^5.2.1",
23
+ "express-compression": "^1.0.2",
24
+ "get-video-duration": "^5.0.0",
25
+ "helmet": "^8.1.0",
26
+ "hpp": "^0.2.3",
27
+ "morgan": "^1.10.1",
28
+ "music-metadata": "^11.10.3",
29
+ "xss": "^1.0.15"
30
+ },
31
+ "devDependencies": {
32
+ "@types/compression": "^1.8.1",
33
+ "@types/express": "^5.0.6",
34
+ "@types/helmet": "^0.0.48",
35
+ "@types/morgan": "^1.9.10",
36
+ "@types/node": "^25.0.0",
37
+ "ts-node": "^10.9.2",
38
+ "ts-node-dev": "^2.0.0",
39
+ "typescript": "^5.9.3"
40
+ }
41
+ }