feat(frontend): connect client to local SurrealDB
Add a SurrealDB service with a local IndexedDB-backed (indxdb://) connection for private, local-first data and an optional remote connection for sync. Initialize the local connection on app start and document the required VITE_* variables in .env.example. Bump the client version to 0.0.1.
This commit is contained in:
@@ -0,0 +1,16 @@
|
|||||||
|
# SurrealDB — frontend (Vite)
|
||||||
|
|
||||||
|
# Wspólna przestrzeń nazw / baza
|
||||||
|
VITE_SURREAL_NAMESPACE=hubmi
|
||||||
|
VITE_SURREAL_DATABASE=hubmi
|
||||||
|
|
||||||
|
# A) Lokalna baza w przeglądarce (WASM + IndexedDB; dane zostają lokalnie)
|
||||||
|
VITE_SURREAL_LOCAL_URL=indxdb://tarninahub
|
||||||
|
|
||||||
|
# B) Backend na dedykowanym porcie (tylko dla SurrealDB) — synchronizacja
|
||||||
|
VITE_SURREAL_REMOTE_URL=ws://127.0.0.1:8010/rpc
|
||||||
|
|
||||||
|
# Poświadczenia do zdalnej bazy. W produkcji NIE używaj root w przeglądarce —
|
||||||
|
# użyj tokenu dostępu rekordowego (record access) lub konta o wąskich uprawnieniach.
|
||||||
|
VITE_SURREAL_USERNAME=
|
||||||
|
VITE_SURREAL_PASSWORD=
|
||||||
Generated
+65
-3
@@ -1,15 +1,17 @@
|
|||||||
{
|
{
|
||||||
"name": "hubmi-client",
|
"name": "hubmi-client",
|
||||||
"version": "0.0.0",
|
"version": "0.0.1",
|
||||||
"lockfileVersion": 3,
|
"lockfileVersion": 3,
|
||||||
"requires": true,
|
"requires": true,
|
||||||
"packages": {
|
"packages": {
|
||||||
"": {
|
"": {
|
||||||
"name": "hubmi-client",
|
"name": "hubmi-client",
|
||||||
"version": "0.0.0",
|
"version": "0.0.1",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@mdi/font": "^7.4.47",
|
"@mdi/font": "^7.4.47",
|
||||||
|
"@surrealdb/wasm": "^2.6.1",
|
||||||
"@vueuse/core": "^15.0.0",
|
"@vueuse/core": "^15.0.0",
|
||||||
|
"surrealdb": "^2.0.10",
|
||||||
"vue": "^3.5.42",
|
"vue": "^3.5.42",
|
||||||
"vuetify": "^4.2.3"
|
"vuetify": "^4.2.3"
|
||||||
},
|
},
|
||||||
@@ -370,6 +372,24 @@
|
|||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "MIT"
|
"license": "MIT"
|
||||||
},
|
},
|
||||||
|
"node_modules/@surrealdb/cbor": {
|
||||||
|
"version": "2.0.0-alpha.4",
|
||||||
|
"resolved": "https://registry.npmjs.org/@surrealdb/cbor/-/cbor-2.0.0-alpha.4.tgz",
|
||||||
|
"integrity": "sha512-l/hNZ3ZCOJq8rzwx1y5ZV/8b2bYCWdhGqRVY33Pu50NAHyAW5qLsMn3ZBkZow77mAKwNCsbDsRGnyYEuU95mjw==",
|
||||||
|
"license": "Apache-2.0",
|
||||||
|
"engines": {
|
||||||
|
"node": ">=18.0.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/@surrealdb/wasm": {
|
||||||
|
"version": "2.6.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/@surrealdb/wasm/-/wasm-2.6.1.tgz",
|
||||||
|
"integrity": "sha512-pBxgOX/wZ+aBvMIJbDv6UtUDCT0RjhpPqa31NMUmAZuTx9WfZb1PQan4vCBH9rcSPDR6BC8zJ4pFQUuliFQUEQ==",
|
||||||
|
"license": "Apache-2.0",
|
||||||
|
"peerDependencies": {
|
||||||
|
"surrealdb": "^2.0.0-0"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/@types/node": {
|
"node_modules/@types/node": {
|
||||||
"version": "24.19.1",
|
"version": "24.19.1",
|
||||||
"resolved": "https://registry.npmjs.org/@types/node/-/node-24.19.1.tgz",
|
"resolved": "https://registry.npmjs.org/@types/node/-/node-24.19.1.tgz",
|
||||||
@@ -1147,6 +1167,33 @@
|
|||||||
"node": ">=0.10.0"
|
"node": ">=0.10.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/surrealdb": {
|
||||||
|
"version": "2.0.10",
|
||||||
|
"resolved": "https://registry.npmjs.org/surrealdb/-/surrealdb-2.0.10.tgz",
|
||||||
|
"integrity": "sha512-4r3LqhvGIRdEMUDO2u21jSi0C8x0x374mOmqCEEM5TrTsQWi5dUihBAfUFee+EBkrJeVDhBgcnvaMNPn+owc2Q==",
|
||||||
|
"license": "Apache-2.0",
|
||||||
|
"dependencies": {
|
||||||
|
"@surrealdb/sqon": "^0.1.5"
|
||||||
|
},
|
||||||
|
"peerDependencies": {
|
||||||
|
"tslib": "^2.6.3",
|
||||||
|
"typescript": "^5.0.0 || ^6.0.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/surrealdb/node_modules/@surrealdb/sqon": {
|
||||||
|
"version": "0.1.5",
|
||||||
|
"resolved": "https://registry.npmjs.org/@surrealdb/sqon/-/sqon-0.1.5.tgz",
|
||||||
|
"integrity": "sha512-wTo5eREYb+spcErgyKsyNt/QVnz9MaPhOrhqalNp6BWWQNXqgd0gZ8Pub2jjckLrULxRi9Cujamif0T34LBhBA==",
|
||||||
|
"license": "Apache-2.0",
|
||||||
|
"dependencies": {
|
||||||
|
"@surrealdb/cbor": "2.0.0-alpha.4",
|
||||||
|
"uuidv7": "^1.0.1"
|
||||||
|
},
|
||||||
|
"peerDependencies": {
|
||||||
|
"tslib": "^2.6.3",
|
||||||
|
"typescript": "^5.0.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/tinyglobby": {
|
"node_modules/tinyglobby": {
|
||||||
"version": "0.2.17",
|
"version": "0.2.17",
|
||||||
"resolved": "https://registry.npmjs.org/tinyglobby/-/tinyglobby-0.2.17.tgz",
|
"resolved": "https://registry.npmjs.org/tinyglobby/-/tinyglobby-0.2.17.tgz",
|
||||||
@@ -1164,11 +1211,17 @@
|
|||||||
"url": "https://github.com/sponsors/SuperchupuDev"
|
"url": "https://github.com/sponsors/SuperchupuDev"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/tslib": {
|
||||||
|
"version": "2.8.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz",
|
||||||
|
"integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==",
|
||||||
|
"license": "0BSD",
|
||||||
|
"peer": true
|
||||||
|
},
|
||||||
"node_modules/typescript": {
|
"node_modules/typescript": {
|
||||||
"version": "6.0.3",
|
"version": "6.0.3",
|
||||||
"resolved": "https://registry.npmjs.org/typescript/-/typescript-6.0.3.tgz",
|
"resolved": "https://registry.npmjs.org/typescript/-/typescript-6.0.3.tgz",
|
||||||
"integrity": "sha512-y2TvuxSZPDyQakkFRPZHKFm+KKVqIisdg9/CZwm9ftvKXLP8NRWj38/ODjNbr43SsoXqNuAisEf1GdCxqWcdBw==",
|
"integrity": "sha512-y2TvuxSZPDyQakkFRPZHKFm+KKVqIisdg9/CZwm9ftvKXLP8NRWj38/ODjNbr43SsoXqNuAisEf1GdCxqWcdBw==",
|
||||||
"devOptional": true,
|
|
||||||
"license": "Apache-2.0",
|
"license": "Apache-2.0",
|
||||||
"bin": {
|
"bin": {
|
||||||
"tsc": "bin/tsc",
|
"tsc": "bin/tsc",
|
||||||
@@ -1185,6 +1238,15 @@
|
|||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "MIT"
|
"license": "MIT"
|
||||||
},
|
},
|
||||||
|
"node_modules/uuidv7": {
|
||||||
|
"version": "1.2.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/uuidv7/-/uuidv7-1.2.1.tgz",
|
||||||
|
"integrity": "sha512-4kPkK3/XTQW9Hbm4CaqfICn+kY9LJtDVEOfgsRRra/+n2Ofg4NqzRFceAkxvQ/Ud/6BpHOPzj8cirqM7TzTN5Q==",
|
||||||
|
"license": "Apache-2.0",
|
||||||
|
"bin": {
|
||||||
|
"uuidv7": "cli.js"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/vite": {
|
"node_modules/vite": {
|
||||||
"version": "8.3.2",
|
"version": "8.3.2",
|
||||||
"resolved": "https://registry.npmjs.org/vite/-/vite-8.3.2.tgz",
|
"resolved": "https://registry.npmjs.org/vite/-/vite-8.3.2.tgz",
|
||||||
|
|||||||
+3
-1
@@ -1,7 +1,7 @@
|
|||||||
{
|
{
|
||||||
"name": "hubmi-client",
|
"name": "hubmi-client",
|
||||||
"private": true,
|
"private": true,
|
||||||
"version": "0.0.0",
|
"version": "0.0.1",
|
||||||
"type": "module",
|
"type": "module",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"dev": "vite",
|
"dev": "vite",
|
||||||
@@ -11,7 +11,9 @@
|
|||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@mdi/font": "^7.4.47",
|
"@mdi/font": "^7.4.47",
|
||||||
|
"@surrealdb/wasm": "^2.6.1",
|
||||||
"@vueuse/core": "^15.0.0",
|
"@vueuse/core": "^15.0.0",
|
||||||
|
"surrealdb": "^2.0.10",
|
||||||
"vue": "^3.5.42",
|
"vue": "^3.5.42",
|
||||||
"vuetify": "^4.2.3"
|
"vuetify": "^4.2.3"
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -1,7 +1,12 @@
|
|||||||
import { createApp } from 'vue'
|
import { createApp } from 'vue'
|
||||||
import vuetify from './plugins/vuetify'
|
import vuetify from './plugins/vuetify'
|
||||||
|
import { connectLocalSurreal } from './services/surreal'
|
||||||
import './style.css'
|
import './style.css'
|
||||||
import './styles/a11y.css'
|
import './styles/a11y.css'
|
||||||
import App from './App.vue'
|
import App from './App.vue'
|
||||||
|
|
||||||
|
void connectLocalSurreal().catch((error: unknown) => {
|
||||||
|
console.error('Nie udało się połączyć z lokalną bazą SurrealDB', error)
|
||||||
|
})
|
||||||
|
|
||||||
createApp(App).use(vuetify).mount('#app')
|
createApp(App).use(vuetify).mount('#app')
|
||||||
|
|||||||
@@ -0,0 +1,59 @@
|
|||||||
|
import { Surreal, createRemoteEngines } from 'surrealdb'
|
||||||
|
import { createWasmEngines } from '@surrealdb/wasm'
|
||||||
|
|
||||||
|
const namespace = import.meta.env.VITE_SURREAL_NAMESPACE ?? 'hubmi'
|
||||||
|
const database = import.meta.env.VITE_SURREAL_DATABASE ?? 'hubmi'
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A) Lokalna baza SurrealDB w przeglądarce.
|
||||||
|
* Persistencja przez IndexedDB (`indxdb://`) — localStorage jest zbyt mały.
|
||||||
|
* Dane prywatne użytkownika zostają tutaj i nie są wysyłane automatycznie.
|
||||||
|
*/
|
||||||
|
const localDatabase = import.meta.env.VITE_SURREAL_LOCAL_DATABASE ?? 'tarninahub'
|
||||||
|
const localUrl = import.meta.env.VITE_SURREAL_LOCAL_URL ?? `indxdb://${localDatabase}`
|
||||||
|
|
||||||
|
export const localSurreal = new Surreal({
|
||||||
|
engines: {
|
||||||
|
...createRemoteEngines(),
|
||||||
|
...createWasmEngines(),
|
||||||
|
},
|
||||||
|
})
|
||||||
|
|
||||||
|
let localConnection: Promise<void> | null = null
|
||||||
|
|
||||||
|
export function connectLocalSurreal(): Promise<void> {
|
||||||
|
localConnection ??= localSurreal
|
||||||
|
.connect(localUrl, { namespace, database })
|
||||||
|
.then(() => undefined)
|
||||||
|
|
||||||
|
return localConnection
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* B) Zdalna baza backendu na dedykowanym porcie (tylko dla SurrealDB),
|
||||||
|
* używana do synchronizacji danych uznanych za nadające się do wysłania.
|
||||||
|
*/
|
||||||
|
const remoteUrl =
|
||||||
|
import.meta.env.VITE_SURREAL_REMOTE_URL ?? 'ws://127.0.0.1:8010/rpc'
|
||||||
|
const username = import.meta.env.VITE_SURREAL_USERNAME as string | undefined
|
||||||
|
const password = import.meta.env.VITE_SURREAL_PASSWORD as string | undefined
|
||||||
|
|
||||||
|
export const remoteSurreal = new Surreal()
|
||||||
|
|
||||||
|
let remoteConnection: Promise<void> | null = null
|
||||||
|
|
||||||
|
export function connectRemoteSurreal(): Promise<void> {
|
||||||
|
remoteConnection ??= remoteSurreal
|
||||||
|
.connect(remoteUrl, {
|
||||||
|
namespace,
|
||||||
|
database,
|
||||||
|
...(username && password
|
||||||
|
? { authentication: { username, password } }
|
||||||
|
: {}),
|
||||||
|
})
|
||||||
|
.then(() => undefined)
|
||||||
|
|
||||||
|
return remoteConnection
|
||||||
|
}
|
||||||
|
|
||||||
|
export { namespace, database }
|
||||||
Reference in New Issue
Block a user