Compare commits

...

9 Commits

  1. 124
      Cargo.lock
  2. 5
      Cargo.toml
  3. 114
      DEV.md
  4. 8
      README.md
  5. 3
      app/nextgraph/.gitignore
  6. 7
      app/nextgraph/.prettierignore
  7. 18
      app/nextgraph/.prettierrc
  8. 147
      app/nextgraph/README.md
  9. 213
      app/nextgraph/index.html
  10. 327
      app/nextgraph/package-lock.json
  11. 43
      app/nextgraph/package.json
  12. 32
      app/nextgraph/prepare-web-file.cjs
  13. 8
      app/nextgraph/src-tauri/Cargo.toml
  14. 1089
      app/nextgraph/src-tauri/src/lib.rs
  15. 2
      app/nextgraph/src-tauri/src/main.rs
  16. 8
      app/nextgraph/src-tauri/tauri.conf.json
  17. 33
      app/nextgraph/src/App.svelte
  18. 16
      app/nextgraph/src/assets/logo.svg
  19. 6
      app/nextgraph/src/assets/tauri.svg
  20. 25
      app/nextgraph/src/assets/typescript.svg
  21. 1
      app/nextgraph/src/assets/vite.svg
  22. 34
      app/nextgraph/src/main-web.ts
  23. 35
      app/nextgraph/src/main.ts
  24. 335
      app/nextgraph/src/native-api.ts
  25. 119
      app/nextgraph/src/styles.css
  26. 11
      app/nextgraph/svelte.config.js
  27. 11
      app/nextgraph/tailwind.config.js
  28. 3
      app/nextgraph/tsconfig.json
  29. 200
      app/nextgraph/vite.config.ts
  30. 8
      bin/ngd/README.md
  31. 2
      engine/broker/auth/src/main.ts
  32. 4
      engine/broker/src/server_ws.rs
  33. 2
      infra/ngaccount/web/package.json
  34. 2
      infra/ngnet/redir/package.json
  35. 5
      package.json
  36. 1840
      pnpm-lock.yaml
  37. 86
      sdk/js/DEV.md
  38. 6
      sdk/js/README.md
  39. 65
      sdk/js/lib-wasm/DEV.md
  40. 59
      sdk/js/lib-wasm/jsland/browser.js
  41. 181
      sdk/python/.github/workflows/CI.yml
  42. 72
      sdk/python/.gitignore
  43. 25
      sdk/python/Cargo.toml
  44. 63
      sdk/python/README.md
  45. 17
      sdk/python/pyproject.toml
  46. 167
      sdk/python/src/lib.rs
  47. 21
      sdk/python/test.py
  48. 15
      sdk/rust/README.md

124
Cargo.lock generated

