@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 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
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@cocreate/file-server",
3
- "version": "1.18.5",
3
+ "version": "1.18.7",
4
4
  "description": "A simple file-server component in vanilla javascript. Easily configured using HTML5 data-attributes and/or JavaScript API.",
5
5
  "keywords": [
6
6
  "file-server",
package/src/index.js CHANGED
@@ -86,15 +86,32 @@ class CoCreateFileSystem {
86
86
  if (!directory.includes(".")) pathname += "/index.html";
87
87
  }
88
88
 
89
- const bcp47Regex = /^\/([a-zA-Z]{2,3}(?:-[a-zA-Z0-9]{2,8})+)\//;
90
- const match = pathname.match(bcp47Regex);
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 (match) {
93
- langRegion = match[1];
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 newPathname = pathname.replace(langRegion, lang);
96
- data.$filter.query.pathname = { $in: [newPathname, 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
- if (
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
- file.urlObject = urlObject;
197
- if (langRegion) {
198
- file.langRegion = langRegion;
199
- }
200
- if (lang) {
201
- file.lang = lang;
202
- }
203
- src = await this.render.HTML(file);
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
- src = Buffer.from(src);
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
  }