@opra/socketio 1.20.0 → 1.22.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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@opra/socketio",
3
- "version": "1.20.0",
3
+ "version": "1.22.0",
4
4
  "description": "Opra Socket.IO adapter",
5
5
  "author": "Panates",
6
6
  "license": "MIT",
@@ -8,50 +8,34 @@
8
8
  "@jsopen/objects": "^2.0.2",
9
9
  "@browsery/type-is": "^2.0.1",
10
10
  "content-type": "^1.0.5",
11
- "iconv-lite": "^0.7.0",
12
- "node-events-async": "^1.2.0",
11
+ "iconv-lite": "^0.7.1",
12
+ "node-events-async": "^1.4.0",
13
13
  "tslib": "^2.8.1",
14
14
  "valgen": "^5.18.2"
15
15
  },
16
16
  "peerDependencies": {
17
- "@opra/common": "^1.20.0",
18
- "@opra/core": "^1.20.0",
17
+ "@opra/common": "^1.22.0",
18
+ "@opra/core": "^1.22.0",
19
19
  "socket.io": ">=4.0.0"
20
20
  },
21
21
  "type": "module",
22
+ "module": "./index.js",
23
+ "types": "./index.d.ts",
22
24
  "exports": {
23
25
  ".": {
24
- "import": {
25
- "types": "./types/index.d.ts",
26
- "default": "./esm/index.js"
27
- },
28
- "require": {
29
- "types": "./types/index.d.cts",
30
- "default": "./cjs/index.js"
31
- },
32
- "default": "./esm/index.js"
26
+ "types": "./index.d.ts",
27
+ "default": "./index.js"
33
28
  },
34
29
  "./package.json": "./package.json"
35
30
  },
36
- "main": "./cjs/index.js",
37
- "module": "./esm/index.js",
38
- "types": "./types/index.d.ts",
31
+ "engines": {
32
+ "node": ">=20.0"
33
+ },
39
34
  "repository": {
40
35
  "type": "git",
41
36
  "url": "git+https://github.com/panates/opra.git",
42
37
  "directory": "packages/socketio"
43
38
  },
