@sockethub/server 5.0.0-alpha.3 → 5.0.0-alpha.6

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 (127) hide show
  1. package/README.md +54 -60
  2. package/bin/sockethub +4 -3
  3. package/package.json +42 -60
  4. package/res/socket.io.js +4908 -0
  5. package/res/sockethub-client.js +602 -0
  6. package/res/sockethub-client.min.js +19 -0
  7. package/sockethub.config.example.json +2 -3
  8. package/src/bootstrap/init.d.ts +20 -7
  9. package/src/bootstrap/init.test.ts +211 -0
  10. package/src/bootstrap/init.ts +152 -75
  11. package/src/bootstrap/load-platforms.ts +151 -0
  12. package/src/config.test.ts +27 -22
  13. package/src/config.ts +82 -78
  14. package/src/defaults.json +24 -16
  15. package/src/index.ts +67 -27
  16. package/src/janitor.test.ts +211 -0
  17. package/src/janitor.ts +145 -77
  18. package/src/listener.ts +151 -57
  19. package/src/middleware/create-activity-object.test.ts +28 -8
  20. package/src/middleware/create-activity-object.ts +17 -8
  21. package/src/middleware/expand-activity-stream.test.data.ts +332 -346
  22. package/src/middleware/expand-activity-stream.test.ts +65 -66
  23. package/src/middleware/expand-activity-stream.ts +29 -19
  24. package/src/middleware/store-credentials.test.ts +74 -62
  25. package/src/middleware/store-credentials.ts +15 -15
  26. package/src/middleware/validate.test.data.ts +240 -242
  27. package/src/middleware/validate.test.ts +39 -78
  28. package/src/middleware/validate.ts +63 -39
  29. package/src/middleware.test.ts +168 -138
  30. package/src/middleware.ts +62 -43
  31. package/src/platform-instance.test.ts +507 -213
  32. package/src/platform-instance.ts +337 -219
  33. package/src/platform.test.ts +375 -0
  34. package/src/platform.ts +306 -139
  35. package/src/process-manager.ts +75 -51
  36. package/src/routes.test.ts +43 -89
  37. package/src/routes.ts +40 -77
  38. package/src/sentry.test.ts +106 -0
  39. package/src/sentry.ts +19 -0
  40. package/src/sockethub.ts +186 -153
  41. package/src/util.ts +5 -0
  42. package/coverage/tmp/coverage-93126-1649152190997-0.json +0 -1
  43. package/dist/bootstrap/init.d.ts +0 -18
  44. package/dist/bootstrap/init.js +0 -63
  45. package/dist/bootstrap/init.js.map +0 -1
  46. package/dist/bootstrap/platforms.js +0 -75
  47. package/dist/common.d.ts +0 -3
  48. package/dist/common.js +0 -20
  49. package/dist/common.js.map +0 -1
  50. package/dist/config.d.ts +0 -6
  51. package/dist/config.js +0 -102
  52. package/dist/config.js.map +0 -1
  53. package/dist/crypto.d.ts +0 -10
  54. package/dist/crypto.js +0 -38
  55. package/dist/crypto.js.map +0 -1
  56. package/dist/defaults.json +0 -28
  57. package/dist/index.d.ts +0 -2
  58. package/dist/index.js +0 -25
  59. package/dist/index.js.map +0 -1
  60. package/dist/janitor.d.ts +0 -15
  61. package/dist/janitor.js +0 -89
  62. package/dist/janitor.js.map +0 -1
  63. package/dist/listener.d.ts +0 -28
  64. package/dist/listener.js +0 -91
  65. package/dist/listener.js.map +0 -1
  66. package/dist/middleware/create-activity-object.d.ts +0 -6
  67. package/dist/middleware/create-activity-object.js +0 -19
  68. package/dist/middleware/create-activity-object.js.map +0 -1
  69. package/dist/middleware/expand-activity-stream.d.ts +0 -2
  70. package/dist/middleware/expand-activity-stream.js +0 -33
  71. package/dist/middleware/expand-activity-stream.js.map +0 -1
  72. package/dist/middleware/expand-activity-stream.test.data.d.ts +0 -480
  73. package/dist/middleware/expand-activity-stream.test.data.js +0 -360
  74. package/dist/middleware/expand-activity-stream.test.data.js.map +0 -1
  75. package/dist/middleware/store-credentials.d.ts +0 -3
  76. package/dist/middleware/store-credentials.js +0 -19
  77. package/dist/middleware/store-credentials.js.map +0 -1
  78. package/dist/middleware/validate.d.ts +0 -2
  79. package/dist/middleware/validate.js +0 -58
  80. package/dist/middleware/validate.js.map +0 -1
  81. package/dist/middleware/validate.test.data.d.ts +0 -532
  82. package/dist/middleware/validate.test.data.js +0 -263
  83. package/dist/middleware/validate.test.data.js.map +0 -1
  84. package/dist/middleware.d.ts +0 -10
  85. package/dist/middleware.js +0 -54
  86. package/dist/middleware.js.map +0 -1
  87. package/dist/platform-instance.d.ts +0 -77
  88. package/dist/platform-instance.js +0 -211
  89. package/dist/platform-instance.js.map +0 -1
  90. package/dist/platform.d.ts +0 -6
  91. package/dist/platform.js +0 -187
  92. package/dist/platform.js.map +0 -1
  93. package/dist/process-manager.d.ts +0 -11
  94. package/dist/process-manager.js +0 -78
  95. package/dist/process-manager.js.map +0 -1
  96. package/dist/routes.d.ts +0 -13
  97. package/dist/routes.js +0 -83
  98. package/dist/routes.js.map +0 -1
  99. package/dist/sockethub.d.ts +0 -39
  100. package/dist/sockethub.js +0 -119
  101. package/dist/sockethub.js.map +0 -1
  102. package/dist/store.d.ts +0 -5
  103. package/dist/store.js +0 -17
  104. package/dist/store.js.map +0 -1
  105. package/src/bootstrap/platforms.js +0 -75
  106. package/src/common.test.ts +0 -54
  107. package/src/common.ts +0 -14
  108. package/src/config.d.ts +0 -2
  109. package/src/crypto.d.ts +0 -5
  110. package/src/crypto.test.ts +0 -41
  111. package/src/crypto.ts +0 -41
  112. package/src/janitor.d.ts +0 -8
  113. package/src/middleware/validate.d.ts +0 -1
  114. package/src/middleware.d.ts +0 -21
  115. package/src/sockethub.d.ts +0 -1
  116. package/src/store.test.ts +0 -28
  117. package/src/store.ts +0 -17
  118. package/test/init-suite.js +0 -41
  119. package/test/queue.functional.test.js +0 -0
  120. package/test/sockethub-suite.js +0 -25
  121. package/tsconfig.json +0 -18
  122. package/views/examples/dummy.ejs +0 -93
  123. package/views/examples/feeds.ejs +0 -90
  124. package/views/examples/irc.ejs +0 -239
  125. package/views/examples/shared.js +0 -72
  126. package/views/examples/xmpp.ejs +0 -191
  127. package/views/index.ejs +0 -17
