@jamesmddoyle/phantom 0.1.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.
Files changed (54) hide show
  1. package/dist/cli.d.ts +7 -0
  2. package/dist/cli.d.ts.map +1 -0
  3. package/dist/cli.js +24 -0
  4. package/dist/cli.js.map +1 -0
  5. package/dist/config.d.ts +16 -0
  6. package/dist/config.d.ts.map +1 -0
  7. package/dist/config.js +46 -0
  8. package/dist/config.js.map +1 -0
  9. package/dist/dashboard-ui/_app/env.js +1 -0
  10. package/dist/dashboard-ui/_app/immutable/assets/0.qdgu5uXf.css +1 -0
  11. package/dist/dashboard-ui/_app/immutable/assets/2.NbOPcGNK.css +1 -0
  12. package/dist/dashboard-ui/_app/immutable/assets/index.BkcWggqo.css +1 -0
  13. package/dist/dashboard-ui/_app/immutable/chunks/BWM6cuy1.js +1 -0
  14. package/dist/dashboard-ui/_app/immutable/chunks/BfCPr1xz.js +1 -0
  15. package/dist/dashboard-ui/_app/immutable/chunks/Bj1t19nj.js +1 -0
  16. package/dist/dashboard-ui/_app/immutable/chunks/CG6hkJ2r.js +4 -0
  17. package/dist/dashboard-ui/_app/immutable/chunks/DHt6uv_5.js +1 -0
  18. package/dist/dashboard-ui/_app/immutable/chunks/DUglripS.js +2 -0
  19. package/dist/dashboard-ui/_app/immutable/chunks/Mkbhf_NF.js +1 -0
  20. package/dist/dashboard-ui/_app/immutable/entry/app.C0Uz1Yok.js +2 -0
  21. package/dist/dashboard-ui/_app/immutable/entry/start.qmYEGFx1.js +1 -0
  22. package/dist/dashboard-ui/_app/immutable/nodes/0.CnuSotPZ.js +1 -0
  23. package/dist/dashboard-ui/_app/immutable/nodes/1.U9Wsfz4H.js +1 -0
  24. package/dist/dashboard-ui/_app/immutable/nodes/2.wYRnMaww.js +1 -0
  25. package/dist/dashboard-ui/_app/version.json +1 -0
  26. package/dist/dashboard-ui/index.html +40 -0
  27. package/dist/dashboard-ui/phantom.svg +3 -0
  28. package/dist/dashboard-ui/robots.txt +3 -0
  29. package/dist/index.d.ts +5 -0
  30. package/dist/index.d.ts.map +1 -0
  31. package/dist/index.js +172 -0
  32. package/dist/index.js.map +1 -0
  33. package/dist/package.json +27 -0
  34. package/dist/parser.d.ts +45 -0
  35. package/dist/parser.d.ts.map +1 -0
  36. package/dist/parser.js +143 -0
  37. package/dist/parser.js.map +1 -0
  38. package/dist/responder.d.ts +14 -0
  39. package/dist/responder.d.ts.map +1 -0
  40. package/dist/responder.js +54 -0
  41. package/dist/responder.js.map +1 -0
  42. package/dist/router.d.ts +13 -0
  43. package/dist/router.d.ts.map +1 -0
  44. package/dist/router.js +61 -0
  45. package/dist/router.js.map +1 -0
  46. package/dist/static.d.ts +7 -0
  47. package/dist/static.d.ts.map +1 -0
  48. package/dist/static.js +39 -0
  49. package/dist/static.js.map +1 -0
  50. package/dist/ws.d.ts +16 -0
  51. package/dist/ws.d.ts.map +1 -0
  52. package/dist/ws.js +68 -0
  53. package/dist/ws.js.map +1 -0
  54. package/package.json +27 -0
