Skip to content
This repository has been archived by the owner on Mar 27, 2024. It is now read-only.

feat: rest client worker for aries JS #1321

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
29 changes: 29 additions & 0 deletions cmd/aries-js-worker/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -91,9 +91,38 @@
}
}

function changeSource(src) {
//stop existing worker before switching
if (aries) {
destroyAries()
}

var head= document.getElementsByTagName('head')[0];
var script= document.createElement('script');
script.src= `dist/${src}/aries.js`;
head.appendChild(script);

const mode = (src == "rest") ? "REST" : "WASM"
document.getElementById("mode-label").innerHTML = `Running in ${mode} mode`

if (src == "rest"){
document.getElementById("opts").innerHTML = `{"assetsPath": "/dist/assets", "agent-rest-url": "http://localhost:8082"}`
} else {
document.getElementById("opts").innerHTML = `{"assetsPath": "/dist/assets", "agent-default-label":"dem-js-agent","http-resolver-url":[],"auto-accept":true,"outbound-transport":["ws","http"],"transport-return-route":"all","log-level":"debug"}`
}
}


</script>
</head>
<body>
<div>
<fieldset>
<legend id="mode-label" style="font-size: medium;font-weight: bold">Running in WASM Mode...</legend>
<button onClick="changeSource('rest')" style="font-size: large">Switch to REST version</button>
<button onClick="changeSource('web')" style="font-size: large">Switch to WASM version</button>
</fieldset>
</div>
<div>
<table>
<tr>
Expand Down
2 changes: 1 addition & 1 deletion cmd/aries-js-worker/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ import (
)

const (
wasmStartupTopic = "wasm-ready"
wasmStartupTopic = "asset-ready"
handleResultFn = "handleResult"
ariesCommandPkg = "aries"
ariesStartFn = "Start"
Expand Down
6 changes: 5 additions & 1 deletion cmd/aries-js-worker/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,9 @@
"scripts": {
"build:node": "webpack --config ./webpack.config.node.js --mode=production",
"build:web": "webpack --config ./webpack.config.web.js --mode=production",
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@llorllale @sudeshrshetty I wonder if web and node names should include that they are wasm. (followup).

"build:rest": "webpack --config ./webpack.config.rest.js --mode=production",
"build:assets": "bash scripts/build_assets.sh",
"build": "rm -rf dist/* && cp -p ../../LICENSE . && npm run build:assets && npm run build:node && npm run build:web",
"build": "rm -rf dist/* && cp -p ../../LICENSE . && npm run build:assets && npm run build:node && npm run build:web && npm run build:rest",
"prepare": "npm run build",
"test": "echo \"Error: no test specified\" && exit 1"
},
Expand Down Expand Up @@ -44,5 +45,8 @@
"engines": {
"node": ">=12.14",
"npm": ">=6.13"
},
"dependencies": {
"axios": "0.19.2"
}
}
132 changes: 132 additions & 0 deletions cmd/aries-js-worker/src/agent-rest-client.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,132 @@
/*
Copyright SecureKey Technologies Inc. All Rights Reserved.

SPDX-License-Identifier: Apache-2.0
*/


import axios from 'axios';

// All REST endpoints provided by agent controller
const pkgs = {
didexchange: {
CreateInvitation: {
path: "/connections/create-invitation",
method: "POST"
},
ReceiveInvitation: {
path: "/connections/receive-invitation",
method: "POST"
},
AcceptInvitation: {
path: "/connections/{id}/accept-invitation",
method: "POST",
pathParam:"id"
},
AcceptExchangeRequest: {
path: "/connections/{id}/accept-request",
method: "POST",
pathParam:"id"
},
CreateImplicitInvitation: {
path: "/connections/create-implicit-invitation",
method: "POST"
},
RemoveConnection: {
path: "/connections/{id}/remove",
method: "POST",
pathParam:"id"
},
QueryConnectionByID: {
path: "/connections/{id}",
method: "GET",
pathParam:"id"
},
QueryConnections: {
path: "/connections",
method: "GET"
},
},
vdri: {
CreatePublicDID: {
path: "/vdri/create-public-did",
method: "POST"
},
},
messaging: {
RegisteredServices: {
path: "/message/services",
method: "GET"
},
RegisterMessageService: {
path: "/message/register-service",
method: "POST"
},
RegisterHTTPMessageService: {
path: "/http-over-didcomm/register",
method: "POST"
},
UnregisterMessageService: {
path: "/message/unregister-service",
method: "POST"
},
SendNewMessage: {
path: "/message/send",
method: "POST"
},
SendReplyMessage: {
path: "/message/reply",
method: "POST"
},
},
route: {
Register: {
path: "/route/register",
method: "POST"
},
Unregister: {
path: "/route/unregister",
method: "DELETE"
},
GetConnection: {
path: "/route/connection",
method: "GET"
},
},
}

