push
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful

This commit is contained in:
Michael Zhang 2023-06-22 00:45:14 -05:00
parent 234a6ebb4b
commit 0ae4b0ba9e
Signed by: michael
GPG key ID: BDA47A31A3C8EE6B
19 changed files with 140 additions and 2575 deletions

View file

@ -6,8 +6,6 @@
# App Developers # App Developers
- [`meta.json`](./dev/meta_json.md)
- [API Reference](./generated/spec/meta.schema.md)
- [App API](./dev/api.md) - [App API](./dev/api.md)
# Core Library Developers # Core Library Developers
@ -20,3 +18,4 @@
- [Package Ecosystem](./notes/packages.md) - [Package Ecosystem](./notes/packages.md)
- [Types](./notes/types.md) - [Types](./notes/types.md)
- [Data Integrity](./notes/integrity.md) - [Data Integrity](./notes/integrity.md)
- [Sled Keyspace](./notes/sledkeys.md)

View file

@ -4,4 +4,4 @@ Must include a file called `panorama_version.json` that details information abou
# Format v0 # Format v0
Includes an SQLite database called `vault.sqlite`. Includes a sled database.

View file

@ -0,0 +1,17 @@
# Sled Keyspace
Panorama uses [sled] as a keystore.
The key space looks like:
- nodes
- by-uuid
- :uuid
- edges
- indexes
-
### Indexes
[sled]: https://github.com/spacejam/sled
[cockroachdb-kv]: https://github.com/cockroachdb/cockroach/blob/master/docs/tech-notes/encoding.md

View file

@ -1,6 +1,8 @@
# Data types # Data types
close to javascript types? i guess close to javascript types? i guess. Apps can define these under their own
namespace and then refer to them. You can also publish type-only apps, and there
will also be some standard ones defined.
## Primitives ## Primitives
@ -15,8 +17,10 @@ close to javascript types? i guess
## Special primitives ## Special primitives
- DateTimeTz - DateTimeTz
- Timezone-aware date (internally stored as ISO8601) - Timezone-aware date (internally stored as ISO8601)
- There is no non-timezone-aware date. Please use a string type for that - There is no non-timezone-aware date. Please use a string type for that
- Unit - Unit
- This is essentially a number with an attached unit specifier (string) - This is essentially a number with an attached unit specifier (string)
- Each unit _type_ is distinct, and allows a number of units that can freely - Each unit _type_ is distinct, and allows a number of units that can freely
@ -25,8 +29,9 @@ close to javascript types? i guess
- File size (byte, kb, mb, mib, gib, etc.) - File size (byte, kb, mb, mib, gib, etc.)
- Temperature (c, f, k) - Temperature (c, f, k)
- Distance (ft, mi, m, km, etc.) - Distance (ft, mi, m, km, etc.)
- Custom unit conversions can be defined.
- Currency is **NOT** considered a unit and has no semantic meaning within the - Currency is **NOT** considered a unit and has no semantic meaning within the
database. database. Please don't add custom conversions for this
## Type constructors ## Type constructors
@ -36,17 +41,11 @@ close to javascript types? i guess
- Heterogeneous map - Heterogeneous map
- Array - Array
- Record - Record
- basically matches interface in typescript
- Records are not allowed to be fully self-recursive (eg. `record Foo { foo: Foo }`)
- Enum - Enum
- Allowed to be self-recursive, but needs at least one terminating variant
## Complex type constructors ## Complex type constructors
- JSON schema - JSON schema
# Interfaces
Interfaces approximately match traits in rust, comprised of
- Associated types
- Functions
TODO: Generics?

View file

@ -81,6 +81,8 @@
"${pkgs.harfbuzz.dev}/lib/pkgconfig" "${pkgs.harfbuzz.dev}/lib/pkgconfig"
"${pkgs.at-spi2-atk.dev}/lib/pkgconfig" "${pkgs.at-spi2-atk.dev}/lib/pkgconfig"
]; ];
GIO_MODULE_DIR = "${pkgs.glib-networking}/lib/gio/modules";
} // prisma-env); } // prisma-env);
ci = pkgs.mkShell { packages = with pkgs; [ bash mdbook nodejs ]; }; ci = pkgs.mkShell { packages = with pkgs; [ bash mdbook nodejs ]; };

1
prisma/.gitignore vendored
View file

@ -1 +0,0 @@
/dev.db*

View file

