@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.
@@ -0,0 +1,3 @@
1
+ export declare const getDerivedKey: (masterKey: string, info: string, length?: number, // Default to 256-bit keys
2
+ salt?: string) => string;
3
+ //# sourceMappingURL=getDerivedKey.d.ts.map
@@ -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,2 @@
1
+ export declare function hashPassword(password: string, salt: string): Promise<Buffer>;
2
+ //# sourceMappingURL=hashPassword.d.ts.map
@@ -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
+ }
@@ -0,0 +1,4 @@
1
+ export * from "./initServer";
2
+ export * from "./getDerivedKey";
3
+ export * from "./hashPassword";
4
+ //# sourceMappingURL=index.d.ts.map
@@ -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,3 @@
1
+ export * from "./initServer";
2
+ export * from "./getDerivedKey";
3
+ export * from "./hashPassword";
@@ -0,0 +1,5 @@
1
+ import { Application } from "express";
2
+ export declare const initServer: (app: Application, serverEnv: {
3
+ [key: string]: string | undefined;
4
+ }) => Promise<void>;
5
+ //# sourceMappingURL=initServer.d.ts.map
@@ -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,3 @@
1
+ import { Application } from "express";
2
+ export declare const metricsIngestProxyMiddleware: (app: Application) => void;
3
+ //# sourceMappingURL=metricsIngestProxyMiddleware.d.ts.map
@@ -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,6 @@
1
+ export type SessionUser = {
2
+ id: string;
3
+ current_tenant_id: string;
4
+ signed_in_tenants: string[];
5
+ };
6
+ //# sourceMappingURL=index.d.ts.map
@@ -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.429.0",
3
+ "version": "0.431.0",
4
4
  "type": "module",
5
- "main": "./src/index.ts",
5
+ "files": [
6
+ "dist"
7
+ ],
8
+ "main": "./dist/index.js",
9
+ "types": "./dist/index.d.ts",
6
10
  "scripts": {
7
- "build": "tsc --watch",
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/**/*"
@@ -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
- }
@@ -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
@@ -1,3 +0,0 @@
1
- export * from "./initServer"
2
- export * from "./getDerivedKey"
3
- export * from "./hashPassword"
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
- }
@@ -1,7 +0,0 @@
1
-
2
-
3
- export type SessionUser = {
4
- id: string;
5
- current_tenant_id: string;
6
- signed_in_tenants: string[];
7
- }
@@ -1,11 +0,0 @@
1
- // types/session.d.ts
2
- import "express-session"
3
-
4
- import { SessionUser } from "./index"
5
-
6
-
7
- declare module "express-session" {
8
- interface SessionData {
9
- user?: SessionUser;
10
- }
11
- }