package/src/listener.ts CHANGED
@@ -1,13 +1,18 @@
1
- import debug from 'debug';
2
- import bodyParser from 'body-parser';
3
- import express from 'express';
4
- import * as HTTP from 'http';
5
- import { Server } from 'socket.io';
1
+ import { existsSync, writeFileSync } from "node:fs";
2
+ import * as HTTP from "node:http";
3
+ import { createRequire } from "node:module";
4
+ import path from "node:path";
5
+ import bodyParser from "body-parser";
6
+ import debug from "debug";
7
+ import express from "express";
8
+ import rateLimit from "express-rate-limit";
9
+ import { Server } from "socket.io";
6
10
 
7
- import config from './config';
8
- import routes from './routes';
11
+ import config from "./config.js";
12
+ import routes from "./routes.js";
13
+ const require = createRequire(import.meta.url);
9
14
 
10
- const log = debug('sockethub:server:listener');
15
+ const log = debug("sockethub:server:listener");
11
16
 
12
17
  /**
13
18
  * Handles the initialization and access of Sockethub resources.
@@ -17,63 +22,152 @@ const log = debug('sockethub:server:listener');
17
22
  * - Socket.io (bidirectional websocket communication)
18
23
  */
19
24
  class Listener {
20
- io: Server;
21
- http: HTTP.Server;
22
-
23
- /**
24
- * Starts the services needed for Sockethub to operate. After this command completes,
25
- * the `http` and `io` class properties will be set.
26
- */
27
- start() {
28
- // initialize express and socket.io objects
29
- const app = Listener.initExpress();
30
- this.http = new HTTP.Server(app);
31
- this.io = new Server(this.http, {
32
- path: config.get('sockethub:path'),
33
- cors: {
34
- origin: "*",
35
- methods: [ "GET", "POST" ]
36
- }
37
- });
38
- routes.setup(app);
39
- this.startHttp();
40
- }
41
-
42
- private startHttp() {
43
- this.http.listen(config.get('sockethub:port'), config.get('sockethub:host'), () => {
44
- log(`sockethub listening on ` +
45
- `http://${config.get('sockethub:host')}:${config.get('sockethub:port')}`);
46
- });
47
- };
48
-
49
- private static initExpress() {
50
- let app = express();
51
- // templating engines
52
- app.set('view engine', 'ejs');
53
- // use bodyParser
54
- app.use(bodyParser.urlencoded({extended: true}));
55
- app.use(bodyParser.json());
56
- return app;
57
- }
25
+ io: Server;
26
+ http: HTTP.Server;
27
+
28
+ /**
29
+ * Starts the services needed for Sockethub to operate. After this command completes,
30
+ * the `http` and `io` class properties will be set.
31
+ */
32
+ start() {
33
+ // initialize express and socket.io objects
34
+ const app = Listener.initExpress();
35
+ this.http = new HTTP.Server(app);
36
+ this.io = new Server(this.http, {
37
+ path: config.get("sockethub:path") as string,
38
+ cors: {
39
+ origin: "*",
40
+ methods: ["GET", "POST"],
41
+ },
42
+ });
43
+
44
+ routes.setup(app);
45
+
46
+ if (config.get("examples")) {
47
+ this.addExamplesRoutes(app);
48
+ }
49
+
50
+ this.startHttp();
51
+ }
52
+
53
+ /**
54
+ * Resolves the path to the examples static files from @sockethub/examples package.
55
+ * Returns null if the package is not installed.
56
+ */
57
+ private resolveExamplesPath(): string | null {
58
+ try {
59
+ const examplesPkgPath = require.resolve(
60
+ "@sockethub/examples/package.json",
61
+ );
62
+ const examplesDir = path.join(
63
+ path.dirname(examplesPkgPath),
64
+ "build",
65
+ );
66
+ if (existsSync(examplesDir)) {
67
+ log(
68
+ `examples resolved from @sockethub/examples: ${examplesDir}`,
69
+ );
70
+ return examplesDir;
71
+ }
72
+ log(
73
+ `@sockethub/examples found but build directory missing: ${examplesDir}`,
74
+ );
75
+ return null;
76
+ } catch {
77
+ return null;
78
+ }
79
+ }
80
+
81
+ private addExamplesRoutes(app) {
82
+ const examplesPath = this.resolveExamplesPath();
83
+
84
+ if (!examplesPath) {
85
+ console.error(
86
+ "\n❌ Error: --examples flag requires @sockethub/examples package\n\n" +
87
+ "The examples package is not installed. To use the examples feature, install it:\n\n" +
88
+ " bun add @sockethub/examples\n\n" +
89
+ "Or run sockethub without the --examples flag.\n",
90
+ );
91
+ process.exit(1);
92
+ }
93
+
94
+ // Set up rate limiter to prevent DoS attacks on file system access
95
+ const limiter = rateLimit({
96
+ windowMs: 1 * 60 * 1000, // 1 minute
97
+ max: 60, // max 60 requests per windowMs
98
+ standardHeaders: true,
99
+ legacyHeaders: false,
100
+ });
101
+
102
+ // Write runtime config for the examples app
103
+ writeFileSync(
104
+ path.join(examplesPath, "config.json"),
105
+ JSON.stringify({
106
+ sockethub: config.get("sockethub"),
107
+ public: config.get("public"),
108
+ }),
109
+ );
110
+
111
+ app.use(express.static(examplesPath));
112
+
113
+ const examplesIndex = path.join(examplesPath, "index.html");
114
+ app.get("*", limiter, (req, res) => {
115
+ res.sendFile(examplesIndex);
116
+ });
117
+
118
+ log(
119
+ `examples served at http://${config.get("sockethub:host")}:${config.get(
120
+ "sockethub:port",
121
+ )}`,
122
+ );
123
+ }
124
+
125
+ private startHttp() {
126
+ this.http.listen(
127
+ config.get("sockethub:port"),
128
+ config.get("sockethub:host") as number,
129
+ () => {
130
+ log(
131
+ `sockethub listening on ws://${config.get("sockethub:host")}:${config.get(
132
+ "sockethub:port",
133
+ )}`,
134
+ );
135
+ },
136
+ );
137
+ }
138
+
139
+ private static initExpress() {
140
+ const app = express();
141
+ // templating engines
142
+ app.set("view engine", "ejs");
143
+ // use bodyParser
144
+ app.use(bodyParser.urlencoded({ extended: true }));
145
+ app.use(bodyParser.json());
146
+ return app;
147
+ }
58
148
  }
