diff --git a/deltachat-jsonrpc/README.md b/deltachat-jsonrpc/README.md index fc02bd4967..3e81a7456a 100644 --- a/deltachat-jsonrpc/README.md +++ b/deltachat-jsonrpc/README.md @@ -16,6 +16,7 @@ We also include a JavaScript and TypeScript client for the JSON-RPC API. The sou The package includes a JavaScript/TypeScript client which is partially auto-generated through the JSON-RPC library used by this crate ([yerpc](https://github.com/chatmail/yerpc)). Find the source in the [`typescript`](typescript) folder. To use it locally, first install the dependencies and compile the TypeScript code to JavaScript: + ```sh cd typescript npm install @@ -24,11 +25,28 @@ npm run build The JavaScript client is [published on NPM](https://www.npmjs.com/package/@deltachat/jsonrpc-client). +###### Usage + +```typescript +import { startDeltaChat } from "@deltachat/stdio-rpc-server"; +import { C } from "@deltachat/jsonrpc-client"; + +const dc = await startDeltaChat("deltachat-data"); +console.log(await dc.rpc.getSystemInfo()); +const accounts = await dc.rpc.getAllAccounts(); +console.log("accounts", accounts); +dc.close(); +``` + +##### Generate TypeScript/JavaScript documentation + A script is included to build autogenerated documentation, which includes all RPC methods: + ```sh cd typescript npm run docs ``` + Then open the [`typescript/docs`](typescript/docs) folder in a web browser. ## Development diff --git a/deltachat-jsonrpc/typescript/Readme.md b/deltachat-jsonrpc/typescript/Readme.md new file mode 100644 index 0000000000..99ae9e7583 --- /dev/null +++ b/deltachat-jsonrpc/typescript/Readme.md @@ -0,0 +1,206 @@ +# @deltachat/jsonrpc-client + +This package is a client for the jsonrpc server. + +> If you are looking for the functions in the documentation, they are under [`RawClient`](https://js.jsonrpc.delta.chat/classes/RawClient.html). + +### Important Terms + +- [chat mail core (formerly delta chat core)](https://github.com/deltachat/deltachat-core-rust/) is heart of all Delta Chat clients. Handels all the heavy lifting (email, encryption, ...) and provides an easy api for bots and clients (`getChatlist`, `getChat`, `getContact`, ...). +- [jsonrpc](https://www.jsonrpc.org/specification) is a JSON based protocol + for applications to speak to each other by [remote procedure calls](https://en.wikipedia.org/wiki/Remote_procedure_call) (short RPC), + which basically means that the client can call methods on the server by sending a JSON messages. +- [`deltachat-rpc-server`](https://github.com/deltachat/deltachat-core-rust/tree/main/deltachat-rpc-server) provides the jsonrpc api over stdio (stdin/stdout) +- [`@deltachat/stdio-rpc-server`](https://www.npmjs.com/package/@deltachat/stdio-rpc-server) is an easy way to install `deltachat-rpc-server` from npm and use it from nodejs. + +#### Transport + +You need to connect this client to an instance of chatmail-core via a transport. + +For this you can use the `StdioTransport`, which you can use by importing `StdioDeltaChat`. + +You can also make your own transport, for example deltachat desktop uses a custom transport that sends the json messages over electron ipc. +Just implement your transport based on the `Transport` interface - look at how the [stdio transport is implemented](https://github.com/deltachat/deltachat-core-rust/blob/7121675d226e69fd85d0194d4b9c4442e4dd8299/deltachat-jsonrpc/typescript/src/client.ts#L113) for an example, it's not hard. + +The other transports that exist (but note that those are not standalone, they list here only serves as reference on how to implement those.): + +- Electron IPC (from Delta Chat Desktop) + - [transport](https://github.com/deltachat/deltachat-desktop/blob/0a4fdb2065c7b14fa097769181afd05e3f552f54/packages/target-electron/runtime-electron/runtime.ts#L49-L123), [request handling](https://github.com/deltachat/deltachat-desktop/blob/0a4fdb2065c7b14fa097769181afd05e3f552f54/packages/target-electron/src/deltachat/controller.ts#L199-L201), [responses](https://github.com/deltachat/deltachat-desktop/blob/0a4fdb2065c7b14fa097769181afd05e3f552f54/packages/target-electron/src/deltachat/controller.ts#L93-L113) +- Tauri IPC (from DC Desktop Tauri edition) + - [transport](https://github.com/deltachat/deltachat-desktop/blob/0a4fdb2065c7b14fa097769181afd05e3f552f54/packages/target-tauri/runtime-tauri/runtime.ts#L86-L118), backend: [request handling](https://github.com/deltachat/deltachat-desktop/blob/0a4fdb2065c7b14fa097769181afd05e3f552f54/packages/target-tauri/src-tauri/src/lib.rs#L85-L94), [responses](https://github.com/deltachat/deltachat-desktop/blob/0a4fdb2065c7b14fa097769181afd05e3f552f54/packages/target-tauri/src-tauri/src/state/deltachat.rs#L43-L95) +- Authenticated Websocket (from DC Desktop Browser edition) + - [transport](https://github.com/deltachat/deltachat-desktop/blob/0a4fdb2065c7b14fa097769181afd05e3f552f54/packages/target-browser/runtime-browser/runtime.ts#L37-L80), backend: [authentication](https://github.com/deltachat/deltachat-desktop/blob/0a4fdb2065c7b14fa097769181afd05e3f552f54/packages/target-browser/src/index.ts#L258-L275), [web socket server](https://github.com/deltachat/deltachat-desktop/blob/0a4fdb2065c7b14fa097769181afd05e3f552f54/packages/target-browser/src/deltachat-rpc.ts#L93) (this also contains some unrelated code, it's easier than it looks at first glance) + +## Usage + +> The **minimum** nodejs version for `@deltachat/stdio-rpc-server` is `16` + +``` +npm i @deltachat/stdio-rpc-server @deltachat/jsonrpc-client +``` + +```js +import { startDeltaChat } from "@deltachat/stdio-rpc-server"; +// Import constants you might need later +import { C } from "@deltachat/jsonrpc-client"; + +async function main() { + const dc = await startDeltaChat("deltachat-data"); + console.log(await dc.rpc.getSystemInfo()); + dc.close(); +} +main(); +``` + +For a more complete example refer to . + +### Listening for events + +```ts +dc.on("Info", (accountId, { msg }) => + console.info(accountId, "[core:info]", msg), +); +// Or get an event emitter for only one account +const emitter = dc.getContextEvents(accountId); +emitter.on("IncomingMsg", async ({ chatId, msgId }) => { + const message = await dc.rpc.getMessage(accountId, msgId); + console.log("got message in chat " + chatId + " : ", message.text); +}); +``` + +### Getting Started + +This section describes how to handle the Delta Chat core library over the jsonrpc bindings. +For general information about Delta Chat itself, +see and . + +Let's start. + +First of all, you have to start the deltachat-rpc-server process. + +```js +import { startDeltaChat } from "@deltachat/stdio-rpc-server"; +const dc = await startDeltaChat("deltachat-data"); +``` + +Then we have to create an Account (also called Context or profile) that is bound to a database. +The database is a normal SQLite file with a "blob directory" beside it. +But these details are handled by deltachat's account manager. +So you just have to tell the account manager to create a new account: + +```js +const accountId = await dc.rpc.addAccount(); +``` + +After that, register event listeners so you can see what core is doing: +Intenally `@deltachat/jsonrpc-client` implments a loop that waits for new events and then emits them to javascript land. + +```js +dc.on("Info", (accountId, { msg }) => + console.info(accountId, "[core:info]", msg), +); +``` + +Now you can **configure the account:** + +```js +// use some real test credentials here +await dc.rpc.setConfig(accountId, "addr", "alice@example.org"); +await dc.rpc.setConfig(accountId, "mail_pw", "***"); +// you can also set multiple config options in one call +await dc.rpc.batchSetConfig(accountId, { + addr: "alice@example.org", + mail_pw: "***", +}); + +// after setting the credentials attempt to login +await dc.rpc.configure(accountId); +``` + +`configure()` returns a promise that is rejected on error (with await is is thrown). +The configuration itself may take a while. You can monitor it's progress like this: + +```js +dc.on("ConfigureProgress", (accountId, { progress, comment }) => { + console.log(accountId, "ConfigureProgress", progress, comment); +}); +// make sure to register this event handler before calling `dc.rpc.configure()` +``` + +The configuration result is saved in the database. +On subsequent starts it is not needed to call `dc.rpc.configure(accountId)` +(you can check this using `dc.rpc.isConfigured(accountId)`). + +On a successfully configuration delta chat core automatically connects to the server, however subsequent starts you **need to do that manually** by calling `dc.rpc.startIo(accountId)` or `dc.rpc.startIoForAllAccounts()`. + +```js +if (!(await dc.rpc.isConfigured(accountId))) { + // use some real test credentials here + await dc.rpc.batchSetConfig(accountId, { + addr: "alice@example.org", + mail_pw: "***", + }); + await dc.rpc.configure(accountId); +} else { + await dc.rpc.startIo(accountId); +} +``` + +Now you can **send the first message:** + +```js +const contactId = await dc.rpc.createContact( + accountId, + "bob@example.org", + null /* optional name */, +); +const chatId = await dc.rpc.createChatByContactId(accountId, contactId); + +await dc.rpc.miscSendTextMessage( + accountId, + chatId, + "Hi, here is my first message!", +); +``` + +`dc.rpc.miscSendTextMessage()` returns immediately; +the sending itself is done in the background. +If you check the testing address (bob), +you should receive a normal e-mail. +Answer this e-mail in any e-mail program with "Got it!", +and the IO you started above will **receive the message**. + +You can then **list all messages** of a chat as follows: + +```js +let i = 0; +for (const msgId of await exp.rpc.getMessageIds(120, 12, false, false)) { + i++; + console.log(`Message: ${i}`, (await dc.rpc.getMessage(120, msgId)).text); +} +``` + +This will output the following two lines: + +``` +Message 1: Hi, here is my first message! +Message 2: Got it! +``` + + + +## Further information + +- `@deltachat/stdio-rpc-server` + - [package on npm](https://www.npmjs.com/package/@deltachat/stdio-rpc-server) + - [source code on github](https://github.com/deltachat/deltachat-core-rust/tree/main/deltachat-rpc-server/npm-package) +- [use `@deltachat/stdio-rpc-server` on an usuported platform](https://github.com/deltachat/deltachat-core-rust/tree/main/deltachat-rpc-server/npm-package#how-to-use-on-an-unsupported-platform) +- The issue-tracker for the core library is here: + +If you need further assistance, +please do not hesitate to contact us +through the channels shown at https://delta.chat/en/contribute + +Please keep in mind, that your derived work +must respect the Mozilla Public License 2.0 of deltachat-rpc-server +and the respective licenses of the libraries deltachat-rpc-server links with. diff --git a/deltachat-jsonrpc/typescript/src/client.ts b/deltachat-jsonrpc/typescript/src/client.ts index dd0c6e32b6..5d10ccbb8a 100644 --- a/deltachat-jsonrpc/typescript/src/client.ts +++ b/deltachat-jsonrpc/typescript/src/client.ts @@ -5,14 +5,14 @@ import { RawClient } from "../generated/client.js"; import { BaseTransport, Request } from "yerpc"; import { TinyEmitter } from "@deltachat/tiny-emitter"; -type Events = { ALL: (accountId: number, event: EventType) => void } & { +export type Events = { ALL: (accountId: number, event: EventType) => void } & { [Property in EventType["kind"]]: ( accountId: number, event: Extract, ) => void; }; -type ContextEvents = { ALL: (event: EventType) => void } & { +export type ContextEvents = { ALL: (event: EventType) => void } & { [Property in EventType["kind"]]: ( event: Extract, ) => void; diff --git a/deltachat-rpc-server/npm-package/README.md b/deltachat-rpc-server/npm-package/README.md index ed2e6cd5cc..d01a5e2816 100644 --- a/deltachat-rpc-server/npm-package/README.md +++ b/deltachat-rpc-server/npm-package/README.md @@ -5,6 +5,8 @@ it does not use NAPI bindings but instead uses stdio executables to let you talk to core over jsonrpc over stdio. This simplifies cross-compilation and even reduces binary size (no CFFI layer and no NAPI layer). +📚 Docs: + ## Usage > The **minimum** nodejs version for this package is `16` @@ -18,20 +20,47 @@ import { startDeltaChat } from "@deltachat/stdio-rpc-server"; import { C } from "@deltachat/jsonrpc-client"; async function main() { - const dc = await startDeltaChat("deltachat-data"); - console.log(await dc.rpc.getSystemInfo()); - dc.close() + const dc = await startDeltaChat("deltachat-data"); + console.log(await dc.rpc.getSystemInfo()); + dc.close(); } -main() +main(); ``` -For a more complete example refer to https://github.com/deltachat-bot/echo/pull/69/files (TODO change link when pr is merged). +For a more complete example refer to . ## How to use on an unsupported platform - +You need to have rust installed to compile deltachat core for your platform and cpu architecture. + is the recommended way to install rust. +Also your system probably needs more than 4GB RAM to compile core, alternatively your could try to build the debug build, which might take less RAM to build. + +1. clone the core repo, right next to your project folder: `git clone git@github.com:deltachat/deltachat-core-rust.git` +2. go into your core checkout and run `git pull` and `git checkout ` to point it to the correct version (needs to be the same version the `@deltachat/jsonrpc-client` package has) +3. run `cargo build --release --package deltachat-rpc-server --bin deltachat-rpc-server` + +Then you have 2 options: + +### point to deltachat-rpc-server via direct path: + +```sh +# start your app with the DELTA_CHAT_RPC_SERVER env var +DELTA_CHAT_RPC_SERVER="../deltachat-core-rust/target/release/deltachat-rpc-server" node myapp.js +``` - +### install deltachat-rpc-server in your $PATH: + +```sh +# use this to install to ~/.cargo/bin +cargo install --release --package deltachat-rpc-server --bin deltachat-rpc-server +# or manually move deltachat-core-rust/target/release/deltachat-rpc-server +# to a location that is included in your $PATH Environment variable. +``` + +And make sure to enable the `takeVersionFromPATH` option: +```js +startDeltaChat("data-dir", { takeVersionFromPATH: true }); +``` ## How does it work when you install it @@ -46,7 +75,7 @@ references: When you import this package it searches for the rpc server in the following locations and order: 1. `DELTA_CHAT_RPC_SERVER` environment variable -2. use the PATH when `{takeVersionFromPATH: true}` is supplied in the options. +2. use the PATH when `{takeVersionFromPATH: true}` is supplied in the options. 3. prebuilds in npm packages so by default it uses the prebuilds.