Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Normi #64

Merged
merged 24 commits into from
Oct 17, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
24 commits
Select commit Hold shift + click to select a range
573f7d6
refactor layer futures and results
Brendonovich Oct 2, 2022
98e8ac0
remove StreamFuture enum
Brendonovich Oct 2, 2022
7cb60df
add arg to RequestResolver
Brendonovich Oct 3, 2022
06818c7
enforce closure in unbuilt builder
Brendonovich Oct 3, 2022
c6f4a9f
typed request future + builder wrapper
Brendonovich Oct 3, 2022
1660d83
procedure builder map
Brendonovich Oct 3, 2022
69598b3
added normi
oscartbeaumont Oct 3, 2022
86f5297
move specta crate
oscartbeaumont Oct 3, 2022
f64fd74
rspc global store + normi check for duplicate types
oscartbeaumont Oct 3, 2022
dbc0f37
normi: normalising subtypes
oscartbeaumont Oct 3, 2022
dcbeea6
rspc: move more API's into internal crate
oscartbeaumont Oct 4, 2022
08c19f5
more normi work + ResponseAndChannel for SD RN bridge
oscartbeaumont Oct 6, 2022
3dbff82
[WIP] Fork tRPC into new rspc client
oscartbeaumont Oct 10, 2022
6e17bb7
[WIP] move tRPC client into main folder and enable all transports
oscartbeaumont Oct 10, 2022
ad9cca8
make `GlobalData` work with `t(...)` syntax
oscartbeaumont Oct 10, 2022
e11e19d
httpz upgrades & move extractor code into new file
oscartbeaumont Oct 11, 2022
13a6d56
Monkey patch minimal required functionality into client
oscartbeaumont Oct 13, 2022
4363c8f
commit disgusting code & populate normi cache
oscartbeaumont Oct 13, 2022
b41e4d7
hotfix for Spacedrive
oscartbeaumont Oct 13, 2022
1a0a568
Primitive OpenAPI plugin
oscartbeaumont Oct 15, 2022
0057f9e
[WIP] Specta support for OpenAPI
oscartbeaumont Oct 16, 2022
0fb3f7d
React hook factory + Normi rename __id to $id
oscartbeaumont Oct 17, 2022
c9e7161
GH Sponsors + GH Actions release to npm on each commit
oscartbeaumont Oct 17, 2022
3831938
Merge remote-tracking branch 'origin/main' into separate-layer-result
oscartbeaumont Oct 17, 2022
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions .github/FUNDING.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
github: [oscartbeaumont]
custom: ["https://paypal.me/oscartbeaumont"]
6 changes: 6 additions & 0 deletions .github/dependabot.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
version: 2
updates:
- package-ecosystem: "github-actions"
directory: "/"
schedule:
interval: "weekly"
71 changes: 71 additions & 0 deletions .github/scripts/setPackageVersions.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
/**
* Updates the package.json files with a version to release to npm under
* the main tag.
*
* Based on https://github.com/facebook/relay/blob/main/gulpfile.js
*/

const fs = require("fs/promises");
const path = require("path");

const RELEASE_COMMIT_SHA = process.env.RELEASE_COMMIT_SHA;

if (RELEASE_COMMIT_SHA && RELEASE_COMMIT_SHA.length !== 40) {
throw new Error(
"If the RELEASE_COMMIT_SHA env variable is set, it should be set to the " +
"40 character git commit hash."
);
}

const VERSION = RELEASE_COMMIT_SHA
? `0.0.0-main-${RELEASE_COMMIT_SHA.substring(0, 8)}`
: process.env.npm_package_version;

console.log(RELEASE_COMMIT_SHA);

async function main() {
const packages = await (
await fs.readdir(path.join(__dirname, "../../packages"))
).filter((pkg) => pkg !== ".DS_Store" && pkg !== "tsconfig.json");
const pkgJsons = {};
const pkgJsonPaths = {};

for (pkg of packages) {
const pkgJsonPath = path.join(
__dirname,
"../../packages",
pkg,
"package.json"
);
pkgJsonPaths[pkg] = pkgJsonPath;
const packageJson = JSON.parse(await fs.readFile(pkgJsonPath, "utf8"));

pkgJsons[pkg] = packageJson;
}

const packageNames = Object.values(pkgJsons).map((pkg) => pkg.name);

for (const pkg of packages) {
let packageJson = pkgJsons[pkg];
packageJson.version = VERSION;
for (const depKind of [
"dependencies",
"devDependencies",
"peerDependencies",
]) {
const deps = packageJson[depKind];
for (const dep in deps) {
if (packageNames.includes(dep)) {
deps[dep] = VERSION;
}
}
}
await fs.writeFile(
pkgJsonPaths[pkg],
JSON.stringify(packageJson, null, 2) + "\n",
"utf8"
);
}
}

main();
60 changes: 60 additions & 0 deletions .github/workflows/CI.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
name: CI

on:
push:
branches: [main]
paths:
- 'packages/**'
# tags:
# - '[0-9]+.[0-9]+.[0-9]+*'
pull_request:
branches: [main]
paths:
- 'packages/**'

jobs:
build-publish:
name: Build and Publish to NPM
runs-on: ubuntu-latest
if: github.event_name == 'push' && github.repository == 'oscartbeaumont/rspc'
steps:
- uses: actions/checkout@v3

- uses: pnpm/action-setup@v2.2.4
with:
version: latest

- uses: actions/setup-node@v3
with:
node-version: '16'
cache: 'pnpm'

- name: Install dependencies
run: pnpm i --frozen-lockfile

- name: Build
run: pnpm build

- name: Configure main version
if: github.ref == 'refs/heads/main'
run: pnpm set-package-versions
env:
RELEASE_COMMIT_SHA: ${{ github.sha }}

- name: Publish main to npm
if: github.ref == 'refs/heads/main'
run: pnpm publish -r ${TAG} --no-git-checks --filter "@rspc/*" --access public
env:
TAG: ${{ (github.ref == 'refs/heads/main' && '--tag=main') || '' }}
NPM_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}

# - name: Configure release version
# if: github.ref_type == 'tag'
# run: pnpm set-package-versions

# - name: Publish release to npm
# if: github.ref_type == 'tag'
# run: pnpm publish -r ${TAG} --no-git-checks --filter "@rspc/*" --access public
# env:
# TAG: ${{ (contains(github.ref_name, '-beta.') && '--tag=beta') || ''}}
# NPM_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}
5 changes: 4 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -23,4 +23,7 @@ node_modules
/packages/*/dist

# Compiled vscode extension
*.vsix
*.vsix

# Trybuild
crates/*/wip
21 changes: 13 additions & 8 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,8 @@ categories = ["web-programming", "asynchronous"]
default = []
tauri = ["dep:tauri"]
tracing = ["dep:tracing"]
httpz = ["dep:httpz"]
# openapi = ["dep:openapiv3"]
httpz = ["dep:httpz", "httpz/cookies"]
openapi = ["dep:openapiv3", "dep:httpz", "dep:include_dir", "dep:mime_guess", "specta/openapi"]
# playground = []

# Webservers # Axum feature basically always enabled because we use the extractors regardless of webserver
Expand All @@ -25,8 +25,8 @@ actix-web = ["httpz/actix-web", "httpz/tokio-ws", "httpz/axum"]
# poem = ["httpz/poem"]
rocket = ["httpz/rocket", "httpz/tokio-ws", "httpz/axum"]
# warp = ["httpz/warp"]
lambda = ["httpz/lambda", "httpz/tokio-ws", "httpz/axum"]
workers = ["httpz/workers"]
lambda = ["httpz/lambda", "httpz/ws", "httpz/axum"]
workers = ["httpz/workers", "httpz/ws"]

# Specta
uuid = ["specta/uuid"]
Expand All @@ -41,8 +41,8 @@ bit-vec = ["specta/bit-vec"]
bson = ["specta/bson"]

[dependencies]
specta = { version = "0.0.4", path = "./specta", features = ["serde"] }
httpz = { git = "https://github.com/oscartbeaumont/httpz.git", optional = true } # TODO: Move back to crates.io release
specta = { version = "0.0.4", path = "./crates/specta", features = ["serde"] }
httpz = { git = "https://github.com/oscartbeaumont/httpz.git", rev = "1ddbd9ad594ac7ee3e5b167afe689d1ce1228519", optional = true } # TODO: Move back to crates.io release
serde = { version = "1.0.145", features = ["derive"] }
serde_json = "1.0.85"
thiserror = "1.0.36"
Expand All @@ -51,15 +51,20 @@ tokio = { version = "1.21.2", features = ["sync", "rt", "macros"] }
tauri = { version = "1.1.1", optional = true }
tracing = { version = "0.1.36", optional = true }
async-stream = "0.3.3"
openapiv3 = { version = "1.0.1", optional = true }
include_dir = { version = "0.7.2", optional = true, features = ["metadata"] }
mime_guess = { version = "2.0.4", optional = true }

[dev-dependencies]
async-stream = "0.3.3"

[workspace]
members = [
"./crates/normi",
"./crates/normi/macros",
"./crates/specta",
"./crates/specta/macros",
"./create-rspc-app",
"./examples",
"./examples/axum",
"./specta",
"./specta/macros"
]
26 changes: 26 additions & 0 deletions crates/normi/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
[package]
name = "normi"
description = "A normalised caching layer for rspc."
version = "0.0.1"
edition = "2021"

[features]
default = ["rspc"]
rspc = ["dep:rspc"]

[dependencies]
rspc = { path = "../../", optional = true }
normi-macros = { path = "./macros" }
serde = "1.0.145"
serde_json = "1.0.85"
specta = { version = "0.0.4", path = "../specta" }

[dev-dependencies]
rspc = { path = "../../", features = ["axum"] }
axum = "0.5.16"
tokio = { version = "1.21.2", features = ["macros", "rt-multi-thread"] }
tower-http = { version = "0.3.4", default-features = false, features = [
"cors",
] }
trybuild = "1.0.65"
assert-json-diff = "2.0.2"
120 changes: 120 additions & 0 deletions crates/normi/examples/basic.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,120 @@
use std::path::PathBuf;

use axum::routing::get;
use normi::{typed, Object};
use rspc::{Config, Router, Type};
use serde::Serialize;
use tower_http::cors::{Any, CorsLayer};

#[derive(Serialize, Type, Object)]
#[normi(rename = "org")]
pub struct Organisation {
#[normi(id)]
pub id: String,
pub name: String,
#[normi(refr)]
pub users: Vec<User>,
#[normi(refr)]
pub owner: User,
pub non_normalised_data: Vec<()>,
}

#[derive(Serialize, Type, Object)]
pub struct User {
#[normi(id)]
pub id: String,
pub name: String,
}

// TODO: Unit test this duplicate naming

#[derive(Serialize, Type, Object)]
pub struct CompositeId {
#[normi(id)]
pub org_id: String,
#[normi(id)]
pub user_id: String,
}

#[tokio::main]
async fn main() {
let router = <Router>::new()
.config(Config::new().export_ts_bindings(
PathBuf::from(env!("CARGO_MANIFEST_DIR")).join("../../examples/bindings.ts"),
))
.query("version", |t| t(|_, _: ()| "0.1.0"))
.query("userSync", |t| {
t.resolver(|_, _: ()| User {
id: "1".to_string(),
name: "Monty Beaumont".to_string(),
})
.map(typed)
})
.query("user", |t| {
t.resolver(|_, _: ()| async move {
Ok(User {
id: "1".to_string(),
name: "Monty Beaumont".to_string(),
})
})
.map(typed)
})
.query("org", |t| {
t.resolver(|_, _: ()| async move {
Ok(Organisation {
id: "org-1".into(),
name: "Org 1".into(),
users: vec![
User {
id: "user-1".into(),
name: "Monty Beaumont".into(),
},
User {
id: "user-2".into(),
name: "Millie Beaumont".into(),
},
User {
id: "user-3".into(),
name: "Oscar Beaumont".into(),
},
],
owner: User {
id: "user-1".into(),
name: "Monty Beaumont".into(),
},
non_normalised_data: vec![(), ()],
})
})
.map(typed)
})
.query("composite", |t| {
t.resolver(|_, _: ()| async move {
Ok(CompositeId {
org_id: "org-1".into(),
user_id: "user-1".into(),
})
})
.map(typed)
})
.build()
.arced();

let app = axum::Router::new()
.route("/", get(|| async { "Hello 'rspc'!" }))
// Attach the rspc router to your axum router. The closure is used to generate the request context for each request.
.route("/rspc/:id", router.endpoint(|| ()).axum())
// We disable CORS because this is just an example. DON'T DO THIS IN PRODUCTION!
.layer(
CorsLayer::new()
.allow_methods(Any)
.allow_headers(Any)
.allow_origin(Any),
);

let addr = "[::]:4000".parse::<std::net::SocketAddr>().unwrap(); // This listens on IPv6 and IPv4
println!("listening on http://{}/rspc/version", addr);
axum::Server::bind(&addr)
.serve(app.into_make_service())
.await
.unwrap();
}
12 changes: 12 additions & 0 deletions crates/normi/macros/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
[package]
name = "normi-macros"
version = "0.0.1"
edition = "2021"

[lib]
proc-macro = true

[dependencies]
proc-macro2 = "1.0.46"
quote = "1.0.21"
syn = "1.0.101"
Loading