more updates
This commit is contained in:
@@ -58,6 +58,15 @@ Two types of functions:
|
||||
- Use JSON tags for TypeScript type definitions
|
||||
- Async functions automatically generate `Promise<R>` return types
|
||||
|
||||
### Calling Convention
|
||||
|
||||
**Important**: Functions have different calling conventions on Go vs JavaScript sides:
|
||||
|
||||
- **Go side**: Function receives a **single argument struct** with all parameters
|
||||
- **JavaScript side**: Function is called with **individual arguments** matching the struct fields (in field order)
|
||||
|
||||
Fields are ordered by their position in the struct, with the generated TypeScript signature using those field names as argument names.
|
||||
|
||||
### Example
|
||||
|
||||
```go
|
||||
|
||||
30
README.md
30
README.md
@@ -102,11 +102,37 @@ That's it! The framework automatically:
|
||||
- Generates TypeScript definitions
|
||||
- Manages the qjs integration
|
||||
|
||||
### Calling Convention
|
||||
|
||||
**Important**: There's an important difference between how functions are defined in Go versus how they're called in JavaScript:
|
||||
|
||||
- **Go side**: The function receives a **single argument struct** containing all parameters
|
||||
- **JavaScript side**: The function is called with the **struct fields as individual arguments** (in the order they appear in the struct)
|
||||
|
||||
```go
|
||||
// Go: Single struct argument
|
||||
type AddArgs struct {
|
||||
A int `json:"a"`
|
||||
B int `json:"b"`
|
||||
}
|
||||
|
||||
func Add(_ context.Context, args AddArgs) (int, error) {
|
||||
return args.A + args.B, nil
|
||||
}
|
||||
```
|
||||
|
||||
```typescript
|
||||
// JavaScript: Individual arguments (not an object!)
|
||||
const result = add(5, 10); // NOT add({ a: 5, b: 10 })
|
||||
```
|
||||
|
||||
The framework extracts the JSON tags from the struct fields and uses them to generate the correct TypeScript function signature.
|
||||
|
||||
### Example
|
||||
|
||||
```typescript
|
||||
// TypeScript code
|
||||
const response = fetch({input: "https://httpbin.org/get"});
|
||||
// TypeScript code - call with individual arguments matching struct fields
|
||||
const response = fetch("https://httpbin.org/get");
|
||||
console.log("OK:", response.ok);
|
||||
console.log("Status:", response.status);
|
||||
console.log("Body:", response.body);
|
||||
|
||||
@@ -9,6 +9,7 @@ import (
|
||||
|
||||
"github.com/fastschema/qjs"
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/require"
|
||||
|
||||
"reichard.io/poiesis/internal/functions"
|
||||
)
|
||||
@@ -86,17 +87,14 @@ func TestAsyncFunctionResolution(t *testing.T) {
|
||||
})
|
||||
|
||||
r, err := New(context.Background())
|
||||
assert.NoError(t, err)
|
||||
require.NoError(t, err)
|
||||
|
||||
result, err := r.ctx.Eval("test.js", qjs.Code(`(async () => { return await resolveTest({field1: "hello"}); })()`))
|
||||
if err == nil && result != nil {
|
||||
defer result.Free()
|
||||
val, err := result.Await()
|
||||
assert.NoError(t, err)
|
||||
assert.Equal(t, "test-result", val.String())
|
||||
} else {
|
||||
t.Logf("Skipping async test - error: %v", err)
|
||||
}
|
||||
// Async functions need to be awaited in an async context
|
||||
result, err := r.ctx.Eval("test.js", qjs.Code(`async function run() { return await resolveTest("hello"); }; run()`))
|
||||
require.NoError(t, err)
|
||||
require.NotNil(t, result)
|
||||
defer result.Free()
|
||||
assert.Equal(t, "test-result", result.String())
|
||||
}
|
||||
|
||||
func TestAsyncFunctionRejection(t *testing.T) {
|
||||
@@ -105,9 +103,10 @@ func TestAsyncFunctionRejection(t *testing.T) {
|
||||
})
|
||||
|
||||
r, err := New(context.Background())
|
||||
assert.NoError(t, err)
|
||||
require.NoError(t, err)
|
||||
|
||||
_, err = r.ctx.Eval("test.js", qjs.Code(`(async () => { return await rejectTest({field1: "hello"}); })()`))
|
||||
// Rejected promises throw when awaited
|
||||
_, err = r.ctx.Eval("test.js", qjs.Code(`async function run() { return await rejectTest("hello"); }; run()`))
|
||||
assert.Error(t, err)
|
||||
}
|
||||
|
||||
|
||||
@@ -32,10 +32,15 @@ func TestFetch(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestFetchHTTPBin(t *testing.T) {
|
||||
t.Skip("httpbin.org test is flaky")
|
||||
ctx := context.Background()
|
||||
server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||
w.Header().Set("Content-Type", "application/json")
|
||||
w.WriteHeader(http.StatusOK)
|
||||
_, _ = w.Write([]byte(`{"args":{}}`))
|
||||
}))
|
||||
defer server.Close()
|
||||
|
||||
result, err := Fetch(ctx, FetchArgs{Input: "https://httpbin.org/get"})
|
||||
result, err := Fetch(ctx, FetchArgs{Input: server.URL})
|
||||
require.NoError(t, err)
|
||||
|
||||
assert.True(t, result.OK)
|
||||
|
||||
Reference in New Issue
Block a user