59
149
 
60
150
  const listener = new Listener();
61
151
 
152
+ interface EmitFunction {
153
+ (type: string, data: unknown);
154
+ }
155
+
62
156
  export interface SocketInstance {
63
- id: string;
64
- emit: Function;
157
+ id: string;
158
+ emit: EmitFunction;
65
159
  }
66
160
 
67
161
  export async function getSocket(sessionId: string): Promise<SocketInstance> {
68
- const sockets: Array<SocketInstance> = await listener.io.fetchSockets();
69
- return new Promise((resolve, reject) => {
70
- for (let socket of sockets) {
71
- if (sessionId === socket.id) {
72
- return resolve(socket);
73
- }
74
- }
75
- return reject(`unable to find socket for sessionId ${sessionId}`);
76
- });
162
+ const sockets: Array<SocketInstance> = await listener.io.fetchSockets();
163
+ return new Promise((resolve, reject) => {
164
+ for (const socket of sockets) {
165
+ if (sessionId === socket.id) {
166
+ return resolve(socket);
167
+ }
168
+ }
169
+ return reject(`unable to find socket for sessionId ${sessionId}`);
170
+ });
77
171
  }
78
172
 
79
173
  export default listener;
@@ -1,10 +1,30 @@
1
- import createActivityObject from "./create-activity-object";
1
+ import { describe, expect, it } from "bun:test";
2
+ import createActivityObject from "./create-activity-object.js";
2
3
 
