@delight-rpc/electron 6.0.0 → 6.0.2

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 CHANGED
@@ -1,10 +1,11 @@
1
1
  {
2
2
  "name": "@delight-rpc/electron",
3
- "version": "6.0.0",
3
+ "version": "6.0.2",
4
4
  "description": "",
5
5
  "keywords": [],
6
6
  "files": [
7
- "lib"
7
+ "lib",
8
+ "src"
8
9
  ],
9
10
  "type": "module",
10
11
  "main": "lib/index.js",
@@ -59,7 +60,7 @@
59
60
  "dependencies": {
60
61
  "@blackglory/errors": "^3.0.0",
61
62
  "@blackglory/prelude": "^0.3.1",
62
- "@delight-rpc/protocol": "^3.0.0",
63
+ "@delight-rpc/protocol": "^4.0.0",
63
64
  "extra-promise": "^6.0.5"
64
65
  },
65
66
  "peerDependencies": {
package/src/client.ts ADDED
@@ -0,0 +1,217 @@
1
+ import * as DelightRPC from 'delight-rpc'
2
+ import { Deferred } from 'extra-promise'
3
+ import Electron from 'electron'
4
+ import { CustomError } from '@blackglory/errors'
5
+ import { IResponse, IError, IBatchResponse } from '@delight-rpc/protocol'
6
+
7
+ export function createClientInMain<IAPI extends object>(
8
+ port: Electron.MessagePortMain
9
+ , { parameterValidators, expectedVersion, channel }: {
10
+ parameterValidators?: DelightRPC.ParameterValidators<IAPI>
11
+ , expectedVersion?: string
12
+ , channel?: string
13
+ } = {}
14
+ ): [client: DelightRPC.ClientProxy<IAPI>, close: () => void] {
15
+ const pendings: Record<string, Deferred<IResponse<unknown>> | undefined> = {}
16
+
17
+ port.addListener('message', handler)
18
+
19
+ const client = DelightRPC.createClient<IAPI>(
20
+ async function send(request) {
21
+ const res = new Deferred<IResponse<unknown>>()
22
+ pendings[request.id] = res
23
+ try {
24
+ port.postMessage(request)
25
+ return await res
26
+ } finally {
27
+ delete pendings[request.id]
28
+ }
29
+ }
30
+ , {
31
+ parameterValidators
32
+ , expectedVersion
33
+ , channel
34
+ }
35
+ )
36
+
37
+ return [client, close]
38
+
39
+ function close(): void {
40
+ port.removeListener('message', handler)
41
+
42
+ for (const [key, deferred] of Object.entries(pendings)) {
43
+ deferred!.reject(new ClientClosed())
44
+ delete pendings[key]
45
+ }
46
+ }
47
+
48
+ function handler(event: Electron.MessageEvent): void {
49
+ const res = event.data
50
+ if (DelightRPC.isResult(res) || DelightRPC.isError(res)) {
51
+ pendings[res.id]?.resolve(res)
52
+ }
53
+ }
54
+ }
55
+
56
+ export function createClientInRenderer<IAPI extends object>(
57
+ port: MessagePort
58
+ , { parameterValidators, expectedVersion, channel }: {
59
+ parameterValidators?: DelightRPC.ParameterValidators<IAPI>
60
+ expectedVersion?: string
61
+ channel?: string
62
+ } = {}
63
+ ): [client: DelightRPC.ClientProxy<IAPI>, close: () => void] {
64
+ const pendings: Record<
65
+ string
66
+ , | Deferred<IResponse<unknown>>
67
+ | undefined
68
+ > = {}
69
+
70
+ port.addEventListener('message', handler)
71
+
72
+ const client = DelightRPC.createClient<IAPI>(
73
+ async function send(request) {
74
+ const res = new Deferred<IResponse<unknown>>()
75
+ pendings[request.id] = res
76
+ try {
77
+ port.postMessage(request)
78
+ return await res
79
+ } finally {
80
+ delete pendings[request.id]
81
+ }
82
+ }
83
+ , {
84
+ parameterValidators
85
+ , expectedVersion
86
+ , channel
87
+ }
88
+ )
89
+
90
+ return [client, close]
91
+
92
+ function close(): void {
93
+ port.removeEventListener('message', handler)
94
+
95
+ for (const [key, deferred] of Object.entries(pendings)) {
96
+ deferred!.reject(new ClientClosed())
97
+ delete pendings[key]
98
+ }
99
+ }
100
+
101
+ function handler(event: MessageEvent): void {
102
+ const res = event.data
103
+ if (DelightRPC.isResult(res) || DelightRPC.isError(res)) {
104
+ pendings[res.id]?.resolve(res)
105
+ }
106
+ }
107
+ }
108
+
109
+ export function createBatchClientInMain<DataType>(
110
+ port: Electron.MessagePortMain
111
+ , { expectedVersion, channel }: {
112
+ expectedVersion?: string
113
+ channel?: string
114
+ } = {}
115
+ ): [client: DelightRPC.BatchClient<DataType>, close: () => void] {
116
+ const pendings: Record<
117
+ string
118
+ , | Deferred<IError | IBatchResponse<unknown>>
119
+ | undefined
120
+ > = {}
121
+
122
+ port.addListener('message', handler)
123
+
124
+ const client = new DelightRPC.BatchClient(
125
+ async function send(request) {
126
+ const res = new Deferred<
127
+ | IError
128
+ | IBatchResponse<unknown>
129
+ >()
130
+ pendings[request.id] = res
131
+ try {
132
+ port.postMessage(request)
133
+ return await res
134
+ } finally {
135
+ delete pendings[request.id]
136
+ }
137
+ }
138
+ , {
139
+ expectedVersion
140
+ , channel
141
+ }
142
+ )
143
+
144
+ return [client, close]
145
+
146
+ function close(): void {
147
+ port.removeListener('message', handler)
148
+
149
+ for (const [key, deferred] of Object.entries(pendings)) {
150
+ deferred!.reject(new ClientClosed())
151
+ delete pendings[key]
152
+ }
153
+ }
154
+
155
+ function handler(event: Electron.MessageEvent): void {
156
+ const res = event.data
157
+ if (DelightRPC.isError(res) || DelightRPC.isBatchResponse(res)) {
158
+ pendings[res.id]?.resolve(res)
159
+ }
160
+ }
161
+ }
162
+
163
+ export function createBatchClientInRenderer<DataType>(
164
+ port: MessagePort
165
+ , { expectedVersion, channel }: {
166
+ expectedVersion?: string
167
+ channel?: string
168
+ } = {}
169
+ ): [client: DelightRPC.BatchClient<DataType>, close: () => void] {
170
+ const pendings: Record<
171
+ string
172
+ , | Deferred<IError | IBatchResponse<unknown>>
173
+ | undefined
174
+ > = {}
175
+
176
+ port.addEventListener('message', handler)
177
+
178
+ const client = new DelightRPC.BatchClient(
179
+ async function send(request) {
180
+ const res = new Deferred<
181
+ | IError
182
+ | IBatchResponse<unknown>
183
+ >()
184
+ pendings[request.id] = res
185
+ try {
186
+ port.postMessage(request)
187
+ return await res
188
+ } finally {
189
+ delete pendings[request.id]
190
+ }
191
+ }
192
+ , {
193
+ expectedVersion
194
+ , channel
195
+ }
196
+ )
197
+
198
+ return [client, close]
199
+
200
+ function close(): void {
201
+ port.removeEventListener('message', handler)
202
+
203
+ for (const [key, deferred] of Object.entries(pendings)) {
204
+ deferred!.reject(new ClientClosed())
205
+ delete pendings[key]
206
+ }
207
+ }
208
+
209
+ function handler(event: MessageEvent): void {
210
+ const res = event.data
211
+ if (DelightRPC.isError(res) || DelightRPC.isBatchResponse(res)) {
212
+ pendings[res.id]?.resolve(res)
213
+ }
214
+ }
215
+ }
216
+
217
+ export class ClientClosed extends CustomError {}
package/src/index.ts ADDED
@@ -0,0 +1,2 @@
1
+ export * from './client.js'
2
+ export * from './server.js'
package/src/server.ts ADDED
@@ -0,0 +1,71 @@
1
+ import * as DelightRPC from 'delight-rpc'
2
+ import Electron from 'electron'
3
+ import { isntNull } from '@blackglory/prelude'
4
+
5
+ export function createServerInMain<IAPI extends object>(
6
+ api: DelightRPC.ImplementationOf<IAPI>
7
+ , port: Electron.MessagePortMain
8
+ , { parameterValidators, version, channel, ownPropsOnly }: {
9
+ parameterValidators?: DelightRPC.ParameterValidators<IAPI>
10
+ version?: `${number}.${number}.${number}`
11
+ channel?: string | RegExp | typeof DelightRPC.AnyChannel
12
+ ownPropsOnly?: boolean
13
+ } = {}
14
+ ): () => void {
15
+ port.addListener('message', handler)
16
+ return () => port.removeListener('message', handler)
17
+
18
+ async function handler(event: Electron.MessageEvent): Promise<void> {
19
+ const req = event.data
20
+ if (DelightRPC.isRequest(req) || DelightRPC.isBatchRequest(req)) {
21
+ const result = await DelightRPC.createResponse(
22
+ api
23
+ , req
24
+ , {
25
+ parameterValidators
26
+ , version
27
+ , channel
28
+ , ownPropsOnly
29
+ }
30
+ )
31
+
32
+ if (isntNull(result)) {
33
+ port.postMessage(result)
34
+ }
35
+ }
36
+ }
37
+ }
38
+
39
+ export function createServerInRenderer<IAPI extends object>(
40
+ api: DelightRPC.ImplementationOf<IAPI>
41
+ , port: MessagePort
42
+ , { parameterValidators, version, channel, ownPropsOnly }: {
43
+ parameterValidators?: DelightRPC.ParameterValidators<IAPI>
44
+ version?: `${number}.${number}.${number}`
45
+ channel?: string | RegExp | typeof DelightRPC.AnyChannel
46
+ ownPropsOnly?: boolean
47
+ } = {}
48
+ ): () => void {
49
+ port.addEventListener('message', handler)
50
+ return () => port.removeEventListener('message', handler)
51
+
52
+ async function handler(event: MessageEvent): Promise<void> {
53
+ const req = event.data
54
+ if (DelightRPC.isRequest(req) || DelightRPC.isBatchRequest(req)) {
55
+ const result = await DelightRPC.createResponse(
56
+ api
57
+ , req
58
+ , {
59
+ parameterValidators
60
+ , version
61
+ , channel
62
+ , ownPropsOnly
63
+ }
64
+ )
65
+
66
+ if (isntNull(result)) {
67
+ port.postMessage(result)
68
+ }
69
+ }
70
+ }
71
+ }