@ -1,75 +0,0 @@
-- CreateTable
CREATE TABLE "Node" (
"id" TEXT NOT NULL PRIMARY KEY,
"label" TEXT
);
-- CreateTable
CREATE TABLE "Interface" (
"id" TEXT NOT NULL PRIMARY KEY
);
-- CreateTable
CREATE TABLE "Edge" (
"id" TEXT NOT NULL PRIMARY KEY,
"label" TEXT,
"appId" TEXT NOT NULL,
"appKey" TEXT NOT NULL,
"fromId" TEXT NOT NULL,
"toId" TEXT NOT NULL,
CONSTRAINT "Edge_appId_fkey" FOREIGN KEY ("appId") REFERENCES "App" ("id") ON DELETE RESTRICT ON UPDATE CASCADE,
CONSTRAINT "Edge_fromId_fkey" FOREIGN KEY ("fromId") REFERENCES "Node" ("id") ON DELETE RESTRICT ON UPDATE CASCADE,
CONSTRAINT "Edge_toId_fkey" FOREIGN KEY ("toId") REFERENCES "Node" ("id") ON DELETE RESTRICT ON UPDATE CASCADE
);
-- CreateTable
CREATE TABLE "NodeMeta" (
"nodeId" TEXT NOT NULL,
"appId" TEXT NOT NULL,
"appKey" TEXT NOT NULL,
"value" BLOB NOT NULL,
PRIMARY KEY ("nodeId", "appId", "appKey"),
CONSTRAINT "NodeMeta_nodeId_fkey" FOREIGN KEY ("nodeId") REFERENCES "Node" ("id") ON DELETE RESTRICT ON UPDATE CASCADE,
CONSTRAINT "NodeMeta_appId_fkey" FOREIGN KEY ("appId") REFERENCES "App" ("id") ON DELETE RESTRICT ON UPDATE CASCADE
);
-- CreateTable
CREATE TABLE "NodeImplements" (
"nodeId" TEXT NOT NULL,
"interfaceId" TEXT NOT NULL,
PRIMARY KEY ("nodeId", "interfaceId"),
CONSTRAINT "NodeImplements_nodeId_fkey" FOREIGN KEY ("nodeId") REFERENCES "Node" ("id") ON DELETE RESTRICT ON UPDATE CASCADE,
CONSTRAINT "NodeImplements_interfaceId_fkey" FOREIGN KEY ("interfaceId") REFERENCES "Interface" ("id") ON DELETE RESTRICT ON UPDATE CASCADE
);
-- CreateTable
CREATE TABLE "App" (
"id" TEXT NOT NULL PRIMARY KEY,
"localName" TEXT NOT NULL,
"title" TEXT NOT NULL,
"installed" DATETIME NOT NULL
);
-- CreateTable
CREATE TABLE "Patterns" (
"id" TEXT NOT NULL PRIMARY KEY,
"pattern" TEXT NOT NULL,
"type" TEXT NOT NULL,
"appId" TEXT NOT NULL,
"functionName" TEXT NOT NULL,
CONSTRAINT "Patterns_appId_fkey" FOREIGN KEY ("appId") REFERENCES "App" ("id") ON DELETE RESTRICT ON UPDATE CASCADE
);
-- CreateIndex
CREATE INDEX "Edge_appId_appKey_idx" ON "Edge"("appId", "appKey");
-- CreateIndex
CREATE UNIQUE INDEX "Edge_fromId_toId_key" ON "Edge"("fromId", "toId");
-- CreateIndex
CREATE INDEX "NodeMeta_appId_appKey_idx" ON "NodeMeta"("appId", "appKey");
-- CreateIndex
CREATE UNIQUE INDEX "App_localName_key" ON "App"("localName");

View file

@ -1,14 +0,0 @@
-- RedefineTables
PRAGMA foreign_keys=OFF;
CREATE TABLE "new_App" (
"id" TEXT NOT NULL PRIMARY KEY,
"localName" TEXT NOT NULL,
"title" TEXT NOT NULL,
"installed" DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP
);
INSERT INTO "new_App" ("id", "installed", "localName", "title") SELECT "id", "installed", "localName", "title" FROM "App";
DROP TABLE "App";
ALTER TABLE "new_App" RENAME TO "App";
CREATE UNIQUE INDEX "App_localName_key" ON "App"("localName");
PRAGMA foreign_key_check;
PRAGMA foreign_keys=ON;

View file

