@ishibashi0112/webview2-bridge-gen 0.2.0

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.
Files changed (52) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +133 -0
  3. package/dist/cli.d.ts +3 -0
  4. package/dist/cli.d.ts.map +1 -0
  5. package/dist/cli.js +60 -0
  6. package/dist/cli.js.map +1 -0
  7. package/dist/define.d.ts +19 -0
  8. package/dist/define.d.ts.map +1 -0
  9. package/dist/define.js +8 -0
  10. package/dist/define.js.map +1 -0
  11. package/dist/emit-ts.d.ts +15 -0
  12. package/dist/emit-ts.d.ts.map +1 -0
  13. package/dist/emit-ts.js +113 -0
  14. package/dist/emit-ts.js.map +1 -0
  15. package/dist/emit-vb.d.ts +22 -0
  16. package/dist/emit-vb.d.ts.map +1 -0
  17. package/dist/emit-vb.js +467 -0
  18. package/dist/emit-vb.js.map +1 -0
  19. package/dist/emitted.d.ts +6 -0
  20. package/dist/emitted.d.ts.map +1 -0
  21. package/dist/emitted.js +2 -0
  22. package/dist/emitted.js.map +1 -0
  23. package/dist/generate.d.ts +47 -0
  24. package/dist/generate.d.ts.map +1 -0
  25. package/dist/generate.js +103 -0
  26. package/dist/generate.js.map +1 -0
  27. package/dist/index.d.ts +7 -0
  28. package/dist/index.d.ts.map +1 -0
  29. package/dist/index.js +8 -0
  30. package/dist/index.js.map +1 -0
  31. package/dist/naming.d.ts +8 -0
  32. package/dist/naming.d.ts.map +1 -0
  33. package/dist/naming.js +42 -0
  34. package/dist/naming.js.map +1 -0
  35. package/dist/schema.d.ts +45 -0
  36. package/dist/schema.d.ts.map +1 -0
  37. package/dist/schema.js +21 -0
  38. package/dist/schema.js.map +1 -0
  39. package/dist/to-schema.d.ts +10 -0
  40. package/dist/to-schema.d.ts.map +1 -0
  41. package/dist/to-schema.js +75 -0
  42. package/dist/to-schema.js.map +1 -0
  43. package/dist/vb-runtime.d.ts +12 -0
  44. package/dist/vb-runtime.d.ts.map +1 -0
  45. package/dist/vb-runtime.js +50 -0
  46. package/dist/vb-runtime.js.map +1 -0
  47. package/package.json +73 -0
  48. package/vb-runtime/README.md +10 -0
  49. package/vb-runtime/runtime/Dispatcher.vb +145 -0
  50. package/vb-runtime/runtime/IBridgeEmitter.vb +16 -0
  51. package/vb-runtime/runtime/JsonRpc.vb +124 -0
  52. package/vb-runtime/winforms/WebViewBridge.vb +100 -0