/**
* Agent rest client for given agent endpoint
* @param url is rest endpoint url
* @class
*/
export const Client = class {
constructor(url) {
this.url = url
}

async handle(request) {
const r = (pkgs[request.pkg]) ? pkgs[request.pkg][request.fn] : null;
if (!r) {
return "unable to find given pkg/fn:"+request.pkg+"/"+request.fn;
}

let url = this.url + r.path
if (r.pathParam){
const p = ((request.payload[r.pathParam])) ? (request.payload[r.pathParam]) : "";
url = this.url + r.path.replace("{"+r.pathParam+"}", p);
}

console.debug(`[${r.method}] ${url}, request ${JSON.stringify(request.payload)}`)

const resp = await axios({
method: r.method,
url: url,
data: request.payload
});

return resp.data;
}
};


2 changes: 1 addition & 1 deletion cmd/aries-js-worker/src/aries.js
Original file line number Diff line number Diff line change
Expand Up @@ -270,7 +270,7 @@ const Aries = function(opts) {
// return promise which waits for worker to load and aries to start.
return new Promise((resolve, reject) => {
const timer = setTimeout(_ => reject(new Error("timout waiting for aries to initialize")), 10000)
notifications.set("wasm-ready", async (result) => {
notifications.set("asset-ready", async (result) => {
clearTimeout(timer)
invoke(aw, pending, "aries", "Start", opts, "timeout while starting aries").then(
resp => resolve(),
Expand Down
70 changes: 70 additions & 0 deletions cmd/aries-js-worker/src/worker-impl-rest.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
/*
Copyright SecureKey Technologies Inc. All Rights Reserved.

SPDX-License-Identifier: Apache-2.0
*/

self.importScripts("./agent-rest-client.js")

postMessage({topic: "asset-ready"})

// TODO synchronized access to controller
let handler, controller

const ariesHandle = {
aries: {
Start: (data) => {
if (controller) {
return newResponse(data.id, null, "aries already started");
}

if (!data.payload["agent-rest-url"]) {
return newResponse(data.id, null, "'agent-rest-url' is required");
}

controller = new RESTAgent.Client(data.payload["agent-rest-url"]);
return newResponse(data.id, "aries is started");
},
Stop: (data) => {
if (!controller) {
return newResponse(data.id, null, "aries already stopped");
}
controller = null;
return newResponse(data.id, "aries stopped");
}
}
}

onmessage = async function (e) {
console.debug('message received :', e.data);
if (ariesHandle[e.data.pkg] && ariesHandle[e.data.pkg][e.data.fn]) {
postMessage(ariesHandle[e.data.pkg][e.data.fn](e.data));
return;
}

if (controller) {
try{
const response = await controller.handle(e.data);
postMessage(newResponse(e.data.id, response));
console.debug("response from rest controller", response);
} catch(error){
console.debug("error from rest controller", error.response);
postMessage(newResponse(e.data.id, null, JSON.stringify(error.response.data)));
}
return;
}

postMessage(newResponse(e.data.id, null, "aries not started"));
}


function newResponse(id, payload, errMsg, topic) {
const isErr = (errMsg) ? true : false;
return {
id: id,
payload: payload,
isErr: isErr,
errMsg: errMsg,
topic: topic
};
}
30 changes: 30 additions & 0 deletions cmd/aries-js-worker/src/worker-loader-rest.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
/*
Copyright SecureKey Technologies Inc. All Rights Reserved.

SPDX-License-Identifier: Apache-2.0
*/

export function loadWorker(pending, notifications, paths) {
const workerJS = paths.dir + "/worker-impl-rest.js"
const worker = new Worker(workerJS)
worker.onmessage = e => {
const result = e.data
if (result.topic){
if (notifications.get(result.topic)) {
notifications.get(result.topic)(result)
} else if (notifications.get("all")){
notifications.get("all")(result)
} else {
console.log("no subscribers found for this topic", result.topic)
}
return
}
const cb = pending.get(result.id)
pending.delete(result.id)
cb(result)
}
worker.onerror = e => {
throw new Error("aries: failed to load worker: " + e.message)
}
return worker
}
54 changes: 54 additions & 0 deletions cmd/aries-js-worker/webpack.config.rest.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
/*
Copyright SecureKey Technologies Inc. All Rights Reserved.

SPDX-License-Identifier: Apache-2.0
*/

const path = require("path")

const { CleanWebpackPlugin } = require('clean-webpack-plugin')
const WebpackShellPlugin = require('webpack-shell-plugin')

const { PATHS } = require("./webpack.config.common.js")

const OUTPUT = path.join(PATHS.buildDir, "rest/")

const restConfig = {
entry: path.join(PATHS.srcDir, "aries.js"),
target: 'web',
output: {
path: OUTPUT,
publicPath: "dist/rest",
libraryTarget: "umd",
filename: 'aries.js',
library: 'Aries'
},
plugins: [
new CleanWebpackPlugin(),
new WebpackShellPlugin({
onBuildStart: [
"mkdir -p " + OUTPUT,
"cp -p src/worker-impl-rest.js dist/assets"
]
})
],
resolve: {
alias: {
worker_loader$: path.join(PATHS.srcDir, "worker-loader-rest.js"),
},
mainFields: ['browser', 'module', 'main']
}
}

const assetConfig = {
entry: path.join(PATHS.srcDir, "agent-rest-client.js"),
target: 'webworker',
output: {
path: path.resolve(PATHS.buildDir, 'assets'),
publicPath: "dist/assets",
filename: 'agent-rest-client.js',
library: "RESTAgent"
},
}

module.exports = [ restConfig, assetConfig ];