v1.4.0: generic Stream[T] — typed stream messages, drop (T, *Stream, error)

- Stream[T]: Send(v T) type-safe; message type recovered from the
  instantiated Send signature (reflect has no type-args API)
- method signatures reduced to (error), (T, error), (*Stream[T], error);
  the (T, *Stream, error) first-message form is gone — send it via Send
- return T and stream message T now run checkType at bind time
  (Stream[any] remains the explicit untyped escape hatch)
- generated clients: TS onMessage: (data: T); Go <-chan T
- fix vacuous panic assertions (fmt.Sprint(nil) -> "<nil>") in
  hardening/route test catch helpers

Generated with [Devin](https://devin.ai)

Co-Authored-By: Devin <158243242+devin-ai-integration[bot]@users.noreply.github.com>
This commit is contained in:
2026-09-19 15:39:41 +08:00
co-authored by Devin
parent 81d36f827e
commit 84c11c6fde
15 changed files with 184 additions and 117 deletions
+7 -6
View File
@@ -27,13 +27,14 @@ func (s *BugSvc) Ping() error { return nil }
func (s *BugSvc) Save(dto BugDto) (string, error) { return "ok", nil }
func (s *BugSvc) Ticker() (string, *Stream, error) {
st := Stream{}
func (s *BugSvc) Ticker() (*Stream[string], error) {
st := &Stream[string]{}
go func() {
st.Send("first")
st.Send("tick")
st.Close()
}()
return "first", &st, nil
return st, nil
}
func bugInvoke(t *testing.T, method string, data map[string]any) (*Result[any], error) {
@@ -99,7 +100,7 @@ func TestBugGenErrorOnly(t *testing.T) {
}
}
// bug4+5: 响应键应为小写;(T, stream, error) 的 T 应作为流的第一条消息下发
// bug4+5: 响应键应为小写;流消息按 Send 顺序逐行下发
func TestBugJsonKeysAndStreamFirst(t *testing.T) {
f := New()
if err := f.BindService(&BugSvc{}); err != nil {
@@ -173,8 +174,8 @@ var leakDone chan struct{}
type LeakSvc struct{}
func (s *LeakSvc) Fail() (*Stream, error) {
st := Stream{}
func (s *LeakSvc) Fail() (*Stream[any], error) {
st := Stream[any]{}
leakDone = make(chan struct{})
go func() {
st.Send("never")