@vyr/remote 0.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +18 -0
- package/src/Bridge.ts +133 -0
- package/src/ChangeScriptable.ts +22 -0
- package/src/Collection.ts +36 -0
- package/src/RemoteExecutor.ts +514 -0
- package/src/RemoteInvoker.ts +72 -0
- package/src/RemoteProcess.ts +87 -0
- package/src/index.ts +7 -0
- package/src/job/IJob.ts +6 -0
- package/src/job/Job.ts +16 -0
- package/src/job/asset/add.ts +23 -0
- package/src/job/asset/dragdrap.ts +24 -0
- package/src/job/asset/index.ts +6 -0
- package/src/job/asset/load.ts +20 -0
- package/src/job/asset/remove.ts +20 -0
- package/src/job/asset/unload.ts +18 -0
- package/src/job/asset/update.ts +22 -0
- package/src/job/bridge/connection.ts +18 -0
- package/src/job/bridge/disconnect.ts +29 -0
- package/src/job/bridge/index.ts +2 -0
- package/src/job/index.ts +1 -0
- package/src/job/invoke/alert.ts +20 -0
- package/src/job/invoke/animation.ts +45 -0
- package/src/job/invoke/event.ts +40 -0
- package/src/job/invoke/index.ts +8 -0
- package/src/job/invoke/orbit.ts +20 -0
- package/src/job/invoke/pick.ts +15 -0
- package/src/job/invoke/properties.ts +43 -0
- package/src/job/invoke/screenshot.ts +35 -0
- package/src/job/invoke/transform.ts +36 -0
- package/src/job/scene/add.ts +22 -0
- package/src/job/scene/dragdrap.ts +23 -0
- package/src/job/scene/index.ts +6 -0
- package/src/job/scene/load.ts +19 -0
- package/src/job/scene/remove.ts +19 -0
- package/src/job/scene/unload.ts +17 -0
- package/src/job/scene/update.ts +20 -0
- package/src/locale/Language.ts +10 -0
- package/src/locale/LanguageProvider.ts +15 -0
- package/src/locale/index.ts +2 -0
- package/src/utils/index.ts +85 -0
- package/src/utils/screenshot.ts +20 -0
package/package.json
ADDED
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@vyr/remote",
|
|
3
|
+
"version": "0.0.1",
|
|
4
|
+
"description": "",
|
|
5
|
+
"main": "./src/index.ts",
|
|
6
|
+
"author": "",
|
|
7
|
+
"license": "MIT",
|
|
8
|
+
"dependencies": {
|
|
9
|
+
"dom-to-image": "^2.6.0",
|
|
10
|
+
"@vyr/locale": "0.0.1",
|
|
11
|
+
"@vyr/declare": "0.0.1",
|
|
12
|
+
"@vyr/engine": "0.0.1"
|
|
13
|
+
},
|
|
14
|
+
"files": [
|
|
15
|
+
"package.json",
|
|
16
|
+
"src/"
|
|
17
|
+
]
|
|
18
|
+
}
|
package/src/Bridge.ts
ADDED
|
@@ -0,0 +1,133 @@
|
|
|
1
|
+
import { AsyncTask, Descriptor, Listener } from "@vyr/engine"
|
|
2
|
+
import { Job } from "./job"
|
|
3
|
+
|
|
4
|
+
interface RemoteConfig {
|
|
5
|
+
/**代理的唯一标识 */
|
|
6
|
+
id: string
|
|
7
|
+
/**远程服务的运行环境 */
|
|
8
|
+
env: 'window' | 'iframe'
|
|
9
|
+
/**远程服务是否执行任务 */
|
|
10
|
+
execute: boolean
|
|
11
|
+
/**是否启用远程服务的调用功能 */
|
|
12
|
+
invoke: boolean
|
|
13
|
+
/**远程服务运行后立即渲染的场景 */
|
|
14
|
+
scene?: string
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
interface BridgeConfig {
|
|
18
|
+
id: string
|
|
19
|
+
args?: any[]
|
|
20
|
+
useRemote?: () => Promise<Window>
|
|
21
|
+
autoConnect?: boolean
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
interface BridgeListener {
|
|
25
|
+
keydown: (event: KeyboardEvent) => void
|
|
26
|
+
keyup: (event: KeyboardEvent) => void
|
|
27
|
+
mouseup: (event: MouseEvent) => void
|
|
28
|
+
close: (args: {}) => void
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
/**
|
|
32
|
+
* 用于在远程环境之间传递信息的桥梁
|
|
33
|
+
*/
|
|
34
|
+
class Bridge {
|
|
35
|
+
static readonly key = '__VYR_RUNTIME_REMOTE'
|
|
36
|
+
static createBaseUrl() {
|
|
37
|
+
const { protocol, hostname, port } = window.location
|
|
38
|
+
return `${protocol}//${hostname}:${port}`
|
|
39
|
+
}
|
|
40
|
+
private _id
|
|
41
|
+
private _args
|
|
42
|
+
private _remote!: Window
|
|
43
|
+
private _closeId = -1
|
|
44
|
+
private _readyId = -1
|
|
45
|
+
private _listener = new Listener<BridgeListener>()
|
|
46
|
+
connected = new AsyncTask()
|
|
47
|
+
comm
|
|
48
|
+
|
|
49
|
+
constructor(config: BridgeConfig) {
|
|
50
|
+
this._id = config.id
|
|
51
|
+
this._args = config.args ?? []
|
|
52
|
+
this.comm = Bridge.createBaseUrl()
|
|
53
|
+
window.addEventListener('message', this.onReceive)
|
|
54
|
+
window.addEventListener('beforeunload', () => this.send(new Job.bridge.disconnect.Response({})))
|
|
55
|
+
if (config.useRemote) config.useRemote().then(this.checkReady)
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
private pipe = (remote: Window, message: Job) => {
|
|
59
|
+
remote.postMessage({ key: Bridge.key, id: this._id, message: Descriptor.serialization(message) }, this.comm)
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
private checkReady = (remote: Window) => {
|
|
63
|
+
if (this._remote) return
|
|
64
|
+
clearTimeout(this._readyId)
|
|
65
|
+
//@ts-ignore
|
|
66
|
+
this._readyId = setTimeout(() => this.checkReady(remote), 1000)
|
|
67
|
+
this.pipe(remote, new Job.bridge.connection.Response({}))
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
private isBridgeMessage = (event: MessageEvent) => {
|
|
71
|
+
return event.data.key === Bridge.key && event.data.id === this._id
|
|
72
|
+
}
|
|
73
|
+
private checkWindowClosed = () => {
|
|
74
|
+
if (this._remote.closed === false) return
|
|
75
|
+
this._listener.trigger('close', {})
|
|
76
|
+
}
|
|
77
|
+
private onDisconnect = () => {
|
|
78
|
+
clearTimeout(this._closeId)
|
|
79
|
+
this._closeId = setTimeout(this.checkWindowClosed, 5000) as unknown as number
|
|
80
|
+
this.connected = new AsyncTask()
|
|
81
|
+
const remote = this._remote
|
|
82
|
+
//@ts-ignore
|
|
83
|
+
this._remote = null
|
|
84
|
+
this.checkReady(remote)
|
|
85
|
+
}
|
|
86
|
+
private onReceive = (event: MessageEvent) => {
|
|
87
|
+
if (this.isBridgeMessage(event) === false) return
|
|
88
|
+
const task = Descriptor.deserialization<Job>(event.data.message)
|
|
89
|
+
switch (task.method) {
|
|
90
|
+
case Job.bridge.connection.Method:
|
|
91
|
+
clearTimeout(this._readyId)
|
|
92
|
+
this._remote = event.source as Window
|
|
93
|
+
this.connected.run()
|
|
94
|
+
const params = task.params as { stop?: boolean }
|
|
95
|
+
if (params.stop === undefined) {
|
|
96
|
+
this.send(new Job.bridge.connection.Response({ stop: true }))
|
|
97
|
+
}
|
|
98
|
+
break;
|
|
99
|
+
case Job.bridge.disconnect.Method:
|
|
100
|
+
this.onDisconnect()
|
|
101
|
+
break;
|
|
102
|
+
default:
|
|
103
|
+
this._listener.trigger(task.method, task, ...this._args)
|
|
104
|
+
break;
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
listen<T extends keyof BridgeListener>(method: T, cb: BridgeListener[T]): void
|
|
109
|
+
listen(method: string, cb: (...args: any[]) => void): void
|
|
110
|
+
listen(method: string, cb: (...args: any[]) => void) {
|
|
111
|
+
this._listener.listen(method, cb)
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
unlisten<T extends keyof BridgeListener>(method: T, cb: BridgeListener[T]): void
|
|
115
|
+
unlisten(method: string, cb: (...args: any[]) => void): void
|
|
116
|
+
unlisten(method: string, cb: (...args: any[]) => void) {
|
|
117
|
+
this._listener.unlisten(method, cb)
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
async send(message: Job) {
|
|
121
|
+
const serialization = Descriptor.serialization(message)
|
|
122
|
+
await this.connected.done()
|
|
123
|
+
this._remote.postMessage({ key: Bridge.key, id: this._id, message: serialization }, this.comm)
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
async close() {
|
|
127
|
+
await this.connected.done()
|
|
128
|
+
this._remote.close()
|
|
129
|
+
this._listener.trigger('close', {})
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
export { RemoteConfig, Bridge }
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import { Descriptor, Graphics, HTMLTransformControllerChangeArgs, HTMLTransformControllerDescriptor, Scriptable } from "@vyr/engine";
|
|
2
|
+
import { RemoteProcess } from "./RemoteProcess";
|
|
3
|
+
import { Job } from "./job";
|
|
4
|
+
|
|
5
|
+
class ChangeScriptable extends Scriptable {
|
|
6
|
+
|
|
7
|
+
execute(descriptor: HTMLTransformControllerDescriptor, graphics: Graphics, args: HTMLTransformControllerChangeArgs) {
|
|
8
|
+
const process = RemoteProcess.get(graphics.engine)
|
|
9
|
+
if (process === null) return
|
|
10
|
+
|
|
11
|
+
if (args.event.type === 'contextmenu') {
|
|
12
|
+
process.bridge.send(new Job.invoke.pick.Response({ descriptor: '' }))
|
|
13
|
+
} else {
|
|
14
|
+
const target = Descriptor.get(args.event.target) as Descriptor
|
|
15
|
+
if (target === null) return
|
|
16
|
+
const params = { eventType: args.event.type, target: args.event.target, descriptor: target.clone(false) }
|
|
17
|
+
process.bridge.send(new Job.invoke.transform.Response(params))
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
export default ChangeScriptable
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
interface Item {
|
|
2
|
+
[k: string]: any
|
|
3
|
+
}
|
|
4
|
+
|
|
5
|
+
class Collection {
|
|
6
|
+
private instance = new Map<Item, Item>()
|
|
7
|
+
private map = new Map<Item, Item>()
|
|
8
|
+
|
|
9
|
+
set(key: Item, value: Item) {
|
|
10
|
+
this.instance.set(key, value)
|
|
11
|
+
this.map.set(value, key)
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
get<T extends Item = Item>(key: Item) {
|
|
15
|
+
return (this.instance.get(key) ?? null) as T | null
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
getByMap<T extends Item = Item>(key: Item) {
|
|
19
|
+
return (this.map.get(key) ?? null) as T | null
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
delete(key: Item) {
|
|
23
|
+
const value = this.instance.get(key)
|
|
24
|
+
if (value === undefined) return
|
|
25
|
+
this.instance.delete(key)
|
|
26
|
+
this.map.delete(value)
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
values<T extends Item = Item>() {
|
|
30
|
+
return [...this.instance.values()] as T[]
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
export {
|
|
35
|
+
Collection
|
|
36
|
+
}
|