@polytric/openws-sdkgen 0.0.5 → 0.0.6
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/README.md +2 -2
- package/dist/main.cjs +13 -1
- package/dist/main.js +13 -1
- package/dist/plans/dotnet.cjs +1 -1
- package/dist/plans/dotnet.d.cts +2 -109
- package/dist/plans/dotnet.d.ts +2 -109
- package/dist/plans/typescript.cjs +569 -0
- package/dist/plans/typescript.d.cts +6 -0
- package/dist/plans/typescript.d.ts +6 -0
- package/dist/plans/typescript.js +532 -0
- package/dist/templates/typescript/package.json.ejs +41 -0
- package/dist/templates/typescript/src/core/index.ts.ejs +6 -0
- package/dist/templates/typescript/src/core/models/index.ts.ejs +3 -0
- package/dist/templates/typescript/src/core/models/model.ts.ejs +41 -0
- package/dist/templates/typescript/src/core/network.ts.ejs +517 -0
- package/dist/templates/typescript/src/core/roles/index.ts.ejs +3 -0
- package/dist/templates/typescript/src/core/roles/role.ts.ejs +104 -0
- package/dist/templates/typescript/src/index.ts.ejs +4 -0
- package/dist/templates/typescript/src/sdk/index.ts.ejs +3 -0
- package/dist/templates/typescript/src/sdk/role.ts.ejs +372 -0
- package/dist/templates/typescript/tsconfig.json.ejs +14 -0
- package/dist/templates/typescript/tsup.config.ts.ejs +10 -0
- package/dist/types-BdZPs123.d.cts +115 -0
- package/dist/types-BdZPs123.d.ts +115 -0
- package/package.json +10 -3
|
@@ -0,0 +1,372 @@
|
|
|
1
|
+
<% const networkImport = ctx.isTypeScript ? '../core/network' : '../core/network.js' -%>
|
|
2
|
+
<% const modelImportPath = ctx.isTypeScript ? `../core/models/${ctx.fileName}` : `../core/models/${ctx.fileName}/index.js` -%>
|
|
3
|
+
<% const rolesImport = ctx.isTypeScript ? '../core/roles' : '../core/roles/index.js' -%>
|
|
4
|
+
<% if (ctx.isTypeScript) { -%>
|
|
5
|
+
import * as WS from '@polytric/openws/class'
|
|
6
|
+
import * as Fluent from '@polytric/openws/fluent'
|
|
7
|
+
import type { ApiProto } from '@polytric/openws/fluent'
|
|
8
|
+
import type { BindTransportOptions, OpenWsEndpoint, OpenWsEnvelope, Transport, Unsubscribe } from '<%= networkImport %>'
|
|
9
|
+
import { WsTransport, bindTransport, canBindTransport, decodeEnvelope, encodeEnvelope } from '<%= networkImport %>'
|
|
10
|
+
<% if (ctx.handlers.length > 0) { -%>
|
|
11
|
+
import type {
|
|
12
|
+
<% for (const handler of ctx.handlers) { -%>
|
|
13
|
+
<%= handler.payloadType %>,
|
|
14
|
+
<% } -%>
|
|
15
|
+
} from '<%= modelImportPath %>'
|
|
16
|
+
export * from '<%= modelImportPath %>'
|
|
17
|
+
<% } -%>
|
|
18
|
+
import {
|
|
19
|
+
<%= ctx.hostRoleClassName %>,
|
|
20
|
+
<% for (const remoteRole of ctx.remoteRoles) { -%>
|
|
21
|
+
<%= remoteRole.roleClassName %>,
|
|
22
|
+
type <%= remoteRole.apiName %>,
|
|
23
|
+
<% } -%>
|
|
24
|
+
} from '<%= rolesImport %>'
|
|
25
|
+
|
|
26
|
+
<% for (const remoteRole of ctx.remoteRoles) { -%>
|
|
27
|
+
export type <%= remoteRole.scopedApiName %> = Pick<<%= remoteRole.apiName %>, <%- remoteRole.allowedMethodNames.length > 0 ? remoteRole.allowedMethodNames.map(methodName => JSON.stringify(methodName)).join(' | ') : 'never' %>>
|
|
28
|
+
<% } -%>
|
|
29
|
+
|
|
30
|
+
<% if (ctx.remoteRoles.length > 0) { -%>
|
|
31
|
+
export type <%= ctx.className %>PeerApi = <%= ctx.remoteRoles.map(remoteRole => remoteRole.scopedApiName).join(' | ') %>
|
|
32
|
+
|
|
33
|
+
<% } else { -%>
|
|
34
|
+
export type <%= ctx.className %>PeerApi = unknown
|
|
35
|
+
|
|
36
|
+
<% } -%>
|
|
37
|
+
<% if (ctx.handlers.length > 0) { -%>
|
|
38
|
+
export type <%= ctx.className %>MessageHandler<TPayload, TApi = <%= ctx.className %>PeerApi> = (payload: TPayload, api: TApi) => void | Promise<void>
|
|
39
|
+
|
|
40
|
+
<% } -%>
|
|
41
|
+
export type <%= ctx.className %>ErrorHandler = (error: unknown) => void | Promise<void>
|
|
42
|
+
|
|
43
|
+
export class <%= ctx.className %> {
|
|
44
|
+
static readonly CONFIG = <%= ctx.hostRoleClassName %>.CONFIG
|
|
45
|
+
|
|
46
|
+
readonly name = <%= ctx.className %>.CONFIG.name
|
|
47
|
+
readonly description = <%= ctx.className %>.CONFIG.description
|
|
48
|
+
<% for (const remoteRole of ctx.remoteRoles) { -%>
|
|
49
|
+
<%= remoteRole.apiVarName %>!: <%= remoteRole.scopedApiName %>
|
|
50
|
+
<% } -%>
|
|
51
|
+
|
|
52
|
+
private readonly binder: Fluent.NetworkBinder
|
|
53
|
+
private readonly runtime: Fluent.Runtime
|
|
54
|
+
private readonly fromRole = <%- JSON.stringify(ctx.roleName) %>
|
|
55
|
+
private readonly sendEnvelope: (toRole: string, messageName: string, payload: unknown) => Promise<void>
|
|
56
|
+
private transportUnsubscribe?: Unsubscribe
|
|
57
|
+
private readonly apisByRole: Record<string, ApiProto> = {}
|
|
58
|
+
private readonly apisByMessageName: Record<string, ApiProto> = {}
|
|
59
|
+
private readonly handlersByMessageName: Record<string, (payload: unknown, api: <%= ctx.className %>PeerApi) => Promise<void>> = {}
|
|
60
|
+
private readonly messageErrorHandlers = new Set<<%= ctx.className %>ErrorHandler>()
|
|
61
|
+
private readonly socketErrorHandlers = new Set<<%= ctx.className %>ErrorHandler>()
|
|
62
|
+
<% for (const handler of ctx.handlers) { -%>
|
|
63
|
+
<% const handlerApiType = handler.bindFromRoles.map(fromRole => ctx.remoteRoles.find(remoteRole => remoteRole.roleName === fromRole.roleName)?.scopedApiName).filter(Boolean).join(' | ') || `${ctx.className}PeerApi` -%>
|
|
64
|
+
private readonly <%= handler.listenerFieldName %> = new Set<<%= ctx.className %>MessageHandler<<%= handler.payloadType %>, <%= handlerApiType %>>>()
|
|
65
|
+
<% } -%>
|
|
66
|
+
|
|
67
|
+
constructor(
|
|
68
|
+
protected readonly transport: Transport = new WsTransport()
|
|
69
|
+
) {
|
|
70
|
+
const HostRole = this.constructor as typeof <%= ctx.className %>
|
|
71
|
+
this.binder = Fluent.bindings(
|
|
72
|
+
WS.network({
|
|
73
|
+
name: <%- JSON.stringify(ctx.networkName) %>,
|
|
74
|
+
description: <%- JSON.stringify(ctx.networkDescription ?? '') %>,
|
|
75
|
+
version: <%- JSON.stringify(ctx.networkVersion ?? '1.0.0') %>,
|
|
76
|
+
roles: [HostRole<% if (ctx.remoteRoles.length > 0) { %>, <%= ctx.remoteRoles.map(remoteRole => remoteRole.roleClassName).join(', ') %><% } %>],
|
|
77
|
+
})
|
|
78
|
+
)
|
|
79
|
+
this.runtime = WS.runtime(this.binder)
|
|
80
|
+
this.sendEnvelope = async (_toRole: string, messageName: string, payload: unknown) => {
|
|
81
|
+
await this.transport.send(encodeEnvelope({ fromRole: this.fromRole, messageName, payload }))
|
|
82
|
+
}
|
|
83
|
+
<% for (const handler of ctx.handlers) { -%>
|
|
84
|
+
<% const handlerApiType = handler.bindFromRoles.map(fromRole => ctx.remoteRoles.find(remoteRole => remoteRole.roleName === fromRole.roleName)?.scopedApiName).filter(Boolean).join(' | ') || `${ctx.className}PeerApi` -%>
|
|
85
|
+
this.handlersByMessageName[<%- JSON.stringify(handler.messageName) %>] = async (payload, api) => {
|
|
86
|
+
await this.<%= handler.dispatchMethodName %>(payload as <%= handler.payloadType %>, api as <%= handlerApiType %>)
|
|
87
|
+
}
|
|
88
|
+
<% for (const fromRole of handler.bindFromRoles) { -%>
|
|
89
|
+
this.binder.fromRoles[<%- JSON.stringify(fromRole.roleName) %>].on(<%- JSON.stringify(handler.messageName) %>, async (payload, api) => {
|
|
90
|
+
await this.<%= handler.dispatchMethodName %>(payload as <%= handler.payloadType %>, api as unknown as <%= handlerApiType %>)
|
|
91
|
+
})
|
|
92
|
+
<% } -%>
|
|
93
|
+
<% } -%>
|
|
94
|
+
if (canBindTransport(transport)) {
|
|
95
|
+
this.bindTransport(transport)
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
<% for (const remoteRole of ctx.remoteRoles) { -%>
|
|
100
|
+
async connect(roleName: <%- JSON.stringify(remoteRole.roleName) %>, endpoint?: OpenWsEndpoint): Promise<<%= remoteRole.scopedApiName %>>
|
|
101
|
+
<% } -%>
|
|
102
|
+
async connect(roleName: string, endpoint?: OpenWsEndpoint): Promise<<%= ctx.className %>PeerApi> {
|
|
103
|
+
switch (roleName) {
|
|
104
|
+
<% for (const remoteRole of ctx.remoteRoles) { -%>
|
|
105
|
+
case <%- JSON.stringify(remoteRole.roleName) %>: {
|
|
106
|
+
const remoteEndpoint = endpoint ?? (<%- remoteRole.endpoints.length > 0 ? JSON.stringify(remoteRole.endpoints[0]) : 'undefined' %> as OpenWsEndpoint | undefined)
|
|
107
|
+
await this.transport.connect?.(roleName, remoteEndpoint)
|
|
108
|
+
if (!this.apisByRole[<%- JSON.stringify(remoteRole.roleName) %>]) {
|
|
109
|
+
const <%= remoteRole.varName %>Api = this.runtime.createApi(<%- JSON.stringify(remoteRole.roleName) %>, this.sendEnvelope)
|
|
110
|
+
this.<%= remoteRole.apiVarName %> = <%= remoteRole.varName %>Api as unknown as <%= remoteRole.scopedApiName %>
|
|
111
|
+
this.apisByRole[<%- JSON.stringify(remoteRole.roleName) %>] = <%= remoteRole.varName %>Api
|
|
112
|
+
<% for (const handler of ctx.handlers) { -%>
|
|
113
|
+
<% const handlerDefaultApi = handler.bindFromRoles.find(fromRole => ctx.remoteRoles.some(remoteRole => remoteRole.roleName === fromRole.roleName)) ?? ctx.remoteRoles[0] -%>
|
|
114
|
+
<% if (handlerDefaultApi?.roleName === remoteRole.roleName) { -%>
|
|
115
|
+
this.apisByMessageName[<%- JSON.stringify(handler.messageName) %>] = <%= remoteRole.varName %>Api
|
|
116
|
+
<% } -%>
|
|
117
|
+
<% } -%>
|
|
118
|
+
}
|
|
119
|
+
return this.<%= remoteRole.apiVarName %>
|
|
120
|
+
}
|
|
121
|
+
<% } -%>
|
|
122
|
+
default:
|
|
123
|
+
throw new Error(`Remote role ${roleName} not found`)
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
async disconnect(roleName: string): Promise<void> {
|
|
128
|
+
await this.transport.disconnect?.(roleName)
|
|
129
|
+
delete this.apisByRole[roleName]
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
bindTransport(transport: Transport = this.transport, options: BindTransportOptions = {}): Unsubscribe {
|
|
133
|
+
this.transportUnsubscribe?.()
|
|
134
|
+
this.transportUnsubscribe = bindTransport(transport, this, options)
|
|
135
|
+
return this.transportUnsubscribe
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
unbindTransport(): void {
|
|
139
|
+
this.transportUnsubscribe?.()
|
|
140
|
+
this.transportUnsubscribe = undefined
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
async messageError(error: unknown): Promise<void> {
|
|
144
|
+
for (const handler of this.messageErrorHandlers) {
|
|
145
|
+
await handler(error)
|
|
146
|
+
}
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
onMessageError(handler: <%= ctx.className %>ErrorHandler): Unsubscribe {
|
|
150
|
+
this.messageErrorHandlers.add(handler)
|
|
151
|
+
return () => {
|
|
152
|
+
this.messageErrorHandlers.delete(handler)
|
|
153
|
+
}
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
async socketError(error: unknown): Promise<void> {
|
|
157
|
+
for (const handler of this.socketErrorHandlers) {
|
|
158
|
+
await handler(error)
|
|
159
|
+
}
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
onSocketError(handler: <%= ctx.className %>ErrorHandler): Unsubscribe {
|
|
163
|
+
this.socketErrorHandlers.add(handler)
|
|
164
|
+
return () => {
|
|
165
|
+
this.socketErrorHandlers.delete(handler)
|
|
166
|
+
}
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
<% for (const handler of ctx.handlers) { -%>
|
|
170
|
+
<% const handlerApiType = handler.bindFromRoles.map(fromRole => ctx.remoteRoles.find(remoteRole => remoteRole.roleName === fromRole.roleName)?.scopedApiName).filter(Boolean).join(' | ') || `${ctx.className}PeerApi` -%>
|
|
171
|
+
async <%= handler.dispatchMethodName %>(payload: <%= handler.payloadType %>, api: <%= handlerApiType %>): Promise<void> {
|
|
172
|
+
for (const handler of this.<%= handler.listenerFieldName %>) {
|
|
173
|
+
await handler(payload, api)
|
|
174
|
+
}
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
<%= handler.onMethodName %>(handler: <%= ctx.className %>MessageHandler<<%= handler.payloadType %>, <%= handlerApiType %>>): Unsubscribe {
|
|
178
|
+
this.<%= handler.listenerFieldName %>.add(handler)
|
|
179
|
+
return () => {
|
|
180
|
+
this.<%= handler.listenerFieldName %>.delete(handler)
|
|
181
|
+
}
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
<% } -%>
|
|
185
|
+
async handleRawMessage(data: string): Promise<void> {
|
|
186
|
+
await this.handleMessage(decodeEnvelope(data))
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
async handleMessage(envelope: OpenWsEnvelope): Promise<void> {
|
|
190
|
+
const remote = this.binder.fromRoles[envelope.fromRole]
|
|
191
|
+
const api = this.apisByRole[envelope.fromRole]
|
|
192
|
+
if (remote && api) {
|
|
193
|
+
await remote.handleMessage(envelope.messageName, envelope.payload, api)
|
|
194
|
+
return
|
|
195
|
+
}
|
|
196
|
+
|
|
197
|
+
const localHandler = this.handlersByMessageName[envelope.messageName]
|
|
198
|
+
const localApi = this.apisByMessageName[envelope.messageName]
|
|
199
|
+
if (envelope.fromRole === this.fromRole && localHandler && localApi) {
|
|
200
|
+
await localHandler(envelope.payload, localApi as unknown as <%= ctx.className %>PeerApi)
|
|
201
|
+
return
|
|
202
|
+
}
|
|
203
|
+
|
|
204
|
+
throw new Error(`Remote role ${envelope.fromRole} not found`)
|
|
205
|
+
}
|
|
206
|
+
}
|
|
207
|
+
<% } else { -%>
|
|
208
|
+
import * as WS from '@polytric/openws/class'
|
|
209
|
+
import * as Fluent from '@polytric/openws/fluent'
|
|
210
|
+
import { WsTransport, bindTransport, canBindTransport, decodeEnvelope, encodeEnvelope } from '<%= networkImport %>'
|
|
211
|
+
<% if (ctx.handlers.length > 0) { -%>
|
|
212
|
+
export * from '<%= modelImportPath %>'
|
|
213
|
+
<% } -%>
|
|
214
|
+
import {
|
|
215
|
+
<%= ctx.hostRoleClassName %>,
|
|
216
|
+
<% for (const remoteRole of ctx.remoteRoles) { -%>
|
|
217
|
+
<%= remoteRole.roleClassName %>,
|
|
218
|
+
<% } -%>
|
|
219
|
+
} from '<%= rolesImport %>'
|
|
220
|
+
|
|
221
|
+
export class <%= ctx.className %> {
|
|
222
|
+
static CONFIG = <%= ctx.hostRoleClassName %>.CONFIG
|
|
223
|
+
|
|
224
|
+
name = <%= ctx.className %>.CONFIG.name
|
|
225
|
+
description = <%= ctx.className %>.CONFIG.description
|
|
226
|
+
runtime
|
|
227
|
+
sendEnvelope
|
|
228
|
+
#transportUnsubscribe
|
|
229
|
+
#apisByRole = {}
|
|
230
|
+
#apisByMessageName = {}
|
|
231
|
+
#handlersByMessageName = {}
|
|
232
|
+
#messageErrorHandlers = new Set()
|
|
233
|
+
#socketErrorHandlers = new Set()
|
|
234
|
+
#fromRole = <%- JSON.stringify(ctx.roleName) %>
|
|
235
|
+
<% for (const handler of ctx.handlers) { -%>
|
|
236
|
+
#<%= handler.listenerFieldName %> = new Set()
|
|
237
|
+
<% } -%>
|
|
238
|
+
|
|
239
|
+
constructor(transport = new WsTransport()) {
|
|
240
|
+
this.transport = transport
|
|
241
|
+
const HostRole = this.constructor
|
|
242
|
+
this.binder = Fluent.bindings(
|
|
243
|
+
WS.network({
|
|
244
|
+
name: <%- JSON.stringify(ctx.networkName) %>,
|
|
245
|
+
description: <%- JSON.stringify(ctx.networkDescription ?? '') %>,
|
|
246
|
+
version: <%- JSON.stringify(ctx.networkVersion ?? '1.0.0') %>,
|
|
247
|
+
roles: [HostRole<% if (ctx.remoteRoles.length > 0) { %>, <%= ctx.remoteRoles.map(remoteRole => remoteRole.roleClassName).join(', ') %><% } %>],
|
|
248
|
+
})
|
|
249
|
+
)
|
|
250
|
+
this.runtime = WS.runtime(this.binder)
|
|
251
|
+
this.sendEnvelope = async (_toRole, messageName, payload) => {
|
|
252
|
+
await this.transport.send(encodeEnvelope({ fromRole: this.#fromRole, messageName, payload }))
|
|
253
|
+
}
|
|
254
|
+
<% for (const handler of ctx.handlers) { -%>
|
|
255
|
+
this.#handlersByMessageName[<%- JSON.stringify(handler.messageName) %>] = async (payload, api) => {
|
|
256
|
+
await this.<%= handler.dispatchMethodName %>(payload, api)
|
|
257
|
+
}
|
|
258
|
+
<% for (const fromRole of handler.bindFromRoles) { -%>
|
|
259
|
+
this.binder.fromRoles[<%- JSON.stringify(fromRole.roleName) %>].on(<%- JSON.stringify(handler.messageName) %>, async (payload, api) => {
|
|
260
|
+
await this.<%= handler.dispatchMethodName %>(payload, api)
|
|
261
|
+
})
|
|
262
|
+
<% } -%>
|
|
263
|
+
<% } -%>
|
|
264
|
+
if (canBindTransport(transport)) {
|
|
265
|
+
this.bindTransport(transport)
|
|
266
|
+
}
|
|
267
|
+
}
|
|
268
|
+
|
|
269
|
+
async connect(roleName, endpoint) {
|
|
270
|
+
switch (roleName) {
|
|
271
|
+
<% for (const remoteRole of ctx.remoteRoles) { -%>
|
|
272
|
+
case <%- JSON.stringify(remoteRole.roleName) %>: {
|
|
273
|
+
const remoteEndpoint = endpoint ?? <%- remoteRole.endpoints.length > 0 ? JSON.stringify(remoteRole.endpoints[0]) : 'undefined' %>
|
|
274
|
+
await this.transport.connect?.(roleName, remoteEndpoint)
|
|
275
|
+
if (!this.#apisByRole[<%- JSON.stringify(remoteRole.roleName) %>]) {
|
|
276
|
+
this.<%= remoteRole.apiVarName %> = this.runtime.createApi(<%- JSON.stringify(remoteRole.roleName) %>, this.sendEnvelope)
|
|
277
|
+
this.#apisByRole[<%- JSON.stringify(remoteRole.roleName) %>] = this.<%= remoteRole.apiVarName %>
|
|
278
|
+
<% for (const handler of ctx.handlers) { -%>
|
|
279
|
+
<% const handlerDefaultApi = handler.bindFromRoles.find(fromRole => ctx.remoteRoles.some(remoteRole => remoteRole.roleName === fromRole.roleName)) ?? ctx.remoteRoles[0] -%>
|
|
280
|
+
<% if (handlerDefaultApi?.roleName === remoteRole.roleName) { -%>
|
|
281
|
+
this.#apisByMessageName[<%- JSON.stringify(handler.messageName) %>] = this.<%= remoteRole.apiVarName %>
|
|
282
|
+
<% } -%>
|
|
283
|
+
<% } -%>
|
|
284
|
+
}
|
|
285
|
+
return this.<%= remoteRole.apiVarName %>
|
|
286
|
+
}
|
|
287
|
+
<% } -%>
|
|
288
|
+
default:
|
|
289
|
+
throw new Error(`Remote role ${roleName} not found`)
|
|
290
|
+
}
|
|
291
|
+
}
|
|
292
|
+
|
|
293
|
+
async disconnect(roleName) {
|
|
294
|
+
await this.transport.disconnect?.(roleName)
|
|
295
|
+
delete this.#apisByRole[roleName]
|
|
296
|
+
}
|
|
297
|
+
|
|
298
|
+
bindTransport(transport = this.transport, options = {}) {
|
|
299
|
+
this.#transportUnsubscribe?.()
|
|
300
|
+
this.#transportUnsubscribe = bindTransport(transport, this, options)
|
|
301
|
+
return this.#transportUnsubscribe
|
|
302
|
+
}
|
|
303
|
+
|
|
304
|
+
unbindTransport() {
|
|
305
|
+
this.#transportUnsubscribe?.()
|
|
306
|
+
this.#transportUnsubscribe = undefined
|
|
307
|
+
}
|
|
308
|
+
|
|
309
|
+
async messageError(error) {
|
|
310
|
+
for (const handler of this.#messageErrorHandlers) {
|
|
311
|
+
await handler(error)
|
|
312
|
+
}
|
|
313
|
+
}
|
|
314
|
+
|
|
315
|
+
onMessageError(handler) {
|
|
316
|
+
this.#messageErrorHandlers.add(handler)
|
|
317
|
+
return () => {
|
|
318
|
+
this.#messageErrorHandlers.delete(handler)
|
|
319
|
+
}
|
|
320
|
+
}
|
|
321
|
+
|
|
322
|
+
async socketError(error) {
|
|
323
|
+
for (const handler of this.#socketErrorHandlers) {
|
|
324
|
+
await handler(error)
|
|
325
|
+
}
|
|
326
|
+
}
|
|
327
|
+
|
|
328
|
+
onSocketError(handler) {
|
|
329
|
+
this.#socketErrorHandlers.add(handler)
|
|
330
|
+
return () => {
|
|
331
|
+
this.#socketErrorHandlers.delete(handler)
|
|
332
|
+
}
|
|
333
|
+
}
|
|
334
|
+
|
|
335
|
+
<% for (const handler of ctx.handlers) { -%>
|
|
336
|
+
async <%= handler.dispatchMethodName %>(payload, api) {
|
|
337
|
+
for (const handler of this.#<%= handler.listenerFieldName %>) {
|
|
338
|
+
await handler(payload, api)
|
|
339
|
+
}
|
|
340
|
+
}
|
|
341
|
+
|
|
342
|
+
<%= handler.onMethodName %>(handler) {
|
|
343
|
+
this.#<%= handler.listenerFieldName %>.add(handler)
|
|
344
|
+
return () => {
|
|
345
|
+
this.#<%= handler.listenerFieldName %>.delete(handler)
|
|
346
|
+
}
|
|
347
|
+
}
|
|
348
|
+
|
|
349
|
+
<% } -%>
|
|
350
|
+
async handleRawMessage(data) {
|
|
351
|
+
await this.handleMessage(decodeEnvelope(data))
|
|
352
|
+
}
|
|
353
|
+
|
|
354
|
+
async handleMessage(envelope) {
|
|
355
|
+
const remote = this.binder.fromRoles[envelope.fromRole]
|
|
356
|
+
const api = this.#apisByRole[envelope.fromRole]
|
|
357
|
+
if (remote && api) {
|
|
358
|
+
await remote.handleMessage(envelope.messageName, envelope.payload, api)
|
|
359
|
+
return
|
|
360
|
+
}
|
|
361
|
+
|
|
362
|
+
const localHandler = this.#handlersByMessageName[envelope.messageName]
|
|
363
|
+
const localApi = this.#apisByMessageName[envelope.messageName]
|
|
364
|
+
if (envelope.fromRole === this.#fromRole && localHandler && localApi) {
|
|
365
|
+
await localHandler(envelope.payload, localApi)
|
|
366
|
+
return
|
|
367
|
+
}
|
|
368
|
+
|
|
369
|
+
throw new Error(`Remote role ${envelope.fromRole} not found`)
|
|
370
|
+
}
|
|
371
|
+
}
|
|
372
|
+
<% } -%>
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
{
|
|
2
|
+
"compilerOptions": {
|
|
3
|
+
"target": "ES2022",
|
|
4
|
+
"module": "ESNext",
|
|
5
|
+
"moduleResolution": "bundler",
|
|
6
|
+
"strict": true,
|
|
7
|
+
"declaration": true,
|
|
8
|
+
"skipLibCheck": true,
|
|
9
|
+
"esModuleInterop": true,
|
|
10
|
+
"outDir": "dist",
|
|
11
|
+
"rootDir": "src"
|
|
12
|
+
},
|
|
13
|
+
"include": ["src/**/*.ts"]
|
|
14
|
+
}
|
|
@@ -0,0 +1,115 @@
|
|
|
1
|
+
import { Spec, Endpoint } from '@polytric/openws-spec/types';
|
|
2
|
+
|
|
3
|
+
interface PipelineContext {
|
|
4
|
+
argv: string[];
|
|
5
|
+
rawInput?: RawInput;
|
|
6
|
+
request?: BuildRequest;
|
|
7
|
+
spec?: Spec;
|
|
8
|
+
ir?: IR;
|
|
9
|
+
plan?: PlanStep[];
|
|
10
|
+
}
|
|
11
|
+
interface RawInput {
|
|
12
|
+
spec: string;
|
|
13
|
+
out: string;
|
|
14
|
+
project: string;
|
|
15
|
+
hostRole: string[];
|
|
16
|
+
language: 'csharp' | 'javascript' | 'typescript';
|
|
17
|
+
environment: 'unity' | 'node' | 'browser';
|
|
18
|
+
frameworks?: string[];
|
|
19
|
+
}
|
|
20
|
+
interface BuildRequest {
|
|
21
|
+
specPath: string;
|
|
22
|
+
outputPath: string;
|
|
23
|
+
project: string;
|
|
24
|
+
hostRoles: string[];
|
|
25
|
+
target: {
|
|
26
|
+
csharp?: {
|
|
27
|
+
environment: 'unity';
|
|
28
|
+
frameworks?: string[];
|
|
29
|
+
};
|
|
30
|
+
javascript?: {
|
|
31
|
+
environment: 'node' | 'browser';
|
|
32
|
+
frameworks?: string[];
|
|
33
|
+
};
|
|
34
|
+
typescript?: {
|
|
35
|
+
environment: 'node' | 'browser';
|
|
36
|
+
frameworks?: string[];
|
|
37
|
+
};
|
|
38
|
+
};
|
|
39
|
+
}
|
|
40
|
+
interface IR {
|
|
41
|
+
package: IRPackage;
|
|
42
|
+
networks: IRNetwork[];
|
|
43
|
+
assemblyName?: string;
|
|
44
|
+
}
|
|
45
|
+
interface IRPackage {
|
|
46
|
+
project: string;
|
|
47
|
+
service: string;
|
|
48
|
+
description?: string;
|
|
49
|
+
version?: string;
|
|
50
|
+
}
|
|
51
|
+
interface IRNetwork {
|
|
52
|
+
name: string;
|
|
53
|
+
description?: string;
|
|
54
|
+
version?: string;
|
|
55
|
+
roles: IRRole[];
|
|
56
|
+
handlers: IRHandler[];
|
|
57
|
+
messages: IRMessage[];
|
|
58
|
+
models: IRModel[];
|
|
59
|
+
}
|
|
60
|
+
interface IRRole {
|
|
61
|
+
name: string;
|
|
62
|
+
description?: string;
|
|
63
|
+
isHost: boolean;
|
|
64
|
+
endpoints: Endpoint[];
|
|
65
|
+
}
|
|
66
|
+
interface IRHandler {
|
|
67
|
+
roleName: string;
|
|
68
|
+
handlerName: string;
|
|
69
|
+
description?: string;
|
|
70
|
+
modelClassName?: string;
|
|
71
|
+
messageName?: string;
|
|
72
|
+
methodName?: string;
|
|
73
|
+
}
|
|
74
|
+
interface IRMessage {
|
|
75
|
+
roleName: string;
|
|
76
|
+
handlerName: string;
|
|
77
|
+
description?: string;
|
|
78
|
+
modelClassName?: string;
|
|
79
|
+
messageName?: string;
|
|
80
|
+
methodName?: string;
|
|
81
|
+
}
|
|
82
|
+
interface IRModel {
|
|
83
|
+
scopeName: string;
|
|
84
|
+
modelName: string;
|
|
85
|
+
type: string;
|
|
86
|
+
description?: string;
|
|
87
|
+
properties?: IRProperty[];
|
|
88
|
+
namespace?: string;
|
|
89
|
+
className?: string;
|
|
90
|
+
}
|
|
91
|
+
interface IRProperty {
|
|
92
|
+
type: string;
|
|
93
|
+
scopeName: string;
|
|
94
|
+
modelName: string;
|
|
95
|
+
description?: string;
|
|
96
|
+
required?: boolean;
|
|
97
|
+
items?: {
|
|
98
|
+
type: string;
|
|
99
|
+
scopeName: string;
|
|
100
|
+
modelName: string;
|
|
101
|
+
description?: string;
|
|
102
|
+
};
|
|
103
|
+
propertyName?: string;
|
|
104
|
+
typeName?: string;
|
|
105
|
+
}
|
|
106
|
+
interface PlanStep {
|
|
107
|
+
name: string;
|
|
108
|
+
command: 'copy' | 'render';
|
|
109
|
+
input?: string;
|
|
110
|
+
output: string;
|
|
111
|
+
template?: string;
|
|
112
|
+
getData?: () => unknown;
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
export type { PipelineContext as P };
|
|
@@ -0,0 +1,115 @@
|
|
|
1
|
+
import { Spec, Endpoint } from '@polytric/openws-spec/types';
|
|
2
|
+
|
|
3
|
+
interface PipelineContext {
|
|
4
|
+
argv: string[];
|
|
5
|
+
rawInput?: RawInput;
|
|
6
|
+
request?: BuildRequest;
|
|
7
|
+
spec?: Spec;
|
|
8
|
+
ir?: IR;
|
|
9
|
+
plan?: PlanStep[];
|
|
10
|
+
}
|
|
11
|
+
interface RawInput {
|
|
12
|
+
spec: string;
|
|
13
|
+
out: string;
|
|
14
|
+
project: string;
|
|
15
|
+
hostRole: string[];
|
|
16
|
+
language: 'csharp' | 'javascript' | 'typescript';
|
|
17
|
+
environment: 'unity' | 'node' | 'browser';
|
|
18
|
+
frameworks?: string[];
|
|
19
|
+
}
|
|
20
|
+
interface BuildRequest {
|
|
21
|
+
specPath: string;
|
|
22
|
+
outputPath: string;
|
|
23
|
+
project: string;
|
|
24
|
+
hostRoles: string[];
|
|
25
|
+
target: {
|
|
26
|
+
csharp?: {
|
|
27
|
+
environment: 'unity';
|
|
28
|
+
frameworks?: string[];
|
|
29
|
+
};
|
|
30
|
+
javascript?: {
|
|
31
|
+
environment: 'node' | 'browser';
|
|
32
|
+
frameworks?: string[];
|
|
33
|
+
};
|
|
34
|
+
typescript?: {
|
|
35
|
+
environment: 'node' | 'browser';
|
|
36
|
+
frameworks?: string[];
|
|
37
|
+
};
|
|
38
|
+
};
|
|
39
|
+
}
|
|
40
|
+
interface IR {
|
|
41
|
+
package: IRPackage;
|
|
42
|
+
networks: IRNetwork[];
|
|
43
|
+
assemblyName?: string;
|
|
44
|
+
}
|
|
45
|
+
interface IRPackage {
|
|
46
|
+
project: string;
|
|
47
|
+
service: string;
|
|
48
|
+
description?: string;
|
|
49
|
+
version?: string;
|
|
50
|
+
}
|
|
51
|
+
interface IRNetwork {
|
|
52
|
+
name: string;
|
|
53
|
+
description?: string;
|
|
54
|
+
version?: string;
|
|
55
|
+
roles: IRRole[];
|
|
56
|
+
handlers: IRHandler[];
|
|
57
|
+
messages: IRMessage[];
|
|
58
|
+
models: IRModel[];
|
|
59
|
+
}
|
|
60
|
+
interface IRRole {
|
|
61
|
+
name: string;
|
|
62
|
+
description?: string;
|
|
63
|
+
isHost: boolean;
|
|
64
|
+
endpoints: Endpoint[];
|
|
65
|
+
}
|
|
66
|
+
interface IRHandler {
|
|
67
|
+
roleName: string;
|
|
68
|
+
handlerName: string;
|
|
69
|
+
description?: string;
|
|
70
|
+
modelClassName?: string;
|
|
71
|
+
messageName?: string;
|
|
72
|
+
methodName?: string;
|
|
73
|
+
}
|
|
74
|
+
interface IRMessage {
|
|
75
|
+
roleName: string;
|
|
76
|
+
handlerName: string;
|
|
77
|
+
description?: string;
|
|
78
|
+
modelClassName?: string;
|
|
79
|
+
messageName?: string;
|
|
80
|
+
methodName?: string;
|
|
81
|
+
}
|
|
82
|
+
interface IRModel {
|
|
83
|
+
scopeName: string;
|
|
84
|
+
modelName: string;
|
|
85
|
+
type: string;
|
|
86
|
+
description?: string;
|
|
87
|
+
properties?: IRProperty[];
|
|
88
|
+
namespace?: string;
|
|
89
|
+
className?: string;
|
|
90
|
+
}
|
|
91
|
+
interface IRProperty {
|
|
92
|
+
type: string;
|
|
93
|
+
scopeName: string;
|
|
94
|
+
modelName: string;
|
|
95
|
+
description?: string;
|
|
96
|
+
required?: boolean;
|
|
97
|
+
items?: {
|
|
98
|
+
type: string;
|
|
99
|
+
scopeName: string;
|
|
100
|
+
modelName: string;
|
|
101
|
+
description?: string;
|
|
102
|
+
};
|
|
103
|
+
propertyName?: string;
|
|
104
|
+
typeName?: string;
|
|
105
|
+
}
|
|
106
|
+
interface PlanStep {
|
|
107
|
+
name: string;
|
|
108
|
+
command: 'copy' | 'render';
|
|
109
|
+
input?: string;
|
|
110
|
+
output: string;
|
|
111
|
+
template?: string;
|
|
112
|
+
getData?: () => unknown;
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
export type { PipelineContext as P };
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@polytric/openws-sdkgen",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.6",
|
|
4
4
|
"description": "OpenWS SDK generator CLI",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"bin": {
|
|
@@ -42,14 +42,21 @@
|
|
|
42
42
|
"devDependencies": {
|
|
43
43
|
"@types/ejs": "^3.1.5",
|
|
44
44
|
"@types/node": "^22.15.29",
|
|
45
|
+
"@types/ws": "^8.18.1",
|
|
45
46
|
"@types/yargs": "^17.0.33",
|
|
47
|
+
"fastify": "^5.6.2",
|
|
46
48
|
"tsup": "^8.5.1",
|
|
47
49
|
"tsx": "^4.21.0",
|
|
48
|
-
"typescript": "^5.9.3"
|
|
50
|
+
"typescript": "^5.9.3",
|
|
51
|
+
"ws": "^8.18.3",
|
|
52
|
+
"@polytric/openws": "0.0.4"
|
|
49
53
|
},
|
|
50
54
|
"scripts": {
|
|
51
55
|
"build": "tsup",
|
|
52
56
|
"typecheck": "tsc --noEmit",
|
|
53
|
-
"test:csharp:unity": "node dist/main.cjs --spec ./test/spec.json --out ./generated/dotnet/unity --project Example --hostRole client --language csharp --environment unity"
|
|
57
|
+
"test:csharp:unity": "node dist/main.cjs --spec ./test/spec.json --out ./generated/dotnet/unity --project Example --hostRole client --language csharp --environment unity",
|
|
58
|
+
"test:typescript:node": "node dist/main.cjs --spec ./test/spec.json --out ./generated/typescript/node --project Example --hostRole client --language typescript --environment node",
|
|
59
|
+
"test:typescript:server": "tsx ./test/typescript/server.ts",
|
|
60
|
+
"test:typescript:client": "tsx ./test/typescript/client.ts"
|
|
54
61
|
}
|
|
55
62
|
}
|