Skip to content
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.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
50 changes: 1 addition & 49 deletions packages/js/plugins/ws/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,57 +3,9 @@
WebSocket plugin allows Polywrap Client to interact with WebSocket servers.

## interface

``` typescript
# subset of JS MessageEvent interface
type Message {
data: String!
origin: String!
lastEventId: String!
}

# path to WRAP method
type Callback {
uri: String!,
method: String!
}

# optional fields are `Number | null` instead of `Option<i32>`
type Number {
value: Int!
}

type Module {
# create a socket with id
## can return after `timeout` if the server is not responding
open(url: String!, timeout: Number): Int!

# close socket `id`
close(id: Int!): Boolean

# send message via socket `id`
send(id: Int!, message: String!): Boolean

# pass all messages to callback
addCallback(id: Int!, callback: Callback!): Boolean

# stop passing messages to callback
removeCallback(id: Int!, callback: Callback!): Boolean

# save messages to ws plugin cache
addCache(id: Int!): Boolean

# stop caching messages
removeCache(id: Int!): Boolean

# get [messages], flush cache
## can wait until receives `min` events or reaches `timeout`
receive(id: Int!, min: Number, timeout: Number): [Message!]!
}
```
See [schema.graphql](./src/schema.graphql).

## callback

Every incoming WebSocket message can be passed to a callback function in another wrapper. Use `addCallback` to start passing messages and `removeCallback` to stop. The callback function is expected to have a parameter `data`, i.e. `foo(data: string)`.

