Set up a shared types library

This commit is contained in:
Savanni D'Gerinel 2025-02-20 09:45:53 -05:00
parent fd3ca9f561
commit 11e33eca2f
22 changed files with 179 additions and 4118 deletions

132
Cargo.lock generated
View File

@ -271,7 +271,7 @@ dependencies = [
"base64ct",
"clap",
"cool_asserts",
"serde 1.0.217",
"serde 1.0.218",
"sha2",
"sqlx",
"thiserror 1.0.69",
@ -317,7 +317,7 @@ dependencies = [
"percent-encoding 2.3.1",
"pin-project-lite",
"rustversion",
"serde 1.0.217",
"serde 1.0.218",
"serde_json",
"serde_path_to_error",
"serde_urlencoded",
@ -415,7 +415,7 @@ version = "1.3.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b1f45e9417d87227c7a56d22e471c6206462cba514c7590c09aff4cf6d1ddcad"
dependencies = [
"serde 1.0.217",
"serde 1.0.218",
]
[[package]]
@ -472,7 +472,7 @@ version = "2.8.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8f68f53c83ab957f72c32642f3868eec03eb974d1fb82e453128456482613d36"
dependencies = [
"serde 1.0.217",
"serde 1.0.218",
]
[[package]]
@ -590,7 +590,7 @@ checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
name = "changeset"
version = "0.1.0"
dependencies = [
"uuid 1.13.1",
"uuid 0.8.2",
]
[[package]]
@ -603,7 +603,7 @@ dependencies = [
"iana-time-zone",
"js-sys",
"num-traits",
"serde 1.0.217",
"serde 1.0.218",
"wasm-bindgen",
"windows-targets 0.52.6",
]
@ -617,7 +617,7 @@ dependencies = [
"chrono",
"chrono-tz-build",
"phf 0.11.3",
"serde 1.0.217",
"serde 1.0.218",
]
[[package]]
@ -718,7 +718,7 @@ version = "0.1.0"
dependencies = [
"config-derive",
"cool_asserts",
"serde 1.0.217",
"serde 1.0.218",
"serde_json",
"thiserror 1.0.69",
]
@ -902,7 +902,7 @@ dependencies = [
"gio",
"glib",
"gtk4",
"serde 1.0.217",
"serde 1.0.218",
"serde_yml",
]
@ -948,7 +948,7 @@ dependencies = [
"libadwaita",
"memorycache",
"reqwest",
"serde 1.0.217",
"serde 1.0.218",
"serde_json",
"tokio",
"unic-langid",
@ -1010,7 +1010,7 @@ checksum = "2517b0555262aeeda0d107a40ecfbbcf185921180ffb4acf316ebe0887467e26"
dependencies = [
"generic-array 0.11.2",
"num-traits",
"serde 1.0.217",
"serde 1.0.218",
"typenum",
]
@ -1022,7 +1022,7 @@ checksum = "a0b0a86c5d31c93238ff4b694fa31f3acdf67440770dc314c57d90e433914397"
dependencies = [
"generic-array 0.14.7",
"num-traits",
"serde 1.0.217",
"serde 1.0.218",
"typenum",
]
@ -1049,7 +1049,7 @@ version = "1.13.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "60b1af1c220855b6ceac025d3f6ecdd2b7c4894bfe9cd9bda4fbb4bc7c0d4cf0"
dependencies = [
"serde 1.0.217",
"serde 1.0.218",
]
[[package]]
@ -1059,7 +1059,7 @@ dependencies = [
"chrono",
"chrono-tz",
"dimensioned 0.7.0",
"serde 1.0.217",
"serde 1.0.218",
"serde_derive",
"serde_json",
"tempfile",
@ -1204,7 +1204,7 @@ dependencies = [
"mime 0.3.17",
"mime_guess 2.0.5",
"pretty_env_logger",
"serde 1.0.217",
"serde 1.0.218",
"serde_json",
"sha2",
"tempdir",
@ -1366,7 +1366,7 @@ dependencies = [
"chrono-tz",
"dimensioned 0.8.0",
"emseries",
"serde 1.0.217",
"serde 1.0.218",
"serde_json",
"tempfile",
]
@ -1752,7 +1752,7 @@ checksum = "2a17868f56b4a24f677b17c8cb69958385102fa879418052d60b50bc1727e261"
dependencies = [
"gloo-utils",
"js-sys",
"serde 1.0.217",
"serde 1.0.218",
"wasm-bindgen",
"web-sys",
]
@ -1798,7 +1798,7 @@ dependencies = [
"getrandom 0.2.15",
"gloo-events",
"gloo-utils",
"serde 1.0.217",
"serde 1.0.218",
"serde-wasm-bindgen",
"serde_urlencoded",
"thiserror 1.0.69",
@ -1819,7 +1819,7 @@ dependencies = [
"http 0.2.12",
"js-sys",
"pin-project",
"serde 1.0.217",
"serde 1.0.218",
"serde_json",
"thiserror 1.0.69",
"wasm-bindgen",
@ -1840,7 +1840,7 @@ dependencies = [
"http 1.2.0",
"js-sys",
"pin-project",
"serde 1.0.217",
"serde 1.0.218",
"serde_json",
"thiserror 1.0.69",
"wasm-bindgen",
@ -1866,7 +1866,7 @@ checksum = "fbc8031e8c92758af912f9bc08fbbadd3c6f3cfcbf6b64cdf3d6a81f0139277a"
dependencies = [
"gloo-utils",
"js-sys",
"serde 1.0.217",
"serde 1.0.218",
"serde_json",
"thiserror 1.0.69",
"wasm-bindgen",
@ -1892,7 +1892,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0b5555354113b18c547c1d3a98fbf7fb32a9ff4f6fa112ce823a21641a0ba3aa"
dependencies = [
"js-sys",
"serde 1.0.217",
"serde 1.0.218",
"serde_json",
"wasm-bindgen",
"web-sys",
@ -1910,7 +1910,7 @@ dependencies = [
"gloo-worker-macros",
"js-sys",
"pinned",
"serde 1.0.217",
"serde 1.0.218",
"thiserror 1.0.69",
"wasm-bindgen",
"wasm-bindgen-futures",
@ -1942,7 +1942,7 @@ dependencies = [
"glib-build-tools 0.16.3",
"gtk4",
"libadwaita",
"serde 1.0.217",
"serde 1.0.218",
"serde_json",
"tokio",
]
@ -1952,7 +1952,7 @@ name = "gm-dash"
version = "0.1.0"
dependencies = [
"pipewire",
"serde 1.0.217",
"serde 1.0.218",
"serde_json",
"tokio",
"warp",
@ -2998,7 +2998,7 @@ version = "0.1.0"
dependencies = [
"chrono",
"futures",
"serde 1.0.217",
"serde 1.0.218",
"serde_derive",
"tokio",
]
@ -3316,7 +3316,7 @@ dependencies = [
"cool_asserts",
"grid",
"nary_tree",
"serde 1.0.217",
"serde 1.0.218",
"serde_json",
"sgf",
"thiserror 1.0.69",
@ -4063,7 +4063,7 @@ dependencies = [
"percent-encoding 2.3.1",
"pin-project-lite",
"rustls-pemfile",
"serde 1.0.217",
"serde 1.0.218",
"serde_json",
"serde_urlencoded",
"sync_wrapper 0.1.2",
@ -4266,9 +4266,9 @@ checksum = "34b623917345a631dc9608d5194cc206b3fe6c3554cd1c75b937e55e285254af"
[[package]]
name = "serde"
version = "1.0.217"
version = "1.0.218"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "02fc4265df13d6fa1d00ecff087228cc0a2b5f3c0e87e258d8b94a156e984c70"
checksum = "e8dfc9d19bdbf6d17e22319da49161d5d0108e4188e8b680aef6299eed22df60"
dependencies = [
"serde_derive",
]
@ -4280,15 +4280,15 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8302e169f0eddcc139c70f139d19d6467353af16f9fce27e8c30158036a1e16b"
dependencies = [
"js-sys",
"serde 1.0.217",
"serde 1.0.218",
"wasm-bindgen",
]
[[package]]
name = "serde_derive"
version = "1.0.217"
version = "1.0.218"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5a9bf7cf98d04a2b28aead066b7496853d4779c9cc183c440dbac457641e19a0"
checksum = "f09503e191f4e797cb8aac08e9a4a4695c5edf6a2e70e376d961ddd5c969f82b"
dependencies = [
"proc-macro2",
"quote",
@ -4304,7 +4304,7 @@ dependencies = [
"itoa",
"memchr",
"ryu",
"serde 1.0.217",
"serde 1.0.218",
]
[[package]]
@ -4314,7 +4314,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "af99884400da37c88f5e9146b7f1fd0fbcae8f6eec4e9da38b67d05486f814a6"
dependencies = [
"itoa",
"serde 1.0.217",
"serde 1.0.218",
]
[[package]]
@ -4323,7 +4323,7 @@ version = "0.6.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "87607cb1398ed59d48732e575a4c28a7a8ebf2454b964fe3f224f2afc07909e1"
dependencies = [
"serde 1.0.217",
"serde 1.0.218",
]
[[package]]
@ -4335,7 +4335,7 @@ dependencies = [
"form_urlencoded",
"itoa",
"ryu",
"serde 1.0.217",
"serde 1.0.218",
]
[[package]]
@ -4349,7 +4349,7 @@ dependencies = [
"libyml",
"memchr",
"ryu",
"serde 1.0.217",
"serde 1.0.218",
"version_check 0.9.5",
]
@ -4359,12 +4359,13 @@ version = "0.1.0"
dependencies = [
"axum",
"result-extended",
"serde 1.0.217",
"serde 1.0.218",
"thiserror 2.0.11",
"tokio",
"tower-http",
"typeshare",
"uuid 1.13.1",
"uuid 1.13.2",
"visions-types",
]
[[package]]
@ -4375,7 +4376,7 @@ dependencies = [
"cool_asserts",
"nary_tree",
"nom",
"serde 1.0.217",
"serde 1.0.218",
"thiserror 1.0.69",
"typeshare",
"uuid 0.8.2",
@ -4476,7 +4477,7 @@ version = "1.13.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3c5e1a9a646d36c3599cd173a41282daf47c44583ad367b8e6837255952e5c67"
dependencies = [
"serde 1.0.217",
"serde 1.0.218",
]
[[package]]
@ -4549,7 +4550,7 @@ dependencies = [
"memchr",
"once_cell",
"percent-encoding 2.3.1",
"serde 1.0.217",
"serde 1.0.218",
"serde_json",
"sha2",
"smallvec",
@ -4586,7 +4587,7 @@ dependencies = [
"once_cell",
"proc-macro2",
"quote",
"serde 1.0.217",
"serde 1.0.218",
"serde_json",
"sha2",
"sqlx-core",
@ -4630,7 +4631,7 @@ dependencies = [
"percent-encoding 2.3.1",
"rand 0.8.5",
"rsa",
"serde 1.0.217",
"serde 1.0.218",
"sha1",
"sha2",
"smallvec",
@ -4667,7 +4668,7 @@ dependencies = [
"memchr",
"once_cell",
"rand 0.8.5",
"serde 1.0.217",
"serde 1.0.218",
"serde_json",
"sha2",
"smallvec",
@ -4694,7 +4695,7 @@ dependencies = [
"libsqlite3-sys",
"log 0.4.25",
"percent-encoding 2.3.1",
"serde 1.0.217",
"serde 1.0.218",
"serde_urlencoded",
"sqlx-core",
"tracing",
@ -4931,7 +4932,7 @@ dependencies = [
"itoa",
"num-conv",
"powerfmt",
"serde 1.0.217",
"serde 1.0.218",
"time-core",
"time-macros",
]
@ -5083,7 +5084,7 @@ version = "0.8.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "185d8ab0dfbb35cf1399a6344d8484209c088f75f8f68230da55d48d95d43e3d"
dependencies = [
"serde 1.0.217",
"serde 1.0.218",
"serde_spanned",
"toml_datetime",
"toml_edit 0.20.2",
@ -5095,7 +5096,7 @@ version = "0.6.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7cda73e2f1397b1262d6dfdcef8aafae14d1de7748d66822d3bfeeb6d03e5e4b"
dependencies = [
"serde 1.0.217",
"serde 1.0.218",
]
[[package]]
@ -5116,7 +5117,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "396e4d48bbb2b7554c944bde63101b5ae446cff6ec4a24227428f15eb72ef338"
dependencies = [
"indexmap",
"serde 1.0.217",
"serde 1.0.218",
"serde_spanned",
"toml_datetime",
"winnow",
@ -5268,7 +5269,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "19be0f411120091e76e13e5a0186d8e2bcc3e7e244afdb70152197f1a8486ceb"
dependencies = [
"chrono",
"serde 1.0.217",
"serde 1.0.218",
"serde_json",
"typeshare-annotation",
]
@ -5433,16 +5434,18 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bc5cf98d8186244414c848017f0e2676b3fcb46807f6668a97dfe67359a3c4b7"
dependencies = [
"getrandom 0.2.15",
"serde 1.0.217",
"serde 1.0.218",
]
[[package]]
name = "uuid"
version = "1.13.1"
version = "1.13.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ced87ca4be083373936a67f8de945faa23b6b42384bd5b64434850802c6dccd0"
checksum = "8c1f41ffb7cf259f1ecc2876861a17e7142e63ead296f671f81f6ae85903e0d6"
dependencies = [
"getrandom 0.3.1",
"js-sys",
"wasm-bindgen",
]
[[package]]
@ -5481,15 +5484,24 @@ version = "0.1.0"
dependencies = [
"gloo-console",
"gloo-net 0.6.0",
"serde 1.0.217",
"serde 1.0.218",
"serde-wasm-bindgen",
"serde_json",
"visions-types",
"wasm-bindgen",
"wasm-bindgen-futures",
"web-sys",
"yew",
]
[[package]]
name = "visions-types"
version = "0.1.0"
dependencies = [
"serde 1.0.218",
"uuid 1.13.2",
]
[[package]]
name = "wait-timeout"
version = "0.2.0"
@ -5527,7 +5539,7 @@ dependencies = [
"percent-encoding 2.3.1",
"pin-project",
"scoped-tls",
"serde 1.0.217",
"serde 1.0.218",
"serde_json",
"serde_urlencoded",
"tokio",
@ -5910,7 +5922,7 @@ dependencies = [
"indexmap",
"js-sys",
"rustversion",
"serde 1.0.217",
"serde 1.0.218",
"slab",
"thiserror 1.0.69",
"tokio",
@ -5927,7 +5939,7 @@ name = "yew-app"
version = "0.1.0"
dependencies = [
"gloo-net 0.6.0",
"serde 1.0.217",
"serde 1.0.218",
"wasm-bindgen-futures",
"yew",
]
@ -5951,7 +5963,7 @@ version = "0.7.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "120e6aef9aa629e3d4f52dc8cc43a015c7724194c97dfaf45180d2daf2b77f40"
dependencies = [
"serde 1.0.217",
"serde 1.0.218",
"stable_deref_trait",
"yoke-derive",
"zerofrom",

View File

@ -2,24 +2,24 @@
resolver = "2"
members = [
"authdb",
# "bike-lights/bike",
"bike-lights/core",
"bike-lights/simulator",
"changeset",
"config",
"config-derive",
"coordinates",
"cyberpunk",
"cyber-slides",
"cyberpunk",
"cyberpunk-splash",
"dashboard",
"emseries",
"file-service",
"fitnesstrax/core",
"fitnesstrax/app",
"fitnesstrax/core",
"fluent-ergonomics",
"geo-types",
"gm-control-panel",
"gm-dash/server",
"hex-grid",
"icon-test",
"memorycache",
@ -32,5 +32,8 @@ members = [
"timezone-testing",
"tree",
"visions/server",
"gm-dash/server"
, "visions/yew-app", "visions/ui"]
"visions/types",
"visions/ui",
"visions/yew-app",
# "bike-lights/bike",
]

View File

@ -1,2 +0,0 @@
gen/
dist/

View File

@ -1,16 +0,0 @@
version: '3'
tasks:
fmt:
cmds:
- npx prettier -w package.json src
build:
cmds:
- cd ../types && task build
- npm install typescript
- npx tsc
test:
cmds:
- npx jest

View File

@ -1,29 +0,0 @@
import js from "@eslint/js";
import globals from "globals";
import reactHooks from "eslint-plugin-react-hooks";
import reactRefresh from "eslint-plugin-react-refresh";
import tseslint from "typescript-eslint";
import eslintConfigPrettier from "eslint-config-prettier";
export default tseslint.config(
{ ignores: ["dist"] },
{
extends: [js.configs.recommended, ...tseslint.configs.recommended, eslintConfigPrettier],
files: ["**/*.{ts,tsx}"],
languageOptions: {
ecmaVersion: 2020,
globals: globals.browser,
},
plugins: {
"react-hooks": reactHooks,
"react-refresh": reactRefresh,
},
rules: {
...reactHooks.configs.recommended.rules,
"react-refresh/only-export-components": [
"warn",
{ allowConstantExport: true },
],
},
},
);

View File

@ -1,8 +0,0 @@
/** @type {import('ts-jest').JestConfigWithTsJest} **/
module.exports = {
testEnvironment: "node",
testMatch: [ "**/*.test.ts" ],
transform: {
"^.+.tsx?$": ["ts-jest",{}],
},
};

File diff suppressed because it is too large Load Diff

View File

@ -1,30 +0,0 @@
{
"name": "visions-client",
"version": "0.0.1",
"description": "Shared data types for Visions",
"main": "dist/index.js",
"types": "dist/index.d.ts",
"files": [
"/dist"
],
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
},
"author": "",
"license": "ISC",
"prettier": {
"singleQuote": true,
"semi": false,
"tabWidth": 4
},
"devDependencies": {
"@types/jest": "^29.5.14",
"jest": "^29.7.0",
"prettier": "^3.5.1",
"ts-jest": "^29.2.5",
"typescript": "^5.7.3"
},
"dependencies": {
"visions-types": "file:../types"
}
}

View File

@ -1,96 +0,0 @@
import { Connection } from './index'
describe('what happens in an authentication', () => {
it('handles a successful response', async () => {
let client = new Connection(new URL('http://127.0.0.1:8001'))
let response = await client.auth('vakarian', 'aoeu')
expect(response).toEqual({
status: 'ok',
content: { type: 'success', content: 'vakarian-session-id' },
})
})
it('handles an authentication failure', async () => {
let client = new Connection(new URL('http://127.0.0.1:8001'))
{
let response = await client.auth('vakarian', '')
expect(response).toEqual({ status: 'unauthorized' })
}
{
let response = await client.auth('grunt', '')
expect(response).toEqual({ status: 'unauthorized' })
}
})
it('handles a password-reset condition', async () => {
let client = new Connection(new URL('http://127.0.0.1:8001'))
{
let response = await client.auth('shephard', 'aoeu')
expect(response).toEqual({
status: 'ok',
content: { type: 'password-reset', content: 'shephard-session-id' },
})
}
{
let response = await client.auth('shephard', '')
expect(response).toEqual({ status: 'unauthorized' })
}
})
it('lists users on an authenticated connection', async () => {
let client = new Connection(new URL('http://127.0.0.1:8001'))
{
let authResponse = await client.auth('vakarian', 'aoeu')
if (authResponse.status === 'ok' && authResponse.content.type === 'success') {
let sessionId = authResponse.content.content
let response = await client.listUsers(sessionId)
expect(response).toEqual({
status: 'ok',
content: [
{
id: 'vakarian-id',
name: 'vakarian',
status: { type: 'ok', content: undefined },
},
{
id: 'shephard-id',
name: 'shephard',
status: {
type: 'password-reset',
content: '2050-01-01 00:00:00',
},
},
{
id: 'tali-id',
name: 'tali',
status: { type: 'locked', content: undefined },
},
],
})
} else {
throw new Error('authorization should have been ok')
}
}
{
let authResponse = await client.auth('shephard', 'aoeu')
if (authResponse.status === 'ok' && authResponse.content.type === 'password-reset') {
let sessionId = authResponse.content.content
expect(await client.listUsers(sessionId)).toEqual({ status: 'unauthorized' })
} else {
throw new Error('Authorization shuld have been password-reset')
}
}
/*
{
let response = await client.listUsers('');
expect(response).toEqual({ status: 'unauthorized' })
}
{
let authResponse = await client.auth('shephard', 'aoeu')
let response = await client.listUsers(authResponse.content);
expect(response).toEqual({ status: 'password-reset' })
}
*/
})
})

View File

@ -1,63 +0,0 @@
import { AuthResponse, SessionId, UserOverview } from 'visions-types'
export interface Client {
auth: (
username: string,
password: string,
) => Promise<ClientResponse<AuthResponse<SessionId>>>
listUsers: (sessionId: SessionId) => Promise<ClientResponse<UserOverview[]>>
}
export type ClientResponse<A> =
| { status: 'ok'; content: A }
| { status: 'unauthorized' }
| { status: 'unexpected'; code: number }
export class Connection implements Client {
private base: URL
constructor(baseUrl: URL) {
this.base = baseUrl
}
async auth(
username: string,
password: string,
): Promise<ClientResponse<AuthResponse<SessionId>>> {
const url = new URL(this.base)
url.pathname = `/api/test/auth`
const response = await fetch(url, {
method: 'POST',
headers: [['Content-Type', 'application/json']],
body: JSON.stringify({ username: username, password: password }),
})
if (response.ok) {
let resp = await response.json()
return { status: 'ok', content: resp }
} else if (response.status == 401) {
return { status: 'unauthorized' }
} else {
return { status: 'unexpected', code: response.status }
}
}
async listUsers(
sessionId: SessionId,
): Promise<ClientResponse<UserOverview[]>> {
const url = new URL(this.base)
url.pathname = `/api/test/list-users`
const response = await fetch(url, {
method: 'GET',
headers: [['Authorization', `Bearer ${sessionId}`]],
})
if (response.ok) {
let resp = await response.json()
return { status: 'ok', content: resp }
} else if (response.status == 401) {
return { status: 'unauthorized' }
} else {
return { status: 'unexpected', code: response.status }
}
}
}

View File

@ -1,15 +0,0 @@
{
"compilerOptions": {
"target": "es2016",
"module": "commonjs",
"declaration": true,
"declarationMap": true,
"sourceMap": true,
"outDir": "./dist",
"esModuleInterop": true,
"forceConsistentCasingInFileNames": true,
"strict": true,
"skipLibCheck": true
},
"include": ["src/**/*"]
}

View File

@ -5,6 +5,7 @@ edition = "2021"
[dependencies]
axum = { version = "0.8.1", features = ["macros"] }
visions-types = { path = "../types" }
serde = { version = "1.0.217", features = ["derive", "serde_derive"] }
tokio = { version = "1.43.0", features = ["full", "rt"] }
tower-http = { version = "0.6.2", features = ["cors"] }

View File

@ -8,95 +8,10 @@ use axum::{
routing::{get, post},
Json, Router,
};
use visions_types::{AccountStatus, AuthRequest, AuthResponse, SessionId, UserOverview};
use result_extended::{error, ok, ResultExt};
use serde::{Deserialize, Serialize};
use thiserror::Error;
use tower_http::cors::{Any, CorsLayer};
use typeshare::typeshare;
use uuid::Uuid;
#[derive(Deserialize, Serialize)]
#[serde(tag = "type", content = "content", rename_all = "kebab-case")]
#[typeshare]
enum AccountStatus {
Ok,
PasswordReset(String),
Locked,
}
#[derive(Deserialize, Serialize)]
#[typeshare]
struct AuthRequest {
username: String,
password: String,
}
#[derive(Clone, Debug, Deserialize, Eq, Hash, PartialEq, Serialize)]
#[typeshare]
struct SessionId(String);
impl SessionId {
pub fn new() -> Self {
Self(format!("{}", Uuid::new_v4().hyphenated()))
}
pub fn as_str(&self) -> &str {
&self.0
}
}
impl From<&str> for SessionId {
fn from(s: &str) -> Self {
Self(s.to_owned())
}
}
impl From<String> for SessionId {
fn from(s: String) -> Self {
Self(s)
}
}
#[derive(Clone, Debug, Deserialize, Eq, Hash, PartialEq, Serialize)]
#[typeshare]
struct UserId(String);
impl UserId {
pub fn new() -> Self {
Self(format!("{}", Uuid::new_v4().hyphenated()))
}
pub fn as_str(&self) -> &str {
&self.0
}
}
impl From<&str> for UserId {
fn from(s: &str) -> Self {
Self(s.to_owned())
}
}
impl From<String> for UserId {
fn from(s: String) -> Self {
Self(s)
}
}
#[derive(Deserialize, Serialize)]
#[typeshare]
struct UserOverview {
id: UserId,
name: String,
status: AccountStatus,
}
#[derive(Deserialize, Serialize)]
#[typeshare]
enum AuthResponse {
Success(SessionId),
PasswordReset(SessionId),
}
#[axum::debug_handler]
async fn check_password(

8
visions/types/Cargo.toml Normal file
View File

@ -0,0 +1,8 @@
[package]
name = "visions-types"
version = "0.1.0"
edition = "2021"
[dependencies]
serde = { version = "1.0.218", features = ["derive"] }
uuid = { version = "1.13.2", features = ["v4", "js"] }

View File

@ -1,8 +0,0 @@
version: '3'
tasks:
build:
cmds:
- npm install typescript
- typeshare --lang typescript --output-file gen/index.ts ../server/src
- npx tsc

View File

@ -1,28 +0,0 @@
{
"name": "visions-types",
"version": "0.0.1",
"lockfileVersion": 3,
"requires": true,
"packages": {
"": {
"name": "visions-types",
"version": "0.0.1",
"license": "ISC",
"dependencies": {
"typescript": "^5.7.3"
}
},
"node_modules/typescript": {
"version": "5.7.3",
"resolved": "https://registry.npmjs.org/typescript/-/typescript-5.7.3.tgz",
"integrity": "sha512-84MVSjMEHP+FQRPy3pX9sTVV/INIex71s9TL2Gm5FG/WG1SqXeKyZ0k7/blY/4FdOzI12CBy1vGc4og/eus0fw==",
"bin": {
"tsc": "bin/tsc",
"tsserver": "bin/tsserver"
},
"engines": {
"node": ">=14.17"
}
}
}
}

View File

@ -1,18 +0,0 @@
{
"name": "visions-types",
"version": "0.0.1",
"description": "Shared data types for Visions",
"main": "dist/index.js",
"types": "dist/index.d.ts",
"files": [
"/dist"
],
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
},
"author": "",
"license": "ISC",
"dependencies": {
"typescript": "^5.7.3"
}
}

81
visions/types/src/lib.rs Normal file
View File

@ -0,0 +1,81 @@
use serde::{Deserialize, Serialize};
use uuid::Uuid;
#[derive(Deserialize, Serialize)]
#[serde(tag = "type", content = "content", rename_all = "kebab-case")]
pub enum AccountStatus {
Ok,
PasswordReset(String),
Locked,
}
#[derive(Deserialize, Serialize)]
pub struct AuthRequest {
pub username: String,
pub password: String,
}
#[derive(Clone, Debug, Deserialize, Eq, Hash, PartialEq, Serialize)]
pub struct SessionId(String);
impl SessionId {
pub fn new() -> Self {
Self(format!("{}", Uuid::new_v4().hyphenated()))
}
pub fn as_str(&self) -> &str {
&self.0
}
}
impl From<&str> for SessionId {
fn from(s: &str) -> Self {
Self(s.to_owned())
}
}
impl From<String> for SessionId {
fn from(s: String) -> Self {
Self(s)
}
}
#[derive(Clone, Debug, Deserialize, Eq, Hash, PartialEq, Serialize)]
pub struct UserId(String);
impl UserId {
pub fn new() -> Self {
Self(format!("{}", Uuid::new_v4().hyphenated()))
}
pub fn as_str(&self) -> &str {
&self.0
}
}
impl From<&str> for UserId {
fn from(s: &str) -> Self {
Self(s.to_owned())
}
}
impl From<String> for UserId {
fn from(s: String) -> Self {
Self(s)
}
}
#[derive(Deserialize, Serialize)]
pub struct UserOverview {
pub id: UserId,
pub name: String,
pub status: AccountStatus,
}
#[derive(Deserialize, Serialize)]
#[serde(tag = "type", content = "content", rename_all = "kebab-case")]
pub enum AuthResponse {
Success(SessionId),
PasswordReset(SessionId),
}

View File

@ -1,16 +0,0 @@
{
"compilerOptions": {
"target": "es6",
"module": "es6",
"moduleResolution": "node",
"declaration": true,
"declarationMap": true,
"sourceMap": true,
"outDir": "./dist",
"esModuleInterop": true,
"forceConsistentCasingInFileNames": true,
"strict": true,
"skipLibCheck": true,
"rootDir": "./gen"
}
}

View File

@ -4,6 +4,7 @@ version = "0.1.0"
edition = "2021"
[dependencies]
visions-types = { path = "../types" }
gloo-console = "0.3.0"
gloo-net = "0.6.0"
serde = { version = "1.0.217", features = ["derive"] }

View File

@ -2,41 +2,16 @@ use std::future::Future;
use gloo_console::log;
use gloo_net::http::{Request, Response};
use serde::{Deserialize, Serialize};
use wasm_bindgen_futures::wasm_bindgen::{self, JsValue};
#[derive(Serialize)]
struct AuthRequest {
username: String,
password: String,
}
#[derive(Deserialize)]
pub enum AuthResponse {
Success(SessionId),
PasswordReset(SessionId),
}
#[derive(Deserialize)]
pub struct SessionId(pub String);
use visions_types::{AuthRequest, AuthResponse, SessionId, UserOverview};
pub enum ClientError {
Unauthorized,
Err(u16),
}
#[derive(Deserialize)]
struct UserId(String);
#[derive(Deserialize)]
struct UserInfo {
id: UserId,
name: String,
}
pub trait Client {
fn auth(&self, username: String, password: String) -> impl Future<Output = Result<AuthResponse, ClientError>>;
fn list_users(&self, session_id: SessionId) -> impl Future<Output = Result<Vec<UserInfo>, ClientError>>;
fn list_users(&self, session_id: SessionId) -> impl Future<Output = Result<Vec<UserOverview>, ClientError>>;
}
pub struct Connection;
@ -63,7 +38,7 @@ impl Client for Connection {
}
}
async fn list_users(&self, session_id: SessionId) -> Result<Vec<UserInfo>, ClientError> {
async fn list_users(&self, session_id: SessionId) -> Result<Vec<UserOverview>, ClientError> {
todo!()
}
}

View File

@ -1,12 +1,13 @@
use std::rc::Rc;
use gloo_console::log;
use visions_types::AuthResponse;
use wasm_bindgen::JsCast;
use web_sys::HtmlInputElement;
use yew::prelude::*;
mod client;
pub use client::*;
use client::*;
struct AuthInfo {
session_id: Option<String>,
@ -87,11 +88,6 @@ fn Login(LoginProps { on_login }: &LoginProps) -> Html {
<input type="password" name="password" placeholder="password" onchange={on_password_changed} />
<button onclick={on_click}>{"Login"}</button>
</div>
<div class="card">
<p>{(*username).clone()}</p>
<p>{(*password).clone()}</p>
</div>
</div>
}
}
@ -108,10 +104,10 @@ fn App() -> Html {
let client = Connection::new();
match client.auth(username, password).await {
Ok(AuthResponse::Success(session_id)) => {
auth_info.dispatch(AuthAction::Auth(session_id.0))
auth_info.dispatch(AuthAction::Auth(session_id.as_str().to_owned()))
}
Ok(AuthResponse::PasswordReset(session_id)) => {
auth_info.dispatch(AuthAction::Auth(session_id.0))
auth_info.dispatch(AuthAction::Auth(session_id.as_str().to_owned()))
}
Err(ClientError::Unauthorized) => todo!(),
Err(ClientError::Err(status)) => todo!(),