Skip to content

feat(sidecar)!: stream request bodies and add route middleware#96

Draft
haveyaseen wants to merge 4 commits into
mainfrom
feat/full-request-sidecar
Draft

feat(sidecar)!: stream request bodies and add route middleware#96
haveyaseen wants to merge 4 commits into
mainfrom
feat/full-request-sidecar

Conversation

@haveyaseen
Copy link
Copy Markdown
Member

Add createRouteToForstMiddleware with route-request-stream JSON (prefix + streamed base64 body + suffix), invokeFunctionRawWithReadableBody, and split ForstSidecar into forst-sidecar; document and test the flow.

BREAKING CHANGE: pipeInvokeRawStream(packageName, functionName, body, destination) now takes body: ReadableStream instead of args: unknown[]. Build the stream from JSON.stringify([args]) or from createInvokeRawJsonBodyReadable for Express.

Example:

    import { Readable } from "node:stream";
    const body = Readable.toWeb(nodeReadable) as ReadableStream<Uint8Array>;
    await client.pipeInvokeRawStream("main", "StreamFn", body, res);

docs: rewrite root README for sidecar-first positioning

Reframe intro, comparisons, migration walkthrough, and package pointers around Node + sidecar adoption.

refactor(devserver): extract dev HTTP server into internal/devserver

Move the dev server out of forst/cmd/forst into forst/internal/devserver: dedicated handlers (health, version, functions, invoke, invoke/raw), shared response helpers, invoke execution, and tests. Drop the old dev_server_http* surface from cmd in favor of the internal package and slimmer runtime wiring.

…eware

Add createRouteToForstMiddleware with route-request-stream JSON (prefix + streamed
base64 body + suffix), invokeFunctionRawWithReadableBody, and split ForstSidecar
into forst-sidecar; document and test the flow.

BREAKING CHANGE: pipeInvokeRawStream(packageName, functionName, body, destination) now
takes body: ReadableStream<Uint8Array> instead of args: unknown[]. Build the stream
from JSON.stringify([args]) or from createInvokeRawJsonBodyReadable for Express.

Example:

```typescript
    import { Readable } from "node:stream";
    const body = Readable.toWeb(nodeReadable) as ReadableStream<Uint8Array>;
    await client.pipeInvokeRawStream("main", "StreamFn", body, res);
```

docs: rewrite root README for sidecar-first positioning

Reframe intro, comparisons, migration walkthrough, and package pointers around Node +
sidecar adoption.

refactor(devserver): extract dev HTTP server into internal/devserver

Move the dev server out of forst/cmd/forst into forst/internal/devserver: dedicated
handlers (health, version, functions, invoke, invoke/raw), shared response helpers,
invoke execution, and tests. Drop the old dev_server_http* surface from cmd in favor
of the internal package and slimmer runtime wiring.
@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented Apr 21, 2026

Important

Review skipped

Draft detected.

Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

⚙️ Run configuration

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro

Run ID: ae470a42-e0a1-49c7-a72d-f346eb442723

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feat/full-request-sidecar

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

… deps

Wire Express + createRouteToForstMiddleware against a stub dev server (connect
mode, GET /health + POST /invoke/raw) to assert full routed request fidelity
(session-style headers, query, body) and mirrored HTTP response; cover streaming
passthrough. Extend unit tests for mapRequest header injection and next(err) on
invoke failure. Pin express@^4 and @types/express@^4 under devDependencies so
Bun tests run (Express 5 router currently breaks under Bun); peer remains
express ^5.
… sidecar)

Add `forst/gateway` (`GatewayRequest` / `GatewayResponse`, constructors, `ValidateGatewayResultJSON`).
Executor builds temp modules against the SDK (`replace forst`), encodes `Ok` gateway values to §12 JSON and maps executor failure JSON to `success: false` + `error`. Discovery sets `isGateway` from `GatewayRequest`→`GatewayResponse` signatures. Dev server bumps `HTTPContractVersion` to `2` and rejects malformed gateway `result` payloads before responding. TypeScript emit maps `gateway.*` qualified names to `@forst/sidecar` wire types; Go workspace resolution supports `forst/gateway` from example roots. Includes gateway example under `examples/in/gateway`, golden JSON fixtures, and RFC/docs updates.

BREAKING CHANGE: `@forst/sidecar` v1.0.0 removes `continue` / `reqPatch` / `ForstRoutedContinue`; gateway success `invoke` `result` must use `kind: "answer"` or `kind: "pass"` (`request` for Express merge). `FORST_DEV_HTTPTRACT_VERSION` is now `"2"` (must match `forst dev`).

Example:

```forst
import "forst/gateway"

func Hello(req gateway.GatewayRequest): Result(gateway.GatewayResponse, Error) {
  return gateway.Plain200Text("hello")
}
```
…FI in goload

Add `forst/gateway` entry points: `StdlibImportPath`, `IsGatewayHandlerSignature`,
`TempModuleNeedsGatewayImport`, `ValidateSuccessResultIfGateway`, `TypeScriptEmitType`,
plus tests. Wire discovery, executor temp `main` imports, devserver invoke validation,
and TS type mapping through those helpers instead of duplicated strings and logic.

Introduce `goload.IsMergeStdlibUserDefinedImport` (delegating to `gateway.StdlibImportPath`)
so `go_interop` maps merge-path named Go types to Forst `UserDefined` without importing
`forst/gateway` directly.

Example:

```go
// Discovery / devserver / codegen delegate to gateway package
gateway.ValidateSuccessResultIfGateway(isGateway, execOk, resultRaw)
goload.IsMergeStdlibUserDefinedImport(pkg.Path()) // go/types FFI classification
```
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant