@nattyjs/express 0.0.1-beta.6 → 0.0.1-beta.60
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 +127 -23
- package/dist/index.mjs +126 -24
- package/package.json +5 -4
package/dist/index.cjs
CHANGED
|
@@ -1,32 +1,36 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
3
|
const express = require('express');
|
|
4
|
+
const path = require('node:path');
|
|
4
5
|
const cors = require('cors');
|
|
5
6
|
const compression = require('compression');
|
|
6
7
|
const core = require('@nattyjs/core');
|
|
7
8
|
const common = require('@nattyjs/common');
|
|
9
|
+
const fs = require('node:fs');
|
|
8
10
|
|
|
9
11
|
function _interopDefaultCompat (e) { return e && typeof e === 'object' && 'default' in e ? e.default : e; }
|
|
10
12
|
|
|
11
13
|
const express__default = /*#__PURE__*/_interopDefaultCompat(express);
|
|
14
|
+
const path__default = /*#__PURE__*/_interopDefaultCompat(path);
|
|
12
15
|
const cors__default = /*#__PURE__*/_interopDefaultCompat(cors);
|
|
13
16
|
const compression__default = /*#__PURE__*/_interopDefaultCompat(compression);
|
|
17
|
+
const fs__default = /*#__PURE__*/_interopDefaultCompat(fs);
|
|
14
18
|
|
|
15
19
|
async function getRequestBodyInfo(request) {
|
|
16
20
|
const contentType = request.headers["content-type"];
|
|
17
21
|
const bodyInfo = {};
|
|
18
|
-
if (request.method !== common.GET)
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
break;
|
|
23
|
-
}
|
|
22
|
+
if (request.method !== common.GET) {
|
|
23
|
+
if (contentType && contentType.toLowerCase().indexOf("application/json") > -1)
|
|
24
|
+
bodyInfo.json = request.body;
|
|
25
|
+
}
|
|
24
26
|
return bodyInfo;
|
|
25
27
|
}
|
|
26
28
|
|
|
27
29
|
function getResponse(expressResponse, responseInfo) {
|
|
28
30
|
if (responseInfo.headers)
|
|
29
|
-
|
|
31
|
+
for (const pair of responseInfo.headers.entries()) {
|
|
32
|
+
expressResponse.setHeader(pair[0], pair[1]);
|
|
33
|
+
}
|
|
30
34
|
if (responseInfo.cookies)
|
|
31
35
|
responseInfo.cookies.forEach((cookie) => {
|
|
32
36
|
const name = cookie.name;
|
|
@@ -38,7 +42,9 @@ function getResponse(expressResponse, responseInfo) {
|
|
|
38
42
|
expressResponse.statusCode = responseInfo.status;
|
|
39
43
|
if (responseInfo.body && responseInfo.body.json) {
|
|
40
44
|
expressResponse.send(responseInfo.body.json);
|
|
41
|
-
} else
|
|
45
|
+
} else if (responseInfo.body && responseInfo.body.buffer)
|
|
46
|
+
expressResponse.send(responseInfo.body.buffer);
|
|
47
|
+
else
|
|
42
48
|
expressResponse.send();
|
|
43
49
|
return expressResponse;
|
|
44
50
|
}
|
|
@@ -49,7 +55,8 @@ function parseCookies(value) {
|
|
|
49
55
|
const cookies = value.split(";");
|
|
50
56
|
for (const cookie of cookies) {
|
|
51
57
|
const splitCookie = cookie.split("=");
|
|
52
|
-
|
|
58
|
+
if (splitCookie.length > 1)
|
|
59
|
+
jsonCookies.push({ name: splitCookie[0].trim(), value: splitCookie[1].trim() });
|
|
53
60
|
}
|
|
54
61
|
}
|
|
55
62
|
return jsonCookies;
|
|
@@ -58,7 +65,8 @@ function parseCookies(value) {
|
|
|
58
65
|
function requestHandler(config) {
|
|
59
66
|
return async (request, response) => {
|
|
60
67
|
const httpHandler = new core.HttpHandler();
|
|
61
|
-
const
|
|
68
|
+
const apiPrefix = `/${common.commonContainer.nattyConfig.api?.rootPath}`;
|
|
69
|
+
const url = config.framework == common.FrameworkType.Firebase ? `http://localhost:3000/api${request.url}` : `http://localhost:3000${apiPrefix}${request.url}`;
|
|
62
70
|
const httpContext = new core.HttpContext(
|
|
63
71
|
{
|
|
64
72
|
url,
|
|
@@ -72,27 +80,123 @@ function requestHandler(config) {
|
|
|
72
80
|
return httpHandler.processRequest(httpContext).then((httpResponse) => {
|
|
73
81
|
return getResponse(response, httpResponse);
|
|
74
82
|
}).catch((t) => {
|
|
75
|
-
response.
|
|
83
|
+
return getResponse(response, t.httpResponse);
|
|
76
84
|
});
|
|
77
85
|
};
|
|
78
86
|
}
|
|
79
87
|
|
|
88
|
+
function hasExtension(p) {
|
|
89
|
+
return /\.[a-z0-9]+$/i.test(p);
|
|
90
|
+
}
|
|
91
|
+
function acceptsJson(req) {
|
|
92
|
+
const a = String(req.headers.accept ?? "");
|
|
93
|
+
return a.includes("application/json") || a.includes("+json");
|
|
94
|
+
}
|
|
95
|
+
function acceptsHtml(req) {
|
|
96
|
+
const a = String(req.headers.accept ?? "");
|
|
97
|
+
return a.includes("text/html") || a.includes("application/xhtml+xml");
|
|
98
|
+
}
|
|
99
|
+
function fileExists(p) {
|
|
100
|
+
try {
|
|
101
|
+
return fs__default.existsSync(p) && fs__default.statSync(p).isFile();
|
|
102
|
+
} catch {
|
|
103
|
+
return false;
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
function dirExists(p) {
|
|
107
|
+
try {
|
|
108
|
+
return fs__default.existsSync(p) && fs__default.statSync(p).isDirectory();
|
|
109
|
+
} catch {
|
|
110
|
+
return false;
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
function staticPrettyRoutes(options) {
|
|
114
|
+
const allowExt = new Set(["html", "json"].map((x) => x.toLowerCase()));
|
|
115
|
+
const absBase = path__default.resolve(options.staticDir);
|
|
116
|
+
return (req, res, next) => {
|
|
117
|
+
if (req.method !== "GET" && req.method !== "HEAD")
|
|
118
|
+
return next();
|
|
119
|
+
const originalUrl = req.url;
|
|
120
|
+
const urlPathRaw = req.path || "/";
|
|
121
|
+
const urlPath = urlPathRaw !== "/" ? urlPathRaw.replace(/\/+$/, "") : "/";
|
|
122
|
+
if (urlPath.startsWith(options.apiPrefix))
|
|
123
|
+
return next();
|
|
124
|
+
if (hasExtension(urlPath))
|
|
125
|
+
return next();
|
|
126
|
+
if (urlPath.includes(".."))
|
|
127
|
+
return res.status(400).send("Bad request");
|
|
128
|
+
if (/(^|\/)\./.test(urlPath))
|
|
129
|
+
return res.status(404).end();
|
|
130
|
+
let rel = urlPath;
|
|
131
|
+
try {
|
|
132
|
+
rel = decodeURIComponent(urlPath);
|
|
133
|
+
} catch {
|
|
134
|
+
}
|
|
135
|
+
const absCandidateBase = path__default.resolve(options.staticDir, "." + rel);
|
|
136
|
+
if (!absCandidateBase.startsWith(absBase))
|
|
137
|
+
return res.status(400).send("Bad request");
|
|
138
|
+
const qs = originalUrl.includes("?") ? originalUrl.slice(originalUrl.indexOf("?")) : "";
|
|
139
|
+
if (dirExists(absCandidateBase)) {
|
|
140
|
+
const idx = path__default.join(absCandidateBase, "index.html");
|
|
141
|
+
if (fileExists(idx)) {
|
|
142
|
+
req.url = rel + "/index.html" + qs;
|
|
143
|
+
return next();
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
const wantJson = acceptsJson(req);
|
|
147
|
+
const wantHtml = acceptsHtml(req);
|
|
148
|
+
const extOrder = wantJson && !wantHtml ? ["json", "html"] : ["html", "json"];
|
|
149
|
+
for (const ext of extOrder) {
|
|
150
|
+
if (!allowExt.has(ext))
|
|
151
|
+
continue;
|
|
152
|
+
const fileAbs = absCandidateBase + "." + ext;
|
|
153
|
+
if (fileExists(fileAbs)) {
|
|
154
|
+
req.url = rel + "." + ext + qs;
|
|
155
|
+
return next();
|
|
156
|
+
}
|
|
157
|
+
}
|
|
158
|
+
return next();
|
|
159
|
+
};
|
|
160
|
+
}
|
|
161
|
+
|
|
80
162
|
const app = express__default();
|
|
81
163
|
const ExpressModule = {
|
|
82
164
|
init(config) {
|
|
165
|
+
const apiPrefix = `/${common.commonContainer.nattyConfig.api?.rootPath}`;
|
|
166
|
+
const staticCfg = common.commonContainer.nattyConfig.static;
|
|
83
167
|
app.use(compression__default());
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
"
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
168
|
+
if (config.cors)
|
|
169
|
+
app.use(cors__default(config.cors));
|
|
170
|
+
app.use(express__default.json({ limit: config.payload?.limit || "1mb" }));
|
|
171
|
+
if (staticCfg.enabled) {
|
|
172
|
+
const staticDir = path__default.resolve("public");
|
|
173
|
+
app.use(staticPrettyRoutes({ staticDir, apiPrefix }));
|
|
174
|
+
app.use(
|
|
175
|
+
express__default.static(staticDir, {
|
|
176
|
+
index: false,
|
|
177
|
+
maxAge: "1d"
|
|
178
|
+
})
|
|
179
|
+
);
|
|
180
|
+
if (staticCfg.spaFallback !== false) {
|
|
181
|
+
app.get("*", (req, res, next) => {
|
|
182
|
+
const url = req.originalUrl || req.url;
|
|
183
|
+
if (url.startsWith(apiPrefix))
|
|
184
|
+
return next();
|
|
185
|
+
if (req.method !== "GET")
|
|
186
|
+
return next();
|
|
187
|
+
const acceptsHtml = req.headers.accept?.includes("text/html");
|
|
188
|
+
if (!acceptsHtml)
|
|
189
|
+
return next();
|
|
190
|
+
return res.sendFile(path__default.join(staticDir, staticCfg.indexFile ?? "index.html"));
|
|
191
|
+
});
|
|
192
|
+
}
|
|
193
|
+
}
|
|
194
|
+
app.use(apiPrefix, requestHandler(config));
|
|
195
|
+
if (config.autoGeneratePort == true || config.autoGeneratePort == void 0)
|
|
196
|
+
common.getPort().then((port) => {
|
|
197
|
+
app.listen(port, () => {
|
|
198
|
+
console.log(`[NATTYJS]:Server is running on port ${port}`);
|
|
199
|
+
});
|
|
96
200
|
});
|
|
97
201
|
return app;
|
|
98
202
|
}
|
package/dist/index.mjs
CHANGED
|
@@ -1,24 +1,26 @@
|
|
|
1
1
|
import express from 'express';
|
|
2
|
+
import path from 'node:path';
|
|
2
3
|
import cors from 'cors';
|
|
3
4
|
import compression from 'compression';
|
|
4
5
|
import { HttpHandler, HttpContext } from '@nattyjs/core';
|
|
5
|
-
import { GET, FrameworkType } from '@nattyjs/common';
|
|
6
|
+
import { GET, commonContainer, FrameworkType, getPort } from '@nattyjs/common';
|
|
7
|
+
import fs from 'node:fs';
|
|
6
8
|
|
|
7
9
|
async function getRequestBodyInfo(request) {
|
|
8
10
|
const contentType = request.headers["content-type"];
|
|
9
11
|
const bodyInfo = {};
|
|
10
|
-
if (request.method !== GET)
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
break;
|
|
15
|
-
}
|
|
12
|
+
if (request.method !== GET) {
|
|
13
|
+
if (contentType && contentType.toLowerCase().indexOf("application/json") > -1)
|
|
14
|
+
bodyInfo.json = request.body;
|
|
15
|
+
}
|
|
16
16
|
return bodyInfo;
|
|
17
17
|
}
|
|
18
18
|
|
|
19
19
|
function getResponse(expressResponse, responseInfo) {
|
|
20
20
|
if (responseInfo.headers)
|
|
21
|
-
|
|
21
|
+
for (const pair of responseInfo.headers.entries()) {
|
|
22
|
+
expressResponse.setHeader(pair[0], pair[1]);
|
|
23
|
+
}
|
|
22
24
|
if (responseInfo.cookies)
|
|
23
25
|
responseInfo.cookies.forEach((cookie) => {
|
|
24
26
|
const name = cookie.name;
|
|
@@ -30,7 +32,9 @@ function getResponse(expressResponse, responseInfo) {
|
|
|
30
32
|
expressResponse.statusCode = responseInfo.status;
|
|
31
33
|
if (responseInfo.body && responseInfo.body.json) {
|
|
32
34
|
expressResponse.send(responseInfo.body.json);
|
|
33
|
-
} else
|
|
35
|
+
} else if (responseInfo.body && responseInfo.body.buffer)
|
|
36
|
+
expressResponse.send(responseInfo.body.buffer);
|
|
37
|
+
else
|
|
34
38
|
expressResponse.send();
|
|
35
39
|
return expressResponse;
|
|
36
40
|
}
|
|
@@ -41,7 +45,8 @@ function parseCookies(value) {
|
|
|
41
45
|
const cookies = value.split(";");
|
|
42
46
|
for (const cookie of cookies) {
|
|
43
47
|
const splitCookie = cookie.split("=");
|
|
44
|
-
|
|
48
|
+
if (splitCookie.length > 1)
|
|
49
|
+
jsonCookies.push({ name: splitCookie[0].trim(), value: splitCookie[1].trim() });
|
|
45
50
|
}
|
|
46
51
|
}
|
|
47
52
|
return jsonCookies;
|
|
@@ -50,7 +55,8 @@ function parseCookies(value) {
|
|
|
50
55
|
function requestHandler(config) {
|
|
51
56
|
return async (request, response) => {
|
|
52
57
|
const httpHandler = new HttpHandler();
|
|
53
|
-
const
|
|
58
|
+
const apiPrefix = `/${commonContainer.nattyConfig.api?.rootPath}`;
|
|
59
|
+
const url = config.framework == FrameworkType.Firebase ? `http://localhost:3000/api${request.url}` : `http://localhost:3000${apiPrefix}${request.url}`;
|
|
54
60
|
const httpContext = new HttpContext(
|
|
55
61
|
{
|
|
56
62
|
url,
|
|
@@ -64,27 +70,123 @@ function requestHandler(config) {
|
|
|
64
70
|
return httpHandler.processRequest(httpContext).then((httpResponse) => {
|
|
65
71
|
return getResponse(response, httpResponse);
|
|
66
72
|
}).catch((t) => {
|
|
67
|
-
response.
|
|
73
|
+
return getResponse(response, t.httpResponse);
|
|
68
74
|
});
|
|
69
75
|
};
|
|
70
76
|
}
|
|
71
77
|
|
|
78
|
+
function hasExtension(p) {
|
|
79
|
+
return /\.[a-z0-9]+$/i.test(p);
|
|
80
|
+
}
|
|
81
|
+
function acceptsJson(req) {
|
|
82
|
+
const a = String(req.headers.accept ?? "");
|
|
83
|
+
return a.includes("application/json") || a.includes("+json");
|
|
84
|
+
}
|
|
85
|
+
function acceptsHtml(req) {
|
|
86
|
+
const a = String(req.headers.accept ?? "");
|
|
87
|
+
return a.includes("text/html") || a.includes("application/xhtml+xml");
|
|
88
|
+
}
|
|
89
|
+
function fileExists(p) {
|
|
90
|
+
try {
|
|
91
|
+
return fs.existsSync(p) && fs.statSync(p).isFile();
|
|
92
|
+
} catch {
|
|
93
|
+
return false;
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
function dirExists(p) {
|
|
97
|
+
try {
|
|
98
|
+
return fs.existsSync(p) && fs.statSync(p).isDirectory();
|
|
99
|
+
} catch {
|
|
100
|
+
return false;
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
function staticPrettyRoutes(options) {
|
|
104
|
+
const allowExt = new Set(["html", "json"].map((x) => x.toLowerCase()));
|
|
105
|
+
const absBase = path.resolve(options.staticDir);
|
|
106
|
+
return (req, res, next) => {
|
|
107
|
+
if (req.method !== "GET" && req.method !== "HEAD")
|
|
108
|
+
return next();
|
|
109
|
+
const originalUrl = req.url;
|
|
110
|
+
const urlPathRaw = req.path || "/";
|
|
111
|
+
const urlPath = urlPathRaw !== "/" ? urlPathRaw.replace(/\/+$/, "") : "/";
|
|
112
|
+
if (urlPath.startsWith(options.apiPrefix))
|
|
113
|
+
return next();
|
|
114
|
+
if (hasExtension(urlPath))
|
|
115
|
+
return next();
|
|
116
|
+
if (urlPath.includes(".."))
|
|
117
|
+
return res.status(400).send("Bad request");
|
|
118
|
+
if (/(^|\/)\./.test(urlPath))
|
|
119
|
+
return res.status(404).end();
|
|
120
|
+
let rel = urlPath;
|
|
121
|
+
try {
|
|
122
|
+
rel = decodeURIComponent(urlPath);
|
|
123
|
+
} catch {
|
|
124
|
+
}
|
|
125
|
+
const absCandidateBase = path.resolve(options.staticDir, "." + rel);
|
|
126
|
+
if (!absCandidateBase.startsWith(absBase))
|
|
127
|
+
return res.status(400).send("Bad request");
|
|
128
|
+
const qs = originalUrl.includes("?") ? originalUrl.slice(originalUrl.indexOf("?")) : "";
|
|
129
|
+
if (dirExists(absCandidateBase)) {
|
|
130
|
+
const idx = path.join(absCandidateBase, "index.html");
|
|
131
|
+
if (fileExists(idx)) {
|
|
132
|
+
req.url = rel + "/index.html" + qs;
|
|
133
|
+
return next();
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
const wantJson = acceptsJson(req);
|
|
137
|
+
const wantHtml = acceptsHtml(req);
|
|
138
|
+
const extOrder = wantJson && !wantHtml ? ["json", "html"] : ["html", "json"];
|
|
139
|
+
for (const ext of extOrder) {
|
|
140
|
+
if (!allowExt.has(ext))
|
|
141
|
+
continue;
|
|
142
|
+
const fileAbs = absCandidateBase + "." + ext;
|
|
143
|
+
if (fileExists(fileAbs)) {
|
|
144
|
+
req.url = rel + "." + ext + qs;
|
|
145
|
+
return next();
|
|
146
|
+
}
|
|
147
|
+
}
|
|
148
|
+
return next();
|
|
149
|
+
};
|
|
150
|
+
}
|
|
151
|
+
|
|
72
152
|
const app = express();
|
|
73
153
|
const ExpressModule = {
|
|
74
154
|
init(config) {
|
|
155
|
+
const apiPrefix = `/${commonContainer.nattyConfig.api?.rootPath}`;
|
|
156
|
+
const staticCfg = commonContainer.nattyConfig.static;
|
|
75
157
|
app.use(compression());
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
"
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
158
|
+
if (config.cors)
|
|
159
|
+
app.use(cors(config.cors));
|
|
160
|
+
app.use(express.json({ limit: config.payload?.limit || "1mb" }));
|
|
161
|
+
if (staticCfg.enabled) {
|
|
162
|
+
const staticDir = path.resolve("public");
|
|
163
|
+
app.use(staticPrettyRoutes({ staticDir, apiPrefix }));
|
|
164
|
+
app.use(
|
|
165
|
+
express.static(staticDir, {
|
|
166
|
+
index: false,
|
|
167
|
+
maxAge: "1d"
|
|
168
|
+
})
|
|
169
|
+
);
|
|
170
|
+
if (staticCfg.spaFallback !== false) {
|
|
171
|
+
app.get("*", (req, res, next) => {
|
|
172
|
+
const url = req.originalUrl || req.url;
|
|
173
|
+
if (url.startsWith(apiPrefix))
|
|
174
|
+
return next();
|
|
175
|
+
if (req.method !== "GET")
|
|
176
|
+
return next();
|
|
177
|
+
const acceptsHtml = req.headers.accept?.includes("text/html");
|
|
178
|
+
if (!acceptsHtml)
|
|
179
|
+
return next();
|
|
180
|
+
return res.sendFile(path.join(staticDir, staticCfg.indexFile ?? "index.html"));
|
|
181
|
+
});
|
|
182
|
+
}
|
|
183
|
+
}
|
|
184
|
+
app.use(apiPrefix, requestHandler(config));
|
|
185
|
+
if (config.autoGeneratePort == true || config.autoGeneratePort == void 0)
|
|
186
|
+
getPort().then((port) => {
|
|
187
|
+
app.listen(port, () => {
|
|
188
|
+
console.log(`[NATTYJS]:Server is running on port ${port}`);
|
|
189
|
+
});
|
|
88
190
|
});
|
|
89
191
|
return app;
|
|
90
192
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@nattyjs/express",
|
|
3
|
-
"version": "0.0.1-beta.
|
|
3
|
+
"version": "0.0.1-beta.60",
|
|
4
4
|
"description": "",
|
|
5
5
|
"keywords": [],
|
|
6
6
|
"author": "ajayojha <ojhaajay@outlook.com>",
|
|
@@ -16,11 +16,12 @@
|
|
|
16
16
|
},
|
|
17
17
|
"dependencies": {
|
|
18
18
|
"express": "4.18.2",
|
|
19
|
+
"chokidar": "4.0.3",
|
|
19
20
|
"cors": "2.8.5",
|
|
20
21
|
"compression": "1.7.4",
|
|
21
|
-
"@nattyjs/core": "0.0.1-beta.
|
|
22
|
-
"@nattyjs/common": "0.0.1-beta.
|
|
23
|
-
"@nattyjs/types": "0.0.1-beta.
|
|
22
|
+
"@nattyjs/core": "0.0.1-beta.60",
|
|
23
|
+
"@nattyjs/common": "0.0.1-beta.60",
|
|
24
|
+
"@nattyjs/types": "0.0.1-beta.60"
|
|
24
25
|
},
|
|
25
26
|
"devDependencies": {
|
|
26
27
|
"@types/node": "20.3.1",
|