@ -6,17 +6,23 @@ version = 3
name = "NextGraph" name = "NextGraph"
version = "0.1.2" version = "0.1.2"
dependencies = [ dependencies = [
"async-std",
"nextgraph", "nextgraph",
"ng-async-tungstenite",
"ng-net", "ng-net",
"ng-repo", "ng-repo",
"ng-wallet", "ng-wallet",
"oxrdf", "oxrdf",
"serde", "serde",
"serde_bare",
"serde_bytes",
"serde_json", "serde_json",
"sys-locale",
"tauri", "tauri",
"tauri-build", "tauri-build",
"tauri-plugin-barcode-scanner", "tauri-plugin-barcode-scanner",
"tauri-plugin-opener", "tauri-plugin-opener",
"zeroize",
] ]
[[package]] [[package]]
@ -2922,6 +2928,12 @@ dependencies = [
"serde_core", "serde_core",
] ]
[[package]]
name = "indoc"
version = "2.0.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f4c7245a08504955605670dbf141fceab975f15ca21570696aebe9d2e71576bd"
[[package]] [[package]]
name = "infer" name = "infer"
version = "0.19.0" version = "0.19.0"
@ -3818,6 +3830,18 @@ dependencies = [
"pkg-config", "pkg-config",
] ]
[[package]]
name = "ng-sdk-python"
version = "0.1.2"
dependencies = [
"async-std",
"nextgraph",
"pyo3",
"pyo3-async-runtimes",
"pythonize",
"serde",
]
[[package]] [[package]]
name = "ng-storage-rocksdb" name = "ng-storage-rocksdb"
version = "0.1.2" version = "0.1.2"
@ -4142,7 +4166,7 @@ version = "0.7.4"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "77e878c846a8abae00dd069496dbe8751b16ac1c3d6bd2a7283a938e8228f90d" checksum = "77e878c846a8abae00dd069496dbe8751b16ac1c3d6bd2a7283a938e8228f90d"
dependencies = [ dependencies = [
"proc-macro-crate 1.3.1", "proc-macro-crate 3.4.0",
"proc-macro2", "proc-macro2",
"quote", "quote",
"syn 2.0.106", "syn 2.0.106",
@ -5015,6 +5039,12 @@ dependencies = [
"universal-hash", "universal-hash",
] ]
[[package]]
name = "portable-atomic"
version = "1.11.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f84267b20a16ea918e43c6a88433c2d54fa145c92a811b5b047ccbe153674483"
[[package]] [[package]]
name = "potential_utf" name = "potential_utf"
version = "0.1.3" version = "0.1.3"
@ -5138,6 +5168,92 @@ version = "2.0.11"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "33cb294fe86a74cbcf50d4445b37da762029549ebeea341421c7c70370f86cac" checksum = "33cb294fe86a74cbcf50d4445b37da762029549ebeea341421c7c70370f86cac"
[[package]]
name = "pyo3"
version = "0.23.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7778bffd85cf38175ac1f545509665d0b9b92a198ca7941f131f85f7a4f9a872"
dependencies = [
"cfg-if",
"indoc",
"libc",
"memoffset",
"once_cell",
"portable-atomic",
"pyo3-build-config",
"pyo3-ffi",
"pyo3-macros",
"unindent",
]
[[package]]
name = "pyo3-async-runtimes"
version = "0.23.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "977dc837525cfd22919ba6a831413854beb7c99a256c03bf8624ad707e45810e"
dependencies = [
"async-std",
"futures",
"once_cell",
"pin-project-lite",
"pyo3",
]
[[package]]
name = "pyo3-build-config"
version = "0.23.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "94f6cbe86ef3bf18998d9df6e0f3fc1050a8c5efa409bf712e661a4366e010fb"
dependencies = [
"once_cell",
"target-lexicon",
]
[[package]]
name = "pyo3-ffi"
version = "0.23.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e9f1b4c431c0bb1c8fb0a338709859eed0d030ff6daa34368d3b152a63dfdd8d"
dependencies = [
"libc",
"pyo3-build-config",
]
[[package]]
name = "pyo3-macros"
version = "0.23.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "fbc2201328f63c4710f68abdf653c89d8dbc2858b88c5d88b0ff38a75288a9da"
dependencies = [
"proc-macro2",
"pyo3-macros-backend",
"quote",
"syn 2.0.106",
]
[[package]]
name = "pyo3-macros-backend"
version = "0.23.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "fca6726ad0f3da9c9de093d6f116a93c1a38e417ed73bf138472cf4064f72028"
dependencies = [
"heck 0.5.0",
"proc-macro2",
"pyo3-build-config",
"quote",
"syn 2.0.106",
]
[[package]]
name = "pythonize"
version = "0.23.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "91a6ee7a084f913f98d70cdc3ebec07e852b735ae3059a1500db2661265da9ff"
dependencies = [
"pyo3",
"serde",
]
[[package]] [[package]]
name = "qoi" name = "qoi"
version = "0.4.1" version = "0.4.1"
@ -7237,6 +7353,12 @@ version = "1.12.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f6ccf251212114b54433ec949fd6a7841275f9ada20dddd2f29e9ceea4501493" checksum = "f6ccf251212114b54433ec949fd6a7841275f9ada20dddd2f29e9ceea4501493"
[[package]]
name = "unindent"
version = "0.2.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7264e107f553ccae879d21fbea1d6724ac785e8c3bfc762137959b5802826ef3"
[[package]] [[package]]
name = "unique_id" name = "unique_id"
version = "0.1.7" version = "0.1.7"

@ -11,6 +11,7 @@ members = [
"engine/oxigraph", "engine/oxigraph",
"sdk/rust", "sdk/rust",
"sdk/js/lib-wasm", "sdk/js/lib-wasm",
"sdk/python",
"bin/ngd", "bin/ngd",
"bin/ngcli", "bin/ngcli",
"infra/ngaccount", "infra/ngaccount",
@ -73,3 +74,7 @@ opt-level = 2
# tauri = { git = "https://git.nextgraph.org/NextGraph/tauri.git", branch="alpha.11-nextgraph", features = ["no-ipc-custom-protocol"] } # tauri = { git = "https://git.nextgraph.org/NextGraph/tauri.git", branch="alpha.11-nextgraph", features = ["no-ipc-custom-protocol"] }
[workspace.dependencies] [workspace.dependencies]
[workspace.metadata.scripts]
libwasm = "cd sdk/js/lib-wasm && cargo run-script app && cd ../../.."

114
DEV.md

@ -26,16 +26,7 @@ git clone git@git.nextgraph.org:NextGraph/nextgraph-rs.git
// or if you don't have a git account with us: git clone https://git.nextgraph.org/NextGraph/nextgraph-rs.git // or if you don't have a git account with us: git clone https://git.nextgraph.org/NextGraph/nextgraph-rs.git
cd nextgraph-rs cd nextgraph-rs
npm install -g pnpm npm install -g pnpm
cd sdk/lib-wasm pnpm buildfront
cargo run-script app
cd ../..
cd helpers/wasm-tools
cargo run-script app
cd ../..
pnpm -C ./ng-app install
pnpm -C ./ng-app webfilebuild
pnpm -C ./helpers/app-auth install
pnpm -C ./helpers/app-auth build
``` ```
For building the native apps, see the [ng-app/README](ng-app/README.md) For building the native apps, see the [ng-app/README](ng-app/README.md)
@ -50,23 +41,29 @@ If you prefer to change the base directory, use the argument `--base [PATH]` whe
cargo run -p ngd -- -vv --save-key -l 14400 cargo run -p ngd -- -vv --save-key -l 14400
``` ```
If you are developing also the front-end, you should run it with this command in a separate terminal:
```
cd ng-app
pnpm -C ../helpers/net-auth builddev
pnpm -C ../helpers/app-auth builddev
pnpm -C ../helpers/net-bootstrap builddev
pnpm webdev
```
In the logs/output of ngd, you will see an invitation link that you should open in your web browser. If there are many links, choose the one that starts with `http://localhost:`, and if you run a local front-end, replace the prefix `http://localhost:14400/` with `http://localhost:1421/` before you open the link in your browser. In the logs/output of ngd, you will see an invitation link that you should open in your web browser. If there are many links, choose the one that starts with `http://localhost:`, and if you run a local front-end, replace the prefix `http://localhost:14400/` with `http://localhost:1421/` before you open the link in your browser.
The computer you use to open the link should have direct access to the ngd server on localhost. In most of the cases, it will work, as you are running ngd on localhost. If you are running ngd in a docker container, then you need to give access to the container to the local network of the host by using `docker run --network="host"`. see more here https://docs.docker.com/network/drivers/host/ The computer you use to open the link should have direct access to the ngd server on localhost. In most of the cases, it will work, as you are running ngd on localhost. If you are running ngd in a docker container, then you need to give access to the container to the local network of the host by using `docker run --network="host"`. see more here https://docs.docker.com/network/drivers/host/
Follow the steps on the screen to create your wallet :) Follow the steps on the screen to create your wallet :)
Once your ngd server will run in your dev env, replace the string in `nextgraph/src/local_broker_dev_env.rs` with the actual PEER ID of your ngd server that is displayed when you first start `ngd`, with a line starting with `INFO ngd] PeerId of node:`. Once your ngd server will run in your dev env, replace the string in `sdk/rust/src/local_broker_dev_env.rs` with the actual PEER ID of your ngd server that is displayed when you first start `ngd`, with a line starting with `INFO ngd] PeerId of node:`. This step is needed if you want to test or develop the import of wallet with QRCode.
More details about usage of ngd [here](bin/ngd/README.md).
### If you are developing the front-end too
If you are also developing the front-end of NextGraph app, you should run it with this command in a separate terminal:
```
// run this only once, from root folder:
pnpm buildfrontdev
// to start the front-end for development
cd app/nextgraph
pnpm webdev
```
more details about developing the front-end [here](app/nextgraph/README.md).
### Using ngcli with the account you just created ### Using ngcli with the account you just created
@ -107,23 +104,37 @@ Then you need to stop your ngd and start it again with the additional option :
### Packages ### Packages
The crates are organized as follow : The crates and packages are organized as follow :
- [nextgraph](nextgraph/README.md) : Client library. Use this crate to embed NextGraph client in your Rust application - app : the main application of NextGraph
- [ngcli](ngcli/README.md) : CLI tool to manipulate the local documents and repos and administrate the server - ui-common : common UI elements
- [ngd](ngd/README.md) : binary executable of the daemon (that can run a broker, verifier and/or Rust services) - [nextgraph](app/nextgraph/README.md)
- [ng-app](ng-app/README.md) : all the native apps, based on Tauri, and the official web app. - src-tauri : the Tauri based native apps
- [lib-wasm](lib-wasm/DEV.md) : contains the JS SDK, with example for: web app, react app, or node service. - src : the Web-based app
- [ng-sdk-python](ng-sdk-python/README.md) : contains the Python SDK. - bin : the binaries
- ng-repo : Repositories common library - [ngcli](bin/ngcli/README.md) : CLI tool to manipulate the local documents and repos and administrate the server
- ng-net : Network common library - [ngd](bin/ngd/README.md) : binary executable of the daemon (that runs a broker, the verifier and additional Rust services)
- ng-oxigraph : Fork of OxiGraph. contains our CRDT of RDF - engine : the core engine including NGproto
- ng-verifier : Verifier library, that exposes the document API to the app - repo : Repositories common library
- ng-wallet : keeps the secret keys of all identities of the user in a safe wallet - net : Network common library
- ng-broker : Core and Server Broker library - oxigraph : Fork of OxiGraph. contains our CRDT of RDF
- ng-client-ws : Websocket client library - verifier : Verifier library, that exposes the document API to the app
- ng-storage-rocksdb : RocksDB backed stores. see also dependency [repo here](https://git.nextgraph.org/NextGraph/rust-rocksdb) - wallet : keeps the secret keys of all identities of the user in a safe wallet
- helpers : all kind of servers and front end code needed for our infrastructure. - broker : Core and Server Broker library
- client-ws : Websocket client library
- storage-rocksdb : RocksDB backed stores. see also dependency [repo here](https://git.nextgraph.org/NextGraph/rust-rocksdb)
- infra : tools and binaries for infrastructure of the platform
- ngaccount : broker service provider (BSP) account manager
- ngapp : server of the web app used by self-hosters on the public web
- ngnet : server of nextgraph.net that shelps with authentication of third-party web apps.
- sdk
- [js](sdk/js/README.md)
- api-web : the web version of the API
- [lib-wasm](sdk/js/lib-wasm/DEV.md) : the WASM library used by api-web
- [examples](sdk/js/DEV.md) : example for: web app, React/Svelte app, or node service
- alien-deepsignals, shex-orm and signals : used by the ORM mechanism
- [rust](sdk/rust/README.md) : Client library. Use this crate to embed NextGraph client in your Rust application
- [python](sdk/python/README.md) : contains the Python SDK.
### Test ### Test
@ -173,13 +184,8 @@ You need to freshly built it from source, following those instructions:
``` ```
cargo install cargo-run-script cargo install cargo-run-script
npm install -g pnpm npm install -g pnpm
cd lib-wasm cargo run-script libwasm
cargo run-script app pnpm buildfront
cd ..
pnpm -C ./ng-app install
pnpm -C ./ng-app webfilebuild
pnpm -C ./helpers/app-auth install
pnpm -C ./helpers/app-auth build
``` ```
then build the ngd daemon then build the ngd daemon
@ -198,9 +204,9 @@ cargo build -r -p ngcli
you can then use the binary `target/release/ngcli` you can then use the binary `target/release/ngcli`
For usage, see the documentation [here](ngd/README.md). For usage, see the documentation [here](bin/ngd/README.md).
For building the apps, see this [documentation](ng-app/README.md). For building the native apps, see this [documentation](app/nextgraph/README.md).
#### OpenBSD #### OpenBSD
@ -239,3 +245,17 @@ The generated documentation can be found in `target/doc/nextgraph`.
Unless you explicitly state otherwise, any contribution intentionally submitted Unless you explicitly state otherwise, any contribution intentionally submitted
for inclusion in the work by you shall be dual licensed as below, without any for inclusion in the work by you shall be dual licensed as below, without any
additional terms or conditions. additional terms or conditions.
## License
Licensed under either of
- Apache License, Version 2.0 ([LICENSE-APACHE2](LICENSE-APACHE2) or http://www.apache.org/licenses/LICENSE-2.0)
- MIT license ([LICENSE-MIT](LICENSE-MIT) or http://opensource.org/licenses/MIT)
at your option.
`SPDX-License-Identifier: Apache-2.0 OR MIT`
---
NextGraph received funding through the [NGI Assure Fund](https://nlnet.nl/assure) and the [NGI Zero Commons Fund](https://nlnet.nl/commonsfund/), both funds established by [NLnet](https://nlnet.nl/) Foundation with financial support from the European Commission's [Next Generation Internet](https://ngi.eu/) programme, under the aegis of DG Communications Networks, Content and Technology under grant agreements No 957073 and No 101092990, respectively.

@ -36,7 +36,7 @@ And our community forum where you can ask questions is here [https://forum.nextg
## How to use NextGraph App & Platform ## How to use NextGraph App & Platform
NextGraph is in alpha release! NextGraph is in alpha release.
You can try it online or by installing the apps. Please follow our [Getting started](https://docs.nextgraph.org/en/getting-started/) guide . You can try it online or by installing the apps. Please follow our [Getting started](https://docs.nextgraph.org/en/getting-started/) guide .
@ -54,9 +54,9 @@ See our [contributor's guide](DEV.md)
Licensed under either of Licensed under either of
- Apache License, Version 2.0 ([LICENSE-APACHE2](LICENSE-APACHE2) or http://www.apache.org/licenses/LICENSE-2.0) - Apache License, Version 2.0 ([LICENSE-APACHE2](LICENSE-APACHE2) or http://www.apache.org/licenses/LICENSE-2.0)
- MIT license ([LICENSE-MIT](LICENSE-MIT) or http://opensource.org/licenses/MIT) - MIT license ([LICENSE-MIT](LICENSE-MIT) or http://opensource.org/licenses/MIT)
at your option. at your option.
`SPDX-License-Identifier: Apache-2.0 OR MIT` `SPDX-License-Identifier: Apache-2.0 OR MIT`

@ -9,8 +9,9 @@ lerna-debug.log*
node_modules node_modules
dist dist
dist-ssr dist-web
*.local *.local
public_dev
# Editor directories and files # Editor directories and files
.vscode/* .vscode/*

@ -0,0 +1,7 @@
# Package Managers
package-lock.json
pnpm-lock.yaml
yarn.lock
*.json
.prettierrc
src-tauri/gen

@ -0,0 +1,18 @@
{
"useTabs": false,
"singleQuote": false,
"trailingComma": "none",
"printWidth": 100,
"tabWidth": 4,
"plugins": [
"prettier-plugin-svelte"
],
"overrides": [
{
"files": "*.svelte",
"options": {
"parser": "svelte"
}
}
]
}

@ -1,7 +1,148 @@
# Tauri + Vanilla TS # NextGraph apps (Linux, MacOS, Windows, Android, iOS, web)
This template should help get you started developing with Tauri in vanilla HTML, CSS and Typescript. All the apps are based on Svelte and share the same code.
The native apps are using the Tauri framework with an embedded WebView to render the Svelte app.
## Install
```
npm install -g pnpm
pnpm install
pnpm install @tauri-apps/cli
```
## Recommended IDE Setup ## Recommended IDE Setup
- [VS Code](https://code.visualstudio.com/) + [Tauri](https://marketplace.visualstudio.com/items?itemName=tauri-apps.tauri-vscode) + [rust-analyzer](https://marketplace.visualstudio.com/items?itemName=rust-lang.rust-analyzer) [VS Codium](https://vscodium.com/) + [Svelte](https://marketplace.visualstudio.com/items?itemName=svelte.svelte-vscode) + [Tauri](https://marketplace.visualstudio.com/items?itemName=tauri-apps.tauri-vscode) + [rust-analyzer](https://marketplace.visualstudio.com/items?itemName=rust-lang.rust-analyzer).
## Web
prerequisites: compile the local JS/WASM SDK
```
pnpm libwasm
```
#### Dev
First time:
```
pnpm buildfrontdev
```
Then run your local front-end:
```
pnpm webdev
// then open http://localhost:1421/
```
#### Prod
this will produce a single html file embedding all the resources. this is what ngd broker needs for production
```
pnpm webbuild
```
## Desktop
```
cargo install tauri-cli --version "^2.0.0" --locked
```
Install [all prerequisites](https://tauri.app/start/prerequisites/) for your dev platform.
Add this line to your environment variables
```
export RANLIB="$NDK_HOME/toolchains/llvm/prebuilt/$(ls -1 $NDK_HOME/toolchains/llvm/prebuilt/)/bin/llvm-ranlib"
```
to run the dev env :
```
## on macos
cargo tauri dev --no-watch --target x86_64-apple-darwin
## on linux
cargo tauri dev --no-watch --target x86_64-unknown-linux-gnu
## on win
cargo tauri dev --no-watch --target x86_64-pc-windows-msvc
```
to build the production app installer :
### MacOs (10.14+)
```
cargo tauri build
// the installer is then available in target/x86_64-apple-darwin/release/bundle/dmg/NextGraph_0.1.2_x64.dmg
// or if you just want the app, it is at target/x86_64-apple-darwin/release/bundle/macos/NextGraph.app
```
### Linux (Ubuntu 22.04)
```
cargo tauri build --target x86_64-unknown-linux-gnu
```
### Windows (7+)
```
cargo tauri build --target x86_64-pc-windows-msvc
```
### Android
- [Install Android Studio](https://developer.android.com/studio)
- add the rust targets for android
```
rustup target add aarch64-linux-android armv7-linux-androideabi i686-linux-android x86_64-linux-android
```
- follow the steps for Android in the [Prerequisites guide of Tauri](https://tauri.app/start/prerequisites/#android)
Before you can generate the APK, you will need to [configure Android Studio with your Signing keys.](https://tauri.app/distribute/sign/android/)
to launch the dev app :
```
cargo tauri android dev
```
to build the production app :
```
cargo tauri android build
```
to debug the Svelte app, use Chrome :
- [chrome://inspect/#devices](chrome://inspect/#devices)
- install the [svelte extension](https://chrome.google.com/webstore/detail/svelte-devtools/ckolcbmkjpjmangdbmnkpjigpkddpogn)
### iOS
Disclaimer: iOS hasn't been tested yet, for lack of suitable dev env (latest MacOS version needed).
First, make sure Xcode is properly installed. then :
```
rustup target add aarch64-apple-ios x86_64-apple-ios aarch64-apple-ios-sim
```
to launch the dev app :
```
cargo tauri ios dev
```
to build the production app :
```
cargo tauri ios build
```

@ -1,43 +1,182 @@
<!--
// Copyright (c) 2022-2025 Niko Bonnieure, Par le Peuple, NextGraph.org developers
// All rights reserved.
// Licensed under the Apache License, Version 2.0
// <LICENSE-APACHE2 or http://www.apache.org/licenses/LICENSE-2.0>
// or the MIT license <LICENSE-MIT or http://opensource.org/licenses/MIT>,
// at your option. All files in the project carrying such
// notice may not be copied, modified, or distributed except
// according to those terms.
-->
<!doctype html> <!doctype html>
<html lang="en"> <html lang="en">
<head> <head>
<meta charset="UTF-8" /> <meta charset="UTF-8" />
<link rel="stylesheet" href="/src/styles.css" /> <link
<meta name="viewport" content="width=device-width, initial-scale=1.0" /> rel="icon"
<title>Tauri App</title> type="image/svg+xml"
<script type="module" src="/src/main.ts" defer></script> href="data:image/svg+xml;base64,
</head> PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAyMjUg
MjI1Ij48Y2lyY2xlIGN4PSIxMDkuODgxIiBjeT0iMTEyLjkwNSIgcj0iMTA2Ljk4IiBzdHlsZT0i
ZmlsbDogcmdiKDI1NSwgMjU1LCAyNTUpOyBzdHJva2U6IG5vbmU7IHN0cm9rZS13aWR0aDogMC4y
NjgzNzU7Ij48L2NpcmNsZT48cGF0aCBkPSJNOTguMzQzIDE5MC4yNjFjLTE3Ljk0LTIuNzI3LTMz
LjMzMS0xMC42ODMtNDUuNzM1LTIzLjYzOC0xNC4wMDYtMTQuNjI5LTIxLjQzLTMzLjIxLTIxLjQz
LTUzLjYzNSAwLTEwLjIxOCAxLjctMTkuNDQ0IDUuMjIxLTI4LjMzMiA0LjI4Ny0xMC44MiAxMC4w
MzgtMTkuMzkgMTguNTM1LTI3LjYyMiA0LjczLTQuNTgyIDYuNjA3LTYuMTA3IDExLjI4MS05LjE2
MyAxMS45LTcuNzggMjQuMTc0LTExLjg4IDM4LjA5Ni0xMi43MjUgMTkuODA1LTEuMjAxIDM5LjEx
MiA1LjExMyA1NC42MDMgMTcuODYgMS41MDcgMS4yNCAyLjczIDIuMzU4IDIuNzE2IDIuNDg2LS4w
MTMuMTI4LTMuODU4IDMuNjM1LTguNTQ0IDcuNzkzLTQuNjg2IDQuMTU3LTEwLjA0NyA4Ljk2Mi0x
MS45MTQgMTAuNjc3LTEuODY2IDEuNzE1LTMuNTQgMy4xMTktMy43MjEgMy4xMTktLjE4MSAwLTEu
NC0uNzQ2LTIuNzEtMS42NTYtNy41My01LjIzOS0xNS45OTQtNy44MjItMjUuNjI1LTcuODIyLTEy
LjczMiAwLTIzLjI1IDQuMzM4LTMyLjE0NCAxMy4yNTctNi4zOTYgNi40MTQtMTAuNzA0IDE0LjU1
Ni0xMi41IDIzLjYyNC0uNjkxIDMuNDg4LS42OSAxMy41My4wMDIgMTcuMDA5IDMuNzA1IDE4LjYy
NiAxOC4zMTggMzMuMTAyIDM2LjY0MiAzNi4yOTcgNC4xNjQuNzI2IDExLjk4LjcxMiAxNS45OS0u
MDI4IDE0LjAzMi0yLjU5NCAyNS44Ni0xMS4zNjggMzIuMjY1LTIzLjkzNi43NzQtMS41MTkgMS4y
Ni0yLjg4NSAxLjA4LTMuMDM2LS4xNzgtLjE1Mi02Ljg3NC0xLjE3OC0xNC44NzctMi4yODEtOS43
OC0xLjM0OC0xNC45MjQtMi4yMTQtMTUuNjg1LTIuNjQxLTEuNTItLjg1NC0yLjgzNi0yLjg4OC0y
LjgzNi00LjM4NiAwLTEuMTczIDIuMDI3LTE1Ljg2OSAyLjQ5LTE4LjA2LjI5OC0xLjQwMSAyLjQy
Ni0zLjQ5MyAzLjg0NC0zLjc3Ny42MjItLjEyNCA4LjgyNy44NTYgMTguMjggMi4xODQgOS40MzQg
MS4zMjUgMTcuMjYzIDIuMjk0IDE3LjM5OSAyLjE1NC4xMzYtLjE0IDEuMTE4LTYuNTQ4IDIuMTgz
LTE0LjI0IDEuMTA4LTggMi4yMDQtMTQuNjAyIDIuNTYyLTE1LjQyNi4zNDQtLjc5MyAxLjExLTEu
ODUgMS43MDMtMi4zNDggMi4wNjMtMS43MzYgMy4xNDMtMS43ODUgMTIuMjA0LS41NTMgOS42MzYg
MS4zMSAxMC43MDkgMS41NjIgMTIuMjggMi44ODUgMS42NDQgMS4zODMgMi4yNzQgMi44MSAyLjI2
IDUuMTIzLS4wMDcgMS4xMDItLjkyMiA4LjI5Ny0yLjAzMyAxNS45ODktMS4xMTIgNy42OTEtMS45
NzIgMTQuMDQtMS45MTIgMTQuMTA5LjA2MS4wNjggNy4xNjcgMS4xMTEgMTUuNzkyIDIuMzE4IDEx
LjEwNSAxLjU1NCAxNi4wMDggMi4zODcgMTYuODAyIDIuODU2IDEuNTMuOTA0IDIuNDggMi42NDgg
Mi40NSA0LjQ5OC0uMDQ2IDIuODQ0LTIuNDEzIDE4LjEyMy0yLjk3NSAxOS4yMS0uNjYyIDEuMjgt
Mi42MDMgMi41NDgtMy45MjEgMi41NjItLjUyLjAwNS03Ljg3NS0uOTYtMTYuMzQ0LTIuMTQ0LTgu
NDctMS4xODUtMTUuNDc2LTIuMDc3LTE1LjU3LTEuOTgzLS4wOTQuMDk0LTEuMTg4IDcuMzQxLTIu
NDMxIDE2LjEwNi0xLjQ0IDEwLjE1My0yLjQ5OCAxNi40MzYtMi45MTYgMTcuMzE2LS43MjUgMS41
MjgtMi43NjIgMy4wNjMtNC41MzggMy40MTgtLjk1Ny4xOTEtMTAuOS0uOTI4LTEzLjU5OC0xLjUz
LS41NDgtLjEyMy0xLjg5Mi42NzItNC41MSAyLjY2NS0xMS4yNjMgOC41NzYtMjQuMzQyIDEzLjkx
LTM4LjM1NyAxNS42NDItNC40LjU0NC0xNS43MjcuNDMzLTE5Ljg1NC0uMTk1eiIgc3R5bGU9ImZp
bGw6IHJnYig3MywgMTE0LCAxNjUpOyBmaWxsLW9wYWNpdHk6IDE7IHN0cm9rZTogcmdiKDczLCAx
MTQsIDE2NSk7IHN0cm9rZS13aWR0aDogMC4zNzc5NzY7IHN0cm9rZS1vcGFjaXR5OiAxOyI+PC9w
YXRoPjwvc3ZnPg=="
/>
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>NextGraph</title>
<meta property="og:title" content="NextGraph App - The New Internet Platform" />
<meta property="og:image" content="https://nextgraph.org/card.png"/>
<meta name="twitter:image" content="https://nextgraph.org/card-twitter.png"/>
<meta name="twitter:card" content="summary_large_image" />
<meta property="og:description" content="Decentralized, encrypted and local-first platform and framework, towards the better internet we all deserve! Features a social network, shared documents, productivity tools, an app store, and more! You can use NextGraph for free, and it works online and offline. With NextGraph you own your data and software, having your privacy respected, while enjoying high-quality apps for your daily use. Try it now! Developers can build new web3.0 local-first apps with our open source framework, based on open standards, with CRDTs, E2EE, Semantic Web, RDF, SPARQL, JSON, Markdown, Svelte, React, JavaScript, Rust, etc... ActivityPub and Solid compatible." />
<meta name="description" content="Decentralized, encrypted and local-first platform and framework, towards the better internet we all deserve! Features a social network, shared documents, productivity tools, an app store, and more! You can use NextGraph for free, and it works online and offline. With NextGraph you own your data and software, having your privacy respected, while enjoying high-quality apps for your daily use. Try it now! Developers can build new web3.0 local-first apps with our open source framework, based on open standards, with CRDTs, E2EE, Semantic Web, RDF, SPARQL, JSON, Markdown, Svelte, React, JavaScript, Rust, etc... ActivityPub and Solid compatible.">
<link rel="stylesheet" href="/src/styles.css" />
<style>
.splashing {
height: 100vh;
width:100%;
display: flex;
justify-content: center;
align-items: center;
}
.noshow {
display: none !important;
}
.error-no-wasm-hidden {
display:none;
}
</style>
</head>
<body> <body>
<main class="container"> <div id="splash" class="splashing">
<h1>Welcome to Tauri 2</h1> <div style="flex-direction: column; justify-content: center;
color:#4972a5;width:100%;text-align:left;
width:300px;
font-family: Inter, Avenir, Helvetica, Arial, sans-serif;"
>
<svg
style="width:100px;height:100px;margin: 0 auto 20px ;display:flex;"
xmlns="http://www.w3.org/2000/svg"
viewBox="0 0 225 225"
>
<g>
<circle
r="106.98013"
cy="112.90476"
cx="109.88096"
style="fill:#ffffff;stroke:none;stroke-width:0.268375" />
<path
d="M 98.343352,190.26108 C 80.403778,187.53354 65.011938,179.57839 52.608228,166.62327 38.602093,151.99448 31.178059,133.41381 31.178059,112.98841 c 0,-10.21889 1.700058,-19.44396 5.221234,-28.332119 4.28678,-10.820699 10.037295,-19.39063 18.535095,-27.62263 4.72982,-4.58187 6.60687,-6.10643 11.28099,-9.16256 11.89869,-7.779841 24.173884,-11.879991 38.095802,-12.724761 19.80437,-1.2017 39.11165,5.11306 54.60284,17.858751 1.50718,1.24006 2.72951,2.35934 2.71628,2.48729 -0.0132,0.12795 -3.85821,3.63443 -8.54442,7.79217 -4.6862,4.157729 -10.04724,8.96276 -11.91342,10.677819 -1.86617,1.715071 -3.54094,3.11831 -3.7217,3.11831 -0.18075,0 -1.39985,-0.745188 -2.70911,-1.655969 -7.53011,-5.23834 -15.99428,-7.82188 -25.62597,-7.82188 -12.731628,0 -23.249192,4.3379 -32.143882,13.257541 -6.39594,6.413868 -10.70387,14.555268 -12.50018,23.623578 -0.69099,3.48832 -0.68968,13.53072 0.002,17.00893 3.70508,18.62577 18.31886,33.10194 36.642322,36.29729 4.16439,0.72621 11.98099,0.71223 15.98975,-0.0286 14.03187,-2.59311 25.86047,-11.36806 32.26533,-23.93578 0.77379,-1.51834 1.26018,-2.88461 1.08086,-3.03616 -0.17934,-0.15156 -6.87448,-1.1779 -14.87813,-2.28078 -9.7795,-1.34758 -14.92353,-2.21379 -15.68471,-2.64117 -1.52067,-0.85379 -2.83611,-2.88806 -2.83611,-4.3859 0,-1.1732 2.02687,-15.86876 2.49085,-18.05962 0.29676,-1.40127 2.42559,-3.4934 3.84317,-3.77691 0.62227,-0.12445 8.82712,0.85555 18.28065,2.18348 9.43343,1.32511 17.26269,2.29453 17.39833,2.15427 0.13566,-0.14026 1.11808,-6.54833 2.18313,-14.24014 1.10778,-8.000208 2.20407,-14.60184 2.56177,-15.426229 0.34392,-0.792599 1.11019,-1.849131 1.70287,-2.34782 2.06321,-1.736079 3.1433,-1.785011 12.20439,-0.55291 9.63637,1.310309 10.70873,1.56224 12.28077,2.88503 1.64359,1.382979 2.2732,2.810909 2.25906,5.123309 -0.007,1.10173 -0.92172,8.29645 -2.03332,15.98826 -1.11158,7.69182 -1.97159,14.04091 -1.91113,14.1091 0.0605,0.0682 7.16644,1.11143 15.79109,2.31832 11.10566,1.55407 16.00827,2.38757 16.80223,2.85657 1.53015,0.90389 2.48023,2.64785 2.45017,4.49756 -0.0462,2.84349 -2.41252,18.12279 -2.97521,19.21089 -0.66164,1.27949 -2.60244,2.54696 -3.92109,2.56074 -0.51973,0.005 -7.87449,-0.95937 -16.34391,-2.144 -8.46944,-1.18464 -15.47588,-2.077 -15.56986,-1.98301 -0.094,0.094 -1.18792,7.34163 -2.43097,16.10589 -1.44004,10.15311 -2.49792,16.43621 -2.91556,17.31631 -0.72531,1.52848 -2.76261,3.06291 -4.53817,3.41802 -0.95688,0.19138 -10.90014,-0.92798 -13.59859,-1.53084 -0.5471,-0.12223 -1.89146,0.67252 -4.50941,2.66588 -11.2627,8.57562 -24.34195,13.90917 -38.35741,15.64164 -4.40038,0.54395 -15.72658,0.43298 -19.853658,-0.19451 z"
style="fill:#4972a5;fill-opacity:1;stroke:#4972a5;stroke-width:0.377976;stroke-opacity:1" />
</g>
</svg>
<div class="row"> <div class="noshow" style="text-align:center;" id="app-loading">&nbsp;&nbsp;&nbsp;Loading ...</div>
<a href="https://vite.dev" target="_blank">
<img src="/src/assets/vite.svg" class="logo vite" alt="Vite logo" />
</a>
<a href="https://tauri.app" target="_blank">
<img
src="/src/assets/tauri.svg"
class="logo tauri"
alt="Tauri logo"
/>
</a>
<a href="https://www.typescriptlang.org/docs" target="_blank">
<img
src="/src/assets/typescript.svg"
class="logo typescript"
alt="typescript logo"
/>
</a>
</div>
<p>Click on the Tauri logo to learn more about the framework</p>
<form class="row" id="greet-form"> <div id="error-no-wasm" style="padding-left:15px;" class="error-no-wasm-hidden">
<input id="greet-input" placeholder="Enter a name..." /> Your browser is too old or is miss-configured.
<button type="submit">Greet</button> Please try one of those options:<br/><br/>
</form> - Upgrade to a newer version of this browser.<br/>
<p id="greet-msg"></p> - Try with another browser software.<br/>
</main> - <a href="https://nextgraph.org/download">install our native apps for
</body> Linux, macOS, Windows desktops and laptops,
and iOS, Android mobiles.</a><br/><br/>
If you are using jshelter or another javascript protection mechanism,
please deactivate it as we need access to the WebWorker, JIT and WASM
features of your browser. If those features are disabled, please
enable them for this website.
</div>
<noscript style="display:grid;padding-left:15px;">
NextGraph cannot load as Javascript is currently deactivated.
You can use the CLI ngcli to access your documents in the terminal.
Or use the <a href="https://nextgraph.org/download">native apps
for Linux, macOS, Windows, Android, iOS.</a><br/>
Or setup an SSR static website generator with AtomicServer for javascript-less and
read-only access.
</noscript>
</div>
</div>
<script>
const supported = () => {
if (RegExp().hasIndices === undefined) {
console.error("no RegExp().hasIndices");
return false;
}
try {
if (Worker === undefined) {
console.error("no Worker");
return false;
}
new Worker(URL.createObjectURL(new Blob([';'], {type: 'application/javascript'})));
if (typeof WebAssembly === "object"
&& typeof WebAssembly.instantiate === "function") {
const module = new WebAssembly.Module(Uint8Array.of(0x0, 0x61, 0x73, 0x6d, 0x01, 0x00, 0x00, 0x00));
if (module instanceof WebAssembly.Module)
return new WebAssembly.Instance(module) instanceof WebAssembly.Instance;
else {
console.log("no WebAssembly module");
}
}
} catch (e) {
console.error(e);
return false;
}
console.error("no WebAssembly");
return false;
};
if (check_supported && !supported()) {
window.document.getElementById("error-no-wasm").className="";
} else {
window.document.getElementById("app-loading").className="";
window.everything_ready = () => {
window.document.getElementById("splash").className="noshow";
window.document.getElementById("app").className="";
};
window.onload = () => {
window.ng_supported = true;
console.log("window loaded");
if (window.ng_spa_loaded) {
everything_ready();
}
};
}
</script>
<div id="app" class="noshow"></div>
<!-- # INSERT SCRIPT HERE -->
</body>
</html> </html>

@ -0,0 +1,327 @@
{
"name": "nextgraph",
"version": "0.1.0",
"lockfileVersion": 3,
"requires": true,
"packages": {
"": {
"name": "nextgraph",
"version": "0.1.0",
"dependencies": {
"@tailwindcss/vite": "^4.1.14",
"@tauri-apps/api": "^2",
"@tauri-apps/plugin-opener": "^2"
},
"devDependencies": {
"@tauri-apps/cli": "^2.8.4",
"tailwindcss": "^4.1.14",
"typescript": "~5.6.2",
"vite": "^7.1.7"
}
},
"../../node_modules/.pnpm/@tailwindcss+vite@4.1.14_vite@7.1.10_@types+node@24.3.0_jiti@2.6.1_lightningcss@1.30.1_yaml@2.8.1_/node_modules/@tailwindcss/vite": {
"version": "4.1.14",
"license": "MIT",
"dependencies": {
"@tailwindcss/node": "4.1.14",
"@tailwindcss/oxide": "4.1.14",
"tailwindcss": "4.1.14"
},
"devDependencies": {
"@types/node": "^20.19.0",
"vite": "^7.0.0"
},
"peerDependencies": {
"vite": "^5.2.0 || ^6 || ^7"
}
},
"../../node_modules/.pnpm/@tauri-apps+api@2.8.0/node_modules/@tauri-apps/api": {
"version": "2.8.0",
"license": "Apache-2.0 OR MIT",
"devDependencies": {
"@eslint/js": "^9.29.0",
"@rollup/plugin-terser": "0.4.4",
"@rollup/plugin-typescript": "12.1.4",
"@types/eslint": "^9.6.1",
"@types/node": "^22.15.32",
"eslint": "^9.29.0",
"eslint-config-prettier": "10.1.8",
"eslint-plugin-security": "3.0.1",
"fast-glob": "3.3.3",
"globals": "^16.2.0",
"rollup": "4.46.3",
"tslib": "^2.8.1",
"typescript": "^5.8.3",
"typescript-eslint": "^8.34.1"
},
"funding": {
"type": "opencollective",
"url": "https://opencollective.com/tauri"
}
},
"../../node_modules/.pnpm/@tauri-apps+cli@2.8.4/node_modules/@tauri-apps/cli": {
"version": "2.8.4",
"dev": true,
"license": "Apache-2.0 OR MIT",
"bin": {
"tauri": "tauri.js"
},
"devDependencies": {
"@napi-rs/cli": "^3.0.0",
"@types/node": "^22.15.32",
"cross-env": "10.0.0",
"vitest": "^3.2.4"
},
"engines": {
"node": ">= 10"
},
"funding": {
"type": "opencollective",
"url": "https://opencollective.com/tauri"
},
"optionalDependencies": {
"@tauri-apps/cli-darwin-arm64": "2.8.4",
"@tauri-apps/cli-darwin-x64": "2.8.4",
"@tauri-apps/cli-linux-arm-gnueabihf": "2.8.4",
"@tauri-apps/cli-linux-arm64-gnu": "2.8.4",
"@tauri-apps/cli-linux-arm64-musl": "2.8.4",
"@tauri-apps/cli-linux-riscv64-gnu": "2.8.4",
"@tauri-apps/cli-linux-x64-gnu": "2.8.4",
"@tauri-apps/cli-linux-x64-musl": "2.8.4",
"@tauri-apps/cli-win32-arm64-msvc": "2.8.4",
"@tauri-apps/cli-win32-ia32-msvc": "2.8.4",
"@tauri-apps/cli-win32-x64-msvc": "2.8.4"
}
},
"../../node_modules/.pnpm/@tauri-apps+plugin-opener@2.5.0/node_modules/@tauri-apps/plugin-opener": {
"version": "2.5.0",
"license": "MIT OR Apache-2.0",
"dependencies": {
"@tauri-apps/api": "^2.8.0"
}
},
"../../node_modules/.pnpm/typescript@5.6.3/node_modules/typescript": {
"version": "5.6.3",
"dev": true,
"license": "Apache-2.0",
"bin": {
"tsc": "bin/tsc",
"tsserver": "bin/tsserver"
},
"devDependencies": {
"@dprint/formatter": "^0.4.1",
"@dprint/typescript": "0.91.6",
"@esfx/canceltoken": "^1.0.0",
"@eslint/js": "^9.9.0",
"@octokit/rest": "^21.0.1",
"@types/chai": "^4.3.17",
"@types/diff": "^5.2.1",
"@types/minimist": "^1.2.5",
"@types/mocha": "^10.0.7",
"@types/ms": "^0.7.34",
"@types/node": "latest",
"@types/source-map-support": "^0.5.10",
"@types/which": "^3.0.4",
"@typescript-eslint/rule-tester": "^8.1.0",
"@typescript-eslint/type-utils": "^8.1.0",
"@typescript-eslint/utils": "^8.1.0",
"azure-devops-node-api": "^14.0.2",
"c8": "^10.1.2",
"chai": "^4.5.0",
"chalk": "^4.1.2",
"chokidar": "^3.6.0",
"diff": "^5.2.0",
"dprint": "^0.47.2",
"esbuild": "^0.23.0",
"eslint": "^9.9.0",
"eslint-formatter-autolinkable-stylish": "^1.4.0",
"eslint-plugin-regexp": "^2.6.0",
"fast-xml-parser": "^4.4.1",
"glob": "^10.4.5",
"globals": "^15.9.0",
"hereby": "^1.9.0",
"jsonc-parser": "^3.3.1",
"knip": "^5.27.2",
"minimist": "^1.2.8",
"mocha": "^10.7.3",
"mocha-fivemat-progress-reporter": "^0.1.0",
"monocart-coverage-reports": "^2.10.2",
"ms": "^2.1.3",
"node-fetch": "^3.3.2",
"playwright": "^1.46.0",
"source-map-support": "^0.5.21",
"tslib": "^2.6.3",
"typescript": "^5.5.4",
"typescript-eslint": "^8.1.0",
"which": "^3.0.1"
},
"engines": {
"node": ">=14.17"
}
},
"../../node_modules/.pnpm/vite@7.1.10_@types+node@24.3.0_jiti@2.6.1_lightningcss@1.30.1_yaml@2.8.1/node_modules/vite": {
"version": "7.1.10",
"dev": true,
"license": "MIT",
"dependencies": {
"esbuild": "^0.25.0",
"fdir": "^6.5.0",
"picomatch": "^4.0.3",
"postcss": "^8.5.6",
"rollup": "^4.43.0",
"tinyglobby": "^0.2.15"
},
"bin": {
"vite": "bin/vite.js"
},
"devDependencies": {
"@babel/parser": "^7.28.4",
"@jridgewell/remapping": "^2.3.5",
"@jridgewell/trace-mapping": "^0.3.31",
"@oxc-project/types": "0.90.0",
"@polka/compression": "^1.0.0-next.25",
"@rolldown/pluginutils": "^1.0.0-beta.43",
"@rollup/plugin-alias": "^5.1.1",
"@rollup/plugin-commonjs": "^28.0.6",
"@rollup/plugin-dynamic-import-vars": "2.1.4",
"@rollup/pluginutils": "^5.3.0",
"@types/escape-html": "^1.0.4",
"@types/pnpapi": "^0.0.5",
"artichokie": "^0.4.2",
"baseline-browser-mapping": "^2.8.16",
"cac": "^6.7.14",
"chokidar": "^3.6.0",
"connect": "^3.7.0",
"convert-source-map": "^2.0.0",
"cors": "^2.8.5",
"cross-spawn": "^7.0.6",
"debug": "^4.4.3",
"dep-types": "link:./src/types",
"dotenv": "^17.2.3",
"dotenv-expand": "^12.0.3",
"es-module-lexer": "^1.7.0",
"escape-html": "^1.0.3",
"estree-walker": "^3.0.3",
"etag": "^1.8.1",
"host-validation-middleware": "^0.1.2",
"http-proxy-3": "^1.22.0",
"launch-editor-middleware": "^2.11.1",
"lightningcss": "^1.30.2",
"magic-string": "^0.30.19",
"mlly": "^1.8.0",
"mrmime": "^2.0.1",
"nanoid": "^5.1.6",
"open": "^10.2.0",
"parse5": "^8.0.0",
"pathe": "^2.0.3",
"periscopic": "^4.0.2",
"picocolors": "^1.1.1",
"postcss-import": "^16.1.1",
"postcss-load-config": "^6.0.1",
"postcss-modules": "^6.0.1",
"premove": "^4.0.0",
"resolve.exports": "^2.0.3",
"rolldown": "^1.0.0-beta.43",
"rolldown-plugin-dts": "^0.16.11",
"rollup-plugin-license": "^3.6.0",
"sass": "^1.93.2",
"sass-embedded": "^1.93.2",
"sirv": "^3.0.2",
"strip-literal": "^3.1.0",
"terser": "^5.44.0",
"tsconfck": "^3.1.6",
"types": "link:./types",
"ufo": "^1.6.1",
"ws": "^8.18.3"
},
"engines": {
"node": "^20.19.0 || >=22.12.0"
},
"funding": {
"url": "https://github.com/vitejs/vite?sponsor=1"
},
"optionalDependencies": {
"fsevents": "~2.3.3"
},
"peerDependencies": {
"@types/node": "^20.19.0 || >=22.12.0",
"jiti": ">=1.21.0",
"less": "^4.0.0",
"lightningcss": "^1.21.0",
"sass": "^1.70.0",
"sass-embedded": "^1.70.0",
"stylus": ">=0.54.8",
"sugarss": "^5.0.0",
"terser": "^5.16.0",
"tsx": "^4.8.1",
"yaml": "^2.4.2"
},
"peerDependenciesMeta": {
"@types/node": {
"optional": true
},
"jiti": {
"optional": true
},
"less": {
"optional": true
},
"lightningcss": {
"optional": true
},
"sass": {
"optional": true
},
"sass-embedded": {
"optional": true
},
"stylus": {
"optional": true
},
"sugarss": {
"optional": true
},
"terser": {
"optional": true
},
"tsx": {
"optional": true
},
"yaml": {
"optional": true
}
}
},
"node_modules/@tailwindcss/vite": {
"resolved": "../../node_modules/.pnpm/@tailwindcss+vite@4.1.14_vite@7.1.10_@types+node@24.3.0_jiti@2.6.1_lightningcss@1.30.1_yaml@2.8.1_/node_modules/@tailwindcss/vite",
"link": true
},
"node_modules/@tauri-apps/api": {
"resolved": "../../node_modules/.pnpm/@tauri-apps+api@2.8.0/node_modules/@tauri-apps/api",
"link": true
},
"node_modules/@tauri-apps/cli": {
"resolved": "../../node_modules/.pnpm/@tauri-apps+cli@2.8.4/node_modules/@tauri-apps/cli",
"link": true
},
"node_modules/@tauri-apps/plugin-opener": {
"resolved": "../../node_modules/.pnpm/@tauri-apps+plugin-opener@2.5.0/node_modules/@tauri-apps/plugin-opener",
"link": true
},
"node_modules/tailwindcss": {
"version": "4.1.14",
"resolved": "https://registry.npmjs.org/tailwindcss/-/tailwindcss-4.1.14.tgz",
"integrity": "sha512-b7pCxjGO98LnxVkKjaZSDeNuljC4ueKUddjENJOADtubtdo8llTaJy7HwBMeLNSSo2N5QIAgklslK1+Ir8r6CA==",
"dev": true,
"license": "MIT"
},
"node_modules/typescript": {
"resolved": "../../node_modules/.pnpm/typescript@5.6.3/node_modules/typescript",
"link": true
},
"node_modules/vite": {
"resolved": "../../node_modules/.pnpm/vite@7.1.10_@types+node@24.3.0_jiti@2.6.1_lightningcss@1.30.1_yaml@2.8.1/node_modules/vite",
"link": true
}
}
}

@ -1,21 +1,48 @@
{ {
"name": "nextgraph", "name": "@ng-org/ng-app",
"private": true, "private": true,
"version": "0.1.0", "version": "0.1.2",
"type": "module", "type": "module",
"scripts": { "scripts": {
"dev": "vite", "dev": "vite",
"build": "tsc && vite build", "build": "vite build",
"preview": "vite preview", "preview": "vite preview",
"tauri": "tauri" "tauri": "tauri",
"format": "prettier --write .",
"check": "svelte-check --tsconfig ./tsconfig.json",
"webdev": "cross-env NG_ENV_WEB=1 TAURI_DEBUG=1 NG_PUBLIC_DEV=1 vite",
"webbuild": "cross-env NG_ENV_WEB=1 NG_ENV_ONEFILE=1 vite build && node prepare-web-file.cjs",
"libwasm": "cd ../.. && cargo install cargo-run-script && cargo run-script libwasm && cd app/nextgraph",
"buildfrontdev": "pnpm -C ../../infra/ngnet/bootstrap builddev && pnpm -C ../../infra/ngnet/auth builddev && pnpm -C ../../infra/ngnet/redir builddev"
}, },
"dependencies": { "dependencies": {
"@ark-ui/svelte": "^5.11.0",
"@dvcol/svelte-simple-router": "^2.7.2",
"@ng-org/lib-wasm": "workspace:*",
"@ng-org/ui-common": "workspace:*",
"@tauri-apps/api": "^2", "@tauri-apps/api": "^2",
"@tauri-apps/plugin-opener": "^2" "@tauri-apps/plugin-opener": "^2",
"async-proxy": "^0.4.1"
}, },
"devDependencies": { "devDependencies": {
"@tauri-apps/cli": "^2", "@hazycora/vite-plugin-svelte-svg": "^2.4.3",
"vite": "^6.0.3", "@sveltejs/vite-plugin-svelte": "^6.2.1",
"typescript": "~5.6.2" "@tailwindcss/typography": "^0.5.19",
"@tailwindcss/vite": "^4.1.14",
"@tauri-apps/cli": "^2.8.4",
"@tsconfig/svelte": "^5.0.5",
"cross-env": "^10.1.0",
"daisyui": "^5.3.1",
"node-gzip": "^1.1.2",
"prettier": "^3.6.2",
"prettier-plugin-svelte": "^3.4.0",
"svelte": "^5.39.13",
"svelte-check": "^4.3.3",
"tailwindcss": "^4.1.14",
"typescript": "~5.6.2",
"vite": "^7.1.7",
"vite-plugin-singlefile": "^2.3.0",
"vite-plugin-top-level-await": "^1.6.0",
"vite-plugin-wasm": "^3.5.0"
} }
} }

@ -0,0 +1,32 @@
const crypto = require('crypto');
const fs = require('fs');
const {gzip, } = require('node-gzip');
var algorithm = 'sha256'
, shasum = crypto.createHash(algorithm)
const sha_file = './dist-web/index.sha256';
const gzip_file = './dist-web/index.gzip';
var filename = './dist-web/index.html'
, s = fs.ReadStream(filename)
var bufs = [];
s.on('data', function(data) {
shasum.update(data)
bufs.push(data);
})
s.on('end', function() {
var hash = shasum.digest('hex')
console.log(hash + ' ' + filename)
fs.writeFileSync(sha_file, hash, 'utf8');
var buf = Buffer.concat(bufs);
gzip(buf).then((compressed) => {fs.writeFileSync(gzip_file, compressed);});
fs.rm(filename,()=>{});
})

@ -26,13 +26,19 @@ crate-type = ["staticlib", "cdylib", "rlib"]
tauri-build = { version = "2", features = [] } tauri-build = { version = "2", features = [] }
[dependencies] [dependencies]
tauri = { version = "2", features = [] } tauri = { version = "2", features = ["unstable"] }
tauri-plugin-opener = "2" tauri-plugin-opener = "2"
serde = { version = "1", features = ["derive"] } serde = { version = "1", features = ["derive"] }
serde_json = "1" serde_json = "1"
serde_bare = "0.5.0"
serde_bytes = "0.11.7"
tauri-plugin-barcode-scanner = "2" tauri-plugin-barcode-scanner = "2"
ng-repo = { path = "../../../engine/repo" } ng-repo = { path = "../../../engine/repo" }
ng-net = { path = "../../../engine/net" } ng-net = { path = "../../../engine/net" }
ng-wallet = { path = "../../../engine/wallet" } ng-wallet = { path = "../../../engine/wallet" }
nextgraph = { path = "../../../sdk/rust" } nextgraph = { path = "../../../sdk/rust" }
oxrdf = { git = "https://git.nextgraph.org/NextGraph/oxigraph.git", branch="main", features = ["rdf-star", "oxsdatatypes"] } oxrdf = { git = "https://git.nextgraph.org/NextGraph/oxigraph.git", branch="main", features = ["rdf-star", "oxsdatatypes"] }
async-std = { version = "1.12.0", features = ["attributes", "unstable"] }
sys-locale = { version = "0.3.1" }
zeroize = { version = "1.7.0", features = ["zeroize_derive"] }
ng-async-tungstenite = { git = "https://git.nextgraph.org/NextGraph/async-tungstenite.git", branch = "nextgraph", features = ["async-std-runtime", "async-native-tls"] }

File diff suppressed because it is too large Load Diff

@ -2,5 +2,5 @@
#![cfg_attr(not(debug_assertions), windows_subsystem = "windows")] #![cfg_attr(not(debug_assertions), windows_subsystem = "windows")]
fn main() { fn main() {
nextgraph_lib::run() nextgraph_lib::AppBuilder::new().run();
} }

@ -1,11 +1,11 @@
{ {
"$schema": "https://schema.tauri.app/config/2", "$schema": "https://schema.tauri.app/config/2",
"productName": "NextGraph", "productName": "NextGraph",
"version": "0.1.0", "version": "0.1.2",
"identifier": "org.nextgraph.app", "identifier": "org.nextgraph.app",
"build": { "build": {
"beforeDevCommand": "pnpm dev", "beforeDevCommand": "pnpm dev",
"devUrl": "http://localhost:5173", "devUrl": "http://localhost:1420",
"beforeBuildCommand": "pnpm build", "beforeBuildCommand": "pnpm build",
"frontendDist": "../dist" "frontendDist": "../dist"
}, },
@ -14,8 +14,8 @@
"windows": [ "windows": [
{ {
"title": "NextGraph", "title": "NextGraph",
"width": 1024, "width": 1280,
"height": 600 "height": 960
} }
], ],
"security": { "security": {

@ -0,0 +1,33 @@
<!--
// Copyright (c) 2022-2025 Niko Bonnieure, Par le Peuple, NextGraph.org developers
// All rights reserved.
// Licensed under the Apache License, Version 2.0
// <LICENSE-APACHE2 or http://www.apache.org/licenses/LICENSE-2.0>
// or the MIT license <LICENSE-MIT or http://opensource.org/licenses/MIT>,
// at your option. All files in the project carrying such
// notice may not be copied, modified, or distributed except
// according to those terms.
-->
<script lang="ts">
import ng from "@ng-org/ui-common/api";
import Logo from "./assets/logo.svg?component";
console.log(await ng.locales());
let info = await ng.client_info();
console.log(info.V0.details);
window.ng_spa_loaded = true;
if (window.ng_supported) {
console.log("READY");
window.everything_ready();
}
</script>
<div class="grid h-screen place-items-center">
<div style="height:144px;">
<Logo class="w-25"/>
</div>
</div>
<style>
</style>

@ -0,0 +1,16 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg
xmlns="http://www.w3.org/2000/svg"
viewBox="0 0 225 225"
>
<g>
<circle
r="106.98013"
cy="112.90476"
cx="109.88096"
style="fill:#ffffff;stroke:none;stroke-width:0.268375" />
<path
d="M 98.343352,190.26108 C 80.403778,187.53354 65.011938,179.57839 52.608228,166.62327 38.602093,151.99448 31.178059,133.41381 31.178059,112.98841 c 0,-10.21889 1.700058,-19.44396 5.221234,-28.332119 4.28678,-10.820699 10.037295,-19.39063 18.535095,-27.62263 4.72982,-4.58187 6.60687,-6.10643 11.28099,-9.16256 11.89869,-7.779841 24.173884,-11.879991 38.095802,-12.724761 19.80437,-1.2017 39.11165,5.11306 54.60284,17.858751 1.50718,1.24006 2.72951,2.35934 2.71628,2.48729 -0.0132,0.12795 -3.85821,3.63443 -8.54442,7.79217 -4.6862,4.157729 -10.04724,8.96276 -11.91342,10.677819 -1.86617,1.715071 -3.54094,3.11831 -3.7217,3.11831 -0.18075,0 -1.39985,-0.745188 -2.70911,-1.655969 -7.53011,-5.23834 -15.99428,-7.82188 -25.62597,-7.82188 -12.731628,0 -23.249192,4.3379 -32.143882,13.257541 -6.39594,6.413868 -10.70387,14.555268 -12.50018,23.623578 -0.69099,3.48832 -0.68968,13.53072 0.002,17.00893 3.70508,18.62577 18.31886,33.10194 36.642322,36.29729 4.16439,0.72621 11.98099,0.71223 15.98975,-0.0286 14.03187,-2.59311 25.86047,-11.36806 32.26533,-23.93578 0.77379,-1.51834 1.26018,-2.88461 1.08086,-3.03616 -0.17934,-0.15156 -6.87448,-1.1779 -14.87813,-2.28078 -9.7795,-1.34758 -14.92353,-2.21379 -15.68471,-2.64117 -1.52067,-0.85379 -2.83611,-2.88806 -2.83611,-4.3859 0,-1.1732 2.02687,-15.86876 2.49085,-18.05962 0.29676,-1.40127 2.42559,-3.4934 3.84317,-3.77691 0.62227,-0.12445 8.82712,0.85555 18.28065,2.18348 9.43343,1.32511 17.26269,2.29453 17.39833,2.15427 0.13566,-0.14026 1.11808,-6.54833 2.18313,-14.24014 1.10778,-8.000208 2.20407,-14.60184 2.56177,-15.426229 0.34392,-0.792599 1.11019,-1.849131 1.70287,-2.34782 2.06321,-1.736079 3.1433,-1.785011 12.20439,-0.55291 9.63637,1.310309 10.70873,1.56224 12.28077,2.88503 1.64359,1.382979 2.2732,2.810909 2.25906,5.123309 -0.007,1.10173 -0.92172,8.29645 -2.03332,15.98826 -1.11158,7.69182 -1.97159,14.04091 -1.91113,14.1091 0.0605,0.0682 7.16644,1.11143 15.79109,2.31832 11.10566,1.55407 16.00827,2.38757 16.80223,2.85657 1.53015,0.90389 2.48023,2.64785 2.45017,4.49756 -0.0462,2.84349 -2.41252,18.12279 -2.97521,19.21089 -0.66164,1.27949 -2.60244,2.54696 -3.92109,2.56074 -0.51973,0.005 -7.87449,-0.95937 -16.34391,-2.144 -8.46944,-1.18464 -15.47588,-2.077 -15.56986,-1.98301 -0.094,0.094 -1.18792,7.34163 -2.43097,16.10589 -1.44004,10.15311 -2.49792,16.43621 -2.91556,17.31631 -0.72531,1.52848 -2.76261,3.06291 -4.53817,3.41802 -0.95688,0.19138 -10.90014,-0.92798 -13.59859,-1.53084 -0.5471,-0.12223 -1.89146,0.67252 -4.50941,2.66588 -11.2627,8.57562 -24.34195,13.90917 -38.35741,15.64164 -4.40038,0.54395 -15.72658,0.43298 -19.853658,-0.19451 z"
style="fill:#4972a5;fill-opacity:1;stroke:#4972a5;stroke-width:0.377976;stroke-opacity:1" />
</g>
</svg>

After

Width:  |  Height:  |  Size: 2.9 KiB

@ -1,6 +0,0 @@
<svg width="206" height="231" viewBox="0 0 206 231" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M143.143 84C143.143 96.1503 133.293 106 121.143 106C108.992 106 99.1426 96.1503 99.1426 84C99.1426 71.8497 108.992 62 121.143 62C133.293 62 143.143 71.8497 143.143 84Z" fill="#FFC131"/>
<ellipse cx="84.1426" cy="147" rx="22" ry="22" transform="rotate(180 84.1426 147)" fill="#24C8DB"/>
<path fill-rule="evenodd" clip-rule="evenodd" d="M166.738 154.548C157.86 160.286 148.023 164.269 137.757 166.341C139.858 160.282 141 153.774 141 147C141 144.543 140.85 142.121 140.558 139.743C144.975 138.204 149.215 136.139 153.183 133.575C162.73 127.404 170.292 118.608 174.961 108.244C179.63 97.8797 181.207 86.3876 179.502 75.1487C177.798 63.9098 172.884 53.4021 165.352 44.8883C157.82 36.3744 147.99 30.2165 137.042 27.1546C126.095 24.0926 114.496 24.2568 103.64 27.6274C92.7839 30.998 83.1319 37.4317 75.8437 46.1553C74.9102 47.2727 74.0206 48.4216 73.176 49.5993C61.9292 50.8488 51.0363 54.0318 40.9629 58.9556C44.2417 48.4586 49.5653 38.6591 56.679 30.1442C67.0505 17.7298 80.7861 8.57426 96.2354 3.77762C111.685 -1.01901 128.19 -1.25267 143.769 3.10474C159.348 7.46215 173.337 16.2252 184.056 28.3411C194.775 40.457 201.767 55.4101 204.193 71.404C206.619 87.3978 204.374 103.752 197.73 118.501C191.086 133.25 180.324 145.767 166.738 154.548ZM41.9631 74.275L62.5557 76.8042C63.0459 72.813 63.9401 68.9018 65.2138 65.1274C57.0465 67.0016 49.2088 70.087 41.9631 74.275Z" fill="#FFC131"/>
<path fill-rule="evenodd" clip-rule="evenodd" d="M38.4045 76.4519C47.3493 70.6709 57.2677 66.6712 67.6171 64.6132C65.2774 70.9669 64 77.8343 64 85.0001C64 87.1434 64.1143 89.26 64.3371 91.3442C60.0093 92.8732 55.8533 94.9092 51.9599 97.4256C42.4128 103.596 34.8505 112.392 30.1816 122.756C25.5126 133.12 23.9357 144.612 25.6403 155.851C27.3449 167.09 32.2584 177.598 39.7906 186.112C47.3227 194.626 57.153 200.784 68.1003 203.846C79.0476 206.907 90.6462 206.743 101.502 203.373C112.359 200.002 122.011 193.568 129.299 184.845C130.237 183.722 131.131 182.567 131.979 181.383C143.235 180.114 154.132 176.91 164.205 171.962C160.929 182.49 155.596 192.319 148.464 200.856C138.092 213.27 124.357 222.426 108.907 227.222C93.458 232.019 76.9524 232.253 61.3736 227.895C45.7948 223.538 31.8055 214.775 21.0867 202.659C10.3679 190.543 3.37557 175.59 0.949823 159.596C-1.47592 143.602 0.768139 127.248 7.41237 112.499C14.0566 97.7497 24.8183 85.2327 38.4045 76.4519ZM163.062 156.711L163.062 156.711C162.954 156.773 162.846 156.835 162.738 156.897C162.846 156.835 162.954 156.773 163.062 156.711Z" fill="#24C8DB"/>
</svg>

Before

Width:  |  Height:  |  Size: 2.5 KiB

@ -1,25 +0,0 @@
<?xml version="1.0" standalone="no"?>
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 20010904//EN"
"http://www.w3.org/TR/2001/REC-SVG-20010904/DTD/svg10.dtd">
<svg version="1.0" xmlns="http://www.w3.org/2000/svg"
width="512.000000pt" height="512.000000pt" viewBox="0 0 512.000000 512.000000"
preserveAspectRatio="xMidYMid meet">
<g transform="translate(0.000000,512.000000) scale(0.100000,-0.100000)"
fill="#2D79C7" stroke="none">
<path d="M430 5109 c-130 -19 -248 -88 -325 -191 -53 -71 -83 -147 -96 -247
-6 -49 -9 -813 -7 -2166 l3 -2090 22 -65 c54 -159 170 -273 328 -323 l70 -22
2140 0 2140 0 66 23 c160 55 272 169 322 327 l22 70 0 2135 0 2135 -22 70
c-49 157 -155 265 -319 327 l-59 23 -2115 1 c-1163 1 -2140 -2 -2170 -7z
m3931 -2383 c48 -9 120 -26 160 -39 l74 -23 3 -237 c1 -130 0 -237 -2 -237 -3
0 -26 14 -53 30 -61 38 -197 84 -310 106 -110 20 -293 15 -368 -12 -111 -39
-175 -110 -175 -193 0 -110 97 -197 335 -300 140 -61 309 -146 375 -189 30
-20 87 -68 126 -107 119 -117 164 -234 164 -426 0 -310 -145 -518 -430 -613
-131 -43 -248 -59 -445 -60 -243 -1 -405 24 -577 90 l-68 26 0 242 c0 175 -3
245 -12 254 -9 9 -9 12 0 12 7 0 12 -4 12 -9 0 -17 139 -102 223 -138 136 -57
233 -77 382 -76 145 0 224 19 295 68 75 52 100 156 59 242 -41 84 -135 148
-374 253 -367 161 -522 300 -581 520 -23 86 -23 253 -1 337 73 275 312 448
682 492 109 13 401 6 506 -13z m-1391 -241 l0 -205 -320 0 -320 0 0 -915 0
-915 -255 0 -255 0 0 915 0 915 -320 0 -320 0 0 205 0 205 895 0 895 0 0 -205z"/>
</g>
</svg>

Before

Width:  |  Height:  |  Size: 1.4 KiB

@ -1 +0,0 @@
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" aria-hidden="true" role="img" class="iconify iconify--logos" width="31.88" height="32" preserveAspectRatio="xMidYMid meet" viewBox="0 0 256 257"><defs><linearGradient id="IconifyId1813088fe1fbc01fb466" x1="-.828%" x2="57.636%" y1="7.652%" y2="78.411%"><stop offset="0%" stop-color="#41D1FF"></stop><stop offset="100%" stop-color="#BD34FE"></stop></linearGradient><linearGradient id="IconifyId1813088fe1fbc01fb467" x1="43.376%" x2="50.316%" y1="2.242%" y2="89.03%"><stop offset="0%" stop-color="#FFEA83"></stop><stop offset="8.333%" stop-color="#FFDD35"></stop><stop offset="100%" stop-color="#FFA800"></stop></linearGradient></defs><path fill="url(#IconifyId1813088fe1fbc01fb466)" d="M255.153 37.938L134.897 252.976c-2.483 4.44-8.862 4.466-11.382.048L.875 37.958c-2.746-4.814 1.371-10.646 6.827-9.67l120.385 21.517a6.537 6.537 0 0 0 2.322-.004l117.867-21.483c5.438-.991 9.574 4.796 6.877 9.62Z"></path><path fill="url(#IconifyId1813088fe1fbc01fb467)" d="M185.432.063L96.44 17.501a3.268 3.268 0 0 0-2.634 3.014l-5.474 92.456a3.268 3.268 0 0 0 3.997 3.378l24.777-5.718c2.318-.535 4.413 1.507 3.936 3.838l-7.361 36.047c-.495 2.426 1.782 4.5 4.151 3.78l15.304-4.649c2.372-.72 4.652 1.36 4.15 3.788l-11.698 56.621c-.732 3.542 3.979 5.473 5.943 2.437l1.313-2.028l72.516-144.72c1.215-2.423-.88-5.186-3.54-4.672l-25.505 4.922c-2.396.462-4.435-1.77-3.759-4.114l16.646-57.705c.677-2.35-1.37-4.583-3.769-4.113Z"></path></svg>

Before

Width:  |  Height:  |  Size: 1.5 KiB

@ -0,0 +1,34 @@
// Copyright (c) 2022-2025 Niko Bonnieure, Par le Peuple, NextGraph.org developers
// All rights reserved.
// Licensed under the Apache License, Version 2.0
// <LICENSE-APACHE2 or http://www.apache.org/licenses/LICENSE-2.0>
// or the MIT license <LICENSE-MIT or http://opensource.org/licenses/MIT>,
// at your option. All files in the project carrying such
// notice may not be copied, modified, or distributed except
// according to those terms.
import * as web_api from "@ng-org/lib-wasm";
import {init_api} from "@ng-org/ui-common/api";
init_api(web_api);
const NEW_VERSION = "0.1.2-alpha.1";
// cleaning old wallets :(
try {
let version = localStorage.getItem("ng_wallet_version");
if (!version || version != NEW_VERSION) {
localStorage.clear();
sessionStorage.clear();
localStorage.setItem("ng_wallet_version",NEW_VERSION)
}
}
catch (e) {
// it is ok to fail. it means access denied for local storage.
}
import { mount } from "svelte";
import App from "./App.svelte";
const app = mount(App, { target: document.getElementById("app") as Element });
export default app;

@ -1,22 +1,19 @@
import { invoke } from "@tauri-apps/api/core"; // Copyright (c) 2022-2025 Niko Bonnieure, Par le Peuple, NextGraph.org developers
// All rights reserved.
// Licensed under the Apache License, Version 2.0
// <LICENSE-APACHE2 or http://www.apache.org/licenses/LICENSE-2.0>
// or the MIT license <LICENSE-MIT or http://opensource.org/licenses/MIT>,
// at your option. All files in the project carrying such
// notice may not be copied, modified, or distributed except
// according to those terms.
let greetInputEl: HTMLInputElement | null; import native_api from "./native-api";
let greetMsgEl: HTMLElement | null; import {init_api} from "@ng-org/ui-common/api";
init_api(native_api);
async function greet() { import { mount } from "svelte";
if (greetMsgEl && greetInputEl) { import App from "./App.svelte";
// Learn more about Tauri commands at https://tauri.app/develop/calling-rust/
greetMsgEl.textContent = await invoke("greet", {
name: greetInputEl.value,
});
}
}
window.addEventListener("DOMContentLoaded", () => { const app = mount(App, { target: document.getElementById("app") as Element });
greetInputEl = document.querySelector("#greet-input");
greetMsgEl = document.querySelector("#greet-msg"); export default app;
document.querySelector("#greet-form")?.addEventListener("submit", (e) => {
e.preventDefault();
greet();
});
});

@ -0,0 +1,335 @@
// Copyright (c) 2022-2025 Niko Bonnieure, Par le Peuple, NextGraph.org developers
// All rights reserved.
// Licensed under the Apache License, Version 2.0
// <LICENSE-APACHE2 or http://www.apache.org/licenses/LICENSE-2.0>
// or the MIT license <LICENSE-MIT or http://opensource.org/licenses/MIT>,
// at your option. All files in the project carrying such
// notice may not be copied, modified, or distributed except
// according to those terms.
import {createAsyncProxy} from "async-proxy";
import { Bowser } from "../../../sdk/js/lib-wasm/jsland/bowser.js";
import {version} from '../package.json';
import { Window } from '@tauri-apps/api/window';
import { invoke } from "@tauri-apps/api/core";
import { listen } from "@tauri-apps/api/event";
const mapping = {
"privkey_to_string": ["privkey"],
"wallet_gen_shuffle_for_pazzle_opening": ["pazzle_length"],
"wallet_gen_shuffle_for_pin": [],
"wallet_open_with_pazzle": ["wallet","pazzle","pin"],
"wallet_open_with_mnemonic_words": ["wallet","mnemonic_words","pin"],
"wallet_open_with_mnemonic": ["wallet","mnemonic","pin"],
"wallet_was_opened": ["opened_wallet"],
"wallet_create": ["params"],
"wallet_read_file": ["file"],
"wallet_get_file": ["wallet_name"],
"wallet_import": ["encrypted_wallet","opened_wallet","in_memory"],
"wallet_export_rendezvous": ["session_id", "code"],
"wallet_export_get_qrcode": ["session_id", "size"],
"wallet_export_get_textcode": ["session_id"],
"wallet_import_rendezvous": ["size"],
"wallet_import_from_code": ["code"],
"wallet_close": ["wallet_name"],
"encode_create_account": ["payload"],
"session_start": ["wallet_name","user"],
"session_start_remote": ["wallet_name","user","peer_id"],
"session_stop": ["user_id"],
"get_wallets": [],
"open_window": ["url","label","title"],
"decode_invitation": ["invite"],
"user_connect": ["info","user_id","location"],
"user_disconnect": ["user_id"],
"discrete_update": ["session_id", "update", "heads", "crdt", "nuri"],
"app_request": ["request"],
"app_request_with_nuri_command": ["nuri", "command", "session_id", "payload"],
"sparql_query": ["session_id","sparql","base","nuri"],
"sparql_update": ["session_id","sparql","nuri"],
"test": [ ],
"get_device_name": [],
"doc_create": [ "session_id", "crdt", "class_name", "destination", "store_repo" ],
"doc_fetch_private_subscribe": [],
"doc_fetch_repo_subscribe": ["repo_o"],
"branch_history": ["session_id", "nuri"],
"file_save_to_downloads": ["session_id", "reference", "filename", "branch_nuri"],
"signature_status": ["session_id", "nuri"],
"signed_snapshot_request": ["session_id", "nuri"],
"signature_request": ["session_id", "nuri"],
"update_header": ["session_id","nuri","title","about"],
"fetch_header": ["session_id", "nuri"],
"retrieve_ng_bootstrap": ["location"],
}
let lastStreamId = 0;
const tauri_handler = {
async apply(target, path, caller, args) {
try {
if (path[0] === "open_window") {
let callback = args[3];
await invoke(path[0],{url:args[0],label:args[1],title:args[2]});
let unsub_register_accepted;
let unsub_register_error;
let unsub_register_close;
const unsub_register = function() {
if (unsub_register_accepted) unsub_register_accepted();
if (unsub_register_error) unsub_register_error();
if (unsub_register_close) unsub_register_close();
unsub_register_close = undefined;
unsub_register_error = undefined;
unsub_register_accepted = undefined;
};
unsub_register_accepted = await listen(
"accepted",
async (event) => {
unsub_register();
let reg_popup = Window.getByLabel("registration");
await reg_popup.close();
await (callback)("accepted",event.payload);
}
);
unsub_register_error = await listen("error", async (event) => {
unsub_register();
let reg_popup = Window.getByLabel("registration");
await reg_popup.close();
await (callback)("error",event.payload);
});
await new Promise((resolve) => setTimeout(resolve, 1000));
let reg_popup = Window.getByLabel("registration");
unsub_register_close = await reg_popup.onCloseRequested(async (event) => {
unsub_register_close = undefined;
unsub_register();
});
return unsub_register;
} else if (path[0] === "client_info") {
let from_rust = await invoke("client_info_rust",{});
let tauri_platform = import.meta.env.TAURI_ENV_PLATFORM;
let client_type;
switch (tauri_platform) {
case 'macos': client_type = "NativeMacOS";break;
case 'linux': client_type = "NativeLinux";break;
case 'windows': client_type = "NativeWin";break;
case 'android': client_type = "NativeAndroid";break;
case 'ios': client_type = "NativeIos";break;
}
let info = Bowser.parse(window.navigator.userAgent);
// info.os.type = import.meta.env.TAURI_ENV_PLATFORM_TYPE;
info.os.family = import.meta.env.TAURI_ENV_FAMILY;
info.os.version_tauri = import.meta.env.TAURI_ENV_PLATFORM_VERSION;
info.os.version_uname = from_rust.uname.version;
info.os.name_rust = from_rust.rust.os_name;
info.os.name_uname = from_rust.uname.os_name;
info.platform.arch = import.meta.env.TAURI_ENV_ARCH;
info.platform.debug = import.meta.env.TAURI_ENV_DEBUG;
info.platform.target = import.meta.env.TAURI_ENV_TARGET_TRIPLE;
info.platform.arch_uname = from_rust.uname.arch;
info.platform.bitness = from_rust.uname.bitness;
info.platform.codename = from_rust.uname.codename || undefined;
info.platform.edition = from_rust.uname.edition || undefined;
info.browser.ua = window.navigator.userAgent;
let res = {
// TODO: install timestamp
V0 : { client_type, details: JSON.stringify(info), version, timestamp_install:0, timestamp_updated:0 }
};
//console.log(info,res);
return res;
} else if (path[0] === "get_device_name") {
let tauri_platform = import.meta.env.TAURI_ENV_PLATFORM;
if (tauri_platform == 'android') return "Android Phone";
else if (tauri_platform == 'ios') return "iPhone";
else return await invoke(path[0],{});
} else if (path[0] === "locales") {
let from_rust = await invoke("locales",{});
let from_js = window.navigator.languages;
console.log(from_rust,from_js);
for (let lang of from_js) {
let split = lang.split("-");
if (split[1]) {
lang = split[0] + "-" + split[1].toUpperCase();
}
if (!from_rust.includes(lang)) { from_rust.push(lang);}
}
return from_rust;
} else if (path[0] === "disconnections_subscribe") {
let callback = args[0];
let unlisten = await Window.getCurrent().listen("disconnections", (event) => {
callback(event.payload).then(()=> {})
})
await invoke(path[0],{});
return () => {
unlisten();
}
} else if (path[0] === "user_connect") {
let arg = {};
args.map((el,ix) => arg[mapping[path[0]][ix]]=el)
let ret = await invoke(path[0],arg);
for (let e of Object.entries(ret)) {
e[1].since = new Date(e[1].since);
}
return ret;
}
else if (path[0] === "file_get") {
let stream_id = (lastStreamId += 1).toString();
//console.log("stream_id",stream_id);
//let session_id = args[0];
let callback = args[3];
let unlisten = await Window.getCurrent().listen(stream_id, async (event) => {
//console.log(event.payload);
if (event.payload.V0.FileBinary) {
event.payload.V0.FileBinary = Uint8Array.from(event.payload.V0.FileBinary);
}
let ret = callback(event.payload);
if (ret === true) {
await invoke("cancel_stream", {stream_id});
} else if (ret.then) {
ret.then(async (val)=> {
if (val === true) {
await invoke("cancel_stream", {stream_id});
}
});
}
})
try {
await invoke("file_get",{stream_id, session_id:args[0], reference: args[1], branch_nuri:args[2]});
} catch (e) {
unlisten();
await invoke("cancel_stream", {stream_id});
throw e;
}
return () => {
unlisten();
tauri.invoke("cancel_stream", {stream_id});
}
} else if (path[0] === "discrete_update") {
let arg = {};
args.map((el,ix) => arg[mapping[path[0]][ix]]=el)
arg.update = Array.from(new Uint8Array(arg.update));
return await invoke(path[0],arg)
} else if (path[0] === "app_request_stream") {
let stream_id = (lastStreamId += 1).toString();
//console.log("stream_id",stream_id);
//let session_id = args[0];
let request = args[0];
let callback = args[1];
let unlisten = await Window.getCurrent().listen(stream_id, async (event) => {
//console.log(event.payload);
if (event.payload.V0.FileBinary) {
event.payload.V0.FileBinary = Uint8Array.from(event.payload.V0.FileBinary);
}
if (event.payload.V0.State?.graph?.triples) {
let json_str = new TextDecoder().decode(Uint8Array.from(event.payload.V0.State.graph.triples));
event.payload.V0.State.graph.triples = JSON.parse(json_str);
} else if (event.payload.V0.Patch?.graph) {
let inserts_json_str = new TextDecoder().decode(Uint8Array.from(event.payload.V0.Patch.graph.inserts));
event.payload.V0.Patch.graph.inserts = JSON.parse(inserts_json_str);
let removes_json_str = new TextDecoder().decode(Uint8Array.from(event.payload.V0.Patch.graph.removes));
event.payload.V0.Patch.graph.removes = JSON.parse(removes_json_str);
}
if (event.payload.V0.State?.discrete) {
let crdt = Object.getOwnPropertyNames(event.payload.V0.State.discrete)[0];
event.payload.V0.State.discrete[crdt] = Uint8Array.from(event.payload.V0.State.discrete[crdt]);
} else if (event.payload.V0.Patch?.discrete) {
let crdt = Object.getOwnPropertyNames(event.payload.V0.Patch.discrete)[0];
event.payload.V0.Patch.discrete[crdt] = Uint8Array.from(event.payload.V0.Patch.discrete[crdt]);
}
let ret = callback(event.payload);
if (ret === true) {
await invoke("cancel_stream", {stream_id});
} else if (ret.then) {
ret.then(async (val)=> {
if (val === true) {
await invoke("cancel_stream", {stream_id});
}
});
}
})
try {
await invoke("app_request_stream",{stream_id, request});
} catch (e) {
unlisten();
await invoke("cancel_stream", {stream_id});
throw e;
}
return () => {
unlisten();
tauri.invoke("cancel_stream", {stream_id});
}
} else if (path[0] === "get_wallets") {
let res = await invoke(path[0],{});
if (res) for (let e of Object.entries(res)) {
e[1].wallet.V0.content.security_img = Uint8Array.from(e[1].wallet.V0.content.security_img);
}
return res || {};
} else if (path[0] === "wallet_import_from_code") {
let arg = {};
args.map((el,ix) => arg[mapping[path[0]][ix]]=el);
let res = await invoke(path[0],arg);
if (res) {
res.V0.content.security_img = Uint8Array.from(res.V0.content.security_img);
}
return res || {};
} else if (path[0] === "upload_chunk") {
let session_id = args[0];
let upload_id = args[1];
let chunk = args[2];
let nuri = args[3];
chunk = Array.from(new Uint8Array(chunk));
return await invoke(path[0],{session_id, upload_id, chunk, nuri})
} else if (path[0] === "wallet_create") {
let params = args[0];
params.result_with_wallet_file = false;
params.security_img = Array.from(new Uint8Array(params.security_img));
return await invoke(path[0],{params})
} else if (path[0] === "wallet_read_file") {
let file = args[0];
file = Array.from(new Uint8Array(file));
return await invoke(path[0],{file})
} else if (path[0] === "wallet_import") {
let encrypted_wallet = args[0];
encrypted_wallet.V0.content.security_img = Array.from(new Uint8Array(encrypted_wallet.V0.content.security_img));
return await invoke(path[0],{encrypted_wallet, opened_wallet:args[1], in_memory:args[2]})
} else if (path[0] && path[0].startsWith("get_local_bootstrap")) {
return false;
} else if (path[0] === "get_local_url") {
return false;
} else if (path[0] === "wallet_open_with_pazzle" || path[0] === "wallet_open_with_mnemonic_words" || path[0] === "wallet_open_with_mnemonic") {
let arg:any = {};
args.map((el,ix) => arg[mapping[path[0]][ix]]=el)
let img = Array.from(new Uint8Array(arg.wallet.V0.content.security_img));
let old_content = arg.wallet.V0.content;
arg.wallet = {V0:{id:arg.wallet.V0.id, sig:arg.wallet.V0.sig, content:{}}};
Object.assign(arg.wallet.V0.content,old_content);
arg.wallet.V0.content.security_img = img;
return await invoke(path[0],arg);
} else {
let arg = {};
args.map((el,ix) => arg[mapping[path[0]][ix]]=el)
return await invoke(path[0],arg)
}
} catch (e) {
let error;
try {
error = JSON.parse(e);
} catch (f) {
error = e;
}
throw error;
}
}
};
const tauri_api = createAsyncProxy({}, tauri_handler);
export default tauri_api;

@ -1,116 +1,3 @@
.logo.vite:hover { @import "tailwindcss";
filter: drop-shadow(0 0 2em #747bff); @plugin "daisyui";
} @plugin "@tailwindcss/typography";
.logo.typescript:hover {
filter: drop-shadow(0 0 2em #2d79c7);
}
:root {
font-family: Inter, Avenir, Helvetica, Arial, sans-serif;
font-size: 16px;
line-height: 24px;
font-weight: 400;
color: #0f0f0f;
background-color: #f6f6f6;
font-synthesis: none;
text-rendering: optimizeLegibility;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
-webkit-text-size-adjust: 100%;
}
.container {
margin: 0;
padding-top: 10vh;
display: flex;
flex-direction: column;
justify-content: center;
text-align: center;
}
.logo {
height: 6em;
padding: 1.5em;
will-change: filter;
transition: 0.75s;
}
.logo.tauri:hover {
filter: drop-shadow(0 0 2em #24c8db);
}
.row {
display: flex;
justify-content: center;
}
a {
font-weight: 500;
color: #646cff;
text-decoration: inherit;
}
a:hover {
color: #535bf2;
}
h1 {
text-align: center;
}
input,
button {
border-radius: 8px;
border: 1px solid transparent;
padding: 0.6em 1.2em;
font-size: 1em;
font-weight: 500;
font-family: inherit;
color: #0f0f0f;
background-color: #ffffff;
transition: border-color 0.25s;
box-shadow: 0 2px 2px rgba(0, 0, 0, 0.2);
}
button {
cursor: pointer;
}
button:hover {
border-color: #396cd8;
}
button:active {
border-color: #396cd8;
background-color: #e8e8e8;
}
input,
button {
outline: none;
}
#greet-input {
margin-right: 5px;
}
@media (prefers-color-scheme: dark) {
:root {
color: #f6f6f6;
background-color: #2f2f2f;
}
a:hover {
color: #24c8db;
}
input,
button {
color: #ffffff;
background-color: #0f0f0f98;
}
button:active {
background-color: #0f0f0f69;
}
}

@ -0,0 +1,11 @@
// svelte.config.js
export default {
compilerOptions: {
experimental: {
async: true
}
},
vitePlugin: {
//inspector: true
}
};

@ -0,0 +1,11 @@
/** @type {import('tailwindcss').Config} */
export default {
content: ["./src/**/*.{html,js,svelte,ts}"],
theme: {
extend: {}
},
plugins: [],
daisyui: {
//themes: ['valentine']
}
};

@ -1,4 +1,5 @@
{ {
"extends": "@tsconfig/svelte/tsconfig.json",
"compilerOptions": { "compilerOptions": {
"target": "ES2020", "target": "ES2020",
"useDefineForClassFields": true, "useDefineForClassFields": true,
@ -19,5 +20,5 @@
"noUnusedParameters": true, "noUnusedParameters": true,
"noFallthroughCasesInSwitch": true "noFallthroughCasesInSwitch": true
}, },
"include": ["src"] "include": ["src/**/*.ts", "src/**/*.js", "src/**/*.svelte"]
} }

@ -1,43 +1,167 @@
import { defineConfig } from "vite"; import tailwindcss from "@tailwindcss/vite";
import { defineConfig, UserConfig } from "vite";
import { svelte } from "@sveltejs/vite-plugin-svelte";
import { viteSingleFile } from "vite-plugin-singlefile"
import svelteSVG from "@hazycora/vite-plugin-svelte-svg";
import wasm from "vite-plugin-wasm";
import topLevelAwait from "vite-plugin-top-level-await";
// @ts-expect-error process is a nodejs global
const host = process.env.TAURI_DEV_HOST; const host = process.env.TAURI_DEV_HOST;
// https://vite.dev/config/ // https://vite.dev/config/
export default defineConfig(async () => ({ export default defineConfig((): UserConfig => {
const worker_plugins = [];
// Vite options tailored for Tauri development and only applied in `tauri dev` or `tauri build` const config = {
// worker: {
// 1. prevent Vite from obscuring rust errors format: 'es',
clearScreen: false, plugins : [
// 2. tauri expects a fixed port, fail if that port is not available ]
server: { },
port: 5173, plugins: [
strictPort: true, tailwindcss(),
host: host || false, svelte(),
hmr: host svelteSVG({
? { svgoConfig: {
protocol: "ws", plugins: [
host, {
port: 1421, name: 'preset-default',
params: {
overrides: {
// disable plugins
removeViewBox: false,
},
},
},
{
name: 'prefixIds',
}
],
}, // See https://github.com/svg/svgo#configuration
requireSuffix: true, // Set false to accept '.svg' without the '?component'
}),
],
// Vite options tailored for Tauri development and only applied in `tauri dev` or `tauri build`
//
// 1. prevent Vite from obscuring rust errors
clearScreen: false,
// 2. tauri expects a fixed port, fail if that port is not available
server: {
port: process.env.NG_ENV_WEB ? 1421 : 1420,
strictPort: true,
host: host || false,
hmr: host
? {
protocol: "ws",
host,
port: process.env.NG_ENV_WEB ? 1421 : 1420,
}
: undefined,
watch: {
// 3. tell Vite to ignore watching `src-tauri`
ignored: ["**/src-tauri/**"]
}
},
publicDir: process.env.NG_PUBLIC_DEV ? "public_dev" : false,
// Env variables starting with the item of `envPrefix` will be exposed in tauri's source code through `import.meta.env`.
envPrefix: ["VITE_", "TAURI_ENV_", "NG_ENV_"],
build: {
outDir: process.env.NG_ENV_WEB ? "dist-web" : "dist",
// Tauri uses Chromium on Windows and WebKit on macOS and Linux
target: process.env.TAURI_ENV_PLATFORM == "windows" ? "chrome105" : "safari13",
// don't minify for debug builds
minify: !process.env.TAURI_ENV_DEBUG ? "esbuild" : false,
// produce sourcemaps for debug builds
sourcemap: !!process.env.TAURI_ENV_DEBUG
}
};
if (process.env.NG_ENV_WEB) {
if (process.env.NG_ENV_ONEFILE) {
config.plugins.push(viteSingleFile());
worker_plugins.push(viteSingleFile());
config.plugins.push(
{
name: 'move-script-body',
transformIndexHtml: {
order: 'post',
handler: function transform(html) {
let scriptTag = html.match(/<script type[^>]*>(.*?)<\/script[^>]*>/)[0]
//console.log("\n SCRIPT TAG", scriptTag, "\n")
html = html.replace(scriptTag, "")
html = html.replace("<!-- # INSERT SCRIPT HERE -->", scriptTag)
return html;
}
}
}
);
} }
: undefined, config.plugins.push(topLevelAwait());
watch: { config.plugins.push(wasm());
// 3. tell Vite to ignore watching `src-tauri` worker_plugins.push(topLevelAwait());
ignored: ["**/src-tauri/**"], worker_plugins.push(wasm());
}, config.plugins.push(
}, {
// Env variables starting with the item of `envPrefix` will be exposed in tauri's source code through `import.meta.env`. name: 'inject-web-script',
envPrefix: ['VITE_', 'TAURI_ENV_*'], transformIndexHtml: {
build: { order: 'pre', // Tells Vite to run this before other processes
// Tauri uses Chromium on Windows and WebKit on macOS and Linux handler: function transform() {
target: return [
process.env.TAURI_ENV_PLATFORM == 'windows' {
? 'chrome105' tag: "script",
: 'safari13', children: "check_supported=true;",
// don't minify for debug builds injectTo: "head"
minify: !process.env.TAURI_ENV_DEBUG ? 'esbuild' : false, },
// produce sourcemaps for debug builds {
sourcemap: !!process.env.TAURI_ENV_DEBUG, tag: "script",
}, attrs: {
})); "type": "module",
"src": "/src/main-web.ts",
"defer": true
},
injectTo: "head"
}]
}
}
}
);
} else {
config.plugins.push(
{
name: 'inject-native-script',
transformIndexHtml: {
order: 'pre', // Tells Vite to run this before other processes
handler: function transform() {
return [
{
tag: "script",
children: "check_supported=false;",
injectTo: "head"
},
{
tag: "script",
attrs: {
"type": "module",
"src": "/src/main.ts",
"defer": true
},
injectTo: "head"
}]
}
}
}
);
config.plugins.push(
{
name: 'make-script-defer',
transformIndexHtml: {
order: 'post',
handler: function transform(html) {
let new_html = html.replace("<script type","<script defer type");
return new_html;
}
}
}
);
}
config.worker.plugins = () => {return worker_plugins;};
return config;
});

@ -42,6 +42,8 @@ See [Build release binaries](../DEV.md#build-release-binaries) in the main READM
ngd --save-key -l 1440 --save-config ngd --save-key -l 1440 --save-config
``` ```
Note that for development, we use port 14400 while in production, port 1440 is used.
In the logs/output, you will see a link that you should open in your web browser. If there are many links, choose the one that starts with `http://localhost:`. In the logs/output, you will see a link that you should open in your web browser. If there are many links, choose the one that starts with `http://localhost:`.
The computer you use to open the link should have direct access to the ngd server on localhost. In most of the cases, it will work, as you are running ngd on localhost. If you are running ngd in a docker container, then you need to give access to the container to the local network of the host by using `docker run --network="host"`. see more here https://docs.docker.com/network/drivers/host/ The computer you use to open the link should have direct access to the ngd server on localhost. In most of the cases, it will work, as you are running ngd on localhost. If you are running ngd in a docker container, then you need to give access to the container to the local network of the host by using `docker run --network="host"`. see more here https://docs.docker.com/network/drivers/host/
@ -73,9 +75,9 @@ ngcli --save-key --save-config -s 127.0.0.1,1440,<PEER_ID_OF_SERVER> -u <THE_PRI
Licensed under either of Licensed under either of
- Apache License, Version 2.0 ([LICENSE-APACHE2](LICENSE-APACHE2) or http://www.apache.org/licenses/LICENSE-2.0) - Apache License, Version 2.0 ([LICENSE-APACHE2](LICENSE-APACHE2) or http://www.apache.org/licenses/LICENSE-2.0)
- MIT license ([LICENSE-MIT](LICENSE-MIT) or http://opensource.org/licenses/MIT) - MIT license ([LICENSE-MIT](LICENSE-MIT) or http://opensource.org/licenses/MIT)
at your option. at your option.
`SPDX-License-Identifier: Apache-2.0 OR MIT` `SPDX-License-Identifier: Apache-2.0 OR MIT`

@ -8,7 +8,7 @@
// according to those terms. // according to those terms.
import "./app.postcss"; import "./app.postcss";
import "../../../common/src/styles.css"; import "../../../../app/ui-common/src/styles.css";
import App from "./App.svelte"; import App from "./App.svelte";
import { fromWritablePort } from 'remote-web-streams'; import { fromWritablePort } from 'remote-web-streams';
import web_api from "@ng-org/api-web"; import web_api from "@ng-org/api-web";

@ -193,13 +193,13 @@ fn prepare_urls_from_private_addrs(addrs: &Vec<BindAddress>, port: u16) -> Vec<S
} }
#[derive(RustEmbed)] #[derive(RustEmbed)]
#[folder = "../../app/nextgraph/dist-file/"] #[folder = "../../app/nextgraph/dist-web/"]
#[include = "*.sha256"] #[include = "*.sha256"]
#[include = "*.gzip"] #[include = "*.gzip"]
struct App; struct App;
#[derive(RustEmbed)] #[derive(RustEmbed)]
#[folder = "../auth/dist/"] #[folder = "./auth/dist/"]
#[include = "*.sha256"] #[include = "*.sha256"]
#[include = "*.gzip"] #[include = "*.gzip"]

@ -1,7 +1,7 @@
{ {
"name": "ng-account-web", "name": "ng-account-web",
"private": true, "private": true,
"version": "0.1.0", "version": "0.1.2",
"type": "module", "type": "module",
"scripts": { "scripts": {
"dev": "cross-env NG_ACCOUNT_DOMAIN=example.com vite", "dev": "cross-env NG_ACCOUNT_DOMAIN=example.com vite",

@ -1,7 +1,7 @@
{ {
"name": "@ng-org/net-redir", "name": "@ng-org/net-redir",
"private": true, "private": true,
"version": "0.1.0", "version": "0.1.2",
"type": "module", "type": "module",
"scripts": { "scripts": {
"dev": "vite", "dev": "vite",

@ -2,7 +2,10 @@
"name": "ng-org", "name": "ng-org",
"private": true, "private": true,
"version": "0.1.2", "version": "0.1.2",
"scripts": {}, "scripts": {
"buildfront": "cargo run-script libwasm && pnpm -C ./app/nextgraph install && pnpm -C ./app/nextgraph webbuild && pnpm -C ./engine/broker/auth install && pnpm -C ./engine/broker/auth build",
"buildfrontdev": "pnpm -C ./engine/broker/auth builddev && pnpm -C ./infra/ngnet/bootstrap builddev && pnpm -C ./infra/ngnet/auth builddev && pnpm -C ./infra/ngnet/redir builddev"
},
"pnpm": { "pnpm": {
"peerDependencyRules": { "peerDependencyRules": {
"ignoreMissing": [ "ignoreMissing": [

File diff suppressed because it is too large Load Diff

@ -0,0 +1,86 @@
# JS SDK of NextGraph
## NextGraph
> NextGraph brings about the convergence of P2P and Semantic Web technologies, towards a decentralized, secure and privacy-preserving cloud, based on CRDTs.
>
> This open source ecosystem provides solutions for end-users (a platform) and software developers (a framework), wishing to use or create **decentralized** apps featuring: **live collaboration** on rich-text documents, peer to peer communication with **end-to-end encryption**, offline-first, **local-first**, portable and interoperable data, total ownership of data and software, security and privacy. Centered on repositories containing **semantic data** (RDF), **rich text**, and structured data formats like **JSON**, synced between peers belonging to permissioned groups of users, it offers strong eventual consistency, thanks to the use of **CRDTs**. Documents can be linked together, signed, shared securely, queried using the **SPARQL** language and organized into sites and containers.
>
> More info here [https://nextgraph.org](https://nextgraph.org)
## WASM module
The [lib-wasm](../lib-wasm/README.md) crate contains the WASM module.
## Examples
- an example of web app using the vite bundler `example-webapp-vite`
- an example of React web app `app-react`
- an example of node-js app `app-node`
- `index.html` an example of vanilla JS usage of the SDK
## Support
Documentation can be found here [https://docs.nextgraph.org](https://docs.nextgraph.org)
And our community forum where you can ask questions is here [https://forum.nextgraph.org](https://forum.nextgraph.org)
## For developers
Read our [getting started guide](https://docs.nextgraph.org/en/getting-started/).
```
// for nodejs
npm i nextgraph
// or for browser
npm i nextgraphweb
```
## Publishing to npm
```
cargo run-script node
cd pkg-node
npm login --auth-type legacy
npm publish --auth-type legacy
```
### Example Plain JS web app (with Vite)
see [README here](example-webapp-vite/README.md)
### Example React web app
```
cd ../app-react
npm run dev
```
This URL will open automatically in browser : [http://localhost:8080](http://localhost:8080)
### Example NodeJS app
```
cd ../app-node
npm run start
```
### Contributions license
Unless you explicitly state otherwise, any contribution intentionally submitted
for inclusion in the work by you shall be dual licensed as below, without any
additional terms or conditions.
## License
Licensed under either of
- Apache License, Version 2.0 ([LICENSE-APACHE2](LICENSE-APACHE2) or http://www.apache.org/licenses/LICENSE-2.0)
- MIT license ([LICENSE-MIT](LICENSE-MIT) or http://opensource.org/licenses/MIT)
at your option.
`SPDX-License-Identifier: Apache-2.0 OR MIT`
---
NextGraph received funding through the [NGI Assure Fund](https://nlnet.nl/assure) and the [NGI Zero Commons Fund](https://nlnet.nl/commonsfund/), both funds established by [NLnet](https://nlnet.nl/) Foundation with financial support from the European Commission's [Next Generation Internet](https://ngi.eu/) programme, under the aegis of DG Communications Networks, Content and Technology under grant agreements No 957073 and No 101092990, respectively.

@ -1,10 +1,10 @@
# lib-wasm # JS SDK of NextGraph
[![Apache 2.0 Licensed][license-image]][license-link] [![Apache 2.0 Licensed][license-image]][license-link]
[![MIT Licensed][license-image2]][license-link2] [![MIT Licensed][license-image2]][license-link2]
[![project chat](https://img.shields.io/badge/zulip-join_chat-brightgreen.svg)](https://forum.nextgraph.org) [![project chat](https://img.shields.io/badge/zulip-join_chat-brightgreen.svg)](https://forum.nextgraph.org)
JavaScript/WASM package containing the SDK of NextGraph JavaScript package containing the SDK of NextGraph
## NextGraph ## NextGraph
@ -25,7 +25,7 @@ And our community forum where you can ask questions is here [https://forum.nextg
Read our [getting started guide](https://docs.nextgraph.org/en/getting-started/). Read our [getting started guide](https://docs.nextgraph.org/en/getting-started/).
``` ```
npm i lib-wasm npm i @ng-org/web
``` ```
The API is divided in 4 parts: The API is divided in 4 parts:

@ -1,6 +1,4 @@
# lib-wasm # WASM module
JS/WASM crate containing the SDK of NextGraph
## NextGraph ## NextGraph
@ -10,33 +8,6 @@ JS/WASM crate containing the SDK of NextGraph
> >
> More info here [https://nextgraph.org](https://nextgraph.org) > More info here [https://nextgraph.org](https://nextgraph.org)
## JS/WASM module
This crate is composed of
- the npm package `lib-wasm` which is the SDK
- an example of web app using the vite bundler `example-webapp-vite`
- an example of React web app `app-react`
- an example of node-js app `app-node`
- `index.html` an example of vanilla JS usage of the SDK
## Support
Documentation can be found here [https://docs.nextgraph.org](https://docs.nextgraph.org)
And our community forum where you can ask questions is here [https://forum.nextgraph.org](https://forum.nextgraph.org)
## For developers
Read our [getting started guide](https://docs.nextgraph.org/en/getting-started/).
```
// for nodejs
npm i nextgraph
// or for browser
npm i nextgraphweb
```
## For contributors ## For contributors
First of all, run: First of all, run:
@ -45,8 +16,6 @@ First of all, run:
cargo install cargo-run-script cargo install cargo-run-script
``` ```
We recommend contributors to use the production build, as the creation and opening of wallets is very slow in the dev build.
Only use the dev build when debugging the sdk. see the next chapter for the production build.
Please note that the dev and prod builds share the same output folder, they thus override each other. Please note that the dev and prod builds share the same output folder, they thus override each other.
When building the app, be sure to have the production build of the SDK in the output folder. When building the app, be sure to have the production build of the SDK in the output folder.
@ -77,45 +46,15 @@ wasm-pack test --chrome --headless
``` ```
cargo run-script app cargo run-script app
tar --exclude .DS_Store -zcvf pkg.tar.gz pkg
cargo run-script node cargo run-script node
cargo run-script web cargo run-script web
``` ```
## Publishing to npm
```
cargo run-script node
cd pkg-node
npm login --auth-type legacy
npm publish --auth-type legacy
```
### Example Plain JS web app (with Vite)
see [README here](example-webapp-vite/README.md)
### Example React web app
```
cd ../app-react
npm run dev
```
This URL will open automatically in browser : [http://localhost:8080](http://localhost:8080)
### Example NodeJS app
```
cd ../app-node
npm run start
```
### Contributions license ### Contributions license
Unless you explicitly state otherwise, any contribution intentionally submitted Unless you explicitly state otherwise, any contribution intentionally submitted
for inclusion in the work by you shall be dual licensed as below, without any for inclusion in the work by you shall be dual licensed as below, without any
additional terms or conditions.s additional terms or conditions.
## License ## License

@ -7,39 +7,6 @@
// notice may not be copied, modified, or distributed except // notice may not be copied, modified, or distributed except
// according to those terms. // according to those terms.
let ls;
let ss;
let no_local_storage; false;
(async () => {
try {
ls = localStorage;
ss = sessionStorage;
try {
let ret = await document.requestStorageAccess({ localStorage: true, sessionStorage: true });
ls = ret.localStorage;
ss = ret.sessionStorage;
console.log("REQUEST STORAGE ACCESS GRANTED by chrome");
}
catch(e) {
console.warn("requestStorageAccess of chrome failed. falling back to previous api", e)
try {
await document.requestStorageAccess();
localStorage;
console.log("REQUEST STORAGE ACCESS GRANTED");
} catch (e) {
console.error("REQUEST STORAGE ACCESS DENIED",e);
no_local_storage = true;
}
}
} catch (e) {
no_local_storage = true;
console.log("no access to localStorage")
}
})();
export function client_details() { export function client_details() {
return window.navigator.userAgent; return window.navigator.userAgent;
} }
@ -56,8 +23,7 @@ export function client_details2(obj,version) {
export function session_save(key,value) { export function session_save(key,value) {
try { try {
ss.setItem(key, value); sessionStorage.setItem(key, value);
} catch(e) { } catch(e) {
console.error(e); console.error(e);
return convert_error(e.message); return convert_error(e.message);
@ -83,31 +49,24 @@ function convert_error(e) {
} }
export function session_get(key) { export function session_get(key) {
try { try {
return ss.getItem(key); return sessionStorage.getItem(key);
} catch(e) { } catch(e) {
console.error(e); console.error(e);
} }
} }
export function session_remove(key) { export function session_remove(key) {
try { try {
return ss.removeItem(key); return sessionStorage.removeItem(key);
} catch(e) { } catch(e) {
console.error(e); console.error(e);
} }
} }
export function local_save(key,value) { export function local_save(key,value) {
try { try {
ls.setItem(key, value); localStorage.setItem(key, value);
} catch(e) { } catch(e) {
console.error(e); console.error(e);
return convert_error(e.message); return convert_error(e.message);
@ -116,21 +75,17 @@ export function local_save(key,value) {
export function storage_clear() { export function storage_clear() {
try { try {
ls.clear(); localStorage.clear();
ss.clear(); sessionStorage.clear();
} catch(e) { } catch(e) {
console.error(e); console.error(e);
} }
} }
export function local_get(key) { export function local_get(key) {
try { try {
return ls.getItem(key); return localStorage.getItem(key);
} catch(e) { } catch(e) {
console.error(e); console.error(e);
} }
} }

@ -0,0 +1,181 @@
# This file is autogenerated by maturin v1.8.2
# To update, run
#
# maturin generate-ci github
#
name: CI
on:
push:
branches:
- main
- master
tags:
- '*'
pull_request:
workflow_dispatch:
permissions:
contents: read
jobs:
linux:
runs-on: ${{ matrix.platform.runner }}
strategy:
matrix:
platform:
- runner: ubuntu-22.04
target: x86_64
- runner: ubuntu-22.04
target: x86
- runner: ubuntu-22.04
target: aarch64
- runner: ubuntu-22.04
target: armv7
- runner: ubuntu-22.04
target: s390x
- runner: ubuntu-22.04
target: ppc64le
steps:
- uses: actions/checkout@v4
- uses: actions/setup-python@v5
with:
python-version: 3.x
- name: Build wheels
uses: PyO3/maturin-action@v1
with:
target: ${{ matrix.platform.target }}
args: --release --out dist --find-interpreter
sccache: ${{ !startsWith(github.ref, 'refs/tags/') }}
manylinux: auto
- name: Upload wheels
uses: actions/upload-artifact@v4
with:
name: wheels-linux-${{ matrix.platform.target }}
path: dist
musllinux:
runs-on: ${{ matrix.platform.runner }}
strategy:
matrix:
platform:
- runner: ubuntu-22.04
target: x86_64
- runner: ubuntu-22.04
target: x86
- runner: ubuntu-22.04
target: aarch64
- runner: ubuntu-22.04
target: armv7
steps:
- uses: actions/checkout@v4
- uses: actions/setup-python@v5
with:
python-version: 3.x
- name: Build wheels
uses: PyO3/maturin-action@v1
with:
target: ${{ matrix.platform.target }}
args: --release --out dist --find-interpreter
sccache: ${{ !startsWith(github.ref, 'refs/tags/') }}
manylinux: musllinux_1_2
- name: Upload wheels
uses: actions/upload-artifact@v4
with:
name: wheels-musllinux-${{ matrix.platform.target }}
path: dist
windows:
runs-on: ${{ matrix.platform.runner }}
strategy:
matrix:
platform:
- runner: windows-latest
target: x64
- runner: windows-latest
target: x86
steps:
- uses: actions/checkout@v4
- uses: actions/setup-python@v5
with:
python-version: 3.x
architecture: ${{ matrix.platform.target }}
- name: Build wheels
uses: PyO3/maturin-action@v1
with:
target: ${{ matrix.platform.target }}
args: --release --out dist --find-interpreter
sccache: ${{ !startsWith(github.ref, 'refs/tags/') }}
- name: Upload wheels
uses: actions/upload-artifact@v4
with:
name: wheels-windows-${{ matrix.platform.target }}
path: dist
macos:
runs-on: ${{ matrix.platform.runner }}
strategy:
matrix:
platform:
- runner: macos-13
target: x86_64
- runner: macos-14
target: aarch64
steps:
- uses: actions/checkout@v4
- uses: actions/setup-python@v5
with:
python-version: 3.x
- name: Build wheels
uses: PyO3/maturin-action@v1
with:
target: ${{ matrix.platform.target }}
args: --release --out dist --find-interpreter
sccache: ${{ !startsWith(github.ref, 'refs/tags/') }}
- name: Upload wheels
uses: actions/upload-artifact@v4
with:
name: wheels-macos-${{ matrix.platform.target }}
path: dist
sdist:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Build sdist
uses: PyO3/maturin-action@v1
with:
command: sdist
args: --out dist
- name: Upload sdist
uses: actions/upload-artifact@v4
with:
name: wheels-sdist
path: dist
release:
name: Release
runs-on: ubuntu-latest
if: ${{ startsWith(github.ref, 'refs/tags/') || github.event_name == 'workflow_dispatch' }}
needs: [linux, musllinux, windows, macos, sdist]
permissions:
# Use to sign the release artifacts
id-token: write
# Used to upload release artifacts
contents: write
# Used to generate artifact attestation
attestations: write
steps:
- uses: actions/download-artifact@v4
- name: Generate artifact attestation
uses: actions/attest-build-provenance@v1
with:
subject-path: 'wheels-*/*'
- name: Publish to PyPI
if: ${{ startsWith(github.ref, 'refs/tags/') }}
uses: PyO3/maturin-action@v1
env:
MATURIN_PYPI_TOKEN: ${{ secrets.PYPI_API_TOKEN }}
with:
command: upload
args: --non-interactive --skip-existing wheels-*/*

@ -0,0 +1,72 @@
/target
.env/
# Byte-compiled / optimized / DLL files
__pycache__/
.pytest_cache/
*.py[cod]
# C extensions
*.so
# Distribution / packaging
.Python
.venv/
env/
bin/
build/
develop-eggs/
dist/
eggs/
lib/
lib64/
parts/
sdist/
var/
include/
man/
venv/
*.egg-info/
.installed.cfg
*.egg
# Installer logs
pip-log.txt
pip-delete-this-directory.txt
pip-selfcheck.json
# Unit test / coverage reports
htmlcov/
.tox/
.coverage
.cache
nosetests.xml
coverage.xml
# Translations
*.mo
# Mr Developer
.mr.developer.cfg
.project
.pydevproject
# Rope
.ropeproject
# Django stuff:
*.log
*.pot
.DS_Store
# Sphinx documentation
docs/_build/
# PyCharm
.idea/
# VSCode
.vscode/
# Pyenv
.python-version

@ -0,0 +1,25 @@
[package]
name = "ng-sdk-python"
version.workspace = true
description = "NextGraph python package. Nextgraph is a decentralized, secure and local-first web 3.0 ecosystem based on Semantic Web and CRDTs"
edition.workspace = true
license.workspace = true
authors.workspace = true
repository.workspace = true
homepage.workspace = true
keywords = [ "crdt","e2ee","local-first","p2p","semantic-web" ]
documentation.workspace = true
rust-version.workspace = true
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[lib]
name = "nextgraphpy"
crate-type = ["cdylib"]
[dependencies]
pyo3 = "0.23.3"
pyo3-async-runtimes = { version = "0.23", features = ["async-std-runtime"] }
pythonize = "0.23.0"
async-std = "1.12.0"
serde = { version = "1.0.142", features = ["derive"] }
nextgraph = { path = "../rust" }

@ -0,0 +1,63 @@
<p align="center">
<img src="https://git.nextgraph.org/NextGraph/nextgraph-rs/raw/branch/master/nextgraph/.static/header.png" alt="nextgraph-header" />
</p>
# nextgraphpy
![MSRV][rustc-image]
[![Apache 2.0 Licensed][license-image]][license-link]
[![MIT Licensed][license-image2]][license-link2]
[![project chat](https://img.shields.io/badge/zulip-join_chat-brightgreen.svg)](https://forum.nextgraph.org)
[![PyPI - Version](https://img.shields.io/pypi/v/nextgraphpy)](https://pypi.org/project/nextgraphpy/)
Python package for NextGraph, implemented in Rust
This repository is in active development at [https://git.nextgraph.org/NextGraph/nextgraph-rs](https://git.nextgraph.org/NextGraph/nextgraph-rs), a Gitea instance. For bug reports, issues, merge requests, and in order to join the dev team, please visit the link above and create an account (you can do so with a github account). The [github repo](https://github.com/nextgraph-org/nextgraph-rs) is just a read-only mirror that does not accept issues.
## NextGraph
> NextGraph brings about the convergence of P2P and Semantic Web technologies, towards a decentralized, secure and privacy-preserving cloud, based on CRDTs.
>
> This open source ecosystem provides solutions for end-users (a platform) and software developers (a framework), wishing to use or create **decentralized** apps featuring: **live collaboration** on rich-text documents, peer to peer communication with **end-to-end encryption**, offline-first, **local-first**, portable and interoperable data, total ownership of data and software, security and privacy. Centered on repositories containing **semantic data** (RDF), **rich text**, and structured data formats like **JSON**, synced between peers belonging to permissioned groups of users, it offers strong eventual consistency, thanks to the use of **CRDTs**. Documents can be linked together, signed, shared securely, queried using the **SPARQL** language and organized into sites and containers.
>
> More info here [https://nextgraph.org](https://nextgraph.org)
## Support
Documentation can be found here [https://docs.nextgraph.org](https://docs.nextgraph.org)
And our community forum where you can ask questions is here [https://forum.nextgraph.org](https://forum.nextgraph.org)
[![Mastodon](https://img.shields.io/badge/-MASTODON-%232B90D9?style=for-the-badge&logo=mastodon&logoColor=white)](https://fosstodon.org/@nextgraph)
## How to use NextGraph App & Platform
NextGraph is in alpha release!
You can try it online or by installing the apps. Please follow our [Getting started](https://docs.nextgraph.org/en/getting-started/) guide .
You can also subscribe to [our newsletter](https://list.nextgraph.org/subscription/form) to get updates, and support us with a [donation](https://nextgraph.org/donate/).
## NextGraph is also a Framework for App developers
Read our [getting started guide for developers](https://docs.nextgraph.org/en/framework/getting-started/).
## License
Licensed under either of
- Apache License, Version 2.0 ([LICENSE-APACHE2](LICENSE-APACHE2) or http://www.apache.org/licenses/LICENSE-2.0)
- MIT license ([LICENSE-MIT](LICENSE-MIT) or http://opensource.org/licenses/MIT)
at your option.
`SPDX-License-Identifier: Apache-2.0 OR MIT`
---
NextGraph received funding through the [NGI Assure Fund](https://nlnet.nl/assure) and the [NGI Zero Commons Fund](https://nlnet.nl/commonsfund/), both funds established by [NLnet](https://nlnet.nl/) Foundation with financial support from the European Commission's [Next Generation Internet](https://ngi.eu/) programme, under the aegis of DG Communications Networks, Content and Technology under grant agreements No 957073 and No 101092990, respectively.
[rustc-image]: https://img.shields.io/badge/rustc-1.81+-blue.svg
[license-image]: https://img.shields.io/badge/license-Apache2.0-blue.svg
[license-link]: https://git.nextgraph.org/NextGraph/nextgraph-rs/raw/branch/master/LICENSE-APACHE2
[license-image2]: https://img.shields.io/badge/license-MIT-blue.svg
[license-link2]: https://git.nextgraph.org/NextGraph/nextgraph-rs/src/branch/master/LICENSE-MIT

@ -0,0 +1,17 @@
[build-system]
requires = ["maturin>=1.8,<2.0"]
build-backend = "maturin"
[project]
name = "nextgraphpy"
requires-python = ">=3.7.3"
description = "NextGraph brings about the convergence of P2P and Semantic Web technologies, towards a decentralized, secure and privacy-preserving cloud, based on CRDTs."
readme = "README.md"
classifiers = [
"Programming Language :: Rust",
"Programming Language :: Python :: Implementation :: CPython",
"Programming Language :: Python :: Implementation :: PyPy",
]
version = "0.1a1.dev4"
[tool.maturin]
features = ["pyo3/extension-module"]

@ -0,0 +1,167 @@
// Copyright (c) 2022-2025 Niko Bonnieure, Par le Peuple, NextGraph.org developers
// All rights reserved.
// Licensed under the Apache License, Version 2.0
// <LICENSE-APACHE2 or http://www.apache.org/licenses/LICENSE-2.0>
// or the MIT license <LICENSE-MIT or http://opensource.org/licenses/MIT>,
// at your option. All files in the project carrying such
// notice may not be copied, modified, or distributed except
// according to those terms.
use pyo3::exceptions::PyTypeError;
use pyo3::prelude::*;
use pythonize::{depythonize, pythonize};
use serde::{Deserialize, Serialize};
use std::fs::read;
#[allow(unused_imports)]
use ::nextgraph::local_broker::{
app_request, app_request_stream, doc_fetch_repo_subscribe, init_local_broker, session_start,
session_stop, user_connect, user_disconnect, wallet_close, wallet_create_v0, wallet_get,
wallet_get_file, wallet_import, wallet_read_file, wallet_was_opened, LocalBrokerConfig,
SessionConfig,
};
use ::nextgraph::net::app_protocol::*;
use ::nextgraph::net::types::BootstrapContentV0;
use ::nextgraph::repo::errors::NgError;
use ::nextgraph::repo::log::*;
use ::nextgraph::repo::types::{BranchCrdt, StoreRepo, PubKey};
use ::nextgraph::wallet::types::{CreateWalletV0, SessionInfo};
use ::nextgraph::wallet::{display_mnemonic, emojis::display_pazzle};
use async_std::stream::StreamExt;
#[pyfunction]
fn init_local_broker_in_memory() -> PyResult<()> {
Ok(())
}
struct PyNgError(NgError);
impl From<PyNgError> for PyErr {
fn from(e: PyNgError) -> PyErr {
let ioe: std::io::Error = e.0.into();
ioe.into()
}
}
impl From<NgError> for PyNgError {
fn from(e: NgError) -> PyNgError {
PyNgError(e)
}
}
/// Open the wallet with mnemonic and PIN, and returns the wallet_name and the SessionInfo
#[pyfunction]
fn wallet_open_with_mnemonic_words(
py: Python,
wallet_file_path: String,
mnemonic_words: Vec<String>,
pin: [u8; 4],
) -> PyResult<Bound<PyAny>> {
pyo3_async_runtimes::async_std::future_into_py(py, async move {
init_local_broker(Box::new(|| LocalBrokerConfig::InMemory)).await;
let wallet_file = read(wallet_file_path).expect("read wallet file");
let wallet = wallet_read_file(wallet_file)
.await
.map_err(|e| Into::<PyNgError>::into(e))?;
let opened_wallet = ::nextgraph::local_broker::wallet_open_with_mnemonic_words(
&wallet,
&mnemonic_words,
pin,
)
.map_err(|e| Into::<PyNgError>::into(e))?;
let user_id = opened_wallet.personal_identity();
let wallet_name = opened_wallet.name();
let _client = wallet_import(wallet.clone(), opened_wallet, true)
.await
.map_err(|e| Into::<PyNgError>::into(e))?;
let session = session_start(SessionConfig::new_in_memory(&user_id, &wallet_name))
.await
.map_err(|e| Into::<PyNgError>::into(e))?;
// let session = session_start(SessionConfig::new_remote(&user_id, &wallet_name, None)).await?;
let _status = user_connect(&user_id)
.await
.map_err(|e| Into::<PyNgError>::into(e))?;
let s = Python::with_gil(|py| pythonize(py, &session).unwrap().unbind());
Ok((wallet_name, s))
})
}
#[pyfunction]
#[pyo3(signature = (session_id, sparql, nuri=None))]
fn doc_sparql_update(
py: Python,
session_id: u64,
sparql: String,
nuri: Option<String>,
) -> PyResult<Bound<PyAny>> {
pyo3_async_runtimes::async_std::future_into_py(py, async move {
let res = ::nextgraph::local_broker::doc_sparql_update(session_id, sparql, nuri)
.await
.map_err(|e| PyTypeError::new_err(e))?;
Ok(res)
})
}
#[pyfunction]
fn disconnect_and_close<'a>(
py: Python<'a>,
user_id: Bound<'a, PyAny>,
wallet_name: String,
) -> PyResult<Bound<'a, PyAny>> {
let user_id: PubKey = depythonize(&user_id)?;
pyo3_async_runtimes::async_std::future_into_py(py, async move {
user_disconnect(&user_id)
.await
.map_err(|e| Into::<PyNgError>::into(e))?;
// stop the session
session_stop(&user_id)
.await
.map_err(|e| Into::<PyNgError>::into(e))?;
// closes the wallet
wallet_close(&wallet_name)
.await
.map_err(|e| Into::<PyNgError>::into(e))?;
Ok(())
})
}
#[pyfunction]
#[pyo3(signature = (session_id, crdt, class_name, destination="store".to_string(), store_type=None, store_repo=None))]
fn doc_create(
py: Python,
session_id: u64,
crdt: String,
class_name: String,
destination: String,
store_type: Option<String>,
store_repo: Option<String>,
) -> PyResult<Bound<PyAny>> {
pyo3_async_runtimes::async_std::future_into_py(py, async move {
Ok(nextgraph::local_broker::doc_create(session_id, crdt, class_name, destination, store_type, store_repo)
.await
.map_err(|e| Into::<PyNgError>::into(e))?
)
})
}
#[pymodule]
fn nextgraphpy(m: &Bound<'_, PyModule>) -> PyResult<()> {
m.add_function(wrap_pyfunction!(wallet_open_with_mnemonic_words, m)?)?;
m.add_function(wrap_pyfunction!(doc_sparql_update, m)?)?;
m.add_function(wrap_pyfunction!(disconnect_and_close, m)?)?;
m.add_function(wrap_pyfunction!(doc_create, m)?)?;
Ok(())
}

@ -0,0 +1,21 @@
import asyncio
from nextgraphpy import wallet_open_with_mnemonic_words, doc_create, doc_sparql_update, disconnect_and_close
async def main():
wallet_session = await wallet_open_with_mnemonic_words(
"/home/nn/Downloads/wallet-bCHhOmlelVtZ60jjGu7m-YtzF4TfD5WyErAMnEDOn-kA.ngw",
["mutual", "wife", "section", "actual", "spend", "illness", "save", "delay", "kiss", "crash", "baby", "degree" ],
[2, 3, 2, 3])
wallet_name = wallet_session[0]
session_info = wallet_session[1]
session_id = session_info["session_id"]
print(wallet_name)
print(session_info)
doc_id = await doc_create(session_id, "Graph", "data:graph", "store")
print(doc_id)
commits = await doc_sparql_update(session_id,
"INSERT DATA { <did:ng:_> <example:predicate> \"An example value22\". }", doc_id)
print(commits)
await disconnect_and_close(session_info["user"], wallet_name)
asyncio.run(main())

@ -27,7 +27,7 @@ This library is in active development at [https://git.nextgraph.org/NextGraph/ne
## Support ## Support
This crate has official documentation at [docs.rs](https://docs.rs/nextgraph/0.1.0/nextgraph/) This crate has official documentation at [docs.rs](https://docs.rs/nextgraph/0.1.2/nextgraph/)
Documentation can be found here [https://docs.nextgraph.org](https://docs.nextgraph.org) Documentation can be found here [https://docs.nextgraph.org](https://docs.nextgraph.org)
@ -44,7 +44,7 @@ A tokio-based version (as a feature) might be available in the future.
```toml ```toml
[dependencies] [dependencies]
nextgraph = "0.1.1-alpha.2" nextgraph = "0.1.2"
async-std = "1.12.0" async-std = "1.12.0"
``` ```
@ -52,16 +52,16 @@ async-std = "1.12.0"
You can find some examples on how to use the library: You can find some examples on how to use the library:
- [in_memory](https://git.nextgraph.org/NextGraph/nextgraph-rs/src/branch/master/nextgraph/examples) - [in_memory](https://git.nextgraph.org/NextGraph/nextgraph-rs/src/branch/master/nextgraph/examples)
- [persistent](https://git.nextgraph.org/NextGraph/nextgraph-rs/src/branch/master/nextgraph/examples) - [persistent](https://git.nextgraph.org/NextGraph/nextgraph-rs/src/branch/master/nextgraph/examples)
## License ## License
Licensed under either of Licensed under either of
- Apache License, Version 2.0 ([LICENSE-APACHE2](LICENSE-APACHE2) or http://www.apache.org/licenses/LICENSE-2.0) - Apache License, Version 2.0 ([LICENSE-APACHE2](LICENSE-APACHE2) or http://www.apache.org/licenses/LICENSE-2.0)
- MIT license ([LICENSE-MIT](LICENSE-MIT) or http://opensource.org/licenses/MIT) - MIT license ([LICENSE-MIT](LICENSE-MIT) or http://opensource.org/licenses/MIT)
at your option. at your option.
`SPDX-License-Identifier: Apache-2.0 OR MIT` `SPDX-License-Identifier: Apache-2.0 OR MIT`
@ -75,7 +75,6 @@ additional terms or conditions.
NextGraph received funding through the [NGI Assure Fund](https://nlnet.nl/assure) and the [NGI Zero Commons Fund](https://nlnet.nl/commonsfund/), both funds established by [NLnet](https://nlnet.nl/) Foundation with financial support from the European Commission's [Next Generation Internet](https://ngi.eu/) programme, under the aegis of DG Communications Networks, Content and Technology under grant agreements No 957073 and No 101092990, respectively. NextGraph received funding through the [NGI Assure Fund](https://nlnet.nl/assure) and the [NGI Zero Commons Fund](https://nlnet.nl/commonsfund/), both funds established by [NLnet](https://nlnet.nl/) Foundation with financial support from the European Commission's [Next Generation Internet](https://ngi.eu/) programme, under the aegis of DG Communications Networks, Content and Technology under grant agreements No 957073 and No 101092990, respectively.
[rustc-image]: https://img.shields.io/badge/rustc-1.81+-blue.svg [rustc-image]: https://img.shields.io/badge/rustc-1.81+-blue.svg
[license-image]: https://img.shields.io/badge/license-Apache2.0-blue.svg [license-image]: https://img.shields.io/badge/license-Apache2.0-blue.svg
[license-link]: https://git.nextgraph.org/NextGraph/nextgraph-rs/raw/branch/master/LICENSE-APACHE2 [license-link]: https://git.nextgraph.org/NextGraph/nextgraph-rs/raw/branch/master/LICENSE-APACHE2

Loading…
Cancel
Save