refactor: move to ci and update deps
This commit is contained in:
parent
31ac340721
commit
1fb9c77d55
|
@ -0,0 +1,13 @@
|
|||
name: Build/Publish
|
||||
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- master
|
||||
- develop
|
||||
- develop-*
|
||||
|
||||
jobs:
|
||||
main:
|
||||
uses: lumeweb/github-node-deploy-workflow/.github/workflows/main.yml@master
|
||||
secrets: inherit
|
|
@ -0,0 +1,5 @@
|
|||
{
|
||||
"preset": [
|
||||
"@lumeweb/node-library-preset"
|
||||
]
|
||||
}
|
|
@ -1,44 +0,0 @@
|
|||
/// <reference types="node" />
|
||||
import EventEmitter from "events";
|
||||
export default class ProtomuxRPC extends EventEmitter {
|
||||
private _id;
|
||||
private _ending;
|
||||
private _error?;
|
||||
private _responding;
|
||||
private _requests;
|
||||
private _defaultValueEncoding;
|
||||
private _responders;
|
||||
private _channel;
|
||||
private _request;
|
||||
private _response;
|
||||
constructor(stream: any, options?: any);
|
||||
private _mux;
|
||||
get mux(): any;
|
||||
private _ready;
|
||||
get ready(): Promise<void>;
|
||||
get closed(): any;
|
||||
get stream(): any;
|
||||
private _init;
|
||||
_onopen(handshake: any): void;
|
||||
_onclose(): void;
|
||||
_ondestroy(): void;
|
||||
_onrequest({ id, method, value, }: {
|
||||
id: number;
|
||||
method: string;
|
||||
value: any;
|
||||
}): Promise<void>;
|
||||
_onresponse({ id, error, value }: {
|
||||
id: number;
|
||||
error: string;
|
||||
value: any;
|
||||
}): void;
|
||||
respond(method: string, options: Function | any, handler: Function): this;
|
||||
unrespond(method: string): this;
|
||||
request(method: string, value: any, options?: any): Promise<unknown>;
|
||||
event(method: string, value: any, options?: any): void;
|
||||
cork(): void;
|
||||
uncork(): void;
|
||||
end(): Promise<void>;
|
||||
_endMaybe(): void;
|
||||
destroy(err: Error): void;
|
||||
}
|
|
@ -1,224 +0,0 @@
|
|||
import EventEmitter from "events";
|
||||
// @ts-ignore
|
||||
import Protomux from "@lumeweb/kernel-protomux-client";
|
||||
// @ts-ignore
|
||||
import c from "compact-encoding";
|
||||
// @ts-ignore
|
||||
import bitfield from "compact-encoding-bitfield";
|
||||
// @ts-ignore
|
||||
import bits from "bits-to-bytes";
|
||||
export default class ProtomuxRPC extends EventEmitter {
|
||||
_id;
|
||||
_ending;
|
||||
_error;
|
||||
_responding;
|
||||
_requests;
|
||||
_defaultValueEncoding;
|
||||
_responders;
|
||||
_channel;
|
||||
_request;
|
||||
_response;
|
||||
constructor(stream, options = {}) {
|
||||
super();
|
||||
this._mux = Protomux.from(stream);
|
||||
this._defaultValueEncoding = options?.valueEncoding;
|
||||
this._id = 1;
|
||||
this._ending = false;
|
||||
this._responding = 0;
|
||||
this._requests = new Map();
|
||||
this._responders = new Map();
|
||||
this._ready = this._init(options);
|
||||
}
|
||||
_mux;
|
||||
get mux() {
|
||||
return this._mux;
|
||||
}
|
||||
_ready;
|
||||
get ready() {
|
||||
return this._ready;
|
||||
}
|
||||
get closed() {
|
||||
return this._channel.closed;
|
||||
}
|
||||
get stream() {
|
||||
return this._mux.stream;
|
||||
}
|
||||
async _init(options) {
|
||||
this._channel = await this._mux.createChannel({
|
||||
protocol: "protomux-rpc",
|
||||
id: options?.id,
|
||||
handshake: options?.handshake
|
||||
? options?.handshakeEncoding || c.raw
|
||||
: null,
|
||||
onopen: this._onopen.bind(this),
|
||||
onclose: this._onclose.bind(this),
|
||||
ondestroy: this._ondestroy.bind(this),
|
||||
});
|
||||
if (this._channel === null)
|
||||
throw new Error("duplicate channel");
|
||||
this._request = await this._channel.addMessage({
|
||||
encoding: request,
|
||||
onmessage: this._onrequest.bind(this),
|
||||
});
|
||||
this._response = await this._channel.addMessage({
|
||||
encoding: response,
|
||||
onmessage: this._onresponse.bind(this),
|
||||
});
|
||||
await this._channel.open(options?.handshake);
|
||||
}
|
||||
_onopen(handshake) {
|
||||
this.emit("open", handshake);
|
||||
}
|
||||
_onclose() {
|
||||
const err = this._error || new Error("channel closed");
|
||||
for (const request of this._requests.values()) {
|
||||
request.reject(err);
|
||||
}
|
||||
this._requests.clear();
|
||||
this._responders.clear();
|
||||
this.emit("close");
|
||||
}
|
||||
_ondestroy() {
|
||||
this.emit("destroy");
|
||||
}
|
||||
async _onrequest({ id, method, value, }) {
|
||||
let error = null;
|
||||
const responder = this._responders.get(method);
|
||||
if (responder === undefined)
|
||||
error = `unknown method '${method}'`;
|
||||
else {
|
||||
const { valueEncoding = this._defaultValueEncoding, requestEncoding = valueEncoding, responseEncoding = valueEncoding, } = responder.options;
|
||||
if (requestEncoding)
|
||||
value = c.decode(requestEncoding, value);
|
||||
this._responding++;
|
||||
try {
|
||||
value = await responder.handler(value);
|
||||
}
|
||||
catch (err) {
|
||||
error = err.message;
|
||||
}
|
||||
this._responding--;
|
||||
if (!error && responseEncoding && id) {
|
||||
value = c.encode(responseEncoding, value);
|
||||
}
|
||||
}
|
||||
if (id)
|
||||
this._response.send({ id, error, value });
|
||||
this._endMaybe();
|
||||
}
|
||||
_onresponse({ id, error, value }) {
|
||||
if (id === 0)
|
||||
return;
|
||||
const request = this._requests.get(id);
|
||||
if (request === undefined)
|
||||
return;
|
||||
this._requests.delete(id);
|
||||
if (error)
|
||||
request.reject(new Error(error));
|
||||
else {
|
||||
const { valueEncoding = this._defaultValueEncoding, responseEncoding = valueEncoding, } = request.options;
|
||||
if (responseEncoding)
|
||||
value = c.decode(responseEncoding, value);
|
||||
request.resolve(value);
|
||||
}
|
||||
this._endMaybe();
|
||||
}
|
||||
respond(method, options, handler) {
|
||||
if (typeof options === "function") {
|
||||
handler = options;
|
||||
options = {};
|
||||
}
|
||||
this._responders.set(method, { options, handler });
|
||||
return this;
|
||||
}
|
||||
unrespond(method) {
|
||||
this._responders.delete(method);
|
||||
return this;
|
||||
}
|
||||
async request(method, value, options = {}) {
|
||||
if (this.closed)
|
||||
throw new Error("channel closed");
|
||||
const { valueEncoding = this._defaultValueEncoding, requestEncoding = valueEncoding, } = options;
|
||||
if (requestEncoding)
|
||||
value = c.encode(requestEncoding, value);
|
||||
const id = this._id++;
|
||||
this._request.send({ id, method, value });
|
||||
return new Promise((resolve, reject) => {
|
||||
this._requests.set(id, { options, resolve, reject });
|
||||
});
|
||||
}
|
||||
event(method, value, options = {}) {
|
||||
if (this.closed)
|
||||
throw new Error("channel closed");
|
||||
const { valueEncoding = this._defaultValueEncoding, requestEncoding = valueEncoding, } = options;
|
||||
if (requestEncoding)
|
||||
value = c.encode(requestEncoding, value);
|
||||
this._request.send({ id: 0, method, value });
|
||||
}
|
||||
cork() {
|
||||
this._channel.cork();
|
||||
}
|
||||
uncork() {
|
||||
this._channel.uncork();
|
||||
}
|
||||
async end() {
|
||||
this._ending = true;
|
||||
this._endMaybe();
|
||||
await EventEmitter.once(this, "close");
|
||||
}
|
||||
_endMaybe() {
|
||||
if (this._ending && this._responding === 0 && this._requests.size === 0) {
|
||||
this._channel.close();
|
||||
}
|
||||
}
|
||||
destroy(err) {
|
||||
this._error = err || new Error("channel destroyed");
|
||||
this._channel.close();
|
||||
}
|
||||
}
|
||||
const request = {
|
||||
preencode(state, m) {
|
||||
c.uint.preencode(state, m.id);
|
||||
c.string.preencode(state, m.method);
|
||||
c.raw.preencode(state, m.value);
|
||||
},
|
||||
encode(state, m) {
|
||||
c.uint.encode(state, m.id);
|
||||
c.string.encode(state, m.method);
|
||||
c.raw.encode(state, m.value);
|
||||
},
|
||||
decode(state) {
|
||||
return {
|
||||
id: c.uint.decode(state),
|
||||
method: c.string.decode(state),
|
||||
value: c.raw.decode(state),
|
||||
};
|
||||
},
|
||||
};
|
||||
const flags = bitfield(1);
|
||||
const response = {
|
||||
preencode(state, m) {
|
||||
flags.preencode(state);
|
||||
c.uint.preencode(state, m.id);
|
||||
if (m.error)
|
||||
c.string.preencode(state, m.error);
|
||||
else
|
||||
c.raw.preencode(state, m.value);
|
||||
},
|
||||
encode(state, m) {
|
||||
flags.encode(state, bits.of(m.error));
|
||||
c.uint.encode(state, m.id);
|
||||
if (m.error)
|
||||
c.string.encode(state, m.error);
|
||||
else
|
||||
c.raw.encode(state, m.value);
|
||||
},
|
||||
decode(state) {
|
||||
const [error] = bits.iterator(flags.decode(state));
|
||||
return {
|
||||
id: c.uint.decode(state),
|
||||
error: error ? c.string.decode(state) : null,
|
||||
value: !error ? c.raw.decode(state) : null,
|
||||
};
|
||||
},
|
||||
};
|
File diff suppressed because it is too large
Load Diff
31
package.json
31
package.json
|
@ -2,18 +2,25 @@
|
|||
"name": "@lumeweb/protomux-rpc-web",
|
||||
"version": "0.1.0",
|
||||
"type": "module",
|
||||
"main": "dist/index.js",
|
||||
"dependencies": {
|
||||
"@lumeweb/kernel-protomux-client": "git+https://git.lumeweb.com/LumeWeb/kernel-protomux-client.git",
|
||||
"bits-to-bytes": "^1.3.0",
|
||||
"compact-encoding": "^2.11.0",
|
||||
"compact-encoding-bitfield": "^1.0.0",
|
||||
"events": "^3.3.0",
|
||||
"protomux": "^3.4.1"
|
||||
},
|
||||
"main": "lib/index.js",
|
||||
"devDependencies": {
|
||||
"@types/node": "^18.15.11",
|
||||
"prettier": "^2.8.7",
|
||||
"typescript": "^5.0.4"
|
||||
"@lumeweb/node-library-preset": "^0.2.7",
|
||||
"presetter": "*"
|
||||
},
|
||||
"readme": "ERROR: No README data found!",
|
||||
"_id": "@lumeweb/protomux-rpc-web@0.1.0",
|
||||
"scripts": {
|
||||
"prepare": "presetter bootstrap",
|
||||
"build": "run build",
|
||||
"semantic-release": "semantic-release"
|
||||
},
|
||||
"dependencies": {
|
||||
"@lumeweb/kernel-protomux-client": "^0.0.2-develop.1"
|
||||
},
|
||||
"files": [
|
||||
"lib"
|
||||
],
|
||||
"publishConfig": {
|
||||
"access": "public"
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,5 +1,4 @@
|
|||
import EventEmitter from "events";
|
||||
// @ts-ignore
|
||||
import Protomux from "@lumeweb/kernel-protomux-client";
|
||||
// @ts-ignore
|
||||
import c from "compact-encoding";
|
||||
|
@ -112,12 +111,13 @@ export default class ProtomuxRPC extends EventEmitter {
|
|||
method: string;
|
||||
value: any;
|
||||
}) {
|
||||
let error = null;
|
||||
let error: string | null = null;
|
||||
|
||||
const responder = this._responders.get(method);
|
||||
|
||||
if (responder === undefined) error = `unknown method '${method}'`;
|
||||
else {
|
||||
if (responder === undefined) {
|
||||
error = `unknown method '${method}'`;
|
||||
} else {
|
||||
const {
|
||||
valueEncoding = this._defaultValueEncoding,
|
||||
requestEncoding = valueEncoding,
|
||||
|
|
|
@ -1,13 +0,0 @@
|
|||
{
|
||||
"compilerOptions": {
|
||||
"target": "esnext",
|
||||
"declaration": true,
|
||||
"moduleResolution": "node",
|
||||
"outDir": "./dist",
|
||||
"strict": true,
|
||||
"allowSyntheticDefaultImports": true,
|
||||
"esModuleInterop": true
|
||||
},
|
||||
"include": ["src"],
|
||||
"exclude": ["node_modules", "**/__tests__/*"]
|
||||
}
|
Loading…
Reference in New Issue