@ -1,18 +0,0 @@
-- RedefineTables
PRAGMA foreign_keys=OFF;
CREATE TABLE "new_NodeMeta" (
"nodeId" TEXT NOT NULL,
"appId" TEXT NOT NULL,
"appKey" TEXT NOT NULL,
"value" BLOB NOT NULL,
PRIMARY KEY ("nodeId", "appId", "appKey"),
CONSTRAINT "NodeMeta_nodeId_fkey" FOREIGN KEY ("nodeId") REFERENCES "Node" ("id") ON DELETE CASCADE ON UPDATE CASCADE,
CONSTRAINT "NodeMeta_appId_fkey" FOREIGN KEY ("appId") REFERENCES "App" ("id") ON DELETE RESTRICT ON UPDATE CASCADE
);
INSERT INTO "new_NodeMeta" ("appId", "appKey", "nodeId", "value") SELECT "appId", "appKey", "nodeId", "value" FROM "NodeMeta";
DROP TABLE "NodeMeta";
ALTER TABLE "new_NodeMeta" RENAME TO "NodeMeta";
CREATE INDEX "NodeMeta_appId_appKey_idx" ON "NodeMeta"("appId", "appKey");
PRAGMA foreign_key_check;
PRAGMA foreign_keys=ON;

View file

@ -1,3 +0,0 @@
# Please do not edit this file manually
# It should be added in your version-control system (i.e. Git)
provider = "sqlite"

2365
src-tauri/Cargo.lock generated

File diff suppressed because it is too large Load diff

View file

@ -7,10 +7,6 @@ license = ""
repository = "" repository = ""
edition = "2021" edition = "2021"
[workspace]
members = ["prisma-cli"]
resolver = "2"
[build-dependencies] [build-dependencies]
tauri-build = { version = "1.3", features = [] } tauri-build = { version = "1.3", features = [] }
@ -18,17 +14,10 @@ tauri-build = { version = "1.3", features = [] }
tauri = { version = "1.3", features = ["shell-open"] } tauri = { version = "1.3", features = ["shell-open"] }
serde = { version = "1.0", features = ["derive"] } serde = { version = "1.0", features = ["derive"] }
serde_json = "1.0" serde_json = "1.0"
# TODO: L @ prisma-client-rust not updating to 0.25.x of the sqlite lib
sqlx = { version = "0.5", features = ["runtime-tokio-rustls", "sqlite"] }
tokio = { version = "1.28.2", features = ["full"] } tokio = { version = "1.28.2", features = ["full"] }
anyhow = "1.0.71" anyhow = "1.0.71"
dirs = "5.0.1" dirs = "5.0.1"
sled = { version = "0.34.7", features = ["compression"] }
[dependencies.prisma-client-rust]
git = "https://github.com/Brendonovich/prisma-client-rust"
tag = "0.6.8"
default-features = false
features = ["sqlite"]
[features] [features]
# this feature is used for production builds or when `devPath` points to the filesystem # this feature is used for production builds or when `devPath` points to the filesystem

View file

@ -1,10 +0,0 @@
[package]
name = "prisma-cli"
version = "0.1.0"
edition = "2021"
[dependencies.prisma-client-rust-cli]
git = "https://github.com/Brendonovich/prisma-client-rust"
tag = "0.6.8"
default-features = false
features = ["sqlite"]

View file

@ -1,3 +0,0 @@
fn main() {
prisma_client_rust_cli::run();
}

View file

@ -1,109 +0,0 @@
generator client {
provider = "cargo prisma"
output = "../src/prisma.rs"
}
datasource db {
provider = "sqlite"
url = env("DATABASE_URL")
}
model Node {
id String @id @default(uuid())
label String?
implements NodeImplements[]
fromNodes Edge[] @relation(name: "fromNode")
toNodes Edge[] @relation(name: "toNode")
metadata NodeMeta[]
}
model Interface {
id String @id @default(uuid())
implementors NodeImplements[]
}
model Edge {
id String @id @default(uuid())
label String?
/// The app that created this edge
app App @relation(fields: [appId], references: [id])
appId String
appKey String
fromId String
fromNode Node @relation(name: "fromNode", fields: [fromId], references: [id])
toId String
toNode Node @relation(name: "toNode", fields: [toId], references: [id])
directional Boolean
@@unique([fromId, toId])
@@index([appId, appKey])
}
model NodeMeta {
nodeId String
node Node @relation(fields: [nodeId], references: [id], onDelete: Cascade)
/// The app that created this metadata field
app App @relation(fields: [appId], references: [id])
appId String
appKey String
value Bytes
@@id([nodeId, appId, appKey])
@@index([appId, appKey])
}
model NodeImplements {
nodeId String
node Node @relation(fields: [nodeId], references: [id])
interfaceId String
interface Interface @relation(fields: [interfaceId], references: [id])
@@id([nodeId, interfaceId])
}
model App {
id String @id @default(uuid())
localName String @unique
title String
installed DateTime @default(now())
patterns Patterns[]
metaKeys NodeMeta[]
edges Edge[]
}
/// Regular expressions table
model Patterns {
id String @id @default(uuid())
pattern String
/// Pattern type, see docs for details
type String
appId String
app App @relation(fields: [appId], references: [id])
functionName String
}
/// Index table, for keeping track of indexes to build and take down when the database first starts
model Indices {
id String @id @default(uuid())
command String
// TODO: Does sqlite avoid making duplicate indexes automatically?
}

