mirror of
https://github.com/mountain-loop/yaak.git
synced 2026-08-24 20:34:05 +02:00
Type the web sender with the generated model types
This commit is contained in:
Generated
+1
@@ -15799,6 +15799,7 @@
|
|||||||
"@tauri-apps/plugin-fs": "^2.5.1",
|
"@tauri-apps/plugin-fs": "^2.5.1",
|
||||||
"@tauri-apps/plugin-opener": "^2.5.4",
|
"@tauri-apps/plugin-opener": "^2.5.4",
|
||||||
"@tauri-apps/plugin-os": "^2.3.2",
|
"@tauri-apps/plugin-os": "^2.3.2",
|
||||||
|
"@yaakapp-internal/models": "^1.0.0",
|
||||||
"@yaakapp-internal/rpc-schema": "^1.0.0",
|
"@yaakapp-internal/rpc-schema": "^1.0.0",
|
||||||
"@yaakapp-internal/web": "^1.0.0"
|
"@yaakapp-internal/web": "^1.0.0"
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -9,6 +9,7 @@
|
|||||||
"lint": "tsc --noEmit"
|
"lint": "tsc --noEmit"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
|
"@yaakapp-internal/models": "^1.0.0",
|
||||||
"@yaakapp-internal/rpc-schema": "^1.0.0",
|
"@yaakapp-internal/rpc-schema": "^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",
|
||||||
|
|||||||
@@ -7,6 +7,13 @@
|
|||||||
* is a change to the other, and the frame `type` tags are the versioning.
|
* is a change to the other, and the frame `type` tags are the versioning.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
import type {
|
||||||
|
Cookie,
|
||||||
|
HttpRequest,
|
||||||
|
HttpResponseEventData,
|
||||||
|
HttpResponseHeader,
|
||||||
|
} from "@yaakapp-internal/models";
|
||||||
|
|
||||||
/* ------------------------------- location -------------------------------- */
|
/* ------------------------------- location -------------------------------- */
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -30,7 +37,7 @@ export function proxySendUrl(): string {
|
|||||||
/** The body of `POST /v1/http/send`. */
|
/** The body of `POST /v1/http/send`. */
|
||||||
export interface ProxyRequestBody {
|
export interface ProxyRequestBody {
|
||||||
/** The rendered request, in the model shape (see `wire.rs` `SendRequest.request`). */
|
/** The rendered request, in the model shape (see `wire.rs` `SendRequest.request`). */
|
||||||
request: Record<string, unknown>;
|
request: HttpRequest;
|
||||||
settings: {
|
settings: {
|
||||||
validateCertificates: boolean;
|
validateCertificates: boolean;
|
||||||
followRedirects: boolean;
|
followRedirects: boolean;
|
||||||
@@ -39,16 +46,11 @@ export interface ProxyRequestBody {
|
|||||||
storeCookies: boolean;
|
storeCookies: boolean;
|
||||||
};
|
};
|
||||||
/** The jar's cookies to start from, or `null` for no jar at all. */
|
/** The jar's cookies to start from, or `null` for no jar at all. */
|
||||||
cookies: unknown[] | null;
|
cookies: Cookie[] | null;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* -------------------------------- down ----------------------------------- */
|
/* -------------------------------- down ----------------------------------- */
|
||||||
|
|
||||||
interface WireHeader {
|
|
||||||
name: string;
|
|
||||||
value: string;
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface ProxySendResponse {
|
export interface ProxySendResponse {
|
||||||
type: "response";
|
type: "response";
|
||||||
status: number;
|
status: number;
|
||||||
@@ -56,8 +58,8 @@ export interface ProxySendResponse {
|
|||||||
url: string;
|
url: string;
|
||||||
remoteAddr: string | null;
|
remoteAddr: string | null;
|
||||||
version: string | null;
|
version: string | null;
|
||||||
headers: WireHeader[];
|
headers: HttpResponseHeader[];
|
||||||
requestHeaders: WireHeader[];
|
requestHeaders: HttpResponseHeader[];
|
||||||
contentLength: number | null;
|
contentLength: number | null;
|
||||||
elapsedHeaders: number;
|
elapsedHeaders: number;
|
||||||
elapsedDns: number;
|
elapsedDns: number;
|
||||||
@@ -65,7 +67,7 @@ export interface ProxySendResponse {
|
|||||||
|
|
||||||
export type ProxyFrame =
|
export type ProxyFrame =
|
||||||
/** A timeline event in the `http_response_event.event` shape. */
|
/** A timeline event in the `http_response_event.event` shape. */
|
||||||
| { type: "event"; event: unknown }
|
| { type: "event"; event: HttpResponseEventData }
|
||||||
| ProxySendResponse
|
| ProxySendResponse
|
||||||
/** A body chunk, decompressed, base64. */
|
/** A body chunk, decompressed, base64. */
|
||||||
| { type: "body"; data: string }
|
| { type: "body"; data: string }
|
||||||
@@ -74,9 +76,9 @@ export type ProxyFrame =
|
|||||||
elapsed: number;
|
elapsed: number;
|
||||||
contentLength: number;
|
contentLength: number;
|
||||||
contentLengthCompressed: number;
|
contentLengthCompressed: number;
|
||||||
cookies: unknown[] | null;
|
cookies: Cookie[] | null;
|
||||||
}
|
}
|
||||||
| { type: "error"; message: string; cookies: unknown[] | 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
|
||||||
|
|||||||
@@ -21,65 +21,38 @@
|
|||||||
* byte it returns is stored by this tab.
|
* byte it returns is stored by this tab.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
// Types only: the models package imports this one at runtime, and a type import
|
||||||
|
// is erased, so there is no cycle.
|
||||||
|
import type {
|
||||||
|
Cookie,
|
||||||
|
CookieJar,
|
||||||
|
HttpRequest,
|
||||||
|
HttpResponse,
|
||||||
|
HttpResponseEventData,
|
||||||
|
} from "@yaakapp-internal/models";
|
||||||
import type { WorkerConnection } from "./connection";
|
import type { WorkerConnection } from "./connection";
|
||||||
import type { ProxyFrame, ProxyRequestBody, ProxySendResponse } from "./proxy";
|
import type { ProxyFrame, ProxyRequestBody, ProxySendResponse } from "./proxy";
|
||||||
import { proxySendUrl, readFrames } from "./proxy";
|
import { proxySendUrl, readFrames } from "./proxy";
|
||||||
|
|
||||||
/* -------------------------------- shapes --------------------------------- */
|
/* -------------------------------- shapes --------------------------------- */
|
||||||
|
|
||||||
// The model types this file writes, spelled out rather than imported from
|
|
||||||
// `@yaakapp-internal/models`: the platform package sits underneath the model
|
|
||||||
// package in the dependency graph and must not import it.
|
|
||||||
|
|
||||||
interface HttpResponseHeader {
|
|
||||||
name: string;
|
|
||||||
value: string;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The fields of the `http_response` model this sender writes as a send
|
* The response row as this file knows it: what identifies it, plus whatever
|
||||||
* progresses. Every one is optional: a field this file never sets takes the
|
* has been written so far. Every other field is optional and takes the model
|
||||||
* model layer's default, the same way the desktop's row does. Defaults live in
|
* layer's default when absent, the same way the desktop's row does — defaults
|
||||||
* Rust, once.
|
* live in Rust, once.
|
||||||
*/
|
*/
|
||||||
interface ResponsePatch {
|
type ResponseRow = Pick<HttpResponse, "model" | "requestId" | "workspaceId"> &
|
||||||
state?: "initialized" | "connected" | "closed";
|
Partial<Omit<HttpResponse, "model" | "requestId" | "workspaceId">>;
|
||||||
url?: string;
|
|
||||||
status?: number;
|
|
||||||
statusReason?: string | null;
|
|
||||||
version?: string | null;
|
|
||||||
remoteAddr?: string | null;
|
|
||||||
headers?: HttpResponseHeader[];
|
|
||||||
requestHeaders?: HttpResponseHeader[];
|
|
||||||
contentLength?: number | null;
|
|
||||||
contentLengthCompressed?: number | null;
|
|
||||||
elapsed?: number;
|
|
||||||
elapsedHeaders?: number;
|
|
||||||
elapsedDns?: number;
|
|
||||||
error?: string | null;
|
|
||||||
}
|
|
||||||
|
|
||||||
/** The row itself: what identifies it, plus whatever has been written so far. */
|
type ResponsePatch = Partial<HttpResponse>;
|
||||||
type ResponseRow = {
|
|
||||||
model: "http_response";
|
|
||||||
id?: string;
|
|
||||||
requestId: string;
|
|
||||||
workspaceId: string;
|
|
||||||
} & ResponsePatch;
|
|
||||||
|
|
||||||
interface CookieJarModel {
|
|
||||||
model: "cookie_jar";
|
|
||||||
id: string;
|
|
||||||
cookies: unknown[];
|
|
||||||
[key: string]: unknown;
|
|
||||||
}
|
|
||||||
|
|
||||||
/** What `prepare_http_send` (crates/yaak-web) hands back. */
|
/** What `prepare_http_send` (crates/yaak-web) hands back. */
|
||||||
interface PreparedHttpSend {
|
interface PreparedHttpSend {
|
||||||
request: { url: string; [key: string]: unknown };
|
request: HttpRequest;
|
||||||
settings: ProxyRequestBody["settings"];
|
settings: ProxyRequestBody["settings"];
|
||||||
settingEvents: unknown[];
|
settingEvents: HttpResponseEventData[];
|
||||||
cookieJar: CookieJarModel | null;
|
cookieJar: CookieJar | null;
|
||||||
}
|
}
|
||||||
|
|
||||||
/** The desktop writes progress at most this often while a body streams in. */
|
/** The desktop writes progress at most this often while a body streams in. */
|
||||||
@@ -92,7 +65,7 @@ export async function sendHttpRequest(
|
|||||||
requestId: string,
|
requestId: string,
|
||||||
environmentId: string | null,
|
environmentId: string | null,
|
||||||
cookieJarId: string | null,
|
cookieJarId: string | null,
|
||||||
): Promise<unknown> {
|
): Promise<ResponseRow> {
|
||||||
// The response row exists before anything can go wrong, as on the desktop, so
|
// The response row exists before anything can go wrong, as on the desktop, so
|
||||||
// a failure to render or to reach the proxy lands in the response pane as
|
// a failure to render or to reach the proxy lands in the response pane as
|
||||||
// that response's error rather than as a toast that names no request.
|
// that response's error rather than as a toast that names no request.
|
||||||
@@ -300,7 +273,7 @@ class ResponseWriter {
|
|||||||
* which the whole timeline is known to be in the database.
|
* which the whole timeline is known to be in the database.
|
||||||
*/
|
*/
|
||||||
class TimelineWriter {
|
class TimelineWriter {
|
||||||
private queue: unknown[] = [];
|
private queue: HttpResponseEventData[] = [];
|
||||||
private inFlight: Promise<void> = Promise.resolve();
|
private inFlight: Promise<void> = Promise.resolve();
|
||||||
|
|
||||||
constructor(
|
constructor(
|
||||||
@@ -309,7 +282,7 @@ class TimelineWriter {
|
|||||||
private readonly workspaceId: string,
|
private readonly workspaceId: string,
|
||||||
) {}
|
) {}
|
||||||
|
|
||||||
push(events: unknown[]): void {
|
push(events: HttpResponseEventData[]): void {
|
||||||
if (events.length === 0) return;
|
if (events.length === 0) return;
|
||||||
this.queue.push(...events);
|
this.queue.push(...events);
|
||||||
this.inFlight = this.inFlight.then(() => this.drain());
|
this.inFlight = this.inFlight.then(() => this.drain());
|
||||||
@@ -331,11 +304,7 @@ class TimelineWriter {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
async function persistCookies(
|
async function persistCookies(db: WorkerConnection, jar: CookieJar, cookies: Cookie[]): Promise<void> {
|
||||||
db: WorkerConnection,
|
|
||||||
jar: CookieJarModel,
|
|
||||||
cookies: unknown[],
|
|
||||||
): Promise<void> {
|
|
||||||
// The desktop compares before writing so a jar edited mid-send isn't clobbered
|
// The desktop compares before writing so a jar edited mid-send isn't clobbered
|
||||||
// by an unchanged copy. Structural equality is enough here: cookies are plain
|
// by an unchanged copy. Structural equality is enough here: cookies are plain
|
||||||
// data and the proxy hands back the whole jar.
|
// data and the proxy hands back the whole jar.
|
||||||
|
|||||||
Reference in New Issue
Block a user