@@ -0,0 +1,145 @@
1
+ Option Strict On
2
+
3
+ Imports System
4
+ Imports System.Collections.Generic
5
+ Imports System.Threading.Tasks
6
+ Imports Newtonsoft.Json
7
+ Imports Newtonsoft.Json.Linq
8
+
9
+ Namespace Global.WebView2Bridge.Runtime
10
+
11
+ ''' <summary>
12
+ ''' JSON-RPC 要求文字列を受け取り、登録されたハンドラへ振り分けて応答文字列を返す。
13
+ ''' 手書き側(このファイル)は契約に依存しない汎用部分。
14
+ ''' 生成側(Dispatcher.Generated.vb)が Register(api As IXxxApi) を提供し、RegisterHandler を呼ぶ。
15
+ ''' WebView2 には依存しない。
16
+ ''' </summary>
17
+ Partial Public Class Dispatcher
18
+
19
+ ''' <summary>型消去したハンドラ。params(JToken) → 結果(Object)</summary>
20
+ Private Interface IHandler
21
+ Function InvokeAsync(params As JToken) As Task(Of Object)
22
+ End Interface
23
+
24
+ Private NotInheritable Class TypedHandler(Of TReq, TRes)
25
+ Implements IHandler
26
+
27
+ Private ReadOnly _handler As Func(Of TReq, Task(Of TRes))
28
+ Private ReadOnly _serializer As JsonSerializer
29
+
30
+ Public Sub New(handler As Func(Of TReq, Task(Of TRes)), serializer As JsonSerializer)
31
+ _handler = handler
32
+ _serializer = serializer
33
+ End Sub
34
+
35
+ Public Async Function InvokeAsync(params As JToken) As Task(Of Object) Implements IHandler.InvokeAsync
36
+ Dim req As TReq
37
+ Try
38
+ ' params 省略時は {} として扱う(全プロパティ optional な入力を許す)
39
+ Dim source As JToken = If(params Is Nothing OrElse params.Type = JTokenType.Null, New JObject(), params)
40
+ If source.Type <> JTokenType.Object Then
41
+ Throw New JsonRpcException(JsonRpcErrorCodes.InvalidParams, "Invalid params: expected an object")
42
+ End If
43
+ req = source.ToObject(Of TReq)(_serializer)
44
+ Catch ex As JsonException
45
+ Throw New JsonRpcException(JsonRpcErrorCodes.InvalidParams, "Invalid params: " & ex.Message, ex.GetType().FullName)
46
+ End Try
47
+ Dim result As TRes = Await _handler(req).ConfigureAwait(False)
48
+ Return result
49
+ End Function
50
+ End Class
51
+
52
+ Private ReadOnly _handlers As New Dictionary(Of String, IHandler)(StringComparer.Ordinal)
53
+ Private ReadOnly _serializer As JsonSerializer
54
+
55
+ Public Sub New()
56
+ Me.New(JsonRpc.CreateSerializerSettings())
57
+ End Sub
58
+
59
+ Public Sub New(settings As JsonSerializerSettings)
60
+ If settings Is Nothing Then Throw New ArgumentNullException(NameOf(settings))
61
+ _serializer = JsonSerializer.Create(settings)
62
+ End Sub
63
+
64
+ ''' <summary>JSON の読み書きに使うシリアライザ。Host 側の通知にも同じものを使う</summary>
65
+ Public ReadOnly Property Serializer As JsonSerializer
66
+ Get
67
+ Return _serializer
68
+ End Get
69
+ End Property
70
+
71
+ ''' <summary>登録済みメソッド名</summary>
72
+ Public ReadOnly Property RegisteredMethods As IEnumerable(Of String)
73
+ Get
74
+ Return _handlers.Keys
75
+ End Get
76
+ End Property
77
+
78
+ ''' <summary>
79
+ ''' 型付きハンドラを登録する。通常は生成側の Register(api) から呼ばれる。
80
+ ''' 同名メソッドは後勝ち。
81
+ ''' </summary>
82
+ Public Sub RegisterHandler(Of TReq, TRes)(method As String, handler As Func(Of TReq, Task(Of TRes)))
83
+ If String.IsNullOrEmpty(method) Then Throw New ArgumentException("method is required", NameOf(method))
84
+ If handler Is Nothing Then Throw New ArgumentNullException(NameOf(handler))
85
+ _handlers(method) = New TypedHandler(Of TReq, TRes)(handler, _serializer)
86
+ End Sub
87
+
88
+ ''' <summary>
89
+ ''' 要求 JSON を処理し、応答 JSON を返す。例外は投げず、必ず JSON-RPC エラー応答にする。
90
+ ''' 要求に id が無い(通知)場合は処理だけ行い Nothing を返す。
91
+ ''' </summary>
92
+ Public Async Function HandleAsync(requestJson As String) As Task(Of String)
93
+ Dim id As JToken = Nothing
94
+ Dim hasId As Boolean = False
95
+ Try
96
+ Dim token As JToken
97
+ Try
98
+ token = JsonRpc.ParseToken(If(requestJson, String.Empty))
99
+ Catch ex As JsonException
100
+ Return JsonRpc.BuildError(Nothing, JsonRpcErrorCodes.ParseError, "Parse error: " & ex.Message, Nothing, _serializer)
101
+ End Try
102
+
103
+ Dim request = TryCast(token, JObject)
104
+ If request Is Nothing Then
105
+ Return JsonRpc.BuildError(Nothing, JsonRpcErrorCodes.InvalidRequest, "Invalid Request: expected an object", Nothing, _serializer)
106
+ End If
107
+
108
+ Dim idToken As JToken = Nothing
109
+ If request.TryGetValue("id", idToken) AndAlso idToken.Type <> JTokenType.Null Then
110
+ id = idToken
111
+ hasId = True
112
+ End If
113
+
114
+ Dim methodToken As JToken = Nothing
115
+ If Not request.TryGetValue("method", methodToken) OrElse methodToken.Type <> JTokenType.String Then
116
+ Return If(hasId, JsonRpc.BuildError(id, JsonRpcErrorCodes.InvalidRequest, "Invalid Request: method is required", Nothing, _serializer), Nothing)
117
+ End If
118
+ Dim method As String = methodToken.Value(Of String)()
119
+
120
+ Dim handler As IHandler = Nothing
121
+ If Not _handlers.TryGetValue(method, handler) Then
122
+ Return If(hasId, JsonRpc.BuildError(id, JsonRpcErrorCodes.MethodNotFound, "Method not found: " & method, Nothing, _serializer), Nothing)
123
+ End If
124
+
125
+ Dim params As JToken = Nothing
126
+ request.TryGetValue("params", params)
127
+
128
+ Dim result As Object = Await handler.InvokeAsync(params).ConfigureAwait(False)
129
+ Return If(hasId, JsonRpc.BuildResult(id, result, _serializer), Nothing)
130
+
131
+ Catch ex As JsonRpcException
132
+ Return If(hasId, JsonRpc.BuildError(id, ex.Code, ex.Message, ex.ErrorData, _serializer), Nothing)
133
+ Catch ex As Exception
134
+ ' 実装側の未処理例外: -32000、message に例外メッセージ、data に例外型名(HANDOFF.md §5)
135
+ Return If(hasId, JsonRpc.BuildError(id, JsonRpcErrorCodes.ServerError, ex.Message, ex.GetType().FullName, _serializer), Nothing)
136
+ End Try
137
+ End Function
138
+
139
+ ''' <summary>Host → Web の通知 JSON を作る(送信は Host 側)</summary>
140
+ Public Function BuildNotification(method As String, params As Object) As String
141
+ Return JsonRpc.BuildNotification(method, params, _serializer)
142
+ End Function
143
+ End Class
144
+
145
+ End Namespace
@@ -0,0 +1,16 @@
1
+ Option Strict On
2
+
3
+ Namespace Global.WebView2Bridge.Runtime
4
+
5
+ ''' <summary>
6
+ ''' Host → Web の通知(JSON-RPC notification)を送る口。
7
+ ''' Contract は WebView2 に依存しないので、実体は Host 側(WebViewBridge)が実装する。
8
+ ''' 生成される BridgeEvents はこれを通して "event.&lt;name&gt;" を発行する。
9
+ ''' </summary>
10
+ Public Interface IBridgeEmitter
11
+ ''' <param name="method">"event.progress" のような通知名</param>
12
+ ''' <param name="params">ペイロード(生成 DTO)。Nothing 可</param>
13
+ Sub Emit(method As String, params As Object)
14
+ End Interface
15
+
16
+ End Namespace
@@ -0,0 +1,124 @@
1
+ Option Strict On
2
+
3
+ Imports System
4
+ Imports System.IO
5
+ Imports Newtonsoft.Json
6
+ Imports Newtonsoft.Json.Linq
7
+
8
+ Namespace Global.WebView2Bridge.Runtime
9
+
10
+ ''' <summary>JSON-RPC 2.0 のエラーコード(HANDOFF.md §5)</summary>
11
+ Public NotInheritable Class JsonRpcErrorCodes
12
+ Private Sub New()
13
+ End Sub
14
+
15
+ Public Const ParseError As Integer = -32700
16
+ Public Const InvalidRequest As Integer = -32600
17
+ Public Const MethodNotFound As Integer = -32601
18
+ Public Const InvalidParams As Integer = -32602
19
+ Public Const InternalError As Integer = -32603
20
+ ''' <summary>アプリ定義エラーの既定値。実装側の未処理例外はこのコードになる</summary>
21
+ Public Const ServerError As Integer = -32000
22
+ End Class
23
+
24
+ ''' <summary>
25
+ ''' 実装(IXxxApi)から意図的に JSON-RPC エラーを返したいときに投げる。
26
+ ''' Code は -32000 以下のアプリ定義コードを使う。
27
+ ''' </summary>
28
+ Public Class JsonRpcException
29
+ Inherits Exception
30
+
31
+ Public ReadOnly Property Code As Integer
32
+ Public ReadOnly Property ErrorData As Object
33
+
34
+ Public Sub New(code As Integer, message As String)
35
+ Me.New(code, message, Nothing)
36
+ End Sub
37
+
38
+ Public Sub New(code As Integer, message As String, data As Object)
39
+ MyBase.New(message)
40
+ Me.Code = code
41
+ Me.ErrorData = data
42
+ End Sub
43
+ End Class
44
+
45
+ ''' <summary>JSON-RPC 封筒の組み立て・解釈。Dispatcher と Host(WebViewBridge)が共用する</summary>
46
+ Public NotInheritable Class JsonRpc
47
+ Private Sub New()
48
+ End Sub
49
+
50
+ Public Const Version As String = "2.0"
51
+
52
+ ''' <summary>
53
+ ''' ブリッジ全体で使う Newtonsoft の設定。
54
+ ''' DateParseHandling.None: "2024-01-01T00:00:00Z" のような文字列を Date に変換せず、文字列のまま往復させる。
55
+ ''' </summary>
56
+ Public Shared Function CreateSerializerSettings() As JsonSerializerSettings
57
+ Return New JsonSerializerSettings() With {
58
+ .DateParseHandling = DateParseHandling.None,
59
+ .NullValueHandling = NullValueHandling.Include,
60
+ .Formatting = Formatting.None
61
+ }
62
+ End Function
63
+
64
+ ''' <summary>JSON 文字列 → JToken。日付文字列を自動変換しない</summary>
65
+ Public Shared Function ParseToken(json As String) As JToken
66
+ Using sr As New StringReader(json)
67
+ Using reader As New JsonTextReader(sr)
68
+ reader.DateParseHandling = DateParseHandling.None
69
+ Dim token = JToken.ReadFrom(reader)
70
+ ' 末尾にゴミが無いことを確認する("{}{}" のような入力を弾く)
71
+ If reader.Read() Then
72
+ Throw New JsonReaderException("Additional text found after JSON root")
73
+ End If
74
+ Return token
75
+ End Using
76
+ End Using
77
+ End Function
78
+
79
+ ''' <summary>成功応答 {"jsonrpc":"2.0","id":...,"result":...}</summary>
80
+ Public Shared Function BuildResult(id As JToken, result As Object, serializer As JsonSerializer) As String
81
+ Dim resultToken As JToken = If(result Is Nothing, CType(JValue.CreateNull(), JToken), JToken.FromObject(result, serializer))
82
+ Dim o As New JObject() From {
83
+ {"jsonrpc", Version},
84
+ {"id", NormalizeId(id)},
85
+ {"result", resultToken}
86
+ }
87
+ Return o.ToString(Formatting.None)
88
+ End Function
89
+
90
+ ''' <summary>エラー応答 {"jsonrpc":"2.0","id":...,"error":{"code","message","data"}}</summary>
91
+ Public Shared Function BuildError(id As JToken, code As Integer, message As String, data As Object, serializer As JsonSerializer) As String
92
+ Dim dataToken As JToken = If(data Is Nothing, CType(JValue.CreateNull(), JToken), JToken.FromObject(data, serializer))
93
+ Dim err As New JObject() From {
94
+ {"code", code},
95
+ {"message", If(message, String.Empty)},
96
+ {"data", dataToken}
97
+ }
98
+ Dim o As New JObject() From {
99
+ {"jsonrpc", Version},
100
+ {"id", NormalizeId(id)},
101
+ {"error", err}
102
+ }
103
+ Return o.ToString(Formatting.None)
104
+ End Function
105
+
106
+ ''' <summary>通知 {"jsonrpc":"2.0","method":...,"params":...}(id なし)</summary>
107
+ Public Shared Function BuildNotification(method As String, params As Object, serializer As JsonSerializer) As String
108
+ If String.IsNullOrEmpty(method) Then Throw New ArgumentException("method is required", NameOf(method))
109
+ Dim paramsToken As JToken = If(params Is Nothing, CType(JValue.CreateNull(), JToken), JToken.FromObject(params, serializer))
110
+ Dim o As New JObject() From {
111
+ {"jsonrpc", Version},
112
+ {"method", method},
113
+ {"params", paramsToken}
114
+ }
115
+ Return o.ToString(Formatting.None)
116
+ End Function
117
+
118
+ Private Shared Function NormalizeId(id As JToken) As JToken
119
+ If id Is Nothing Then Return JValue.CreateNull()
120
+ Return id.DeepClone()
121
+ End Function
122
+ End Class
123
+
124
+ End Namespace
@@ -0,0 +1,100 @@
1
+ Option Strict On
2
+
3
+ Imports System
4
+ Imports System.Diagnostics
5
+ Imports System.Windows.Forms
6
+ Imports Microsoft.Web.WebView2.Core
7
+ Imports Microsoft.Web.WebView2.WinForms
8
+ Imports WebView2Bridge.Runtime
9
+
10
+ Namespace Global.WebView2Bridge.WinForms
11
+
12
+ ''' <summary>
13
+ ''' WebView2 コントロールと Dispatcher をつなぐ。
14
+ ''' Web → Host: WebMessageReceived → Dispatcher.HandleAsync → PostWebMessageAsJson
15
+ ''' Host → Web: Emit(method, payload) → 通知 JSON → PostWebMessageAsJson(UI スレッドへマーシャリング)
16
+ ''' AddHostObjectToScript は使わない(HANDOFF.md §5)。
17
+ ''' </summary>
18
+ Public NotInheritable Class WebViewBridge
19
+ Implements IBridgeEmitter
20
+ Implements IDisposable
21
+
22
+ Private ReadOnly _webView As WebView2
23
+ Private ReadOnly _dispatcher As Dispatcher
24
+ Private _core As CoreWebView2
25
+ Private _attached As Boolean
26
+
27
+ Public Sub New(webView As WebView2, dispatcher As Dispatcher)
28
+ If webView Is Nothing Then Throw New ArgumentNullException(NameOf(webView))
29
+ If dispatcher Is Nothing Then Throw New ArgumentNullException(NameOf(dispatcher))
30
+ _webView = webView
31
+ _dispatcher = dispatcher
32
+ End Sub
33
+
34
+ Public ReadOnly Property Dispatcher As Dispatcher
35
+ Get
36
+ Return _dispatcher
37
+ End Get
38
+ End Property
39
+
40
+ ''' <summary>EnsureCoreWebView2Async の後に呼ぶ。WebMessageReceived を購読する</summary>
41
+ Public Sub Attach()
42
+ If _attached Then Return
43
+ If _webView.CoreWebView2 Is Nothing Then
44
+ Throw New InvalidOperationException("Call EnsureCoreWebView2Async before Attach")
45
+ End If
46
+ _core = _webView.CoreWebView2
47
+ AddHandler _core.WebMessageReceived, AddressOf OnWebMessageReceived
48
+ _attached = True
49
+ End Sub
50
+
51
+ Private Async Sub OnWebMessageReceived(sender As Object, e As CoreWebView2WebMessageReceivedEventArgs)
52
+ ' Web 側は postMessage(obj) で送るので WebMessageAsJson で受ける(TryGetWebMessageAsString は使わない)
53
+ Dim requestJson As String = e.WebMessageAsJson
54
+ Dim responseJson As String
55
+ Try
56
+ ' HandleAsync は例外を投げず JSON-RPC エラーに変換する。ここは UI スレッドに戻ってくる
57
+ responseJson = Await _dispatcher.HandleAsync(requestJson)
58
+ Catch ex As Exception
59
+ Debug.WriteLine($"[WebViewBridge] unexpected: {ex}")
60
+ Return
61
+ End Try
62
+ If responseJson Is Nothing Then Return ' 通知(id なし)には応答しない
63
+ Post(responseJson)
64
+ End Sub
65
+
66
+ ''' <summary>Host → Web の通知。どのスレッドから呼んでもよい</summary>
67
+ Public Sub Emit(method As String, params As Object) Implements IBridgeEmitter.Emit
68
+ Dim json As String = _dispatcher.BuildNotification(method, params)
69
+ Post(json)
70
+ End Sub
71
+
72
+ Private Sub Post(json As String)
73
+ If _core Is Nothing OrElse _webView.IsDisposed Then Return
74
+ If _webView.InvokeRequired Then
75
+ _webView.BeginInvoke(New Action(Sub() PostOnUiThread(json)))
76
+ Else
77
+ PostOnUiThread(json)
78
+ End If
79
+ End Sub
80
+
81
+ Private Sub PostOnUiThread(json As String)
82
+ If _core Is Nothing OrElse _webView.IsDisposed Then Return
83
+ Try
84
+ _core.PostWebMessageAsJson(json)
85
+ Catch ex As Exception
86
+ ' ナビゲーション中・破棄中など。ブリッジ自体は落とさない
87
+ Debug.WriteLine($"[WebViewBridge] PostWebMessageAsJson failed: {ex.Message}")
88
+ End Try
89
+ End Sub
90
+
91
+ Public Sub Dispose() Implements IDisposable.Dispose
92
+ If _attached AndAlso _core IsNot Nothing Then
93
+ RemoveHandler _core.WebMessageReceived, AddressOf OnWebMessageReceived
94
+ End If
95
+ _attached = False
96
+ _core = Nothing
97
+ End Sub
98
+ End Class
99
+
100
+ End Namespace