Coder Social home page Coder Social logo

jsonnull / electron-trpc Goto Github PK

View Code? Open in Web Editor NEW
208.0 208.0 20.0 590 KB

Build type-safe Electron inter-process communication using tRPC

Home Page: https://www.electron-trpc.dev

License: MIT License

TypeScript 98.53% Nix 0.75% JavaScript 0.72%
electron hacktoberfest ipc trpc typescript

electron-trpc's People

Contributors

beeequeue avatar eslym avatar github-actions[bot] avatar joehartzell avatar jsonnull avatar nickymeuleman avatar renovate[bot] avatar skyrpex avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar

electron-trpc's Issues

No way to access window from request

I would like to add a route that toggles DevTools and in order to do that I need access to the BrowserWindow that the request was made from. It doesn't look like there is a way for this, which is kind of strange as I'm seeing loads of use-cases where you would need the instance of the BrowserWindow. Or have I missed something?

EDIT: Found the createContext property :)

Add README and package meta to published package

I just noticed that the npm page doesn't have the necessary details for the electron-trpc package since the README is in the root and I haven't included additional meta in the published package's package.json.

Remove `strict-peer-dependencies=false` when trpc v10 is released

In the beta versions of trpc v10, @trpc/react@next has a peer pin on beta 20 instead of beta 25 for the other @trpc packages. In order to stay on @next for all these packages, I'm leaving strict peer dependencies off for the project.

When trpc v10 releases, let's get back to strict peer deps.

Not compatible with default sandbox mode of Electron 20+

Since Electron 20, the sandbox option of window webPreferences has been set to true by default. This means that preload scripts can only use a small subset of the Electron and Node APIs. Specifically, require is polyfilled with a version that will only allow requiring a small subset of node core modules.

This causes a problem for this lib, since we need to require electron-trpc/main in the preload script, and then call exposeElectronTRPC().

Disabling the sandbox of course resolves this issue, but at the cost of losing the security benefits of sandboxing.

After a quick think about this I have two potential solutions:

  1. Advise users to process and bundle their preload script. This would inline the import of the constants, leaving only the allowed contextBridge code. This should be a documentation only change, perhaps based on a sample vite-plugin-electron config.
  2. Remove ELECTRON_TRPC_CHANNEL and make it up to the user to configure an appropriate and consistent channel across main, preload, and renderer. Then supply a copy/paste snippet for the preload file that only uses the contextBridge API. It would be helpful to export the RendererGlobalElectronTRPC type so consumers could at least match up with some sort of package API.

There may be other options I haven't considered.

Thanks for creating such a useful lib!

`process is not defined` after importing ipcLink in renderer

At first, that entire code works if I copy/paste it into my app. When I tried to use the npm package I faced with that issue:

CleanShot 2022-11-18 at 12 43 40@2x

I am using electron-react-boilerplate

I think it is caused because I am using import { ipcLink } from 'electron-trpc';. When I am trying to use import { ipcLink } from 'electron-trpc/renderer'; I am getting:

Module not found: Error: Package path ./renderer is not exported from package [...]/node_modules/electron-trpc

Query never resolves when the input is undefined

I'm consulting a query that does not have parameters this way:

trpc.endpoint.useQuery(undefined);

And it is never responding.

My current workaround is to send an empty object like this:

trpc.endpoint.useQuery({});

Improved Stack Trace

Is there a way to get a more detailed stack trace for an error that occurs during an electron-trpc call? For example, a Zod error results in this:

image

Matches.tsx:267 Uncaught TRPCClientError: [
  {
    "code": "invalid_type",
    "expected": "object",
    "received": "null",
    "path": [],
    "message": "Expected object, received null"
  }
]
    at _y.from (renderer.mjs:60:10)
    at Object.next (renderer.mjs:487:23)
    at V.M (renderer.mjs:469:21)
    at renderer.mjs:447:21

There's no line numbers in the stack trace that indicate where the error actually came from.

handleIPCMessage only sends replies to electron main frame

