SQL with Prisma under Electron



我的主要目标是创建一个在SQLite数据库中本地存储数据的电子应用程序(Windows)。由于类型安全,我选择使用Prisma框架而不是其他SQLite框架。我选择了这个电子样本项目,现在尝试包括Prisma。根据我尝试的不同,会出现不同的问题。

1。PrismaClient无法在浏览器中运行

我执行了npx prisma generate,然后尝试通过按钮执行此函数:

import { PrismaClient } from '@prisma/client';
onSqlTestAction(): void {
const prisma = new PrismaClient();
const newTestObject = prisma.testTable.create(
{
data: {
value: "TestValue"
}
}
);
}

当在电子中执行这个时,我得到这个:

core.js:6456 ERROR Error: PrismaClient is unable to be run in the browser.
In case this error is unexpected for you, please report it in https://github.com/prisma/prisma/issues
at new PrismaClient (index-browser.js:93)
at HomeComponent.onSqlTestAction (home.component.ts:19)
at HomeComponent_Template_button_click_7_listener (template.html:7)
at executeListenerWithErrorHandling (core.js:15281)
at wrapListenerIn_markDirtyAndPreventDefault (core.js:15319)
at HTMLButtonElement.<anonymous> (platform-browser.js:568)
at ZoneDelegate.invokeTask (zone.js:406)
at Object.onInvokeTask (core.js:28666)
at ZoneDelegate.invokeTask (zone.js:405)
at Zone.runTask (zone.js:178)
在某种程度上,Prisma不能在浏览器中运行似乎是合乎逻辑的。但我实际上是用嵌入了浏览器的电子构建了一个本地应用程序。这似乎是一个漏洞。

2。突破性的变化:webpack <5用于包含多边形

所以我发现了这个问题:如何使用Prisma与Electron这似乎正是我要找的。但是错误信息是不同的(没有找到Debian二进制文件)。提供的解决方案是将棱柱工件生成到src文件夹中而不是node_modules文件夹中-这导致19个多边形填充错误。一个例子:

./src/database/generated/index.js:20:11-26 - Error: Module not found: Error: Can't resolve 'path' in '[PATH_TO_MY_PROJECT]srcdatabasegenerated'
BREAKING CHANGE: webpack < 5 used to include polyfills for node.js core modules by default.
This is no longer the case. Verify if you need this module and configure a polyfill for it.
If you want to include a polyfill, you need to:
- add a fallback 'resolve.fallback: { "path": require.resolve("path-browserify") }'
- install 'path-browserify'
If you don't want to include a polyfill, you can use an empty module like this:
resolve.fallback: { "path": false }

在其他18个模块中重复。由于开始的错误信息是不同的,我也怀疑这是不是正确的方法。

我终于想通了。我需要了解的是,所有的电子应用程序都由两部分组成:前端web应用程序(运行在嵌入式Chromium中)和Node后端服务器。这两个部分被称为IPC Main和IPC Renderer,它们可以相互通信。由于Prisma只能在主进程上运行,所以我必须将我的SQL操作发送到电子后端并在那里执行它们。

我的最小示例

在前端(我使用Angular)

// This refers to the node_modules folder of the Electron Backend, the folder where the main.ts file is located.
// I just use this import so that I can use the prisma generated classes for type safety.
import { TestTable } from '../../../app/node_modules/.prisma/client';
// Button action
onSqlTestAction(): void {
this.electronService.ipcRenderer.invoke("prisma-channel", 'Test input').then((value) => {
const testObject: TestTable = JSON.parse(value);
console.log(testObject);
});

我使用的示例项目已经有这个服务来提供IPC Renderer:

@Injectable({
providedIn: 'root'
})
export class ElectronService {
ipcRenderer: typeof ipcRenderer;
webFrame: typeof webFrame;
remote: typeof remote;
childProcess: typeof childProcess;
fs: typeof fs;
get isElectron(): boolean {
return !!(window && window.process && window.process.type);
}
constructor() {
// Conditional imports
if (this.isElectron) {
this.ipcRenderer = window.require('electron').ipcRenderer;
this.webFrame = window.require('electron').webFrame;
this.childProcess = window.require('child_process');
this.fs = window.require('fs');
// If you want to use a NodeJS 3rd party deps in Renderer process (like @electron/remote),
// it must be declared in dependencies of both package.json (in root and app folders)
// If you want to use remote object in renderer process, please set enableRemoteModule to true in main.ts
this.remote = window.require('@electron/remote');
}
}

然后在电子后端,我首先将"@prisma/client": "^3.0.1"添加到package.json(用于电子后端而不是前端)。然后我在main.ts中添加了这个函数来处理来自渲染器的请求:

// main.ts
ipcMain.handle("prisma-channel", async (event, args) => {
const prisma = new PrismaClient();
await prisma.testTable.create(
{
data: {
value: args
}
}
);
const readValue = await prisma.testTable.findMany();
return JSON.stringify(readValue);
})
这种简单地在main.ts文件中添加IPC Main处理程序的方式当然是一个很大的代码气味,但作为最小的例子是有用的。我想我将继续介绍本文中提出的架构概念。

最新更新