@sockethub/server 5.0.0-alpha.10
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/LICENSE +165 -0
- package/README.md +130 -0
- package/bin/sockethub +4 -0
- package/dist/defaults.json +36 -0
- package/dist/index.js +166465 -0
- package/dist/index.js.map +1877 -0
- package/dist/platform.js +103625 -0
- package/dist/platform.js.map +1435 -0
- package/package.json +100 -0
- package/res/socket.io.js +4908 -0
- package/res/sockethub-client.js +631 -0
- package/res/sockethub-client.min.js +19 -0
- package/src/bootstrap/init.d.ts +21 -0
- package/src/bootstrap/init.test.ts +211 -0
- package/src/bootstrap/init.ts +160 -0
- package/src/bootstrap/load-platforms.ts +151 -0
- package/src/config.test.ts +33 -0
- package/src/config.ts +98 -0
- package/src/defaults.json +36 -0
- package/src/index.ts +68 -0
- package/src/janitor.test.ts +211 -0
- package/src/janitor.ts +157 -0
- package/src/listener.ts +173 -0
- package/src/middleware/create-activity-object.test.ts +30 -0
- package/src/middleware/create-activity-object.ts +22 -0
- package/src/middleware/expand-activity-stream.test.data.ts +351 -0
- package/src/middleware/expand-activity-stream.test.ts +77 -0
- package/src/middleware/expand-activity-stream.ts +37 -0
- package/src/middleware/store-credentials.test.ts +85 -0
- package/src/middleware/store-credentials.ts +16 -0
- package/src/middleware/validate.test.data.ts +259 -0
- package/src/middleware/validate.test.ts +44 -0
- package/src/middleware/validate.ts +73 -0
- package/src/middleware.test.ts +184 -0
- package/src/middleware.ts +71 -0
- package/src/platform-instance.test.ts +531 -0
- package/src/platform-instance.ts +360 -0
- package/src/platform.test.ts +375 -0
- package/src/platform.ts +358 -0
- package/src/process-manager.ts +88 -0
- package/src/routes.test.ts +54 -0
- package/src/routes.ts +61 -0
- package/src/sentry.test.ts +106 -0
- package/src/sentry.ts +19 -0
- package/src/sockethub.ts +198 -0
- package/src/util.ts +5 -0
package/src/sockethub.ts
ADDED
|
@@ -0,0 +1,198 @@
|
|
|
1
|
+
import debug from "debug";
|
|
2
|
+
import type { Socket } from "socket.io";
|
|
3
|
+
|
|
4
|
+
import { crypto } from "@sockethub/crypto";
|
|
5
|
+
import { CredentialsStore } from "@sockethub/data-layer";
|
|
6
|
+
import type { CredentialsStoreInterface } from "@sockethub/data-layer";
|
|
7
|
+
import type {
|
|
8
|
+
ActivityStream,
|
|
9
|
+
InternalActivityStream,
|
|
10
|
+
} from "@sockethub/schemas";
|
|
11
|
+
|
|
12
|
+
import getInitObject from "./bootstrap/init.js";
|
|
13
|
+
import config from "./config";
|
|
14
|
+
import janitor from "./janitor.js";
|
|
15
|
+
import listener from "./listener.js";
|
|
16
|
+
import middleware from "./middleware.js";
|
|
17
|
+
import createActivityObject from "./middleware/create-activity-object.js";
|
|
18
|
+
import expandActivityStream from "./middleware/expand-activity-stream.js";
|
|
19
|
+
import storeCredentials from "./middleware/store-credentials.js";
|
|
20
|
+
import validate from "./middleware/validate.js";
|
|
21
|
+
import ProcessManager from "./process-manager.js";
|
|
22
|
+
|
|
23
|
+
const log = debug("sockethub:server:core");
|
|
24
|
+
|
|
25
|
+
type ErrMsg = {
|
|
26
|
+
context: string;
|
|
27
|
+
error: string;
|
|
28
|
+
content: object;
|
|
29
|
+
};
|
|
30
|
+
|
|
31
|
+
function attachError(err: unknown, msg: InternalActivityStream | undefined) {
|
|
32
|
+
const finalError: ErrMsg = {
|
|
33
|
+
context: "error",
|
|
34
|
+
error: err.toString(),
|
|
35
|
+
content: {},
|
|
36
|
+
};
|
|
37
|
+
|
|
38
|
+
// biome-ignore lint/performance/noDelete: <explanation>
|
|
39
|
+
delete msg.sessionSecret;
|
|
40
|
+
|
|
41
|
+
if (msg) {
|
|
42
|
+
finalError.content = msg;
|
|
43
|
+
}
|
|
44
|
+
return finalError;
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
class Sockethub {
|
|
48
|
+
private readonly parentId: string;
|
|
49
|
+
private readonly parentSecret1: string;
|
|
50
|
+
private readonly parentSecret2: string;
|
|
51
|
+
counter: number;
|
|
52
|
+
platforms: Map<string, object>;
|
|
53
|
+
status: boolean;
|
|
54
|
+
processManager: ProcessManager;
|
|
55
|
+
|
|
56
|
+
constructor() {
|
|
57
|
+
this.status = false;
|
|
58
|
+
this.parentId = crypto.randToken(16);
|
|
59
|
+
this.parentSecret1 = crypto.randToken(16);
|
|
60
|
+
this.parentSecret2 = crypto.randToken(16);
|
|
61
|
+
log(`session id: ${this.parentId}`);
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
/**
|
|
65
|
+
* initialization of Sockethub starts here
|
|
66
|
+
*/
|
|
67
|
+
async boot() {
|
|
68
|
+
if (this.status) {
|
|
69
|
+
return log("Sockethub.boot() called more than once");
|
|
70
|
+
}
|
|
71
|
+
this.status = true;
|
|
72
|
+
|
|
73
|
+
const init = await getInitObject().catch((err) => {
|
|
74
|
+
log(err);
|
|
75
|
+
process.exit(1);
|
|
76
|
+
});
|
|
77
|
+
|
|
78
|
+
this.processManager = new ProcessManager(
|
|
79
|
+
this.parentId,
|
|
80
|
+
this.parentSecret1,
|
|
81
|
+
this.parentSecret2,
|
|
82
|
+
init,
|
|
83
|
+
);
|
|
84
|
+
|
|
85
|
+
this.platforms = init.platforms;
|
|
86
|
+
|
|
87
|
+
log("active platforms: ", [...init.platforms.keys()]);
|
|
88
|
+
listener.start(); // start external services
|
|
89
|
+
janitor.start(); // start cleanup cycle
|
|
90
|
+
log("registering handlers");
|
|
91
|
+
listener.io.on("connection", this.handleIncomingConnection.bind(this));
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
async shutdown() {
|
|
95
|
+
await janitor.stop();
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
private handleIncomingConnection(socket: Socket) {
|
|
99
|
+
// session-specific debug messages
|
|
100
|
+
const sessionLog = debug(`sockethub:server:core:${socket.id}`);
|
|
101
|
+
const sessionSecret = crypto.randToken(16);
|
|
102
|
+
// stores instance is session-specific
|
|
103
|
+
// stores = getSessionStore(this.parentId, this.parentSecret1, socket.id, sessionSecret);
|
|
104
|
+
const credentialsStore: CredentialsStoreInterface =
|
|
105
|
+
new CredentialsStore(
|
|
106
|
+
this.parentId,
|
|
107
|
+
socket.id,
|
|
108
|
+
this.parentSecret1 + sessionSecret,
|
|
109
|
+
config.get("redis"),
|
|
110
|
+
);
|
|
111
|
+
|
|
112
|
+
sessionLog("socket.io connection");
|
|
113
|
+
|
|
114
|
+
socket.on("disconnect", () => {
|
|
115
|
+
sessionLog("disconnect received from client");
|
|
116
|
+
});
|
|
117
|
+
|
|
118
|
+
socket.on(
|
|
119
|
+
"credentials",
|
|
120
|
+
middleware("credentials")
|
|
121
|
+
.use(expandActivityStream)
|
|
122
|
+
.use(validate("credentials", socket.id))
|
|
123
|
+
.use(storeCredentials(credentialsStore))
|
|
124
|
+
.use((err, data, next) => {
|
|
125
|
+
// error handler
|
|
126
|
+
next(attachError(err, data));
|
|
127
|
+
})
|
|
128
|
+
.use((data, next) => {
|
|
129
|
+
next();
|
|
130
|
+
})
|
|
131
|
+
.done(),
|
|
132
|
+
);
|
|
133
|
+
|
|
134
|
+
// when new activity objects are created on the client side, an event is
|
|
135
|
+
// fired, and we receive a copy on the server side.
|
|
136
|
+
socket.on(
|
|
137
|
+
"activity-object",
|
|
138
|
+
middleware("activity-object")
|
|
139
|
+
.use(validate("activity-object", socket.id))
|
|
140
|
+
.use(createActivityObject)
|
|
141
|
+
.use((err, data, next) => {
|
|
142
|
+
next(attachError(err, data));
|
|
143
|
+
})
|
|
144
|
+
.use((data, next) => {
|
|
145
|
+
next();
|
|
146
|
+
})
|
|
147
|
+
.done(),
|
|
148
|
+
);
|
|
149
|
+
|
|
150
|
+
socket.on(
|
|
151
|
+
"message",
|
|
152
|
+
middleware("message")
|
|
153
|
+
.use(expandActivityStream)
|
|
154
|
+
.use(validate("message", socket.id))
|
|
155
|
+
.use((msg, next) => {
|
|
156
|
+
// The platform thread must find the credentials on their own using the given
|
|
157
|
+
// sessionSecret, which indicates that this specific session (socket
|
|
158
|
+
// connection) has provided credentials.
|
|
159
|
+
msg.sessionSecret = sessionSecret;
|
|
160
|
+
next(msg);
|
|
161
|
+
})
|
|
162
|
+
.use((err, data, next) => {
|
|
163
|
+
next(attachError(err, data));
|
|
164
|
+
})
|
|
165
|
+
.use(async (msg: ActivityStream, next) => {
|
|
166
|
+
const platformInstance = this.processManager.get(
|
|
167
|
+
msg.context,
|
|
168
|
+
msg.actor.id,
|
|
169
|
+
socket.id,
|
|
170
|
+
);
|
|
171
|
+
// job validated and queued, stores socket.io callback for when job is completed
|
|
172
|
+
try {
|
|
173
|
+
const job = await platformInstance.queue.add(
|
|
174
|
+
socket.id,
|
|
175
|
+
msg,
|
|
176
|
+
);
|
|
177
|
+
if (job) {
|
|
178
|
+
platformInstance.completedJobHandlers.set(
|
|
179
|
+
job.title,
|
|
180
|
+
next,
|
|
181
|
+
);
|
|
182
|
+
} else {
|
|
183
|
+
// failed to add job to queue, reject handler immediately
|
|
184
|
+
msg.error = "failed to add job to queue";
|
|
185
|
+
next(msg);
|
|
186
|
+
}
|
|
187
|
+
} catch (err) {
|
|
188
|
+
// Queue is closed (platform terminating) - send error to client
|
|
189
|
+
msg.error = err.message || "platform unavailable";
|
|
190
|
+
next(msg);
|
|
191
|
+
}
|
|
192
|
+
})
|
|
193
|
+
.done(),
|
|
194
|
+
);
|
|
195
|
+
}
|
|
196
|
+
}
|
|
197
|
+
|
|
198
|
+
export default Sockethub;
|