Skip to content

Commit

Permalink
feat: add Vue composable package and introduced a vue-supabase-todo p…
Browse files Browse the repository at this point in the history
…roject (#111)

Co-authored-by: Christiaan Landman <[email protected]>
  • Loading branch information
Chriztiaan and Christiaan Landman authored Apr 16, 2024
1 parent 028ad70 commit ad94b59
Show file tree
Hide file tree
Showing 59 changed files with 2,976 additions and 39 deletions.
3 changes: 2 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -39,9 +39,10 @@ _Bad connectivity is everywhere, and we're tired of it. PowerSync is on a missio

Demo applications are located in the [`demos/`](./demos/) directory. Also see our [Demo Apps / Example Projects](https://docs.powersync.com/resources/demo-apps-example-projects) gallery which lists all projects by the backend and client-side framework they use.

- [demos/react-supabase-todolist](./demos/react-supabase-todolist/): A React to-do list example app using the PowerSync Web SDK and a Supabase backend.
- [demos/react-supabase-todolist](./demos/react-supabase-todolist/README.md): A React to-do list example app using the PowerSync Web SDK and a Supabase backend.
- [demos/yjs-react-supabase-text-collab](./demos/yjs-react-supabase-text-collab/README.md): A React real-time text editing collaboration example app powered by [Yjs](https://github.com/yjs/yjs) CRDTs and [Tiptap](https://tiptap.dev/), using the PowerSync Web SDK and a Supabase backend.
- [demos/react-native-supabase-todolist](./demos/react-native-supabase-todolist): A React Native to-do list example app using a Supabase backend.
- [demos/vue-supabase-todolist](./demos/vue-supabase-todolist/README.md): A Vue to-do list example app using the PowerSync Web SDK and a Supabase backend.
- [demos/angular-supabase-todolist](./demos/angular-supabase-todolist/README.md) An Angular to-do list example app using the PowerSync Web SDK and a Supabase backend.
- [demos/example-webpack](./demos/example-webpack/README.md): A minimal example demonstrating bundling with Webpack.
- [demos/example-vite](./demos/example-vite/README.md): A minimal example demonstrating bundling with Vite.
Expand Down
5 changes: 5 additions & 0 deletions demos/vue-supabase-todolist/.env.local.template
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
# Copy this template: `cp .env.local.template .env.local`
# Edit .env.local and enter your Supabase and PowerSync project details.
VITE_SUPABASE_URL=https://foo.supabase.co
VITE_SUPABASE_ANON_KEY=foo
VITE_POWERSYNC_URL=https://foo.powersync.journeyapps.com
27 changes: 27 additions & 0 deletions demos/vue-supabase-todolist/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
# Logs
logs
*.log
npm-debug.log*
yarn-debug.log*
yarn-error.log*
pnpm-debug.log*
lerna-debug.log*

node_modules
dist
dist-ssr
*.local

# Generated vue declaration files
components.d.ts

# Editor directories and files
.vscode/*
!.vscode/extensions.json
.idea
.DS_Store
*.suo
*.ntvs*
*.njsproj
*.sln
*.sw?
64 changes: 64 additions & 0 deletions demos/vue-supabase-todolist/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
# PowerSync + Supabase Vue Demo: Todo List (TypeScript)

## Note: Alpha Release

This package is currently in an alpha release.

## Overview

Demo app demonstrating use of the [PowerSync Vue](https://www.npmjs.com/package/@journeyapps/powersync-vue) together with Supabase.

A step-by-step guide through the Supabase<>PowerSync integration is available [here](https://docs.powersync.com/integration-guides/supabase).

## Recommended Setup

- [VS Code](https://code.visualstudio.com/) + [Vue - Official](https://marketplace.visualstudio.com/items?itemName=Vue.volar) (previously Volar) and disable Vetur

- Use [vue-tsc](https://github.com/vuejs/language-tools/tree/master/packages/tsc) for performing the same type checking from the command line, or for generating d.ts files for SFCs.

## Getting Started

In the repo directory, use [pnpm](https://pnpm.io/installation) to install dependencies:

```bash
pnpm install
pnpm build:packages
```

Then switch into the demo's directory:

```bash
cd demos/vue-supabase-todolist
```

Set up the Environment variables: Copy the `.env.local.template` file:

```bash
cp .env.local.template .env.local
```

And then edit `.env.local` to insert your credentials for Supabase and PowerSync.

Run the development server:

```bash
pnpm dev
```

Open [http://localhost:5173](http://localhost:5173) with your browser to see the result.

## Progressive Web App (PWA)

This demo is PWA compatible, and works fully offline. PWA is not available in development (watch) mode. The manifest and service worker is built using [vite-plugin-pwa](https://vite-pwa-org.netlify.app/).

Build the production codebase:

```bash
pnpm build
```

## Learn More

Check out [PowerSync Vue on GitHub](https://github.com/powersync-ja/powersync-js/tree/main/packages/powersync-vue) - your feedback and contributions are welcome!

To learn more about PowerSync, see the [PowerSync docs](https://docs.powersync.com).
13 changes: 13 additions & 0 deletions demos/vue-supabase-todolist/index.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<link rel="icon" type="image/svg+xml" href="/favicon.ico" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Vite + Vue + TS</title>
</head>
<body>
<div id="app"></div>
<script type="module" src="/src/main.ts"></script>
</body>
</html>
36 changes: 36 additions & 0 deletions demos/vue-supabase-todolist/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
{
"name": "vue-supabase-todolist",
"private": true,
"version": "0.0.0",
"type": "module",
"scripts": {
"dev": "vue-tsc --noEmit --watch & vite dev",
"build": "vue-tsc && vite build",
"preview": "vite preview",
"type-check": "vue-tsc --noEmit"
},
"dependencies": {
"@journeyapps/powersync-sdk-web": "workspace:*",
"@journeyapps/powersync-vue": "workspace:*",
"@mdi/font": "7.4.47",
"@supabase/supabase-js": "^2.39.7",
"@vuelidate/core": "^2.0.3",
"@vuelidate/validators": "^2.0.4",
"js-logger": "^1.6.1",
"uuid": "^9.0.1",
"vue": "^3.4.21",
"vue-router": "4",
"vuetify": "^3.5.7"
},
"devDependencies": {
"@types/vuelidate": "^0.7.21",
"@vitejs/plugin-vue": "^5.0.4",
"sass": "^1.71.1",
"typescript": "^5.2.2",
"unplugin-fonts": "^1.1.1",
"unplugin-vue-components": "^0.26.0",
"vite": "^5.2.0",
"vite-plugin-vuetify": "^2.0.3",
"vue-tsc": "^2.0.6"
}
}
Binary file added demos/vue-supabase-todolist/public/favicon.ico
Binary file not shown.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added demos/vue-supabase-todolist/public/icons/icon.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
1 change: 1 addition & 0 deletions demos/vue-supabase-todolist/public/vite.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
28 changes: 28 additions & 0 deletions demos/vue-supabase-todolist/src/App.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
<script setup lang="ts">
import Logger from 'js-logger';
import { powerSync } from '@/plugins/powerSync';
import { supabase } from '@/plugins/supabase';
Logger.useDefaults();
Logger.setLevel(Logger.DEBUG);
// For console testing purposes
(window as any)._powersync = powerSync;
powerSync.init();
supabase.registerListener({
sessionStarted: () => {
powerSync.connect(supabase);
}
});
supabase.init();
</script>

<template>
<v-app dark>
<v-main class="bg-black" style="width: 100vw">
<router-view />
</v-main>
</v-app>
</template>
1 change: 1 addition & 0 deletions demos/vue-supabase-todolist/src/assets/powersync-logo.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
1 change: 1 addition & 0 deletions demos/vue-supabase-todolist/src/assets/vue.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
5 changes: 5 additions & 0 deletions demos/vue-supabase-todolist/src/components/ErrorMessage.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
<template>
<v-alert type="error" border="start" elevation="2" class="mt-4">
<slot />
</v-alert>
</template>
50 changes: 50 additions & 0 deletions demos/vue-supabase-todolist/src/components/LoadingMessage.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
<template>
<div
v-if="showLoadingMessage"
class="mt-0 mb-6 d-flex align-center justify-center"
style="position: absolute; top: 68px; left: 0%; right: 0; margin: auto; z-index: 100; width: 350px"
>
<v-progress-circular class="mr-4" indeterminate color="primary" />

<div v-if="!status.hasSynced">Busy with initial sync...</div>
<v-tooltip v-else :text="loadingMessage">
<template v-slot:activator="{ props }"> <v-icon v-bind="props">mdi-information</v-icon> </template>
</v-tooltip>
</div>
</template>

<script setup lang="ts">
import { usePowerSyncStatus } from '@journeyapps/powersync-vue';
import { ref } from 'vue';
import { watchEffect } from 'vue';
import { computed } from 'vue';
const { status } = usePowerSyncStatus();
const props = defineProps({
loading: Boolean,
fetching: Boolean
});
let dispose: (() => void) | undefined = undefined;
const showLoadingMessage = ref(false);
watchEffect(() => {
if (props.fetching || props.loading || !status.value.hasSynced) {
if (!dispose) {
const timeout = setTimeout(() => {
showLoadingMessage.value = true;
}, 100);
dispose = () => clearTimeout(timeout);
}
} else {
dispose?.();
dispose = undefined;
showLoadingMessage.value = false;
}
});
const loadingMessage = computed(() => (props.loading ? 'Loading' : 'Re-executing query'));
</script>
11 changes: 11 additions & 0 deletions demos/vue-supabase-todolist/src/components/buttons/Fab.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
<template>
<v-fab class="fab mr-4" size="large" color="white" icon="mdi-plus" @click="$emit('click')" />
</template>

<style scoped>
.fab {
bottom: 50px;
right: 10px;
position: fixed;
}
</style>
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
<template>
<v-list-item
rounded
class="bg-surface text-left"
style="margin-bottom: 10px"
:subtitle="props.description"
:title="props.title"
@click="emit('press')"
>
<template v-slot:prepend>
<v-avatar color="surface-variant">
<v-icon color="black" icon="mdi-list-box-outline" />
</v-avatar>
</template>

<template v-slot:append>
<v-btn variant="text" icon="mdi-delete-outline" @click.stop="emit('delete')" />
<v-btn variant="text" icon="mdi-arrow-right" @click.stop="emit('press')" />
</template>
</v-list-item>
</template>

<script setup lang="ts">
const props = defineProps({
title: String,
description: String
});
const emit = defineEmits<{
delete: [];
press: [];
}>();
</script>

<style scoped>
.main-paper {
margin-bottom: 10px;
}
</style>
Loading

0 comments on commit ad94b59

Please sign in to comment.