mirror of
https://github.com/mountain-loop/yaak.git
synced 2026-07-05 04:21:50 +02:00
Compare commits
6 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| e7a0a6077e | |||
| e52853cc2d | |||
| 851d0a26f0 | |||
| 78de83c754 | |||
| 9f3fd46d49 | |||
| 6c42b27edb |
@@ -39,18 +39,18 @@ jobs:
|
|||||||
targets: ""
|
targets: ""
|
||||||
- platform: "ubuntu-22.04"
|
- platform: "ubuntu-22.04"
|
||||||
args: >-
|
args: >-
|
||||||
--bundles appimage
|
--bundles deb
|
||||||
--config ./tauri.release.conf.json
|
--config ./tauri.release.conf.json
|
||||||
--config '{"productName":"yaak-cef","mainBinaryName":"yaak-cef","identifier":"app.yaak.desktop.cef","build":{"features":["license","cef"]},"bundle":{"createUpdaterArtifacts":false,"linux":{"appimage":{"files":{"/usr/lib/libfreebl3.chk":"/usr/lib/x86_64-linux-gnu/libfreebl3.chk","/usr/lib/libfreebl3.so":"/usr/lib/x86_64-linux-gnu/libfreebl3.so","/usr/lib/libfreeblpriv3.chk":"/usr/lib/x86_64-linux-gnu/libfreeblpriv3.chk","/usr/lib/libfreeblpriv3.so":"/usr/lib/x86_64-linux-gnu/libfreeblpriv3.so","/usr/lib/libsoftokn3.chk":"/usr/lib/x86_64-linux-gnu/nss/libsoftokn3.chk","/usr/lib/libsoftokn3.so":"/usr/lib/x86_64-linux-gnu/nss/libsoftokn3.so","/usr/lib/nss/libfreebl3.chk":"/usr/lib/x86_64-linux-gnu/nss/libfreebl3.chk","/usr/lib/nss/libfreebl3.so":"/usr/lib/x86_64-linux-gnu/nss/libfreebl3.so","/usr/lib/nss/libfreeblpriv3.chk":"/usr/lib/x86_64-linux-gnu/nss/libfreeblpriv3.chk","/usr/lib/nss/libfreeblpriv3.so":"/usr/lib/x86_64-linux-gnu/nss/libfreeblpriv3.so","/usr/lib/nss/libnssckbi.so":"/usr/lib/x86_64-linux-gnu/nss/libnssckbi.so","/usr/lib/nss/libnssdbm3.chk":"/usr/lib/x86_64-linux-gnu/nss/libnssdbm3.chk","/usr/lib/nss/libnssdbm3.so":"/usr/lib/x86_64-linux-gnu/nss/libnssdbm3.so","/usr/lib/nss/libsoftokn3.chk":"/usr/lib/x86_64-linux-gnu/nss/libsoftokn3.chk","/usr/lib/nss/libsoftokn3.so":"/usr/lib/x86_64-linux-gnu/nss/libsoftokn3.so"}}}}}'
|
--config '{"productName":"yaak-cef","mainBinaryName":"yaak-cef","identifier":"app.yaak.desktop.cef","build":{"features":["license","cef"]},"bundle":{"createUpdaterArtifacts":false}}'
|
||||||
yaak_arch: "x64"
|
yaak_arch: "x64"
|
||||||
os: "ubuntu"
|
os: "ubuntu"
|
||||||
runtime: "cef"
|
runtime: "cef"
|
||||||
targets: ""
|
targets: ""
|
||||||
- platform: "ubuntu-22.04-arm"
|
- platform: "ubuntu-22.04-arm"
|
||||||
args: >-
|
args: >-
|
||||||
--bundles appimage
|
--bundles deb
|
||||||
--config ./tauri.release.conf.json
|
--config ./tauri.release.conf.json
|
||||||
--config '{"productName":"yaak-cef","mainBinaryName":"yaak-cef","identifier":"app.yaak.desktop.cef","build":{"features":["license","cef"]},"bundle":{"createUpdaterArtifacts":false,"linux":{"appimage":{"files":{"/usr/lib/libfreebl3.chk":"/usr/lib/aarch64-linux-gnu/libfreebl3.chk","/usr/lib/libfreebl3.so":"/usr/lib/aarch64-linux-gnu/libfreebl3.so","/usr/lib/libfreeblpriv3.chk":"/usr/lib/aarch64-linux-gnu/libfreeblpriv3.chk","/usr/lib/libfreeblpriv3.so":"/usr/lib/aarch64-linux-gnu/libfreeblpriv3.so","/usr/lib/libsoftokn3.chk":"/usr/lib/aarch64-linux-gnu/nss/libsoftokn3.chk","/usr/lib/libsoftokn3.so":"/usr/lib/aarch64-linux-gnu/nss/libsoftokn3.so","/usr/lib/nss/libfreebl3.chk":"/usr/lib/aarch64-linux-gnu/nss/libfreebl3.chk","/usr/lib/nss/libfreebl3.so":"/usr/lib/aarch64-linux-gnu/nss/libfreebl3.so","/usr/lib/nss/libfreeblpriv3.chk":"/usr/lib/aarch64-linux-gnu/nss/libfreeblpriv3.chk","/usr/lib/nss/libfreeblpriv3.so":"/usr/lib/aarch64-linux-gnu/nss/libfreeblpriv3.so","/usr/lib/nss/libnssckbi.so":"/usr/lib/aarch64-linux-gnu/nss/libnssckbi.so","/usr/lib/nss/libnssdbm3.chk":"/usr/lib/aarch64-linux-gnu/nss/libnssdbm3.chk","/usr/lib/nss/libnssdbm3.so":"/usr/lib/aarch64-linux-gnu/nss/libnssdbm3.so","/usr/lib/nss/libsoftokn3.chk":"/usr/lib/aarch64-linux-gnu/nss/libsoftokn3.chk","/usr/lib/nss/libsoftokn3.so":"/usr/lib/aarch64-linux-gnu/nss/libsoftokn3.so"}}}}}'
|
--config '{"productName":"yaak-cef","mainBinaryName":"yaak-cef","identifier":"app.yaak.desktop.cef","build":{"features":["license","cef"]},"bundle":{"createUpdaterArtifacts":false}}'
|
||||||
yaak_arch: "arm64"
|
yaak_arch: "arm64"
|
||||||
os: "ubuntu"
|
os: "ubuntu"
|
||||||
runtime: "cef"
|
runtime: "cef"
|
||||||
@@ -190,6 +190,22 @@ jobs:
|
|||||||
projectPath: ./crates-tauri/yaak-app-client
|
projectPath: ./crates-tauri/yaak-app-client
|
||||||
args: "${{ matrix.args }}"
|
args: "${{ matrix.args }}"
|
||||||
|
|
||||||
|
- name: Build and upload CEF tarball from deb (Linux only)
|
||||||
|
if: matrix.os == 'ubuntu' && matrix.runtime == 'cef'
|
||||||
|
env:
|
||||||
|
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||||
|
run: |
|
||||||
|
set -euo pipefail
|
||||||
|
deb=$(find target/release/bundle/deb -maxdepth 1 -type f -name '*.deb' | head -n 1)
|
||||||
|
version="${GITHUB_REF_NAME#v}"
|
||||||
|
extract_dir="target/release/bundle/deb/yaak-cef-linux-${{ matrix.yaak_arch }}"
|
||||||
|
tarball="target/release/bundle/deb/yaak-cef_${version}_linux_${{ matrix.yaak_arch }}.tar.gz"
|
||||||
|
rm -rf "$extract_dir"
|
||||||
|
mkdir -p "$extract_dir"
|
||||||
|
dpkg-deb -x "$deb" "$extract_dir"
|
||||||
|
tar -C "$extract_dir" -czf "$tarball" .
|
||||||
|
gh release upload "${{ github.ref_name }}" "$tarball" --clobber
|
||||||
|
|
||||||
# Build a per-machine NSIS installer for enterprise deployment (PDQ, SCCM, Intune)
|
# Build a per-machine NSIS installer for enterprise deployment (PDQ, SCCM, Intune)
|
||||||
- name: Build and upload machine-wide installer (Windows only)
|
- name: Build and upload machine-wide installer (Windows only)
|
||||||
if: matrix.os == 'windows'
|
if: matrix.os == 'windows'
|
||||||
|
|||||||
@@ -2,7 +2,7 @@ name: Release CLI to NPM
|
|||||||
|
|
||||||
on:
|
on:
|
||||||
push:
|
push:
|
||||||
tags: [yaak-cli-*]
|
tags: [v*]
|
||||||
workflow_dispatch:
|
workflow_dispatch:
|
||||||
inputs:
|
inputs:
|
||||||
version:
|
version:
|
||||||
@@ -118,7 +118,7 @@ jobs:
|
|||||||
if [ "${{ github.event_name }}" = "workflow_dispatch" ]; then
|
if [ "${{ github.event_name }}" = "workflow_dispatch" ]; then
|
||||||
VERSION="$WORKFLOW_VERSION"
|
VERSION="$WORKFLOW_VERSION"
|
||||||
else
|
else
|
||||||
VERSION="${GITHUB_REF_NAME#yaak-cli-}"
|
VERSION="${GITHUB_REF_NAME}"
|
||||||
fi
|
fi
|
||||||
VERSION="${VERSION#v}"
|
VERSION="${VERSION#v}"
|
||||||
echo "Building yaak version: $VERSION"
|
echo "Building yaak version: $VERSION"
|
||||||
@@ -175,7 +175,7 @@ jobs:
|
|||||||
if [ "${{ github.event_name }}" = "workflow_dispatch" ]; then
|
if [ "${{ github.event_name }}" = "workflow_dispatch" ]; then
|
||||||
VERSION="$WORKFLOW_VERSION"
|
VERSION="$WORKFLOW_VERSION"
|
||||||
else
|
else
|
||||||
VERSION="${GITHUB_REF_NAME#yaak-cli-}"
|
VERSION="${GITHUB_REF_NAME}"
|
||||||
fi
|
fi
|
||||||
VERSION="${VERSION#v}"
|
VERSION="${VERSION#v}"
|
||||||
if [[ "$VERSION" == *-* ]]; then
|
if [[ "$VERSION" == *-* ]]; then
|
||||||
|
|||||||
@@ -10,6 +10,7 @@ import { DismissibleBanner } from "./core/DismissibleBanner";
|
|||||||
const COMMERCIAL_USE_SNOOZE_MS = 7 * 24 * 60 * 60 * 1000;
|
const COMMERCIAL_USE_SNOOZE_MS = 7 * 24 * 60 * 60 * 1000;
|
||||||
const COMMERCIAL_USE_BANNER_MESSAGE =
|
const COMMERCIAL_USE_BANNER_MESSAGE =
|
||||||
"Personal use of Yaak is free. If you’re using Yaak at work, please purchase a license.";
|
"Personal use of Yaak is free. If you’re using Yaak at work, please purchase a license.";
|
||||||
|
const hiddenBanner = <span aria-hidden className="block h-0 w-0 shrink-0 overflow-hidden" />;
|
||||||
|
|
||||||
export function CommercialUseBanner({
|
export function CommercialUseBanner({
|
||||||
source,
|
source,
|
||||||
@@ -55,7 +56,7 @@ export function CommercialUseBanner({
|
|||||||
}, [setSnoozedAt, snoozed, source]);
|
}, [setSnoozedAt, snoozed, source]);
|
||||||
|
|
||||||
if (!visible || isSnoozeLoading || (snoozed && !snoozeStartedRef.current)) {
|
if (!visible || isSnoozeLoading || (snoozed && !snoozeStartedRef.current)) {
|
||||||
return null;
|
return hiddenBanner;
|
||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
|||||||
@@ -20,6 +20,7 @@ import { deepEqualAtom } from "../lib/atoms";
|
|||||||
import { languageFromContentType } from "../lib/contentType";
|
import { languageFromContentType } from "../lib/contentType";
|
||||||
import { generateId } from "../lib/generateId";
|
import { generateId } from "../lib/generateId";
|
||||||
import { extractPathPlaceholders } from "../lib/pathPlaceholders";
|
import { extractPathPlaceholders } from "../lib/pathPlaceholders";
|
||||||
|
import { convertRequestBody } from "../lib/requestBodyConversion";
|
||||||
import {
|
import {
|
||||||
BODY_TYPE_BINARY,
|
BODY_TYPE_BINARY,
|
||||||
BODY_TYPE_FORM_MULTIPART,
|
BODY_TYPE_FORM_MULTIPART,
|
||||||
@@ -195,7 +196,14 @@ export function HttpRequestPane({ style, fullHeight, className, activeRequest }:
|
|||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
const patch: Partial<HttpRequest> = { bodyType };
|
const patch: Partial<HttpRequest> = {
|
||||||
|
bodyType,
|
||||||
|
body: convertRequestBody({
|
||||||
|
body: activeRequest.body,
|
||||||
|
fromBodyType: activeRequest.bodyType,
|
||||||
|
toBodyType: bodyType,
|
||||||
|
}),
|
||||||
|
};
|
||||||
let newContentType: string | null | undefined;
|
let newContentType: string | null | undefined;
|
||||||
if (bodyType === BODY_TYPE_NONE) {
|
if (bodyType === BODY_TYPE_NONE) {
|
||||||
newContentType = null;
|
newContentType = null;
|
||||||
|
|||||||
@@ -14,6 +14,7 @@ import { Editor } from "../core/Editor/LazyEditor";
|
|||||||
import { Banner, FormattedError, Icon } from "@yaakapp-internal/ui";
|
import { Banner, FormattedError, Icon } from "@yaakapp-internal/ui";
|
||||||
import { Separator } from "../core/Separator";
|
import { Separator } from "../core/Separator";
|
||||||
import { tryFormatGraphql } from "../../lib/formatters";
|
import { tryFormatGraphql } from "../../lib/formatters";
|
||||||
|
import { normalizeGraphQLBody } from "../../lib/requestBodyConversion";
|
||||||
import { showGraphQLDocExplorerAtom } from "./graphqlAtoms";
|
import { showGraphQLDocExplorerAtom } from "./graphqlAtoms";
|
||||||
|
|
||||||
type Props = Pick<EditorProps, "heightMode" | "className" | "forceUpdateKey"> & {
|
type Props = Pick<EditorProps, "heightMode" | "className" | "forceUpdateKey"> & {
|
||||||
@@ -38,17 +39,7 @@ function GraphQLEditorInner({ request, onChange, baseRequest, ...extraEditorProp
|
|||||||
const [currentBody, setCurrentBody] = useStateWithDeps<{
|
const [currentBody, setCurrentBody] = useStateWithDeps<{
|
||||||
query: string;
|
query: string;
|
||||||
variables: string | undefined;
|
variables: string | undefined;
|
||||||
}>(() => {
|
}>(() => normalizeGraphQLBody(request.body), [extraEditorProps.forceUpdateKey]);
|
||||||
// Migrate text bodies to GraphQL format
|
|
||||||
// NOTE: This is how GraphQL used to be stored
|
|
||||||
if ("text" in request.body) {
|
|
||||||
const b = tryParseJson(request.body.text, {});
|
|
||||||
const variables = JSON.stringify(b.variables || undefined, null, 2);
|
|
||||||
return { query: b.query ?? "", variables };
|
|
||||||
}
|
|
||||||
|
|
||||||
return { query: request.body.query ?? "", variables: request.body.variables ?? "" };
|
|
||||||
}, [extraEditorProps.forceUpdateKey]);
|
|
||||||
|
|
||||||
const [isDocOpenRecord, setGraphqlDocStateAtomValue] = useAtom(showGraphQLDocExplorerAtom);
|
const [isDocOpenRecord, setGraphqlDocStateAtomValue] = useAtom(showGraphQLDocExplorerAtom);
|
||||||
const isDocOpen = isDocOpenRecord[request.id] !== undefined;
|
const isDocOpen = isDocOpenRecord[request.id] !== undefined;
|
||||||
@@ -236,11 +227,3 @@ function GraphQLEditorInner({ request, onChange, baseRequest, ...extraEditorProp
|
|||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
function tryParseJson(text: string, fallback: unknown) {
|
|
||||||
try {
|
|
||||||
return JSON.parse(text);
|
|
||||||
} catch {
|
|
||||||
return fallback;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -0,0 +1,103 @@
|
|||||||
|
import { describe, expect, test } from "vite-plus/test";
|
||||||
|
import {
|
||||||
|
BODY_TYPE_FORM_URLENCODED,
|
||||||
|
BODY_TYPE_GRAPHQL,
|
||||||
|
BODY_TYPE_JSON,
|
||||||
|
BODY_TYPE_OTHER,
|
||||||
|
BODY_TYPE_XML,
|
||||||
|
} from "./model_util";
|
||||||
|
import { convertRequestBody } from "./requestBodyConversion";
|
||||||
|
|
||||||
|
describe("convertRequestBody", () => {
|
||||||
|
test("converts imported JSON GraphQL bodies to GraphQL shape", () => {
|
||||||
|
const body = convertRequestBody({
|
||||||
|
fromBodyType: BODY_TYPE_JSON,
|
||||||
|
toBodyType: BODY_TYPE_GRAPHQL,
|
||||||
|
body: {
|
||||||
|
text: JSON.stringify({
|
||||||
|
query: "query GetUser($id: ID!) { user(id: $id) { name } }",
|
||||||
|
variables: { id: "123" },
|
||||||
|
}),
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
expect(body).toEqual({
|
||||||
|
query: "query GetUser($id: ID!) { user(id: $id) { name } }",
|
||||||
|
variables: '{\n "id": "123"\n}',
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
test("converts GraphQL bodies to JSON text", () => {
|
||||||
|
const body = convertRequestBody({
|
||||||
|
fromBodyType: BODY_TYPE_GRAPHQL,
|
||||||
|
toBodyType: BODY_TYPE_JSON,
|
||||||
|
body: {
|
||||||
|
query: "query GetUser($id: ID!) { user(id: $id) { name } }",
|
||||||
|
variables: '{ "id": "123" }',
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
expect(body).toEqual({
|
||||||
|
text: JSON.stringify(
|
||||||
|
{
|
||||||
|
query: "query GetUser($id: ID!) { user(id: $id) { name } }",
|
||||||
|
variables: { id: "123" },
|
||||||
|
},
|
||||||
|
null,
|
||||||
|
2,
|
||||||
|
),
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
test("converts urlencoded forms to urlencoded text for text-like bodies", () => {
|
||||||
|
const body = convertRequestBody({
|
||||||
|
fromBodyType: BODY_TYPE_FORM_URLENCODED,
|
||||||
|
toBodyType: BODY_TYPE_OTHER,
|
||||||
|
body: {
|
||||||
|
form: [
|
||||||
|
{ enabled: true, name: "basic", value: "aaa" },
|
||||||
|
{ enabled: true, name: "funky stuff", value: "*)%&#$)@ *$#)@&" },
|
||||||
|
{ enabled: false, name: "disabled", value: "hidden" },
|
||||||
|
{ enabled: true, name: "", value: "unnamed" },
|
||||||
|
],
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
expect(body).toEqual({
|
||||||
|
text: "basic=aaa&funky+stuff=*%29%25%26%23%24%29%40+*%24%23%29%40%26",
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
test("converts urlencoded forms to JSON text for JSON bodies", () => {
|
||||||
|
const body = convertRequestBody({
|
||||||
|
fromBodyType: BODY_TYPE_FORM_URLENCODED,
|
||||||
|
toBodyType: BODY_TYPE_JSON,
|
||||||
|
body: {
|
||||||
|
form: [
|
||||||
|
{ enabled: true, name: "tag", value: "one" },
|
||||||
|
{ enabled: true, name: "tag", value: "two" },
|
||||||
|
{ enabled: true, name: "limit", value: "10" },
|
||||||
|
],
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
expect(body).toEqual({
|
||||||
|
text: JSON.stringify({ tag: ["one", "two"], limit: "10" }, null, 2),
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
test("converts urlencoded text to form pairs", () => {
|
||||||
|
const body = convertRequestBody({
|
||||||
|
fromBodyType: BODY_TYPE_XML,
|
||||||
|
toBodyType: BODY_TYPE_FORM_URLENCODED,
|
||||||
|
body: { text: "a=1&b=two+words" },
|
||||||
|
});
|
||||||
|
|
||||||
|
expect(body).toEqual({
|
||||||
|
form: [
|
||||||
|
{ enabled: true, name: "a", value: "1" },
|
||||||
|
{ enabled: true, name: "b", value: "two words" },
|
||||||
|
],
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
@@ -0,0 +1,224 @@
|
|||||||
|
import type { HttpRequest } from "@yaakapp-internal/models";
|
||||||
|
import {
|
||||||
|
BODY_TYPE_BINARY,
|
||||||
|
BODY_TYPE_FORM_MULTIPART,
|
||||||
|
BODY_TYPE_FORM_URLENCODED,
|
||||||
|
BODY_TYPE_GRAPHQL,
|
||||||
|
BODY_TYPE_JSON,
|
||||||
|
BODY_TYPE_NONE,
|
||||||
|
} from "./model_util";
|
||||||
|
|
||||||
|
type Body = HttpRequest["body"];
|
||||||
|
type BodyType = HttpRequest["bodyType"];
|
||||||
|
type GraphQLBody = {
|
||||||
|
query: string;
|
||||||
|
variables: string | undefined;
|
||||||
|
};
|
||||||
|
|
||||||
|
export function convertRequestBody({
|
||||||
|
body,
|
||||||
|
fromBodyType,
|
||||||
|
toBodyType,
|
||||||
|
}: {
|
||||||
|
body: Body;
|
||||||
|
fromBodyType: BodyType;
|
||||||
|
toBodyType: BodyType;
|
||||||
|
}): Body {
|
||||||
|
if (toBodyType === BODY_TYPE_NONE) {
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
|
||||||
|
if (toBodyType === BODY_TYPE_GRAPHQL) {
|
||||||
|
return toGraphQLBody(body);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (toBodyType === BODY_TYPE_FORM_URLENCODED || toBodyType === BODY_TYPE_FORM_MULTIPART) {
|
||||||
|
return toFormBody(body);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (toBodyType === BODY_TYPE_BINARY) {
|
||||||
|
return typeof body.filePath === "string" ? { filePath: body.filePath } : {};
|
||||||
|
}
|
||||||
|
|
||||||
|
return toTextBody(body, fromBodyType, toBodyType);
|
||||||
|
}
|
||||||
|
|
||||||
|
export function normalizeGraphQLBody(body: Body): GraphQLBody {
|
||||||
|
return toGraphQLBody(body);
|
||||||
|
}
|
||||||
|
|
||||||
|
function toGraphQLBody(body: Body): GraphQLBody {
|
||||||
|
if (typeof body.query === "string") {
|
||||||
|
return {
|
||||||
|
query: body.query,
|
||||||
|
variables: typeof body.variables === "string" ? body.variables : undefined,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
if (typeof body.text === "string") {
|
||||||
|
const parsed = parseJsonObject(body.text);
|
||||||
|
if (parsed != null) {
|
||||||
|
const query = typeof parsed.query === "string" ? parsed.query : "";
|
||||||
|
const variables =
|
||||||
|
parsed.variables == null ? undefined : JSON.stringify(parsed.variables, null, 2);
|
||||||
|
|
||||||
|
return { query, variables };
|
||||||
|
}
|
||||||
|
|
||||||
|
return { query: body.text, variables: undefined };
|
||||||
|
}
|
||||||
|
|
||||||
|
return { query: "", variables: undefined };
|
||||||
|
}
|
||||||
|
|
||||||
|
function toFormBody(body: Body): Body {
|
||||||
|
if (Array.isArray(body.form)) {
|
||||||
|
return {
|
||||||
|
form: body.form.map((p) => ({
|
||||||
|
enabled: p.enabled !== false,
|
||||||
|
name: typeof p.name === "string" ? p.name : "",
|
||||||
|
value: stringifyFormValue(p.value ?? p.file),
|
||||||
|
contentType: typeof p.contentType === "string" ? p.contentType : undefined,
|
||||||
|
filename: typeof p.filename === "string" ? p.filename : undefined,
|
||||||
|
file: typeof p.file === "string" ? p.file : undefined,
|
||||||
|
id: typeof p.id === "string" ? p.id : undefined,
|
||||||
|
})),
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
if (typeof body.text === "string") {
|
||||||
|
const parsed = parseJsonObject(body.text);
|
||||||
|
if (parsed != null) {
|
||||||
|
return { form: objectToFormPairs(parsed) };
|
||||||
|
}
|
||||||
|
|
||||||
|
return { form: urlEncodedTextToFormPairs(body.text) };
|
||||||
|
}
|
||||||
|
|
||||||
|
if (typeof body.query === "string") {
|
||||||
|
return {
|
||||||
|
form: [
|
||||||
|
{ enabled: true, name: "query", value: body.query },
|
||||||
|
...(typeof body.variables === "string"
|
||||||
|
? [{ enabled: true, name: "variables", value: body.variables }]
|
||||||
|
: []),
|
||||||
|
],
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
return { form: [] };
|
||||||
|
}
|
||||||
|
|
||||||
|
function toTextBody(body: Body, fromBodyType: BodyType, toBodyType: BodyType): Body {
|
||||||
|
const sendJsonComments =
|
||||||
|
typeof body.sendJsonComments === "boolean" ? { sendJsonComments: body.sendJsonComments } : {};
|
||||||
|
|
||||||
|
if (typeof body.text === "string") {
|
||||||
|
return { text: body.text, ...sendJsonComments };
|
||||||
|
}
|
||||||
|
|
||||||
|
if (Array.isArray(body.form)) {
|
||||||
|
if (toBodyType === BODY_TYPE_JSON) {
|
||||||
|
return { text: JSON.stringify(formBodyToObject(body.form), null, 2) };
|
||||||
|
}
|
||||||
|
|
||||||
|
return { text: formBodyToUrlEncodedText(body.form) };
|
||||||
|
}
|
||||||
|
|
||||||
|
if (typeof body.query === "string") {
|
||||||
|
if (toBodyType === BODY_TYPE_JSON || fromBodyType === BODY_TYPE_GRAPHQL) {
|
||||||
|
const value: Record<string, unknown> = { query: body.query };
|
||||||
|
if (typeof body.variables === "string" && body.variables.trim() !== "") {
|
||||||
|
value.variables = parseJson(body.variables) ?? body.variables;
|
||||||
|
}
|
||||||
|
|
||||||
|
return { text: JSON.stringify(value, null, 2) };
|
||||||
|
}
|
||||||
|
|
||||||
|
return { text: body.query };
|
||||||
|
}
|
||||||
|
|
||||||
|
if (typeof body.filePath === "string") {
|
||||||
|
return { text: body.filePath };
|
||||||
|
}
|
||||||
|
|
||||||
|
return { text: "" };
|
||||||
|
}
|
||||||
|
|
||||||
|
function formBodyToUrlEncodedText(form: unknown[]): string {
|
||||||
|
const params = new URLSearchParams();
|
||||||
|
|
||||||
|
for (const pair of form) {
|
||||||
|
if (!isRecord(pair)) continue;
|
||||||
|
if (pair.enabled === false) continue;
|
||||||
|
if (typeof pair.name !== "string" || pair.name === "") continue;
|
||||||
|
params.append(pair.name, stringifyFormValue(pair.value));
|
||||||
|
}
|
||||||
|
|
||||||
|
return params.toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
function urlEncodedTextToFormPairs(text: string) {
|
||||||
|
if (!text.includes("=") && !text.includes("&")) {
|
||||||
|
return [];
|
||||||
|
}
|
||||||
|
|
||||||
|
return Array.from(new URLSearchParams(text).entries()).map(([name, value]) => ({
|
||||||
|
enabled: true,
|
||||||
|
name,
|
||||||
|
value,
|
||||||
|
}));
|
||||||
|
}
|
||||||
|
|
||||||
|
function formBodyToObject(form: unknown[]) {
|
||||||
|
const result: Record<string, unknown> = {};
|
||||||
|
|
||||||
|
for (const pair of form) {
|
||||||
|
if (!isRecord(pair)) continue;
|
||||||
|
if (pair.enabled === false) continue;
|
||||||
|
if (typeof pair.name !== "string" || pair.name === "") continue;
|
||||||
|
|
||||||
|
const value = stringifyFormValue(pair.value);
|
||||||
|
if (pair.name in result) {
|
||||||
|
const existing = result[pair.name];
|
||||||
|
result[pair.name] = Array.isArray(existing) ? [...existing, value] : [existing, value];
|
||||||
|
} else {
|
||||||
|
result[pair.name] = value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
function objectToFormPairs(value: Record<string, unknown>) {
|
||||||
|
return Object.entries(value).flatMap(([name, rawValue]) => {
|
||||||
|
if (Array.isArray(rawValue)) {
|
||||||
|
return rawValue.map((item) => ({ enabled: true, name, value: stringifyFormValue(item) }));
|
||||||
|
}
|
||||||
|
|
||||||
|
return [{ enabled: true, name, value: stringifyFormValue(rawValue) }];
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
function stringifyFormValue(value: unknown): string {
|
||||||
|
if (value == null) return "";
|
||||||
|
if (typeof value === "string") return value;
|
||||||
|
return JSON.stringify(value);
|
||||||
|
}
|
||||||
|
|
||||||
|
function parseJsonObject(text: string): Record<string, unknown> | null {
|
||||||
|
const parsed = parseJson(text);
|
||||||
|
return isRecord(parsed) ? parsed : null;
|
||||||
|
}
|
||||||
|
|
||||||
|
function parseJson(text: string): unknown | null {
|
||||||
|
try {
|
||||||
|
return JSON.parse(text);
|
||||||
|
} catch {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function isRecord(value: unknown): value is Record<string, unknown> {
|
||||||
|
return value != null && typeof value === "object" && !Array.isArray(value);
|
||||||
|
}
|
||||||
@@ -1,4 +1,7 @@
|
|||||||
{
|
{
|
||||||
|
"build": {
|
||||||
|
"features": ["updater", "license", "wry"]
|
||||||
|
},
|
||||||
"app": {
|
"app": {
|
||||||
"security": {
|
"security": {
|
||||||
"capabilities": [
|
"capabilities": [
|
||||||
|
|||||||
Generated
+1
-1
@@ -83,7 +83,7 @@
|
|||||||
"@tauri-apps/cli": "npm:@tauri-apps/cli-cef@3.0.0-alpha.6",
|
"@tauri-apps/cli": "npm:@tauri-apps/cli-cef@3.0.0-alpha.6",
|
||||||
"@types/babel__core": "^7.20.5",
|
"@types/babel__core": "^7.20.5",
|
||||||
"@vitejs/plugin-react": "^6.0.1",
|
"@vitejs/plugin-react": "^6.0.1",
|
||||||
"@yaakapp/cli": "^0.5.1",
|
"@yaakapp/cli": "latest",
|
||||||
"babel-plugin-react-compiler": "^1.0.0",
|
"babel-plugin-react-compiler": "^1.0.0",
|
||||||
"dotenv-cli": "^11.0.0",
|
"dotenv-cli": "^11.0.0",
|
||||||
"nodejs-file-downloader": "^4.13.0",
|
"nodejs-file-downloader": "^4.13.0",
|
||||||
|
|||||||
+1
-1
@@ -116,7 +116,7 @@
|
|||||||
"@tauri-apps/cli": "npm:@tauri-apps/cli-cef@3.0.0-alpha.6",
|
"@tauri-apps/cli": "npm:@tauri-apps/cli-cef@3.0.0-alpha.6",
|
||||||
"@types/babel__core": "^7.20.5",
|
"@types/babel__core": "^7.20.5",
|
||||||
"@vitejs/plugin-react": "^6.0.1",
|
"@vitejs/plugin-react": "^6.0.1",
|
||||||
"@yaakapp/cli": "^0.5.1",
|
"@yaakapp/cli": "latest",
|
||||||
"babel-plugin-react-compiler": "^1.0.0",
|
"babel-plugin-react-compiler": "^1.0.0",
|
||||||
"dotenv-cli": "^11.0.0",
|
"dotenv-cli": "^11.0.0",
|
||||||
"nodejs-file-downloader": "^4.13.0",
|
"nodejs-file-downloader": "^4.13.0",
|
||||||
|
|||||||
Reference in New Issue
Block a user