appstage 0.2.19 → 0.2.20

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
@@ -90,50 +90,55 @@ const files = (params) => {
90
90
  let exts = p.extensions ?? defaultExtensions;
91
91
  let fallthrough = p.fallthrough ?? true;
92
92
  return async (req, res, next) => {
93
- let path = typeof p.path === "string" ? p.path : (p.path ?? defaultPath)(req);
94
- if (!matches(path, p.matches)) {
93
+ let urlPath = typeof p.path === "string" ? p.path : (p.path ?? defaultPath)(req);
94
+ if (!matches(urlPath, p.matches)) {
95
95
  if (fallthrough) next();
96
96
  else {
97
- emitLog(req.app, "Unmatched path", { data: { path } });
97
+ emitLog(req.app, "Unmatched path", { data: { urlPath } });
98
98
  res.status(404).send(await req.app.renderStatus?.(req, res, {
99
99
  code: "unmatched_path",
100
- path
100
+ urlPath
101
101
  }));
102
102
  }
103
103
  return;
104
104
  }
105
- if (path.includes("../")) {
105
+ if (urlPath.includes("../")) {
106
106
  if (fallthrough) next();
107
107
  else {
108
- emitLog(req.app, "Invalid path (potential traversal attempt)", { data: { path } });
108
+ emitLog(req.app, "Invalid path (potential traversal attempt)", { data: { urlPath } });
109
109
  res.status(400).send(await req.app.renderStatus?.(req, res, {
110
110
  code: "invalid_path",
111
- path
111
+ urlPath
112
112
  }));
113
113
  }
114
114
  return;
115
115
  }
116
116
  let langs = (p.languages ?? defaultLanguages)(req);
117
117
  let filePath = null;
118
+ let urlExt = (0, node_path.extname)(urlPath);
118
119
  for (let k = 0; k < bases.length && filePath === null; k++) {
119
120
  let base = bases[k];
120
- if (!path.endsWith("/")) {
121
- for (let i = 0; i < langs.length && filePath === null; i++) filePath = await resolve(base, `${path}.${langs[i]}`);
122
- if (filePath === null) filePath = await resolve(base, path);
123
- for (let i = 0; i < langs.length && filePath === null; i++) for (let j = 0; j < exts.length && filePath === null; j++) filePath = await resolve(base, `${path}.${langs[i]}.${exts[j]}`);
124
- for (let i = 0; i < exts.length && filePath === null; i++) filePath = await resolve(base, `${path}.${exts[i]}`);
121
+ if (!urlPath.endsWith("/")) {
122
+ for (let i = 0; i < langs.length && filePath === null; i++) filePath = await resolve(base, `${urlPath}.${langs[i]}`);
123
+ if (filePath === null && urlExt) {
124
+ 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}`);
126
+ }
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]}`);
125
130
  }
126
- for (let i = 0; i < langs.length && filePath === null; i++) for (let j = 0; j < exts.length && filePath === null; j++) filePath = await resolve(base, `${path}.${langs[i]}`, `index.${exts[j]}`);
127
- for (let i = 0; i < langs.length && filePath === null; i++) for (let j = 0; j < exts.length && filePath === null; j++) filePath = await resolve(base, path, `index.${langs[i]}.${exts[j]}`);
128
- for (let i = 0; i < exts.length && filePath === null; i++) filePath = await resolve(base, path, `index.${exts[i]}`);
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]}`);
129
134
  }
130
135
  if (filePath === null) {
131
136
  if (fallthrough) next();
132
137
  else {
133
- emitLog(req.app, "Unknown path", { data: { path } });
138
+ emitLog(req.app, "Unknown path", { data: { urlPath } });
134
139
  res.status(404).send(await req.app.renderStatus?.(req, res, {
135
140
  code: "unknown_path",
136
- path
141
+ urlPath
137
142
  }));
138
143
  }
139
144
  return;
@@ -143,17 +148,17 @@ const files = (params) => {
143
148
  return;
144
149
  }
145
150
  let content = (await (0, node_fs_promises.readFile)(filePath)).toString();
146
- let ext = (0, node_path.extname)(filePath);
147
- let name = (0, node_path.basename)(filePath, ext);
151
+ let fileExt = (0, node_path.extname)(filePath);
152
+ let fileName = (0, node_path.basename)(filePath, fileExt);
148
153
  for (let transform of p.transform) {
149
154
  let result = transform(req, res, {
150
155
  content,
151
156
  path: filePath,
152
- name
157
+ name: fileName
153
158
  });
154
159
  content = result instanceof Promise ? await result : result;
155
160
  }
156
- res.type(ext.slice(1)).send(content);
161
+ res.type(fileExt.slice(1)).send(content);
157
162
  };
158
163
  };
159
164
 
package/dist/index.mjs CHANGED
@@ -64,50 +64,55 @@ const files = (params) => {
64
64
  let exts = p.extensions ?? defaultExtensions;
65
65
  let fallthrough = p.fallthrough ?? true;
66
66
  return async (req, res, next) => {
67
- let path = typeof p.path === "string" ? p.path : (p.path ?? defaultPath)(req);
68
- if (!matches(path, p.matches)) {
67
+ let urlPath = typeof p.path === "string" ? p.path : (p.path ?? defaultPath)(req);
68
+ if (!matches(urlPath, p.matches)) {
69
69
  if (fallthrough) next();
70
70
  else {
71
- emitLog(req.app, "Unmatched path", { data: { path } });
71
+ emitLog(req.app, "Unmatched path", { data: { urlPath } });
72
72
  res.status(404).send(await req.app.renderStatus?.(req, res, {
73
73
  code: "unmatched_path",
74
- path
74
+ urlPath
75
75
  }));
76
76
  }
77
77
  return;
78
78
  }
79
- if (path.includes("../")) {
79
+ if (urlPath.includes("../")) {
80
80
  if (fallthrough) next();
81
81
  else {
82
- emitLog(req.app, "Invalid path (potential traversal attempt)", { data: { path } });
82
+ emitLog(req.app, "Invalid path (potential traversal attempt)", { data: { urlPath } });
83
83
  res.status(400).send(await req.app.renderStatus?.(req, res, {
84
84
  code: "invalid_path",
85
- path
85
+ urlPath
86
86
  }));
87
87
  }
88
88
  return;
89
89
  }
90
90
  let langs = (p.languages ?? defaultLanguages)(req);
91
91
  let filePath = null;
92
+ let urlExt = extname(urlPath);
92
93
  for (let k = 0; k < bases.length && filePath === null; k++) {
93
94
  let base = bases[k];
94
- if (!path.endsWith("/")) {
95
- for (let i = 0; i < langs.length && filePath === null; i++) filePath = await resolve$1(base, `${path}.${langs[i]}`);
96
- if (filePath === null) filePath = await resolve$1(base, path);
97
- 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, `${path}.${langs[i]}.${exts[j]}`);
98
- for (let i = 0; i < exts.length && filePath === null; i++) filePath = await resolve$1(base, `${path}.${exts[i]}`);
95
+ if (!urlPath.endsWith("/")) {
96
+ for (let i = 0; i < langs.length && filePath === null; i++) filePath = await resolve$1(base, `${urlPath}.${langs[i]}`);
97
+ if (filePath === null && urlExt) {
98
+ 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}`);
100
+ }
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]}`);
99
104
  }
100
- 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, `${path}.${langs[i]}`, `index.${exts[j]}`);
101
- 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, path, `index.${langs[i]}.${exts[j]}`);
102
- for (let i = 0; i < exts.length && filePath === null; i++) filePath = await resolve$1(base, path, `index.${exts[i]}`);
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]}`);
103
108
  }