44
- "engines": {
45
- "node": ">=16.0",
46
- "npm": ">=7.0.0"
47
- },
48
- "files": [
49
- "cjs/",
50
- "esm/",
51
- "types/",
52
- "LICENSE",
53
- "README.md"
54
- ],
55
39
  "keywords": [
56
40
  "opra",
57
41
  "socketio",
@@ -1,19 +1,24 @@
1
1
  import { OpraException, WSApi, } from '@opra/common';
2
2
  import { PlatformAdapter } from '@opra/core';
3
3
  import * as socketio from 'socket.io';
4
+ import { vg } from 'valgen';
4
5
  import { SocketioContext } from './socketio-context.js';
5
6
  /**
6
7
  *
7
8
  * @class SocketioAdapter
8
9
  */
9
10
  export class SocketioAdapter extends PlatformAdapter {
11
+ static PlatformName = 'socketio';
12
+ _controllerInstances = new Map();
13
+ _eventsRegByName = new Map();
14
+ _eventsRegByPattern = [];
15
+ _scope;
16
+ transform = 'ws';
17
+ platform = SocketioAdapter.PlatformName;
18
+ interceptors;
19
+ server;
10
20
  constructor(document, options) {
11
21
  super(options);
12
- this._controllerInstances = new Map();
13
- this._eventsRegByName = new Map();
14
- this._eventsRegByPattern = [];
15
- this.transform = 'ws';
16
- this.platform = SocketioAdapter.PlatformName;
17
22
  this._document = document;
18
23
  if (!(this.document.api instanceof WSApi)) {
19
24
  throw new TypeError(`The document doesn't expose a WS Api`);
@@ -28,6 +33,32 @@ export class SocketioAdapter extends PlatformAdapter {
28
33
  this._initSocket(socket);
29
34
  this.emit('connection', socket, this);
30
35
  });
36
+ }
37
+ get api() {
38
+ return this.document.getWsApi();
39
+ }
40
+ get scope() {
41
+ return this._scope;
42
+ }
43
+ async close() {
44
+ return this.server.close().finally(() => {
45
+ this._controllerInstances.clear();
46
+ this._eventsRegByName.clear();
47
+ this._eventsRegByPattern = [];
48
+ });
49
+ }
50
+ /**
51
+ * Attaches socket.io to a server or port.
52
+ *
53
+ * @param srv - server or port
54
+ * @param opts - options passed to engine.io
55
+ * @return self
56
+ */
57
+ listen(srv, opts) {
58
+ if (this.server.httpServer?.listening)
59
+ throw new Error('Server is already listening');
60
+ if (opts?.path)
61
+ this.server.path(opts?.path);
31
62
  for (const contDef of this.api.controllers.values()) {
32
63
  for (const oprDef of contDef.operations.values()) {
33
64
  const fn = contDef.instance[oprDef.name];
@@ -46,11 +77,16 @@ export class SocketioAdapter extends PlatformAdapter {
46
77
  this._eventsRegByPattern.push(reg);
47
78
  /** Generate decoders */
48
79
  if (oprDef.arguments?.length) {
49
- for (const dt of oprDef.arguments) {
50
- reg.decoders.push(dt.generateCodec('decode', {
80
+ for (const arg of oprDef.arguments) {
81
+ let fn2 = arg.type.generateCodec('decode', {
51
82
  scope: this.scope,
52
83
  ignoreReadonlyFields: true,
53
- }));
84
+ });
85
+ if (arg.required)
86
+ fn2 = vg.required(fn2);
87
+ else
88
+ fn2 = vg.optional(fn2);
89
+ reg.decoders.push(fn2);
54
90
  }
55
91
  }
56
92
  /** Generate response encoder */
@@ -62,28 +98,6 @@ export class SocketioAdapter extends PlatformAdapter {
62
98
  }
63
99
  }
64
100
  }
65
- }
66
- get api() {
67
- return this.document.getWsApi();
68
- }
69
- get scope() {
70
- return this._scope;
71
- }
72
- close() {
73
- return this.server.close();
74
- }
75
- /**
76
- * Attaches socket.io to a server or port.
77
- *
78
- * @param srv - server or port
79
- * @param opts - options passed to engine.io
80
- * @return self
81
- */
82
- listen(srv, opts) {
83
- if (this.server.httpServer?.listening)
84
- throw new Error('Server is already listening');
85
- if (opts?.path)
86
- this.server.path(opts?.path);
87
101
  this.server.listen(srv, opts);
88
102
  return this;
89
103
  }
@@ -100,26 +114,40 @@ export class SocketioAdapter extends PlatformAdapter {
100
114
  this._eventsRegByPattern.find(r => r.event.test(event));
101
115
  if (!reg) {
102
116
  if (callback)
103
- callback(new Error(`Unknown event "${event}"`));
117
+ callback(new OpraException(`Unknown event "${event}"`));
104
118
  return;
105
119
  }
106
- const parameters = callback ? args.slice(0, -1) : args;
107
120
  Promise.resolve().then(async () => {
108
- const ctx = new SocketioContext({
109
- __adapter: this,
110
- __contDef: reg.contDef,
111
- __oprDef: reg.oprDef,
112
- __controller: reg.contDef.instance,
113
- __handler: reg.handler,
114
- socket,
115
- event,
116
- parameters,
117
- });
118
121
  try {
119
- let x = await reg.handler.apply(reg.contDef.instance, [
120
- ctx,
121
- ...parameters,
122
- ]);
122
+ const inputParameters = callback ? args.slice(0, -1) : args;
123
+ const ctx = new SocketioContext({
124
+ __adapter: this,
125
+ __contDef: reg.contDef,
126
+ __oprDef: reg.oprDef,
127
+ __controller: reg.contDef.instance,
128
+ __handler: reg.handler,
129
+ socket,
130
+ event,
131
+ });
132
+ const callArgs = [ctx];
133
+ let i = 0;
134
+ for (const prm of inputParameters) {
135
+ try {
136
+ const v = reg.decoders[i](prm);
137
+ const arg = reg.oprDef.arguments[i];
138
+ ctx.parameters.push(v);
139
+ if (arg.parameterIndex != null)
140
+ callArgs[arg.parameterIndex] = v;
141
+ else
142
+ callArgs.push(v);
143
+ }
144
+ catch (err) {
145
+ err.message = `Failed to decode parameter ${i} of event "${event}": ${err.message}`;
146
+ throw err;
147
+ }
148
+ i++;
149
+ }
150
+ let x = await reg.handler.apply(reg.contDef.instance, callArgs);
123
151
  if (reg.encoder)
124
152
  x = reg.encoder(x);
125
153
  if (x != null && typeof x !== 'string')
@@ -127,8 +155,8 @@ export class SocketioAdapter extends PlatformAdapter {
127
155
  callback(x);
128
156
  }
129
157
  catch (err) {
130
- const error = new OpraException(err);
131
- callback(error);
158
+ const error = err instanceof OpraException ? err : new OpraException(err);
159
+ callback({ error });
132
160
  }
133
161
  });
134
162
  });
@@ -138,4 +166,3 @@ export class SocketioAdapter extends PlatformAdapter {
138
166
  return controller && this._controllerInstances.get(controller);
139
167
  }
140
168
  }
141
- SocketioAdapter.PlatformName = 'socketio';
@@ -4,6 +4,9 @@ import { ExecutionContext } from '@opra/core';
4
4
  * It extends the ExecutionContext and implements the AsyncEventEmitter.
5
5
  */
6
6
  export class SocketioContext extends ExecutionContext {
7
+ socket;
8
+ event;
9
+ parameters = [];
7
10
  /**
8
11
  * Constructor
9
12
  * @param init the context options
@@ -17,7 +20,6 @@ export class SocketioContext extends ExecutionContext {
17
20
  transport: 'ws',
18
21
  platform: 'socketio',
19
22
  });
20
- this.parameters = [];
21
23
  this.socket = init.socket;
22
24
  this.event = init.event;
23
25
  this.parameters = init.parameters || [];
package/cjs/index.js DELETED
@@ -1,6 +0,0 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- const tslib_1 = require("tslib");
4
- // export * from './constants.js';
5
- tslib_1.__exportStar(require("./socketio-adapter.js"), exports);
6
- tslib_1.__exportStar(require("./socketio-context.js"), exports);
package/cjs/package.json DELETED
@@ -1,3 +0,0 @@
1
- {
2
- "type": "commonjs"
3
- }
@@ -1,146 +0,0 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.SocketioAdapter = void 0;
4
- const tslib_1 = require("tslib");
5
- const common_1 = require("@opra/common");
6
- const core_1 = require("@opra/core");
7
- const socketio = tslib_1.__importStar(require("socket.io"));
8
- const socketio_context_js_1 = require("./socketio-context.js");
9
- /**
10
- *
11
- * @class SocketioAdapter
12
- */
13
- class SocketioAdapter extends core_1.PlatformAdapter {
14
- constructor(document, options) {
15
- super(options);
16
- this._controllerInstances = new Map();
17
- this._eventsRegByName = new Map();
18
- this._eventsRegByPattern = [];
19
- this.transform = 'ws';
20
- this.platform = SocketioAdapter.PlatformName;
21
- this._document = document;
22
- if (!(this.document.api instanceof common_1.WSApi)) {
23
- throw new TypeError(`The document doesn't expose a WS Api`);
24
- }
25
- this.interceptors = [...(options?.interceptors || [])];
26
- this._scope = options?.scope;
27
- this.server = new socketio.Server();
28
- this.server.on('error', error => {
29
- this.emit('error', error, undefined, this);
30
- });
31
- this.server.on('connection', (socket) => {
32
- this._initSocket(socket);
33
- this.emit('connection', socket, this);
34
- });
35
- for (const contDef of this.api.controllers.values()) {
36
- for (const oprDef of contDef.operations.values()) {
37
- const fn = contDef.instance[oprDef.name];
38
- if (typeof fn !== 'function')
39
- continue;
40
- const reg = {
41
- event: oprDef.event,
42
- contDef,
43
- oprDef,
44
- handler: fn,
45
- decoders: [],
46
- };
47
- if (typeof reg.event === 'string')
48
- this._eventsRegByName.set(reg.event, reg);
49
- else
50
- this._eventsRegByPattern.push(reg);
51
- /** Generate decoders */
52
- if (oprDef.arguments?.length) {
53
- for (const dt of oprDef.arguments) {
54
- reg.decoders.push(dt.generateCodec('decode', {
55
- scope: this.scope,
56
- ignoreReadonlyFields: true,
57
- }));
58
- }
59
- }
60
- /** Generate response encoder */
61
- if (oprDef.response) {
62
- reg.encoder = oprDef.response.generateCodec('encode', {
63
- scope: this.scope,
64
- ignoreWriteonlyFields: true,
65
- });
66
- }
67
- }
68
- }
69
- }
70
- get api() {
71
- return this.document.getWsApi();
72
- }
73
- get scope() {
74
- return this._scope;
75
- }
76
- close() {
77
- return this.server.close();
78
- }
79
- /**
80
- * Attaches socket.io to a server or port.
81
- *
82
- * @param srv - server or port
83
- * @param opts - options passed to engine.io
84
- * @return self
85
- */
86
- listen(srv, opts) {
87
- if (this.server.httpServer?.listening)
88
- throw new Error('Server is already listening');
89
- if (opts?.path)
90
- this.server.path(opts?.path);
91
- this.server.listen(srv, opts);
92
- return this;
93
- }
94
- _initSocket(socket) {
95
- socket.on('close', () => {
96
- this.emit('close', socket, this);
97
- });
98
- socket.on('error', error => {
99
- this.emit('error', error, socket, this);
100
- });
101
- socket.onAny((event, ...args) => {
102
- const callback = args.length > 0 ? args[args.length - 1] : null;
103
- const reg = this._eventsRegByName.get(event) ||
104
- this._eventsRegByPattern.find(r => r.event.test(event));
105
- if (!reg) {
106
- if (callback)
107
- callback(new Error(`Unknown event "${event}"`));
108
- return;
109
- }
110
- const parameters = callback ? args.slice(0, -1) : args;
111
- Promise.resolve().then(async () => {
112
- const ctx = new socketio_context_js_1.SocketioContext({
113
- __adapter: this,
114
- __contDef: reg.contDef,
115
- __oprDef: reg.oprDef,
116
- __controller: reg.contDef.instance,
117
- __handler: reg.handler,
118
- socket,
119
- event,
120
- parameters,
121
- });
122
- try {
123
- let x = await reg.handler.apply(reg.contDef.instance, [
124
- ctx,
125
- ...parameters,
126
- ]);
127
- if (reg.encoder)
128
- x = reg.encoder(x);
129
- if (x != null && typeof x !== 'string')
130
- x = JSON.stringify(x);
131
- callback(x);
132
- }
133
- catch (err) {
134
- const error = new common_1.OpraException(err);
135
- callback(error);
136
- }
137
- });
138
- });
139
- }
140
- getControllerInstance(controllerPath) {
141
- const controller = this.api.findController(controllerPath);
142
- return controller && this._controllerInstances.get(controller);
143
- }
144
- }
145
- exports.SocketioAdapter = SocketioAdapter;
146
- SocketioAdapter.PlatformName = 'socketio';
@@ -1,40 +0,0 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.SocketioContext = void 0;
4
- const core_1 = require("@opra/core");
5
- /**
6
- * Provides the context for handling messages.
7
- * It extends the ExecutionContext and implements the AsyncEventEmitter.
8
- */
9
- class SocketioContext extends core_1.ExecutionContext {
10
- /**
11
- * Constructor
12
- * @param init the context options
13
- */
14
- constructor(init) {
15
- super({
16
- ...init,
17
- __docNode: init.__oprDef?.node ||
18
- init.__contDef?.node ||
19
- init.__adapter.document.node,
20
- transport: 'ws',
21
- platform: 'socketio',
22
- });
23
- this.parameters = [];
24
- this.socket = init.socket;
25
- this.event = init.event;
26
- this.parameters = init.parameters || [];
27
- if (init.__contDef)
28
- this.__contDef = init.__contDef;
29
- if (init.__controller)
30
- this.__controller = init.__controller;
31
- if (init.__oprDef)
32
- this.__oprDef = init.__oprDef;
33
- if (init.__handler)
34
- this.__handler = init.__handler;
35
- }
36
- get server() {
37
- return this.__adapter.server;
38
- }
39
- }
40
- exports.SocketioContext = SocketioContext;
package/esm/package.json DELETED
@@ -1,3 +0,0 @@
1
- {
2
- "type": "module"
3
- }
package/types/index.d.cts DELETED
@@ -1,2 +0,0 @@
1
- export * from './socketio-adapter.js';
2
- export * from './socketio-context.js';
File without changes
File without changes