From a997814623e31336af2455ccc71aec510d8eae48 Mon Sep 17 00:00:00 2001 From: Alexander Kolberg Date: Fri, 11 Oct 2024 10:27:01 +0200 Subject: [PATCH 1/3] SSE: Add close and abort methods --- client.go.tmpl | 22 ++++++++++++++++++---- clientHelpers.go.tmpl | 6 ++++++ types.go.tmpl | 2 +- 3 files changed, 25 insertions(+), 5 deletions(-) diff --git a/client.go.tmpl b/client.go.tmpl index 7c59779..a5dcb5a 100644 --- a/client.go.tmpl +++ b/client.go.tmpl @@ -15,7 +15,7 @@ export class {{.Name}} implements {{.Name}} { protected path = '/rpc/{{.Name}}/' constructor(hostname: string, fetch: Fetch) { - this.hostname = hostname + this.hostname = hostname.replace(/\/*$/, '') this.fetch = (input: RequestInfo, init?: RequestInit) => fetch(input, init) } @@ -23,16 +23,30 @@ export class {{.Name}} implements {{.Name}} { return this.hostname + this.path + name } {{range $_, $method := .Methods}} - {{firstLetterToLower .Name}} = ({{template "methodInputs" dict "Method" . "TypeMap" $typeMap}}): Promise<{{if $method.StreamOutput}}void{{else}}{{$method.Name}}Return{{end}}> => { + {{firstLetterToLower .Name}} = ({{template "methodInputs" dict "Method" . "TypeMap" $typeMap}}): {{if $method.StreamOutput}}WebrpcStreamController{{else}}Promise<{{$method.Name}}Return>{{end}} => { {{- if $method.StreamOutput }} + const abortController = new AbortController(); + const abortSignal = abortController.signal + + if (options.signal) { + abortSignal.addEventListener("abort", () => abortController.abort(options.signal?.reason), { + signal: options.signal, + }); + } + const _fetch = () => this.fetch(this.url('{{.Name}}'), - {{- if .Inputs | len }}createHTTPRequest(args, options.headers, options.signal){{- else}}createHTTPRequest({}, options.headers, options.signal){{end }} + {{- if .Inputs | len }}createHTTPRequest(args, options.headers, abortSignal){{- else}}createHTTPRequest({}, options.headers, options.signal){{end }} ).then(async (res) => { await sseResponse(res, options, _fetch); }, (error) => { options.onError(error, _fetch); }); - return _fetch(); + + const resp = _fetch(); + return { + abort: abortController.abort.bind(abortController), + closed: resp + }; } {{- else }} return this.fetch( diff --git a/clientHelpers.go.tmpl b/clientHelpers.go.tmpl index 8b901d8..70ba9bc 100644 --- a/clientHelpers.go.tmpl +++ b/clientHelpers.go.tmpl @@ -122,9 +122,15 @@ export interface WebrpcStreamOptions extends WebrpcOptions { onOpen?: () => void; onClose?: () => void; } + export interface WebrpcOptions { headers?: HeadersInit; signal?: AbortSignal; } + +export interface WebrpcStreamController { + abort: (reason?: any) => void; + closed: Promise; +} {{end}} {{end}} diff --git a/types.go.tmpl b/types.go.tmpl index 1493a87..7d209b4 100644 --- a/types.go.tmpl +++ b/types.go.tmpl @@ -44,7 +44,7 @@ export interface {{$type.Name}} { {{- range $_, $service := $services}} export interface {{$service.Name}} { {{- range $_, $method := $service.Methods}} - {{firstLetterToLower $method.Name}}({{template "methodInputs" dict "Method" $method "TypeMap" $typeMap}}): Promise<{{if $method.StreamOutput}}void{{else}}{{$method.Name}}Return{{end}}> + {{firstLetterToLower $method.Name}}({{template "methodInputs" dict "Method" $method "TypeMap" $typeMap}}): {{if $method.StreamOutput}}WebrpcStreamController{{else}}Promise<{{$method.Name}}Return>{{end}} {{- end}} } From b062983bc0ca3e6eb132f7998272c5aea883e915 Mon Sep 17 00:00:00 2001 From: Alexander Kolberg Date: Fri, 11 Oct 2024 10:28:27 +0200 Subject: [PATCH 2/3] Regenerate sse client --- _examples/sse/webapp/client.gen.ts | 52 ++++++++++++++++++++++++------ 1 file changed, 43 insertions(+), 9 deletions(-) diff --git a/_examples/sse/webapp/client.gen.ts b/_examples/sse/webapp/client.gen.ts index ee8dd02..bec7512 100644 --- a/_examples/sse/webapp/client.gen.ts +++ b/_examples/sse/webapp/client.gen.ts @@ -3,7 +3,7 @@ // -- // Code generated by webrpc-gen@v0.19.3 with ../.. generator. DO NOT EDIT. // -// webrpc-gen -schema=service.ridl -target=../.. -client -out=rpc.gen.ts +// webrpc-gen -schema=service.ridl -target=../.. -client -out=./webapp/client.gen.ts // WebRPC description and code-gen version export const WebRPCVersion = "v1" @@ -28,8 +28,8 @@ export interface Message { export interface Chat { sendMessage(args: SendMessageArgs, headers?: object, signal?: AbortSignal): Promise - subscribeMessages(args: SubscribeMessagesArgs, options: WebrpcStreamOptions): Promise - subscribeUsers(options: WebrpcStreamOptions): Promise + subscribeMessages(args: SubscribeMessagesArgs, options: WebrpcStreamOptions): WebrpcStreamController + subscribeUsers(options: WebrpcStreamOptions): WebrpcStreamController } export interface SendMessageArgs { @@ -64,7 +64,7 @@ export class Chat implements Chat { protected path = '/rpc/Chat/' constructor(hostname: string, fetch: Fetch) { - this.hostname = hostname + this.hostname = hostname.replace(/\/*$/, '') this.fetch = (input: RequestInfo, init?: RequestInit) => fetch(input, init) } @@ -84,23 +84,51 @@ export class Chat implements Chat { }) } - subscribeMessages = (args: SubscribeMessagesArgs, options: WebrpcStreamOptions): Promise => { - const _fetch = () => this.fetch(this.url('SubscribeMessages'),createHTTPRequest(args, options.headers, options.signal) + subscribeMessages = (args: SubscribeMessagesArgs, options: WebrpcStreamOptions): WebrpcStreamController => { + const abortController = new AbortController(); + const abortSignal = abortController.signal + + if (options.signal) { + abortSignal.addEventListener("abort", () => abortController.abort(options.signal?.reason), { + signal: options.signal, + }); + } + + const _fetch = () => this.fetch(this.url('SubscribeMessages'),createHTTPRequest(args, options.headers, abortSignal) ).then(async (res) => { await sseResponse(res, options, _fetch); }, (error) => { options.onError(error, _fetch); }); - return _fetch(); + + const resp = _fetch(); + return { + abort: abortController.abort.bind(abortController), + closed: resp + }; } - subscribeUsers = (options: WebrpcStreamOptions): Promise => { + subscribeUsers = (options: WebrpcStreamOptions): WebrpcStreamController => { + const abortController = new AbortController(); + const abortSignal = abortController.signal + + if (options.signal) { + abortSignal.addEventListener("abort", () => abortController.abort(options.signal?.reason), { + signal: options.signal, + }); + } + const _fetch = () => this.fetch(this.url('SubscribeUsers'),createHTTPRequest({}, options.headers, options.signal) ).then(async (res) => { await sseResponse(res, options, _fetch); }, (error) => { options.onError(error, _fetch); }); - return _fetch(); + + const resp = _fetch(); + return { + abort: abortController.abort.bind(abortController), + closed: resp + }; } } @@ -494,8 +522,14 @@ export interface WebrpcStreamOptions extends WebrpcOptions { onOpen?: () => void; onClose?: () => void; } + export interface WebrpcOptions { headers?: HeadersInit; signal?: AbortSignal; } +export interface WebrpcStreamController { + abort: (reason?: any) => void; + closed: Promise; +} + From 7190c044bb32688ce3465771e580a230187c98b9 Mon Sep 17 00:00:00 2001 From: Alexander Kolberg Date: Mon, 4 Nov 2024 21:08:00 +0100 Subject: [PATCH 3/3] Regenerate examples --- _examples/node-ts/server/server.gen.ts | 4 ++-- _examples/node-ts/webapp/client.gen.ts | 4 ++-- _examples/sse/webapp/client.gen.ts | 6 +++--- 3 files changed, 7 insertions(+), 7 deletions(-) diff --git a/_examples/node-ts/server/server.gen.ts b/_examples/node-ts/server/server.gen.ts index ae49dd8..c5019bc 100644 --- a/_examples/node-ts/server/server.gen.ts +++ b/_examples/node-ts/server/server.gen.ts @@ -1,13 +1,13 @@ /* eslint-disable */ // node-ts v1.0.0 6713366104e62b8479d628a193e2a7ca03f37edc // -- -// Code generated by webrpc-gen@v0.21.0-1-g96d144e with ../../../gen-typescript generator. DO NOT EDIT. +// Code generated by webrpc-gen@v0.21.1 with ../../../gen-typescript generator. DO NOT EDIT. // // webrpc-gen -schema=service.ridl -target=../../../gen-typescript -server -out=./server/server.gen.ts export const WebrpcHeader = "Webrpc" -export const WebrpcHeaderValue = "webrpc@v0.21.0-1-g96d144e;gen-typescript@unknown;node-ts@v1.0.0" +export const WebrpcHeaderValue = "webrpc@v0.21.1;gen-typescript@unknown;node-ts@v1.0.0" // WebRPC description and code-gen version export const WebRPCVersion = "v1" diff --git a/_examples/node-ts/webapp/client.gen.ts b/_examples/node-ts/webapp/client.gen.ts index 8f5c9b9..e1dad0d 100644 --- a/_examples/node-ts/webapp/client.gen.ts +++ b/_examples/node-ts/webapp/client.gen.ts @@ -1,13 +1,13 @@ /* eslint-disable */ // node-ts v1.0.0 6713366104e62b8479d628a193e2a7ca03f37edc // -- -// Code generated by webrpc-gen@v0.21.0-1-g96d144e with ../../../gen-typescript generator. DO NOT EDIT. +// Code generated by webrpc-gen@v0.21.1 with ../../../gen-typescript generator. DO NOT EDIT. // // webrpc-gen -schema=service.ridl -target=../../../gen-typescript -client -out=./webapp/client.gen.ts export const WebrpcHeader = "Webrpc" -export const WebrpcHeaderValue = "webrpc@v0.21.0-1-g96d144e;gen-typescript@unknown;node-ts@v1.0.0" +export const WebrpcHeaderValue = "webrpc@v0.21.1;gen-typescript@unknown;node-ts@v1.0.0" // WebRPC description and code-gen version export const WebRPCVersion = "v1" diff --git a/_examples/sse/webapp/client.gen.ts b/_examples/sse/webapp/client.gen.ts index 3e26316..405edcc 100644 --- a/_examples/sse/webapp/client.gen.ts +++ b/_examples/sse/webapp/client.gen.ts @@ -1,13 +1,13 @@ /* eslint-disable */ // webrpc-sse-chat v1.0.0 a799dc63b082644f5d003c8881424546aee23a2c // -- -// Code generated by webrpc-gen@v0.21.0-1-g96d144e with ../../ generator. DO NOT EDIT. +// Code generated by webrpc-gen@v0.21.1 with ../../ generator. DO NOT EDIT. // -// webrpc-gen -schema=service.ridl -target=../.. -client -out=./webapp/client.gen.ts +// webrpc-gen -schema=service.ridl -target=../../ -client -out=./webapp/client.gen.ts export const WebrpcHeader = "Webrpc" -export const WebrpcHeaderValue = "webrpc@v0.21.0-1-g96d144e;@unknown;webrpc-sse-chat@v1.0.0" +export const WebrpcHeaderValue = "webrpc@v0.21.1;@unknown;webrpc-sse-chat@v1.0.0" // WebRPC description and code-gen version export const WebRPCVersion = "v1"