104
109
  if (filePath === null) {
105
110
  if (fallthrough) next();
106
111
  else {
107
- emitLog(req.app, "Unknown path", { data: { path } });
112
+ emitLog(req.app, "Unknown path", { data: { urlPath } });
108
113
  res.status(404).send(await req.app.renderStatus?.(req, res, {
109
114
  code: "unknown_path",
110
- path
115
+ urlPath
111
116
  }));
112
117
  }
113
118
  return;
@@ -117,17 +122,17 @@ const files = (params) => {
117
122
  return;
118
123
  }
119
124
  let content = (await readFile(filePath)).toString();
120
- let ext = extname(filePath);
121
- let name = basename(filePath, ext);
125
+ let fileExt = extname(filePath);
126
+ let fileName = basename(filePath, fileExt);
122
127
  for (let transform of p.transform) {
123
128
  let result = transform(req, res, {
124
129
  content,
125
130
  path: filePath,
126
- name
131
+ name: fileName
127
132
  });
128
133
  content = result instanceof Promise ? await result : result;
129
134
  }
130
- res.type(ext.slice(1)).send(content);
135
+ res.type(fileExt.slice(1)).send(content);
131
136
  };
132
137
  };
133
138
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "appstage",
3
- "version": "0.2.19",
3
+ "version": "0.2.20",
4
4
  "description": "",
