better transfer of user data between accounts when repairing, moved velconnect-svelte to npm package
parent
9029ed5917
commit
a0ce622c5d
|
|
@ -15,4 +15,5 @@ db/
|
||||||
velconnect*.db
|
velconnect*.db
|
||||||
.idea/
|
.idea/
|
||||||
velconnect/data/
|
velconnect/data/
|
||||||
*.db.bak
|
*.db.bak
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -8,6 +8,7 @@
|
||||||
"name": "example-dashboard",
|
"name": "example-dashboard",
|
||||||
"version": "0.0.1",
|
"version": "0.0.1",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
|
"@velaboratory/velconnect-svelte": "file:../velconnect-svelte-npm",
|
||||||
"humanize-duration": "^3.28.0",
|
"humanize-duration": "^3.28.0",
|
||||||
"luxon": "^3.3.0",
|
"luxon": "^3.3.0",
|
||||||
"pocketbase": "^0.15.2"
|
"pocketbase": "^0.15.2"
|
||||||
|
|
@ -31,6 +32,28 @@
|
||||||
"vite": "^4.3.6"
|
"vite": "^4.3.6"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"../velconect-svelte-npm": {
|
||||||
|
"name": "@velaboratory/velconnect-svelte",
|
||||||
|
"version": "1.0.0",
|
||||||
|
"extraneous": true,
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"pocketbase": "^0.15.3",
|
||||||
|
"svelte": "^4.0.5"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"../velconnect-svelte-npm": {
|
||||||
|
"name": "@velaboratory/velconnect-svelte",
|
||||||
|
"version": "1.0.0",
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"pocketbase": "^0.15.3",
|
||||||
|
"svelte": "^4.0.5"
|
||||||
|
},
|
||||||
|
"devDependencies": {
|
||||||
|
"typescript": "^5.1.6"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/@aashutoshrathi/word-wrap": {
|
"node_modules/@aashutoshrathi/word-wrap": {
|
||||||
"version": "1.2.6",
|
"version": "1.2.6",
|
||||||
"resolved": "https://registry.npmjs.org/@aashutoshrathi/word-wrap/-/word-wrap-1.2.6.tgz",
|
"resolved": "https://registry.npmjs.org/@aashutoshrathi/word-wrap/-/word-wrap-1.2.6.tgz",
|
||||||
|
|
@ -889,6 +912,10 @@
|
||||||
"url": "https://opencollective.com/typescript-eslint"
|
"url": "https://opencollective.com/typescript-eslint"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/@velaboratory/velconnect-svelte": {
|
||||||
|
"resolved": "../velconnect-svelte-npm",
|
||||||
|
"link": true
|
||||||
|
},
|
||||||
"node_modules/acorn": {
|
"node_modules/acorn": {
|
||||||
"version": "8.10.0",
|
"version": "8.10.0",
|
||||||
"resolved": "https://registry.npmjs.org/acorn/-/acorn-8.10.0.tgz",
|
"resolved": "https://registry.npmjs.org/acorn/-/acorn-8.10.0.tgz",
|
||||||
|
|
@ -3712,6 +3739,14 @@
|
||||||
"eslint-visitor-keys": "^3.3.0"
|
"eslint-visitor-keys": "^3.3.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"@velaboratory/velconnect-svelte": {
|
||||||
|
"version": "file:../velconnect-svelte-npm",
|
||||||
|
"requires": {
|
||||||
|
"pocketbase": "^0.15.3",
|
||||||
|
"svelte": "^4.0.5",
|
||||||
|
"typescript": "^5.1.6"
|
||||||
|
}
|
||||||
|
},
|
||||||
"acorn": {
|
"acorn": {
|
||||||
"version": "8.10.0",
|
"version": "8.10.0",
|
||||||
"resolved": "https://registry.npmjs.org/acorn/-/acorn-8.10.0.tgz",
|
"resolved": "https://registry.npmjs.org/acorn/-/acorn-8.10.0.tgz",
|
||||||
|
|
|
||||||
|
|
@ -31,6 +31,7 @@
|
||||||
},
|
},
|
||||||
"type": "module",
|
"type": "module",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
|
"@velaboratory/velconnect-svelte": "file:../velconnect-svelte-npm",
|
||||||
"humanize-duration": "^3.28.0",
|
"humanize-duration": "^3.28.0",
|
||||||
"luxon": "^3.3.0",
|
"luxon": "^3.3.0",
|
||||||
"pocketbase": "^0.15.2"
|
"pocketbase": "^0.15.2"
|
||||||
|
|
|
||||||
|
|
@ -1,44 +1,34 @@
|
||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import { currentUser, pb } from '$lib/js/velconnect';
|
import { currentUser, signUp, signOut, login } from '@velaboratory/velconnect-svelte';
|
||||||
|
|
||||||
let email: string;
|
let username: string;
|
||||||
let password: string;
|
let password: string;
|
||||||
|
let errorMessage = '';
|
||||||
async function login() {
|
|
||||||
const user = await pb.collection('Users').authWithPassword(email, password);
|
|
||||||
console.log(user);
|
|
||||||
}
|
|
||||||
|
|
||||||
async function signUp() {
|
|
||||||
try {
|
|
||||||
const data = {
|
|
||||||
email,
|
|
||||||
password,
|
|
||||||
passwordConfirm: password
|
|
||||||
};
|
|
||||||
const createdUser = await pb.collection('Users').create(data);
|
|
||||||
await login();
|
|
||||||
} catch (err) {
|
|
||||||
console.error(err);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function signOut() {
|
|
||||||
pb.authStore.clear();
|
|
||||||
}
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
{#if $currentUser}
|
{#if $currentUser}
|
||||||
<p>
|
<p>
|
||||||
Signed in as {$currentUser.email}
|
Signed in as {$currentUser.username}
|
||||||
<button on:click={signOut}>Sign Out</button>
|
<button on:click={signOut}>Sign Out</button>
|
||||||
</p>
|
</p>
|
||||||
{:else}
|
{:else}
|
||||||
<form on:submit|preventDefault>
|
<form on:submit|preventDefault>
|
||||||
<input placeholder="Email" type="text" bind:value={email} />
|
<input placeholder="Username" type="text" bind:value={username} />
|
||||||
|
|
||||||
<input placeholder="Password" type="password" bind:value={password} />
|
<input placeholder="Password" type="password" bind:value={password} />
|
||||||
<button on:click={signUp}>Sign Up</button>
|
<button
|
||||||
<button on:click={login}>Login</button>
|
on:click={() => {
|
||||||
|
signUp(username, password);
|
||||||
|
}}>Sign Up</button
|
||||||
|
>
|
||||||
|
<button
|
||||||
|
on:click={() => {
|
||||||
|
login(username, password);
|
||||||
|
}}>Login</button
|
||||||
|
>
|
||||||
|
<p class="error">{errorMessage}</p>
|
||||||
</form>
|
</form>
|
||||||
{/if}
|
{/if}
|
||||||
|
|
||||||
|
<style>
|
||||||
|
</style>
|
||||||
|
|
|
||||||
|
|
@ -1,37 +1,17 @@
|
||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import { currentDevice, currentUser, pb, type DeviceData, pairedDevices } from '$lib/js/velconnect';
|
import { pair } from '@velaboratory/velconnect-svelte';
|
||||||
|
|
||||||
let pairingCode: string;
|
let pairingCode: string;
|
||||||
let errorMessage: string | null;
|
let errorMessage: string | null;
|
||||||
|
|
||||||
async function pair() {
|
async function pairClick() {
|
||||||
// find the device by pairing code
|
const ret = await pair(pairingCode);
|
||||||
try {
|
errorMessage = ret.error ?? '';
|
||||||
let device = (await pb
|
|
||||||
.collection('Device')
|
|
||||||
.getFirstListItem(`pairing_code="${pairingCode}"`)) as DeviceData;
|
|
||||||
|
|
||||||
// add it to the local data
|
|
||||||
currentDevice.set(device.id);
|
|
||||||
pairedDevices.set([...$pairedDevices, device.id]);
|
|
||||||
|
|
||||||
// add it to my account if logged in
|
|
||||||
if ($currentUser) {
|
|
||||||
$currentUser.devices.push(device.id);
|
|
||||||
await pb.collection('Users').update($currentUser.id, $currentUser);
|
|
||||||
}
|
|
||||||
errorMessage = null;
|
|
||||||
} catch (e) {
|
|
||||||
if (e == "ClientResponseError 404: The requested resource wasn't found.") {
|
|
||||||
errorMessage = 'Device not found with this pairing code.';
|
|
||||||
}
|
|
||||||
console.error('Not found: ' + e);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<input bind:value={pairingCode} placeholder="Paring Code" />
|
<input bind:value={pairingCode} placeholder="Paring Code" />
|
||||||
<button on:click={pair}>Pair</button>
|
<button on:click={pairClick}>Pair</button>
|
||||||
{#if errorMessage}
|
{#if errorMessage}
|
||||||
<p>{errorMessage}</p>
|
<p>{errorMessage}</p>
|
||||||
{/if}
|
{/if}
|
||||||
|
|
|
||||||
|
|
@ -1,184 +0,0 @@
|
||||||
import PocketBase from 'pocketbase';
|
|
||||||
import { writable } from 'svelte/store';
|
|
||||||
import { type Record } from 'pocketbase';
|
|
||||||
import { get } from 'svelte/store';
|
|
||||||
|
|
||||||
export const pb = new PocketBase('https://velconnect-v3.ugavel.com');
|
|
||||||
// export const pb = new PocketBase('http://localhost:8090/_');
|
|
||||||
|
|
||||||
export const currentUser = writable(pb.authStore.model);
|
|
||||||
|
|
||||||
pb.authStore.onChange((auth) => {
|
|
||||||
console.log('authStore changed', auth);
|
|
||||||
currentUser.set(pb.authStore.model);
|
|
||||||
});
|
|
||||||
|
|
||||||
export const pairedDevices = writable<string[]>([]);
|
|
||||||
export const currentDevice = writable('');
|
|
||||||
|
|
||||||
interface HasData extends Record {
|
|
||||||
data: { [key: string]: string };
|
|
||||||
}
|
|
||||||
export interface DeviceData extends Record {
|
|
||||||
current_room: string;
|
|
||||||
current_app: string;
|
|
||||||
data: { [key: string]: string };
|
|
||||||
}
|
|
||||||
export interface RoomData extends HasData { }
|
|
||||||
|
|
||||||
const device = get(currentDevice);
|
|
||||||
if (device == '' && device.length > 0) {
|
|
||||||
currentDevice.set(device[0]);
|
|
||||||
}
|
|
||||||
|
|
||||||
let unsubscribeDeviceData: () => void;
|
|
||||||
let unsubscribeRoomData: () => void;
|
|
||||||
let unsubscribeCurrentDevice: () => void;
|
|
||||||
let unsubscribeCurrentUser: () => void;
|
|
||||||
|
|
||||||
export let deviceData = writable<DeviceData | null>(null);
|
|
||||||
export let roomData = writable<RoomData | null>(null);
|
|
||||||
|
|
||||||
export let sending = false;
|
|
||||||
|
|
||||||
export async function startListening() {
|
|
||||||
if (get(currentDevice) != '') {
|
|
||||||
deviceData = await pb.collection('Device').getOne(get(currentDevice));
|
|
||||||
}
|
|
||||||
|
|
||||||
unsubscribeCurrentDevice = currentDevice.subscribe(async (val) => {
|
|
||||||
console.log('current device changed');
|
|
||||||
unsubscribeDeviceData?.();
|
|
||||||
if (val != '') {
|
|
||||||
const d = (await pb.collection('Device').getOne(get(currentDevice))) as DeviceData;
|
|
||||||
deviceData.set(d);
|
|
||||||
if (d != null) getRoomData(d);
|
|
||||||
unsubscribeDeviceData = await pb.collection('Device').subscribe(val, async (data) => {
|
|
||||||
const d = data.record as DeviceData;
|
|
||||||
deviceData.set(d);
|
|
||||||
getRoomData(d);
|
|
||||||
});
|
|
||||||
} else {
|
|
||||||
deviceData.set(null);
|
|
||||||
roomData.set(null);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
unsubscribeCurrentUser = currentUser.subscribe((user) => {
|
|
||||||
pairedDevices.set(user?.devices ?? []);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
export function stopListening() {
|
|
||||||
unsubscribeCurrentDevice?.();
|
|
||||||
unsubscribeDeviceData?.();
|
|
||||||
unsubscribeRoomData?.();
|
|
||||||
unsubscribeCurrentUser?.();
|
|
||||||
}
|
|
||||||
|
|
||||||
async function getRoomData(deviceData: DeviceData) {
|
|
||||||
unsubscribeRoomData?.();
|
|
||||||
|
|
||||||
// create or just fetch room by name
|
|
||||||
const r = await fetch(
|
|
||||||
`${pb.baseUrl}/data_block/${deviceData.current_app}_${deviceData.current_room}`,
|
|
||||||
{
|
|
||||||
method: 'POST'
|
|
||||||
}
|
|
||||||
).then((r) => r.json());
|
|
||||||
roomData.set(r);
|
|
||||||
if (r) {
|
|
||||||
unsubscribeDeviceData = await pb.collection('DataBlock').subscribe(r.id, (data) => {
|
|
||||||
roomData.set(data.record as RoomData);
|
|
||||||
unsubscribeRoomData?.();
|
|
||||||
});
|
|
||||||
} else {
|
|
||||||
console.error('Failed to get or create room');
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
let abortController = new AbortController();
|
|
||||||
export function delayedSend() {
|
|
||||||
console.log('fn: delayedSend()');
|
|
||||||
|
|
||||||
// abort the previous send
|
|
||||||
abortController.abort();
|
|
||||||
const newAbortController = new AbortController();
|
|
||||||
abortController = newAbortController;
|
|
||||||
setTimeout(() => {
|
|
||||||
if (!newAbortController.signal.aborted) {
|
|
||||||
send();
|
|
||||||
} else {
|
|
||||||
console.log('aborted');
|
|
||||||
}
|
|
||||||
}, 1000);
|
|
||||||
}
|
|
||||||
|
|
||||||
export function send() {
|
|
||||||
console.log('sending...');
|
|
||||||
sending = true;
|
|
||||||
let promises = [];
|
|
||||||
const r = get(roomData);
|
|
||||||
const d = get(deviceData);
|
|
||||||
if (d) {
|
|
||||||
promises.push(pb.collection('Device').update(d.id, d));
|
|
||||||
}
|
|
||||||
if (r) {
|
|
||||||
promises.push(pb.collection('DataBlock').update(r.id, r));
|
|
||||||
}
|
|
||||||
Promise.all(promises).then(() => {
|
|
||||||
sending = false;
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
export function removeDevice(d: string) {
|
|
||||||
pairedDevices.set(get(pairedDevices).filter((i) => i != d));
|
|
||||||
|
|
||||||
if (get(currentDevice) == d) {
|
|
||||||
console.log('Removed current device');
|
|
||||||
|
|
||||||
// if there are still devices left
|
|
||||||
if (get(pairedDevices).length > 0) {
|
|
||||||
currentDevice.set(get(pairedDevices)[0]);
|
|
||||||
} else {
|
|
||||||
currentDevice.set('');
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
const user = get(currentUser);
|
|
||||||
if (user) {
|
|
||||||
user.devices.filter((i: string) => i != d);
|
|
||||||
pb.collection('Users').update(user.id, user);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
export async function pair(pairingCode: string) {
|
|
||||||
// find the device by pairing code
|
|
||||||
try {
|
|
||||||
let device = (await pb
|
|
||||||
.collection('Device')
|
|
||||||
.getFirstListItem(`pairing_code="${pairingCode}"`)) as DeviceData;
|
|
||||||
|
|
||||||
// add it to the local data
|
|
||||||
currentDevice.set(device.id);
|
|
||||||
pairedDevices.set([...get(pairedDevices), device.id]);
|
|
||||||
|
|
||||||
// add it to my account if logged in
|
|
||||||
const u = get(currentUser)
|
|
||||||
if (u) {
|
|
||||||
u.devices.push(device.id);
|
|
||||||
await pb.collection('Users').update(u.id, u);
|
|
||||||
}
|
|
||||||
return { error: null }
|
|
||||||
} catch (e) {
|
|
||||||
console.error('Not found: ' + e);
|
|
||||||
if (e == "ClientResponseError 404: The requested resource wasn't found.") {
|
|
||||||
return {
|
|
||||||
error: 'Device not found with this pairing code.'
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return {
|
|
||||||
error: e
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1,22 +1,24 @@
|
||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import {
|
import {
|
||||||
currentDevice,
|
currentDeviceId,
|
||||||
|
currentUser,
|
||||||
delayedSend,
|
delayedSend,
|
||||||
deviceData,
|
deviceData,
|
||||||
|
deviceFields,
|
||||||
pairedDevices,
|
pairedDevices,
|
||||||
removeDevice,
|
removeDevice,
|
||||||
roomData,
|
roomData,
|
||||||
sending,
|
sending,
|
||||||
startListening,
|
startListening,
|
||||||
stopListening
|
stopListening
|
||||||
} from '$lib/js/velconnect';
|
} from '@velaboratory/velconnect-svelte';
|
||||||
import Login from '$lib/components/Login.svelte';
|
import Login from '$lib/components/Login.svelte';
|
||||||
import Pair from '$lib/components/Pair.svelte';
|
import Pair from '$lib/components/Pair.svelte';
|
||||||
import { prettyDate } from '$lib/js/util';
|
import { prettyDate } from '$lib/js/util';
|
||||||
import { onDestroy, onMount } from 'svelte';
|
import { onDestroy, onMount } from 'svelte';
|
||||||
|
|
||||||
onMount(async () => {
|
onMount(async () => {
|
||||||
await startListening();
|
await startListening('http://localhost:8090');
|
||||||
});
|
});
|
||||||
onDestroy(() => {
|
onDestroy(() => {
|
||||||
stopListening();
|
stopListening();
|
||||||
|
|
@ -30,8 +32,9 @@
|
||||||
<h1>VEL-Connect</h1>
|
<h1>VEL-Connect</h1>
|
||||||
<img src="/img/velconnect_logo_1.png" alt="logo" width="70px" height="28px" />
|
<img src="/img/velconnect_logo_1.png" alt="logo" width="70px" height="28px" />
|
||||||
<p>
|
<p>
|
||||||
This is a demo dashboard. Visit the <a href="https://github.com/velaboratory/VEL-Connect"
|
This is a demo dashboard. Visit the <a
|
||||||
>GitHub repo</a
|
href="https://github.com/velaboratory/VEL-Connect"
|
||||||
|
target="_blank">GitHub repo</a
|
||||||
> to copy it and make your own.
|
> to copy it and make your own.
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
|
|
@ -45,7 +48,7 @@
|
||||||
<div>
|
<div>
|
||||||
<button
|
<button
|
||||||
on:click={() => {
|
on:click={() => {
|
||||||
currentDevice.set(d);
|
currentDeviceId.set(d);
|
||||||
}}>{d}</button
|
}}>{d}</button
|
||||||
>
|
>
|
||||||
<button
|
<button
|
||||||
|
|
@ -67,25 +70,25 @@
|
||||||
</div>
|
</div>
|
||||||
{/if}
|
{/if}
|
||||||
|
|
||||||
{#if $deviceData != null && $deviceData.data != null}
|
{#if $deviceFields != null && $deviceData != null}
|
||||||
<div>
|
<div>
|
||||||
<h3>Device Info</h3>
|
<h3>Device Info</h3>
|
||||||
|
|
||||||
<device-field>
|
<device-field>
|
||||||
<h6>Device ID:</h6>
|
<h6>Device ID:</h6>
|
||||||
<code>{$deviceData.id}</code>
|
<code>{$deviceFields.id}</code>
|
||||||
</device-field>
|
</device-field>
|
||||||
<device-field>
|
<device-field>
|
||||||
<h6>Pairing Code:</h6>
|
<h6>Pairing Code:</h6>
|
||||||
<code>{$deviceData.pairing_code}</code>
|
<code>{$deviceFields.pairing_code}</code>
|
||||||
</device-field>
|
</device-field>
|
||||||
<device-field>
|
<device-field>
|
||||||
<h6>First Seen</h6>
|
<h6>First Seen</h6>
|
||||||
<p>{prettyDate($deviceData.created)}</p>
|
<p>{prettyDate($deviceFields.created)}</p>
|
||||||
</device-field>
|
</device-field>
|
||||||
<device-field>
|
<device-field>
|
||||||
<h6>Last Seen</h6>
|
<h6>Last Seen</h6>
|
||||||
<p>{prettyDate($deviceData.updated)}</p>
|
<p>{prettyDate($deviceFields.updated)}</p>
|
||||||
</device-field>
|
</device-field>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|
@ -97,7 +100,7 @@
|
||||||
<input
|
<input
|
||||||
type="text"
|
type="text"
|
||||||
placeholder="Enter username..."
|
placeholder="Enter username..."
|
||||||
bind:value={$deviceData.friendly_name}
|
bind:value={$deviceFields.friendly_name}
|
||||||
on:input={delayedSend}
|
on:input={delayedSend}
|
||||||
/>
|
/>
|
||||||
</label>
|
</label>
|
||||||
|
|
@ -123,7 +126,7 @@
|
||||||
|
|
||||||
<device-field>
|
<device-field>
|
||||||
<h6>Current Room</h6>
|
<h6>Current Room</h6>
|
||||||
<a href="/join/{$deviceData.current_app}/room_name" target="blank">
|
<a href="/join/{$deviceFields.current_app}/room_name" target="blank">
|
||||||
Shareable Link
|
Shareable Link
|
||||||
<svg style="width:1em;height:1em;margin-bottom:-.15em;" viewBox="0 0 24 24">
|
<svg style="width:1em;height:1em;margin-bottom:-.15em;" viewBox="0 0 24 24">
|
||||||
<path
|
<path
|
||||||
|
|
@ -135,13 +138,17 @@
|
||||||
<input
|
<input
|
||||||
type="text"
|
type="text"
|
||||||
placeholder="room_1"
|
placeholder="room_1"
|
||||||
bind:value={$deviceData.current_room}
|
bind:value={$deviceFields.current_room}
|
||||||
on:input={delayedSend}
|
on:input={delayedSend}
|
||||||
/>
|
/>
|
||||||
</device-field>
|
</device-field>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<h3>Raw JSON:</h3>
|
<h3>Raw JSON:</h3>
|
||||||
|
<h6>User</h6>
|
||||||
|
<pre><code>{JSON.stringify($currentUser, null, 2)}</code></pre>
|
||||||
|
<h6>Device</h6>
|
||||||
|
<pre><code>{JSON.stringify($deviceFields, null, 2)}</code></pre>
|
||||||
<h6>Device Data</h6>
|
<h6>Device Data</h6>
|
||||||
<pre><code>{JSON.stringify($deviceData, null, 2)}</code></pre>
|
<pre><code>{JSON.stringify($deviceData, null, 2)}</code></pre>
|
||||||
<h6>Room Data</h6>
|
<h6>Room Data</h6>
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,12 @@
|
||||||
|
.DS_Store
|
||||||
|
node_modules
|
||||||
|
/build
|
||||||
|
/.svelte-kit
|
||||||
|
/package
|
||||||
|
.env
|
||||||
|
.env.*
|
||||||
|
!.env.example
|
||||||
|
vite.config.js.timestamp-*
|
||||||
|
vite.config.ts.timestamp-*
|
||||||
|
dist/
|
||||||
|
lib/
|
||||||
|
|
@ -0,0 +1,424 @@
|
||||||
|
{
|
||||||
|
"name": "@velaboratory/velconnect-svelte",
|
||||||
|
"version": "1.0.0",
|
||||||
|
"lockfileVersion": 2,
|
||||||
|
"requires": true,
|
||||||
|
"packages": {
|
||||||
|
"": {
|
||||||
|
"name": "@velaboratory/velconnect-svelte",
|
||||||
|
"version": "1.0.0",
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"pocketbase": "^0.15.3",
|
||||||
|
"svelte": "^4.0.5"
|
||||||
|
},
|
||||||
|
"devDependencies": {
|
||||||
|
"typescript": "^5.1.6"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/@ampproject/remapping": {
|
||||||
|
"version": "2.2.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/@ampproject/remapping/-/remapping-2.2.1.tgz",
|
||||||
|
"integrity": "sha512-lFMjJTrFL3j7L9yBxwYfCq2k6qqwHyzuUl/XBnif78PWTJYyL/dfowQHWE3sp6U6ZzqWiiIZnpTMO96zhkjwtg==",
|
||||||
|
"dependencies": {
|
||||||
|
"@jridgewell/gen-mapping": "^0.3.0",
|
||||||
|
"@jridgewell/trace-mapping": "^0.3.9"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">=6.0.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/@jridgewell/gen-mapping": {
|
||||||
|
"version": "0.3.3",
|
||||||
|
"resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.3.tgz",
|
||||||
|
"integrity": "sha512-HLhSWOLRi875zjjMG/r+Nv0oCW8umGb0BgEhyX3dDX3egwZtB8PqLnjz3yedt8R5StBrzcg4aBpnh8UA9D1BoQ==",
|
||||||
|
"dependencies": {
|
||||||
|
"@jridgewell/set-array": "^1.0.1",
|
||||||
|
"@jridgewell/sourcemap-codec": "^1.4.10",
|
||||||
|
"@jridgewell/trace-mapping": "^0.3.9"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">=6.0.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/@jridgewell/resolve-uri": {
|
||||||
|
"version": "3.1.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.0.tgz",
|
||||||
|
"integrity": "sha512-F2msla3tad+Mfht5cJq7LSXcdudKTWCVYUgw6pLFOOHSTtZlj6SWNYAp+AhuqLmWdBO2X5hPrLcu8cVP8fy28w==",
|
||||||
|
"engines": {
|
||||||
|
"node": ">=6.0.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/@jridgewell/set-array": {
|
||||||
|
"version": "1.1.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/@jridgewell/set-array/-/set-array-1.1.2.tgz",
|
||||||
|
"integrity": "sha512-xnkseuNADM0gt2bs+BvhO0p78Mk762YnZdsuzFV018NoG1Sj1SCQvpSqa7XUaTam5vAGasABV9qXASMKnFMwMw==",
|
||||||
|
"engines": {
|
||||||
|
"node": ">=6.0.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/@jridgewell/sourcemap-codec": {
|
||||||
|
"version": "1.4.15",
|
||||||
|
"resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.15.tgz",
|
||||||
|
"integrity": "sha512-eF2rxCRulEKXHTRiDrDy6erMYWqNw4LPdQ8UQA4huuxaQsVeRPFl2oM8oDGxMFhJUWZf9McpLtJasDDZb/Bpeg=="
|
||||||
|
},
|
||||||
|
"node_modules/@jridgewell/trace-mapping": {
|
||||||
|
"version": "0.3.18",
|
||||||
|
"resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.18.tgz",
|
||||||
|
"integrity": "sha512-w+niJYzMHdd7USdiH2U6869nqhD2nbfZXND5Yp93qIbEmnDNk7PD48o+YchRVpzMU7M6jVCbenTR7PA1FLQ9pA==",
|
||||||
|
"dependencies": {
|
||||||
|
"@jridgewell/resolve-uri": "3.1.0",
|
||||||
|
"@jridgewell/sourcemap-codec": "1.4.14"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/@jridgewell/trace-mapping/node_modules/@jridgewell/sourcemap-codec": {
|
||||||
|
"version": "1.4.14",
|
||||||
|
"resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.14.tgz",
|
||||||
|
"integrity": "sha512-XPSJHWmi394fuUuzDnGz1wiKqWfo1yXecHQMRf2l6hztTO+nPru658AyDngaBe7isIxEkRsPR3FZh+s7iVa4Uw=="
|
||||||
|
},
|
||||||
|
"node_modules/@types/estree": {
|
||||||
|
"version": "1.0.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.1.tgz",
|
||||||
|
"integrity": "sha512-LG4opVs2ANWZ1TJoKc937iMmNstM/d0ae1vNbnBvBhqCSezgVUOzcLCqbI5elV8Vy6WKwKjaqR+zO9VKirBBCA=="
|
||||||
|
},
|
||||||
|
"node_modules/acorn": {
|
||||||
|
"version": "8.10.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/acorn/-/acorn-8.10.0.tgz",
|
||||||
|
"integrity": "sha512-F0SAmZ8iUtS//m8DmCTA0jlh6TDKkHQyK6xc6V4KDTyZKA9dnvX9/3sRTVQrWm79glUAZbnmmNcdYwUIHWVybw==",
|
||||||
|
"bin": {
|
||||||
|
"acorn": "bin/acorn"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">=0.4.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/aria-query": {
|
||||||
|
"version": "5.3.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/aria-query/-/aria-query-5.3.0.tgz",
|
||||||
|
"integrity": "sha512-b0P0sZPKtyu8HkeRAfCq0IfURZK+SuwMjY1UXGBU27wpAiTwQAIlq56IbIO+ytk/JjS1fMR14ee5WBBfKi5J6A==",
|
||||||
|
"dependencies": {
|
||||||
|
"dequal": "^2.0.3"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/axobject-query": {
|
||||||
|
"version": "3.2.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/axobject-query/-/axobject-query-3.2.1.tgz",
|
||||||
|
"integrity": "sha512-jsyHu61e6N4Vbz/v18DHwWYKK0bSWLqn47eeDSKPB7m8tqMHF9YJ+mhIk2lVteyZrY8tnSj/jHOv4YiTCuCJgg==",
|
||||||
|
"dependencies": {
|
||||||
|
"dequal": "^2.0.3"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/code-red": {
|
||||||
|
"version": "1.0.3",
|
||||||
|
"resolved": "https://registry.npmjs.org/code-red/-/code-red-1.0.3.tgz",
|
||||||
|
"integrity": "sha512-kVwJELqiILQyG5aeuyKFbdsI1fmQy1Cmf7dQ8eGmVuJoaRVdwey7WaMknr2ZFeVSYSKT0rExsa8EGw0aoI/1QQ==",
|
||||||
|
"dependencies": {
|
||||||
|
"@jridgewell/sourcemap-codec": "^1.4.14",
|
||||||
|
"@types/estree": "^1.0.0",
|
||||||
|
"acorn": "^8.8.2",
|
||||||
|
"estree-walker": "^3.0.3",
|
||||||
|
"periscopic": "^3.1.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/css-tree": {
|
||||||
|
"version": "2.3.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/css-tree/-/css-tree-2.3.1.tgz",
|
||||||
|
"integrity": "sha512-6Fv1DV/TYw//QF5IzQdqsNDjx/wc8TrMBZsqjL9eW01tWb7R7k/mq+/VXfJCl7SoD5emsJop9cOByJZfs8hYIw==",
|
||||||
|
"dependencies": {
|
||||||
|
"mdn-data": "2.0.30",
|
||||||
|
"source-map-js": "^1.0.1"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": "^10 || ^12.20.0 || ^14.13.0 || >=15.0.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/dequal": {
|
||||||
|
"version": "2.0.3",
|
||||||
|
"resolved": "https://registry.npmjs.org/dequal/-/dequal-2.0.3.tgz",
|
||||||
|
"integrity": "sha512-0je+qPKHEMohvfRTCEo3CrPG6cAzAYgmzKyxRiYSSDkS6eGJdyVJm7WaYA5ECaAD9wLB2T4EEeymA5aFVcYXCA==",
|
||||||
|
"engines": {
|
||||||
|
"node": ">=6"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/estree-walker": {
|
||||||
|
"version": "3.0.3",
|
||||||
|
"resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-3.0.3.tgz",
|
||||||
|
"integrity": "sha512-7RUKfXgSMMkzt6ZuXmqapOurLGPPfgj6l9uRZ7lRGolvk0y2yocc35LdcxKC5PQZdn2DMqioAQ2NoWcrTKmm6g==",
|
||||||
|
"dependencies": {
|
||||||
|
"@types/estree": "^1.0.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/is-reference": {
|
||||||
|
"version": "3.0.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/is-reference/-/is-reference-3.0.1.tgz",
|
||||||
|
"integrity": "sha512-baJJdQLiYaJdvFbJqXrcGv3WU3QCzBlUcI5QhbesIm6/xPsvmO+2CDoi/GMOFBQEQm+PXkwOPrp9KK5ozZsp2w==",
|
||||||
|
"dependencies": {
|
||||||
|
"@types/estree": "*"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/locate-character": {
|
||||||
|
"version": "3.0.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/locate-character/-/locate-character-3.0.0.tgz",
|
||||||
|
"integrity": "sha512-SW13ws7BjaeJ6p7Q6CO2nchbYEc3X3J6WrmTTDto7yMPqVSZTUyY5Tjbid+Ab8gLnATtygYtiDIJGQRRn2ZOiA=="
|
||||||
|
},
|
||||||
|
"node_modules/magic-string": {
|
||||||
|
"version": "0.30.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.30.1.tgz",
|
||||||
|
"integrity": "sha512-mbVKXPmS0z0G4XqFDCTllmDQ6coZzn94aMlb0o/A4HEHJCKcanlDZwYJgwnkmgD3jyWhUgj9VsPrfd972yPffA==",
|
||||||
|
"dependencies": {
|
||||||
|
"@jridgewell/sourcemap-codec": "^1.4.15"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">=12"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/mdn-data": {
|
||||||
|
"version": "2.0.30",
|
||||||
|
"resolved": "https://registry.npmjs.org/mdn-data/-/mdn-data-2.0.30.tgz",
|
||||||
|
"integrity": "sha512-GaqWWShW4kv/G9IEucWScBx9G1/vsFZZJUO+tD26M8J8z3Kw5RDQjaoZe03YAClgeS/SWPOcb4nkFBTEi5DUEA=="
|
||||||
|
},
|
||||||
|
"node_modules/periscopic": {
|
||||||
|
"version": "3.1.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/periscopic/-/periscopic-3.1.0.tgz",
|
||||||
|
"integrity": "sha512-vKiQ8RRtkl9P+r/+oefh25C3fhybptkHKCZSPlcXiJux2tJF55GnEj3BVn4A5gKfq9NWWXXrxkHBwVPUfH0opw==",
|
||||||
|
"dependencies": {
|
||||||
|
"@types/estree": "^1.0.0",
|
||||||
|
"estree-walker": "^3.0.0",
|
||||||
|
"is-reference": "^3.0.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/pocketbase": {
|
||||||
|
"version": "0.15.3",
|
||||||
|
"resolved": "https://registry.npmjs.org/pocketbase/-/pocketbase-0.15.3.tgz",
|
||||||
|
"integrity": "sha512-sjM0XO4wHUlVZs94VhRJi4FeYtbLqvxFbRDJlfjFb/4FkxypbGwxLM4HDAEr8q6jdreuxAM1/n/b5HB1GjQ1Vg=="
|
||||||
|
},
|
||||||
|
"node_modules/source-map-js": {
|
||||||
|
"version": "1.0.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.0.2.tgz",
|
||||||
|
"integrity": "sha512-R0XvVJ9WusLiqTCEiGCmICCMplcCkIwwR11mOSD9CR5u+IXYdiseeEuXCVAjS54zqwkLcPNnmU4OeJ6tUrWhDw==",
|
||||||
|
"engines": {
|
||||||
|
"node": ">=0.10.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/svelte": {
|
||||||
|
"version": "4.0.5",
|
||||||
|
"resolved": "https://registry.npmjs.org/svelte/-/svelte-4.0.5.tgz",
|
||||||
|
"integrity": "sha512-PHKPWP1wiWHBtsE57nCb8xiWB3Ht7/3Kvi3jac0XIxUM2rep8alO7YoAtgWeGD7++tFy46krilOrPW0mG3Dx+A==",
|
||||||
|
"dependencies": {
|
||||||
|
"@ampproject/remapping": "^2.2.1",
|
||||||
|
"@jridgewell/sourcemap-codec": "^1.4.15",
|
||||||
|
"@jridgewell/trace-mapping": "^0.3.18",
|
||||||
|
"acorn": "^8.9.0",
|
||||||
|
"aria-query": "^5.3.0",
|
||||||
|
"axobject-query": "^3.2.1",
|
||||||
|
"code-red": "^1.0.3",
|
||||||
|
"css-tree": "^2.3.1",
|
||||||
|
"estree-walker": "^3.0.3",
|
||||||
|
"is-reference": "^3.0.1",
|
||||||
|
"locate-character": "^3.0.0",
|
||||||
|
"magic-string": "^0.30.0",
|
||||||
|
"periscopic": "^3.1.0"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">=16"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/typescript": {
|
||||||
|
"version": "5.1.6",
|
||||||
|
"resolved": "https://registry.npmjs.org/typescript/-/typescript-5.1.6.tgz",
|
||||||
|
"integrity": "sha512-zaWCozRZ6DLEWAWFrVDz1H6FVXzUSfTy5FUMWsQlU8Ym5JP9eO4xkTIROFCQvhQf61z6O/G6ugw3SgAnvvm+HA==",
|
||||||
|
"dev": true,
|
||||||
|
"bin": {
|
||||||
|
"tsc": "bin/tsc",
|
||||||
|
"tsserver": "bin/tsserver"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">=14.17"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"dependencies": {
|
||||||
|
"@ampproject/remapping": {
|
||||||
|
"version": "2.2.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/@ampproject/remapping/-/remapping-2.2.1.tgz",
|
||||||
|
"integrity": "sha512-lFMjJTrFL3j7L9yBxwYfCq2k6qqwHyzuUl/XBnif78PWTJYyL/dfowQHWE3sp6U6ZzqWiiIZnpTMO96zhkjwtg==",
|
||||||
|
"requires": {
|
||||||
|
"@jridgewell/gen-mapping": "^0.3.0",
|
||||||
|
"@jridgewell/trace-mapping": "^0.3.9"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"@jridgewell/gen-mapping": {
|
||||||
|
"version": "0.3.3",
|
||||||
|
"resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.3.tgz",
|
||||||
|
"integrity": "sha512-HLhSWOLRi875zjjMG/r+Nv0oCW8umGb0BgEhyX3dDX3egwZtB8PqLnjz3yedt8R5StBrzcg4aBpnh8UA9D1BoQ==",
|
||||||
|
"requires": {
|
||||||
|
"@jridgewell/set-array": "^1.0.1",
|
||||||
|
"@jridgewell/sourcemap-codec": "^1.4.10",
|
||||||
|
"@jridgewell/trace-mapping": "^0.3.9"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"@jridgewell/resolve-uri": {
|
||||||
|
"version": "3.1.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.0.tgz",
|
||||||
|
"integrity": "sha512-F2msla3tad+Mfht5cJq7LSXcdudKTWCVYUgw6pLFOOHSTtZlj6SWNYAp+AhuqLmWdBO2X5hPrLcu8cVP8fy28w=="
|
||||||
|
},
|
||||||
|
"@jridgewell/set-array": {
|
||||||
|
"version": "1.1.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/@jridgewell/set-array/-/set-array-1.1.2.tgz",
|
||||||
|
"integrity": "sha512-xnkseuNADM0gt2bs+BvhO0p78Mk762YnZdsuzFV018NoG1Sj1SCQvpSqa7XUaTam5vAGasABV9qXASMKnFMwMw=="
|
||||||
|
},
|
||||||
|
"@jridgewell/sourcemap-codec": {
|
||||||
|
"version": "1.4.15",
|
||||||
|
"resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.15.tgz",
|
||||||
|
"integrity": "sha512-eF2rxCRulEKXHTRiDrDy6erMYWqNw4LPdQ8UQA4huuxaQsVeRPFl2oM8oDGxMFhJUWZf9McpLtJasDDZb/Bpeg=="
|
||||||
|
},
|
||||||
|
"@jridgewell/trace-mapping": {
|
||||||
|
"version": "0.3.18",
|
||||||
|
"resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.18.tgz",
|
||||||
|
"integrity": "sha512-w+niJYzMHdd7USdiH2U6869nqhD2nbfZXND5Yp93qIbEmnDNk7PD48o+YchRVpzMU7M6jVCbenTR7PA1FLQ9pA==",
|
||||||
|
"requires": {
|
||||||
|
"@jridgewell/resolve-uri": "3.1.0",
|
||||||
|
"@jridgewell/sourcemap-codec": "1.4.14"
|
||||||
|
},
|
||||||
|
"dependencies": {
|
||||||
|
"@jridgewell/sourcemap-codec": {
|
||||||
|
"version": "1.4.14",
|
||||||
|
"resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.14.tgz",
|
||||||
|
"integrity": "sha512-XPSJHWmi394fuUuzDnGz1wiKqWfo1yXecHQMRf2l6hztTO+nPru658AyDngaBe7isIxEkRsPR3FZh+s7iVa4Uw=="
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"@types/estree": {
|
||||||
|
"version": "1.0.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.1.tgz",
|
||||||
|
"integrity": "sha512-LG4opVs2ANWZ1TJoKc937iMmNstM/d0ae1vNbnBvBhqCSezgVUOzcLCqbI5elV8Vy6WKwKjaqR+zO9VKirBBCA=="
|
||||||
|
},
|
||||||
|
"acorn": {
|
||||||
|
"version": "8.10.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/acorn/-/acorn-8.10.0.tgz",
|
||||||
|
"integrity": "sha512-F0SAmZ8iUtS//m8DmCTA0jlh6TDKkHQyK6xc6V4KDTyZKA9dnvX9/3sRTVQrWm79glUAZbnmmNcdYwUIHWVybw=="
|
||||||
|
},
|
||||||
|
"aria-query": {
|
||||||
|
"version": "5.3.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/aria-query/-/aria-query-5.3.0.tgz",
|
||||||
|
"integrity": "sha512-b0P0sZPKtyu8HkeRAfCq0IfURZK+SuwMjY1UXGBU27wpAiTwQAIlq56IbIO+ytk/JjS1fMR14ee5WBBfKi5J6A==",
|
||||||
|
"requires": {
|
||||||
|
"dequal": "^2.0.3"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"axobject-query": {
|
||||||
|
"version": "3.2.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/axobject-query/-/axobject-query-3.2.1.tgz",
|
||||||
|
"integrity": "sha512-jsyHu61e6N4Vbz/v18DHwWYKK0bSWLqn47eeDSKPB7m8tqMHF9YJ+mhIk2lVteyZrY8tnSj/jHOv4YiTCuCJgg==",
|
||||||
|
"requires": {
|
||||||
|
"dequal": "^2.0.3"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"code-red": {
|
||||||
|
"version": "1.0.3",
|
||||||
|
"resolved": "https://registry.npmjs.org/code-red/-/code-red-1.0.3.tgz",
|
||||||
|
"integrity": "sha512-kVwJELqiILQyG5aeuyKFbdsI1fmQy1Cmf7dQ8eGmVuJoaRVdwey7WaMknr2ZFeVSYSKT0rExsa8EGw0aoI/1QQ==",
|
||||||
|
"requires": {
|
||||||
|
"@jridgewell/sourcemap-codec": "^1.4.14",
|
||||||
|
"@types/estree": "^1.0.0",
|
||||||
|
"acorn": "^8.8.2",
|
||||||
|
"estree-walker": "^3.0.3",
|
||||||
|
"periscopic": "^3.1.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"css-tree": {
|
||||||
|
"version": "2.3.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/css-tree/-/css-tree-2.3.1.tgz",
|
||||||
|
"integrity": "sha512-6Fv1DV/TYw//QF5IzQdqsNDjx/wc8TrMBZsqjL9eW01tWb7R7k/mq+/VXfJCl7SoD5emsJop9cOByJZfs8hYIw==",
|
||||||
|
"requires": {
|
||||||
|
"mdn-data": "2.0.30",
|
||||||
|
"source-map-js": "^1.0.1"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"dequal": {
|
||||||
|
"version": "2.0.3",
|
||||||
|
"resolved": "https://registry.npmjs.org/dequal/-/dequal-2.0.3.tgz",
|
||||||
|
"integrity": "sha512-0je+qPKHEMohvfRTCEo3CrPG6cAzAYgmzKyxRiYSSDkS6eGJdyVJm7WaYA5ECaAD9wLB2T4EEeymA5aFVcYXCA=="
|
||||||
|
},
|
||||||
|
"estree-walker": {
|
||||||
|
"version": "3.0.3",
|
||||||
|
"resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-3.0.3.tgz",
|
||||||
|
"integrity": "sha512-7RUKfXgSMMkzt6ZuXmqapOurLGPPfgj6l9uRZ7lRGolvk0y2yocc35LdcxKC5PQZdn2DMqioAQ2NoWcrTKmm6g==",
|
||||||
|
"requires": {
|
||||||
|
"@types/estree": "^1.0.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"is-reference": {
|
||||||
|
"version": "3.0.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/is-reference/-/is-reference-3.0.1.tgz",
|
||||||
|
"integrity": "sha512-baJJdQLiYaJdvFbJqXrcGv3WU3QCzBlUcI5QhbesIm6/xPsvmO+2CDoi/GMOFBQEQm+PXkwOPrp9KK5ozZsp2w==",
|
||||||
|
"requires": {
|
||||||
|
"@types/estree": "*"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"locate-character": {
|
||||||
|
"version": "3.0.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/locate-character/-/locate-character-3.0.0.tgz",
|
||||||
|
"integrity": "sha512-SW13ws7BjaeJ6p7Q6CO2nchbYEc3X3J6WrmTTDto7yMPqVSZTUyY5Tjbid+Ab8gLnATtygYtiDIJGQRRn2ZOiA=="
|
||||||
|
},
|
||||||
|
"magic-string": {
|
||||||
|
"version": "0.30.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.30.1.tgz",
|
||||||
|
"integrity": "sha512-mbVKXPmS0z0G4XqFDCTllmDQ6coZzn94aMlb0o/A4HEHJCKcanlDZwYJgwnkmgD3jyWhUgj9VsPrfd972yPffA==",
|
||||||
|
"requires": {
|
||||||
|
"@jridgewell/sourcemap-codec": "^1.4.15"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"mdn-data": {
|
||||||
|
"version": "2.0.30",
|
||||||
|
"resolved": "https://registry.npmjs.org/mdn-data/-/mdn-data-2.0.30.tgz",
|
||||||
|
"integrity": "sha512-GaqWWShW4kv/G9IEucWScBx9G1/vsFZZJUO+tD26M8J8z3Kw5RDQjaoZe03YAClgeS/SWPOcb4nkFBTEi5DUEA=="
|
||||||
|
},
|
||||||
|
"periscopic": {
|
||||||
|
"version": "3.1.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/periscopic/-/periscopic-3.1.0.tgz",
|
||||||
|
"integrity": "sha512-vKiQ8RRtkl9P+r/+oefh25C3fhybptkHKCZSPlcXiJux2tJF55GnEj3BVn4A5gKfq9NWWXXrxkHBwVPUfH0opw==",
|
||||||
|
"requires": {
|
||||||
|
"@types/estree": "^1.0.0",
|
||||||
|
"estree-walker": "^3.0.0",
|
||||||
|
"is-reference": "^3.0.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"pocketbase": {
|
||||||
|
"version": "0.15.3",
|
||||||
|
"resolved": "https://registry.npmjs.org/pocketbase/-/pocketbase-0.15.3.tgz",
|
||||||
|
"integrity": "sha512-sjM0XO4wHUlVZs94VhRJi4FeYtbLqvxFbRDJlfjFb/4FkxypbGwxLM4HDAEr8q6jdreuxAM1/n/b5HB1GjQ1Vg=="
|
||||||
|
},
|
||||||
|
"source-map-js": {
|
||||||
|
"version": "1.0.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.0.2.tgz",
|
||||||
|
"integrity": "sha512-R0XvVJ9WusLiqTCEiGCmICCMplcCkIwwR11mOSD9CR5u+IXYdiseeEuXCVAjS54zqwkLcPNnmU4OeJ6tUrWhDw=="
|
||||||
|
},
|
||||||
|
"svelte": {
|
||||||
|
"version": "4.0.5",
|
||||||
|
"resolved": "https://registry.npmjs.org/svelte/-/svelte-4.0.5.tgz",
|
||||||
|
"integrity": "sha512-PHKPWP1wiWHBtsE57nCb8xiWB3Ht7/3Kvi3jac0XIxUM2rep8alO7YoAtgWeGD7++tFy46krilOrPW0mG3Dx+A==",
|
||||||
|
"requires": {
|
||||||
|
"@ampproject/remapping": "^2.2.1",
|
||||||
|
"@jridgewell/sourcemap-codec": "^1.4.15",
|
||||||
|
"@jridgewell/trace-mapping": "^0.3.18",
|
||||||
|
"acorn": "^8.9.0",
|
||||||
|
"aria-query": "^5.3.0",
|
||||||
|
"axobject-query": "^3.2.1",
|
||||||
|
"code-red": "^1.0.3",
|
||||||
|
"css-tree": "^2.3.1",
|
||||||
|
"estree-walker": "^3.0.3",
|
||||||
|
"is-reference": "^3.0.1",
|
||||||
|
"locate-character": "^3.0.0",
|
||||||
|
"magic-string": "^0.30.0",
|
||||||
|
"periscopic": "^3.1.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"typescript": {
|
||||||
|
"version": "5.1.6",
|
||||||
|
"resolved": "https://registry.npmjs.org/typescript/-/typescript-5.1.6.tgz",
|
||||||
|
"integrity": "sha512-zaWCozRZ6DLEWAWFrVDz1H6FVXzUSfTy5FUMWsQlU8Ym5JP9eO4xkTIROFCQvhQf61z6O/G6ugw3SgAnvvm+HA==",
|
||||||
|
"dev": true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,22 @@
|
||||||
|
{
|
||||||
|
"name": "@velaboratory/velconnect-svelte",
|
||||||
|
"version": "1.0.1",
|
||||||
|
"description": "Use VEL-Connect with a Svelte dashboard",
|
||||||
|
"main": "src/index.js",
|
||||||
|
"files": [
|
||||||
|
"dist",
|
||||||
|
"src"
|
||||||
|
],
|
||||||
|
"scripts": {
|
||||||
|
"build": "tsc --module commonjs"
|
||||||
|
},
|
||||||
|
"author": "VEL",
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"pocketbase": "^0.15.3",
|
||||||
|
"svelte": "^4.0.5"
|
||||||
|
},
|
||||||
|
"devDependencies": {
|
||||||
|
"typescript": "^5.1.6"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,267 @@
|
||||||
|
import PocketBase from "pocketbase";
|
||||||
|
import { writable } from "svelte/store";
|
||||||
|
import type { Record } from "pocketbase";
|
||||||
|
import { get } from "svelte/store";
|
||||||
|
|
||||||
|
export const pb = new PocketBase();
|
||||||
|
|
||||||
|
export const currentUser = writable(pb.authStore.model);
|
||||||
|
|
||||||
|
pb.authStore.onChange((auth) => {
|
||||||
|
console.log("authStore changed", auth);
|
||||||
|
currentUser.set(pb.authStore.model);
|
||||||
|
if (pb.authStore.isValid) {
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
export const pairedDevices = writable<string[]>([]);
|
||||||
|
export const currentDeviceId = writable("");
|
||||||
|
|
||||||
|
export interface Device extends Record {
|
||||||
|
os_info: string;
|
||||||
|
friendly_name: string;
|
||||||
|
current_room: string;
|
||||||
|
current_app: string;
|
||||||
|
pairing_code: string;
|
||||||
|
data: string;
|
||||||
|
expand: { data?: DataBlock };
|
||||||
|
}
|
||||||
|
export interface DataBlock extends Record {
|
||||||
|
data: { [key: string]: string };
|
||||||
|
}
|
||||||
|
|
||||||
|
// const device = get(currentDevice);
|
||||||
|
// if (device == '' && device.length > 0) {
|
||||||
|
// currentDevice.set(device[0]);
|
||||||
|
// }
|
||||||
|
|
||||||
|
let unsubscribeDeviceFields: () => void;
|
||||||
|
let unsubscribeDeviceData: () => void;
|
||||||
|
let unsubscribeRoomData: () => void;
|
||||||
|
let unsubscribeCurrentDevice: () => void;
|
||||||
|
let unsubscribeCurrentUser: () => void;
|
||||||
|
|
||||||
|
export let deviceFields = writable<Device | null>(null);
|
||||||
|
export let deviceData = writable<DataBlock | null>(null);
|
||||||
|
export let roomData = writable<DataBlock | null>(null);
|
||||||
|
|
||||||
|
export let sending = false;
|
||||||
|
|
||||||
|
export async function startListening(baseUrl: string) {
|
||||||
|
pb.baseUrl = baseUrl;
|
||||||
|
if (get(currentDeviceId) != "") {
|
||||||
|
const d = (await pb.collection("Device").getOne(get(currentDeviceId), {
|
||||||
|
expand: "data",
|
||||||
|
})) as Device;
|
||||||
|
deviceFields.set(d);
|
||||||
|
deviceData.set(d.expand.data as DataBlock);
|
||||||
|
}
|
||||||
|
|
||||||
|
unsubscribeCurrentDevice = currentDeviceId.subscribe(async (val) => {
|
||||||
|
console.log("current device changed");
|
||||||
|
unsubscribeDeviceFields?.();
|
||||||
|
unsubscribeDeviceData?.();
|
||||||
|
if (val != "") {
|
||||||
|
const d = (await pb
|
||||||
|
.collection("Device")
|
||||||
|
.getOne(get(currentDeviceId), { expand: "data" })) as Device;
|
||||||
|
deviceFields.set(d);
|
||||||
|
deviceData.set(d.expand.data as DataBlock);
|
||||||
|
|
||||||
|
unsubscribeDeviceFields = await pb
|
||||||
|
.collection("Device")
|
||||||
|
.subscribe(val, async (data) => {
|
||||||
|
const d = data.record as Device;
|
||||||
|
deviceFields.set(d);
|
||||||
|
|
||||||
|
unsubscribeDeviceData = await pb
|
||||||
|
.collection("DataBlock")
|
||||||
|
.subscribe(d.id, async (data) => {
|
||||||
|
deviceData.set(data.record as DataBlock);
|
||||||
|
});
|
||||||
|
|
||||||
|
getRoomData(d);
|
||||||
|
});
|
||||||
|
|
||||||
|
if (d != null) getRoomData(d);
|
||||||
|
} else {
|
||||||
|
deviceFields.set(null);
|
||||||
|
deviceData.set(null);
|
||||||
|
roomData.set(null);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
unsubscribeCurrentUser = currentUser.subscribe((user) => {
|
||||||
|
pairedDevices.set(user?.["devices"] ?? []);
|
||||||
|
currentDeviceId.set(get(pairedDevices)[0] ?? "");
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
export function stopListening() {
|
||||||
|
unsubscribeCurrentDevice?.();
|
||||||
|
unsubscribeDeviceFields?.();
|
||||||
|
unsubscribeDeviceData?.();
|
||||||
|
unsubscribeRoomData?.();
|
||||||
|
unsubscribeCurrentUser?.();
|
||||||
|
console.log("Stop listening");
|
||||||
|
}
|
||||||
|
|
||||||
|
async function getRoomData(device: Device) {
|
||||||
|
unsubscribeRoomData?.();
|
||||||
|
|
||||||
|
// create or just fetch room by name
|
||||||
|
const r = (await pb
|
||||||
|
.collection("DataBlock")
|
||||||
|
.getFirstListItem(
|
||||||
|
`block_id="${device.current_app}_${device.current_room}"`
|
||||||
|
)) as DataBlock;
|
||||||
|
roomData.set(r);
|
||||||
|
if (r) {
|
||||||
|
unsubscribeRoomData = await pb
|
||||||
|
.collection("DataBlock")
|
||||||
|
.subscribe(r.id, (data) => {
|
||||||
|
roomData.set(data.record as DataBlock);
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
console.error("Failed to get or create room");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
let abortController = new AbortController();
|
||||||
|
export function delayedSend() {
|
||||||
|
console.log("fn: delayedSend()");
|
||||||
|
|
||||||
|
// abort the previous send
|
||||||
|
abortController.abort();
|
||||||
|
const newAbortController = new AbortController();
|
||||||
|
abortController = newAbortController;
|
||||||
|
setTimeout(() => {
|
||||||
|
if (!newAbortController.signal.aborted) {
|
||||||
|
send();
|
||||||
|
} else {
|
||||||
|
console.log("aborted");
|
||||||
|
}
|
||||||
|
}, 1000);
|
||||||
|
}
|
||||||
|
|
||||||
|
export function send() {
|
||||||
|
console.log("sending...");
|
||||||
|
sending = true;
|
||||||
|
let promises: Promise<any>[] = [];
|
||||||
|
const room = get(roomData);
|
||||||
|
const device = get(deviceFields);
|
||||||
|
const data = get(deviceData);
|
||||||
|
if (device) {
|
||||||
|
promises.push(pb.collection("Device").update(device.id, device));
|
||||||
|
}
|
||||||
|
if (data) {
|
||||||
|
promises.push(pb.collection("DataBlock").update(data.id, data));
|
||||||
|
}
|
||||||
|
if (room) {
|
||||||
|
promises.push(pb.collection("DataBlock").update(room.id, room));
|
||||||
|
}
|
||||||
|
Promise.all(promises).then(() => {
|
||||||
|
sending = false;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
export function removeDevice(d: string) {
|
||||||
|
pairedDevices.set(get(pairedDevices).filter((i) => i != d));
|
||||||
|
|
||||||
|
if (get(currentDeviceId) == d) {
|
||||||
|
console.log("Removed current device");
|
||||||
|
|
||||||
|
// if there are still devices left
|
||||||
|
if (get(pairedDevices).length > 0) {
|
||||||
|
currentDeviceId.set(get(pairedDevices)[0] ?? "");
|
||||||
|
} else {
|
||||||
|
currentDeviceId.set("");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const user = get(currentUser);
|
||||||
|
if (user) {
|
||||||
|
user["devices"] = user["devices"].filter((i: string) => i != d);
|
||||||
|
pb.collection("Users").update(user.id, user);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function pair(pairingCode: string) {
|
||||||
|
try {
|
||||||
|
// find the device by pairing code
|
||||||
|
const device = (await pb
|
||||||
|
.collection("Device")
|
||||||
|
.getFirstListItem(`pairing_code="${pairingCode}"`)) as Device;
|
||||||
|
|
||||||
|
// add it to the local data
|
||||||
|
currentDeviceId.set(device.id);
|
||||||
|
pairedDevices.set([...get(pairedDevices), device.id]);
|
||||||
|
|
||||||
|
// add it to my account if logged in
|
||||||
|
const u = get(currentUser);
|
||||||
|
if (u) {
|
||||||
|
// add the device to the user's devices
|
||||||
|
u["devices"].push(device.id);
|
||||||
|
|
||||||
|
// add the account data to the device
|
||||||
|
if (
|
||||||
|
u.user_data == null ||
|
||||||
|
u.user_data == undefined ||
|
||||||
|
u.user_data == ""
|
||||||
|
) {
|
||||||
|
// create a new user data block if it doesn't exist on the user already
|
||||||
|
const userDataBlock = await pb.collection("DataBlock").create({
|
||||||
|
category: "device",
|
||||||
|
data: {},
|
||||||
|
owner: u.id,
|
||||||
|
});
|
||||||
|
u.user_data = userDataBlock.id;
|
||||||
|
}
|
||||||
|
device["data"] = u.user_data;
|
||||||
|
device["owner"] = u.id;
|
||||||
|
device["past_owners"] = [...device["past_owners"], u.id];
|
||||||
|
|
||||||
|
await pb.collection("Device").update(device.id, device);
|
||||||
|
await pb.collection("Users").update(u.id, u);
|
||||||
|
}
|
||||||
|
|
||||||
|
return { error: null };
|
||||||
|
} catch (e) {
|
||||||
|
console.error("Not found: " + e);
|
||||||
|
if (e == "ClientResponseError 404: The requested resource wasn't found.") {
|
||||||
|
return {
|
||||||
|
error: "Device not found with this pairing code.",
|
||||||
|
};
|
||||||
|
}
|
||||||
|
return {
|
||||||
|
error: e as string,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function login(username: string, password: string) {
|
||||||
|
try {
|
||||||
|
await pb.collection("Users").authWithPassword(username, password);
|
||||||
|
return "";
|
||||||
|
} catch (err) {
|
||||||
|
return err as string;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function signUp(username: string, password: string) {
|
||||||
|
try {
|
||||||
|
const data = {
|
||||||
|
email: username,
|
||||||
|
password,
|
||||||
|
passwordConfirm: password,
|
||||||
|
};
|
||||||
|
await pb.collection("Users").create(data);
|
||||||
|
return await login(username, password);
|
||||||
|
} catch (err) {
|
||||||
|
return err as string;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export function signOut() {
|
||||||
|
pb.authStore.clear();
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,27 @@
|
||||||
|
{
|
||||||
|
"include": ["src"],
|
||||||
|
"compilerOptions": {
|
||||||
|
"target": "es2018",
|
||||||
|
"moduleResolution": "node", // don't have to import actual filenames, can import extensionless files
|
||||||
|
"declaration": true, // generate .d.ts files
|
||||||
|
"sourceMap": true, // generate source map
|
||||||
|
"outDir": "dist", // output compiled js, d.ts, and source map to dist folder
|
||||||
|
"strict": true,
|
||||||
|
"noImplicitAny": true,
|
||||||
|
"esModuleInterop": true,
|
||||||
|
"forceConsistentCasingInFileNames": true,
|
||||||
|
"strictNullChecks": true,
|
||||||
|
"strictFunctionTypes": true,
|
||||||
|
"strictBindCallApply": true,
|
||||||
|
"strictPropertyInitialization": true,
|
||||||
|
"noImplicitThis": true,
|
||||||
|
"alwaysStrict": true,
|
||||||
|
"noUnusedLocals": true,
|
||||||
|
"noUnusedParameters": true,
|
||||||
|
"noImplicitReturns": true,
|
||||||
|
"noFallthroughCasesInSwitch": true,
|
||||||
|
"noUncheckedIndexedAccess": true,
|
||||||
|
"noImplicitOverride": true,
|
||||||
|
"noPropertyAccessFromIndexSignature": true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -34,7 +34,7 @@ func main() {
|
||||||
dao := app.Dao()
|
dao := app.Dao()
|
||||||
requestData := apis.RequestData(c)
|
requestData := apis.RequestData(c)
|
||||||
|
|
||||||
log.Println(requestData)
|
// log.Println(requestData)
|
||||||
|
|
||||||
// get the old value to do a merge
|
// get the old value to do a merge
|
||||||
record, err := dao.FindFirstRecordByData("DataBlock", "block_id", c.PathParam("block_id"))
|
record, err := dao.FindFirstRecordByData("DataBlock", "block_id", c.PathParam("block_id"))
|
||||||
|
|
@ -68,7 +68,7 @@ func main() {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
log.Println(record)
|
// log.Println(record)
|
||||||
return c.JSON(http.StatusOK, record)
|
return c.JSON(http.StatusOK, record)
|
||||||
},
|
},
|
||||||
apis.ActivityLogger(app),
|
apis.ActivityLogger(app),
|
||||||
|
|
@ -108,7 +108,7 @@ func main() {
|
||||||
deviceRecord = models.NewRecord(collection)
|
deviceRecord = models.NewRecord(collection)
|
||||||
deviceRecord.SetId(c.PathParam("device_id"))
|
deviceRecord.SetId(c.PathParam("device_id"))
|
||||||
}
|
}
|
||||||
log.Println(deviceRecord.PublicExport())
|
// log.Println(deviceRecord.PublicExport())
|
||||||
|
|
||||||
// get the device data block
|
// get the device data block
|
||||||
deviceDataRecord, err := dao.FindRecordById("DataBlock", deviceRecord.GetString("data"))
|
deviceDataRecord, err := dao.FindRecordById("DataBlock", deviceRecord.GetString("data"))
|
||||||
|
|
@ -180,9 +180,12 @@ func main() {
|
||||||
}
|
}
|
||||||
|
|
||||||
apis.EnrichRecord(c, app.Dao(), deviceRecord, "data")
|
apis.EnrichRecord(c, app.Dao(), deviceRecord, "data")
|
||||||
room, _ := app.Dao().FindFirstRecordByData("DataBlock", "block_id", deviceRecord.GetString("current_room"))
|
room, roomErr := app.Dao().FindFirstRecordByData("DataBlock", "block_id", deviceRecord.GetString("current_app")+"_"+deviceRecord.GetString("current_room"))
|
||||||
user, _ := app.Dao().FindRecordById("Users", deviceRecord.GetString("owner"))
|
user, _ := app.Dao().FindRecordById("Users", deviceRecord.GetString("owner"))
|
||||||
|
|
||||||
|
log.Println(deviceRecord.GetString("current_room"))
|
||||||
|
log.Println(roomErr)
|
||||||
|
|
||||||
output := map[string]interface{}{
|
output := map[string]interface{}{
|
||||||
"device": deviceRecord,
|
"device": deviceRecord,
|
||||||
"room": room,
|
"room": room,
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,54 @@
|
||||||
|
package migrations
|
||||||
|
|
||||||
|
import (
|
||||||
|
"encoding/json"
|
||||||
|
|
||||||
|
"github.com/pocketbase/dbx"
|
||||||
|
"github.com/pocketbase/pocketbase/daos"
|
||||||
|
m "github.com/pocketbase/pocketbase/migrations"
|
||||||
|
"github.com/pocketbase/pocketbase/models/schema"
|
||||||
|
)
|
||||||
|
|
||||||
|
func init() {
|
||||||
|
m.Register(func(db dbx.Builder) error {
|
||||||
|
dao := daos.New(db);
|
||||||
|
|
||||||
|
collection, err := dao.FindCollectionByNameOrId("_pb_users_auth_")
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
// add
|
||||||
|
new_device_data := &schema.SchemaField{}
|
||||||
|
json.Unmarshal([]byte(`{
|
||||||
|
"system": false,
|
||||||
|
"id": "xvw8arlm",
|
||||||
|
"name": "device_data",
|
||||||
|
"type": "relation",
|
||||||
|
"required": false,
|
||||||
|
"unique": false,
|
||||||
|
"options": {
|
||||||
|
"collectionId": "3qwwkz4wb0lyi78",
|
||||||
|
"cascadeDelete": false,
|
||||||
|
"minSelect": null,
|
||||||
|
"maxSelect": 1,
|
||||||
|
"displayFields": []
|
||||||
|
}
|
||||||
|
}`), new_device_data)
|
||||||
|
collection.Schema.AddField(new_device_data)
|
||||||
|
|
||||||
|
return dao.SaveCollection(collection)
|
||||||
|
}, func(db dbx.Builder) error {
|
||||||
|
dao := daos.New(db);
|
||||||
|
|
||||||
|
collection, err := dao.FindCollectionByNameOrId("_pb_users_auth_")
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
// remove
|
||||||
|
collection.Schema.RemoveField("xvw8arlm")
|
||||||
|
|
||||||
|
return dao.SaveCollection(collection)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,70 @@
|
||||||
|
package migrations
|
||||||
|
|
||||||
|
import (
|
||||||
|
"encoding/json"
|
||||||
|
|
||||||
|
"github.com/pocketbase/dbx"
|
||||||
|
"github.com/pocketbase/pocketbase/daos"
|
||||||
|
m "github.com/pocketbase/pocketbase/migrations"
|
||||||
|
"github.com/pocketbase/pocketbase/models/schema"
|
||||||
|
)
|
||||||
|
|
||||||
|
func init() {
|
||||||
|
m.Register(func(db dbx.Builder) error {
|
||||||
|
dao := daos.New(db);
|
||||||
|
|
||||||
|
collection, err := dao.FindCollectionByNameOrId("_pb_users_auth_")
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
// update
|
||||||
|
edit_user_data := &schema.SchemaField{}
|
||||||
|
json.Unmarshal([]byte(`{
|
||||||
|
"system": false,
|
||||||
|
"id": "xvw8arlm",
|
||||||
|
"name": "user_data",
|
||||||
|
"type": "relation",
|
||||||
|
"required": false,
|
||||||
|
"unique": false,
|
||||||
|
"options": {
|
||||||
|
"collectionId": "3qwwkz4wb0lyi78",
|
||||||
|
"cascadeDelete": false,
|
||||||
|
"minSelect": null,
|
||||||
|
"maxSelect": 1,
|
||||||
|
"displayFields": []
|
||||||
|
}
|
||||||
|
}`), edit_user_data)
|
||||||
|
collection.Schema.AddField(edit_user_data)
|
||||||
|
|
||||||
|
return dao.SaveCollection(collection)
|
||||||
|
}, func(db dbx.Builder) error {
|
||||||
|
dao := daos.New(db);
|
||||||
|
|
||||||
|
collection, err := dao.FindCollectionByNameOrId("_pb_users_auth_")
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
// update
|
||||||
|
edit_user_data := &schema.SchemaField{}
|
||||||
|
json.Unmarshal([]byte(`{
|
||||||
|
"system": false,
|
||||||
|
"id": "xvw8arlm",
|
||||||
|
"name": "device_data",
|
||||||
|
"type": "relation",
|
||||||
|
"required": false,
|
||||||
|
"unique": false,
|
||||||
|
"options": {
|
||||||
|
"collectionId": "3qwwkz4wb0lyi78",
|
||||||
|
"cascadeDelete": false,
|
||||||
|
"minSelect": null,
|
||||||
|
"maxSelect": 1,
|
||||||
|
"displayFields": []
|
||||||
|
}
|
||||||
|
}`), edit_user_data)
|
||||||
|
collection.Schema.AddField(edit_user_data)
|
||||||
|
|
||||||
|
return dao.SaveCollection(collection)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,37 @@
|
||||||
|
package migrations
|
||||||
|
|
||||||
|
import (
|
||||||
|
"encoding/json"
|
||||||
|
|
||||||
|
"github.com/pocketbase/dbx"
|
||||||
|
"github.com/pocketbase/pocketbase/daos"
|
||||||
|
m "github.com/pocketbase/pocketbase/migrations"
|
||||||
|
)
|
||||||
|
|
||||||
|
func init() {
|
||||||
|
m.Register(func(db dbx.Builder) error {
|
||||||
|
dao := daos.New(db);
|
||||||
|
|
||||||
|
collection, err := dao.FindCollectionByNameOrId("_pb_users_auth_")
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
json.Unmarshal([]byte(`[
|
||||||
|
"CREATE INDEX ` + "`" + `idx_FDKjrjp` + "`" + ` ON ` + "`" + `Users` + "`" + ` (` + "`" + `user_data` + "`" + `)"
|
||||||
|
]`), &collection.Indexes)
|
||||||
|
|
||||||
|
return dao.SaveCollection(collection)
|
||||||
|
}, func(db dbx.Builder) error {
|
||||||
|
dao := daos.New(db);
|
||||||
|
|
||||||
|
collection, err := dao.FindCollectionByNameOrId("_pb_users_auth_")
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
json.Unmarshal([]byte(`[]`), &collection.Indexes)
|
||||||
|
|
||||||
|
return dao.SaveCollection(collection)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,37 @@
|
||||||
|
package migrations
|
||||||
|
|
||||||
|
import (
|
||||||
|
"encoding/json"
|
||||||
|
|
||||||
|
"github.com/pocketbase/dbx"
|
||||||
|
"github.com/pocketbase/pocketbase/daos"
|
||||||
|
m "github.com/pocketbase/pocketbase/migrations"
|
||||||
|
)
|
||||||
|
|
||||||
|
func init() {
|
||||||
|
m.Register(func(db dbx.Builder) error {
|
||||||
|
dao := daos.New(db);
|
||||||
|
|
||||||
|
collection, err := dao.FindCollectionByNameOrId("_pb_users_auth_")
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
json.Unmarshal([]byte(`[]`), &collection.Indexes)
|
||||||
|
|
||||||
|
return dao.SaveCollection(collection)
|
||||||
|
}, func(db dbx.Builder) error {
|
||||||
|
dao := daos.New(db);
|
||||||
|
|
||||||
|
collection, err := dao.FindCollectionByNameOrId("_pb_users_auth_")
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
json.Unmarshal([]byte(`[
|
||||||
|
"CREATE INDEX ` + "`" + `idx_FDKjrjp` + "`" + ` ON ` + "`" + `Users` + "`" + ` (` + "`" + `user_data` + "`" + `)"
|
||||||
|
]`), &collection.Indexes)
|
||||||
|
|
||||||
|
return dao.SaveCollection(collection)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
@ -18,22 +18,22 @@ func init() {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
// add
|
// update
|
||||||
new_block_id := &schema.SchemaField{}
|
edit_block_id := &schema.SchemaField{}
|
||||||
json.Unmarshal([]byte(`{
|
json.Unmarshal([]byte(`{
|
||||||
"system": false,
|
"system": false,
|
||||||
"id": "vvqemti1",
|
"id": "80tmi6fm",
|
||||||
"name": "block_id",
|
"name": "block_id",
|
||||||
"type": "text",
|
"type": "text",
|
||||||
"required": true,
|
"required": false,
|
||||||
"unique": false,
|
"unique": false,
|
||||||
"options": {
|
"options": {
|
||||||
"min": null,
|
"min": null,
|
||||||
"max": null,
|
"max": null,
|
||||||
"pattern": ""
|
"pattern": ""
|
||||||
}
|
}
|
||||||
}`), new_block_id)
|
}`), edit_block_id)
|
||||||
collection.Schema.AddField(new_block_id)
|
collection.Schema.AddField(edit_block_id)
|
||||||
|
|
||||||
return dao.SaveCollection(collection)
|
return dao.SaveCollection(collection)
|
||||||
}, func(db dbx.Builder) error {
|
}, func(db dbx.Builder) error {
|
||||||
|
|
@ -44,8 +44,22 @@ func init() {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
// remove
|
// update
|
||||||
collection.Schema.RemoveField("vvqemti1")
|
edit_block_id := &schema.SchemaField{}
|
||||||
|
json.Unmarshal([]byte(`{
|
||||||
|
"system": false,
|
||||||
|
"id": "80tmi6fm",
|
||||||
|
"name": "block_id",
|
||||||
|
"type": "text",
|
||||||
|
"required": true,
|
||||||
|
"unique": false,
|
||||||
|
"options": {
|
||||||
|
"min": null,
|
||||||
|
"max": null,
|
||||||
|
"pattern": ""
|
||||||
|
}
|
||||||
|
}`), edit_block_id)
|
||||||
|
collection.Schema.AddField(edit_block_id)
|
||||||
|
|
||||||
return dao.SaveCollection(collection)
|
return dao.SaveCollection(collection)
|
||||||
})
|
})
|
||||||
|
|
@ -0,0 +1,58 @@
|
||||||
|
package migrations
|
||||||
|
|
||||||
|
import (
|
||||||
|
"encoding/json"
|
||||||
|
|
||||||
|
"github.com/pocketbase/dbx"
|
||||||
|
"github.com/pocketbase/pocketbase/daos"
|
||||||
|
m "github.com/pocketbase/pocketbase/migrations"
|
||||||
|
"github.com/pocketbase/pocketbase/models/schema"
|
||||||
|
)
|
||||||
|
|
||||||
|
func init() {
|
||||||
|
m.Register(func(db dbx.Builder) error {
|
||||||
|
dao := daos.New(db);
|
||||||
|
|
||||||
|
collection, err := dao.FindCollectionByNameOrId("3qwwkz4wb0lyi78")
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
// update
|
||||||
|
edit_data := &schema.SchemaField{}
|
||||||
|
json.Unmarshal([]byte(`{
|
||||||
|
"system": false,
|
||||||
|
"id": "mkzyfsng",
|
||||||
|
"name": "data",
|
||||||
|
"type": "json",
|
||||||
|
"required": false,
|
||||||
|
"unique": false,
|
||||||
|
"options": {}
|
||||||
|
}`), edit_data)
|
||||||
|
collection.Schema.AddField(edit_data)
|
||||||
|
|
||||||
|
return dao.SaveCollection(collection)
|
||||||
|
}, func(db dbx.Builder) error {
|
||||||
|
dao := daos.New(db);
|
||||||
|
|
||||||
|
collection, err := dao.FindCollectionByNameOrId("3qwwkz4wb0lyi78")
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
// update
|
||||||
|
edit_data := &schema.SchemaField{}
|
||||||
|
json.Unmarshal([]byte(`{
|
||||||
|
"system": false,
|
||||||
|
"id": "mkzyfsng",
|
||||||
|
"name": "data",
|
||||||
|
"type": "json",
|
||||||
|
"required": true,
|
||||||
|
"unique": false,
|
||||||
|
"options": {}
|
||||||
|
}`), edit_data)
|
||||||
|
collection.Schema.AddField(edit_data)
|
||||||
|
|
||||||
|
return dao.SaveCollection(collection)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,39 @@
|
||||||
|
package migrations
|
||||||
|
|
||||||
|
import (
|
||||||
|
"encoding/json"
|
||||||
|
|
||||||
|
"github.com/pocketbase/dbx"
|
||||||
|
"github.com/pocketbase/pocketbase/daos"
|
||||||
|
m "github.com/pocketbase/pocketbase/migrations"
|
||||||
|
)
|
||||||
|
|
||||||
|
func init() {
|
||||||
|
m.Register(func(db dbx.Builder) error {
|
||||||
|
dao := daos.New(db);
|
||||||
|
|
||||||
|
collection, err := dao.FindCollectionByNameOrId("3qwwkz4wb0lyi78")
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
json.Unmarshal([]byte(`[
|
||||||
|
"CREATE INDEX ` + "`" + `idx_aYVfg1q` + "`" + ` ON ` + "`" + `DataBlock` + "`" + ` (` + "`" + `block_id` + "`" + `)"
|
||||||
|
]`), &collection.Indexes)
|
||||||
|
|
||||||
|
return dao.SaveCollection(collection)
|
||||||
|
}, func(db dbx.Builder) error {
|
||||||
|
dao := daos.New(db);
|
||||||
|
|
||||||
|
collection, err := dao.FindCollectionByNameOrId("3qwwkz4wb0lyi78")
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
json.Unmarshal([]byte(`[
|
||||||
|
"CREATE UNIQUE INDEX ` + "`" + `idx_aYVfg1q` + "`" + ` ON ` + "`" + `DataBlock` + "`" + ` (` + "`" + `block_id` + "`" + `)"
|
||||||
|
]`), &collection.Indexes)
|
||||||
|
|
||||||
|
return dao.SaveCollection(collection)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,72 @@
|
||||||
|
package migrations
|
||||||
|
|
||||||
|
import (
|
||||||
|
"encoding/json"
|
||||||
|
|
||||||
|
"github.com/pocketbase/dbx"
|
||||||
|
"github.com/pocketbase/pocketbase/daos"
|
||||||
|
m "github.com/pocketbase/pocketbase/migrations"
|
||||||
|
"github.com/pocketbase/pocketbase/models/schema"
|
||||||
|
)
|
||||||
|
|
||||||
|
func init() {
|
||||||
|
m.Register(func(db dbx.Builder) error {
|
||||||
|
dao := daos.New(db);
|
||||||
|
|
||||||
|
collection, err := dao.FindCollectionByNameOrId("_pb_users_auth_")
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
// update
|
||||||
|
edit_user_data := &schema.SchemaField{}
|
||||||
|
json.Unmarshal([]byte(`{
|
||||||
|
"system": false,
|
||||||
|
"id": "xvw8arlm",
|
||||||
|
"name": "user_data",
|
||||||
|
"type": "relation",
|
||||||
|
"required": false,
|
||||||
|
"unique": false,
|
||||||
|
"options": {
|
||||||
|
"collectionId": "3qwwkz4wb0lyi78",
|
||||||
|
"cascadeDelete": false,
|
||||||
|
"minSelect": null,
|
||||||
|
"maxSelect": 1,
|
||||||
|
"displayFields": [
|
||||||
|
"data"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}`), edit_user_data)
|
||||||
|
collection.Schema.AddField(edit_user_data)
|
||||||
|
|
||||||
|
return dao.SaveCollection(collection)
|
||||||
|
}, func(db dbx.Builder) error {
|
||||||
|
dao := daos.New(db);
|
||||||
|
|
||||||
|
collection, err := dao.FindCollectionByNameOrId("_pb_users_auth_")
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
// update
|
||||||
|
edit_user_data := &schema.SchemaField{}
|
||||||
|
json.Unmarshal([]byte(`{
|
||||||
|
"system": false,
|
||||||
|
"id": "xvw8arlm",
|
||||||
|
"name": "user_data",
|
||||||
|
"type": "relation",
|
||||||
|
"required": false,
|
||||||
|
"unique": false,
|
||||||
|
"options": {
|
||||||
|
"collectionId": "3qwwkz4wb0lyi78",
|
||||||
|
"cascadeDelete": false,
|
||||||
|
"minSelect": null,
|
||||||
|
"maxSelect": 1,
|
||||||
|
"displayFields": []
|
||||||
|
}
|
||||||
|
}`), edit_user_data)
|
||||||
|
collection.Schema.AddField(edit_user_data)
|
||||||
|
|
||||||
|
return dao.SaveCollection(collection)
|
||||||
|
})
|
||||||
|
}
|
||||||
Loading…
Reference in New Issue