digitallyinduced / thin-backend

🔥 Thin Backend is a Blazing Fast, Universal Web App Backend for Making Realtime Single Page Apps
https://thin.dev/
MIT License
1.24k stars 32 forks source link

Vuejs support #32

Closed ilya-buligin closed 2 years ago

ilya-buligin commented 2 years ago

Hi! Is there any plan to provide Vue.js support? Vue has a perfect reactivity system based on the same concepts as Thin.

mpscholten commented 2 years ago

This should be easily possible 👍 We already have integrations for Svelte and ReScript as well

mpscholten commented 2 years ago

I've been working on a draft of the vue support locally.

Here's a bit of code if you already want to play with it.

First we need to call init from the App.vue:

<script setup lang="ts">
import HelloWorld from './components/HelloWorld.vue'
import TheWelcome from './components/TheWelcome.vue'

// Add this:
import { initThinBackend, ensureIsUser } from 'thin-backend';

initThinBackend({
  host: 'https://testus.thinbackend.app' // <- replace this with your project url
});
ensureIsUser();
</script>

Next create a file useQuery.ts somewhere in the project with this:

import { DataSubscription, QueryBuilder, type TableName } from 'thin-backend';
import { onMounted, onUnmounted, ref, type Ref } from 'vue';

export default function useQuery<table extends TableName, result>(queryBuilder: QueryBuilder<table, result>): Ref<Array<result> | null> {
  const records = ref(null);
  let dataSubscription = null;

  onMounted(() => {
    dataSubscription = new DataSubscription(queryBuilder.query);
    dataSubscription.createOnServer();

    let unsubscribeCallback = dataSubscription.subscribe(updatedRecords => {
      records.value = updatedRecords;
    });

    onUnmounted(unsubscribeCallback);
  });

  return records;
}

Now we already build things with Thin. E.g. here's a simple todo app with vue:

<script setup lang="ts">
import { createRecord, query, updateRecord, type Task } from 'thin-backend';
import useQuery from './../useQuery';

const tasks = useQuery(query('tasks').orderBy('createdAt'));

function updateTask(task: Task) {
  updateRecord('tasks', task.id, { title: window.prompt('New title') || '' })
}

function addTask() {
  createRecord('tasks', {
    title: window.prompt('Title:') || ''
  });
}
</script>

<template>
  <div v-for="task in tasks" v-on:dblclick="updateTask(task)">
    {{task.title}}
  </div>

  <button v-on:click="addTask()">Add Task</button>
</template>

<style scoped>
</style>

Maybe you can give it a try and let me know how it goes :) If everything is alright we can likely move the useQuery helper into it's own thin-backend/vue package.

mpscholten commented 2 years ago

I've just published the thin-backend-vue package to npm 🎉

You can find basic documentation here https://github.com/digitallyinduced/thin-backend/tree/master/vue 👍

I'll add more detailed docs to the Thin documentation soon.