-
Notifications
You must be signed in to change notification settings - Fork 3
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Add remote package for calling interactors on a remote process
- Loading branch information
Showing
9 changed files
with
404 additions
and
5 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,12 @@ | ||
import { connect } from '../src/index'; | ||
import { main } from 'effection'; | ||
import { Heading, Link } from '@interactors/html'; | ||
|
||
main(function*() { | ||
console.log("[client] connecting..."); | ||
yield connect('ws://127.0.0.1:30400'); | ||
console.log("[client] connected!"); | ||
|
||
yield Heading('Hello World').exists(); | ||
yield Link('Some Link').has({ href: '/incorrect' }); | ||
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,20 @@ | ||
import { serve } from '../src/index'; | ||
import { main } from 'effection'; | ||
import { Heading, Link } from '@interactors/html'; | ||
import { JSDOM } from 'jsdom'; | ||
import { setDocumentResolver } from '@interactors/globals'; | ||
|
||
let dom = new JSDOM(` | ||
<!doctype html> | ||
<html> | ||
<h1>Hello World</h1> | ||
<a href="/foobar">Some Link</a> | ||
</html> | ||
`); | ||
|
||
setDocumentResolver(() => dom.window.document); | ||
|
||
main(function*() { | ||
console.log('[server] starting'); | ||
yield serve(30400, { heading: Heading, link: Link }); | ||
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,60 @@ | ||
{ | ||
"name": "@interactors/remote", | ||
"version": "1.0.0-rc1.2", | ||
"description": "Call interactors running in a remote process", | ||
"main": "dist/cjs/index.js", | ||
"browser": "dist/esm/index.js", | ||
"types": "dist/index.d.ts", | ||
"repository": "https://github.com/thefrontside/interactors.git", | ||
"homepage": "https://frontside.com/interactors", | ||
"author": "Frontside Engineering <engineering@frontside.com>", | ||
"license": "MIT", | ||
"files": [ | ||
"dist/**/*", | ||
"src/**/*", | ||
"README.md" | ||
], | ||
"exports": { | ||
".": { | ||
"require": "./dist/cjs/index.js", | ||
"default": "./dist/esm/index.js" | ||
} | ||
}, | ||
"scripts": { | ||
"clean": "rm -rf dist *.tsbuildinfo", | ||
"lint": "eslint \"{src,test}/**/*.ts\"", | ||
"check:types": "tsc --noEmit", | ||
"test": "mocha -r ts-node/register \"test/**/*.test.ts\"", | ||
"docs": "rm -rf docs && yarn typedoc --options typedoc.json", | ||
"docs:netlify": "yarn prepack && yarn docs", | ||
"docs:preview": "yarn parcel docs/api/v1/index.html", | ||
"prepack": "tsc --build ./tsconfig.build.json && yarn prepack:es2015 && yarn prepack:commonjs", | ||
"prepack:es2015": "tsc --project ./tsconfig.build.json --outdir dist/esm --module es2015", | ||
"prepack:commonjs": "tsc --project ./tsconfig.build.json --outdir dist/cjs --module commonjs" | ||
}, | ||
"dependencies": { | ||
"@effection/dispatch": "^2.0.3", | ||
"@effection/websocket-client": "^2.0.3", | ||
"@effection/websocket-server": "^2.0.3", | ||
"@interactors/core": "1.0.0-rc1.2", | ||
"@interactors/globals": "1.0.0-rc1.1", | ||
"uuid": "^8.3.2" | ||
}, | ||
"devDependencies": { | ||
"@frontside/tsconfig": "^1.2.0", | ||
"@types/mocha": "^7.0.1", | ||
"@types/node": "^14.17.5", | ||
"@types/uuid": "^8.3.4", | ||
"expect": "^24.9.0", | ||
"jsdom": "^16.2.2", | ||
"mocha": "^6.2.2", | ||
"parcel": "^2.0.0-beta.2", | ||
"ts-node": "^10.4.0", | ||
"typedoc": "^0.22.7", | ||
"typescript": "~4.4.4" | ||
}, | ||
"volta": { | ||
"node": "14.17.5", | ||
"yarn": "1.22.11" | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,98 @@ | ||
/* eslint-disable @typescript-eslint/no-explicit-any */ | ||
import { Operation, spawn } from 'effection'; | ||
import { addInteractionWrapper } from '@interactors/globals'; | ||
import { InteractorConstructor, Interactor } from '@interactors/core'; | ||
import { createWebSocketServer, WebSocketConnection, WebSocketServer } from '@effection/websocket-server'; | ||
import { createWebSocketClient, WebSocketClient } from '@effection/websocket-client'; | ||
import { createDispatch } from '@effection/dispatch'; | ||
import { v4 as uuid } from 'uuid'; | ||
|
||
type ServerMessage = { | ||
key: string; | ||
method: string; | ||
args: unknown[]; | ||
options: SerializedOptions, | ||
}; | ||
|
||
type ClientMessage = { | ||
key: string; | ||
status: "success" | "error"; | ||
value?: unknown; | ||
error?: string; | ||
}; | ||
|
||
// TODO: we should change InteractionOptions in core so it is more easily serializable | ||
type SerializedOptions = { | ||
name: string; | ||
locator: string | undefined; | ||
filters: Record<string, unknown>; | ||
ancestors: SerializedOptions[]; | ||
} | ||
|
||
function serializeOptions(options: Interactor<any, any>['options']): SerializedOptions { | ||
return { | ||
name: options.name, | ||
locator: options.locator?.value as string | undefined, | ||
filters: options.filter.filters, | ||
ancestors: options.ancestors.map(serializeOptions), | ||
} | ||
} | ||
|
||
export function connect(url: string): Operation<void> { | ||
return { | ||
*init() { | ||
let client: WebSocketClient<ClientMessage, ServerMessage> = yield createWebSocketClient(url); | ||
let dispatch = createDispatch(); | ||
|
||
addInteractionWrapper(function*(interaction) { | ||
let key = uuid(); | ||
let interactor = interaction.interactor as Interactor<any, any>; | ||
yield client.send({ | ||
key, | ||
method: interaction.method, | ||
args: interaction.args, | ||
options: serializeOptions(interactor.options), | ||
}); | ||
|
||
let reply = yield dispatch.get(key).expect(); | ||
if(reply.status === 'error') { | ||
throw new Error(reply.error || "unknown error"); | ||
} else { | ||
return reply.value; | ||
} | ||
}) | ||
|
||
yield spawn(client.forEach(function*(message) { | ||
dispatch.send(message.key, message); | ||
})); | ||
} | ||
} | ||
} | ||
|
||
export function* serve(port: number, map: Record<string, InteractorConstructor<any, any, any, any>>): Operation<void> { | ||
console.log('[server] strarting...'); | ||
let server: WebSocketServer<ServerMessage, ClientMessage> = yield createWebSocketServer({ port }); | ||
|
||
console.log(`[server] started! Listening on port ${port}`); | ||
|
||
while(true) { | ||
let connection: WebSocketConnection<ServerMessage, ClientMessage> = yield server.first(); | ||
if(!connection) break; | ||
|
||
yield spawn(connection.forEach(({ options, key, method, args }) => function*() { | ||
console.log('[server] received request', key, options); | ||
let interactor = options.locator ? | ||
map[options.name](options.locator, options.filters) : | ||
map[options.name](options.filters); | ||
|
||
try { | ||
let value = yield interactor[method](...args); | ||
console.log('[server] success', key); | ||
yield connection.send({ key, status: "success", value }); | ||
} catch(error: any) { | ||
console.log('[server] error', key); | ||
yield connection.send({ key, status: "error", error: error.message }); | ||
} | ||
})); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,15 @@ | ||
{ | ||
"extends": "../../tsconfig-base.json", | ||
"compilerOptions": { | ||
"outDir": "dist/cjs", | ||
"rootDir": "./src", | ||
"declarationDir": "dist" | ||
}, | ||
"include": [ | ||
"src/**/*.ts" | ||
], | ||
"references": [ | ||
{ "path": "../core/tsconfig.build.json" }, | ||
{ "path": "../globals/tsconfig.build.json" } | ||
] | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,4 @@ | ||
{ | ||
"extends": "@frontside/tsconfig", | ||
"exclude": ["types/**/*.ts"] | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,7 @@ | ||
{ | ||
"out": "docs/api/v1", | ||
"name": "@interactors/html", | ||
"entryPoints": "src/index.ts", | ||
"includeVersion": true, | ||
"excludePrivate": true | ||
} |
Oops, something went wrong.