package/dist/ws.d.ts ADDED
@@ -0,0 +1,16 @@
1
+ import type { Socket } from "node:net";
2
+ import type { MockRequest } from "./parser.ts";
3
+ export declare function handleWebSocketHandshake(socket: Socket, request: MockRequest): void;
4
+ /**
5
+ * Wraps a string in a WebSocket text frame (RFC 6455).
6
+ */
7
+ export declare function encodeWsFrame(dataString: string): Buffer;
8
+ /**
9
+ * Broadcasts a message to all connected WebSocket clients.
10
+ */
11
+ export declare function broadcast(clients: Map<string, Socket>, message: any): void;
12
+ /**
13
+ * Starts a heartbeat interval to keep WebSocket connections alive.
14
+ */
15
+ export declare function startHeartbeat(clients: Map<string, Socket>): void;
16
+ //# sourceMappingURL=ws.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ws.d.ts","sourceRoot":"","sources":["../ws.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,UAAU,CAAC;AACvC,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAG/C,wBAAgB,wBAAwB,CAAC,MAAM,EAAE,MAAM,EAAE,OAAO,EAAE,WAAW,QAyB5E;AAED;;GAEG;AACH,wBAAgB,aAAa,CAAC,UAAU,EAAE,MAAM,GAAG,MAAM,CAuBxD;AAED;;GAEG;AACH,wBAAgB,SAAS,CAAC,OAAO,EAAE,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,EAAE,OAAO,EAAE,GAAG,QAKnE;AAED;;GAEG;AACH,wBAAgB,cAAc,CAAC,OAAO,EAAE,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,QAM1D"}
package/dist/ws.js ADDED
@@ -0,0 +1,68 @@
1
+ import { createHash } from "node:crypto";
2
+ export function handleWebSocketHandshake(socket, request) {
3
+ const key = request.headers["sec-websocket-key"];
4
+ if (!key) {
5
+ socket.write("HTTP/1.1 400 Bad Request\r\n\r\n");
6
+ socket.destroy();
7
+ return;
8
+ }
9
+ const MAGIC_STRING = "258EAFA5-E914-47DA-95CA-C5AB0DC85B11";
10
+ const acceptKey = createHash("sha1")
11
+ .update(key + MAGIC_STRING)
12
+ .digest("base64");
13
+ const response = [
14
+ "HTTP/1.1 101 Switching Protocols",
15
+ "Upgrade: websocket",
16
+ "Connection: Upgrade",
17
+ `Sec-WebSocket-Accept: ${acceptKey}`,
18
+ "", // Empty line boundary
19
+ "",
20
+ ].join("\r\n");
21
+ socket.write(response);
22
+ }
23
+ /**
24
+ * Wraps a string in a WebSocket text frame (RFC 6455).
25
+ */
26
+ export function encodeWsFrame(dataString) {
27
+ const payload = Buffer.from(dataString, "utf-8");
28
+ const length = payload.length;
29
+ let header;
30
+ if (length <= 125) {
31
+ header = Buffer.alloc(2);
32
+ header[0] = 0x81; // 10000001
33
+ header[1] = length;
34
+ }
35
+ else if (length <= 65535) {
36
+ header = Buffer.alloc(4);
37
+ header[0] = 0x81;
38
+ header[1] = 126;
39
+ header.writeUInt16BE(length, 2);
40
+ }
41
+ else {
42
+ header = Buffer.alloc(10);
43
+ header[0] = 0x81;
44
+ header[1] = 127;
45
+ header.writeBigUInt64BE(BigInt(length), 2);
46
+ }
47
+ return Buffer.concat([header, payload]);
48
+ }
49
+ /**
50
+ * Broadcasts a message to all connected WebSocket clients.
51
+ */
52
+ export function broadcast(clients, message) {
53
+ const frame = encodeWsFrame(JSON.stringify(message));
54
+ for (const socket of clients.values()) {
55
+ socket.write(frame);
56
+ }
57
+ }
58
+ /**
59
+ * Starts a heartbeat interval to keep WebSocket connections alive.
60
+ */
61
+ export function startHeartbeat(clients) {
62
+ setInterval(() => {
63
+ if (clients.size === 0)
64
+ return;
65
+ broadcast(clients, { type: "PING", timestamp: Date.now() });
66
+ }, 30000);
67
+ }
68
+ //# sourceMappingURL=ws.js.map
package/dist/ws.js.map ADDED
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ws.js","sourceRoot":"","sources":["../ws.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AAEzC,MAAM,UAAU,wBAAwB,CAAC,MAAc,EAAE,OAAoB;IAC3E,MAAM,GAAG,GAAG,OAAO,CAAC,OAAO,CAAC,mBAAmB,CAAC,CAAC;IAEjD,IAAI,CAAC,GAAG,EAAE,CAAC;QACT,MAAM,CAAC,KAAK,CAAC,kCAAkC,CAAC,CAAC;QACjD,MAAM,CAAC,OAAO,EAAE,CAAC;QACjB,OAAO;IACT,CAAC;IAED,MAAM,YAAY,GAAG,sCAAsC,CAAC;IAE5D,MAAM,SAAS,GAAG,UAAU,CAAC,MAAM,CAAC;SACjC,MAAM,CAAC,GAAG,GAAG,YAAY,CAAC;SAC1B,MAAM,CAAC,QAAQ,CAAC,CAAC;IAEpB,MAAM,QAAQ,GAAG;QACf,kCAAkC;QAClC,oBAAoB;QACpB,qBAAqB;QACrB,yBAAyB,SAAS,EAAE;QACpC,EAAE,EAAE,sBAAsB;QAC1B,EAAE;KACH,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;IAEf,MAAM,CAAC,KAAK,CAAC,QAAQ,CAAC,CAAC;AACzB,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,aAAa,CAAC,UAAkB;IAC9C,MAAM,OAAO,GAAG,MAAM,CAAC,IAAI,CAAC,UAAU,EAAE,OAAO,CAAC,CAAC;IACjD,MAAM,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC;IAE9B,IAAI,MAAc,CAAC;IAEnB,IAAI,MAAM,IAAI,GAAG,EAAE,CAAC;QAClB,MAAM,GAAG,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;QACzB,MAAM,CAAC,CAAC,CAAC,GAAG,IAAI,CAAC,CAAC,WAAW;QAC7B,MAAM,CAAC,CAAC,CAAC,GAAG,MAAM,CAAC;IACrB,CAAC;SAAM,IAAI,MAAM,IAAI,KAAK,EAAE,CAAC;QAC3B,MAAM,GAAG,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;QACzB,MAAM,CAAC,CAAC,CAAC,GAAG,IAAI,CAAC;QACjB,MAAM,CAAC,CAAC,CAAC,GAAG,GAAG,CAAC;QAChB,MAAM,CAAC,aAAa,CAAC,MAAM,EAAE,CAAC,CAAC,CAAC;IAClC,CAAC;SAAM,CAAC;QACN,MAAM,GAAG,MAAM,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC;QAC1B,MAAM,CAAC,CAAC,CAAC,GAAG,IAAI,CAAC;QACjB,MAAM,CAAC,CAAC,CAAC,GAAG,GAAG,CAAC;QAChB,MAAM,CAAC,gBAAgB,CAAC,MAAM,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC,CAAC;IAC7C,CAAC;IAED,OAAO,MAAM,CAAC,MAAM,CAAC,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,CAAC;AAC1C,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,SAAS,CAAC,OAA4B,EAAE,OAAY;IAClE,MAAM,KAAK,GAAG,aAAa,CAAC,IAAI,CAAC,SAAS,CAAC,OAAO,CAAC,CAAC,CAAC;IACrD,KAAK,MAAM,MAAM,IAAI,OAAO,CAAC,MAAM,EAAE,EAAE,CAAC;QACtC,MAAM,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC;IACtB,CAAC;AACH,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,cAAc,CAAC,OAA4B;IACzD,WAAW,CAAC,GAAG,EAAE;QACf,IAAI,OAAO,CAAC,IAAI,KAAK,CAAC;YAAE,OAAO;QAE/B,SAAS,CAAC,OAAO,EAAE,EAAE,IAAI,EAAE,MAAM,EAAE,SAAS,EAAE,IAAI,CAAC,GAAG,EAAE,EAAE,CAAC,CAAC;IAC9D,CAAC,EAAE,KAAK,CAAC,CAAC;AACZ,CAAC"}
package/package.json ADDED
@@ -0,0 +1,27 @@
1
+ {
2
+ "name": "@jamesmddoyle/phantom",
3
+ "version": "0.1.0",
4
+ "description": "API mocker and traffic inspector with a built-in dashboard.",
5
+ "author": "James Doyle",
6
+ "license": "MIT",
7
+ "bin": {
8
+ "phantom": "./dist/index.js"
9
+ },
10
+ "files": [
11
+ "dist"
12
+ ],
13
+ "type": "module",
14
+ "scripts": {
15
+ "build": "tsc && cp package.json ./dist/ && cp -r ../dashboard/build ./dist/dashboard-ui",
16
+ "dev": "node --watch --experimental-strip-types index.ts",
17
+ "test": "vitest run"
18
+ },
19
+ "devDependencies": {
20
+ "@types/node": "^25.3.0",
21
+ "typescript": "^5.9.3",
22
+ "vitest": "^4.0.18"
23
+ },
24
+ "dependencies": {
25
+ "cac": "^7.0.0"
26
+ }
27
+ }