Summary

I have a use case that involves using iframes and tRPC to communicate between each frame and the main thread. After spending some time debugging it seems that handleIPCMessage replies to the sender using event.sender.send which will always reply to the main frame.

References

  • Electron Docs

    • To send an asynchronous message back to the sender, you can use event.reply(...). This helper method will automatically handle messages coming from frames that aren't the main frame (e.g. iframes) whereas event.sender.send(...) will always send to the main frame.

  • handleIPCMessage code

Solution

I think the solution here is pretty simple. handleIPCMessage should be able to use event.reply to respond to incoming events as stated by the Electron docs. This would also involve updating the types on the event parameters to use ipcMainEvent instead of IpcMainInvokeEvent.

Example

Current implementation

import { IpcMainInvokeEvent } from 'electron'
export async function handleIPCMessage<TRouter extends AnyRouter>({
  router,
  createContext,
  internalId,
  message,
  event,
  subscriptions,
}: {
  router: TRouter;
  createContext?: (opts: CreateContextOptions) => Promise<inferRouterContext<TRouter>>;
  internalId: string;
  message: ETRPCRequest;
  event: IpcMainInvokeEvent; // OLD
  subscriptions: Map<string, Unsubscribable>;
}) { 
// ...
}

Suggested change

import { IpcMainEvent } from 'electron'
export async function handleIPCMessage<TRouter extends AnyRouter>({
  router,
  createContext,
  internalId,
  message,
  event,
  subscriptions,
}: {
  router: TRouter;
  createContext?: (opts: CreateContextOptions) => Promise<inferRouterContext<TRouter>>;
  internalId: string;
  message: ETRPCRequest;
  event: IpcMainEvent; // NEW
  subscriptions: Map<string, Unsubscribable>;
}) { 
// ...
}

Contributing

Would be more than happy to make a PR with the suggested changes above.

Versions

  • electron-trpc: 0.5.0
  • electron: 24.4.1
  • node: 16.14.0
  • pnpm: 8.6.1

Dependency Dashboard

This issue lists Renovate updates and detected dependencies. Read the Dependency Dashboard docs to learn more.

Rate-Limited

These updates are currently rate-limited. Click on a checkbox below to force their creation now.

  • Update dependencies (@tanstack/react-query, superjson, zod)

Open

These updates have all been created already. Click a checkbox below to force a retry/rebase of any.

Detected dependencies

github-actions
.github/workflows/lint.yml
  • actions/checkout v3
  • pnpm/action-setup v2
  • actions/setup-node v3
.github/workflows/release.yml
  • actions/checkout v3
  • pnpm/action-setup v2
  • actions/setup-node v3
  • changesets/action v1
  • actions/checkout v3
  • pnpm/action-setup v2
  • actions/setup-node v3
  • changesets/action v1
.github/workflows/test.yml
  • actions/checkout v3
  • pnpm/action-setup v2
  • actions/setup-node v3
  • codecov/codecov-action v3
  • actions/checkout v3
  • pnpm/action-setup v2
  • actions/setup-node v3
npm
examples/basic-react-superjson/package.json
  • @tanstack/react-query ^4.29.14
  • @trpc/client 10.33.1
  • @trpc/react-query 10.33.1
  • @trpc/server 10.33.1
  • electron ^25.1.1
  • react ^18.2.0
  • react-dom ^18.2.0
  • superjson ^1.12.3
  • zod ^3.21.4
  • @types/node ^20.3.1
  • @types/react ^18.2.13
  • @types/react-dom ^18.2.6
  • @vitejs/plugin-react ^4.0.0
  • vite ^4.3.9
  • vite-plugin-electron ^0.12.0
examples/basic-react/package.json
  • @tanstack/react-query ^4.29.14
  • @trpc/client 10.33.1
  • @trpc/react-query 10.33.1
  • @trpc/server 10.33.1
  • electron ^25.1.1
  • react ^18.2.0
  • react-dom ^18.2.0
  • zod ^3.21.4
  • @types/node ^20.3.1
  • @types/react ^18.2.13
  • @types/react-dom ^18.2.6
  • @vitejs/plugin-react ^4.0.0
  • vite ^4.3.9
  • vite-plugin-electron ^0.12.0
