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

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 (95) hide show
  1. package/coverage/tmp/coverage-39338-1663949520416-0.json +1 -0
  2. package/dist/bootstrap/init.js +2 -1
  3. package/dist/bootstrap/init.js.map +1 -1
  4. package/dist/config.d.ts +7 -1
  5. package/dist/config.js +6 -1
  6. package/dist/config.js.map +1 -1
  7. package/dist/index.d.ts +1 -2
  8. package/dist/index.js +7 -3
  9. package/dist/index.js.map +1 -1
  10. package/dist/janitor.d.ts +27 -12
  11. package/dist/janitor.js +97 -66
  12. package/dist/janitor.js.map +1 -1
  13. package/dist/listener.d.ts +4 -1
  14. package/dist/listener.js +8 -5
  15. package/dist/listener.js.map +1 -1
  16. package/dist/middleware/create-activity-object.d.ts +3 -1
  17. package/dist/middleware/create-activity-object.js.map +1 -1
  18. package/dist/middleware/expand-activity-stream.d.ts +2 -1
  19. package/dist/middleware/expand-activity-stream.js +4 -1
  20. package/dist/middleware/expand-activity-stream.js.map +1 -1
  21. package/dist/middleware/expand-activity-stream.test.data.js +4 -4
  22. package/dist/middleware/expand-activity-stream.test.data.js.map +1 -1
  23. package/dist/middleware/store-credentials.d.ts +3 -3
  24. package/dist/middleware/store-credentials.js +2 -12
  25. package/dist/middleware/store-credentials.js.map +1 -1
  26. package/dist/middleware/validate.d.ts +2 -2
  27. package/dist/middleware/validate.js +1 -3
  28. package/dist/middleware/validate.js.map +1 -1
  29. package/dist/middleware/validate.test.data.js +5 -5
  30. package/dist/middleware/validate.test.data.js.map +1 -1
  31. package/dist/middleware.d.ts +14 -3
  32. package/dist/middleware.js +3 -1
  33. package/dist/middleware.js.map +1 -1
  34. package/dist/platform-instance.d.ts +11 -10
  35. package/dist/platform-instance.js +77 -62
  36. package/dist/platform-instance.js.map +1 -1
  37. package/dist/platform.js +93 -104
  38. package/dist/platform.js.map +1 -1
  39. package/dist/process-manager.js +7 -3
  40. package/dist/process-manager.js.map +1 -1
  41. package/dist/routes.d.ts +1 -1
  42. package/dist/routes.js +1 -1
  43. package/dist/routes.js.map +1 -1
  44. package/dist/sockethub.d.ts +1 -22
  45. package/dist/sockethub.js +19 -26
  46. package/dist/sockethub.js.map +1 -1
  47. package/package.json +30 -36
  48. package/src/bootstrap/init.d.ts +17 -7
  49. package/src/bootstrap/init.ts +2 -1
  50. package/src/config.ts +9 -1
  51. package/src/index.ts +3 -2
  52. package/src/janitor.test.ts +189 -0
  53. package/src/janitor.ts +110 -65
  54. package/src/listener.ts +11 -7
  55. package/src/middleware/create-activity-object.ts +5 -2
  56. package/src/middleware/expand-activity-stream.test.data.ts +5 -5
  57. package/src/middleware/expand-activity-stream.test.ts +2 -2
  58. package/src/middleware/expand-activity-stream.ts +12 -7
  59. package/src/middleware/store-credentials.test.ts +4 -6
  60. package/src/middleware/store-credentials.ts +8 -14
  61. package/src/middleware/validate.test.data.ts +5 -5
  62. package/src/middleware/validate.ts +4 -6
  63. package/src/middleware.ts +28 -11
  64. package/src/platform-instance.test.ts +18 -18
  65. package/src/platform-instance.ts +98 -73
  66. package/src/platform.ts +79 -101
  67. package/src/process-manager.ts +1 -1
  68. package/src/routes.ts +3 -2
  69. package/src/sockethub.ts +29 -57
  70. package/views/examples/dummy.ejs +3 -1
  71. package/views/examples/shared.js +1 -1
  72. package/views/examples/xmpp.ejs +60 -34
  73. package/coverage/tmp/coverage-93126-1649152190997-0.json +0 -1
  74. package/dist/common.d.ts +0 -3
  75. package/dist/common.js +0 -20
  76. package/dist/common.js.map +0 -1
  77. package/dist/crypto.d.ts +0 -10
  78. package/dist/crypto.js +0 -38
  79. package/dist/crypto.js.map +0 -1
  80. package/dist/store.d.ts +0 -5
  81. package/dist/store.js +0 -17
  82. package/dist/store.js.map +0 -1
  83. package/src/common.test.ts +0 -54
  84. package/src/common.ts +0 -14
  85. package/src/config.d.ts +0 -2
  86. package/src/crypto.d.ts +0 -5
  87. package/src/crypto.test.ts +0 -41
  88. package/src/crypto.ts +0 -41
  89. package/src/janitor.d.ts +0 -8
  90. package/src/middleware/validate.d.ts +0 -1
  91. package/src/middleware.d.ts +0 -21
  92. package/src/sockethub.d.ts +0 -1
  93. package/src/store.test.ts +0 -28
  94. package/src/store.ts +0 -17
  95. package/test/queue.functional.test.js +0 -0
