xypriss 2.2.0 → 2.2.1
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.
- package/dist/cjs/src/plugins/modules/network/builtin/CompressionPlugin.js +2 -110
- package/dist/cjs/src/plugins/modules/network/builtin/CompressionPlugin.js.map +1 -1
- package/dist/cjs/src/plugins/modules/network/builtin/ConnectionPlugin.js.map +1 -1
- package/dist/cjs/src/plugins/modules/network/core/NetworkPlugin.js.map +1 -1
- package/dist/cjs/src/plugins/modules/network/types/NetworkTypes.js.map +1 -1
- package/dist/cjs/src/server/FastServer.js +10 -10
- package/dist/cjs/src/server/FastServer.js.map +1 -1
- package/dist/cjs/src/server/components/fastapi/RouteManager.js.map +1 -1
- package/dist/cjs/src/server/components/fastapi/smart-routes.js.map +1 -1
- package/dist/cjs/src/server/core/HttpServer.js +13 -0
- package/dist/cjs/src/server/core/HttpServer.js.map +1 -1
- package/dist/cjs/src/server/core/XyprissApp.js.map +1 -1
- package/dist/cjs/src/server/handlers/NotFoundHandler.js.map +1 -1
- package/dist/cjs/src/server/optimization/RequestPreCompiler.js +1 -0
- package/dist/cjs/src/server/optimization/RequestPreCompiler.js.map +1 -1
- package/dist/cjs/src/server/utils/ConfigLoader.js +245 -148
- package/dist/cjs/src/server/utils/ConfigLoader.js.map +1 -1
- package/dist/esm/src/plugins/modules/network/builtin/CompressionPlugin.js +2 -110
- package/dist/esm/src/plugins/modules/network/builtin/CompressionPlugin.js.map +1 -1
- package/dist/esm/src/plugins/modules/network/builtin/ConnectionPlugin.js.map +1 -1
- package/dist/esm/src/plugins/modules/network/core/NetworkPlugin.js.map +1 -1
- package/dist/esm/src/plugins/modules/network/types/NetworkTypes.js.map +1 -1
- package/dist/esm/src/server/FastServer.js +10 -10
- package/dist/esm/src/server/FastServer.js.map +1 -1
- package/dist/esm/src/server/components/fastapi/RouteManager.js.map +1 -1
- package/dist/esm/src/server/components/fastapi/smart-routes.js.map +1 -1
- package/dist/esm/src/server/core/HttpServer.js +13 -0
- package/dist/esm/src/server/core/HttpServer.js.map +1 -1
- package/dist/esm/src/server/core/XyprissApp.js.map +1 -1
- package/dist/esm/src/server/handlers/NotFoundHandler.js.map +1 -1
- package/dist/esm/src/server/optimization/RequestPreCompiler.js +1 -0
- package/dist/esm/src/server/optimization/RequestPreCompiler.js.map +1 -1
- package/dist/esm/src/server/utils/ConfigLoader.js +227 -151
- package/dist/esm/src/server/utils/ConfigLoader.js.map +1 -1
- package/dist/index.d.ts +68 -44
- package/package.json +1 -2
|
@@ -3,207 +3,304 @@
|
|
|
3
3
|
var fs = require('fs');
|
|
4
4
|
var path = require('path');
|
|
5
5
|
|
|
6
|
+
function _interopNamespaceDefault(e) {
|
|
7
|
+
var n = Object.create(null);
|
|
8
|
+
if (e) {
|
|
9
|
+
Object.keys(e).forEach(function (k) {
|
|
10
|
+
if (k !== 'default') {
|
|
11
|
+
var d = Object.getOwnPropertyDescriptor(e, k);
|
|
12
|
+
Object.defineProperty(n, k, d.get ? d : {
|
|
13
|
+
enumerable: true,
|
|
14
|
+
get: function () { return e[k]; }
|
|
15
|
+
});
|
|
16
|
+
}
|
|
17
|
+
});
|
|
18
|
+
}
|
|
19
|
+
n.default = e;
|
|
20
|
+
return Object.freeze(n);
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
var fs__namespace = /*#__PURE__*/_interopNamespaceDefault(fs);
|
|
24
|
+
var path__namespace = /*#__PURE__*/_interopNamespaceDefault(path);
|
|
25
|
+
|
|
26
|
+
/**
|
|
27
|
+
* XyPriss Configuration Loader
|
|
28
|
+
*
|
|
29
|
+
* Automatically loads configuration from external files (TypeScript or JSON)
|
|
30
|
+
* Supports xypriss.config.ts, xypriss.config.js, and xypriss.config.json files
|
|
31
|
+
*
|
|
32
|
+
* @fileoverview Configuration loader for external config files
|
|
33
|
+
* @version 1.0.0
|
|
34
|
+
* @author XyPriss Team
|
|
35
|
+
* @since 2025-01-01
|
|
36
|
+
*/
|
|
6
37
|
/**
|
|
7
|
-
* Configuration
|
|
8
|
-
|
|
38
|
+
* Configuration file names to search for (in order of preference)
|
|
39
|
+
*/
|
|
40
|
+
const CONFIG_FILES = [
|
|
41
|
+
"xypriss.config.ts",
|
|
42
|
+
"xypriss.config.js",
|
|
43
|
+
"xypriss.config.json",
|
|
44
|
+
"xypriss.config.cjs",
|
|
45
|
+
"xypriss.config.mjs",
|
|
46
|
+
];
|
|
47
|
+
/**
|
|
48
|
+
* Configuration loader class
|
|
49
|
+
* Handles loading and validation of external configuration files
|
|
9
50
|
*/
|
|
10
51
|
class ConfigLoader {
|
|
11
52
|
/**
|
|
12
|
-
* Load configuration from
|
|
53
|
+
* Load configuration from external files (synchronous - JSON only)
|
|
54
|
+
*
|
|
55
|
+
* Searches for JSON configuration files in the current working directory
|
|
56
|
+
* and loads the first one found. This is a synchronous version for use in constructors.
|
|
57
|
+
*
|
|
58
|
+
* @param cwd - Current working directory (defaults to process.cwd())
|
|
59
|
+
* @returns Loaded configuration or null if no config found
|
|
60
|
+
*
|
|
61
|
+
* @example
|
|
62
|
+
* ```typescript
|
|
63
|
+
* const configLoader = new ConfigLoader();
|
|
64
|
+
* const config = configLoader.loadConfigSync();
|
|
65
|
+
* if (config) {
|
|
66
|
+
* console.log("Loaded config from:", config._source);
|
|
67
|
+
* }
|
|
68
|
+
* ```
|
|
13
69
|
*/
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
70
|
+
loadConfigSync(cwd = process.cwd()) {
|
|
71
|
+
// Only load JSON files synchronously for constructor use
|
|
72
|
+
const jsonConfigPath = path__namespace.resolve(cwd, "xypriss.config.json");
|
|
73
|
+
if (fs__namespace.existsSync(jsonConfigPath)) {
|
|
74
|
+
try {
|
|
75
|
+
const config = this.loadJsonConfig(jsonConfigPath);
|
|
76
|
+
if (config && typeof config === "object") {
|
|
77
|
+
// Add source information for debugging
|
|
78
|
+
config._source = jsonConfigPath;
|
|
79
|
+
return config;
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
catch (error) {
|
|
83
|
+
// Silently fail in constructor - config loading errors should not break initialization
|
|
84
|
+
console.warn(`Warning: Failed to load JSON config from ${jsonConfigPath}:`, error);
|
|
27
85
|
}
|
|
28
86
|
}
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
87
|
+
return null;
|
|
88
|
+
}
|
|
89
|
+
/**
|
|
90
|
+
* Load configuration from external files (asynchronous)
|
|
91
|
+
*
|
|
92
|
+
* Searches for configuration files in the current working directory
|
|
93
|
+
* and loads the first one found. Supports TypeScript, JavaScript, and JSON files.
|
|
94
|
+
*
|
|
95
|
+
* @param cwd - Current working directory (defaults to process.cwd())
|
|
96
|
+
* @returns Promise resolving to loaded configuration or null if no config found
|
|
97
|
+
*
|
|
98
|
+
* @example
|
|
99
|
+
* ```typescript
|
|
100
|
+
* const configLoader = new ConfigLoader();
|
|
101
|
+
* const config = await configLoader.loadConfig();
|
|
102
|
+
* if (config) {
|
|
103
|
+
* console.log("Loaded config from:", config._source);
|
|
104
|
+
* }
|
|
105
|
+
* ```
|
|
106
|
+
*/
|
|
107
|
+
async loadConfig(cwd = process.cwd()) {
|
|
108
|
+
for (const configFile of CONFIG_FILES) {
|
|
109
|
+
const configPath = path__namespace.resolve(cwd, configFile);
|
|
110
|
+
if (fs__namespace.existsSync(configPath)) {
|
|
111
|
+
try {
|
|
112
|
+
const config = await this.loadConfigFile(configPath);
|
|
113
|
+
if (config && typeof config === "object") {
|
|
114
|
+
// Add source information for debugging
|
|
115
|
+
config._source = configPath;
|
|
37
116
|
return config;
|
|
38
117
|
}
|
|
39
118
|
}
|
|
119
|
+
catch (error) {
|
|
120
|
+
console.warn(`Warning: Failed to load config from ${configPath}:`, error);
|
|
121
|
+
// Continue to next file instead of failing
|
|
122
|
+
}
|
|
40
123
|
}
|
|
41
124
|
}
|
|
42
|
-
return null;
|
|
125
|
+
return null; // No configuration file found
|
|
43
126
|
}
|
|
44
127
|
/**
|
|
45
128
|
* Load configuration from a specific file
|
|
129
|
+
*
|
|
130
|
+
* @param configPath - Absolute path to the configuration file
|
|
131
|
+
* @returns Promise resolving to the loaded configuration
|
|
132
|
+
* @private
|
|
46
133
|
*/
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
default:
|
|
62
|
-
// Try to parse as JSON for .XyPrissrc files
|
|
63
|
-
return ConfigLoader.loadJsonConfig(filePath);
|
|
64
|
-
}
|
|
65
|
-
}
|
|
66
|
-
catch (error) {
|
|
67
|
-
console.warn(` Failed to load config from ${filePath}: ${error.message}`);
|
|
68
|
-
return null;
|
|
134
|
+
async loadConfigFile(configPath) {
|
|
135
|
+
const ext = path__namespace.extname(configPath).toLowerCase();
|
|
136
|
+
switch (ext) {
|
|
137
|
+
case ".json":
|
|
138
|
+
return this.loadJsonConfig(configPath);
|
|
139
|
+
case ".js":
|
|
140
|
+
case ".cjs":
|
|
141
|
+
return this.loadJsConfig(configPath);
|
|
142
|
+
case ".mjs":
|
|
143
|
+
return this.loadMjsConfig(configPath);
|
|
144
|
+
case ".ts":
|
|
145
|
+
return this.loadTsConfig(configPath);
|
|
146
|
+
default:
|
|
147
|
+
throw new Error(`Unsupported config file extension: ${ext}`);
|
|
69
148
|
}
|
|
70
149
|
}
|
|
71
150
|
/**
|
|
72
|
-
* Load JSON configuration
|
|
151
|
+
* Load JSON configuration file
|
|
152
|
+
*
|
|
153
|
+
* @param configPath - Path to JSON config file
|
|
154
|
+
* @returns Parsed JSON configuration
|
|
155
|
+
* @private
|
|
156
|
+
*/
|
|
157
|
+
loadJsonConfig(configPath) {
|
|
158
|
+
const content = fs__namespace.readFileSync(configPath, "utf-8");
|
|
159
|
+
return JSON.parse(content);
|
|
160
|
+
}
|
|
161
|
+
/**
|
|
162
|
+
* Load JavaScript configuration file
|
|
163
|
+
*
|
|
164
|
+
* @param configPath - Path to JS config file
|
|
165
|
+
* @returns Configuration object exported by the JS file
|
|
166
|
+
* @private
|
|
73
167
|
*/
|
|
74
|
-
|
|
168
|
+
async loadJsConfig(configPath) {
|
|
169
|
+
// For CommonJS and ESM files, we need dynamic import which works for both
|
|
75
170
|
try {
|
|
76
|
-
|
|
77
|
-
|
|
171
|
+
// Use dynamic import which works for both CommonJS and ESM
|
|
172
|
+
const config = await import(configPath);
|
|
173
|
+
// Handle both default export and named exports
|
|
174
|
+
return config.default || config;
|
|
78
175
|
}
|
|
79
176
|
catch (error) {
|
|
80
|
-
|
|
81
|
-
|
|
177
|
+
// Fallback to require for CommonJS in environments where dynamic import fails
|
|
178
|
+
try {
|
|
179
|
+
// Clear require cache to allow reloading
|
|
180
|
+
delete require.cache[require.resolve(configPath)];
|
|
181
|
+
const config = require(configPath);
|
|
182
|
+
// Handle both default export and module.exports
|
|
183
|
+
return config.default || config;
|
|
184
|
+
}
|
|
185
|
+
catch (fallbackError) {
|
|
186
|
+
throw new Error(`Failed to load JS config: ${error}. Fallback also failed: ${fallbackError}`);
|
|
187
|
+
}
|
|
82
188
|
}
|
|
83
189
|
}
|
|
84
190
|
/**
|
|
85
|
-
* Load
|
|
191
|
+
* Load ES Module configuration file
|
|
192
|
+
*
|
|
193
|
+
* @param configPath - Path to MJS config file
|
|
194
|
+
* @returns Configuration object exported by the MJS file
|
|
195
|
+
* @private
|
|
86
196
|
*/
|
|
87
|
-
|
|
197
|
+
async loadMjsConfig(configPath) {
|
|
198
|
+
// For ES modules, we need dynamic import
|
|
88
199
|
try {
|
|
89
|
-
|
|
90
|
-
delete require.cache[require.resolve(filePath)];
|
|
91
|
-
const config = require(filePath);
|
|
92
|
-
// Handle both default export and named export
|
|
200
|
+
const config = await import(configPath);
|
|
93
201
|
return config.default || config;
|
|
94
202
|
}
|
|
95
203
|
catch (error) {
|
|
96
|
-
|
|
97
|
-
return null;
|
|
204
|
+
throw new Error(`Failed to load MJS config: ${error}`);
|
|
98
205
|
}
|
|
99
206
|
}
|
|
100
207
|
/**
|
|
101
|
-
* Load TypeScript configuration
|
|
208
|
+
* Load TypeScript configuration file
|
|
209
|
+
*
|
|
210
|
+
* @param configPath - Path to TS config file
|
|
211
|
+
* @returns Configuration object exported by the TS file
|
|
212
|
+
* @private
|
|
102
213
|
*/
|
|
103
|
-
|
|
214
|
+
async loadTsConfig(configPath) {
|
|
104
215
|
try {
|
|
105
|
-
//
|
|
106
|
-
|
|
107
|
-
|
|
216
|
+
// First, try to load as JavaScript (if user compiled it)
|
|
217
|
+
const jsPath = configPath.replace(/\.ts$/, ".js");
|
|
218
|
+
if (fs__namespace.existsSync(jsPath)) {
|
|
219
|
+
return this.loadJsConfig(jsPath);
|
|
108
220
|
}
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
try {
|
|
112
|
-
require("tsx/cjs");
|
|
113
|
-
}
|
|
114
|
-
catch {
|
|
115
|
-
console.warn(` TypeScript config found but no TypeScript loader available. Install ts-node or tsx.`);
|
|
116
|
-
return null;
|
|
117
|
-
}
|
|
118
|
-
}
|
|
119
|
-
// Clear require cache
|
|
120
|
-
delete require.cache[require.resolve(filePath)];
|
|
121
|
-
const config = require(filePath);
|
|
122
|
-
// Handle both default export and named export
|
|
221
|
+
// Try dynamic import directly (works if ts-node or similar is available)
|
|
222
|
+
const config = await import(configPath);
|
|
123
223
|
return config.default || config;
|
|
124
224
|
}
|
|
125
225
|
catch (error) {
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
226
|
+
// If direct import fails, try to compile with ts-node if available
|
|
227
|
+
try {
|
|
228
|
+
// Check if ts-node is available
|
|
229
|
+
require.resolve("ts-node");
|
|
230
|
+
// Register ts-node for TypeScript compilation
|
|
231
|
+
require("ts-node/register");
|
|
232
|
+
// Clear require cache and load the TypeScript file
|
|
233
|
+
delete require.cache[require.resolve(configPath)];
|
|
234
|
+
const config = require(configPath);
|
|
235
|
+
return config.default || config;
|
|
236
|
+
}
|
|
237
|
+
catch (tsNodeError) {
|
|
238
|
+
// If ts-node is not available or fails, provide helpful error message
|
|
239
|
+
throw new Error(`Failed to load TS config from ${configPath}. ` +
|
|
240
|
+
`Please ensure ts-node is installed (npm install ts-node) or compile to JS first. ` +
|
|
241
|
+
`Original error: ${error.message}`);
|
|
138
242
|
}
|
|
139
243
|
}
|
|
140
|
-
return merged;
|
|
141
244
|
}
|
|
142
245
|
/**
|
|
143
|
-
*
|
|
246
|
+
* Validate configuration object
|
|
247
|
+
*
|
|
248
|
+
* Performs basic validation on the loaded configuration
|
|
249
|
+
*
|
|
250
|
+
* @param config - Configuration object to validate
|
|
251
|
+
* @returns True if configuration is valid
|
|
252
|
+
*
|
|
253
|
+
* @example
|
|
254
|
+
* ```typescript
|
|
255
|
+
* const loader = new ConfigLoader();
|
|
256
|
+
* const config = await loader.loadConfig();
|
|
257
|
+
* if (config && loader.validateConfig(config)) {
|
|
258
|
+
* console.log("Config is valid");
|
|
259
|
+
* }
|
|
260
|
+
* ```
|
|
144
261
|
*/
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
if (typeof source[key] === "object" &&
|
|
150
|
-
source[key] !== null &&
|
|
151
|
-
!Array.isArray(source[key]) &&
|
|
152
|
-
typeof target[key] === "object" &&
|
|
153
|
-
target[key] !== null &&
|
|
154
|
-
!Array.isArray(target[key])) {
|
|
155
|
-
result[key] = ConfigLoader.deepMerge(target[key], source[key]);
|
|
156
|
-
}
|
|
157
|
-
else {
|
|
158
|
-
result[key] = source[key];
|
|
159
|
-
}
|
|
160
|
-
}
|
|
262
|
+
validateConfig(config) {
|
|
263
|
+
// Basic validation - check if it's an object
|
|
264
|
+
if (!config || typeof config !== "object") {
|
|
265
|
+
return false;
|
|
161
266
|
}
|
|
162
|
-
|
|
267
|
+
// Check for required structure (at least one valid property)
|
|
268
|
+
const validKeys = [
|
|
269
|
+
"env", "server", "security", "performance", "monitoring",
|
|
270
|
+
"cache", "cluster", "plugins", "requestManagement", "fileUpload"
|
|
271
|
+
];
|
|
272
|
+
return validKeys.some(key => key in config);
|
|
163
273
|
}
|
|
164
274
|
/**
|
|
165
|
-
*
|
|
275
|
+
* Get list of available configuration files in a directory
|
|
276
|
+
*
|
|
277
|
+
* @param cwd - Directory to search (defaults to process.cwd())
|
|
278
|
+
* @returns Array of available configuration file names
|
|
279
|
+
*
|
|
280
|
+
* @example
|
|
281
|
+
* ```typescript
|
|
282
|
+
* const loader = new ConfigLoader();
|
|
283
|
+
* const files = loader.getAvailableConfigFiles();
|
|
284
|
+
* console.log("Available config files:", files);
|
|
285
|
+
* ```
|
|
166
286
|
*/
|
|
167
|
-
|
|
168
|
-
const
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
typeof fw.typescript.runner !== "string") {
|
|
174
|
-
errors.push("fileWatcher.typescript.runner must be a string");
|
|
175
|
-
}
|
|
176
|
-
if (fw.typescript?.runnerArgs &&
|
|
177
|
-
!Array.isArray(fw.typescript.runnerArgs)) {
|
|
178
|
-
errors.push("fileWatcher.typescript.runnerArgs must be an array");
|
|
179
|
-
}
|
|
180
|
-
if (fw.extensions && !Array.isArray(fw.extensions)) {
|
|
181
|
-
errors.push("fileWatcher.extensions must be an array");
|
|
182
|
-
}
|
|
183
|
-
if (fw.watchPaths && !Array.isArray(fw.watchPaths)) {
|
|
184
|
-
errors.push("fileWatcher.watchPaths must be an array");
|
|
287
|
+
getAvailableConfigFiles(cwd = process.cwd()) {
|
|
288
|
+
const available = [];
|
|
289
|
+
for (const configFile of CONFIG_FILES) {
|
|
290
|
+
const configPath = path__namespace.resolve(cwd, configFile);
|
|
291
|
+
if (fs__namespace.existsSync(configPath)) {
|
|
292
|
+
available.push(configFile);
|
|
185
293
|
}
|
|
186
294
|
}
|
|
187
|
-
return
|
|
188
|
-
valid: errors.length === 0,
|
|
189
|
-
errors,
|
|
190
|
-
};
|
|
295
|
+
return available;
|
|
191
296
|
}
|
|
192
297
|
}
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
".XyPrissrc",
|
|
199
|
-
".XyPrissrc.json",
|
|
200
|
-
".XyPrissrc.js",
|
|
201
|
-
];
|
|
202
|
-
ConfigLoader.DEFAULT_SEARCH_PATHS = [
|
|
203
|
-
process.cwd(),
|
|
204
|
-
path.join(process.cwd(), "config"),
|
|
205
|
-
path.join(process.cwd(), ".config"),
|
|
206
|
-
];
|
|
298
|
+
/**
|
|
299
|
+
* Default configuration loader instance
|
|
300
|
+
* Can be used directly without creating a new instance
|
|
301
|
+
*/
|
|
302
|
+
const configLoader = new ConfigLoader();
|
|
207
303
|
|
|
208
304
|
exports.ConfigLoader = ConfigLoader;
|
|
305
|
+
exports.configLoader = configLoader;
|
|
209
306
|
//# sourceMappingURL=ConfigLoader.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ConfigLoader.js","sources":["../../../../../src/server/utils/ConfigLoader.ts"],"sourcesContent":[null],"names":["
|
|
1
|
+
{"version":3,"file":"ConfigLoader.js","sources":["../../../../../src/server/utils/ConfigLoader.ts"],"sourcesContent":[null],"names":["path","fs"],"mappings":"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"}
|
|
@@ -162,7 +162,7 @@ class CompressionPlugin extends NetworkPlugin {
|
|
|
162
162
|
return false;
|
|
163
163
|
}
|
|
164
164
|
// Check content type
|
|
165
|
-
const contentType = res.get("Content-Type") || "";
|
|
165
|
+
const contentType = String(res.get("Content-Type") || "");
|
|
166
166
|
if (!this.shouldCompressContentType(contentType)) {
|
|
167
167
|
return false;
|
|
168
168
|
}
|
|
@@ -171,7 +171,7 @@ class CompressionPlugin extends NetworkPlugin {
|
|
|
171
171
|
return false;
|
|
172
172
|
}
|
|
173
173
|
// Check content length threshold
|
|
174
|
-
const contentLength = parseInt(res.get("Content-Length") || "0");
|
|
174
|
+
const contentLength = parseInt(String(res.get("Content-Length") || "0"));
|
|
175
175
|
if (contentLength > 0 && contentLength < (config.threshold || 1024)) {
|
|
176
176
|
return false;
|
|
177
177
|
}
|
|
@@ -217,112 +217,6 @@ class CompressionPlugin extends NetworkPlugin {
|
|
|
217
217
|
}
|
|
218
218
|
return contentType.toLowerCase().includes(pattern.toLowerCase());
|
|
219
219
|
}
|
|
220
|
-
/**
|
|
221
|
-
* Select best compression algorithm based on client support and preferences
|
|
222
|
-
*/
|
|
223
|
-
selectCompressionAlgorithm(req) {
|
|
224
|
-
const acceptEncoding = req.get("Accept-Encoding") || "";
|
|
225
|
-
const encodings = acceptEncoding.toLowerCase();
|
|
226
|
-
// Priority order: brotli > gzip > deflate
|
|
227
|
-
const priorityOrder = [
|
|
228
|
-
"brotli",
|
|
229
|
-
"gzip",
|
|
230
|
-
"deflate",
|
|
231
|
-
];
|
|
232
|
-
for (const algorithm of priorityOrder) {
|
|
233
|
-
if (this.supportedAlgorithms.includes(algorithm) &&
|
|
234
|
-
encodings.includes(algorithm)) {
|
|
235
|
-
return algorithm;
|
|
236
|
-
}
|
|
237
|
-
}
|
|
238
|
-
return null;
|
|
239
|
-
}
|
|
240
|
-
/**
|
|
241
|
-
* Apply compression to response
|
|
242
|
-
*/
|
|
243
|
-
async applyCompression(context, algorithm) {
|
|
244
|
-
const { res } = context;
|
|
245
|
-
const config = this.getCompressionConfig();
|
|
246
|
-
// Set compression headers
|
|
247
|
-
res.setHeader("Content-Encoding", algorithm);
|
|
248
|
-
res.setHeader("Vary", "Accept-Encoding");
|
|
249
|
-
// Remove content-length header as it will change
|
|
250
|
-
res.removeHeader("Content-Length");
|
|
251
|
-
// Create compression stream
|
|
252
|
-
const compressionStream = this.createCompressionStream(algorithm, config.level || 6);
|
|
253
|
-
// Intercept response write/end methods
|
|
254
|
-
this.interceptResponse(res, compressionStream, context);
|
|
255
|
-
}
|
|
256
|
-
/**
|
|
257
|
-
* Create compression stream for algorithm
|
|
258
|
-
*/
|
|
259
|
-
createCompressionStream(algorithm, level) {
|
|
260
|
-
switch (algorithm) {
|
|
261
|
-
case "gzip":
|
|
262
|
-
return zlib.createGzip({ level });
|
|
263
|
-
case "deflate":
|
|
264
|
-
return zlib.createDeflate({ level });
|
|
265
|
-
case "brotli":
|
|
266
|
-
return zlib.createBrotliCompress({
|
|
267
|
-
params: {
|
|
268
|
-
[zlib.constants.BROTLI_PARAM_QUALITY]: level,
|
|
269
|
-
},
|
|
270
|
-
});
|
|
271
|
-
default:
|
|
272
|
-
throw new Error(`Unsupported compression algorithm: ${algorithm}`);
|
|
273
|
-
}
|
|
274
|
-
}
|
|
275
|
-
/**
|
|
276
|
-
* Intercept response to apply compression
|
|
277
|
-
*/
|
|
278
|
-
interceptResponse(res, compressionStream, context) {
|
|
279
|
-
res.write.bind(res);
|
|
280
|
-
res.end.bind(res);
|
|
281
|
-
let originalSize = 0;
|
|
282
|
-
let compressedSize = 0;
|
|
283
|
-
// Track compressed data
|
|
284
|
-
compressionStream.on("data", (chunk) => {
|
|
285
|
-
compressedSize += chunk.length;
|
|
286
|
-
});
|
|
287
|
-
// Override write method
|
|
288
|
-
res.write = function (chunk, encoding, callback) {
|
|
289
|
-
if (chunk) {
|
|
290
|
-
originalSize += Buffer.isBuffer(chunk)
|
|
291
|
-
? chunk.length
|
|
292
|
-
: Buffer.byteLength(chunk, encoding);
|
|
293
|
-
return compressionStream.write(chunk, encoding, callback);
|
|
294
|
-
}
|
|
295
|
-
return true;
|
|
296
|
-
};
|
|
297
|
-
// Override end method
|
|
298
|
-
res.end = function (chunk, encoding, callback) {
|
|
299
|
-
if (chunk) {
|
|
300
|
-
originalSize += Buffer.isBuffer(chunk)
|
|
301
|
-
? chunk.length
|
|
302
|
-
: Buffer.byteLength(chunk, encoding);
|
|
303
|
-
}
|
|
304
|
-
compressionStream.end(chunk, encoding, () => {
|
|
305
|
-
// Update metrics
|
|
306
|
-
context.networkMetrics.bytesSent = compressedSize;
|
|
307
|
-
context.networkMetrics.compressionRatio =
|
|
308
|
-
originalSize > 0 ? compressedSize / originalSize : 1;
|
|
309
|
-
if (callback)
|
|
310
|
-
callback();
|
|
311
|
-
});
|
|
312
|
-
return this;
|
|
313
|
-
};
|
|
314
|
-
// Pipe compression stream to response
|
|
315
|
-
compressionStream.pipe(res, { end: false });
|
|
316
|
-
}
|
|
317
|
-
/**
|
|
318
|
-
* Update compression statistics
|
|
319
|
-
*/
|
|
320
|
-
updateCompressionStats(algorithm) {
|
|
321
|
-
this.compressionStats.totalRequests++;
|
|
322
|
-
this.compressionStats.compressedRequests++;
|
|
323
|
-
const currentUsage = this.compressionStats.algorithmUsage.get(algorithm) || 0;
|
|
324
|
-
this.compressionStats.algorithmUsage.set(algorithm, currentUsage + 1);
|
|
325
|
-
}
|
|
326
220
|
/**
|
|
327
221
|
* Get compression configuration
|
|
328
222
|
*/
|
|
@@ -350,8 +244,6 @@ class CompressionPlugin extends NetworkPlugin {
|
|
|
350
244
|
async checkNetworkHealth() {
|
|
351
245
|
const errorRate = this.performanceMetrics.errorCount /
|
|
352
246
|
Math.max(this.performanceMetrics.totalExecutions, 1);
|
|
353
|
-
this.compressionStats.compressedRequests /
|
|
354
|
-
Math.max(this.compressionStats.totalRequests, 1);
|
|
355
247
|
return {
|
|
356
248
|
healthy: errorRate < 0.1 &&
|
|
357
249
|
this.performanceMetrics.averageExecutionTime <
|