Skip to content

Commit

Permalink
Merge pull request #83 from powersync-ja/todolist-demo-vite
Browse files Browse the repository at this point in the history
Switch from NextJS -> Vite for demos
  • Loading branch information
rkistner authored Mar 11, 2024
2 parents aede9e7 + 1aed928 commit be8d8d8
Show file tree
Hide file tree
Showing 123 changed files with 2,755 additions and 1,709 deletions.
7 changes: 7 additions & 0 deletions .changeset/fair-flowers-type.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
---
"@journeyapps/powersync-sdk-react-native": minor
"@journeyapps/powersync-sdk-common": minor
"@journeyapps/powersync-sdk-web": minor
---

Fix PowerSyncBackendConnector.fetchCredentials type to allow returning null
5 changes: 3 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -39,12 +39,13 @@ _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/nextjs-supabase-todolist](./demos/nextjs-supabase-todolist/): A Next.js to-do list example app using the PowerSync Web SDK and a Supabase backend.
- [demos/yjs-nextjs-supabase-text-collab](./demos/yjs-nextjs-supabase-text-collab/README.md): A Next.js 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-supabase-todolist](./demos/react-supabase-todolist/): 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/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.
- [demos/example-nextjs](./demos/example-nextjs/README.md): An example demonstrating setup with Next.js.

# Development

Expand Down
4 changes: 4 additions & 0 deletions demos/example-nextjs/.env.local.template
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
# Copy to .env.local, and complete these variables.
# Leave blank to test local-only.
NEXT_PUBLIC_POWERSYNC_URL=
NEXT_PUBLIC_POWERSYNC_TOKEN=
File renamed without changes.
File renamed without changes.
File renamed without changes.
10 changes: 10 additions & 0 deletions demos/example-nextjs/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
# PowerSync Next.js example

