Socket
Socket
Sign inDemoInstall

metacom

Package Overview
Dependencies
Maintainers
1
Versions
70
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

metacom - npm Package Compare versions

Comparing version 3.0.0-alpha.4 to 3.0.0-alpha.5

12

CHANGELOG.md

@@ -5,2 +5,11 @@ # Changelog

## [3.0.0-alpha.5][] - 2022-12-23
- Move `serveStatic` to impress
- Fix path separaton in url for windows
- Fix serving static files
- Use `fetch` polyfill from metautil
- Optimize abstractions
- Update dependencies
## [3.0.0-alpha.4][] - 2022-07-30

@@ -223,3 +232,4 @@

[unreleased]: https://github.com/metarhia/metacom/compare/v3.0.0-alpha.4...HEAD
[unreleased]: https://github.com/metarhia/metacom/compare/v3.0.0-alpha.5...HEAD
[3.0.0-alpha.5]: https://github.com/metarhia/metacom/compare/v3.0.0-alpha.4...v3.0.0-alpha.5
[3.0.0-alpha.4]: https://github.com/metarhia/metacom/compare/v3.0.0-alpha.3...v3.0.0-alpha.4

@@ -226,0 +236,0 @@ [3.0.0-alpha.3]: https://github.com/metarhia/metacom/compare/v3.0.0-alpha.2...v3.0.0-alpha.3

26

dist/events.js

@@ -14,3 +14,2 @@ const warnAboutMemoryLeak = (eventName, count) =>

}
getMaxListeners() {

@@ -46,7 +45,16 @@ return this.maxListenersCount;

emit(name, ...args) {
if (name === '*') {
throw new Error('Cannot emit reserved "*" global listeners.');
}
const event = this.events.get(name);
if (!event) return;
for (const fn of event.values()) {
fn(...args);
if (event) {
for (const fn of event.values()) {
fn(...args);
}
}
const globalListeners = this.events.get('*');
if (!globalListeners) return;
for (const fn of globalListeners.values()) {
fn(name, ...args);
}
}

@@ -63,5 +71,11 @@

clear(name) {
if (name) this.events.delete(name);
else this.events.clear();
const globalListeners = this.events.get('*');
if (!name) {
this.events.clear();
globalListeners.clear();
return;
}
if (name === '*') globalListeners.clear();
else this.events.delete(name);
}
}
import EventEmitter from './events.js';
import { MetacomChunk, MetacomReadable, MetacomWritable } from './streams.js';
import { Chunk, MetaReadable, MetaWritable } from './streams.js';

@@ -39,2 +39,3 @@ const CALL_TIMEOUT = 7 * 1000;

this.streamId = 0;
this.eventId = 0;
this.active = false;

@@ -66,3 +67,3 @@ this.connected = false;

const transport = this;
return new MetacomWritable(transport, initData);
return new MetaWritable(transport, initData);
}

@@ -122,3 +123,3 @@

const streamData = { streamId, name, size };
const stream = new MetacomReadable(streamData);
const stream = new MetaReadable(streamData);
this.streams.set(streamId, stream);

@@ -144,3 +145,3 @@ }

const byteView = new Uint8Array(buffer);
const { streamId, payload } = MetacomChunk.decode(byteView);
const { streamId, payload } = Chunk.decode(byteView);
const stream = this.streams.get(streamId);

@@ -164,2 +165,7 @@ if (stream) await stream.push(payload);

}
methods.on('*', (eventName, data) => {
const target = `${interfaceName}/${eventName}`;
const packet = { event: ++this.eventId, [target]: data };
this.send(JSON.stringify(packet));
});
this.api[interfaceName] = methods;

@@ -166,0 +172,0 @@ }

@@ -17,3 +17,3 @@ import EventEmitter from './events.js';

