diff --git a/generators/tsclient/testdata/todo_client.ts b/generators/tsclient/testdata/todo_client.ts new file mode 100644 index 0000000..6aa65b8 --- /dev/null +++ b/generators/tsclient/testdata/todo_client.ts @@ -0,0 +1,96 @@ + +let fetch = typeof window !== 'undefined' ? window.fetch : null +if(!fetch) { + fetch = require('node-fetch') +} + + +/** +* Call method with params via a POST request. +*/ + +async function call(url: string, authToken: string, method: string, params?: any): Promise { + const res = await fetch(url + '/' + method, { + method: 'POST', + body: JSON.stringify(params), + headers: { + 'Content-Type': 'application/json', + 'Authorization': `Bearer ${authToken}` + } + }) + + // we have an error, try to parse a well-formed json + // error response, otherwise default to status code + if (res.status >= 300) { + let err + try { + const { type, message } = await res.json() + err = new Error(message) + err.type = type + } catch { + err = new Error(`${res.status} ${res.statusText}`) + } + throw err + } + + return res.text() +} + + +const reISO8601 = /(\d{4}-[01]\d-[0-3]\dT[0-2]\d:[0-5]\d:[0-5]\d\.\d+([+-][0-2]\d:[0-5]\d|Z))|(\d{4}-[01]\d-[0-3]\dT[0-2]\d:[0-5]\d:[0-5]\d([+-][0-2]\d:[0-5]\d|Z))|(\d{4}-[01]\d-[0-3]\dT[0-2]\d:[0-5]\d([+-][0-2]\d:[0-5]\d|Z))/ + +/** + * Client is the API client. + */ + +export class Client { + + private url: string + private authToken: string + + /** + * Initialize. + */ + + constructor(params: { url: string, authToken?: string }) { + this.url = params.url + this.authToken = params.authToken + } + + /** + * Decoder is used as the reviver parameter when decoding responses. + */ + + private decoder(key: any, value: any) { + return typeof value == 'string' && reISO8601.test(value) + ? new Date(value) + : value + } + + /** + * addItem: Add an item to the list. + */ + + async addItem(params: AddItemInput) { + await call(this.url, this.authToken, 'add_item', params) + } + + /** + * getItems: Return all items in the list. + */ + + async getItems(): Promise { + let res = await call(this.url, this.authToken, 'get_items') + let out: GetItemsOutput = JSON.parse(res, this.decoder) + return out + } + + /** + * removeItem: removes an item from the to-do list. + */ + + async removeItem(params: RemoveItemInput) { + await call(this.url, this.authToken, 'remove_item', params) + } + +} diff --git a/generators/tsclient/tsclient.go b/generators/tsclient/tsclient.go index 55f91b4..1725de3 100644 --- a/generators/tsclient/tsclient.go +++ b/generators/tsclient/tsclient.go @@ -54,6 +54,8 @@ func Generate(w io.Writer, s *schema.Schema, fetchLibrary string) error { out(w, require, fetchLibrary) out(w, "\n%s\n", call) out(w, "\n\n") + out(w, `const reISO8601 = /(\d{4}-[01]\d-[0-3]\dT[0-2]\d:[0-5]\d:[0-5]\d\.\d+([+-][0-2]\d:[0-5]\d|Z))|(\d{4}-[01]\d-[0-3]\dT[0-2]\d:[0-5]\d:[0-5]\d([+-][0-2]\d:[0-5]\d|Z))|(\d{4}-[01]\d-[0-3]\dT[0-2]\d:[0-5]\d([+-][0-2]\d:[0-5]\d|Z))/`) + out(w, "\n\n") out(w, "/**\n") out(w, " * Client is the API client.\n") out(w, " */\n") @@ -72,6 +74,16 @@ func Generate(w io.Writer, s *schema.Schema, fetchLibrary string) error { out(w, " this.authToken = params.authToken\n") out(w, " }\n") out(w, "\n") + out(w, " /**\n") + out(w, " * Decoder is used as the reviver parameter when decoding responses.\n") + out(w, " */\n") + out(w, "\n") + out(w, " private decoder(key: any, value: any) {\n") + out(w, " return typeof value == 'string' && reISO8601.test(value)\n") + out(w, " ? new Date(value)\n") + out(w, " : value\n") + out(w, " }\n") + out(w, "\n") // methods for _, m := range s.Methods { @@ -103,7 +115,7 @@ func Generate(w io.Writer, s *schema.Schema, fetchLibrary string) error { } else { out(w, "await call(this.url, this.authToken, '%s')\n", m.Name) } - out(w, " let out: %sOutput = JSON.parse(res)\n", format.GoName(m.Name)) + out(w, " let out: %sOutput = JSON.parse(res, this.decoder)\n", format.GoName(m.Name)) out(w, " return out\n") } else { // call diff --git a/generators/tsclient/tsclient_test.go b/generators/tsclient/tsclient_test.go index c8d24f1..d8b24dc 100644 --- a/generators/tsclient/tsclient_test.go +++ b/generators/tsclient/tsclient_test.go @@ -1 +1,25 @@ package tsclient_test + +import ( + "bytes" + "io/ioutil" + "testing" + + "github.com/apex/rpc/generators/tsclient" + "github.com/apex/rpc/schema" + "github.com/tj/assert" +) + +func TestGenerate(t *testing.T) { + exp, err := ioutil.ReadFile("testdata/todo_client.ts") + assert.NoError(t, err, "reading fixture") + + schema, err := schema.Load("../../examples/todo/schema.json") + assert.NoError(t, err, "loading schema") + + var act bytes.Buffer + err = tsclient.Generate(&act, schema, "node-fetch") + assert.NoError(t, err, "generating") + + assert.Equal(t, string(exp), act.String()) +} diff --git a/go.sum b/go.sum index 31f2359..cc795db 100644 --- a/go.sum +++ b/go.sum @@ -2,6 +2,7 @@ github.com/davecgh/go-spew v1.1.0 h1:ZDRjVQ15GmhC3fiQ8ni8+OwkZQO4DARzQgrnXU1Liz8 github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/google/gofuzz v1.0.0 h1:A8PeW59pxE9IoFRqBp37U+mSNaQoZ46F1f0f863XSXw= github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= github.com/iancoleman/strcase v0.0.0-20191112232945-16388991a334 h1:VHgatEHNcBFEB7inlalqfNqw65aNkM1lGX2yt3NmbS8= github.com/iancoleman/strcase v0.0.0-20191112232945-16388991a334/go.mod h1:SK73tn/9oHe+/Y0h39VT4UCxmurVJkR5NA7kMEAOgSE= @@ -13,6 +14,7 @@ github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742 h1:Esafd1046DLD github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= +github.com/stretchr/objx v0.1.0 h1:4G4v2dO3VZwixGIRoQ5Lfboy6nUhCyYzaqnIAPPhYs4= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= github.com/stretchr/testify v1.4.0 h1:2E4SXV/wtOkTonXsotYi4li6zVWxYlZuYNCXe9XRJyk=