3
- describe('Middleware: createActivityObject', () => {
4
- it('Calls activity.Object.create with incoming data', (done) => {
5
- // @ts-ignore
6
- createActivityObject({foo: 'bar'}, (msg) => {
7
- done();
4
+ describe("Middleware: createActivityObject", () => {
5
+ it("Calls activity.Object.create and fails with invalid property", async () => {
6
+ expect(() => {
7
+ createActivityObject({ foo: "bar" }, (o) => {
8
+ expect(o).not.toEqual({ foo: "bar" });
9
+ });
10
+ }).toThrow("ActivityStreams validation failed: the \"object\" property requires an 'id' property. Example: { id: \"user@example.com\", type: \"person\" }");
8
11
  });
9
- });
10
- });
12
+ it("Calls activity.Object.create with incoming data", async () => {
13
+ createActivityObject(
14
+ {
15
+ id: "test",
16
+ context: "foo",
17
+ type: "bar",
18
+ content: "some text",
19
+ },
20
+ (o) => {
21
+ expect(o).toEqual({
22
+ id: "test",
23
+ context: "foo",
24
+ type: "bar",
25
+ content: "some text",
26
+ });
27
+ },
28
+ );
29
+ });
30
+ });
@@ -1,13 +1,22 @@
1
- import ActivityStreams from '@sockethub/activity-streams';
2
- import config from "../config";
3
- const activity = ActivityStreams(config.get('activity-streams:opts'));
1
+ import { ASFactory } from "@sockethub/activity-streams";
2
+ import type { ActivityObject } from "@sockethub/schemas";
3
+
4
+ import config from "../config.js";
5
+ import type { MiddlewareChainInterface } from "../middleware.js";
6
+
7
+ const activity = ASFactory(
8
+ config.get("packageConfig:@sockethub/activity-streams"),
9
+ );
4
10
 
5
11
  /**
6
- * A simple middleware wrapper for the activity-streams Object.create method.
12
+ * A simple middleware wrapper for the activity-streams `Object.create` method.
7
13
  * @param obj
8
14
  * @param done
9
15
  */
10
- export default function createActivityObject(obj: any, done: Function) {
11
- activity.Object.create(obj);
12
- done(obj);
13
- }
16
+ export default function createActivityObject(
17
+ obj: ActivityObject,
18
+ done: MiddlewareChainInterface,
19
+ ) {
20
+ activity.Object.create(obj);
21
+ done(obj);
22
+ }