mirror of
https://github.com/mountain-loop/yaak.git
synced 2026-08-25 21:04:04 +02:00
Generate the proxy wire types with ts-rs (@yaakapp-internal/send-proxy)
This commit is contained in:
Generated
+1
@@ -11689,6 +11689,7 @@ dependencies = [
|
|||||||
"serde_json",
|
"serde_json",
|
||||||
"tokio",
|
"tokio",
|
||||||
"tower-http",
|
"tower-http",
|
||||||
|
"ts-rs",
|
||||||
"url",
|
"url",
|
||||||
"uuid",
|
"uuid",
|
||||||
"yaak-http",
|
"yaak-http",
|
||||||
|
|||||||
@@ -29,6 +29,7 @@ serde = { workspace = true, features = ["derive"] }
|
|||||||
serde_json = { workspace = true }
|
serde_json = { workspace = true }
|
||||||
tokio = { workspace = true, features = ["rt-multi-thread", "macros", "signal", "sync", "io-util", "time", "net"] }
|
tokio = { workspace = true, features = ["rt-multi-thread", "macros", "signal", "sync", "io-util", "time", "net"] }
|
||||||
tower-http = { version = "0.6", features = ["cors", "trace"] }
|
tower-http = { version = "0.6", features = ["cors", "trace"] }
|
||||||
|
ts-rs = { workspace = true }
|
||||||
url = "2"
|
url = "2"
|
||||||
uuid = { version = "1", features = ["v4"] }
|
uuid = { version = "1", features = ["v4"] }
|
||||||
yaak-http = { workspace = true }
|
yaak-http = { workspace = true }
|
||||||
|
|||||||
@@ -121,6 +121,11 @@ construction, cancellable by closing the connection, readable with `curl`, and
|
|||||||
needs no upgrade handling on either side. A WebSocket only earns its keep when
|
needs no upgrade handling on either side. A WebSocket only earns its keep when
|
||||||
traffic is bidirectional, which a single send is not.
|
traffic is bidirectional, which a single send is not.
|
||||||
|
|
||||||
|
The TypeScript side of this contract is generated from `src/wire.rs` by ts-rs
|
||||||
|
into `bindings/` (run `cargo test -p yaak-send-proxy` after changing a frame)
|
||||||
|
and published to the tab as `@yaakapp-internal/send-proxy`, so a change to the
|
||||||
|
wire on one side is a type error on the other.
|
||||||
|
|
||||||
`GET /v1/health` reports the version and the effective limits.
|
`GET /v1/health` reports the version and the effective limits.
|
||||||
|
|
||||||
## What comes later
|
## What comes later
|
||||||
|
|||||||
@@ -0,0 +1,48 @@
|
|||||||
|
// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually.
|
||||||
|
|
||||||
|
export type Cookie = { name: string, value: string, domain: CookieDomain, expires: CookieExpires, path: string, secure: boolean, httpOnly: boolean, sameSite: CookieSameSite | null, };
|
||||||
|
|
||||||
|
export type CookieDomain = { "HostOnly": string } | { "Suffix": string } | "NotPresent" | "Empty";
|
||||||
|
|
||||||
|
export type CookieExpires = { "AtUtc": string } | "SessionEnd";
|
||||||
|
|
||||||
|
export type CookieSameSite = "Strict" | "Lax" | "None";
|
||||||
|
|
||||||
|
export type HttpRequest = { model: "http_request", id: string, createdAt: string, updatedAt: string, workspaceId: string, folderId: string | null, authentication: Record<string, any>, authenticationType: string | null, body: Record<string, any>, bodyType: string | null, description: string, headers: Array<HttpRequestHeader>, method: string, name: string, sortPriority: number, url: string,
|
||||||
|
/**
|
||||||
|
* URL parameters used for both path placeholders (`:id`) and query string entries.
|
||||||
|
*/
|
||||||
|
urlParameters: Array<HttpUrlParameter>, settingSendCookies: InheritedBoolSetting, settingStoreCookies: InheritedBoolSetting, settingValidateCertificates: InheritedBoolSetting, settingFollowRedirects: InheritedBoolSetting, settingRequestTimeout: InheritedIntSetting, };
|
||||||
|
|
||||||
|
export type HttpRequestHeader = { enabled?: boolean, name: string, value: string, id?: string, };
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Serializable representation of HTTP response events for DB storage.
|
||||||
|
* This mirrors `yaak_http::sender::HttpResponseEvent` but with serde support.
|
||||||
|
* The `From` impl is in yaak-http to avoid circular dependencies.
|
||||||
|
*/
|
||||||
|
export type HttpResponseEventData = { "type": "setting", name: string, value: string, source_model?: string, source_id?: string, source_name?: string, } | { "type": "info", message: string, } | { "type": "redirect", url: string, status: number, behavior: string, dropped_body: boolean, dropped_headers: Array<string>, } | { "type": "send_url", method: string, scheme: string, username: string, password: string, host: string, port: number, path: string, query: string, fragment: string, } | { "type": "receive_url", version: string, status: string, } | { "type": "header_up", name: string, value: string, } | { "type": "header_down", name: string, value: string, } | { "type": "chunk_sent", bytes: number, } | { "type": "chunk_received", bytes: number, } | { "type": "dns_resolved", hostname: string, addresses: Array<string>, duration: bigint, overridden: boolean, };
|
||||||
|
|
||||||
|
export type HttpResponseHeader = { name: string, value: string, };
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The resolved send settings, values only: what an executor has to obey, with the sources
|
||||||
|
* (which model each came from) left behind in [`ResolvedHttpRequestSettings`]. This is what
|
||||||
|
* crosses from a tab to the send proxy, and what the proxy reads.
|
||||||
|
*/
|
||||||
|
export type HttpSendSettings = { validateCertificates: boolean, followRedirects: boolean,
|
||||||
|
/**
|
||||||
|
* Milliseconds. Zero or negative means no timeout.
|
||||||
|
*/
|
||||||
|
timeoutMs: number, sendCookies: boolean, storeCookies: boolean, };
|
||||||
|
|
||||||
|
export type HttpUrlParameter = { enabled?: boolean,
|
||||||
|
/**
|
||||||
|
* Colon-prefixed parameters are treated as path parameters if they match, like `/users/:id`
|
||||||
|
* Other entries are appended as query parameters
|
||||||
|
*/
|
||||||
|
name: string, value: string, id?: string, };
|
||||||
|
|
||||||
|
export type InheritedBoolSetting = { enabled?: boolean, value: boolean, };
|
||||||
|
|
||||||
|
export type InheritedIntSetting = { enabled?: boolean, value: number, };
|
||||||
@@ -0,0 +1,64 @@
|
|||||||
|
// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually.
|
||||||
|
import type { Cookie, HttpRequest, HttpResponseEventData, HttpResponseHeader, HttpSendSettings } from "./gen_models";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* One line of the reply stream. Tags are snake_case like the timeline event tags; fields are
|
||||||
|
* camelCase like every model the tab stores.
|
||||||
|
*/
|
||||||
|
export type Frame = { "type": "event", event: HttpResponseEventData, } | { "type": "response", status: number, statusReason: string | null,
|
||||||
|
/**
|
||||||
|
* The URL that answered, after redirects.
|
||||||
|
*/
|
||||||
|
url: string, remoteAddr: string | null, version: string | null, headers: Array<HttpResponseHeader>,
|
||||||
|
/**
|
||||||
|
* The headers that were actually sent on the final hop, cookies and all.
|
||||||
|
*/
|
||||||
|
requestHeaders: Array<HttpResponseHeader>,
|
||||||
|
/**
|
||||||
|
* `Content-Length` as declared by the server, if it declared one.
|
||||||
|
*/
|
||||||
|
contentLength: number | null,
|
||||||
|
/**
|
||||||
|
* Milliseconds from the start of the send to the response head.
|
||||||
|
*/
|
||||||
|
elapsedHeaders: number,
|
||||||
|
/**
|
||||||
|
* Milliseconds spent in DNS on the last lookup, or zero.
|
||||||
|
*/
|
||||||
|
elapsedDns: number, } | { "type": "body", data: string, } | { "type": "done",
|
||||||
|
/**
|
||||||
|
* Milliseconds from the start of the send to the end of the body.
|
||||||
|
*/
|
||||||
|
elapsed: number,
|
||||||
|
/**
|
||||||
|
* Bytes of body relayed, after decompression.
|
||||||
|
*/
|
||||||
|
contentLength: number,
|
||||||
|
/**
|
||||||
|
* Bytes on the wire as declared by the server, or the relayed size when unknown.
|
||||||
|
*/
|
||||||
|
contentLengthCompressed: number,
|
||||||
|
/**
|
||||||
|
* The jar as the send left it, for the tab to persist. `None` when the tab sent none.
|
||||||
|
*/
|
||||||
|
cookies: Array<Cookie> | null, } | { "type": "error", message: string, cookies: Array<Cookie> | null, };
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The body of `POST /v1/http/send`.
|
||||||
|
*/
|
||||||
|
export type SendRequest = {
|
||||||
|
/**
|
||||||
|
* The request to send, in the desktop's own model shape but with every template already
|
||||||
|
* rendered by the tab. The proxy builds the URL, headers and body from it exactly the way
|
||||||
|
* the desktop does after rendering.
|
||||||
|
*/
|
||||||
|
request: HttpRequest,
|
||||||
|
/**
|
||||||
|
* The resolved settings, values only. Where they came from is the tab's to record in
|
||||||
|
* its timeline; the proxy only needs to obey them.
|
||||||
|
*/
|
||||||
|
settings: HttpSendSettings,
|
||||||
|
/**
|
||||||
|
* The cookies to start with. `None` means no jar at all: nothing sent, nothing kept.
|
||||||
|
*/
|
||||||
|
cookies: Array<Cookie> | null, };
|
||||||
@@ -0,0 +1,4 @@
|
|||||||
|
// The send proxy's wire contract, generated by ts-rs from src/wire.rs
|
||||||
|
// (`cargo test -p yaak-send-proxy`). The tab imports these so a change to a
|
||||||
|
// frame on the Rust side is a type error in packages/platform/src/web.
|
||||||
|
export type { Frame, SendRequest } from "./bindings/gen_send_proxy";
|
||||||
@@ -0,0 +1,6 @@
|
|||||||
|
{
|
||||||
|
"name": "@yaakapp-internal/send-proxy",
|
||||||
|
"version": "1.0.0",
|
||||||
|
"private": true,
|
||||||
|
"main": "index.ts"
|
||||||
|
}
|
||||||
@@ -9,15 +9,21 @@
|
|||||||
//! Nothing here names a workspace, a request id, or a response id. The proxy
|
//! Nothing here names a workspace, a request id, or a response id. The proxy
|
||||||
//! does not know what the tab will call this response; it only knows what came
|
//! does not know what the tab will call this response; it only knows what came
|
||||||
//! back.
|
//! back.
|
||||||
|
//!
|
||||||
|
//! The TypeScript side of this contract is generated from these types into
|
||||||
|
//! `bindings/` (`cargo test -p yaak-send-proxy`) and published to the tab as
|
||||||
|
//! `@yaakapp-internal/send-proxy`, so a change here is a type error there.
|
||||||
|
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
|
use ts_rs::TS;
|
||||||
use yaak_models::models::{
|
use yaak_models::models::{
|
||||||
Cookie, HttpRequest, HttpResponseEventData, HttpResponseHeader, HttpSendSettings,
|
Cookie, HttpRequest, HttpResponseEventData, HttpResponseHeader, HttpSendSettings,
|
||||||
};
|
};
|
||||||
|
|
||||||
/// The body of `POST /v1/http/send`.
|
/// The body of `POST /v1/http/send`.
|
||||||
#[derive(Deserialize, Debug)]
|
#[derive(Deserialize, Debug, TS)]
|
||||||
#[serde(rename_all = "camelCase")]
|
#[serde(rename_all = "camelCase")]
|
||||||
|
#[ts(export, export_to = "gen_send_proxy.ts")]
|
||||||
pub struct SendRequest {
|
pub struct SendRequest {
|
||||||
/// The request to send, in the desktop's own model shape but with every template already
|
/// The request to send, in the desktop's own model shape but with every template already
|
||||||
/// rendered by the tab. The proxy builds the URL, headers and body from it exactly the way
|
/// rendered by the tab. The proxy builds the URL, headers and body from it exactly the way
|
||||||
@@ -33,12 +39,13 @@ pub struct SendRequest {
|
|||||||
|
|
||||||
/// One line of the reply stream. Tags are snake_case like the timeline event tags; fields are
|
/// One line of the reply stream. Tags are snake_case like the timeline event tags; fields are
|
||||||
/// camelCase like every model the tab stores.
|
/// camelCase like every model the tab stores.
|
||||||
#[derive(Serialize, Debug)]
|
#[derive(Serialize, Debug, TS)]
|
||||||
#[serde(
|
#[serde(
|
||||||
tag = "type",
|
tag = "type",
|
||||||
rename_all = "snake_case",
|
rename_all = "snake_case",
|
||||||
rename_all_fields = "camelCase"
|
rename_all_fields = "camelCase"
|
||||||
)]
|
)]
|
||||||
|
#[ts(export, export_to = "gen_send_proxy.ts")]
|
||||||
pub enum Frame {
|
pub enum Frame {
|
||||||
/// A timeline event, in the same shape the desktop stores. Interleaved with everything
|
/// A timeline event, in the same shape the desktop stores. Interleaved with everything
|
||||||
/// else in the order the engine produced it.
|
/// else in the order the engine produced it.
|
||||||
@@ -56,10 +63,13 @@ pub enum Frame {
|
|||||||
/// The headers that were actually sent on the final hop, cookies and all.
|
/// The headers that were actually sent on the final hop, cookies and all.
|
||||||
request_headers: Vec<HttpResponseHeader>,
|
request_headers: Vec<HttpResponseHeader>,
|
||||||
/// `Content-Length` as declared by the server, if it declared one.
|
/// `Content-Length` as declared by the server, if it declared one.
|
||||||
|
#[ts(type = "number | null")]
|
||||||
content_length: Option<u64>,
|
content_length: Option<u64>,
|
||||||
/// Milliseconds from the start of the send to the response head.
|
/// Milliseconds from the start of the send to the response head.
|
||||||
|
#[ts(type = "number")]
|
||||||
elapsed_headers: u64,
|
elapsed_headers: u64,
|
||||||
/// Milliseconds spent in DNS on the last lookup, or zero.
|
/// Milliseconds spent in DNS on the last lookup, or zero.
|
||||||
|
#[ts(type = "number")]
|
||||||
elapsed_dns: u64,
|
elapsed_dns: u64,
|
||||||
},
|
},
|
||||||
/// A piece of the response body, decompressed, base64-encoded.
|
/// A piece of the response body, decompressed, base64-encoded.
|
||||||
@@ -67,10 +77,13 @@ pub enum Frame {
|
|||||||
/// The send finished. The last frame on a successful stream.
|
/// The send finished. The last frame on a successful stream.
|
||||||
Done {
|
Done {
|
||||||
/// Milliseconds from the start of the send to the end of the body.
|
/// Milliseconds from the start of the send to the end of the body.
|
||||||
|
#[ts(type = "number")]
|
||||||
elapsed: u64,
|
elapsed: u64,
|
||||||
/// Bytes of body relayed, after decompression.
|
/// Bytes of body relayed, after decompression.
|
||||||
|
#[ts(type = "number")]
|
||||||
content_length: u64,
|
content_length: u64,
|
||||||
/// Bytes on the wire as declared by the server, or the relayed size when unknown.
|
/// Bytes on the wire as declared by the server, or the relayed size when unknown.
|
||||||
|
#[ts(type = "number")]
|
||||||
content_length_compressed: u64,
|
content_length_compressed: u64,
|
||||||
/// The jar as the send left it, for the tab to persist. `None` when the tab sent none.
|
/// The jar as the send left it, for the tab to persist. `None` when the tab sent none.
|
||||||
cookies: Option<Vec<Cookie>>,
|
cookies: Option<Vec<Cookie>>,
|
||||||
|
|||||||
Generated
+10
@@ -70,6 +70,7 @@
|
|||||||
"crates/yaak-web",
|
"crates/yaak-web",
|
||||||
"crates/yaak-ws",
|
"crates/yaak-ws",
|
||||||
"crates-proxy/yaak-proxy-lib",
|
"crates-proxy/yaak-proxy-lib",
|
||||||
|
"crates-server/yaak-send-proxy",
|
||||||
"apps/yaak-client",
|
"apps/yaak-client",
|
||||||
"apps/yaak-proxy"
|
"apps/yaak-proxy"
|
||||||
],
|
],
|
||||||
@@ -272,6 +273,10 @@
|
|||||||
"name": "@yaakapp-internal/proxy-lib",
|
"name": "@yaakapp-internal/proxy-lib",
|
||||||
"version": "1.0.0"
|
"version": "1.0.0"
|
||||||
},
|
},
|
||||||
|
"crates-server/yaak-send-proxy": {
|
||||||
|
"name": "@yaakapp-internal/send-proxy",
|
||||||
|
"version": "1.0.0"
|
||||||
|
},
|
||||||
"crates-tauri/yaak-app-client": {
|
"crates-tauri/yaak-app-client": {
|
||||||
"name": "@yaakapp-internal/tauri-client",
|
"name": "@yaakapp-internal/tauri-client",
|
||||||
"version": "1.0.0"
|
"version": "1.0.0"
|
||||||
@@ -5645,6 +5650,10 @@
|
|||||||
"resolved": "crates/common/yaak-rpc-schema",
|
"resolved": "crates/common/yaak-rpc-schema",
|
||||||
"link": true
|
"link": true
|
||||||
},
|
},
|
||||||
|
"node_modules/@yaakapp-internal/send-proxy": {
|
||||||
|
"resolved": "crates-server/yaak-send-proxy",
|
||||||
|
"link": true
|
||||||
|
},
|
||||||
"node_modules/@yaakapp-internal/sse": {
|
"node_modules/@yaakapp-internal/sse": {
|
||||||
"resolved": "crates/yaak-sse",
|
"resolved": "crates/yaak-sse",
|
||||||
"link": true
|
"link": true
|
||||||
@@ -15801,6 +15810,7 @@
|
|||||||
"@tauri-apps/plugin-os": "^2.3.2",
|
"@tauri-apps/plugin-os": "^2.3.2",
|
||||||
"@yaakapp-internal/models": "^1.0.0",
|
"@yaakapp-internal/models": "^1.0.0",
|
||||||
"@yaakapp-internal/rpc-schema": "^1.0.0",
|
"@yaakapp-internal/rpc-schema": "^1.0.0",
|
||||||
|
"@yaakapp-internal/send-proxy": "^1.0.0",
|
||||||
"@yaakapp-internal/web": "^1.0.0"
|
"@yaakapp-internal/web": "^1.0.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -69,6 +69,7 @@
|
|||||||
"crates/yaak-web",
|
"crates/yaak-web",
|
||||||
"crates/yaak-ws",
|
"crates/yaak-ws",
|
||||||
"crates-proxy/yaak-proxy-lib",
|
"crates-proxy/yaak-proxy-lib",
|
||||||
|
"crates-server/yaak-send-proxy",
|
||||||
"apps/yaak-client",
|
"apps/yaak-client",
|
||||||
"apps/yaak-proxy"
|
"apps/yaak-proxy"
|
||||||
],
|
],
|
||||||
|
|||||||
@@ -11,6 +11,7 @@
|
|||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@yaakapp-internal/models": "^1.0.0",
|
"@yaakapp-internal/models": "^1.0.0",
|
||||||
"@yaakapp-internal/rpc-schema": "^1.0.0",
|
"@yaakapp-internal/rpc-schema": "^1.0.0",
|
||||||
|
"@yaakapp-internal/send-proxy": "^1.0.0",
|
||||||
"@yaakapp-internal/web": "^1.0.0",
|
"@yaakapp-internal/web": "^1.0.0",
|
||||||
"@tauri-apps/api": "^2.11.0",
|
"@tauri-apps/api": "^2.11.0",
|
||||||
"@tauri-apps/plugin-clipboard-manager": "^2.3.2",
|
"@tauri-apps/plugin-clipboard-manager": "^2.3.2",
|
||||||
|
|||||||
@@ -1,19 +1,11 @@
|
|||||||
/**
|
/**
|
||||||
* The wire to the send proxy: where it is, what goes up, and what comes back.
|
* The wire to the send proxy: where it is, and how to read what comes back.
|
||||||
*
|
*
|
||||||
* These shapes mirror `crates-server/yaak-send-proxy/src/wire.rs` by hand. The
|
* The shapes themselves are generated from `crates-server/yaak-send-proxy/src/wire.rs`
|
||||||
* proxy is a separate binary with its own release cadence, so the contract is
|
* into `@yaakapp-internal/send-proxy`, so the two sides cannot drift silently.
|
||||||
* written down on both sides rather than generated across them; a change to one
|
|
||||||
* is a change to the other, and the frame `type` tags are the versioning.
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import type {
|
import type { Frame } from "@yaakapp-internal/send-proxy";
|
||||||
Cookie,
|
|
||||||
HttpRequest,
|
|
||||||
HttpResponseEventData,
|
|
||||||
HttpResponseHeader,
|
|
||||||
HttpSendSettings,
|
|
||||||
} from "@yaakapp-internal/models";
|
|
||||||
|
|
||||||
/* ------------------------------- location -------------------------------- */
|
/* ------------------------------- location -------------------------------- */
|
||||||
|
|
||||||
@@ -33,54 +25,12 @@ export function proxySendUrl(): string {
|
|||||||
return `${proxyBaseUrl()}/v1/http/send`;
|
return `${proxyBaseUrl()}/v1/http/send`;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* --------------------------------- up ------------------------------------ */
|
|
||||||
|
|
||||||
/** The body of `POST /v1/http/send`. */
|
|
||||||
export interface ProxyRequestBody {
|
|
||||||
/** The rendered request, in the model shape (see `wire.rs` `SendRequest.request`). */
|
|
||||||
request: HttpRequest;
|
|
||||||
settings: HttpSendSettings;
|
|
||||||
/** The jar's cookies to start from, or `null` for no jar at all. */
|
|
||||||
cookies: Cookie[] | null;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* -------------------------------- down ----------------------------------- */
|
|
||||||
|
|
||||||
export interface ProxySendResponse {
|
|
||||||
type: "response";
|
|
||||||
status: number;
|
|
||||||
statusReason: string | null;
|
|
||||||
url: string;
|
|
||||||
remoteAddr: string | null;
|
|
||||||
version: string | null;
|
|
||||||
headers: HttpResponseHeader[];
|
|
||||||
requestHeaders: HttpResponseHeader[];
|
|
||||||
contentLength: number | null;
|
|
||||||
elapsedHeaders: number;
|
|
||||||
elapsedDns: number;
|
|
||||||
}
|
|
||||||
|
|
||||||
export type ProxyFrame =
|
|
||||||
/** A timeline event in the `http_response_event.event` shape. */
|
|
||||||
| { type: "event"; event: HttpResponseEventData }
|
|
||||||
| ProxySendResponse
|
|
||||||
/** A body chunk, decompressed, base64. */
|
|
||||||
| { type: "body"; data: string }
|
|
||||||
| {
|
|
||||||
type: "done";
|
|
||||||
elapsed: number;
|
|
||||||
contentLength: number;
|
|
||||||
contentLengthCompressed: number;
|
|
||||||
cookies: Cookie[] | null;
|
|
||||||
}
|
|
||||||
| { type: "error"; message: string; cookies: Cookie[] | null };
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Yield frames from an NDJSON stream as they arrive. A partial trailing line is
|
* Yield frames from an NDJSON stream as they arrive. A partial trailing line is
|
||||||
* held until its newline comes; anything left when the stream ends is dropped,
|
* held until its newline comes; anything left when the stream ends is dropped,
|
||||||
* because a frame without its newline is a frame the proxy didn't finish writing.
|
* because a frame without its newline is a frame the proxy didn't finish writing.
|
||||||
*/
|
*/
|
||||||
export async function* readFrames(stream: ReadableStream<Uint8Array>): AsyncGenerator<ProxyFrame> {
|
export async function* readFrames(stream: ReadableStream<Uint8Array>): AsyncGenerator<Frame> {
|
||||||
const reader = stream.getReader();
|
const reader = stream.getReader();
|
||||||
const decoder = new TextDecoder();
|
const decoder = new TextDecoder();
|
||||||
let buffer = "";
|
let buffer = "";
|
||||||
@@ -93,7 +43,7 @@ export async function* readFrames(stream: ReadableStream<Uint8Array>): AsyncGene
|
|||||||
while (newline !== -1) {
|
while (newline !== -1) {
|
||||||
const line = buffer.slice(0, newline);
|
const line = buffer.slice(0, newline);
|
||||||
buffer = buffer.slice(newline + 1);
|
buffer = buffer.slice(newline + 1);
|
||||||
if (line.trim() !== "") yield JSON.parse(line) as ProxyFrame;
|
if (line.trim() !== "") yield JSON.parse(line) as Frame;
|
||||||
newline = buffer.indexOf("\n");
|
newline = buffer.indexOf("\n");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -31,8 +31,8 @@ import type {
|
|||||||
HttpResponseEventData,
|
HttpResponseEventData,
|
||||||
HttpSendSettings,
|
HttpSendSettings,
|
||||||
} from "@yaakapp-internal/models";
|
} from "@yaakapp-internal/models";
|
||||||
|
import type { Frame, SendRequest } from "@yaakapp-internal/send-proxy";
|
||||||
import type { WorkerConnection } from "./connection";
|
import type { WorkerConnection } from "./connection";
|
||||||
import type { ProxyFrame, ProxyRequestBody, ProxySendResponse } from "./proxy";
|
|
||||||
import { proxySendUrl, readFrames } from "./proxy";
|
import { proxySendUrl, readFrames } from "./proxy";
|
||||||
|
|
||||||
/* -------------------------------- shapes --------------------------------- */
|
/* -------------------------------- shapes --------------------------------- */
|
||||||
@@ -106,7 +106,7 @@ async function runSend(
|
|||||||
const timeline = new TimelineWriter(db, response.id, response.workspaceId);
|
const timeline = new TimelineWriter(db, response.id, response.workspaceId);
|
||||||
timeline.push(prepared.settingEvents);
|
timeline.push(prepared.settingEvents);
|
||||||
|
|
||||||
const body: ProxyRequestBody = {
|
const body: SendRequest = {
|
||||||
request: prepared.request,
|
request: prepared.request,
|
||||||
settings: prepared.settings,
|
settings: prepared.settings,
|
||||||
cookies: prepared.cookieJar?.cookies ?? null,
|
cookies: prepared.cookieJar?.cookies ?? null,
|
||||||
@@ -139,7 +139,7 @@ async function runSend(
|
|||||||
const chunks: Uint8Array[] = [];
|
const chunks: Uint8Array[] = [];
|
||||||
let received = 0;
|
let received = 0;
|
||||||
let lastProgress = startedAt;
|
let lastProgress = startedAt;
|
||||||
let terminal: ProxyFrame | null = null;
|
let terminal: Frame | null = null;
|
||||||
|
|
||||||
for await (const frame of readFrames(res.body)) {
|
for await (const frame of readFrames(res.body)) {
|
||||||
switch (frame.type) {
|
switch (frame.type) {
|
||||||
@@ -201,7 +201,7 @@ async function runSend(
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
function headOf(frame: ProxySendResponse): ResponsePatch {
|
function headOf(frame: Extract<Frame, { type: "response" }>): ResponsePatch {
|
||||||
return {
|
return {
|
||||||
state: "connected",
|
state: "connected",
|
||||||
status: frame.status,
|
status: frame.status,
|
||||||
|
|||||||
Reference in New Issue
Block a user