Skip to content

add graphiql-desktop standalone Electron app - #4467

Draft
trevor-scheer wants to merge 11 commits into
mainfrom
trevor/graphiql-desktop
Draft

add graphiql-desktop standalone Electron app#4467
trevor-scheer wants to merge 11 commits into
mainfrom
trevor/graphiql-desktop

Conversation

@trevor-scheer

Copy link
Copy Markdown
Contributor

No description provided.

Standalone Electron GraphiQL: renderer is a small React app with an
endpoint bar over `<GraphiQL>`, GraphQL requests run in the main process
over IPC so they aren't subject to browser CORS. Renderer is served from
a privileged `graphiql-desktop://` scheme (real origin for localStorage +
monaco workers) instead of `file://`. Packaging/e2e/CI comes later.
Lowercase incoming header keys before merging with the lowercase
defaults, otherwise a conventionally-cased `Content-Type` from GraphiQL's
headers editor survives alongside `content-type` and fetch's `Headers`
comma-joins them instead of overriding. Also reject backslashes in the
decoded request path in the `graphiql-desktop://` handler (Windows
packaging is coming, and `\` isn't a separator to a POSIX join/resolve),
and revert `tsgo` invocations in package.json back to bare commands to
match every sibling package — turbo resolves them fine.
…dy vs missing-body

Pull the pure request-path -> file-path resolution (decode, backslash
reject, traversal containment, /->index.html, MIME lookup) out of
main.ts into resolve-renderer-path.ts with no Electron import, and fix
the containment check to use path.relative instead of a POSIX-hardcoded
`/` suffix — the old check silently 404'd every asset on Windows, where
path.resolve yields backslash paths. New tests run the containment logic
against both path.posix and path.win32 so that's actually asserted.

Also: App.tsx's fetcher treated an empty-but-successful 200 the same as
a missing response body (`!result.text`) — check `=== undefined`
instead so an empty body still reports its status. Plus a comment on
why GraphiQL remounts by `key={endpoint}`.
Config lives in electron-builder.yml (not package.json's build field, to
avoid confusion with the build script). Targets: dmg+zip for mac
(arm64+x64), AppImage+deb for linux (AppImage arm64+x64, deb x64), nsis for
win. Builds are unsigned (identity: null) — intentional for now.

electronVersion is pinned explicitly since electron-builder needs an exact
version to download matching platform binaries, but electron itself stays a
semver range in package.json.
Launches the built app via Electron's `_electron` API, points it at a local
mock GraphQL server (a real schema executed with graphql-js, so it answers
introspection generically instead of hand-maintaining canned JSON), and
asserts the endpoint bar wiring + IPC round-trip to the main process both
work. No display here, so it can't run locally — CI runs it under xvfb.
PR: new `desktop-e2e` job builds graphiql-desktop, runs its Playwright e2e
under xvfb, uploads traces on failure.

Release: mirrors the vsix pattern — a `desktop-published` output on the
release job, gated on the changesets output containing
"name":"graphiql-desktop", feeding a new `attach-desktop-artifacts` job that
builds installers on each OS (mac/linux/win matrix) and uploads them plus a
SHA256SUMS file to the GitHub release via scripts/release-desktop.mts.

Also updates the README (downloads, packaging, e2e sections) and adds
words electron-builder/playwright brought in to the cspell wordlist.
@changeset-bot

changeset-bot Bot commented Aug 25, 2026

Copy link
Copy Markdown

🦋 Changeset detected

Latest commit: 2235549

The changes in this PR will be included in the next version bump.

This PR includes changesets to release 1 package
Name Type
graphiql-desktop Minor

Not sure what this means? Click here to learn what changesets are.

Click here if you're a maintainer who wants to add another changeset to this PR


async function readVersion(): Promise<string> {
const json = await readFile(`packages/${PACKAGE_NAME}/package.json`, 'utf8');
return (JSON.parse(json) as { version: string }).version;

@dimaMachina dimaMachina Aug 25, 2026

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Use directly import with assert type json?

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.

2 participants