package.json
  • @changesets/changelog-github ^0.4.8
  • @changesets/cli ^2.26.1
  • @playwright/test ^1.35.1
  • prettier ^2.8.8
  • typescript ^5.1.3
  • unocss ^0.54.0
  • vite ^4.3.9
  • vitepress 1.0.0-beta.7
  • vue ^3.3.4
  • node >=18
  • pnpm >=8
  • pnpm 8.6.11
packages/electron-trpc/package.json
  • debug ^4.3.4
  • @tanstack/react-query ^4.29.14
  • @trpc/client 10.33.1
  • @trpc/server 10.33.1
  • @types/debug ^4.1.8
  • @types/node ^20.3.1
  • @vitest/coverage-v8 ^0.34.0
  • builtin-modules ^3.3.0
  • dts-bundle-generator ^8.0.1
  • electron ^25.1.1
  • react ^18.2.0
  • react-dom ^18.2.0
  • superjson ^1.12.3
  • vite ^4.3.9
  • vite-plugin-commonjs-externals ^0.1.3
  • vitest ^0.34.0
  • zod ^3.21.4
  • @trpc/client >10.0.0
  • @trpc/server >10.0.0
  • electron >19.0.0

  • Check this box to trigger a request for Renovate to run again on this repository

`subscription.stop` method has no `input`, causing crash with superjson transformer

I noticed a crash when using this lib with superjson. The stack trace indicated that superjson.deserialize was being called with the input being undefined.