@@ -1,8 +1,18 @@
1
- declare const init: {
2
- version: any;
3
- platforms: Map<any, any>;
4
- host: any;
5
- port: any;
6
- path: any;
7
- };
1
+ export interface IInitObject {
2
+ version: string;
3
+ platforms: Map<string, {
4
+ id: string;
5
+ moduleName: string;
6
+ config: {
7
+ persist?: boolean;
8
+ };
9
+ schemas: {
10
+ credentials?: object;
11
+ messages?: object;
12
+ };
13
+ version: string;
14
+ types: Array<string>;
15
+ }>;
16
+ }
17
+ declare const init: IInitObject;
8
18
  export default init;
@@ -6,6 +6,7 @@ import platformLoad from './platforms';
6
6
  const log = debug('sockethub:server:bootstrap:init');
7
7
  log('running init routines');
8
8
 
9
+ // eslint-disable-next-line @typescript-eslint/no-var-requires
9
10
  const packageJSON = require('./../../package.json');
10
11
  const platforms = platformLoad(config.get('platforms'));
11
12
 
@@ -40,7 +41,7 @@ if (config.get('info')) {
40
41
  console.log('platforms: ' + Array.from(platforms.keys()).join(', '));
41
42
 
42
43
  if (platforms.size > 0) {
43
- for (let platform of platforms.values()) {
44
+ for (const platform of platforms.values()) {
44
45
  console.log();
45
46
  // eslint-disable-next-line security-node/detect-crlf
46
47
  console.log(platform.moduleName);
package/src/config.ts CHANGED
@@ -4,6 +4,13 @@ import * as fs from "fs";
4
4
 
5
5
  const log = debug('sockethub:server:bootstrap:config');
6
6
 
7
+ export type ActivityStreamConfigOptions = {
8
+ warnOnUnknownObjectProperties?: boolean;
9
+ failOnUnknownObjectProperties?: boolean;
10
+ specialObjs?: object;
11
+ customProps?: object;
12
+ }
13
+
7
14
  export class Config {
8
15
  constructor() {
9
16
  log('initializing config');
@@ -58,6 +65,7 @@ export class Config {
58
65
  nconf.set('examples:enabled', (examples ? true : nconf.get('examples:enabled')));
59
66
 
60
67
  // load defaults
68
+ // eslint-disable-next-line @typescript-eslint/no-var-requires
61
69
  const defaults: object = require(__dirname + '/defaults.json');
62
70
  nconf.defaults(defaults);
63
71
 
@@ -87,7 +95,7 @@ export class Config {
87
95
  nconf.clear('redis:port');
88
96
  }
89
97
  }
90
- get = (key: string): any => nconf.get(key);
98
+ get = (key: string): unknown => nconf.get(key);
91
99
  }
92
100
 
93
101
  const config = new Config();
package/src/index.ts CHANGED
@@ -1,4 +1,5 @@
1
- const Sockethub = require('./sockethub').default;
1
+ import Sockethub from "./sockethub";
2
+
2
3
  const sockethub = new Sockethub();
3
4
 
4
5
  module.exports = async () => {
@@ -21,7 +22,7 @@ module.exports = async () => {
21
22
 
22
23
  process.once('exit', async function () {
23
24
  console.log('destroying all platform instances');
24
- await sockethub.removeAllPlatformInstances();
25
+ await sockethub.shutdown();
25
26
  });
26
27
 
27
28
  sockethub.boot();
@@ -0,0 +1,189 @@
1
+ import proxyquire from 'proxyquire';
2
+ import { expect } from 'chai';
3
+ import * as sinon from 'sinon';
4
+
5
+ let sockets = [
6
+ { id: 'socket foo', emit: () => {} },
7
+ { id: 'socket bar', emit: () => {} }
8
+ ]
9
+
10
+ proxyquire.noPreserveCache();
11
+ proxyquire.noCallThru();
12
+
13
+ function getPlatformInstanceFake() {
14
+ return {
15
+ flaggedForTermination: false,
16
+ initialized: false,
17
+ global: false,
18
+ shutdown: sinon.stub(),
19
+ process: {
20
+ removeListener: sinon.stub()
21
+ },
22
+ sessions: new Set(['session foo', 'session bar']),
23
+ sessionCallbacks: {
24
+ 'close': (() => new Map([
25
+ ['session foo', function sessionFooClose() {}],
26
+ ['session bar', function sessionBarClose() {}]
27
+ ]))(),
28
+ 'message': (() => new Map([
29
+ ['session foo', function sessionFooMessage() {}],
30
+ ['session bar', function sessionBarMessage() {}]
31
+ ]))()
32
+ }
33
+ }
34
+ }
35
+
36
+ const cycleInterval = 10;
37
+
38
+ describe('Janitor', () => {
39
+ let sandbox, fetchSocketsFake, janitor;
40
+
41
+ beforeEach(function (done) {
42
+ this.timeout(3000);
43
+ sandbox = sinon.createSandbox();
44
+ fetchSocketsFake = sandbox.stub().returns(sockets);
45
+ const janitorMod = proxyquire('./janitor', {
46
+ listener: {
47
+ io: {
48
+ fetchSockets: fetchSocketsFake
49
+ }
50
+ }
51
+ });
52
+ janitor = janitorMod.default;
53
+ janitor.getSockets = fetchSocketsFake;
54
+ expect(janitor.cycleInterval).to.not.equal(cycleInterval);
55
+ janitor.cycleInterval = cycleInterval;
56
+ expect(janitor.cycleInterval).to.equal(cycleInterval);
57
+ janitor.start();
58
+ setTimeout(() => {
59
+ expect(janitor.cycleCount).to.equal(1);
60
+ done();
61
+ }, cycleInterval)
62
+ });
63
+
64
+ afterEach((done) => {
65
+ sandbox.reset();
66
+ janitor.stop();
67
+ setTimeout(() => {
68
+ done();
69
+ }, janitor.cycleInterval * 2)
70
+ });
71
+
72
+ it('runs cycle at every cycleInterval', (done) => {
73
+ const currCycleCount = janitor.cycleCount;
74
+ expect(currCycleCount).to.not.equal(0);
75
+ setTimeout(() => {
76
+ expect(janitor.cycleCount).to.equal(currCycleCount + 1);
77
+ setTimeout(() => {
78
+ expect(janitor.cycleCount).to.equal(currCycleCount + 2);
79
+ done();
80
+ }, cycleInterval);
81
+ }, cycleInterval);
82
+ });
83
+
84
+ describe('removeSessionCallbacks', () => {
85
+ it('removes session listeners and callbacks for a given platform', () => {
86
+ const pi = getPlatformInstanceFake();
87
+ const barMessage = pi.sessionCallbacks.message.get('session bar');
88
+ const barClose = pi.sessionCallbacks.close.get('session bar');
89
+ pi.flaggedForTermination = true;
90
+ janitor.removeSessionCallbacks(pi, 'session foo');
91
+ sinon.assert.calledTwice(pi.process.removeListener);
92
+ expect(pi.sessionCallbacks.message.get('session foo')).to.be.undefined;
93
+ expect(pi.sessionCallbacks.message.get('session bar')).to.equal(barMessage);
94
+ expect(pi.sessionCallbacks.close.get('session foo')).to.be.undefined;
95
+ expect(pi.sessionCallbacks.close.get('session bar')).to.equal(barClose);
96
+ });
97
+ });
98
+
99
+ describe('removeStaleSocketSessions', () => {
100
+ it('doesnt do anything if the socket is active and stop is not flagged', async () => {
101
+ const pi = getPlatformInstanceFake();
102
+ janitor.removeSessionCallbacks = sinon.stub();
103
+ janitor.socketExists = sinon.stub().returns(true);
104
+ expect(janitor.stopTriggered).to.be.false;
105
+ await janitor.removeStaleSocketSessions(pi);
106
+ sinon.assert.notCalled(janitor.removeSessionCallbacks);
107
+ });
108
+
109
+ it('removes session if the socket is active and stop is flagged', async () => {
110
+ const pi = getPlatformInstanceFake();
111
+ janitor.removeSessionCallbacks = sinon.stub();
112
+ janitor.socketExists = sinon.stub().returns(true);
113
+ janitor.stop();
114
+ expect(janitor.stopTriggered).to.be.true;
115
+ await janitor.removeStaleSocketSessions(pi);
116
+ sinon.assert.calledTwice(janitor.removeSessionCallbacks);
117
+ sinon.assert.calledWith(janitor.removeSessionCallbacks, pi, 'session foo');
118
+ sinon.assert.calledWith(janitor.removeSessionCallbacks, pi, 'session bar');
119
+ });
120
+
121
+ it('removes session if the socket is inactive', async () => {
122
+ const pi = getPlatformInstanceFake();
123
+ janitor.removeSessionCallbacks = sinon.stub();
124
+ janitor.socketExists = sinon.stub().onFirstCall().returns(false).onSecondCall().returns(true);
125
+ expect(janitor.stopTriggered).to.be.false;
126
+ await janitor.removeStaleSocketSessions(pi);
127
+ sinon.assert.calledOnce(janitor.removeSessionCallbacks);
128
+ sinon.assert.calledWith(janitor.removeSessionCallbacks, pi, 'session foo');
129
+ });
130
+ });
131
+
132
+ describe('performStaleCheck', () => {
133
+ it('removes flagged and uninitialized platform instances', async () => {
134
+ const pi = getPlatformInstanceFake();
135
+ pi.flaggedForTermination = true;
136
+ pi.initialized = false;
137
+ janitor.removeStaleSocketSessions = sandbox.stub();
138
+ janitor.removeStalePlatformInstance = sandbox.stub();
139
+ await janitor.performStaleCheck(pi);
140
+ sinon.assert.calledOnce(janitor.removeStaleSocketSessions);
141
+ sinon.assert.calledOnce(janitor.removeStalePlatformInstance);
142
+ expect(pi.flaggedForTermination).to.be.true;
143
+ });
144
+
145
+ it('flags for termination when there are not sockets', async () => {
146
+ const pi = getPlatformInstanceFake();
147
+ pi.sessions = new Set();
148
+ pi.flaggedForTermination = false;
149
+ pi.initialized = true;
150
+ janitor.removeStaleSocketSessions = sandbox.stub();
151
+ janitor.removeStalePlatformInstance = sandbox.stub();
152
+ await janitor.performStaleCheck(pi);
153
+ sinon.assert.calledOnce(janitor.removeStaleSocketSessions);
154
+ sinon.assert.calledOnce(janitor.removeStalePlatformInstance);
155
+ });
156
+ });
157
+
158
+ describe('removeStalePlatformInstance', () => {
159
+ it('flags stale platform', async () => {
160
+ const pi = getPlatformInstanceFake();
161
+ expect(pi.flaggedForTermination).to.be.false;
162
+ await janitor.removeStalePlatformInstance(pi);
163
+ sinon.assert.notCalled(pi.shutdown);
164
+ expect(pi.flaggedForTermination).to.be.true;
165
+ });
166
+
167
+ it('removes flagged stale platform', async () => {
168
+ const pi = getPlatformInstanceFake();
169
+ pi.flaggedForTermination = true;
170
+ await janitor.removeStalePlatformInstance(pi);
171
+ sinon.assert.calledOnce(pi.shutdown);
172
+ });
173
+ });
174
+
175
+ it('closes all connections when stop() is called', (done) => {
176
+ const prevCycle = janitor.cycleCount;
177
+ janitor.stop();
178
+ setTimeout(() => {
179
+ expect(janitor.cycleCount).to.equal(prevCycle);
180
+ setTimeout(() => {
181
+ expect(janitor.cycleCount).to.equal(prevCycle);
182
+ setTimeout(() => {
183
+ expect(janitor.cycleCount).to.equal(prevCycle);
184
+ done();
185
+ }, cycleInterval)
186
+ }, cycleInterval)
187
+ }, cycleInterval);
188
+ });
189
+ })
package/src/janitor.ts CHANGED
@@ -5,85 +5,130 @@ import listener, { SocketInstance } from "./listener";
5
5
 
6
6
  const rmLog = debug('sockethub:server:janitor');
7
7
 
8
- const TICK = 15000;
9
- let alreadyCalled: boolean = false;
10
- let cycleCount: number = 0; // a counter for each setInterval call
11
- let reportCount: number = 0; // number of times a report is printed
12
-
13
- /**
14
- * Every TICK the Janitor will compare existing platform instances with socket.ids (aka. sessionId)
15
- * If all of the sessionIds associated with a platformInstance have no corresponding socket.id
16
- * (from the http.io socket.io instance), then the platformInstance will first be flagged, if after
17
- * the next TICK the same state is determined, the platform will be destroyed (this allows for page
18
- * refreshes not destroying platform instances)
19
- */
20
- function janitorCycle() {
21
- if (! alreadyCalled) { alreadyCalled = true; }
22
- else { return; }
23
- rmLog('initializing resource manager');
24
- setInterval(async () => {
25
- cycleCount++;
26
- const sockets: Array<SocketInstance> = await listener.io.fetchSockets();
27
-
28
- if (! (cycleCount % 4)) {
29
- reportCount++;
30
- rmLog(`socket sessions: ${sockets.length} platform instances: ${platformInstances.size}`);
8
+ class Janitor {
9
+ cycleInterval = 15000;
10
+ cycleCount = 0; // a counter for each cycleInterval
11
+ reportCount = 0; // number of times a report is printed
12
+ protected stopTriggered = false;
13
+ protected sockets: Array<SocketInstance>;
14
+ private cycleRunning = false;
15
+
16
+ /**
17
+ * Every TICK the `Janitor` will compare existing platform instances with `socket.ids`
18
+ * (aka. `sessionId`). If all of the `sessionIds` associated with a `platformInstance` have
19
+ * no corresponding `socket.id` (from the `http.io` `socket.io` instance), then the
20
+ * `platformInstance` will first be flagged, if after the next `cycleInterval` the same
21
+ * state is determined, the platform will be destroyed (this allows for page
22
+ * refreshes not destroying platform instances)
23
+ */
24
+ start(): void {
25
+ rmLog('initializing');
26
+ this.clean().then(() => {
27
+ rmLog('cleaning cycle started');
28
+ });
29
+ }
30
+
31
+ async stop(): Promise<void> {
32
+ this.stopTriggered = true;
33
+ rmLog('stopping, terminating all sessions');
34
+ for (const platformInstance of platformInstances.values()) {
35
+ this.removeStaleSocketSessions(platformInstance);
36
+ await this.removeStalePlatformInstance(platformInstance);
37
+ await platformInstance.shutdown();
31
38
  }
39
+ }
40
+
41
+ private removeSessionCallbacks(platformInstance: PlatformInstance, sessionId: string): void {
42
+ for (const key in platformInstance.sessionCallbacks) {
43
+ platformInstance.process.removeListener(
44
+ key, platformInstance.sessionCallbacks[key].get(sessionId));
45
+ platformInstance.sessionCallbacks[key].delete(sessionId);
46
+ }
47
+ }
32
48
 
33
- for (let platformInstance of platformInstances.values()) {
34
- removeStaleSocketSessions(platformInstance, sockets);
35
- // Static platforms are for global use, not tied to a unique to session / eg. credentials)
36
- if ((! platformInstance.global) && (platformInstance.sessions.size === 0)) {
37
- removeStalePlatformInstance(platformInstance);
38
- } else {
39
- platformInstance.flaggedForTermination = false;
49
+ private removeStaleSocketSessions(
50
+ platformInstance: PlatformInstance
51
+ ): void {
52
+ for (const sessionId of platformInstance.sessions.values()) {
53
+ if ((this.stopTriggered) || (!this.socketExists(sessionId))) {
54
+ this.removeStaleSocketSession(platformInstance, sessionId);
40
55
  }
41
56
  }
42
- }, TICK);
43
- }
57
+ }
58
+
59
+ private removeStaleSocketSession(platformInstance: PlatformInstance, sessionId: string) {
60
+ rmLog(
61
+ `removing ${!this.stopTriggered ? 'stale ' : ''}socket session reference ${sessionId}
62
+ in platform instance ${platformInstance.id}`
63
+ );
64
+ platformInstance.sessions.delete(sessionId);
65
+ this.removeSessionCallbacks(platformInstance, sessionId);
66
+ }
44
67
 
45
- function socketExists(sessionId: string, sockets: Array<SocketInstance>) {
46
- for (let socket of sockets) {
47
- if (socket.id === sessionId) {
48
- return true;
68
+ private async removeStalePlatformInstance(platformInstance: PlatformInstance): Promise<void> {
69
+ if ((platformInstance.flaggedForTermination) || (this.stopTriggered)) {
70
+ rmLog(`terminating platform instance ${platformInstance.id}`);
71
+ await platformInstance.shutdown(); // terminate
72
+ } else {
73
+ rmLog(`flagging for termination platform instance ${platformInstance.id} ` +
74
+ `(no registered sessions found)`);
75
+ platformInstance.flaggedForTermination = true;
49
76
  }
50
77
  }
51
- return false;
52
- }
53
78
 
54
- function removeSessionCallbacks(platformInstance: PlatformInstance, sessionId: string) {
55
- for (const key in platformInstance.sessionCallbacks) {
56
- platformInstance.sessionCallbacks[key].delete(sessionId);
79
+ private socketExists(sessionId: string) {
80
+ for (const socket of this.sockets) {
81
+ if (socket.id === sessionId) {
82
+ return true;
83
+ }
84
+ }
85
+ return false;
86
+ }
87
+
88
+ private async delay(ms): Promise<void> {
89
+ return await new Promise(resolve => setTimeout(resolve, ms));
57
90
  }
58
- }
59
91
 
60
- function removeStaleSocketSessions(platformInstance: PlatformInstance,
61
- sockets: Array<SocketInstance>) {
62
- for (const sessionId of platformInstance.sessions.values()) {
63
- if (! socketExists(sessionId, sockets)) {
64
- rmLog('removing stale socket session reference ' + sessionId + ' in platform instance '
65
- + platformInstance.id);
66
- platformInstance.sessions.delete(sessionId);
67
- removeSessionCallbacks(platformInstance, sessionId);
92
+ private async getSockets(): Promise<Array<SocketInstance>> {
93
+ return await listener.io.fetchSockets();
94
+ }
95
+
96
+ private async performStaleCheck(platformInstance: PlatformInstance) {
97
+ this.removeStaleSocketSessions(platformInstance);
98
+ // Static platforms are for global use, not tied to a unique to session / eg. credentials)
99
+ if (!platformInstance.global) {
100
+ if ((!platformInstance.initialized) || (platformInstance.sessions.size === 0)) {
101
+ // either the platform failed to initialize, or there are no more sessions linked to it
102
+ await this.removeStalePlatformInstance(platformInstance);
103
+ }
68
104
  }
69
105
  }
70
- }
71
106
 
72
- function removeStalePlatformInstance(platformInstance: PlatformInstance) {
73
- if (platformInstance.flaggedForTermination) {
74
- rmLog(`terminating platform instance ${platformInstance.id}`);
75
- platformInstance.destroy(); // terminate
76
- } else {
77
- rmLog(`flagging for termination platform instance ${platformInstance.id} ` +
78
- `(no registered sessions found)`);
79
- platformInstance.flaggedForTermination = true;
107
+ private async clean(): Promise<void> {
108
+ if (this.stopTriggered) {
109
+ this.cycleRunning = false;
110
+ return;
111
+ } else if (this.cycleRunning) {
112
+ throw new Error('janitor cleanup cycle called while already running');
113
+ }
114
+ this.cycleRunning = true;
115
+ this.cycleCount++;
116
+ this.sockets = await this.getSockets();
117
+
118
+ if (!(this.cycleCount % 4)) {
119
+ this.reportCount++;
120
+ rmLog(
121
+ `socket sessions: ${this.sockets.length} platform instances: ${platformInstances.size}`);
122
+ }
123
+
124
+ for (const platformInstance of platformInstances.values()) {
125
+ await this.performStaleCheck(platformInstance);
126
+ }
127
+ this.cycleRunning = false;
128
+ await this.delay(this.cycleInterval);
129
+ return this.clean();
80
130
  }
81
131
  }
82
132
 
83
- const janitor = {
84
- clean: janitorCycle,
85
- alreadyCalled: alreadyCalled,
86
- cycleCount: cycleCount,
87
- reportCount: reportCount
88
- };
133
+ const janitor = new Janitor();
89
134
  export default janitor;
package/src/listener.ts CHANGED
@@ -29,7 +29,7 @@ class Listener {
29
29
  const app = Listener.initExpress();
30
30
  this.http = new HTTP.Server(app);
31
31
  this.io = new Server(this.http, {
32
- path: config.get('sockethub:path'),
32
+ path: config.get('sockethub:path') as string,
33
33
  cors: {
34
34
  origin: "*",
35
35
  methods: [ "GET", "POST" ]
@@ -40,14 +40,14 @@ class Listener {
40
40
  }
41
41
 
42
42
  private startHttp() {
43
- this.http.listen(config.get('sockethub:port'), config.get('sockethub:host'), () => {
43
+ this.http.listen(config.get('sockethub:port'), config.get('sockethub:host') as number, () => {
44
44
  log(`sockethub listening on ` +
45
- `http://${config.get('sockethub:host')}:${config.get('sockethub:port')}`);
45
+ `${config.get('sockethub:host')}:${config.get('sockethub:port')}`);
46
46
  });
47
- };
47
+ }
48
48
 
49
49
  private static initExpress() {
50
- let app = express();
50
+ const app = express();
51
51
  // templating engines
52
52
  app.set('view engine', 'ejs');
53
53
  // use bodyParser
@@ -59,15 +59,19 @@ class Listener {
59
59
 
60
60
  const listener = new Listener();
61
61
 
62
+ interface EmitFunction {
63
+ (type: string, data: unknown)
64
+ }
65
+
62
66
  export interface SocketInstance {
63
67
  id: string;
64
- emit: Function;
68
+ emit: EmitFunction;
65
69
  }
66
70
 
67
71
  export async function getSocket(sessionId: string): Promise<SocketInstance> {
68
72
  const sockets: Array<SocketInstance> = await listener.io.fetchSockets();
69
73
  return new Promise((resolve, reject) => {
70
- for (let socket of sockets) {
74
+ for (const socket of sockets) {
71
75
  if (sessionId === socket.id) {
72
76
  return resolve(socket);
73
77
  }
@@ -1,5 +1,7 @@
1
1
  import ActivityStreams from '@sockethub/activity-streams';
2
2
  import config from "../config";
3
+ import {IActivityStream} from "@sockethub/schemas";
4
+ import {MiddlewareChainInterface} from "../middleware";
3
5
  const activity = ActivityStreams(config.get('activity-streams:opts'));
4
6
 
5
7
  /**
@@ -7,7 +9,8 @@ const activity = ActivityStreams(config.get('activity-streams:opts'));
7
9
  * @param obj
8
10
  * @param done
9
11
  */
10
- export default function createActivityObject(obj: any, done: Function) {
12
+ export default function createActivityObject(obj: IActivityStream,
13
+ done: MiddlewareChainInterface) {
11
14
  activity.Object.create(obj);
12
15
  done(obj);
13
- }
16
+ }
@@ -68,10 +68,10 @@ export default [
68
68
  "image":{
69
69
  "height":250,
70
70
  "mediaType":"image/jpeg",
71
- "url":"http://example.org/image.jpg",
71
+ "url":"https://example.org/image.jpg",
72
72
  "width":250
73
73
  },
74
- "url":"http://sockethub.org"
74
+ "url":"https://sockethub.org"
75
75
  },
76
76
  "object":{
77
77
  "type":"credentials",
@@ -340,10 +340,10 @@ export default [
340
340
  "image":{
341
341
  "height":250,
342
342
  "mediaType":"image/jpeg",
343
- "url":"http://example.org/image.jpg",
343
+ "url":"https://example.org/image.jpg",
344
344
  "width":250
345
345
  },
346
- "url":"http://sockethub.org"
346
+ "url":"https://sockethub.org"
347
347
  },
348
348
  "target":{
349
349
  "id":"blah3",
@@ -362,4 +362,4 @@ export default [
362
362
  }
363
363
  }
364
364
  }
365
- ];
365
+ ];
@@ -30,10 +30,10 @@ const activity = ActivityStreams();
30
30
  "image":{
31
31
  "height":250,
32
32
  "mediaType":"image/jpeg",
33
- "url":"http://example.org/image.jpg",
33
+ "url":"https://example.org/image.jpg",
34
34
  "width":250
35
35
  },
36
- "url":"http://sockethub.org"
36
+ "url":"https://sockethub.org"
37
37
  },
38
38
  {
39
39
  "id":"blah3",
@@ -1,24 +1,29 @@
1
1
  import ActivityStreams from '@sockethub/activity-streams';
2
- import { IActivityStream } from "@sockethub/schemas";
2
+ import {IActivityStream} from "@sockethub/schemas";
3
3
 
4
- import config from "../config";
4
+ import config, {ActivityStreamConfigOptions} from "../config";
5
+ import {MiddlewareChainInterface} from "../middleware";
5
6
 
6
- const activity = ActivityStreams(config.get('activity-streams:opts'));
7
+ const asConfig = config.get('activity-streams:opts') as ActivityStreamConfigOptions;
8
+ asConfig.warnOnUnknownObjectProperties = false;
9
+ asConfig.failOnUnknownObjectProperties = false;
10
+ const activity = ActivityStreams(asConfig);
7
11
 
8
- function ensureObject(msg: any) {
12
+ function ensureObject(msg: unknown) {
9
13
  return !((typeof msg !== 'object') || (Array.isArray(msg)));
10
14
  }
11
15
 
12
- export default function expandActivityStream(msg: IActivityStream, done: Function) {
16
+ export default function expandActivityStream(msg: IActivityStream,
17
+ done: MiddlewareChainInterface) {
13
18
  if (! ensureObject(msg)) {
14
19
  done(new Error(`message received is not an object.`));
15
20
  } else if (typeof msg.context !== 'string') {
16
21
  done(new Error('activity stream must contain a context property'));
17
- } else if (typeof msg.type !== 'string') {
22
+ } else if (typeof msg.type !== 'string') {
18
23
  done(new Error('activity stream must contain a type property.'));
19
24
  } else {
20
25
  msg = activity.Stream(msg);
21
- if (! msg.actor) {
26
+ if (!msg.actor) {
22
27
  done(new Error('activity stream must contain an actor property.'));
23
28
  } else {
24
29
  done(msg);
@@ -24,7 +24,7 @@ const creds = {
24
24
 
25
25
  describe('Middleware: storeCredentials', () => {
26
26
  let storeSuccess: any, storeError: any, saveErrorFake: any,
27
- saveSuccessFake: any, sessionLogStub: any;
27
+ saveSuccessFake: any;
28
28
 
29
29
  beforeEach(() => {
30
30
  storeSuccess = {
@@ -39,7 +39,6 @@ describe('Middleware: storeCredentials', () => {
39
39
  };
40
40
  saveSuccessFake = sinon.replace(storeSuccess, 'save', sinon.fake(storeSuccess.save));
41
41
  saveErrorFake = sinon.replace(storeError, 'save', sinon.fake(storeError.save));
42
- sessionLogStub = sinon.stub();
43
42
  });
44
43
 
45
44
  afterEach(() => {
@@ -47,14 +46,13 @@ describe('Middleware: storeCredentials', () => {
47
46
  });
48
47
 
49
48
  it('returns a middleware handler', () => {
50
- const sc = storeCredentials(storeSuccess, sessionLogStub);
49
+ const sc = storeCredentials(storeSuccess);
51
50
  expect(typeof sc).to.equal('function');
52
51
  expect(saveSuccessFake.callCount).to.equal(0);
53
- expect(sessionLogStub.callCount).to.equal(0);
54
52
  });
55
53
 
56
54
  it('successfully store credentials', () => {
57
- const sc = storeCredentials(storeSuccess, sessionLogStub);
55
+ const sc = storeCredentials(storeSuccess);
58
56
  sc(creds, (err: any) => {
59
57
  expect(saveSuccessFake.callCount).to.equal(1);
60
58
  expect(saveSuccessFake.firstArg).to.equal(creds.actor.id);
@@ -63,7 +61,7 @@ describe('Middleware: storeCredentials', () => {
63
61
  });
64
62
 
65
63
  it('handle error while storing credentials', () => {
66
- const sc = storeCredentials(storeError, sessionLogStub);
64
+ const sc = storeCredentials(storeError);
67
65
  sc(creds, (err: any) => {
68
66
  expect(saveErrorFake.callCount).to.equal(1);
69
67
  expect(saveErrorFake.firstArg).to.equal(creds.actor.id);