This example is built using [Next.js](https://nextjs.org/) and the [PowerSync JS web SDK](https://docs.powersync.com/client-sdk-references/js-web).

To see it in action:

1. Make sure to run `pnpm build:packages` in the root directory of this Git repo.
2. Copy `.env.local.template` to `.env.local`, and complete the environment variables. You can generate a [temporary development token](https://docs.powersync.com/usage/installation/authentication-setup/development-tokens), or leave blank to test with local-only data.
3. `pnpm start`
4. Open the localhost URL in the browser displayed in the terminal output.
File renamed without changes.
56 changes: 56 additions & 0 deletions demos/example-nextjs/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
{
"name": "@journeyapps/powersync-example-nextjs",
"version": "0.0.1",
"private": true,
"scripts": {
"build": "next build",
"clean": "rm -rf .next",
"watch": "next dev",
"start": "next start",
"lint": "next lint"
},
"dependencies": {
"@emotion/react": "^11.11.4",
"@emotion/styled": "^11.11.0",
"@fontsource/roboto": "^5.0.12",
"@journeyapps/powersync-react": "workspace:*",
"@journeyapps/powersync-sdk-web": "workspace:*",
"@journeyapps/wa-sqlite": "~0.1.1",
"@lexical/react": "^0.11.3",
"@mui/icons-material": "^5.15.12",
"@mui/material": "^5.15.12",
"fast-glob": "^3.3.2",
"formik": "^2.4.5",
"highlight.js": "^11.9.0",
"js-logger": "^1.6.1",
"lato-font": "^3.0.0",
"lexical": "^0.11.3",
"lodash": "^4.17.21",
"lowlight": "^2.9.0",
"next": "14.1.0",
"next-images": "1.8.5",
"react": "^18.2.0",
"react-dom": "^18.2.0",
"remixicon": "^2.5.0",
"shiki": "^0.10.1",
"simplify-js": "^1.2.4",
"uuid": "9.0.1"
},
"devDependencies": {
"@types/lodash": "^4.14.202",
"@types/node": "^20.11.25",
"@types/react": "^18.2.64",
"@types/react-dom": "^18.2.21",
"@types/uuid": "9.0.8",
"autoprefixer": "^10.4.18",
"babel-loader": "^9.1.3",
"css-loader": "^6.10.0",
"eslint": "^8.57.0",
"eslint-config-next": "14.0.0",
"postcss": "^8.4.35",
"sass": "^1.71.1",
"sass-loader": "^13.3.3",
"style-loader": "^3.3.4",
"tailwindcss": "^3.4.1"
}
}
File renamed without changes.
File renamed without changes.
File renamed without changes.
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@
import React from 'react';
import { CssBaseline } from '@mui/material';

import { ThemeProviderContainer } from '@/components/providers/ThemeProviderContainer';
import { DynamicSystemProvider } from '@/components/providers/DynamicSystemProvider';

import './globals.scss';
Expand All @@ -13,13 +12,11 @@ export default function RootLayout({ children }: { children: React.ReactNode })
return (
<html lang="en">
<head>
<title>PowerSync Yjs CRDT Text Collaboration Demo</title>
<title>PowerSync Next.js Example</title>
</head>
<body>
<CssBaseline />
<ThemeProviderContainer>
<DynamicSystemProvider>{children}</DynamicSystemProvider>
</ThemeProviderContainer>
<DynamicSystemProvider>{children}</DynamicSystemProvider>
</body>
</html>
);
Expand Down
49 changes: 49 additions & 0 deletions demos/example-nextjs/src/app/page.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
'use client';

import React, { useEffect } from 'react';
import { CircularProgress, Grid, ListItem, styled } from '@mui/material';
import { useRouter } from 'next/navigation';
import { usePowerSync, usePowerSyncWatchedQuery } from '@journeyapps/powersync-react';

export default function EntryPage() {
const router = useRouter();
const db = usePowerSync();
const customers = usePowerSyncWatchedQuery('SELECT id, name FROM customers');

useEffect(() => {
// Insert some test data
const names = ['Fred', 'Willard', 'Tina', 'Jake', 'Corey'];
const name = names[Math.floor(Math.random() * names.length)];
db.execute('INSERT INTO customers(id, name) VALUES(uuid(), ?)', [name]);
return () => { };
}, []);

return (
<S.MainGrid container>
<S.CenteredGrid item xs={12} md={6} lg={5}>
<div>
<h1>Customers</h1>
{
customers.map(c =>
<ListItem key={c.id}>{c.name}</ListItem>
)
}
{customers.length == 0 ? <CircularProgress /> : []}

</div>
</S.CenteredGrid>
</S.MainGrid>
);
}

namespace S {
export const CenteredGrid = styled(Grid)`
display: flex;
justify-content: center;
align-items: center;
`;

export const MainGrid = styled(CenteredGrid)`
min-height: 100vh;
`;
}
35 changes: 35 additions & 0 deletions demos/example-nextjs/src/components/providers/SystemProvider.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
'use client';

import { AppSchema } from '@/library/powersync/AppSchema';
import { BackendConnector } from '@/library/powersync/BackendConnector';
import { PowerSyncContext } from '@journeyapps/powersync-react';
import { WASQLitePowerSyncDatabaseOpenFactory } from '@journeyapps/powersync-sdk-web';
import { CircularProgress } from '@mui/material';
import Logger from 'js-logger';
import React, { Suspense } from 'react';

Logger.useDefaults();
Logger.setLevel(Logger.DEBUG);

const powerSync = new WASQLitePowerSyncDatabaseOpenFactory({
dbFilename: 'powersync2.db',
schema: AppSchema,
flags: {
disableSSRWarning: true
}
}).getInstance()
const connector = new BackendConnector();

powerSync.connect(connector);

export const SystemProvider = ({ children }: { children: React.ReactNode }) => {
return (
<Suspense fallback={<CircularProgress />}>
<PowerSyncContext.Provider value={powerSync}>
{children}
</PowerSyncContext.Provider>
</Suspense>
);
};

export default SystemProvider;
13 changes: 13 additions & 0 deletions demos/example-nextjs/src/library/powersync/AppSchema.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
import { column, Schema, TableV2 } from '@journeyapps/powersync-sdk-web';

const customers = new TableV2({
name: column.text,
created_at: column.text
});

export const AppSchema = new Schema({
customers
});

export type Database = (typeof AppSchema)['types'];
export type Customer = Database['customers'];
59 changes: 59 additions & 0 deletions demos/example-nextjs/src/library/powersync/BackendConnector.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
import { AbstractPowerSyncDatabase, BaseObserver, PowerSyncBackendConnector } from '@journeyapps/powersync-sdk-web';

export class BackendConnector implements PowerSyncBackendConnector {
private powersyncUrl: string | undefined;
private powersyncToken: string | undefined;

constructor() {
this.powersyncUrl = process.env.NEXT_PUBLIC_POWERSYNC_URL;
// This token is for development only.
// For production applications, integrate with an auth provider or custom auth.
this.powersyncToken = process.env.NEXT_PUBLIC_POWERSYNC_TOKEN;
}

async fetchCredentials() {
// TODO: Use an authentication service or custom implementation here.

if (this.powersyncToken == null || this.powersyncUrl == null) {
return null;
}

return {
endpoint: this.powersyncUrl,
token: this.powersyncToken
};
}

async uploadData(database: AbstractPowerSyncDatabase): Promise<void> {
const transaction = await database.getNextCrudTransaction();

if (!transaction) {
return;
}

try {
// TODO: Upload here

await transaction.complete();
} catch (error: any) {
if (shouldDiscardDataOnError(error)) {
// Instead of blocking the queue with these errors, discard the (rest of the) transaction.
//
// Note that these errors typically indicate a bug in the application.
// If protecting against data loss is important, save the failing records
// elsewhere instead of discarding, and/or notify the user.
console.error(`Data upload error - discarding`, error);
await transaction.complete();
} else {
// Error may be retryable - e.g. network error or temporary server error.
// Throwing an error here causes this call to be retried after a delay.
throw error;
}
}
}
}

function shouldDiscardDataOnError(error: any) {
// TODO: Ignore non-retryable errors here
return false;
}
File renamed without changes.
Original file line number Diff line number Diff line change
Expand Up @@ -23,10 +23,5 @@
}
},
"include": ["next-env.d.ts", "**/*.ts", "**/*.tsx", ".next/types/**/*.ts"],
"exclude": ["node_modules"],
"references": [
{
"path": "../../packages/powersync-sdk-web"
}
]
"exclude": ["node_modules"]
}
4 changes: 3 additions & 1 deletion demos/example-vite/vite.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,10 @@ export default defineConfig({
outDir: '../dist',
rollupOptions: {
input: 'src/index.html'
}
},
emptyOutDir: true
},
envDir: '..', // Use this dir for env vars, not 'src'.
optimizeDeps: {
// Don't optimize these packages as they contain web workers and WASM files.
// https://github.com/vitejs/vite/issues/11672#issuecomment-1415820673
Expand Down
6 changes: 1 addition & 5 deletions demos/example-webpack/src/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -15,11 +15,7 @@ let PowerSync;
const openDatabase = async () => {
PowerSync = new WASQLitePowerSyncDatabaseOpenFactory({
schema: AppSchema,
dbFilename: 'test.sqlite',
flags: {
// This is disabled once CSR+SSR functionality is verified to be working correctly
disableSSRWarning: true
}
dbFilename: 'test.sqlite'
}).getInstance();

await PowerSync.init();
Expand Down
74 changes: 0 additions & 74 deletions demos/nextjs-supabase-todolist/README.md

This file was deleted.

Loading

0 comments on commit be8d8d8

Please sign in to comment.