5
5
  "main": "./dist/index.cjs",
6
6
  "module": "./dist/index.mjs",
@@ -88,18 +88,18 @@ export const files: Controller<string | FilesParams> = (params) => {
88
88
  let fallthrough = p.fallthrough ?? true;
89
89
 
90
90
  return async (req, res, next) => {
91
- let path =
91
+ let urlPath =
92
92
  typeof p.path === "string" ? p.path : (p.path ?? defaultPath)(req);
93
93
 
94
- if (!matches(path, p.matches)) {
94
+ if (!matches(urlPath, p.matches)) {
95
95
  if (fallthrough) next();
96
96
  else {
97
- emitLog(req.app, "Unmatched path", { data: { path } });
97
+ emitLog(req.app, "Unmatched path", { data: { urlPath } });
98
98
 
99
99
  res.status(404).send(
100
100
  await req.app.renderStatus?.(req, res, {
101
101
  code: "unmatched_path",
102
- path,
102
+ urlPath,
103
103
  }),
104
104
  );
105
105
  }
@@ -107,17 +107,17 @@ export const files: Controller<string | FilesParams> = (params) => {
107
107
  return;
108
108
  }
109
109
 
110
- if (path.includes("../")) {
110
+ if (urlPath.includes("../")) {
111
111
  if (fallthrough) next();
112
112
  else {
113
113
  emitLog(req.app, "Invalid path (potential traversal attempt)", {
114
- data: { path },
114
+ data: { urlPath },
115
115
  });
116
116
 
117
117
  res.status(400).send(
118
118
  await req.app.renderStatus?.(req, res, {
119
119
  code: "invalid_path",
120
- path,
120
+ urlPath,
121
121
  }),
122
122
  );
123
123
  }
@@ -127,28 +127,40 @@ export const files: Controller<string | FilesParams> = (params) => {
127
127
 
128
128
  let langs = (p.languages ?? defaultLanguages)(req);
129
129
  let filePath: string | null = null;
130
+ let urlExt = extname(urlPath);
130
131
 
131
132
  // Example: path = /x, langs = [en, ru], exts = [html, htm]
132
133
  for (let k = 0; k < bases.length && filePath === null; k++) {
133
134
  let base = bases[k];
134
135
 
135
- if (!path.endsWith("/")) {
136
+ if (!urlPath.endsWith("/")) {
136
137
  // /x.en /x.ru
137
138
  for (let i = 0; i < langs.length && filePath === null; i++)
138
- filePath = await resolve(base, `${path}.${langs[i]}`);
139
+ filePath = await resolve(base, `${urlPath}.${langs[i]}`);
140
+
141
+ if (filePath === null && urlExt) {
142
+ let urlPathBase = urlPath.slice(0, -urlExt.length);
143
+
144
+ // /x.en.ext /x.ru.ext
145
+ for (let i = 0; i < langs.length && filePath === null; i++)
146
+ filePath = await resolve(
147
+ base,
148
+ `${urlPathBase}.${langs[i]}${urlExt}`,
149
+ );
150
+ }
139
151
 
140
152
  // /x
141
- if (filePath === null) filePath = await resolve(base, path);
153
+ if (filePath === null) filePath = await resolve(base, urlPath);
142
154
 
143
155
  // /x.en.html /x.en.htm /x.ru.html /x.ru.htm
144
156
  for (let i = 0; i < langs.length && filePath === null; i++) {
145
157
  for (let j = 0; j < exts.length && filePath === null; j++)
146
- filePath = await resolve(base, `${path}.${langs[i]}.${exts[j]}`);
158
+ filePath = await resolve(base, `${urlPath}.${langs[i]}.${exts[j]}`);
147
159
  }
148
160
 
149
161
  // /x.html /x.htm
150
162
  for (let i = 0; i < exts.length && filePath === null; i++)
151
- filePath = await resolve(base, `${path}.${exts[i]}`);
163
+ filePath = await resolve(base, `${urlPath}.${exts[i]}`);
152
164
  }
153
165
 
154
166
  // /x.en/index.html /x.en/index.htm /x.ru/index.html /x.ru/index.htm
@@ -156,7 +168,7 @@ export const files: Controller<string | FilesParams> = (params) => {
156
168
  for (let j = 0; j < exts.length && filePath === null; j++)
157
169
  filePath = await resolve(
158
170
  base,
159
- `${path}.${langs[i]}`,
171
+ `${urlPath}.${langs[i]}`,
160
172
  `index.${exts[j]}`,
161
173
  );
162
174
  }
@@ -164,23 +176,27 @@ export const files: Controller<string | FilesParams> = (params) => {
164
176
  // /x/index.en.html /x/index.en.htm /x/index.ru.html /x/index.ru.htm
165
177
  for (let i = 0; i < langs.length && filePath === null; i++) {
166
178
  for (let j = 0; j < exts.length && filePath === null; j++)
167
- filePath = await resolve(base, path, `index.${langs[i]}.${exts[j]}`);
179
+ filePath = await resolve(
180
+ base,
181
+ urlPath,
182
+ `index.${langs[i]}.${exts[j]}`,
183
+ );
168
184
  }
169
185
 
170
186
  // /x/index.html /x/index.htm
171
187
  for (let i = 0; i < exts.length && filePath === null; i++)
172
- filePath = await resolve(base, path, `index.${exts[i]}`);
188
+ filePath = await resolve(base, urlPath, `index.${exts[i]}`);
173
189
  }
174
190
 
175
191
  if (filePath === null) {
176
192
  if (fallthrough) next();
177
193
  else {
178
- emitLog(req.app, "Unknown path", { data: { path } });
194
+ emitLog(req.app, "Unknown path", { data: { urlPath } });
179
195
 
180
196
  res.status(404).send(
181
197
  await req.app.renderStatus?.(req, res, {
182
198
  code: "unknown_path",
183
- path,
199
+ urlPath,
184
200
  }),
185
201
  );
186
202
  }
@@ -194,15 +210,19 @@ export const files: Controller<string | FilesParams> = (params) => {
194
210
  }
195
211
 
196
212
  let content = (await readFile(filePath)).toString();
197
- let ext = extname(filePath);
198
- let name = basename(filePath, ext);
213
+ let fileExt = extname(filePath);
214
+ let fileName = basename(filePath, fileExt);
199
215
 
200
216
  for (let transform of p.transform) {
201
- let result = transform(req, res, { content, path: filePath, name });
217
+ let result = transform(req, res, {
218
+ content,
219
+ path: filePath,
220
+ name: fileName,
221
+ });
202
222
 
203
223
  content = result instanceof Promise ? await result : result;
204
224
  }
205
225
 
206
- res.type(ext.slice(1)).send(content);
226
+ res.type(fileExt.slice(1)).send(content);
207
227
  };
208
228
  };