@juit/pgproxy-server 1.0.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/README.md +8 -0
- package/dist/index.cjs +25 -0
- package/dist/index.cjs.map +6 -0
- package/dist/index.d.ts +20 -0
- package/dist/index.mjs +3 -0
- package/dist/index.mjs.map +6 -0
- package/dist/server.cjs +390 -0
- package/dist/server.cjs.map +6 -0
- package/dist/server.d.ts +30 -0
- package/dist/server.mjs +355 -0
- package/dist/server.mjs.map +6 -0
- package/dist/token.cjs +53 -0
- package/dist/token.cjs.map +6 -0
- package/dist/token.d.ts +1 -0
- package/dist/token.mjs +18 -0
- package/dist/token.mjs.map +6 -0
- package/package.json +48 -0
- package/src/index.ts +25 -0
- package/src/server.ts +514 -0
- package/src/token.ts +53 -0
package/dist/server.mjs
ADDED
|
@@ -0,0 +1,355 @@
|
|
|
1
|
+
// server.ts
|
|
2
|
+
import assert from "node:assert";
|
|
3
|
+
import { randomUUID } from "node:crypto";
|
|
4
|
+
import { createServer, STATUS_CODES } from "node:http";
|
|
5
|
+
import { resolve } from "node:path";
|
|
6
|
+
import { parse as parseQueryString } from "node:querystring";
|
|
7
|
+
import { ConnectionPool } from "@juit/pgproxy-pool";
|
|
8
|
+
import { WebSocketServer } from "ws";
|
|
9
|
+
import { verifyToken } from "./token.mjs";
|
|
10
|
+
var ServerImpl = class {
|
|
11
|
+
/* Keep those as private class members, they contain auth data... */
|
|
12
|
+
#tokens = {};
|
|
13
|
+
#pool;
|
|
14
|
+
#secret;
|
|
15
|
+
_server;
|
|
16
|
+
_logger;
|
|
17
|
+
_healthCheck;
|
|
18
|
+
_backlog;
|
|
19
|
+
_address;
|
|
20
|
+
_port;
|
|
21
|
+
_started = false;
|
|
22
|
+
_stopped = false;
|
|
23
|
+
constructor(logger, options) {
|
|
24
|
+
const { address, port, backlog, secret, healthCheck, pool, ...serverOptions } = options;
|
|
25
|
+
this.#pool = new ConnectionPool(logger, pool);
|
|
26
|
+
this.#secret = secret;
|
|
27
|
+
this._healthCheck = healthCheck ? resolve("/", healthCheck) : null;
|
|
28
|
+
this._backlog = backlog;
|
|
29
|
+
this._address = address;
|
|
30
|
+
this._logger = logger;
|
|
31
|
+
this._port = port;
|
|
32
|
+
this._server = createServer(serverOptions);
|
|
33
|
+
const wss = new WebSocketServer({ noServer: true });
|
|
34
|
+
this._server.on("request", (req, res) => this._requestHandler(req, res));
|
|
35
|
+
this._server.on("upgrade", (req, sock, head) => this._upgradeHandler(req, sock, head, wss));
|
|
36
|
+
this._server.on("close", () => {
|
|
37
|
+
wss.close((wssError) => {
|
|
38
|
+
if (wssError)
|
|
39
|
+
logger.error("Error closing WebSocket server:", wssError);
|
|
40
|
+
try {
|
|
41
|
+
this.#pool.stop();
|
|
42
|
+
} catch (poolError) {
|
|
43
|
+
logger.error("Error closing connection pool:", poolError);
|
|
44
|
+
} finally {
|
|
45
|
+
this._logger.info("DB proxy server stopped");
|
|
46
|
+
}
|
|
47
|
+
});
|
|
48
|
+
});
|
|
49
|
+
}
|
|
50
|
+
_catchError(message) {
|
|
51
|
+
return (error) => this._logger.error(message, error);
|
|
52
|
+
}
|
|
53
|
+
/* ======================================================================== *
|
|
54
|
+
* PROPERTIES *
|
|
55
|
+
* ======================================================================== */
|
|
56
|
+
get address() {
|
|
57
|
+
const address = this._server?.address();
|
|
58
|
+
assert(address, "Server not started");
|
|
59
|
+
return address;
|
|
60
|
+
}
|
|
61
|
+
/* coverage ignore next */
|
|
62
|
+
get url() {
|
|
63
|
+
const { address, family, port } = this.address;
|
|
64
|
+
if (family === "IPv6")
|
|
65
|
+
return new URL(`http://[${address}]:${port}/`);
|
|
66
|
+
if (family === "IPv4")
|
|
67
|
+
return new URL(`http://${address}:${port}/`);
|
|
68
|
+
throw new Error(`Unsupported address family "${family}"`);
|
|
69
|
+
}
|
|
70
|
+
get stats() {
|
|
71
|
+
return this.#pool.stats;
|
|
72
|
+
}
|
|
73
|
+
/* ======================================================================== *
|
|
74
|
+
* LIFECYCLE METHODS *
|
|
75
|
+
* ======================================================================== */
|
|
76
|
+
async start() {
|
|
77
|
+
assert(!this._started, "Server already started");
|
|
78
|
+
this._started = true;
|
|
79
|
+
this._logger.debug("Starting server");
|
|
80
|
+
await this.#pool.start();
|
|
81
|
+
await new Promise((resolve2, reject) => {
|
|
82
|
+
this._server.on("error", reject);
|
|
83
|
+
this._server.listen(this._port, this._address, this._backlog, () => {
|
|
84
|
+
this._server.off("error", reject);
|
|
85
|
+
resolve2();
|
|
86
|
+
});
|
|
87
|
+
});
|
|
88
|
+
this._server.on(
|
|
89
|
+
"error",
|
|
90
|
+
/* coverage ignore next */
|
|
91
|
+
(error) => {
|
|
92
|
+
this._logger.error("Server Error:", error);
|
|
93
|
+
this.stop().catch(this._catchError("Error stopping server")).finally(() => process.exit(1));
|
|
94
|
+
}
|
|
95
|
+
);
|
|
96
|
+
setInterval(() => {
|
|
97
|
+
const now = Date.now();
|
|
98
|
+
for (const [token, expiry] of Object.entries(this.#tokens)) {
|
|
99
|
+
if (expiry < now)
|
|
100
|
+
delete this.#tokens[token];
|
|
101
|
+
}
|
|
102
|
+
}).unref();
|
|
103
|
+
this._logger.info(`DB proxy server started at ${this.url}`);
|
|
104
|
+
if (this._healthCheck) {
|
|
105
|
+
this._logger.info(`Unauthenticated health check available at "${this._healthCheck}"`);
|
|
106
|
+
}
|
|
107
|
+
this._logger.info("Connection pool options");
|
|
108
|
+
for (const [key, value] of Object.entries(this.#pool.configuration)) {
|
|
109
|
+
const name = key.replaceAll(/[A-Z]/g, (c) => ` ${c.toLowerCase()}`);
|
|
110
|
+
this._logger.info(`- ${name}: ${value}`);
|
|
111
|
+
}
|
|
112
|
+
return this;
|
|
113
|
+
}
|
|
114
|
+
async stop() {
|
|
115
|
+
assert(this._started, "Server never started");
|
|
116
|
+
assert(!this._stopped, "Server already stopped");
|
|
117
|
+
this._stopped = true;
|
|
118
|
+
this._logger.info(`Stopping DB proxy server at "${this.url}"`);
|
|
119
|
+
await new Promise(
|
|
120
|
+
/* coverage ignore next */
|
|
121
|
+
(resolve2, reject) => {
|
|
122
|
+
this._server.close((error) => error ? reject(error) : resolve2());
|
|
123
|
+
}
|
|
124
|
+
);
|
|
125
|
+
}
|
|
126
|
+
/* ======================================================================== *
|
|
127
|
+
* REQUEST HANDLING *
|
|
128
|
+
* ======================================================================== */
|
|
129
|
+
_sendResponse(object, statusCode, request, response) {
|
|
130
|
+
new Promise((resolve2, reject) => {
|
|
131
|
+
try {
|
|
132
|
+
const json = JSON.stringify(object);
|
|
133
|
+
const buffer = Buffer.from(json, "utf-8");
|
|
134
|
+
response.statusCode = statusCode;
|
|
135
|
+
response.setHeader("content-type", "application/json");
|
|
136
|
+
response.setHeader("content-length", buffer.length);
|
|
137
|
+
response.write(buffer, (error) => {
|
|
138
|
+
if (error)
|
|
139
|
+
reject(error);
|
|
140
|
+
else
|
|
141
|
+
resolve2();
|
|
142
|
+
});
|
|
143
|
+
} catch (error) {
|
|
144
|
+
reject(error);
|
|
145
|
+
}
|
|
146
|
+
}).catch(
|
|
147
|
+
/* coverage ignore next */
|
|
148
|
+
(error) => {
|
|
149
|
+
this._logger.error(`Error handling request "${request.url}"`, error);
|
|
150
|
+
response.statusCode = 500;
|
|
151
|
+
}
|
|
152
|
+
).finally(() => response.end());
|
|
153
|
+
}
|
|
154
|
+
_healthCheckHandler(request, response) {
|
|
155
|
+
if (request.url !== this._healthCheck) {
|
|
156
|
+
response.statusCode = 404;
|
|
157
|
+
return void response.end();
|
|
158
|
+
}
|
|
159
|
+
void Promise.resolve().then(async () => {
|
|
160
|
+
const stats = { ...this.stats };
|
|
161
|
+
const start = process.hrtime.bigint();
|
|
162
|
+
const connection = await this.#pool.acquire();
|
|
163
|
+
const queryStart = process.hrtime.bigint();
|
|
164
|
+
try {
|
|
165
|
+
await connection.query("SELECT now()");
|
|
166
|
+
} finally {
|
|
167
|
+
this.#pool.release(connection);
|
|
168
|
+
}
|
|
169
|
+
const queryEnd = process.hrtime.bigint();
|
|
170
|
+
const latency = Math.floor(Number(queryEnd - start) / 1e4) / 100;
|
|
171
|
+
const connTime = Math.floor(Number(queryStart - start) / 1e4) / 100;
|
|
172
|
+
const queryTime = Math.floor(Number(queryEnd - queryStart) / 1e4) / 100;
|
|
173
|
+
return { ...stats, latency, connTime, queryTime };
|
|
174
|
+
}).then((data) => {
|
|
175
|
+
const { connTime, queryTime, ...stats } = data;
|
|
176
|
+
this._sendResponse(stats, 200, request, response);
|
|
177
|
+
this._logger.info(`Handled Health check with latency of ${data.latency} ms (connection ${connTime} ms, query ${queryTime} ms)`);
|
|
178
|
+
});
|
|
179
|
+
}
|
|
180
|
+
_requestHandler(request, response) {
|
|
181
|
+
if (request.method === "GET")
|
|
182
|
+
return this._healthCheckHandler(request, response);
|
|
183
|
+
const statusCode = this._validateAuth(request);
|
|
184
|
+
if (statusCode !== 200) {
|
|
185
|
+
response.statusCode = statusCode;
|
|
186
|
+
return void response.end();
|
|
187
|
+
}
|
|
188
|
+
if (request.method !== "POST") {
|
|
189
|
+
response.statusCode = 405;
|
|
190
|
+
return void response.end();
|
|
191
|
+
}
|
|
192
|
+
if (request.headers["content-type"] !== "application/json") {
|
|
193
|
+
response.statusCode = 415;
|
|
194
|
+
return void response.end();
|
|
195
|
+
}
|
|
196
|
+
const now = process.hrtime.bigint();
|
|
197
|
+
void Promise.resolve().then(async () => {
|
|
198
|
+
const string = await this._readRequest(request);
|
|
199
|
+
const payload = this._validatePayload(string);
|
|
200
|
+
if (!payload.valid) {
|
|
201
|
+
return { id: payload.id, statusCode: 400, error: payload.error };
|
|
202
|
+
}
|
|
203
|
+
let connection;
|
|
204
|
+
try {
|
|
205
|
+
const now2 = process.hrtime.bigint();
|
|
206
|
+
connection = await this.#pool.acquire();
|
|
207
|
+
const ms = Number(process.hrtime.bigint() - now2) / 1e6;
|
|
208
|
+
this._logger.debug(`Acquired connection ${connection.id} in ${ms} ms`);
|
|
209
|
+
} catch (error) {
|
|
210
|
+
this._logger.error("Error acquiring connection:", error);
|
|
211
|
+
return { id: payload.id, statusCode: 500, error: "Error acquiring connection" };
|
|
212
|
+
}
|
|
213
|
+
try {
|
|
214
|
+
const result = await connection.query(payload.query, payload.params);
|
|
215
|
+
return { ...result, statusCode: 200, id: payload.id };
|
|
216
|
+
} catch (error) {
|
|
217
|
+
return { id: payload.id, statusCode: 400, error: error.message };
|
|
218
|
+
} finally {
|
|
219
|
+
this.#pool.release(connection);
|
|
220
|
+
}
|
|
221
|
+
}).then((data) => {
|
|
222
|
+
this._sendResponse(data, data.statusCode, request, response);
|
|
223
|
+
const ms = Math.floor(Number(process.hrtime.bigint() - now) / 1e4) / 100;
|
|
224
|
+
this._logger.info(`Handled "${data.command}" HTTP request in ${ms} ms`);
|
|
225
|
+
});
|
|
226
|
+
}
|
|
227
|
+
_upgradeHandler(request, socket, head, wss) {
|
|
228
|
+
const statusCode = this._validateAuth(request);
|
|
229
|
+
if (statusCode !== 200) {
|
|
230
|
+
const onSocketError = (error) => {
|
|
231
|
+
this._logger.error("Socket error", error);
|
|
232
|
+
socket.destroy();
|
|
233
|
+
};
|
|
234
|
+
socket.on("error", onSocketError);
|
|
235
|
+
socket.write(`HTTP/1.1 ${statusCode} ${STATUS_CODES[statusCode]}\r
|
|
236
|
+
\r
|
|
237
|
+
`);
|
|
238
|
+
socket.destroy();
|
|
239
|
+
socket.off("error", onSocketError);
|
|
240
|
+
return;
|
|
241
|
+
}
|
|
242
|
+
wss.handleUpgrade(request, socket, head, (ws) => {
|
|
243
|
+
const promise = this.#pool.acquire().catch(
|
|
244
|
+
/* coverage ignore next */
|
|
245
|
+
(error) => {
|
|
246
|
+
this._logger.error("Error acquiring connection for WebSocket:", error);
|
|
247
|
+
ws.close();
|
|
248
|
+
}
|
|
249
|
+
);
|
|
250
|
+
const release = () => void promise.then((connection) => connection && this.#pool.release(connection)).catch(this._catchError("Error releasing connection for WebSocket:"));
|
|
251
|
+
const send = (data) => {
|
|
252
|
+
const message = JSON.stringify(data);
|
|
253
|
+
ws.send(message, (error) => {
|
|
254
|
+
if (error) {
|
|
255
|
+
this._logger.error("Error sending WebSocket response:", error);
|
|
256
|
+
ws.close();
|
|
257
|
+
}
|
|
258
|
+
});
|
|
259
|
+
};
|
|
260
|
+
ws.on(
|
|
261
|
+
"error",
|
|
262
|
+
/* coverage ignore next */
|
|
263
|
+
(error) => {
|
|
264
|
+
this._logger.error("WebSocket error", error);
|
|
265
|
+
release();
|
|
266
|
+
}
|
|
267
|
+
);
|
|
268
|
+
ws.on("close", (code, reason) => {
|
|
269
|
+
const extra = reason.toString("utf-8");
|
|
270
|
+
extra ? this._logger.info(`WebSocket closed (${code}):`, extra) : this._logger.info(`WebSocket closed (${code}):`);
|
|
271
|
+
release();
|
|
272
|
+
});
|
|
273
|
+
ws.on("message", (data) => {
|
|
274
|
+
const now = process.hrtime.bigint();
|
|
275
|
+
const payload = this._validatePayload(data.toString("utf-8"));
|
|
276
|
+
if (!payload.valid) {
|
|
277
|
+
send({ id: payload.id, statusCode: 400, error: payload.error });
|
|
278
|
+
} else {
|
|
279
|
+
promise.then(async (connection) => {
|
|
280
|
+
if (!connection)
|
|
281
|
+
return;
|
|
282
|
+
try {
|
|
283
|
+
const result = await connection.query(payload.query, payload.params);
|
|
284
|
+
const ms = Math.floor(Number(process.hrtime.bigint() - now) / 1e4) / 100;
|
|
285
|
+
this._logger.info(`Handled "${result.command}" WebSocket request in ${ms} ms`);
|
|
286
|
+
return send({ ...result, statusCode: 200, id: payload.id });
|
|
287
|
+
} catch (error) {
|
|
288
|
+
return send({ id: payload.id, statusCode: 400, error: error.message });
|
|
289
|
+
}
|
|
290
|
+
}).catch(this._catchError("Error querying in websocket"));
|
|
291
|
+
}
|
|
292
|
+
});
|
|
293
|
+
});
|
|
294
|
+
}
|
|
295
|
+
/* ======================================================================== *
|
|
296
|
+
* INTERNALS *
|
|
297
|
+
* ======================================================================== */
|
|
298
|
+
/** Read the body of an HTTP request fully */
|
|
299
|
+
_readRequest(stream) {
|
|
300
|
+
return new Promise((resolve2, reject) => {
|
|
301
|
+
const buffers = [];
|
|
302
|
+
stream.on(
|
|
303
|
+
"error",
|
|
304
|
+
/* coverage ignore next */
|
|
305
|
+
(error) => reject(error)
|
|
306
|
+
);
|
|
307
|
+
stream.on("data", (buffer) => buffers.push(buffer));
|
|
308
|
+
stream.on("end", () => resolve2(Buffer.concat(buffers)));
|
|
309
|
+
if (stream.isPaused())
|
|
310
|
+
stream.resume();
|
|
311
|
+
}).then((buffer) => buffer.toString("utf-8"));
|
|
312
|
+
}
|
|
313
|
+
/** Parse a payload string as JSON and validate it */
|
|
314
|
+
_validatePayload(string) {
|
|
315
|
+
try {
|
|
316
|
+
const payload = JSON.parse(string || "{}");
|
|
317
|
+
const id = payload?.id ? `${payload.id}` : randomUUID();
|
|
318
|
+
if (!payload?.query) {
|
|
319
|
+
return { id, valid: false, error: "Invalid payload (or query missing)" };
|
|
320
|
+
}
|
|
321
|
+
if (typeof payload.query !== "string") {
|
|
322
|
+
return { id, valid: false, error: "Query is not a string" };
|
|
323
|
+
}
|
|
324
|
+
if (payload.params && !Array.isArray(payload.params)) {
|
|
325
|
+
return { id, valid: false, error: "Parameters are not an array" };
|
|
326
|
+
}
|
|
327
|
+
return { id, valid: true, query: payload.query, params: payload.params };
|
|
328
|
+
} catch (error) {
|
|
329
|
+
return { id: randomUUID(), valid: false, error: "Error parsing JSON" };
|
|
330
|
+
}
|
|
331
|
+
}
|
|
332
|
+
/** Validate a request (it must have an "auth" query parameter) */
|
|
333
|
+
_validateAuth(request) {
|
|
334
|
+
const auth = parseQueryString(request.url.split("?")[1] || "").auth;
|
|
335
|
+
if (typeof auth !== "string")
|
|
336
|
+
return 401;
|
|
337
|
+
try {
|
|
338
|
+
const token = verifyToken(auth, this.#secret);
|
|
339
|
+
if (token in this.#tokens) {
|
|
340
|
+
this._logger.error("Attempted to reuse an existing token");
|
|
341
|
+
return 403;
|
|
342
|
+
}
|
|
343
|
+
this.#tokens[token] = Date.now() + 6e4;
|
|
344
|
+
return 200;
|
|
345
|
+
} catch (error) {
|
|
346
|
+
this._logger.error(error);
|
|
347
|
+
return 403;
|
|
348
|
+
}
|
|
349
|
+
}
|
|
350
|
+
};
|
|
351
|
+
var Server = ServerImpl;
|
|
352
|
+
export {
|
|
353
|
+
Server
|
|
354
|
+
};
|
|
355
|
+
//# sourceMappingURL=server.mjs.map
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../src/server.ts"],
|
|
4
|
+
"mappings": "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",
|
|
5
|
+
"names": ["resolve", "now"]
|
|
6
|
+
}
|
package/dist/token.cjs
ADDED
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __create = Object.create;
|
|
3
|
+
var __defProp = Object.defineProperty;
|
|
4
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
5
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
6
|
+
var __getProtoOf = Object.getPrototypeOf;
|
|
7
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
8
|
+
var __export = (target, all) => {
|
|
9
|
+
for (var name in all)
|
|
10
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
11
|
+
};
|
|
12
|
+
var __copyProps = (to, from, except, desc) => {
|
|
13
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
14
|
+
for (let key of __getOwnPropNames(from))
|
|
15
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
16
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
17
|
+
}
|
|
18
|
+
return to;
|
|
19
|
+
};
|
|
20
|
+
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
|
|
21
|
+
// If the importer is in node compatibility mode or this is not an ESM
|
|
22
|
+
// file that has been converted to a CommonJS file using a Babel-
|
|
23
|
+
// compatible transform (i.e. "__esModule" has not been set), then set
|
|
24
|
+
// "default" to the CommonJS "module.exports" for node compatibility.
|
|
25
|
+
isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
|
|
26
|
+
mod
|
|
27
|
+
));
|
|
28
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
29
|
+
|
|
30
|
+
// token.ts
|
|
31
|
+
var token_exports = {};
|
|
32
|
+
__export(token_exports, {
|
|
33
|
+
verifyToken: () => verifyToken
|
|
34
|
+
});
|
|
35
|
+
module.exports = __toCommonJS(token_exports);
|
|
36
|
+
var import_node_assert = __toESM(require("node:assert"));
|
|
37
|
+
var import_node_crypto = require("node:crypto");
|
|
38
|
+
function verifyToken(token, secret) {
|
|
39
|
+
import_node_assert.default.strictEqual(token.length, 64, `Invalid encoded token length (${token.length} != 64)`);
|
|
40
|
+
const buffer = Buffer.from(token, "base64url");
|
|
41
|
+
import_node_assert.default.strictEqual(buffer.length, 48, `Invalid decoded token length (${buffer.length} != 48)`);
|
|
42
|
+
const timeDelta = buffer.readBigInt64LE(0) - BigInt(Date.now());
|
|
43
|
+
const absoluteDelta = timeDelta < 0n ? -timeDelta : timeDelta;
|
|
44
|
+
(0, import_node_assert.default)(absoluteDelta < 10000n, `Timestamp delta out of range (${timeDelta} ms)`);
|
|
45
|
+
const signature = (0, import_node_crypto.createHmac)("sha256", Buffer.from(secret, "utf8")).update(buffer.subarray(0, 16)).digest();
|
|
46
|
+
(0, import_node_assert.default)(signature.compare(buffer, 16) === 0, "Token signature mismatch");
|
|
47
|
+
return buffer.toString("hex", 0, 16).toLowerCase();
|
|
48
|
+
}
|
|
49
|
+
// Annotate the CommonJS export names for ESM import in node:
|
|
50
|
+
0 && (module.exports = {
|
|
51
|
+
verifyToken
|
|
52
|
+
});
|
|
53
|
+
//# sourceMappingURL=token.cjs.map
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../src/token.ts"],
|
|
4
|
+
"mappings": ";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,yBAAmB;AACnB,yBAA2B;AA6BpB,SAAS,YACZ,OACA,QACM;AACR,qBAAAA,QAAO,YAAY,MAAM,QAAQ,IAAI,iCAAiC,MAAM,MAAM,SAAS;AAE3F,QAAM,SAAS,OAAO,KAAK,OAAO,WAAW;AAC7C,qBAAAA,QAAO,YAAY,OAAO,QAAQ,IAAI,iCAAiC,OAAO,MAAM,SAAS;AAG7F,QAAM,YAAY,OAAO,eAAe,CAAC,IAAI,OAAO,KAAK,IAAI,CAAC;AAC9D,QAAM,gBAAgB,YAAY,KAAK,CAAC,YAAY;AACpD,yBAAAA,SAAO,gBAAgB,QAAS,iCAAiC,SAAS,MAAM;AAGhF,QAAM,gBAAY,+BAAW,UAAU,OAAO,KAAK,QAAQ,MAAM,CAAC,EAC7D,OAAO,OAAO,SAAS,GAAG,EAAE,CAAC,EAC7B,OAAO;AAGZ,yBAAAA,SAAO,UAAU,QAAQ,QAAQ,EAAE,MAAM,GAAG,0BAA0B;AACtE,SAAO,OAAO,SAAS,OAAO,GAAG,EAAE,EAAE,YAAY;AACnD;",
|
|
5
|
+
"names": ["assert"]
|
|
6
|
+
}
|
package/dist/token.d.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare function verifyToken(token: string, secret: string): string;
|
package/dist/token.mjs
ADDED
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
// token.ts
|
|
2
|
+
import assert from "node:assert";
|
|
3
|
+
import { createHmac } from "node:crypto";
|
|
4
|
+
function verifyToken(token, secret) {
|
|
5
|
+
assert.strictEqual(token.length, 64, `Invalid encoded token length (${token.length} != 64)`);
|
|
6
|
+
const buffer = Buffer.from(token, "base64url");
|
|
7
|
+
assert.strictEqual(buffer.length, 48, `Invalid decoded token length (${buffer.length} != 48)`);
|
|
8
|
+
const timeDelta = buffer.readBigInt64LE(0) - BigInt(Date.now());
|
|
9
|
+
const absoluteDelta = timeDelta < 0n ? -timeDelta : timeDelta;
|
|
10
|
+
assert(absoluteDelta < 10000n, `Timestamp delta out of range (${timeDelta} ms)`);
|
|
11
|
+
const signature = createHmac("sha256", Buffer.from(secret, "utf8")).update(buffer.subarray(0, 16)).digest();
|
|
12
|
+
assert(signature.compare(buffer, 16) === 0, "Token signature mismatch");
|
|
13
|
+
return buffer.toString("hex", 0, 16).toLowerCase();
|
|
14
|
+
}
|
|
15
|
+
export {
|
|
16
|
+
verifyToken
|
|
17
|
+
};
|
|
18
|
+
//# sourceMappingURL=token.mjs.map
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../src/token.ts"],
|
|
4
|
+
"mappings": ";AAAA,OAAO,YAAY;AACnB,SAAS,kBAAkB;AA6BpB,SAAS,YACZ,OACA,QACM;AACR,SAAO,YAAY,MAAM,QAAQ,IAAI,iCAAiC,MAAM,MAAM,SAAS;AAE3F,QAAM,SAAS,OAAO,KAAK,OAAO,WAAW;AAC7C,SAAO,YAAY,OAAO,QAAQ,IAAI,iCAAiC,OAAO,MAAM,SAAS;AAG7F,QAAM,YAAY,OAAO,eAAe,CAAC,IAAI,OAAO,KAAK,IAAI,CAAC;AAC9D,QAAM,gBAAgB,YAAY,KAAK,CAAC,YAAY;AACpD,SAAO,gBAAgB,QAAS,iCAAiC,SAAS,MAAM;AAGhF,QAAM,YAAY,WAAW,UAAU,OAAO,KAAK,QAAQ,MAAM,CAAC,EAC7D,OAAO,OAAO,SAAS,GAAG,EAAE,CAAC,EAC7B,OAAO;AAGZ,SAAO,UAAU,QAAQ,QAAQ,EAAE,MAAM,GAAG,0BAA0B;AACtE,SAAO,OAAO,SAAS,OAAO,GAAG,EAAE,EAAE,YAAY;AACnD;",
|
|
5
|
+
"names": []
|
|
6
|
+
}
|
package/package.json
ADDED
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@juit/pgproxy-server",
|
|
3
|
+
"version": "1.0.0",
|
|
4
|
+
"main": "./dist/index.cjs",
|
|
5
|
+
"module": "./dist/index.mjs",
|
|
6
|
+
"types": "./dist/index.d.ts",
|
|
7
|
+
"exports": {
|
|
8
|
+
".": {
|
|
9
|
+
"require": {
|
|
10
|
+
"types": "./dist/index.d.ts",
|
|
11
|
+
"default": "./dist/index.cjs"
|
|
12
|
+
},
|
|
13
|
+
"import": {
|
|
14
|
+
"types": "./dist/index.d.ts",
|
|
15
|
+
"default": "./dist/index.mjs"
|
|
16
|
+
}
|
|
17
|
+
}
|
|
18
|
+
},
|
|
19
|
+
"author": "Juit Developers <developers@juit.com>",
|
|
20
|
+
"license": "Apache-2.0",
|
|
21
|
+
"repository": {
|
|
22
|
+
"type": "git",
|
|
23
|
+
"url": "git+ssh://git@github.com/juitnow/juit-pgproxy.git"
|
|
24
|
+
},
|
|
25
|
+
"keywords": [
|
|
26
|
+
"database",
|
|
27
|
+
"pg",
|
|
28
|
+
"pool",
|
|
29
|
+
"postgres",
|
|
30
|
+
"proxy"
|
|
31
|
+
],
|
|
32
|
+
"bugs": {
|
|
33
|
+
"url": "https://github.com/juitnow/juit-pgproxy/issues"
|
|
34
|
+
},
|
|
35
|
+
"homepage": "https://github.com/juitnow/juit-pgproxy#readme",
|
|
36
|
+
"dependencies": {
|
|
37
|
+
"@juit/pgproxy-pool": "^1.0.0",
|
|
38
|
+
"ws": "^8.15.1"
|
|
39
|
+
},
|
|
40
|
+
"directories": {
|
|
41
|
+
"test": "test"
|
|
42
|
+
},
|
|
43
|
+
"files": [
|
|
44
|
+
"*.md",
|
|
45
|
+
"dist/",
|
|
46
|
+
"src/"
|
|
47
|
+
]
|
|
48
|
+
}
|
package/src/index.ts
ADDED
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import type { ConnectionQueryResult } from '@juit/pgproxy-pool'
|
|
2
|
+
|
|
3
|
+
export * from './server'
|
|
4
|
+
|
|
5
|
+
export interface Request {
|
|
6
|
+
id: string,
|
|
7
|
+
query: string,
|
|
8
|
+
params?: (string | null)[],
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
export interface PositiveResponse extends ConnectionQueryResult {
|
|
12
|
+
statusCode: 200,
|
|
13
|
+
error?: never,
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
export type NegativeResponse = {
|
|
17
|
+
[ key in keyof ConnectionQueryResult ]?: never
|
|
18
|
+
} & {
|
|
19
|
+
statusCode: 400 | 500,
|
|
20
|
+
error: string,
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
export type Response = {
|
|
24
|
+
id: string,
|
|
25
|
+
} & ( PositiveResponse | NegativeResponse )
|