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 +19 -10
- package/dist/index.d.ts +9 -0
- package/dist/index.mjs +19 -10
- package/package.json +1 -1
- package/src/controllers/files.ts +43 -29
- package/src/controllers/redirect.ts +10 -0
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 <
|
|
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 <
|
|
129
|
+
for (let i = 0; i < suffixes.length && filePath === null; i++) filePath = await resolve(base, `${urlPathBase}${suffixes[i]}${urlExt}`);
|
|
126
130
|
}
|
|
127
|
-
|
|
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 <
|
|
132
|
-
for (let i = 0; i <
|
|
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 <
|
|
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 <
|
|
103
|
+
for (let i = 0; i < suffixes.length && filePath === null; i++) filePath = await resolve$1(base, `${urlPathBase}${suffixes[i]}${urlExt}`);
|
|
100
104
|
}
|
|
101
|
-
|
|
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 <
|
|
106
|
-
for (let i = 0; i <
|
|
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
package/src/controllers/files.ts
CHANGED
|
@@ -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
|
-
|
|
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 <
|
|
139
|
-
filePath = await resolve(base, `${urlPath}
|
|
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 <
|
|
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}
|
|
170
|
+
`${urlPathBase}${suffixes[i]}${urlExt}`,
|
|
149
171
|
);
|
|
150
172
|
}
|
|
151
173
|
|
|
152
|
-
// /x
|
|
153
|
-
|
|
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(
|
|
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 <
|
|
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}
|
|
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 <
|
|
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
|
|
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
|
};
|