appstage 0.2.22 → 0.2.23

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/index.cjs CHANGED
@@ -79,7 +79,6 @@ function matches(x, matcher) {
79
79
  }
80
80
  const defaultExtensions = ["html", "htm"];
81
81
  const defaultPath = (req) => req.path;
82
- const defaultLanguages = getLanguageList;
83
82
  /**
84
83
  * Serves files from the specified directory path or paths in a locale-aware
85
84
  * fashion after applying optional transforms.
@@ -91,6 +90,7 @@ const files = (params) => {
91
90
  let fallthrough = p.fallthrough ?? true;
92
91
  return async (req, res, next) => {
93
92
  let urlPath = typeof p.path === "string" ? p.path : (p.path ?? defaultPath)(req);
93
+ let defaultLanguage = typeof p.defaultLanguage === "function" ? p.defaultLanguage(req) : p.defaultLanguage ?? "en";
94
94
  if (!matches(urlPath, p.matches)) {
95
95
  if (fallthrough) next();
96
96
  else {
@@ -113,24 +113,25 @@ const files = (params) => {
113
113
  }
114
114
  return;
115
115
  }
116
- let langs = (p.languages ?? defaultLanguages)(req);
117
116
  let filePath = null;
118
117
  let urlExt = (0, node_path.extname)(urlPath);
118
+ let langs = (p.languages ?? getLanguageList)(req);
119
+ let defaultLanguageIndex = langs.indexOf(defaultLanguage);
120
+ let suffixes = langs.map((s) => `.${s}`);
121
+ if (defaultLanguageIndex === -1) suffixes.push("");
122
+ else suffixes.splice(defaultLanguageIndex + 1, 0, "");
119
123
  for (let k = 0; k < bases.length && filePath === null; k++) {
120
124
  let base = bases[k];
121
125
  if (!urlPath.endsWith("/")) {
122
- for (let i = 0; i < langs.length && filePath === null; i++) filePath = await resolve(base, `${urlPath}.${langs[i]}`);
126
+ for (let i = 0; i < suffixes.length && filePath === null; i++) filePath = await resolve(base, `${urlPath}${suffixes[i]}`);
123
127
  if (filePath === null && urlExt) {
124
128
  let urlPathBase = urlPath.slice(0, -urlExt.length);
125
- for (let i = 0; i < langs.length && filePath === null; i++) filePath = await resolve(base, `${urlPathBase}.${langs[i]}${urlExt}`);
129
+ for (let i = 0; i < suffixes.length && filePath === null; i++) filePath = await resolve(base, `${urlPathBase}${suffixes[i]}${urlExt}`);
126
130
  }
127
- if (filePath === null) filePath = await resolve(base, urlPath);
128
- for (let i = 0; i < langs.length && filePath === null; i++) for (let j = 0; j < exts.length && filePath === null; j++) filePath = await resolve(base, `${urlPath}.${langs[i]}.${exts[j]}`);
129
- for (let i = 0; i < exts.length && filePath === null; i++) filePath = await resolve(base, `${urlPath}.${exts[i]}`);
131
+ for (let i = 0; i < suffixes.length && filePath === null; i++) for (let j = 0; j < exts.length && filePath === null; j++) filePath = await resolve(base, `${urlPath}${suffixes[i]}.${exts[j]}`);
130
132
  }
131
- for (let i = 0; i < langs.length && filePath === null; i++) for (let j = 0; j < exts.length && filePath === null; j++) filePath = await resolve(base, `${urlPath}.${langs[i]}`, `index.${exts[j]}`);
132
- for (let i = 0; i < langs.length && filePath === null; i++) for (let j = 0; j < exts.length && filePath === null; j++) filePath = await resolve(base, urlPath, `index.${langs[i]}.${exts[j]}`);
133
- for (let i = 0; i < exts.length && filePath === null; i++) filePath = await resolve(base, urlPath, `index.${exts[i]}`);
133
+ for (let i = 0; i < suffixes.length && filePath === null; i++) for (let j = 0; j < exts.length && filePath === null; j++) filePath = await resolve(base, `${urlPath}${suffixes[i]}`, `index.${exts[j]}`);
134
+ for (let i = 0; i < suffixes.length && filePath === null; i++) for (let j = 0; j < exts.length && filePath === null; j++) filePath = await resolve(base, urlPath, `index${suffixes[i]}.${exts[j]}`);
134
135
  }
135
136
  if (filePath === null) {
136
137
  if (fallthrough) next();
@@ -167,6 +168,14 @@ const redirect = (params) => {
167
168
  return (req, res) => {
168
169
  let search = req.originalUrl.split("?")[1] ?? "";
169
170
  if (search) search = `${url.includes("?") ? "&" : "?"}${search}`;
171
+ emitLog(req.app, "Redirecting", {
172
+ data: {
173
+ from: req.originalUrl,
174
+ to: `${url}${search}`
175
+ },
176
+ req,
177
+ res
178
+ });
170
179
  res.redirect(status, `${url}${search}`);
171
180
  };
172
181
  };
package/dist/index.d.ts CHANGED
@@ -21,8 +21,17 @@ type FilesParams = {
21
21
  base: string | string[];
22
22
  path?: string | ((req: Request) => string); /** Specifies which paths should be accepted. */
23
23
  matches?: StringMatcher;
24
+ /**
25
+ * @default ["html", "htm"]
26
+ */
24
27
  extensions?: string[];
25
28
  languages?: (req: Request) => string[];
29
+ /**
30
+ * Assumed file language if unspecified in the file name.
31
+ *
32
+ * @default "en"
33
+ */
34
+ defaultLanguage?: string | ((req: Request) => string);
26
35
  transform?: TransformContent[];
27
36
  fallthrough?: boolean;
28
37
  };
package/dist/index.mjs CHANGED
@@ -53,7 +53,6 @@ function matches(x, matcher) {
53
53
  }
54
54
  const defaultExtensions = ["html", "htm"];
55
55
  const defaultPath = (req) => req.path;
56
- const defaultLanguages = getLanguageList;
57
56
  /**
58
57
  * Serves files from the specified directory path or paths in a locale-aware
59
58
  * fashion after applying optional transforms.
@@ -65,6 +64,7 @@ const files = (params) => {
65
64
  let fallthrough = p.fallthrough ?? true;
66
65
  return async (req, res, next) => {
67
66
  let urlPath = typeof p.path === "string" ? p.path : (p.path ?? defaultPath)(req);
67
+ let defaultLanguage = typeof p.defaultLanguage === "function" ? p.defaultLanguage(req) : p.defaultLanguage ?? "en";
68
68
  if (!matches(urlPath, p.matches)) {
69
69
  if (fallthrough) next();
70
70
  else {
@@ -87,24 +87,25 @@ const files = (params) => {
87
87
  }
88
88
  return;
89
89
  }
90
- let langs = (p.languages ?? defaultLanguages)(req);
91
90
  let filePath = null;
92
91
  let urlExt = extname(urlPath);
92
+ let langs = (p.languages ?? getLanguageList)(req);
93
+ let defaultLanguageIndex = langs.indexOf(defaultLanguage);
94
+ let suffixes = langs.map((s) => `.${s}`);
95
+ if (defaultLanguageIndex === -1) suffixes.push("");
96
+ else suffixes.splice(defaultLanguageIndex + 1, 0, "");
93
97
  for (let k = 0; k < bases.length && filePath === null; k++) {
94
98
  let base = bases[k];
95
99
  if (!urlPath.endsWith("/")) {
96
- for (let i = 0; i < langs.length && filePath === null; i++) filePath = await resolve$1(base, `${urlPath}.${langs[i]}`);
100
+ for (let i = 0; i < suffixes.length && filePath === null; i++) filePath = await resolve$1(base, `${urlPath}${suffixes[i]}`);
97
101
  if (filePath === null && urlExt) {
98
102
  let urlPathBase = urlPath.slice(0, -urlExt.length);
99
- for (let i = 0; i < langs.length && filePath === null; i++) filePath = await resolve$1(base, `${urlPathBase}.${langs[i]}${urlExt}`);
103
+ for (let i = 0; i < suffixes.length && filePath === null; i++) filePath = await resolve$1(base, `${urlPathBase}${suffixes[i]}${urlExt}`);
100
104
  }
101
- if (filePath === null) filePath = await resolve$1(base, urlPath);
102
- for (let i = 0; i < langs.length && filePath === null; i++) for (let j = 0; j < exts.length && filePath === null; j++) filePath = await resolve$1(base, `${urlPath}.${langs[i]}.${exts[j]}`);
103
- for (let i = 0; i < exts.length && filePath === null; i++) filePath = await resolve$1(base, `${urlPath}.${exts[i]}`);
105
+ for (let i = 0; i < suffixes.length && filePath === null; i++) for (let j = 0; j < exts.length && filePath === null; j++) filePath = await resolve$1(base, `${urlPath}${suffixes[i]}.${exts[j]}`);
104
106
  }
105
- for (let i = 0; i < langs.length && filePath === null; i++) for (let j = 0; j < exts.length && filePath === null; j++) filePath = await resolve$1(base, `${urlPath}.${langs[i]}`, `index.${exts[j]}`);
106
- for (let i = 0; i < langs.length && filePath === null; i++) for (let j = 0; j < exts.length && filePath === null; j++) filePath = await resolve$1(base, urlPath, `index.${langs[i]}.${exts[j]}`);
107
- for (let i = 0; i < exts.length && filePath === null; i++) filePath = await resolve$1(base, urlPath, `index.${exts[i]}`);
107
+ for (let i = 0; i < suffixes.length && filePath === null; i++) for (let j = 0; j < exts.length && filePath === null; j++) filePath = await resolve$1(base, `${urlPath}${suffixes[i]}`, `index.${exts[j]}`);
108
+ for (let i = 0; i < suffixes.length && filePath === null; i++) for (let j = 0; j < exts.length && filePath === null; j++) filePath = await resolve$1(base, urlPath, `index${suffixes[i]}.${exts[j]}`);
108
109
  }
109
110
  if (filePath === null) {
110
111
  if (fallthrough) next();
@@ -141,6 +142,14 @@ const redirect = (params) => {
141
142
  return (req, res) => {
142
143
  let search = req.originalUrl.split("?")[1] ?? "";
143
144
  if (search) search = `${url.includes("?") ? "&" : "?"}${search}`;
145
+ emitLog(req.app, "Redirecting", {
146
+ data: {
147
+ from: req.originalUrl,
148
+ to: `${url}${search}`
149
+ },
150
+ req,
151
+ res
152
+ });
144
153
  res.redirect(status, `${url}${search}`);
145
154
  };
146
155
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "appstage",
3
- "version": "0.2.22",
3
+ "version": "0.2.23",
4
4
  "description": "",
5
5
  "main": "./dist/index.cjs",
6
6
  "module": "./dist/index.mjs",
@@ -66,15 +66,23 @@ export type FilesParams = {
66
66
  path?: string | ((req: Request) => string);
67
67
  /** Specifies which paths should be accepted. */
