Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 3 additions & 3 deletions packages/app/test/fixtures/http/run-test.ts
Original file line number Diff line number Diff line change
@@ -1,13 +1,13 @@
import { createRemoteClient } from '@t-req/core';
import { createClient } from '@t-req/core';

const client = createRemoteClient({
const client = createClient({
variables: {
baseUrl: 'https://httpbin.org/',
//baseUrl: 'https://dummyjson.com/carts',
userId: '123',
token: '1234567890'
}
});

console.log('Running simple GET request...');
await client.run('./post-json.http');

Expand Down
45 changes: 27 additions & 18 deletions packages/core/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -120,6 +120,14 @@ const client = createClient({
// Required in Node to run from files.
// In Bun, you can omit this and the library will use Bun's filesystem APIs.
io: createNodeIO(),

// Connect to TUI/server for observability (optional)
// Auto-detected from TREQ_SERVER env var when run from TUI
server: 'http://localhost:4096',

// Optional auth token for server mode
serverToken: process.env.TREQ_TOKEN,

// Variables available to all requests
variables: {
baseUrl: 'https://api.example.com',
Expand Down Expand Up @@ -179,32 +187,33 @@ client.setVariables({ a: 1, b: 2 });
console.log(client.getVariables());
```

### Remote Client (via `treq serve`)
### Server Mode (TUI / Observability)

If you want **Observer Mode** (TUI / event streaming / execution store) without rewriting your existing scripts, use `createRemoteClient()` to route requests through the `@t-req/app` server (`treq serve`).
When you want requests to appear in the TUI or web dashboard, the client can route
requests through a t-req server instead of executing them locally.

This keeps the same high-level API as `createClient()` (`run`, `runString`, `setVariable(s)`), but executes via HTTP and creates a **server session + flow** on first use so the run can be observed.
**Automatic detection:** When scripts are run from the TUI (via script runner),
the `TREQ_SERVER` environment variable is automatically injected. Your scripts
work without any code changes.

```typescript
import { createRemoteClient } from '@t-req/core';
**Manual configuration:** For scripts run from a separate terminal:

const client = createRemoteClient({
serverUrl: 'http://localhost:4096',
// Optional bearer token if the server requires it:
// token: process.env.TREQ_TOKEN,
variables: { baseUrl: 'https://api.example.com' }
```typescript
const client = createClient({
server: 'http://localhost:4096', // or set TREQ_SERVER env var
variables: { ... }
});

await client.run('./auth/login.http');
client.setVariable('token', '...');
await client.close(); // finishes the flow (best-effort; server TTL still applies)
```

Additional remote-only methods:
**Behavior:**
- No `server` option + no `TREQ_SERVER` → Local mode (direct execution)
- `server` option OR `TREQ_SERVER` set → Server mode (routed through server)
- Server mode creates a session and flow for observability
- Call `client.close()` when done to finalize the flow

- `close(): Promise<void>`
- `getSessionId(): string | undefined`
- `getFlowId(): string | undefined`
**Server-specific methods:**
- `close(): Promise<void>` - Finalize the session/flow
- `[Symbol.asyncDispose]` - Supports `await using` syntax

### Response

Expand Down
23 changes: 22 additions & 1 deletion packages/core/src/client.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,22 @@ import type { CookieJar } from 'tough-cookie';
import type { EngineConfig, EngineRunOptions } from './engine/engine';
import { createEngine } from './engine/engine';
import type { CookieStore } from './runtime/types';
import { createServerClient, getEnvVar } from './server-client';
import type { Client, ClientConfig, RunOptions } from './types';
import { setOptional } from './utils/optional';

export function createClient(config: ClientConfig = {}): Client {
// Route to server implementation if server URL provided
const serverUrl = config.server ?? getEnvVar('TREQ_SERVER');
if (serverUrl) {
return createServerClient({
...config,
serverUrl,
token: config.serverToken ?? getEnvVar('TREQ_TOKEN')
});
}

// Local implementation
let variables: Record<string, unknown> = { ...config.variables };
const cookieJar = config.cookieJar;
const defaultTimeout = config.timeout ?? 30000;
Expand All @@ -28,6 +40,11 @@ export function createClient(config: ClientConfig = {}): Client {
return { ...variables, ...runVars };
}

// No-op close for local client
async function close(): Promise<void> {
// Local client has no external resources to release
}

return {
async run(filePath: string, options: RunOptions = {}): Promise<Response> {
return await engine.runFile(
Expand Down Expand Up @@ -70,7 +87,11 @@ export function createClient(config: ClientConfig = {}): Client {

getVariables(): Record<string, unknown> {
return { ...variables };
}
},

close,

[Symbol.asyncDispose]: close
};
}

Expand Down
3 changes: 2 additions & 1 deletion packages/core/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,9 +23,10 @@ export {
// Interpolation
export { createInterpolator, interpolate } from './interpolate';
export { parse, parseFile, parseFileWithIO } from './parser';
export { createRemoteClient, type RemoteClient, type RemoteClientConfig } from './remote-client';
// Runtime adapters
export { createAutoTransport, createFetchTransport } from './runtime';
// Server metadata utilities
export { getServerMetadata, type ServerMetadata } from './server-metadata';

// Types
export type {
Expand Down
Loading