appstage 0.2.17 → 0.2.19

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
@@ -81,32 +81,39 @@ const defaultExtensions = ["html", "htm"];
81
81
  const defaultPath = (req) => req.path;
82
82
  const defaultLanguages = getLanguageList;
83
83
  /**
84
- * Serves files from the specified directory path in a locale-aware
84
+ * Serves files from the specified directory path or paths in a locale-aware
85
85
  * fashion after applying optional transforms.
86
86
  */
87
87
  const files = (params) => {
88
88
  let p = typeof params === "string" ? { base: params } : params;
89
89
  let bases = Array.isArray(p.base) ? p.base : [p.base];
90
90
  let exts = p.extensions ?? defaultExtensions;
91
- return async (req, res) => {
92
- let langs = (p.languages ?? defaultLanguages)(req);
91
+ let fallthrough = p.fallthrough ?? true;
92
+ return async (req, res, next) => {
93
93
  let path = typeof p.path === "string" ? p.path : (p.path ?? defaultPath)(req);
94
94
  if (!matches(path, p.matches)) {
95
- emitLog(req.app, "Unmatched path", { data: { path } });
96
- res.status(404).send(await req.app.renderStatus?.(req, res, {
97
- code: "unmatched_path",
98
- path
99
- }));
95
+ if (fallthrough) next();
96
+ else {
97
+ emitLog(req.app, "Unmatched path", { data: { path } });
98
+ res.status(404).send(await req.app.renderStatus?.(req, res, {
99
+ code: "unmatched_path",
100
+ path
101
+ }));
102
+ }
100
103
  return;
101
104
  }
102
105
  if (path.includes("../")) {
103
- emitLog(req.app, "Invalid path (potential traversal attempt)", { data: { path } });
104
- res.status(400).send(await req.app.renderStatus?.(req, res, {
105
- code: "invalid_path",
106
- path
107
- }));
106
+ if (fallthrough) next();
107
+ else {
108
+ emitLog(req.app, "Invalid path (potential traversal attempt)", { data: { path } });
109
+ res.status(400).send(await req.app.renderStatus?.(req, res, {
110
+ code: "invalid_path",
111
+ path
112
+ }));
113
+ }
108
114
  return;
109
115
  }
116
+ let langs = (p.languages ?? defaultLanguages)(req);
110
117
  let filePath = null;
111
118
  for (let k = 0; k < bases.length && filePath === null; k++) {
112
119
  let base = bases[k];
@@ -121,11 +128,14 @@ const files = (params) => {
121
128
  for (let i = 0; i < exts.length && filePath === null; i++) filePath = await resolve(base, path, `index.${exts[i]}`);
122
129
  }
123
130
  if (filePath === null) {
124
- emitLog(req.app, "Unknown path", { data: { path } });
125
- res.status(404).send(await req.app.renderStatus?.(req, res, {
126
- code: "unknown_path",
127
- path
128
- }));
131
+ if (fallthrough) next();
132
+ else {
133
+ emitLog(req.app, "Unknown path", { data: { path } });
134
+ res.status(404).send(await req.app.renderStatus?.(req, res, {
135
+ code: "unknown_path",
136
+ path
137
+ }));
138
+ }
129
139
  return;
130
140
  }
131
141
  if (!p.transform?.length) {
package/dist/index.d.ts CHANGED
@@ -24,9 +24,10 @@ type FilesParams = {
24
24
  extensions?: string[];
25
25
  languages?: (req: Request) => string[];
26
26
  transform?: TransformContent[];
27
+ fallthrough?: boolean;
27
28
  };
28
29
  /**
29
- * Serves files from the specified directory path in a locale-aware
30
+ * Serves files from the specified directory path or paths in a locale-aware
30
31
  * fashion after applying optional transforms.
31
32
  */
32
33
  declare const files: Controller<string | FilesParams>;
package/dist/index.mjs CHANGED
@@ -55,32 +55,39 @@ const defaultExtensions = ["html", "htm"];
55
55
  const defaultPath = (req) => req.path;
56
56
  const defaultLanguages = getLanguageList;
57
57
  /**
58
- * Serves files from the specified directory path in a locale-aware
58
+ * Serves files from the specified directory path or paths in a locale-aware
59
59
  * fashion after applying optional transforms.
60
60
  */
61
61
  const files = (params) => {
62
62
  let p = typeof params === "string" ? { base: params } : params;
63
63
  let bases = Array.isArray(p.base) ? p.base : [p.base];
64
64
  let exts = p.extensions ?? defaultExtensions;
65
- return async (req, res) => {
66
- let langs = (p.languages ?? defaultLanguages)(req);
65
+ let fallthrough = p.fallthrough ?? true;
66
+ return async (req, res, next) => {
67
67
  let path = typeof p.path === "string" ? p.path : (p.path ?? defaultPath)(req);
68
68
  if (!matches(path, p.matches)) {
69
- emitLog(req.app, "Unmatched path", { data: { path } });
70
- res.status(404).send(await req.app.renderStatus?.(req, res, {
71
- code: "unmatched_path",
72
- path
73
- }));
69
+ if (fallthrough) next();
70
+ else {
71
+ emitLog(req.app, "Unmatched path", { data: { path } });
72
+ res.status(404).send(await req.app.renderStatus?.(req, res, {
73
+ code: "unmatched_path",
74
+ path
75
+ }));
76
+ }
74
77
  return;
75
78
  }
76
79
  if (path.includes("../")) {
77
- emitLog(req.app, "Invalid path (potential traversal attempt)", { data: { path } });
78
- res.status(400).send(await req.app.renderStatus?.(req, res, {
79
- code: "invalid_path",
80
- path
81
- }));
80
+ if (fallthrough) next();
81
+ else {
82
+ emitLog(req.app, "Invalid path (potential traversal attempt)", { data: { path } });
83
+ res.status(400).send(await req.app.renderStatus?.(req, res, {
84
+ code: "invalid_path",
85
+ path
86
+ }));
87
+ }
82
88
  return;
83
89
  }
90
+ let langs = (p.languages ?? defaultLanguages)(req);
84
91
  let filePath = null;
85
92
  for (let k = 0; k < bases.length && filePath === null; k++) {
86
93
  let base = bases[k];
@@ -95,11 +102,14 @@ const files = (params) => {
95
102
  for (let i = 0; i < exts.length && filePath === null; i++) filePath = await resolve$1(base, path, `index.${exts[i]}`);
96
103
  }
97
104
  if (filePath === null) {
98
- emitLog(req.app, "Unknown path", { data: { path } });
99
- res.status(404).send(await req.app.renderStatus?.(req, res, {
100
- code: "unknown_path",
101
- path
102
- }));
105
+ if (fallthrough) next();
106
+ else {
107
+ emitLog(req.app, "Unknown path", { data: { path } });
108
+ res.status(404).send(await req.app.renderStatus?.(req, res, {
109
+ code: "unknown_path",
110
+ path
111
+ }));
112
+ }
103
113
  return;
104
114
  }
105
115
  if (!p.transform?.length) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "appstage",
3
- "version": "0.2.17",
3
+ "version": "0.2.19",
4
4
  "description": "",
5
5
  "main": "./dist/index.cjs",
6
6
  "module": "./dist/index.mjs",
@@ -69,6 +69,7 @@ export type FilesParams = {
69
69
  extensions?: string[];
70
70
  languages?: (req: Request) => string[];
71
71
  transform?: TransformContent[];
72
+ fallthrough?: boolean;
72
73
  };
73
74
 
74
75
  const defaultExtensions = ["html", "htm"];
@@ -76,7 +77,7 @@ const defaultPath = (req: Request) => req.path;
76
77
  const defaultLanguages = getLanguageList;
77
78
 
78
79
  /**
79
- * Serves files from the specified directory path in a locale-aware
80
+ * Serves files from the specified directory path or paths in a locale-aware
80
81
  * fashion after applying optional transforms.
81
82
  */
82
83
  export const files: Controller<string | FilesParams> = (params) => {
@@ -84,45 +85,50 @@ export const files: Controller<string | FilesParams> = (params) => {
84
85
 
85
86
  let bases = Array.isArray(p.base) ? p.base : [p.base];
86
87
  let exts = p.extensions ?? defaultExtensions;
88
+ let fallthrough = p.fallthrough ?? true;
87
89
 
88
- return async (req, res) => {
89
- let langs = (p.languages ?? defaultLanguages)(req);
90
-
90
+ return async (req, res, next) => {
91
91
  let path =
92
92
  typeof p.path === "string" ? p.path : (p.path ?? defaultPath)(req);
93
93
 
94
94
  if (!matches(path, p.matches)) {
95
- emitLog(req.app, "Unmatched path", { data: { path } });
96
-
97
- res.status(404).send(
98
- await req.app.renderStatus?.(req, res, {
99
- code: "unmatched_path",
100
- path,
101
- }),
102
- );
95
+ if (fallthrough) next();
96
+ else {
97
+ emitLog(req.app, "Unmatched path", { data: { path } });
98
+
99
+ res.status(404).send(
100
+ await req.app.renderStatus?.(req, res, {
101
+ code: "unmatched_path",
102
+ path,
103
+ }),
104
+ );
105
+ }
103
106
 
104
107
  return;
105
108
  }
106
109
 
107
110
  if (path.includes("../")) {
108
- emitLog(req.app, "Invalid path (potential traversal attempt)", {
109
- data: { path },
110
- });
111
-
112
- res.status(400).send(
113
- await req.app.renderStatus?.(req, res, {
114
- code: "invalid_path",
115
- path,
116
- }),
117
- );
111
+ if (fallthrough) next();
112
+ else {
113
+ emitLog(req.app, "Invalid path (potential traversal attempt)", {
114
+ data: { path },
115
+ });
116
+
117
+ res.status(400).send(
118
+ await req.app.renderStatus?.(req, res, {
119
+ code: "invalid_path",
120
+ path,
121
+ }),
122
+ );
123
+ }
118
124
 
119
125
  return;
120
126
  }
121
127
 
128
+ let langs = (p.languages ?? defaultLanguages)(req);
122
129
  let filePath: string | null = null;
123
130
 
124
- // path: /x
125
- // langs: en, ru
131
+ // Example: path = /x, langs = [en, ru], exts = [html, htm]
126
132
  for (let k = 0; k < bases.length && filePath === null; k++) {
127
133
  let base = bases[k];
128
134
 
@@ -167,14 +173,17 @@ export const files: Controller<string | FilesParams> = (params) => {
167
173
  }
168
174
 
169
175
  if (filePath === null) {
170
- emitLog(req.app, "Unknown path", { data: { path } });
171
-
172
- res.status(404).send(
173
- await req.app.renderStatus?.(req, res, {
174
- code: "unknown_path",
175
- path,
176
- }),
177
- );
176
+ if (fallthrough) next();
177
+ else {
178
+ emitLog(req.app, "Unknown path", { data: { path } });
179
+
180
+ res.status(404).send(
181
+ await req.app.renderStatus?.(req, res, {
182
+ code: "unknown_path",
183
+ path,
184
+ }),
185
+ );
186
+ }
178
187
 
179
188
  return;
180
189
  }