68
68
  matches?: StringMatcher;
69
+ /**
70
+ * @default ["html", "htm"]
71
+ */
69
72
  extensions?: string[];
70
73
  languages?: (req: Request) => string[];
74
+ /**
75
+ * Assumed file language if unspecified in the file name.
76
+ *
77
+ * @default "en"
78
+ */
79
+ defaultLanguage?: string | ((req: Request) => string);
71
80
  transform?: TransformContent[];
72
81
  fallthrough?: boolean;
73
82
  };
74
83
 
75
84
  const defaultExtensions = ["html", "htm"];
76
85
  const defaultPath = (req: Request) => req.path;
77
- const defaultLanguages = getLanguageList;
78
86
 
79
87
  /**
80
88
  * Serves files from the specified directory path or paths in a locale-aware
@@ -91,6 +99,11 @@ export const files: Controller<string | FilesParams> = (params) => {
91
99
  let urlPath =
92
100
  typeof p.path === "string" ? p.path : (p.path ?? defaultPath)(req);
93
101
 
102
+ let defaultLanguage =
103
+ typeof p.defaultLanguage === "function"
104
+ ? p.defaultLanguage(req)
105
+ : (p.defaultLanguage ?? "en");
106
+
94
107
  if (!matches(urlPath, p.matches)) {
95
108
  if (fallthrough) next();
96
109
  else {
@@ -125,67 +138,68 @@ export const files: Controller<string | FilesParams> = (params) => {
125
138
  return;
126
139
  }
127
140
 
128
- let langs = (p.languages ?? defaultLanguages)(req);
129
141
  let filePath: string | null = null;
130
142
  let urlExt = extname(urlPath);
131
143
 
132
- // Example: path = /x, langs = [en, ru], exts = [html, htm]
144
+ let langs = (p.languages ?? getLanguageList)(req);
145
+ let defaultLanguageIndex = langs.indexOf(defaultLanguage);
146
+
147
+ let suffixes = langs.map((s) => `.${s}`);
148
+
149
+ // Check the suffixless path right after the default language suffix.
150
+ if (defaultLanguageIndex === -1) suffixes.push("");
151
+ else suffixes.splice(defaultLanguageIndex + 1, 0, "");
152
+
153
+ // Example:
154
+ // path = /x, langs = [en, ru], default lang: en, exts = [html, htm]
133
155
  for (let k = 0; k < bases.length && filePath === null; k++) {
134
156
  let base = bases[k];
135
157
 
136
158
  if (!urlPath.endsWith("/")) {
137
- // /x.en /x.ru
138
- for (let i = 0; i < langs.length && filePath === null; i++)
139
- filePath = await resolve(base, `${urlPath}.${langs[i]}`);
159
+ // /x.en /x /x.ru
160
+ for (let i = 0; i < suffixes.length && filePath === null; i++)
161
+ filePath = await resolve(base, `${urlPath}${suffixes[i]}`);
140
162
 
141
163
  if (filePath === null && urlExt) {
142
164
  let urlPathBase = urlPath.slice(0, -urlExt.length);
143
165
 
144
- // /x.en.ext /x.ru.ext
145
- for (let i = 0; i < langs.length && filePath === null; i++)
166
+ // /x.en.ext /x.ext /x.ru.ext
167
+ for (let i = 0; i < suffixes.length && filePath === null; i++)
146
168
  filePath = await resolve(
147
169
  base,
148
- `${urlPathBase}.${langs[i]}${urlExt}`,
170
+ `${urlPathBase}${suffixes[i]}${urlExt}`,
149
171
  );
150
172
  }
151
173
 
152
- // /x
153
- if (filePath === null) filePath = await resolve(base, urlPath);
154
-
155
- // /x.en.html /x.en.htm /x.ru.html /x.ru.htm
156
- for (let i = 0; i < langs.length && filePath === null; i++) {
174
+ // /x.en.html /x.en.htm /x.html /x.htm /x.ru.html /x.ru.htm
175
+ for (let i = 0; i < suffixes.length && filePath === null; i++) {
157
176
  for (let j = 0; j < exts.length && filePath === null; j++)
158
- filePath = await resolve(base, `${urlPath}.${langs[i]}.${exts[j]}`);
177
+ filePath = await resolve(
178
+ base,
179
+ `${urlPath}${suffixes[i]}.${exts[j]}`,
180
+ );
159
181
  }
160
-
161
- // /x.html /x.htm
162
- for (let i = 0; i < exts.length && filePath === null; i++)
163
- filePath = await resolve(base, `${urlPath}.${exts[i]}`);
164
182
  }
165
183
 
166
- // /x.en/index.html /x.en/index.htm /x.ru/index.html /x.ru/index.htm
167
- for (let i = 0; i < langs.length && filePath === null; i++) {
184
+ // /x.en/index.html /x.en/index.htm /x/index.html /x/index.htm /x.ru/index.html /x.ru/index.htm
185
+ for (let i = 0; i < suffixes.length && filePath === null; i++) {
168
186
  for (let j = 0; j < exts.length && filePath === null; j++)
169
187
  filePath = await resolve(
170
188
  base,
171
- `${urlPath}.${langs[i]}`,
189
+ `${urlPath}${suffixes[i]}`,
172
190
  `index.${exts[j]}`,
173
191
  );
174
192
  }
175
193
 
176
- // /x/index.en.html /x/index.en.htm /x/index.ru.html /x/index.ru.htm
177
- for (let i = 0; i < langs.length && filePath === null; i++) {
194
+ // /x/index.en.html /x/index.en.htm /x/index.html /x/index.htm /x/index.ru.html /x/index.ru.htm
195
+ for (let i = 0; i < suffixes.length && filePath === null; i++) {
178
196
  for (let j = 0; j < exts.length && filePath === null; j++)
179
197
  filePath = await resolve(
180
198
  base,
181
199
  urlPath,
182
- `index.${langs[i]}.${exts[j]}`,
200
+ `index${suffixes[i]}.${exts[j]}`,
183
201
  );
184
202
  }
185
-
186
- // /x/index.html /x/index.htm
187
- for (let i = 0; i < exts.length && filePath === null; i++)
188
- filePath = await resolve(base, urlPath, `index.${exts[i]}`);
189
203
  }
190
204
 
191
205
  if (filePath === null) {
@@ -1,4 +1,5 @@
1
1
  import type { Controller } from "../types/Controller.ts";
2
+ import { emitLog } from "../utils/emitLog.ts";
2
3
 
3
4
  export type RedirectParams = {
4
5
  url: string;
@@ -14,6 +15,15 @@ export const redirect: Controller<string | RedirectParams> = (params) => {
14
15
 
15
16
  if (search) search = `${url.includes("?") ? "&" : "?"}${search}`;
16
17
 
18
+ emitLog(req.app, "Redirecting", {
19
+ data: {
20
+ from: req.originalUrl,
21
+ to: `${url}${search}`,
22
+ },
23
+ req,
24
+ res,
25
+ });
26
+
17
27
  res.redirect(status, `${url}${search}`);
18
28
  };
19
29
  };