@cocreate/file-server 1.18.5 → 1.18.7
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/CHANGELOG.md +20 -0
- package/package.json +1 -1
- package/src/index.js +89 -27
package/CHANGELOG.md
CHANGED
|
@@ -1,3 +1,23 @@
|
|
|
1
|
+
## [1.18.7](https://github.com/CoCreate-app/CoCreate-file-server/compare/v1.18.6...v1.18.7) (2025-10-08)
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
### Bug Fixes
|
|
5
|
+
|
|
6
|
+
* enhance file content handling and error logging for font files ([3093df3](https://github.com/CoCreate-app/CoCreate-file-server/commit/3093df39c633ff4e6add31c20c57c469c751ab1a))
|
|
7
|
+
|
|
8
|
+
## [1.18.6](https://github.com/CoCreate-app/CoCreate-file-server/compare/v1.18.5...v1.18.6) (2025-10-08)
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
### Bug Fixes
|
|
12
|
+
|
|
13
|
+
* add handling for font files and improve error processing in CoCreateFileSystem ([de3c618](https://github.com/CoCreate-app/CoCreate-file-server/commit/de3c6186eebef00bfb6c237dc6d5c7435773ba41))
|
|
14
|
+
* correct pathname handling by ensuring language region is prefixed with a slash ([680832b](https://github.com/CoCreate-app/CoCreate-file-server/commit/680832b7cf710f48afd28a2fe2b425c7eb41d4b1))
|
|
15
|
+
* enhance language detection in pathname processing and support Accept-Language header ([cccc35d](https://github.com/CoCreate-app/CoCreate-file-server/commit/cccc35dc68107a5f39fbf2af053181825eb252fa))
|
|
16
|
+
* enhance language handling in pathname processing and improve file retrieval logic ([b499141](https://github.com/CoCreate-app/CoCreate-file-server/commit/b499141fe599e095a3d0a051ccede4b6131d3fa7))
|
|
17
|
+
* simplify pathname query handling in CoCreateFileSystem ([1632670](https://github.com/CoCreate-app/CoCreate-file-server/commit/1632670b17b7c76775094b2726178248e4e903d6))
|
|
18
|
+
* streamline HTML rendering logic by removing unnecessary language handling ([924041b](https://github.com/CoCreate-app/CoCreate-file-server/commit/924041bc4fba30fbeef5bcd85b6fe42f811af695))
|
|
19
|
+
* streamline language handling in pathname processing and simplify file retrieval logic ([fd43225](https://github.com/CoCreate-app/CoCreate-file-server/commit/fd432258880c33ba9f417d7a0d40eba8a9997863))
|
|
20
|
+
|
|
1
21
|
## [1.18.5](https://github.com/CoCreate-app/CoCreate-file-server/compare/v1.18.4...v1.18.5) (2025-09-02)
|
|
2
22
|
|
|
3
23
|
|
package/package.json
CHANGED
package/src/index.js
CHANGED
|
@@ -86,15 +86,32 @@ class CoCreateFileSystem {
|
|
|
86
86
|
if (!directory.includes(".")) pathname += "/index.html";
|
|
87
87
|
}
|
|
88
88
|
|
|
89
|
-
|
|
90
|
-
const
|
|
89
|
+
// Match both /en/ and /en-US/ style URLs
|
|
90
|
+
const bcp47Regex = /^\/([a-zA-Z]{2,3}(?:-[a-zA-Z0-9]{2,8})?)\//;
|
|
91
|
+
const langMatch = pathname.match(bcp47Regex);
|
|
91
92
|
let lang, langRegion;
|
|
92
|
-
if (
|
|
93
|
-
langRegion =
|
|
93
|
+
if (langMatch) {
|
|
94
|
+
langRegion = langMatch[1];
|
|
94
95
|
lang = langRegion.split("-")[0]; // Get just the base language (e.g., 'en', 'es', 'fr')
|
|
95
|
-
let
|
|
96
|
-
data.$filter.query.pathname =
|
|
96
|
+
let basePathname = pathname.replace("/" + langRegion, "");
|
|
97
|
+
data.$filter.query.pathname = basePathname;
|
|
97
98
|
} else {
|
|
99
|
+
// No language in URL, try Accept-Language header
|
|
100
|
+
let acceptLang = req.headers && req.headers["accept-language"];
|
|
101
|
+
if (acceptLang) {
|
|
102
|
+
// Parse the Accept-Language header, get the first language
|
|
103
|
+
let preferred = acceptLang.split(",")[0].trim();
|
|
104
|
+
if (preferred) {
|
|
105
|
+
lang = preferred.split("-")[0];
|
|
106
|
+
langRegion = preferred;
|
|
107
|
+
// --- BEGIN OPTIONAL REDIRECT ---
|
|
108
|
+
// Uncomment to enable automatic redirect to language-specific path
|
|
109
|
+
// let newPath = `/${preferred}${pathname.startsWith('/') ? '' : '/'}${pathname.replace(/^\//, '')}`;
|
|
110
|
+
// res.writeHead(302, { Location: newPath });
|
|
111
|
+
// return res.end();
|
|
112
|
+
// --- END OPTIONAL REDIRECT ---
|
|
113
|
+
}
|
|
114
|
+
}
|
|
98
115
|
data.$filter.query.pathname = pathname;
|
|
99
116
|
}
|
|
100
117
|
|
|
@@ -182,7 +199,56 @@ class CoCreateFileSystem {
|
|
|
182
199
|
|
|
183
200
|
let contentType = file["content-type"] || "text/html";
|
|
184
201
|
|
|
185
|
-
|
|
202
|
+
try {
|
|
203
|
+
if (typeof src === "string") {
|
|
204
|
+
// Decode the file content based on its MIME type
|
|
205
|
+
if (/^(image|audio|video|font|application\/octet-stream|application\/x-font-ttf|application\/x-font-woff|application\/x-font-woff2|application\/x-font-opentype|application\/x-font-truetype|application\/x-font-eot)/.test(contentType)) {
|
|
206
|
+
src = Buffer.from(src, "base64");
|
|
207
|
+
} else if (/^(application\/zip|application\/x-7z-compressed|application\/x-rar-compressed|application\/pdf)/.test(contentType)) {
|
|
208
|
+
src = Buffer.from(src, "binary");
|
|
209
|
+
} else {
|
|
210
|
+
src = Buffer.from(src, "utf8");
|
|
211
|
+
}
|
|
212
|
+
} else {
|
|
213
|
+
throw new Error("File content is not in a valid format");
|
|
214
|
+
}
|
|
215
|
+
} catch (err) {
|
|
216
|
+
console.error("Error decoding file content:", {
|
|
217
|
+
message: err.message,
|
|
218
|
+
contentType,
|
|
219
|
+
srcType: typeof src
|
|
220
|
+
});
|
|
221
|
+
let pageNotFound = await getDefaultFile("/404.html");
|
|
222
|
+
return sendResponse(pageNotFound.object[0].src, 404, {
|
|
223
|
+
"Content-Type": "text/html"
|
|
224
|
+
});
|
|
225
|
+
}
|
|
226
|
+
|
|
227
|
+
// Remove redundant handling for `src.src` in font file processing
|
|
228
|
+
if (contentType.startsWith("font/") || /\.(woff2?|ttf|otf)$/i.test(pathname)) {
|
|
229
|
+
try {
|
|
230
|
+
if (typeof src === "string") {
|
|
231
|
+
if (/^([A-Za-z0-9+/]+={0,2})$/.test(src)) {
|
|
232
|
+
// Decode base64-encoded font data
|
|
233
|
+
src = Buffer.from(src, "base64");
|
|
234
|
+
} else {
|
|
235
|
+
throw new Error("Font data is not valid base64");
|
|
236
|
+
}
|
|
237
|
+
} else {
|
|
238
|
+
throw new Error("Font data is not a valid base64 string");
|
|
239
|
+
}
|
|
240
|
+
} catch (err) {
|
|
241
|
+
console.error("Error processing font file:", {
|
|
242
|
+
message: err.message,
|
|
243
|
+
contentType,
|
|
244
|
+
srcType: typeof src
|
|
245
|
+
});
|
|
246
|
+
let pageNotFound = await getDefaultFile("/404.html");
|
|
247
|
+
return sendResponse(pageNotFound.object[0].src, 404, {
|
|
248
|
+
"Content-Type": "text/html"
|
|
249
|
+
});
|
|
250
|
+
}
|
|
251
|
+
} else if (
|
|
186
252
|
/^data:image\/[a-zA-Z0-9+.-]+;base64,([A-Za-z0-9+/]+={0,2})$/.test(
|
|
187
253
|
src
|
|
188
254
|
)
|
|
@@ -193,14 +259,15 @@ class CoCreateFileSystem {
|
|
|
193
259
|
src = Buffer.from(src, "base64");
|
|
194
260
|
} else if (contentType === "text/html") {
|
|
195
261
|
try {
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
262
|
+
let data = {};
|
|
263
|
+
|
|
264
|
+
src = await this.render.HTML(
|
|
265
|
+
file,
|
|
266
|
+
organization,
|
|
267
|
+
urlObject,
|
|
268
|
+
langRegion,
|
|
269
|
+
lang
|
|
270
|
+
);
|
|
204
271
|
} catch (err) {
|
|
205
272
|
console.warn("server-side-render: " + err.message);
|
|
206
273
|
}
|
|
@@ -210,6 +277,9 @@ class CoCreateFileSystem {
|
|
|
210
277
|
) {
|
|
211
278
|
const protocol = "https://"; // || req.headers['x-forwarded-proto'] || req.protocol;
|
|
212
279
|
src = src.replaceAll("{{$host}}", `${protocol}${hostname}`);
|
|
280
|
+
} else {
|
|
281
|
+
// Log unknown file types
|
|
282
|
+
console.warn(`Unknown content type: ${contentType}`);
|
|
213
283
|
}
|
|
214
284
|
|
|
215
285
|
sendResponse(src, 200, { "Content-Type": contentType });
|
|
@@ -226,10 +296,7 @@ class CoCreateFileSystem {
|
|
|
226
296
|
file["cache-control"] !== null
|
|
227
297
|
) {
|
|
228
298
|
const val = file["cache-control"];
|
|
229
|
-
if (
|
|
230
|
-
typeof val === "number" ||
|
|
231
|
-
/^\s*\d+\s*$/.test(val)
|
|
232
|
-
) {
|
|
299
|
+
if (typeof val === "number" || /^\s*\d+\s*$/.test(val)) {
|
|
233
300
|
// If it's numeric (number or numeric string) treat it as max-age.
|
|
234
301
|
cacheControl = `public, max-age=${String(
|
|
235
302
|
val
|
|
@@ -239,19 +306,14 @@ class CoCreateFileSystem {
|
|
|
239
306
|
cacheControl = val;
|
|
240
307
|
}
|
|
241
308
|
} else {
|
|
242
|
-
cacheControl =
|
|
243
|
-
organization["cache-control"] ||
|
|
244
|
-
"public, max-age=3600";
|
|
309
|
+
cacheControl = organization["cache-control"] || "public, max-age=3600";
|
|
245
310
|
}
|
|
246
311
|
|
|
247
312
|
// Always override/set Cache-Control header so the response aligns with the file metadata/defaults
|
|
248
313
|
headers["Cache-Control"] = cacheControl;
|
|
249
314
|
|
|
250
|
-
if (src instanceof Uint8Array) {
|
|
251
|
-
|
|
252
|
-
} else if (Buffer.isBuffer(src)) {
|
|
253
|
-
// Buffer is fine to send — don't bail out here (previous code returned early)
|
|
254
|
-
// keep src as-is
|
|
315
|
+
if (src instanceof Uint8Array || Buffer.isBuffer(src)) {
|
|
316
|
+
// Ensure binary data is sent as-is
|
|
255
317
|
} else if (typeof src === "object") {
|
|
256
318
|
src = JSON.stringify(src);
|
|
257
319
|
}
|