class MetacomChunk {
class Chunk {
static encode(streamId, payload) {

@@ -39,3 +39,3 @@ const streamIdView = new Uint8Array(createStreamIdBuffer(streamId));

class MetacomReadable extends EventEmitter {
class MetaReadable extends EventEmitter {
constructor(initData, options = {}) {

@@ -149,3 +149,3 @@ super();

class MetacomWritable extends EventEmitter {
class MetaWritable extends EventEmitter {
constructor(transport, initData) {

@@ -170,3 +170,3 @@ super();

write(data) {
const chunk = MetacomChunk.encode(this.streamId, data);
const chunk = Chunk.encode(this.streamId, data);
this.transport.send(chunk);

@@ -186,2 +186,2 @@ }

export { MetacomChunk, MetacomReadable, MetacomWritable };
export { Chunk, MetaReadable, MetaWritable };
'use strict';
const http = require('http');
const { EventEmitter } = require('events');
const metautil = require('metautil');
const {
MetacomReadable,
MetacomWritable,
MetacomChunk,
} = require('./streams.js');
const { MetaReadable, MetaWritable, Chunk } = require('./streams.js');

@@ -16,3 +13,3 @@ const EMPTY_PACKET = Buffer.from('{}');

this.token = token;
this.channel = channel;
this.channels = new Set([channel]);
this.data = data;

@@ -27,3 +24,3 @@ this.context = new Proxy(data, {

const res = Reflect.set(data, key, value);
channel.application.auth.saveSession(token, data);
channel.auth.saveSession(token, data);
return res;

@@ -36,7 +33,9 @@ },

const sessions = new Map(); // token: Session
const channels = new Map(); // Client: Channel
class Client {
constructor() {
this.events = { close: [] };
class Client extends EventEmitter {
#channel;
constructor(channel) {
super();
this.#channel = channel;
this.eventId = 0;

@@ -48,28 +47,23 @@ this.streams = new Map();

redirect(location) {
const channel = channels.get(this);
if (channel) channel.redirect(location);
if (this.#channel) this.#channel.redirect(location);
}
get ip() {
const channel = channels.get(this);
return channel ? channel.ip : undefined;
return this.#channel ? this.#channel.ip : undefined;
}
on(name, callback) {
if (name !== 'close') return;
this.events.close.push(callback);
}
emit(name, data) {
if (name === 'close') {
super.emit(name, data);
return;
}
const packet = { event: --this.eventId, [name]: data };
const channel = channels.get(this);
if (!channel || !channel.connection) {
if (!this.#channel || !this.#channel.connection) {
throw new Error(`Can't send metacom events to http transport`);
}
channel.send(packet);
this.#channel.send(packet);
}
getStream(streamId) {
const channel = channels.get(this);
if (!channel.connection) {
if (!this.#channel.connection) {
throw new Error(`Can't receive stream from http transport`);

@@ -83,4 +77,3 @@ }

createStream(name, size) {
const channel = channels.get(this);
if (!channel.connection) {
if (!this.#channel.connection) {
throw new Error(`Can't send metacom streams to http transport`);

@@ -92,12 +85,11 @@ }

const initData = { streamId, name, size };
const transport = channel.connection;
return new MetacomWritable(transport, initData);
const transport = this.#channel.connection;
return new MetaWritable(transport, initData);
}
startSession(token, data = {}) {
const channel = channels.get(this);
if (!channel) return false;
if (channel.session) sessions.delete(channel.session.token);
const session = new Session(token, channel, data);
channel.session = session;
if (!this.#channel) return false;
if (this.#channel.session) sessions.delete(this.#channel.session.token);
const session = new Session(token, this.#channel, data);
this.#channel.session = session;
sessions.set(token, session);

@@ -110,5 +102,4 @@ return true;

if (!session) return false;
const channel = channels.get(this);
if (!channel) return false;
channel.session = session;
if (!this.#channel) return false;
this.#channel.session = session;
return true;

@@ -120,6 +111,5 @@ }

if (!session) return false;
const channel = channels.get(this);
if (!channel.session) return false;
sessions.delete(channel.session.token);
channel.session = null;
if (!this.#channel.session) return false;
sessions.delete(this.#channel.session.token);
this.#channel.session = null;
return true;

@@ -130,9 +120,10 @@ }

class Channel {
constructor(application, req, res) {
this.application = application;
constructor(server, req, res) {
this.server = server;
this.auth = server.application.auth;
this.console = server.application.console;
this.req = req;
this.res = res;
this.ip = req.socket.remoteAddress;
this.client = new Client();
channels.set(this.client, this);
this.client = new Client(this);
this.session = null;

@@ -172,3 +163,3 @@ this.restoreSession();

try {
const { streamId, payload } = MetacomChunk.decode(data);
const { streamId, payload } = Chunk.decode(data);
const upstream = this.client.streams.get(streamId);

@@ -208,3 +199,3 @@ if (upstream) {

const streamData = { streamId, name, size };
const stream = new MetacomReadable(streamData);
const stream = new MetaReadable(streamData);
this.client.streams.set(streamId, stream);

@@ -228,5 +219,5 @@ }

async rpc(callId, interfaceName, methodName, args) {
const { application, session, client } = this;
const { server, console, session, client } = this;
const [iname, ver = '*'] = interfaceName.split('.');
const proc = application.getMethod(iname, ver, methodName);
const proc = server.application.getMethod(iname, ver, methodName);
if (!proc) {

@@ -265,8 +256,7 @@ this.error(404, { callId });

this.send({ callback: callId, result });
const record = `${this.ip}\t${interfaceName}/${methodName}`;
application.console.log(record);
console.log(`${this.ip}\t${interfaceName}/${methodName}`);
}
error(code = 500, { callId, error = null, httpCode = null } = {}) {
const { req, ip, application } = this;
const { console, req, ip } = this;
const { url, method } = req;

@@ -278,3 +268,3 @@ if (!httpCode) httpCode = (error && error.httpCode) || code;

const reason = `${httpCode}\t${code}\t${error ? error.stack : status}`;
application.console.error(`${ip}\t${method}\t${url}\t${reason}`);
console.error(`${ip}\t${method}\t${url}\t${reason}`);
const packet = { callback: callId, error: { message, code } };

@@ -290,3 +280,3 @@ this.send(packet, httpCode);

if (!token) return null;
const session = await this.application.auth.restoreSession(token);
const session = await this.auth.restoreSession(token);
if (!session) return null;

@@ -297,4 +287,3 @@ return session;

destroy() {
channels.delete(this.client);
for (const callback of this.client.events.close) callback();
this.emit('close');
if (!this.session) return;

@@ -305,2 +294,2 @@ sessions.delete(this.session.token);

module.exports = { Channel, channels };
module.exports = { Channel };
'use strict';
const http = require('http');
const https = require('https');
const { EventEmitter } = require('events');
const transport = { http, https };
const WebSocket = require('ws');
const { MetacomWritable, MetacomReadable, MetacomChunk } = require('./streams');
const metautil = require('metautil');
const { MetaWritable, MetaReadable, Chunk } = require('./streams.js');

@@ -17,18 +15,3 @@ class MetacomError extends Error {

const fetch = (url, options) => {
const dest = new URL(url);
return new Promise((resolve, reject) => {
const protocol = transport[dest.protocol.slice(0, -1)];
const req = protocol.request(url, options, async (res) => {
const buffers = [];
for await (const chunk of res) {
buffers.push(chunk);
}
resolve(Buffer.concat(buffers).toString());
});
req.on('error', reject);
req.write(options.body);
req.end();
});
};
class MetacomInterface extends EventEmitter {}

@@ -99,3 +82,3 @@ class Metacom extends EventEmitter {

const streamData = { streamId, name, size };
const stream = new MetacomReadable(streamData);
const stream = new MetaReadable(streamData);
this.streams.set(streamId, stream);

@@ -120,3 +103,3 @@ }

const byteView = new Uint8Array(buffer);
const { streamId, payload } = MetacomChunk.decode(byteView);
const { streamId, payload } = Chunk.decode(byteView);
const stream = this.streams.get(streamId);

@@ -144,3 +127,3 @@ if (stream) await stream.push(payload);

if (!available.includes(interfaceName)) continue;
const methods = {};
const methods = new MetacomInterface();
const iface = introspection[interfaceName];

@@ -168,3 +151,3 @@ const request = this.socketCall(interfaceName);

const transport = this;
return new MetacomWritable(transport, initData);
return new MetaWritable(transport, initData);
}

@@ -191,3 +174,3 @@

return (methodName) =>
(args = {}) => {
async (args = {}) => {
const callId = ++this.callId;

@@ -200,11 +183,10 @@ const interfaceName = ver ? `${iname}.${ver}` : iname;

const url = `${protocol}://${dest.host}/api`;
return fetch(url, {
const res = metautil.fetch(url, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify(packet),
}).then((json) => {
const packet = JSON.parse(json);
if (packet.error) throw new MetacomError(packet.error);
return packet.result;
});
const data = await res.json();
if (data.error) throw new MetacomError(data.error);
return data.result;
};

@@ -211,0 +193,0 @@ }

@@ -87,4 +87,4 @@ 'use strict';

class HttpChannel extends Channel {
constructor(application, req, res) {
super(application, req, res);
constructor(server, req, res) {
super(server, req, res);
res.on('close', () => {

@@ -123,3 +123,3 @@ this.destroy();

async hook(proc, interfaceName, methodName, args, headers) {
const { application, client, req } = this;
const { console, client, req } = this;
const verb = req.method;

@@ -141,11 +141,10 @@ const callId = -1;

this.send(result);
const record = `${this.ip}\t${interfaceName}/${methodName}`;
application.console.log(record);
console.log(`${this.ip}\t${interfaceName}/${methodName}`);
}
startSession() {
const token = this.application.auth.generateToken();
const token = this.auth.generateToken();
const host = metautil.parseHost(this.req.headers.host);
const cookie = `${TOKEN}=${token}; ${COOKIE_HOST}=${host}`;
const session = this.application.auth.startSession();
const session = this.auth.startSession();
if (this.res) this.res.setHeader('Set-Cookie', cookie);

@@ -160,8 +159,7 @@ return session;

this.res.setHeader('Set-Cookie', COOKIE_DELETE + host);
this.application.auth.deleteSession(token);
this.auth.deleteSession(token);
}
}
const createChannel = (application, req, res) =>
new HttpChannel(application, req, res);
const createChannel = (server, req, res) => new HttpChannel(server, req, res);

@@ -168,0 +166,0 @@ const addHeaders = (headers) => {

@@ -8,5 +8,6 @@ 'use strict';

const ws = require('ws');
const { channels } = require('./channel.js');
const { serveStatic } = require('./static.js');
const transport = require('./transport.js');
const transport = {
http: require('./http.js'),
ws: require('./ws.js'),
};

@@ -20,2 +21,3 @@ const SHORT_TIMEOUT = 500;

this.application = application;
this.console = application.console;
if (cors) transport.http.addHeaders(cors);

@@ -26,3 +28,3 @@ const concurrency = queue.concurrency || options.concurrency;

this.ws = null;
this.channels = channels;
this.channels = new Set();
this.bind();

@@ -32,3 +34,3 @@ }

bind() {
const { options, application } = this;
const { options, application, console } = this;
const { host, port, kind, protocol, timeouts, nagle = true } = options;

@@ -44,11 +46,12 @@ const proto = protocol === 'http' || kind === 'balancer' ? http : https;

this.server.on('listening', () => {
application.console.info(`Listen port ${port}`);
console.info(`Listen port ${port}`);
});
this.ws = new ws.Server({ server: this.server });
this.ws.on('connection', (connection, req) => {
transport.ws.createChannel(application, req, connection);
const channel = transport.ws.createChannel(this, req, connection);
this.channels.add(channel);
});
this.ws.on('error', (err) => {
if (err.code !== 'EADDRINUSE') return;
application.console.warn(`Address in use: ${host}:${port}, retry...`);
console.warn(`Address in use: ${host}:${port}, retry...`);
setTimeout(() => {

@@ -63,3 +66,4 @@ this.bind();

const { url } = req;
const channel = transport.http.createChannel(this.application, req, res);
const channel = transport.http.createChannel(this, req, res);
this.channels.add(channel);
if (this.options.kind === 'balancer') {

@@ -73,3 +77,3 @@ const host = metautil.parseHost(req.headers.host);

if (url.startsWith('/api')) this.request(channel);
else serveStatic(channel);
else this.application.serveStatic(channel);
}

@@ -131,3 +135,3 @@

this.server.close((err) => {
if (err) this.application.console.error(err);
if (err) this.console.error(err);
});

@@ -134,0 +138,0 @@ if (this.channels.size === 0) {

@@ -20,3 +20,3 @@ 'use strict';

class MetacomChunk {
class Chunk {
static encode(streamId, payload) {

@@ -42,3 +42,3 @@ const streamIdView = new Uint8Array(createStreamIdBuffer(streamId));

class MetacomReadable extends EventEmitter {
class MetaReadable extends EventEmitter {
constructor(initData, options = {}) {

@@ -153,3 +153,3 @@ super();

class MetacomWritable extends EventEmitter {
class MetaWritable extends EventEmitter {
constructor(transport, initData) {

@@ -175,3 +175,3 @@ super();

write(data) {
const chunk = MetacomChunk.encode(this.streamId, data);
const chunk = Chunk.encode(this.streamId, data);
this.transport.send(chunk);

@@ -193,6 +193,2 @@ return true;

module.exports = {
MetacomChunk,
MetacomReadable,
MetacomWritable,
};
module.exports = { Chunk, MetaReadable, MetaWritable };

@@ -6,4 +6,4 @@ 'use strict';

class WsChannel extends Channel {
constructor(application, req, connection) {
super(application, req);
constructor(server, req, connection) {
super(server, req);
this.connection = connection;

@@ -28,5 +28,5 @@ connection.on('message', (data, isBinary) => {

const createChannel = (application, req, connection) =>
new WsChannel(application, req, connection);
const createChannel = (server, req, connection) =>
new WsChannel(server, req, connection);
module.exports = { createChannel };

@@ -11,3 +11,3 @@ import { EventEmitter } from 'events';

export class MetacomReadable extends EventEmitter {
export class MetaReadable extends EventEmitter {
streamId: number;

@@ -22,3 +22,3 @@ name: string;

export class MetacomWritable extends EventEmitter {
export class MetaWritable extends EventEmitter {
streamId: number;

@@ -55,4 +55,4 @@ name: string;

): (methodName: string) => (args: object) => Promise<void>;
getStream(streamId: number): MetacomReadable;
createStream(name: string, size: number): MetacomWritable;
getStream(streamId: number): MetaReadable;
createStream(name: string, size: number): MetaWritable;
createBlobUploader(blob: Blob): BlobUploader;

@@ -81,2 +81,12 @@ }

export interface Auth {
generateToken(): string;
saveSession(token: string, data: object): void;
startSession(token: string, data: object, fields?: object): void;
restoreSession(token: string): Promise<object | null>;
deleteSession(token: string): void;
registerUser(login: string, password: string): Promise<object>;
getUser(login: string): Promise<object>;
}
export class Client extends EventEmitter {

@@ -87,8 +97,8 @@ ip: string | undefined;

events: { close: Array<Function> };
streams: Map<number, MetacomReadable>;
streams: Map<number, MetaReadable>;
redirect(location: string): void;
startSession(token: string, data: object): boolean;
restoreSession(token: string): boolean;
getStream(streamId: number): MetacomReadable;
createStream(name: string, size: number): MetacomWritable;
getStream(streamId: number): MetaReadable;
createStream(name: string, size: number): MetaWritable;
}

@@ -98,2 +108,4 @@

application: object;
console: Console;
auth: Auth;
req: ClientRequest;

@@ -152,2 +164,3 @@ res: ServerResponse;

application: object;
console: Console;
semaphore: Semaphore;

@@ -154,0 +167,0 @@ server?: any;

{
"name": "metacom",
"version": "3.0.0-alpha.4",
"version": "3.0.0-alpha.5",
"author": "Timur Shemsedinov <timur.shemsedinov@gmail.com>",

@@ -53,12 +53,12 @@ "description": "Communication protocol for Metarhia stack with rpc, events, binary streams, memory and db access",

"engines": {
"node": "14 || 16 || 18"
"node": "14 || 16 || 18 || 19"
},
"dependencies": {
"metautil": "^3.5.22",
"ws": "^8.8.1"
"metautil": "^3.6.0",
"ws": "^8.11.0"
},
"devDependencies": {
"@types/node": "^18.6.2",
"@types/node": "^18.11.17",
"@types/ws": "^8.5.3",
"eslint": "^8.20.0",
"eslint": "^8.30.0",
"eslint-config-metarhia": "^8.1.0",

@@ -69,5 +69,5 @@ "eslint-config-prettier": "^8.5.0",

"metatests": "^0.8.2",
"prettier": "^2.6.2",
"typescript": "^4.6.4"
"prettier": "^2.8.1",
"typescript": "^4.9.4"
}
}
SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc