Skip to content

Commit

Permalink
* Implements unverified requests / responses.
Browse files Browse the repository at this point in the history
* Implements IFrame communication stream.
  • Loading branch information
hediet committed Mar 8, 2021
1 parent 600b00f commit 52f8878
Show file tree
Hide file tree
Showing 18 changed files with 1,438 additions and 2,655 deletions.
3 changes: 2 additions & 1 deletion .vscode/settings.json
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
{
"plantuml.diagramsRoot": "docs",
"plantuml.exportFormat": "svg",
"plantuml.exportOutDir": "docs/exported"
"plantuml.exportOutDir": "docs/exported",
"editor.formatOnSave": true
}
9 changes: 5 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,7 @@ import {
} from "@hediet/json-rpc";

const myRpcContract = contract({
name: "MyRpcContract",
// the interface for clients to interact with servers
server: {
calculate: requestType({
Expand Down Expand Up @@ -185,7 +186,7 @@ const worker = new Worker("./browser-worker.ts");
const { server } = Contract.getServerFromStream(
myRpcContract,
connectToWorker(worker),
logger,
{ logger },
{
progress: ({ progress }) => console.log("progress", progress),
}
Expand All @@ -197,12 +198,12 @@ Web-Worker:

```ts
import { Contract } from "@hediet/json-rpc";
import { workerConnectToParent } from "@hediet/json-rpc-browser";
import { connectWorkerToParent } from "@hediet/json-rpc-browser";

const { server } = Contract.getServerFromStream(
myRpcContract,
workerConnectToParent(),
logger,
connectWorkerToParent(),
{ logger },
{
calculate: async ({ data }) => {
await client.progress({ progress: 0.5 });
Expand Down
12 changes: 10 additions & 2 deletions demo/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,15 @@
"@hediet/json-rpc-websocket-server": "*"
},
"devDependencies": {
"parcel": "^1.12.3",
"typescript": "^3.4.5"
"@types/html-webpack-plugin": "^3.2.2",
"@types/webpack": "^4.41.10",
"clean-webpack-plugin": "^3.0.0",
"html-webpack-plugin": "^5.3.0",
"ts-loader": "^8.0.17",
"ts-node": "^9.1.1",
"webpack": "^5.24.3",
"webpack-cli": "^4.5.0",
"webpack-dev-server": "^3.11.2",
"typescript": "^4.2.3"
}
}
65 changes: 0 additions & 65 deletions demo/src/browser-worker.ts

This file was deleted.

70 changes: 70 additions & 0 deletions demo/src/demo1-webworker.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
import {
connectToWorker,
connectWorkerToParent,
} from "@hediet/json-rpc-browser";
import {
contract,
ConsoleRpcLogger,
Contract,
unverifiedRequest,
unverifiedNotification,
} from "@hediet/json-rpc";

const api = contract({
name: "API",
server: {
calculate: unverifiedRequest<{ name: string }, string>(),
},
client: {
progress: unverifiedNotification<{ progress: number }>(),
},
});

if (typeof window !== "undefined") {
function writeln(str: string) {
document.writeln(str + "<br />");
}

// window:
const worker = new Worker(new URL("./demo1-webworker.ts", import.meta.url));
const { server } = Contract.getServerFromStream(
api,
connectToWorker(worker),
{ logger: new ConsoleRpcLogger() },
{
progress: ({ progress }) => {
writeln(`${progress}`);
},
}
);

(async () => {
try {
const result1 = await server.calculate({ name: "foo" });
writeln(`result1: ${result1}`);
const result2 = await server.calculate({ name: "bar" });
writeln(`result2: ${result2}`);
} catch (e) {
writeln(`${e}`);
}
})();
} else {
// worker:
Contract.registerServerToStream(
api,
connectWorkerToParent(),
{ logger: new ConsoleRpcLogger(), sendExceptionDetails: true },
{
calculate: async ({ name }, { counterpart }) => {
for (let i = 0; i <= 10; i++) {
for (let j = 0; j < 100000000; j++) {}
if (i === 5 && name === "bar") {
throw "`bar` is not supported.";
}
counterpart.progress({ progress: i / 10 });
}
return "bla" + name;
},
}
);
}
80 changes: 80 additions & 0 deletions demo/src/demo2-iframe.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
import {
connectToIFrame,
connectIFrameToParent,
} from "@hediet/json-rpc-browser";
import {
contract,
ConsoleRpcLogger,
Contract,
unverifiedRequest,
unverifiedNotification,
} from "@hediet/json-rpc";

const api = contract({
name: "API",
server: {
calculate: unverifiedRequest<{ name: string }, string>(),
},
client: {
progress: unverifiedNotification<{ progress: number }>(),
},
});

if (window.self === window.top) {
// parent
document.body.innerHTML = `
<h1>IFrame Demo (Parent Window)</h1>
<iframe id="iframe1" src="${document.URL}"></iframe>
<div id="myDiv" />
`;
const myDiv = document.getElementById("myDiv")!;

function writeln(str: string) {
myDiv.innerHTML += str + "<br />";
}

const { server } = Contract.getServerFromStream(
api,
connectToIFrame(
document.getElementById("iframe1") as HTMLIFrameElement
),
{ logger: new ConsoleRpcLogger() },
{
progress: ({ progress }) => {
writeln(`${progress}`);
},
}
);

(async () => {
try {
const result1 = await server.calculate({ name: "foo" });
writeln(`result1: ${result1}`);
const result2 = await server.calculate({ name: "bar" });
writeln(`result2: ${result2}`);
} catch (e) {
writeln(`${e}`);
}
})();
} else {
// IFrame
document.body.innerHTML = `(IFrame Window)`;

Contract.registerServerToStream(
api,
connectIFrameToParent(),
{ logger: new ConsoleRpcLogger(), sendExceptionDetails: true },
{
calculate: async ({ name }, { counterpart }) => {
for (let i = 0; i <= 10; i++) {
for (let j = 0; j < 100000000; j++) {}
if (i === 5 && name === "bar") {
throw new Error("Example Error.");
}
counterpart.progress({ progress: i / 10 });
}
return "bla" + name;
},
}
);
}
5 changes: 0 additions & 5 deletions demo/src/index.html

This file was deleted.

4 changes: 3 additions & 1 deletion demo/tsconfig.json
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,9 @@
"extends": "../tsconfig.settings.json",
"compilerOptions": {
"outDir": "./dist",
"rootDir": "./src"
"rootDir": "./src",
"module": "ESNext",
"moduleResolution": "Node"
},
"references": [
{ "path": "../json-rpc" },
Expand Down
30 changes: 30 additions & 0 deletions demo/webpack.config.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
import * as webpack from "webpack";
import path = require("path");
import HtmlWebpackPlugin = require("html-webpack-plugin");

const r = (file: string) => path.resolve(__dirname, file);

module.exports = {
entry: {
demo1: r("./src/demo1-webworker.ts"),
demo2: r("./src/demo2-iframe.ts"),
},
output: { path: r("dist") },
resolve: {
extensions: [".webpack.js", ".web.js", ".ts", ".tsx", ".js"],
},
devtool: "source-map",
module: {
rules: [
{
test: /\.tsx?$/,
loader: "ts-loader",
options: { transpileOnly: true },
},
],
},
plugins: [
new HtmlWebpackPlugin({ chunks: ["demo1"], filename: "demo1.html" }),
new HtmlWebpackPlugin({ chunks: ["demo2"], filename: "demo2.html" }),
],
} as webpack.Configuration;
4 changes: 2 additions & 2 deletions json-rpc-browser/package.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"name": "@hediet/json-rpc-browser",
"description": "Provides JSON RPC through window.postMessage.",
"version": "0.1.0",
"version": "0.3.0",
"author": {
"name": "Henning Dieterichs",
"email": "henning.dieterichs@live.de"
Expand All @@ -19,7 +19,7 @@
},
"dependencies": {
"@hediet/std": "^0.6.0",
"@hediet/json-rpc": "^0.1.0"
"@hediet/json-rpc": "^0.2.0"
},
"publishConfig": {
"access": "public",
Expand Down
41 changes: 41 additions & 0 deletions json-rpc-browser/src/WindowLikeStream.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
import { BaseMessageStream, Message } from "@hediet/json-rpc";

export interface WindowLike {
postMessage(data: any, ...misc: any[]): void;
addEventListener(
ev: "message",
handler: (ev: { data: any; source: WindowLike | undefined }) => void
): void;
}

export class WindowLikeStream extends BaseMessageStream {
constructor(
private readonly windowLike: WindowLike,
private readonly source: WindowLike | undefined = undefined,
private readonly loadingState:
| { loaded: boolean; onLoaded: Promise<void> }
| undefined = undefined
) {
super();

windowLike.addEventListener("message", ({ data, source }) => {
if (this.source && source !== this.source) {
return;
}
if ("rpcMsg" in data) {
this.onMessage(data.rpcMsg);
}
});
}

public async write(message: Message): Promise<void> {
if (this.loadingState && !this.loadingState.loaded) {
await this.loadingState.onLoaded;
}
this.windowLike.postMessage({ rpcMsg: message }, "*");
}

public toString(): string {
return `${this.id}@${this.windowLike}`;
}
}
Loading

0 comments on commit 52f8878

Please sign in to comment.