A little digging and console logging led me to notice that this was happening for subscription.stop methods (which are being emitted here: https://github.com/jsonnull/electron-trpc/blob/main/packages/electron-trpc/src/renderer/ipcLink.ts#L77-L80) because they don't have an input property.

Thus when the handleIPCOperation function picks this up on the main thread, it is calling deserialize on an empty object (here: https://github.com/jsonnull/electron-trpc/blob/main/packages/electron-trpc/src/main/handleIPCOperation.ts#L23).

Seems like this function needs to look for the presence of operation.input before calling deserialize, or else filter by the operation method if it is a stable API.

TRPC 11.x.x (next) introduces breaking changes that will break electron-trpc

One of the breaking changes involves transformers, the error manifests itself on client side as:

Uncaught TypeError: Cannot read properties of undefined (reading 'serialize')

With this line being at fault:

op.input = runtime.transformer.serialize(op.input);

I've forked the repository and resolved the compatibility issues with the next version of TRPC: mat-sz@994bd41

Since this is an unstable version of TRPC, I'm not submitting this as a pull request. If you'd like me to submit that in the future when 11.x.x becomes stable, please let me know; otherwise I'll continue maintaining this as a fork.

Support tRPC v10

Hi there!

As discussed on Twitter, I'd like to help move this package to support v10 of tRPC.
I've gotten it to work on my starter that ties together vite, electron, tRPC, and Prisma.
Currently, that uses a bunch of copy-pasted internal tRPC source code.

I saw you PRd trpc/trpc#2397 for v9, so something similar for v10 is probably needed if we want to avoid rewriting a bunch of tRPCs sourcecode.

I can PR a proof-of-concept at the end of the week if you're interested!
Or wait until v10 is out of beta, let me know!

How to use electron-trpc with Jest?

When I'm trying to run my jest tests I got this error:

Test suite failed to run

    Configuration error:

    Could not locate module electron-trpc/renderer mapped as:
    node_modules/electron-trpc/dist/renderer.

    Please check your configuration for these entries:
    {
      "moduleNameMapper": {
        "/^electron\-trpc\/renderer$/": "node_modules/electron-trpc/dist/renderer"
      },
      "resolver": undefined
    }

      2 | import { QueryClient, QueryClientProvider } from '@tanstack/react-query';
      3 | import { render, RenderOptions } from '@testing-library/react';
    > 4 | import { ipcLink } from 'electron-trpc/renderer';
        | ^
      5 | import { ReactElement, useState } from 'react';
      6 | import { MemoryRouter } from 'react-router-dom';
      7 |

      at createNoMappedModuleFoundError (../../node_modules/jest-resolve/build/resolver.js:759:17)
      at Object.<anonymous> (test-utils/TestWrapper.tsx:4:1)

Any ideas on how to resole this issue?

Subscription returns `undefined` with superjson

If is use superjson as transformer, this procedure:

open: publicProcedure.subscription(async () => {
  return observable<{ open: boolean }>((emit) => {
    const setFileopenVisible = (data: boolean) => {
      console.log("setFileopenVisible", data);
        emit.next({ open: data });
    };
    ee.on("setFileopenVisible", setFileopenVisible);
    return () => {
      ee.off("setFileopenVisible", setFileopenVisible);
    };
  })
}),

returns undefined when called here:

trpc.ui.openFileVisible.open.useSubscription(undefined, {
  onData: (data) => {
    console.log("data", data);
  },
});

The data is properly returned, if I remove the transformer from the api and the client.

Using electron-trpc version 0.4.2.

Cannot find module error

Hi,

For some reason all the imports in the README fail.

// All of the following give "Cannot find module..." error
import { createIPCHandler } from "electron-trpc/main";
import { exposeElectronTRPC } from "electron-trpc/main";
import { ipcLink } from "electron-trpc/renderer";

Importing from /dist or /src compiles, but fails at runtime with the same error.

I'm using version 0.2.1 of electron-trpc.

Subscriptions do not cleanup

Using your example repo, I noticed that subscriptions do not clean up. Eventually I get the following error:

[1] (node:22811) MaxListenersExceededWarning: Possible EventEmitter memory leak detected. 11 output listeners added to [EventEmitter]. Use emitter.setMaxListeners() to increase limit
[1] (Use `Electron --trace-warnings ...` to show where the warning was created)
[1] (node:22811) MaxListenersExceededWarning: Possible EventEmitter memory leak detected. 11 destroyed listeners added to [EventEmitter]. Use emitter.setMaxListeners() to increase limit
[1] subscribed

Add support for different router types

Hi,

In my application I have two windows with different type of routers. For both windows I'm trying to register IPC handlers using createIPCHandler({router: router1, windows: [win1]}) and createIPCHandler({router: router2, windows: [win2]}).
When I try to invoke some query from win1, I'm getting the following error:

TRPCClientError: No "query"-procedure on path "getSomething"

I assume it happens because both routers replies to the same query simultaneously which brings to race condition. In my case, router2 is trying to handle a query that can be handled only by router1.
It would be nice to check event.source inside ipcMain.on message handler and process only those messages which come from BrowserWindow passed in windows property of createIPCHandler call.

Risk for memory leaks with subscriptions on page reload

Sometimes during development it's necessary to fully reload the page. I created this little subscription procedure to see whether there is a risk for memory leaks. And yes, there is. Check the code below:

let count = 0;

export const testSubscription = publicProcedure.subscription(async () => {
  return observable<string>(() => {
    count ++;
    console.log(count);

    return () => {
      count --;
    };
  });
});

Whenever this procedure is being subscribed to, count will increment or decrement to keep track of amount of active subscriptions. However, if you do a page reload, there is no cleanup process being made and count keeps increasing.

[Discussion] Roadmap to v1.0.0

This is a discussion around what the roadmap to v1.0.0 looks like. I really enjoy this library and believe it's the best way to work with ipc communication. I would like to contribute more to this project but don't know what the roadmap looks like.

Was hoping we could start a discussion specifically with @jsonnull around what work needs to be done to push this to v1.0.0. More than happy to help with planning, implementation, etc...

Thanks in advance for all the work on this project thus far and looking forward to future discussions!

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.