View file

@ -3,9 +3,6 @@ pub mod meta;
use std::{collections::HashMap, env, path::PathBuf}; use std::{collections::HashMap, env, path::PathBuf};
use anyhow::Result; use anyhow::Result;
use sqlx::SqlitePool;
use crate::prisma::PrismaClient;
pub struct Handler {} pub struct Handler {}
@ -16,17 +13,14 @@ pub enum Event {
} }
pub struct AppManager { pub struct AppManager {
prisma: PrismaClient,
apps: Vec<App>, apps: Vec<App>,
key_handlers: HashMap<(String, Event), Handler>, key_handlers: HashMap<(String, Event), Handler>,
} }
impl AppManager { impl AppManager {
pub async fn new() -> Result<Self> { pub async fn new() -> Result<Self> {
let prisma = PrismaClient::_builder().build().await?;
let apps = vec![]; let apps = vec![];
Ok(Self { Ok(Self {
prisma,
apps, apps,
key_handlers: HashMap::default(), key_handlers: HashMap::default(),
}) })
@ -51,9 +45,7 @@ impl AppManager {
} }
/// Figure out which indices are required by the set of known apps /// Figure out which indices are required by the set of known apps
pub async fn compute_indices(&self) -> Result<()> { pub async fn compute_indices(&self) -> Result<()> { Ok(()) }
Ok(())
}
} }
pub struct App { pub struct App {

View file

@ -1,15 +0,0 @@
use sqlx::SqlitePool;
use tauri::State;
pub struct Db(pub SqlitePool);
#[derive(Debug, Serialize, Deserialize)]
pub struct QueryOptions {}
#[tauri::command]
pub async fn query(
state: State<'_, Db>,
options: QueryOptions,
) -> Result<(), String> {
Ok(())
}

22
src-tauri/src/db.rs Normal file
View file

@ -0,0 +1,22 @@
use anyhow::Result;
use sled::Tree;
pub struct Db {
db: sled::Db,
node_tree: Tree,
}
impl Db {
pub fn create_node(&self) -> Result<()> {
let id = self.db.generate_id()?;
/*
self.db.transaction(|tx_db| {
tx_db.insert("nodes", &id.to_be_bytes())?;
Ok(())
})?;
*/
Ok(())
}
}

View file

@ -5,11 +5,9 @@
extern crate serde; extern crate serde;
pub mod apps; pub mod apps;
pub mod dal; pub mod db;
pub mod prisma;
use anyhow::Result; use anyhow::Result;
use prisma::PrismaClient;
use crate::apps::AppManager; use crate::apps::AppManager;
@ -17,22 +15,16 @@ pub use crate::apps::meta::AppMetadata;
#[tokio::main] #[tokio::main]
async fn main() -> Result<()> { async fn main() -> Result<()> {
// Open database
let client = PrismaClient::_builder().build().await?;
// Register apps // Register apps
let mut app_manager = AppManager::new().await?; let mut app_manager = AppManager::new().await?;
app_manager.register().await?; app_manager.register().await?;
// Read indexes // Read indexes
let indexes_from_apps = app_manager.compute_indices().await?; let indexes_from_apps = app_manager.compute_indices().await?;
let indexes_from_db = client.indices().find_many(vec![]).exec().await?;
println!("indexes: {:?}", indexes_from_db);
tauri::Builder::default() tauri::Builder::default()
.manage(app_manager) .manage(app_manager)
.manage(client) .invoke_handler(tauri::generate_handler![])
.invoke_handler(tauri::generate_handler![dal::query])
.run(tauri::generate_context!()) .run(tauri::generate_context!())
.expect("error while running tauri application"); .expect("error while running tauri application");