Compare commits

..

No commits in common. "v0.0.2-develop.16" and "master" have entirely different histories.

10 changed files with 331 additions and 18057 deletions

View File

@ -1,13 +0,0 @@
name: Build/Publish
on:
push:
branches:
- master
- develop
- develop-*
jobs:
main:
uses: lumeweb/github-node-deploy-workflow/.github/workflows/main.yml@master
secrets: inherit

View File

@ -1,5 +0,0 @@
{
"preset": [
"@lumeweb/node-library-preset"
]
}

View File

@ -1,31 +0,0 @@
## [0.0.2-develop.16](https://git.lumeweb.com/LumeWeb/protomux-rpc-web/compare/v0.0.2-develop.15...v0.0.2-develop.16) (2023-07-29)
## [0.0.2-develop.15](https://git.lumeweb.com/LumeWeb/protomux-rpc-web/compare/v0.0.2-develop.14...v0.0.2-develop.15) (2023-07-24)
## [0.0.2-develop.14](https://git.lumeweb.com/LumeWeb/protomux-rpc-web/compare/v0.0.2-develop.13...v0.0.2-develop.14) (2023-07-23)
## [0.0.2-develop.13](https://git.lumeweb.com/LumeWeb/protomux-rpc-web/compare/v0.0.2-develop.12...v0.0.2-develop.13) (2023-07-23)
## [0.0.2-develop.12](https://git.lumeweb.com/LumeWeb/protomux-rpc-web/compare/v0.0.2-develop.11...v0.0.2-develop.12) (2023-07-22)
## [0.0.2-develop.11](https://git.lumeweb.com/LumeWeb/protomux-rpc-web/compare/v0.0.2-develop.10...v0.0.2-develop.11) (2023-07-22)
## [0.0.2-develop.10](https://git.lumeweb.com/LumeWeb/protomux-rpc-web/compare/v0.0.2-develop.9...v0.0.2-develop.10) (2023-07-22)
## [0.0.2-develop.9](https://git.lumeweb.com/LumeWeb/protomux-rpc-web/compare/v0.0.2-develop.8...v0.0.2-develop.9) (2023-07-22)
## [0.0.2-develop.8](https://git.lumeweb.com/LumeWeb/protomux-rpc-web/compare/v0.0.2-develop.7...v0.0.2-develop.8) (2023-07-22)
## [0.0.2-develop.7](https://git.lumeweb.com/LumeWeb/protomux-rpc-web/compare/v0.0.2-develop.6...v0.0.2-develop.7) (2023-07-12)
## [0.0.2-develop.6](https://git.lumeweb.com/LumeWeb/protomux-rpc-web/compare/v0.0.2-develop.5...v0.0.2-develop.6) (2023-07-08)
## [0.0.2-develop.5](https://git.lumeweb.com/LumeWeb/protomux-rpc-web/compare/v0.0.2-develop.4...v0.0.2-develop.5) (2023-07-08)
## [0.0.2-develop.4](https://git.lumeweb.com/LumeWeb/protomux-rpc-web/compare/v0.0.2-develop.3...v0.0.2-develop.4) (2023-07-05)
## [0.0.2-develop.3](https://git.lumeweb.com/LumeWeb/protomux-rpc-web/compare/v0.0.2-develop.2...v0.0.2-develop.3) (2023-07-05)
## [0.0.2-develop.2](https://git.lumeweb.com/LumeWeb/protomux-rpc-web/compare/v0.0.2-develop.1...v0.0.2-develop.2) (2023-07-04)
## [0.0.2-develop.1](https://git.lumeweb.com/LumeWeb/protomux-rpc-web/compare/v0.0.1...v0.0.2-develop.1) (2023-07-04)

45
LICENSE
View File

@ -1,14 +1,37 @@
Copyright 2023 Holepunch Inc MIT License
Copyright 2023 Hammer Technologies LLC
Licensed under the Apache License, Version 2.0 (the "License"); Copyright (c) 2022 Hammer Technologies LLC
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0 Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
Unless required by applicable law or agreed to in writing, software The above copyright notice and this permission notice shall be included in all
distributed under the License is distributed on an "AS IS" BASIS, copies or substantial portions of the Software.
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
limitations under the License. IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
ISC License
Copyright (c) 2022 Kasper Isager Dalsgarð <kasper@funktionel.co> & Contributors
Permission to use, copy, modify, and/or distribute this software for any
purpose with or without fee is hereby granted, provided that the above
copyright notice and this permission notice appear in all copies.
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
PERFORMANCE OF THIS SOFTWARE.

44
dist/index.d.ts vendored Normal file
View File

@ -0,0 +1,44 @@
/// <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;
}

224
dist/index.js vendored Normal file
View File

@ -0,0 +1,224 @@
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,
};
},
};

17971
npm-shrinkwrap.json generated

File diff suppressed because it is too large Load Diff

View File

@ -1,29 +1,19 @@
{ {
"name": "@lumeweb/protomux-rpc-web", "name": "@lumeweb/protomux-rpc-web",
"version": "0.0.2-develop.16", "version": "0.1.0",
"type": "module", "type": "module",
"main": "lib/index.js", "main": "dist/index.js",
"devDependencies": {
"@lumeweb/node-library-preset": "^0.2.7",
"presetter": "*"
},
"repository": {
"type": "git",
"url": "gitea@git.lumeweb.com:LumeWeb/protomux-rpc-web.git"
},
"readme": "ERROR: No README data found!",
"scripts": {
"prepare": "presetter bootstrap",
"build": "run build",
"semantic-release": "semantic-release"
},
"dependencies": { "dependencies": {
"@lumeweb/kernel-protomux-client": "^0.0.2-develop.16" "@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"
}, },
"files": [ "devDependencies": {
"lib" "@types/node": "^18.15.11",
], "prettier": "^2.8.7",
"publishConfig": { "typescript": "^5.0.4"
"access": "public"
} }
} }

View File

@ -1,4 +1,5 @@
import EventEmitter from "events"; import EventEmitter from "events";
// @ts-ignore
import Protomux from "@lumeweb/kernel-protomux-client"; import Protomux from "@lumeweb/kernel-protomux-client";
// @ts-ignore // @ts-ignore
import c from "compact-encoding"; import c from "compact-encoding";
@ -111,13 +112,12 @@ export default class ProtomuxRPC extends EventEmitter {
method: string; method: string;
value: any; value: any;
}) { }) {
let error: string | null = null; let error = null;
const responder = this._responders.get(method); const responder = this._responders.get(method);
if (responder === undefined) { if (responder === undefined) error = `unknown method '${method}'`;
error = `unknown method '${method}'`; else {
} else {
const { const {
valueEncoding = this._defaultValueEncoding, valueEncoding = this._defaultValueEncoding,
requestEncoding = valueEncoding, requestEncoding = valueEncoding,

13
tsconfig.json Normal file
View File

@ -0,0 +1,13 @@
{
"compilerOptions": {
"target": "esnext",
"declaration": true,
"moduleResolution": "node",
"outDir": "./dist",
"strict": true,
"allowSyntheticDefaultImports": true,
"esModuleInterop": true
},
"include": ["src"],
"exclude": ["node_modules", "**/__tests__/*"]
}