``` typescript
Expand Down
14 changes: 7 additions & 7 deletions packages/js/plugins/ws/src/__tests__/e2e/e2e.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,7 @@ describe("WebSocket plugin", () => {
method: "open",
args: {
url: "ws://localhost:1235",
timeout: { value: 50 }
timeout: 50
}
})
});
Expand Down Expand Up @@ -347,7 +347,7 @@ describe("WebSocket plugin", () => {
method: "receive",
args: {
id,
timeout: { value: 250 }
timeout: 250
}
})

Expand Down Expand Up @@ -378,7 +378,7 @@ describe("WebSocket plugin", () => {
method: "receive",
args: {
id,
min: { value: 2 }
min: 2
}
})

Expand Down Expand Up @@ -408,8 +408,8 @@ describe("WebSocket plugin", () => {
method: "receive",
args: {
id,
timeout: { value: 110 },
min: { value: 2 }
timeout: 110,
min: 2
}
})

Expand Down Expand Up @@ -439,8 +439,8 @@ describe("WebSocket plugin", () => {
method: "receive",
args: {
id,
timeout: { value: 300 },
min: { value: 1 }
timeout: 300,
min: 1
}
})

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -106,7 +106,7 @@ describe("e2e tests for WsPlugin", () => {
class MemoryPlugin extends PluginModule<{}> {
set(args: { key: string, value: string }, _client: Client): boolean {
value[args.key] = args.value
return true
return true
}
get(args: { key: string }, _client: Client): string | null {
return value[args.key] ?? null
Expand Down Expand Up @@ -140,7 +140,7 @@ describe("e2e tests for WsPlugin", () => {
uri,
method: "callback"
},
message: "test"
message: "test"
}
});

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,6 @@ type Module {

get(
url: String!,
timeout: Int!
timeout: UInt32!
): [String!]!
}
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import {
Args_subscribeAndSend,
Args_get
} from "./wrap";
import { Box } from "@polywrap/wasm-as";

export function send(args: Args_send): boolean {
const id = WS_Module.open({
Expand Down Expand Up @@ -68,9 +69,9 @@ export function get(args: Args_get): string[] {

WS_Module.addCache({
id
}).unwrap().unwrap()
}).unwrap()

const messages = WS_Module.receive({ id, timeout: { value: args.timeout } }).unwrap();
const messages = WS_Module.receive({ id, timeout: Box.from(args.timeout) }).unwrap();

const data: string[] = messages.map<string>((msg) => msg.data);

Expand Down
24 changes: 9 additions & 15 deletions packages/js/plugins/ws/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -32,18 +32,15 @@ export class WsPlugin extends Module<NoConfig> {
if (args.timeout) {
setTimeout(() => {
reject(new Error("timeout reached"));
}, args.timeout.value);
}, args.timeout);
}
this._sockets[id].onopen = () => {
resolve(id);
};
});
}

public async close(
args: Args_close,
_client: Client
): Promise<boolean | null> {
public async close(args: Args_close, _client: Client): Promise<boolean> {
this._sockets[args.id].close();
return await new Promise((resolve) => {
this._sockets[args.id].onclose = () => {
Expand All @@ -52,12 +49,12 @@ export class WsPlugin extends Module<NoConfig> {
});
}

public send(args: Args_send, _client: Client): boolean | null {
public send(args: Args_send, _client: Client): boolean {
this._sockets[args.id].send(args.message);
return true;
}

public addCallback(args: Args_addCallback, _client: Client): boolean | null {
public addCallback(args: Args_addCallback, _client: Client): boolean {
const callbackId = this._callbackId(args.callback);
this._callbacks[callbackId] = async (msg) => {
await _client.invoke<{ callback: boolean }>({
Expand All @@ -73,10 +70,7 @@ export class WsPlugin extends Module<NoConfig> {
return true;
}

public removeCallback(
args: Args_removeCallback,
_client: Client
): boolean | null {
public removeCallback(args: Args_removeCallback, _client: Client): boolean {
const callbackId = this._callbackId(args.callback);
this._sockets[args.id].removeEventListener(
"message",
Expand All @@ -85,7 +79,7 @@ export class WsPlugin extends Module<NoConfig> {
return true;
}

public addCache(args: Args_addCache, _client: Client): boolean | null {
public addCache(args: Args_addCache, _client: Client): boolean {
const callback = { uri: args.id.toString(), method: "cache" };
const callbackId = this._callbackId(callback);
this._caches[args.id] = [];
Expand All @@ -109,7 +103,7 @@ export class WsPlugin extends Module<NoConfig> {
return true;
}

public removeCache(args: Args_removeCache, _client: Client): boolean | null {
public removeCache(args: Args_removeCache, _client: Client): boolean {
const callback = { uri: args.id.toString(), method: "cache" };
const callbackId = this._callbackId(callback);
this._sockets[args.id].removeEventListener(
Expand All @@ -135,7 +129,7 @@ export class WsPlugin extends Module<NoConfig> {
if (args.min) {
interval = setInterval(() => {
if (args.min) {
if (this._caches[args.id].length >= args.min.value) {
if (this._caches[args.id].length >= args.min) {
clearInterval(interval);
clear();
}
Expand All @@ -146,7 +140,7 @@ export class WsPlugin extends Module<NoConfig> {
setTimeout(() => {
clearInterval(interval);
clear();
}, args.timeout.value);
}, args.timeout);
}
if (!args.timeout && !args.min) {
clear();
Expand Down
66 changes: 49 additions & 17 deletions packages/js/plugins/ws/src/schema.graphql
Original file line number Diff line number Diff line change
@@ -1,25 +1,57 @@
"""Subset of JS MessageEvent interface"""
type Message {
data: String!
origin: String!
lastEventId: String!
data: String!
origin: String!
lastEventId: String!
}

type Callback {
uri: String!,
method: String!
}

type Number {
value: Int!
"""WRAP Module URI"""
uri: String!
"""WRAP Module Method"""
method: String!
}

type Module {
open(url: String!, timeout: Number): Int!
close(id: Int!): Boolean
send(id: Int!, message: String!): Boolean
addCallback(id: Int!, callback: Callback!): Boolean
removeCallback(id: Int!, callback: Callback!): Boolean
addCache(id: Int!): Boolean
removeCache(id: Int!): Boolean
receive(id: Int!, min: Number, timeout: Number): [Message!]!
"""
create a socket with id, can return after `timeout`
if the server is not responding. Returns the socket `id`
"""
open(url: String!, timeout: UInt32): UInt32!

"""
close socket `id`
"""
close(id: UInt32!): Boolean!

"""
send message via socket `id`
"""
send(id: UInt32!, message: String!): Boolean!

"""
send all messages to callback for socket `id`
"""
addCallback(id: UInt32!, callback: Callback!): Boolean!

"""
stop sending messages to callback for socket `id`
"""
removeCallback(id: UInt32!, callback: Callback!): Boolean!

"""
save messages to ws plugin cache for socket `id`
"""
addCache(id: UInt32!): Boolean!

"""
stop caching messages for socket `id`
"""
removeCache(id: UInt32!): Boolean!

"""
get messages and flush cache,
can wait until receives `min` events or reaches `timeout`
"""
receive(id: UInt32!, min: UInt32, timeout: UInt32): [Message!]!
}
Original file line number Diff line number Diff line change
Expand Up @@ -51,14 +51,10 @@ export const toWasmInit: MustacheFn = () => {
type = type.substring(0, type.length - 1);
} else {
const nullType = toWasm()(value, render);
const optional = "Option";
const nullOptional = "| null";

if (nullType.endsWith(nullOptional)) {
return "null";
} else if (nullType.startsWith(optional)) {
type = nullType.substring(6);
return `Option.None${type}()`;
}
}

Expand Down Expand Up @@ -250,7 +246,7 @@ const applyOptional = (
) {
return `${type} | null`;
} else {
return `Option<${type}>`;
return `Box<${type}> | null`;
}
} else {
return type;
Expand Down
3 changes: 3 additions & 0 deletions packages/schema/bind/src/bindings/assemblyscript/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -199,6 +199,9 @@ const keywords = {
Float64Array: "Float64Array",
TemplateStringsArray: "TemplateStringsArray",
Error: "Error",
Result: "Result",
Box: "Box",
JSON: "JSON",
// runtime
abort: "abort",
trace: "trace",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,19 +8,19 @@ if (reader.isNextString()) {
}
{{/required}}
{{^required}}
let value: Option<Types.{{#detectKeyword}}{{type}}{{/detectKeyword}}>;
let value: Box<Types.{{#detectKeyword}}{{type}}{{/detectKeyword}}> | null;
if (!reader.isNextNil()) {
if (reader.isNextString()) {
value = Option.Some(
value = Box.from(
Types.get{{type}}Value(reader.readString())
);
} else {
value = Option.Some(
value = Box.from(
reader.readInt32()
);
Types.sanitize{{type}}Value(value.unwrap());
}
} else {
value = Option.None<Types.{{#detectKeyword}}{{type}}{{/detectKeyword}}>();
value = null;
}
{{/required}}
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import {
Read,
Write,
Option,
Box,
BigInt,
BigNumber,
JSON
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import {
wrap_subinvoke,
wrap_subinvokeImplementation,
Option,
Box,
BigInt,
BigNumber,
JSON,
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import {
Read,
Write,
Option,
Box,
BigInt,
BigNumber,
JSON
Expand Down
Loading