@rpcbase/server 0.429.0 → 0.431.0
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/getDerivedKey.d.ts +3 -0
- package/dist/getDerivedKey.d.ts.map +1 -0
- package/dist/getDerivedKey.js +7 -0
- package/dist/hashPassword.d.ts +2 -0
- package/dist/hashPassword.d.ts.map +1 -0
- package/dist/hashPassword.js +21 -0
- package/dist/index.d.ts +4 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +3 -0
- package/dist/initServer.d.ts +5 -0
- package/dist/initServer.d.ts.map +1 -0
- package/dist/initServer.js +79 -0
- package/dist/metricsIngestProxyMiddleware.d.ts +3 -0
- package/dist/metricsIngestProxyMiddleware.d.ts.map +1 -0
- package/dist/metricsIngestProxyMiddleware.js +14 -0
- package/dist/types/index.d.ts +6 -0
- package/dist/types/index.d.ts.map +1 -0
- package/dist/types/index.js +1 -0
- package/package.json +22 -4
- package/src/getDerivedKey.ts +0 -20
- package/src/hashPassword.ts +0 -24
- package/src/index.ts +0 -3
- package/src/initServer.ts +0 -100
- package/src/metricsIngestProxyMiddleware.ts +0 -17
- package/src/types/index.ts +0 -7
- package/src/types/session.d.ts +0 -11
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"getDerivedKey.d.ts","sourceRoot":"","sources":["../../../../pkg/server/src/getDerivedKey.ts"],"names":[],"mappings":"AAIA,eAAO,MAAM,aAAa,GACxB,WAAW,MAAM,EACjB,MAAM,MAAM,EACZ,SAAQ,MAAW,EAAE,0BAA0B;AAC/C,OAAM,MAAW,KAChB,MAUF,CAAA"}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import assert from "assert";
|
|
2
|
+
import { hkdfSync } from "crypto";
|
|
3
|
+
export const getDerivedKey = (masterKey, info, length = 32, // Default to 256-bit keys
|
|
4
|
+
salt = "") => {
|
|
5
|
+
assert(masterKey?.length >= 32, "MASTER_KEY must be 32 chars or longer.");
|
|
6
|
+
return Buffer.from(hkdfSync("sha256", masterKey, Buffer.from(salt), Buffer.from(info), length)).toString("hex");
|
|
7
|
+
};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"hashPassword.d.ts","sourceRoot":"","sources":["../../../../pkg/server/src/hashPassword.ts"],"names":[],"mappings":"AAGA,wBAAsB,YAAY,CAAC,QAAQ,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAoBlF"}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import { scrypt } from "crypto";
|
|
2
|
+
export async function hashPassword(password, salt) {
|
|
3
|
+
const keyLength = 64; // Length of the derived key
|
|
4
|
+
const options = {
|
|
5
|
+
N: 8192, // CPU/memory cost parameter
|
|
6
|
+
r: 8, // Block size
|
|
7
|
+
p: 1 // Parallelization factor
|
|
8
|
+
};
|
|
9
|
+
// Return a Promise-wrapped scrypt call
|
|
10
|
+
const derivedKey = await new Promise((resolve, reject) => {
|
|
11
|
+
scrypt(password, salt, keyLength, options, (err, derivedKey) => {
|
|
12
|
+
if (err) {
|
|
13
|
+
reject(err);
|
|
14
|
+
}
|
|
15
|
+
else {
|
|
16
|
+
resolve(derivedKey);
|
|
17
|
+
}
|
|
18
|
+
});
|
|
19
|
+
});
|
|
20
|
+
return derivedKey;
|
|
21
|
+
}
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../pkg/server/src/index.ts"],"names":[],"mappings":"AAAA,cAAc,cAAc,CAAA;AAC5B,cAAc,iBAAiB,CAAA;AAC/B,cAAc,gBAAgB,CAAA"}
|
package/dist/index.js
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"initServer.d.ts","sourceRoot":"","sources":["../../../../pkg/server/src/initServer.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,MAAM,SAAS,CAAA;AAsBrC,eAAO,MAAM,UAAU,GAAU,KAAK,WAAW,EAAE,WAAW;IAAE,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,CAAA;CAAE,kBA6ElG,CAAA"}
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
import session from "express-session";
|
|
2
|
+
import { RedisStore } from "connect-redis";
|
|
3
|
+
import { createClient } from "redis";
|
|
4
|
+
import requestIp from "request-ip";
|
|
5
|
+
import env from "@rpcbase/env";
|
|
6
|
+
import { initApiClient } from "@rpcbase/client";
|
|
7
|
+
// dotenv setup, merge process env with vite process.env file
|
|
8
|
+
process.env = {
|
|
9
|
+
...__vite_env__,
|
|
10
|
+
...process.env,
|
|
11
|
+
...env.config().parsed
|
|
12
|
+
};
|
|
13
|
+
import { getDerivedKey } from "./getDerivedKey";
|
|
14
|
+
import { metricsIngestProxyMiddleware } from "./metricsIngestProxyMiddleware";
|
|
15
|
+
const isProduction = process.env.NODE_ENV === "production";
|
|
16
|
+
export const initServer = async (app, serverEnv) => {
|
|
17
|
+
await initApiClient({ app });
|
|
18
|
+
app.disable("x-powered-by");
|
|
19
|
+
app.set("trust proxy", true);
|
|
20
|
+
app.use(requestIp.mw());
|
|
21
|
+
// redirect www to non-www middleware
|
|
22
|
+
app.use((req, res, next) => {
|
|
23
|
+
if (req.headers.host?.startsWith("www.")) {
|
|
24
|
+
const newHost = req.headers.host.replace("www.", "");
|
|
25
|
+
return res.redirect(301, `${req.protocol}://${newHost}${req.originalUrl}`);
|
|
26
|
+
}
|
|
27
|
+
next();
|
|
28
|
+
});
|
|
29
|
+
metricsIngestProxyMiddleware(app);
|
|
30
|
+
if (!serverEnv.REDIS_URL) {
|
|
31
|
+
console.log("WARNING", "missing REDIS_URL, will skip session storage middleware");
|
|
32
|
+
return;
|
|
33
|
+
}
|
|
34
|
+
else {
|
|
35
|
+
console.log("REDIS_URL:", serverEnv.REDIS_URL);
|
|
36
|
+
}
|
|
37
|
+
const sessionSecret = getDerivedKey(serverEnv.MASTER_KEY, "express_session_key");
|
|
38
|
+
const reconnectStrategy = (retries) => {
|
|
39
|
+
console.log("redis_client::rb/server reconnectStrategy::retrying with arg", retries);
|
|
40
|
+
if (retries < 5) {
|
|
41
|
+
console.log("retry count:", retries, "retrying in 1s");
|
|
42
|
+
return 4000;
|
|
43
|
+
}
|
|
44
|
+
else {
|
|
45
|
+
return new Error("max retries expired");
|
|
46
|
+
}
|
|
47
|
+
};
|
|
48
|
+
const redisClient = createClient({
|
|
49
|
+
url: serverEnv.REDIS_URL,
|
|
50
|
+
socket: {
|
|
51
|
+
reconnectStrategy,
|
|
52
|
+
connectTimeout: 10000,
|
|
53
|
+
keepAlive: false,
|
|
54
|
+
},
|
|
55
|
+
});
|
|
56
|
+
redisClient.on("ready", () => {
|
|
57
|
+
console.log("session-storage::redis_client connected");
|
|
58
|
+
});
|
|
59
|
+
redisClient.on("error", (error) => {
|
|
60
|
+
console.log("session-storage::redis_client ERROR", error);
|
|
61
|
+
});
|
|
62
|
+
redisClient.connect();
|
|
63
|
+
const sessionConfig = {
|
|
64
|
+
name: "session",
|
|
65
|
+
store: new RedisStore({ client: redisClient }),
|
|
66
|
+
proxy: true,
|
|
67
|
+
resave: false,
|
|
68
|
+
saveUninitialized: false,
|
|
69
|
+
secret: sessionSecret,
|
|
70
|
+
cookie: {
|
|
71
|
+
maxAge: 1000 * 3600 * 24 * 60 // 60 days
|
|
72
|
+
},
|
|
73
|
+
};
|
|
74
|
+
if (isProduction) {
|
|
75
|
+
sessionConfig.cookie.secure = true;
|
|
76
|
+
// sessionConfig.cookie.domain = ""
|
|
77
|
+
}
|
|
78
|
+
app.use(session(sessionConfig));
|
|
79
|
+
};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"metricsIngestProxyMiddleware.d.ts","sourceRoot":"","sources":["../../../../pkg/server/src/metricsIngestProxyMiddleware.ts"],"names":[],"mappings":"AAAA,OAAO,EAAC,WAAW,EAAC,MAAM,SAAS,CAAA;AAUnC,eAAO,MAAM,4BAA4B,GAAI,KAAK,WAAW,SAY5D,CAAA"}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { createProxyMiddleware } from "http-proxy-middleware";
|
|
2
|
+
const handleProxyError = (err) => {
|
|
3
|
+
console.error(`Proxy error: ${err.message}`);
|
|
4
|
+
};
|
|
5
|
+
export const metricsIngestProxyMiddleware = (app) => {
|
|
6
|
+
app.use("/ingest", createProxyMiddleware({
|
|
7
|
+
target: "https://eu.i.posthog.com",
|
|
8
|
+
changeOrigin: true,
|
|
9
|
+
pathRewrite: { "^/ingest": "" }, // Remove '/ingest' from the proxied request
|
|
10
|
+
on: {
|
|
11
|
+
error: handleProxyError
|
|
12
|
+
}
|
|
13
|
+
}));
|
|
14
|
+
};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../../pkg/server/src/types/index.ts"],"names":[],"mappings":"AAEA,MAAM,MAAM,WAAW,GAAG;IACxB,EAAE,EAAE,MAAM,CAAC;IACX,iBAAiB,EAAE,MAAM,CAAC;IAC1B,iBAAiB,EAAE,MAAM,EAAE,CAAC;CAC7B,CAAA"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
package/package.json
CHANGED
|
@@ -1,16 +1,34 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@rpcbase/server",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.431.0",
|
|
4
4
|
"type": "module",
|
|
5
|
-
"
|
|
5
|
+
"files": [
|
|
6
|
+
"dist"
|
|
7
|
+
],
|
|
8
|
+
"main": "./dist/index.js",
|
|
9
|
+
"types": "./dist/index.d.ts",
|
|
6
10
|
"scripts": {
|
|
7
|
-
"build": "
|
|
11
|
+
"build": "wireit",
|
|
8
12
|
"release": "wireit"
|
|
9
13
|
},
|
|
10
14
|
"wireit": {
|
|
15
|
+
"build": {
|
|
16
|
+
"command": "node ../../scripts/build-package.js server",
|
|
17
|
+
"files": [
|
|
18
|
+
"src/**/*",
|
|
19
|
+
"../../tsconfig.json",
|
|
20
|
+
"../../tsconfig.base.json",
|
|
21
|
+
"../../scripts/build-package.js"
|
|
22
|
+
],
|
|
23
|
+
"output": [
|
|
24
|
+
"dist/"
|
|
25
|
+
]
|
|
26
|
+
},
|
|
11
27
|
"release": {
|
|
12
28
|
"command": "../../scripts/publish.js",
|
|
13
|
-
"dependencies": [
|
|
29
|
+
"dependencies": [
|
|
30
|
+
"build"
|
|
31
|
+
],
|
|
14
32
|
"files": [
|
|
15
33
|
"package.json",
|
|
16
34
|
"src/**/*"
|
package/src/getDerivedKey.ts
DELETED
|
@@ -1,20 +0,0 @@
|
|
|
1
|
-
import assert from "assert"
|
|
2
|
-
import { hkdfSync } from "crypto"
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
export const getDerivedKey = (
|
|
6
|
-
masterKey: string,
|
|
7
|
-
info: string,
|
|
8
|
-
length: number = 32, // Default to 256-bit keys
|
|
9
|
-
salt: string = "",
|
|
10
|
-
): string => {
|
|
11
|
-
assert(masterKey?.length >= 32, "MASTER_KEY must be 32 chars or longer.")
|
|
12
|
-
|
|
13
|
-
return Buffer.from(hkdfSync(
|
|
14
|
-
"sha256",
|
|
15
|
-
masterKey,
|
|
16
|
-
Buffer.from(salt),
|
|
17
|
-
Buffer.from(info),
|
|
18
|
-
length,
|
|
19
|
-
)).toString("hex")
|
|
20
|
-
}
|
package/src/hashPassword.ts
DELETED
|
@@ -1,24 +0,0 @@
|
|
|
1
|
-
import { scrypt } from "crypto"
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
export async function hashPassword(password: string, salt: string): Promise<Buffer> {
|
|
5
|
-
const keyLength = 64 // Length of the derived key
|
|
6
|
-
const options = {
|
|
7
|
-
N: 8192, // CPU/memory cost parameter
|
|
8
|
-
r: 8, // Block size
|
|
9
|
-
p: 1 // Parallelization factor
|
|
10
|
-
}
|
|
11
|
-
|
|
12
|
-
// Return a Promise-wrapped scrypt call
|
|
13
|
-
const derivedKey = await new Promise<Buffer>((resolve, reject) => {
|
|
14
|
-
scrypt(password, salt, keyLength, options, (err, derivedKey) => {
|
|
15
|
-
if (err) {
|
|
16
|
-
reject(err)
|
|
17
|
-
} else {
|
|
18
|
-
resolve(derivedKey)
|
|
19
|
-
}
|
|
20
|
-
})
|
|
21
|
-
})
|
|
22
|
-
|
|
23
|
-
return derivedKey
|
|
24
|
-
}
|
package/src/index.ts
DELETED
package/src/initServer.ts
DELETED
|
@@ -1,100 +0,0 @@
|
|
|
1
|
-
import { Application } from "express"
|
|
2
|
-
import session, { SessionOptions } from "express-session"
|
|
3
|
-
import {RedisStore} from "connect-redis"
|
|
4
|
-
import {createClient} from "redis"
|
|
5
|
-
import requestIp from "request-ip"
|
|
6
|
-
import env from "@rpcbase/env"
|
|
7
|
-
import { initApiClient } from "@rpcbase/client"
|
|
8
|
-
|
|
9
|
-
// dotenv setup, merge process env with vite process.env file
|
|
10
|
-
process.env = {
|
|
11
|
-
...__vite_env__,
|
|
12
|
-
...process.env,
|
|
13
|
-
...env.config().parsed
|
|
14
|
-
}
|
|
15
|
-
|
|
16
|
-
import { getDerivedKey } from "./getDerivedKey"
|
|
17
|
-
import { metricsIngestProxyMiddleware } from "./metricsIngestProxyMiddleware"
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
const isProduction = process.env.NODE_ENV === "production"
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
export const initServer = async (app: Application, serverEnv: { [key: string]: string | undefined }) => {
|
|
24
|
-
await initApiClient({app})
|
|
25
|
-
|
|
26
|
-
app.disable("x-powered-by")
|
|
27
|
-
|
|
28
|
-
app.set("trust proxy", true)
|
|
29
|
-
|
|
30
|
-
app.use(requestIp.mw())
|
|
31
|
-
|
|
32
|
-
// redirect www to non-www middleware
|
|
33
|
-
app.use((req, res, next) => {
|
|
34
|
-
if (req.headers.host?.startsWith("www.")) {
|
|
35
|
-
const newHost = req.headers.host.replace("www.", "")
|
|
36
|
-
return res.redirect(301, `${req.protocol}://${newHost}${req.originalUrl}`)
|
|
37
|
-
}
|
|
38
|
-
next()
|
|
39
|
-
})
|
|
40
|
-
|
|
41
|
-
metricsIngestProxyMiddleware(app)
|
|
42
|
-
|
|
43
|
-
if (!serverEnv.REDIS_URL) {
|
|
44
|
-
console.log("WARNING", "missing REDIS_URL, will skip session storage middleware")
|
|
45
|
-
return
|
|
46
|
-
} else {
|
|
47
|
-
console.log("REDIS_URL:", serverEnv.REDIS_URL)
|
|
48
|
-
}
|
|
49
|
-
|
|
50
|
-
const sessionSecret = getDerivedKey(serverEnv.MASTER_KEY!, "express_session_key")
|
|
51
|
-
|
|
52
|
-
const reconnectStrategy = (retries: number) => {
|
|
53
|
-
console.log("redis_client::rb/server reconnectStrategy::retrying with arg", retries)
|
|
54
|
-
if (retries < 5) {
|
|
55
|
-
console.log("retry count:", retries, "retrying in 1s")
|
|
56
|
-
return 4000
|
|
57
|
-
} else {
|
|
58
|
-
return new Error("max retries expired")
|
|
59
|
-
}
|
|
60
|
-
}
|
|
61
|
-
|
|
62
|
-
const redisClient = createClient({
|
|
63
|
-
url: serverEnv.REDIS_URL,
|
|
64
|
-
socket: {
|
|
65
|
-
reconnectStrategy,
|
|
66
|
-
connectTimeout: 10000,
|
|
67
|
-
keepAlive: 0,
|
|
68
|
-
},
|
|
69
|
-
})
|
|
70
|
-
|
|
71
|
-
redisClient.on("ready", () => {
|
|
72
|
-
console.log("session-storage::redis_client connected")
|
|
73
|
-
})
|
|
74
|
-
|
|
75
|
-
redisClient.on("error", (error) => {
|
|
76
|
-
console.log("session-storage::redis_client ERROR", error)
|
|
77
|
-
})
|
|
78
|
-
|
|
79
|
-
redisClient.connect()
|
|
80
|
-
|
|
81
|
-
const sessionConfig: SessionOptions = {
|
|
82
|
-
name: "session",
|
|
83
|
-
store: new RedisStore({client: redisClient}),
|
|
84
|
-
proxy: true,
|
|
85
|
-
resave: false,
|
|
86
|
-
saveUninitialized: false,
|
|
87
|
-
secret: sessionSecret,
|
|
88
|
-
cookie: {
|
|
89
|
-
maxAge: 1000 * 3600 * 24 * 60 // 60 days
|
|
90
|
-
},
|
|
91
|
-
}
|
|
92
|
-
|
|
93
|
-
if (isProduction) {
|
|
94
|
-
sessionConfig.cookie!.secure = true
|
|
95
|
-
// sessionConfig.cookie.domain = ""
|
|
96
|
-
}
|
|
97
|
-
|
|
98
|
-
app.use(session(sessionConfig))
|
|
99
|
-
|
|
100
|
-
}
|
|
@@ -1,17 +0,0 @@
|
|
|
1
|
-
import {Application} from "express"
|
|
2
|
-
import { createProxyMiddleware } from "http-proxy-middleware"
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
export const metricsIngestProxyMiddleware = (app: Application) => {
|
|
6
|
-
app.use(
|
|
7
|
-
"/ingest",
|
|
8
|
-
createProxyMiddleware({
|
|
9
|
-
target: "https://eu.i.posthog.com",
|
|
10
|
-
changeOrigin: true,
|
|
11
|
-
pathRewrite: { "^/ingest": "" }, // Remove '/ingest' from the proxied request
|
|
12
|
-
onError: (err, _req, _res) => {
|
|
13
|
-
console.error(`Proxy error: ${err.message}`)
|
|
14
|
-
}
|
|
15
|
-
})
|
|
16
|
-
)
|
|
17
|
-
}
|
package/src/types/index.ts
DELETED