diff --git a/CHANGELOG.md b/CHANGELOG.md index a49ea20..34992b0 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,9 @@ # PowerSync Self Hosted Example +## v0.3.0 + +- Added a Django demo. Split code to make demos more modular + ## v0.2.0 - Updated to MongoDB v7 diff --git a/README.md b/README.md index 0edd798..137d2af 100644 --- a/README.md +++ b/README.md @@ -8,21 +8,21 @@ Learn more about self-hosting PowerSync [here](https://docs.powersync.com/self-h # Run -This repository contains a basic local configuration for Postgres. The entire stack can be started with a single command. +This repository contains basic demonstrations in the `demos` folder. -```bash -docker compose up -``` +- [NodeJS](./demos/nodejs/README.md) -## Demo app + - This can be stared from the repo root with `docker compose -f demos/nodejs/docker-compose.yaml up` -This compose file serves an example app at `localhost:3030`. This app syncs changes made from the Postgres server database. +- [Django](./demos/django/README.md) + + - This can be stared from the repo root with `docker compose -f demos/django/docker-compose.yaml up` # Config The configuration can be modified to match other project topologies. -Edit the `.env` file and config files in the `./config` directory with your specific settings. +Edit the demo `.env` files and config files in the `./config` directory with your specific settings. ### Connections @@ -46,8 +46,6 @@ The `key-generator` project demonstrates generating RSA key pairs for token sign # Cleanup -The `setup.sql` script only runs on the first initialization of the container. - If you want to start from a fresh start: - Delete the Docker volumes `mongo_storage` and `db_data` diff --git a/config/powersync.yaml b/config/powersync.yaml index 08b9eb2..64f5bb8 100644 --- a/config/powersync.yaml +++ b/config/powersync.yaml @@ -65,7 +65,7 @@ replication: storage: type: mongodb uri: !env PS_MONGO_URI - # Use these if authentication is required. The user should have `readWrite` and `dbAdmin` roles + # Use these if authentication is required. The user should have `readWrite` and `dbAdmin` roles # username: my-mongo-user # password: my-password diff --git a/demos/django/.env b/demos/django/.env new file mode 100644 index 0000000..928e22f --- /dev/null +++ b/demos/django/.env @@ -0,0 +1,20 @@ +# ==================== Postgres credentials ================================ +PG_DATABASE_NAME=django_demo +PG_DATABASE_PORT=5432 +PG_DATABASE_USER=postgres +PG_DATABASE_PASSWORD=mypassword + +# ==================== Demo config ========================================= +DEMO_BACKEND_PORT=6061 +# The front-end demo application is accessible at this port on the host machine +DEMO_CLIENT_PORT=3030 +PS_JWKS_URL=http://demo-backend:${DEMO_BACKEND_PORT}/api/get_keys/ + +# These can be generated by following the instructions in the `key-generator` folder +# A temporary key will be used if these are not specified +DEMO_JWKS_PUBLIC_KEY= +DEMO_JWKS_PRIVATE_KEY= + +# ==================== PowerSync variables ==================== +# The PowerSync API is accessible via this port +PS_PORT=8080 diff --git a/demos/django/README.md b/demos/django/README.md new file mode 100644 index 0000000..f3ddb42 --- /dev/null +++ b/demos/django/README.md @@ -0,0 +1,26 @@ +# Django Self Hosted Demo + +This demo contains a Django backend with no frontend client. This can be used in conjunction with our Django demos: + +- [React Native](https://github.com/powersync-ja/powersync-js/tree/main/demos/django-react-native-todolist) +- [Dart](https://github.com/powersync-ja/powersync.dart/tree/master/demos/django-todolist) + +Backend code can be found [here](https://github.com/powersync-ja/powersync-django-backend-todolist-demo) + +## Running + +This demo can be started by running the following in this demo directory + +```bash +docker compose up +``` + +or in the root directory run + +```bash +docker compose -f demos/django/docker-compose.yaml up +``` + +The backend will by default be available at `http://localhost:6061`. + +See the client demos above for starting a client. diff --git a/demos/django/docker-compose.yaml b/demos/django/docker-compose.yaml new file mode 100644 index 0000000..9f28cf0 --- /dev/null +++ b/demos/django/docker-compose.yaml @@ -0,0 +1,23 @@ +# Include syntax requires Docker compose > 2.20.3 +# https://docs.docker.com/compose/release-notes/#2203 +include: + # Creates a standard Postgress instance + - path: ../../services/postgres.yaml + + # Creates the internal MongoDB replica set + - path: ../../services/mongo.yaml + + # Demo Django backend server and front-end web client + - path: ./ps-django-backend.yaml + +services: + # Extend PowerSync with Mongo and Postgres healthchecks + powersync: + extends: + file: ../../services/powersync.yaml + service: powersync + depends_on: + mongo-rs-init: + condition: service_completed_successfully + pg-db: + condition: service_healthy diff --git a/demos/django/ps-django-backend.yaml b/demos/django/ps-django-backend.yaml new file mode 100644 index 0000000..380ee1d --- /dev/null +++ b/demos/django/ps-django-backend.yaml @@ -0,0 +1,28 @@ +services: + # A backend which provides basic authentication and CRUD access to the Postgres DB from the client + demo-backend: + depends_on: + pg-db: + condition: service_healthy + build: + context: https://github.com/powersync-ja/powersync-django-backend-todolist-demo.git + environment: + # From the Postgres service name in linked Docker Compose file + DATABASE_HOST: pg-db + # Shared environment variables for Postgres connection + DATABASE_PORT: ${PG_DATABASE_PORT} + DATABASE_NAME: ${PG_DATABASE_NAME} + DATABASE_USER: ${PG_DATABASE_USER} + DATABASE_PASSWORD: ${PG_DATABASE_PASSWORD} + + # From the PowerSync service name + # This is just used to populate the JWT audience + POWERSYNC_URL: powersync-dev + + # Keys here for demonstration + POWERSYNC_PUBLIC_KEY: ${DEMO_JWKS_PUBLIC_KEY} + POWERSYNC_PRIVATE_KEY: ${DEMO_JWKS_PRIVATE_KEY} + + DJANGO_PORT: ${DEMO_BACKEND_PORT} + ports: + - ${DEMO_BACKEND_PORT}:${DEMO_BACKEND_PORT} diff --git a/.env b/demos/nodejs/.env similarity index 91% rename from .env rename to demos/nodejs/.env index 91d7525..0987616 100644 --- a/.env +++ b/demos/nodejs/.env @@ -1,6 +1,6 @@ # ==================== Postgres credentials ================================ -PG_DATABASE_PORT=5432 PG_DATABASE_NAME=postgres +PG_DATABASE_PORT=5432 PG_DATABASE_USER=postgres PG_DATABASE_PASSWORD=mypassword @@ -8,6 +8,7 @@ PG_DATABASE_PASSWORD=mypassword DEMO_BACKEND_PORT=6060 # The front-end demo application is accessible at this port on the host machine DEMO_CLIENT_PORT=3030 +PS_JWKS_URL=http://demo-backend:${DEMO_BACKEND_PORT}/api/auth/keys # These can be generated by following the instructions in the `key-generator` folder # A temporary key will be used if these are not specified diff --git a/demos/nodejs/README.md b/demos/nodejs/README.md new file mode 100644 index 0000000..af66c9b --- /dev/null +++ b/demos/nodejs/README.md @@ -0,0 +1,25 @@ +# JavaScript Self Hosted Demo + +This demo contains a NodeJS backend and React frontend which are linked to a self hosted PowerSync instance. + +Backend code can be found [here](https://github.com/powersync-ja/powersync-nodejs-backend-todolist-demo) + +## Running + +This demo can be started by running the following in this demo directory + +```bash +docker compose up +``` + +or in the root directory run + +```bash +docker compose -f demos/nodejs/docker-compose.yaml up +``` + +The frontend can be accessed at `http://localhost:3030` in a browser. + +## Cleanup + +The `setup.sql` script only runs on the first initialization of the container. Delete the container and volumes if making changes. diff --git a/demo-app/.dockerignore b/demos/nodejs/demo-app/.dockerignore similarity index 100% rename from demo-app/.dockerignore rename to demos/nodejs/demo-app/.dockerignore diff --git a/demo-app/.env.template b/demos/nodejs/demo-app/.env.template similarity index 100% rename from demo-app/.env.template rename to demos/nodejs/demo-app/.env.template diff --git a/demo-app/.gitignore b/demos/nodejs/demo-app/.gitignore similarity index 100% rename from demo-app/.gitignore rename to demos/nodejs/demo-app/.gitignore diff --git a/demo-app/Dockerfile b/demos/nodejs/demo-app/Dockerfile similarity index 100% rename from demo-app/Dockerfile rename to demos/nodejs/demo-app/Dockerfile diff --git a/demo-app/LICENSE b/demos/nodejs/demo-app/LICENSE similarity index 100% rename from demo-app/LICENSE rename to demos/nodejs/demo-app/LICENSE diff --git a/demo-app/README.md b/demos/nodejs/demo-app/README.md similarity index 100% rename from demo-app/README.md rename to demos/nodejs/demo-app/README.md diff --git a/demo-app/package.json b/demos/nodejs/demo-app/package.json similarity index 100% rename from demo-app/package.json rename to demos/nodejs/demo-app/package.json diff --git a/demo-app/pnpm-lock.yaml b/demos/nodejs/demo-app/pnpm-lock.yaml similarity index 100% rename from demo-app/pnpm-lock.yaml rename to demos/nodejs/demo-app/pnpm-lock.yaml diff --git a/demo-app/public/favicon.ico b/demos/nodejs/demo-app/public/favicon.ico similarity index 100% rename from demo-app/public/favicon.ico rename to demos/nodejs/demo-app/public/favicon.ico diff --git a/demo-app/public/icons/icon-192x192.png b/demos/nodejs/demo-app/public/icons/icon-192x192.png similarity index 100% rename from demo-app/public/icons/icon-192x192.png rename to demos/nodejs/demo-app/public/icons/icon-192x192.png diff --git a/demo-app/public/icons/icon-256x256.png b/demos/nodejs/demo-app/public/icons/icon-256x256.png similarity index 100% rename from demo-app/public/icons/icon-256x256.png rename to demos/nodejs/demo-app/public/icons/icon-256x256.png diff --git a/demo-app/public/icons/icon-384x384.png b/demos/nodejs/demo-app/public/icons/icon-384x384.png similarity index 100% rename from demo-app/public/icons/icon-384x384.png rename to demos/nodejs/demo-app/public/icons/icon-384x384.png diff --git a/demo-app/public/icons/icon-512x512.png b/demos/nodejs/demo-app/public/icons/icon-512x512.png similarity index 100% rename from demo-app/public/icons/icon-512x512.png rename to demos/nodejs/demo-app/public/icons/icon-512x512.png diff --git a/demo-app/public/icons/icon.png b/demos/nodejs/demo-app/public/icons/icon.png similarity index 100% rename from demo-app/public/icons/icon.png rename to demos/nodejs/demo-app/public/icons/icon.png diff --git a/demo-app/public/powersync-logo.svg b/demos/nodejs/demo-app/public/powersync-logo.svg similarity index 100% rename from demo-app/public/powersync-logo.svg rename to demos/nodejs/demo-app/public/powersync-logo.svg diff --git a/demo-app/public/supabase-logo.png b/demos/nodejs/demo-app/public/supabase-logo.png similarity index 100% rename from demo-app/public/supabase-logo.png rename to demos/nodejs/demo-app/public/supabase-logo.png diff --git a/demo-app/src/app/globals.css b/demos/nodejs/demo-app/src/app/globals.css similarity index 100% rename from demo-app/src/app/globals.css rename to demos/nodejs/demo-app/src/app/globals.css diff --git a/demo-app/src/app/index.tsx b/demos/nodejs/demo-app/src/app/index.tsx similarity index 100% rename from demo-app/src/app/index.tsx rename to demos/nodejs/demo-app/src/app/index.tsx diff --git a/demo-app/src/app/page.tsx b/demos/nodejs/demo-app/src/app/page.tsx similarity index 100% rename from demo-app/src/app/page.tsx rename to demos/nodejs/demo-app/src/app/page.tsx diff --git a/demo-app/src/app/router.tsx b/demos/nodejs/demo-app/src/app/router.tsx similarity index 100% rename from demo-app/src/app/router.tsx rename to demos/nodejs/demo-app/src/app/router.tsx diff --git a/demo-app/src/app/views/layout.tsx b/demos/nodejs/demo-app/src/app/views/layout.tsx similarity index 100% rename from demo-app/src/app/views/layout.tsx rename to demos/nodejs/demo-app/src/app/views/layout.tsx diff --git a/demo-app/src/app/views/sql-console/page.tsx b/demos/nodejs/demo-app/src/app/views/sql-console/page.tsx similarity index 100% rename from demo-app/src/app/views/sql-console/page.tsx rename to demos/nodejs/demo-app/src/app/views/sql-console/page.tsx diff --git a/demo-app/src/app/views/todo-lists/edit/page.tsx b/demos/nodejs/demo-app/src/app/views/todo-lists/edit/page.tsx similarity index 100% rename from demo-app/src/app/views/todo-lists/edit/page.tsx rename to demos/nodejs/demo-app/src/app/views/todo-lists/edit/page.tsx diff --git a/demo-app/src/app/views/todo-lists/page.tsx b/demos/nodejs/demo-app/src/app/views/todo-lists/page.tsx similarity index 100% rename from demo-app/src/app/views/todo-lists/page.tsx rename to demos/nodejs/demo-app/src/app/views/todo-lists/page.tsx diff --git a/demo-app/src/components/navigation/NavigationPage.tsx b/demos/nodejs/demo-app/src/components/navigation/NavigationPage.tsx similarity index 100% rename from demo-app/src/components/navigation/NavigationPage.tsx rename to demos/nodejs/demo-app/src/components/navigation/NavigationPage.tsx diff --git a/demo-app/src/components/navigation/NavigationPanelContext.tsx b/demos/nodejs/demo-app/src/components/navigation/NavigationPanelContext.tsx similarity index 100% rename from demo-app/src/components/navigation/NavigationPanelContext.tsx rename to demos/nodejs/demo-app/src/components/navigation/NavigationPanelContext.tsx diff --git a/demo-app/src/components/providers/SystemProvider.tsx b/demos/nodejs/demo-app/src/components/providers/SystemProvider.tsx similarity index 100% rename from demo-app/src/components/providers/SystemProvider.tsx rename to demos/nodejs/demo-app/src/components/providers/SystemProvider.tsx diff --git a/demo-app/src/components/providers/ThemeProviderContainer.tsx b/demos/nodejs/demo-app/src/components/providers/ThemeProviderContainer.tsx similarity index 100% rename from demo-app/src/components/providers/ThemeProviderContainer.tsx rename to demos/nodejs/demo-app/src/components/providers/ThemeProviderContainer.tsx diff --git a/demo-app/src/components/widgets/ListItemWidget.tsx b/demos/nodejs/demo-app/src/components/widgets/ListItemWidget.tsx similarity index 100% rename from demo-app/src/components/widgets/ListItemWidget.tsx rename to demos/nodejs/demo-app/src/components/widgets/ListItemWidget.tsx diff --git a/demo-app/src/components/widgets/TodoItemWidget.tsx b/demos/nodejs/demo-app/src/components/widgets/TodoItemWidget.tsx similarity index 100% rename from demo-app/src/components/widgets/TodoItemWidget.tsx rename to demos/nodejs/demo-app/src/components/widgets/TodoItemWidget.tsx diff --git a/demo-app/src/components/widgets/TodoListsWidget.tsx b/demos/nodejs/demo-app/src/components/widgets/TodoListsWidget.tsx similarity index 100% rename from demo-app/src/components/widgets/TodoListsWidget.tsx rename to demos/nodejs/demo-app/src/components/widgets/TodoListsWidget.tsx diff --git a/demo-app/src/index.html b/demos/nodejs/demo-app/src/index.html similarity index 100% rename from demo-app/src/index.html rename to demos/nodejs/demo-app/src/index.html diff --git a/demo-app/src/library/powersync/AppSchema.ts b/demos/nodejs/demo-app/src/library/powersync/AppSchema.ts similarity index 100% rename from demo-app/src/library/powersync/AppSchema.ts rename to demos/nodejs/demo-app/src/library/powersync/AppSchema.ts diff --git a/demo-app/src/library/powersync/DemoConnector.ts b/demos/nodejs/demo-app/src/library/powersync/DemoConnector.ts similarity index 100% rename from demo-app/src/library/powersync/DemoConnector.ts rename to demos/nodejs/demo-app/src/library/powersync/DemoConnector.ts diff --git a/demo-app/src/library/powersync/vite-env.d.ts b/demos/nodejs/demo-app/src/library/powersync/vite-env.d.ts similarity index 100% rename from demo-app/src/library/powersync/vite-env.d.ts rename to demos/nodejs/demo-app/src/library/powersync/vite-env.d.ts diff --git a/demo-app/tsconfig.json b/demos/nodejs/demo-app/tsconfig.json similarity index 100% rename from demo-app/tsconfig.json rename to demos/nodejs/demo-app/tsconfig.json diff --git a/demo-app/vite.config.mts b/demos/nodejs/demo-app/vite.config.mts similarity index 100% rename from demo-app/vite.config.mts rename to demos/nodejs/demo-app/vite.config.mts diff --git a/demo-backend/Dockerfile b/demos/nodejs/demo-backend/Dockerfile similarity index 100% rename from demo-backend/Dockerfile rename to demos/nodejs/demo-backend/Dockerfile diff --git a/demo-backend/README.md b/demos/nodejs/demo-backend/README.md similarity index 100% rename from demo-backend/README.md rename to demos/nodejs/demo-backend/README.md diff --git a/demos/nodejs/docker-compose.yaml b/demos/nodejs/docker-compose.yaml new file mode 100644 index 0000000..f1597bf --- /dev/null +++ b/demos/nodejs/docker-compose.yaml @@ -0,0 +1,33 @@ +# Include syntax requires Docker compose > 2.20.3 +# https://docs.docker.com/compose/release-notes/#2203 +include: + # Creates the internal MongoDB replica set + - path: ../../services/mongo.yaml + + # Demo NodeJS backend server and front-end web client + - path: ./ps-nodejs-demo.yaml + +services: + # Extend PowerSync with Mongo and Postgres healthchecks + powersync: + extends: + file: ../../services/powersync.yaml + service: powersync + depends_on: + mongo-rs-init: + condition: service_completed_successfully + pg-db: + condition: service_healthy + + # Extend pg-db to include init scripts + # The NodeJS demo creates tables and publications in `setup.sql` + pg-db: + extends: + file: ../../services/postgres.yaml + service: pg-db + volumes: + - ./init-scripts:/docker-entrypoint-initdb.d + +volumes: + # Postgres data + pg_data: diff --git a/init-scripts/setup.sql b/demos/nodejs/init-scripts/setup.sql similarity index 100% rename from init-scripts/setup.sql rename to demos/nodejs/init-scripts/setup.sql diff --git a/ps-demo.yaml b/demos/nodejs/ps-nodejs-demo.yaml similarity index 100% rename from ps-demo.yaml rename to demos/nodejs/ps-nodejs-demo.yaml diff --git a/ps-postgres.yaml b/ps-postgres.yaml deleted file mode 100644 index 3279f6b..0000000 --- a/ps-postgres.yaml +++ /dev/null @@ -1,18 +0,0 @@ -services: - pg-db: - image: postgres:latest - restart: always - environment: - PGPORT: ${PG_DATABASE_PORT} - POSTGRES_DB: ${PG_DATABASE_NAME} - POSTGRES_USER: ${PG_DATABASE_USER} - POSTGRES_PASSWORD: ${PG_DATABASE_PASSWORD} - volumes: - - db_data:/var/lib/postgresql/data - - ./init-scripts:/docker-entrypoint-initdb.d - ports: - - "${PG_DATABASE_PORT}:${PG_DATABASE_PORT}" - command: ["postgres", "-c", "wal_level=logical"] - -volumes: - db_data: diff --git a/ps-mongo.yaml b/services/mongo.yaml similarity index 69% rename from ps-mongo.yaml rename to services/mongo.yaml index cb701a8..e012836 100644 --- a/ps-mongo.yaml +++ b/services/mongo.yaml @@ -14,11 +14,11 @@ services: image: mongo:7.0 depends_on: - mongo - restart: "no" + restart: on-failure entrypoint: - bash - -c - - 'sleep 10 && mongosh --host mongo:27017 --eval ''try{rs.status().ok && quit(0)} catch {} rs.initiate({_id: "rs0", version: 1, members: [{ _id: 0, host : "mongo:27017" }]})''' + - 'mongosh --host mongo:27017 --eval ''try{rs.status().ok && quit(0)} catch {} rs.initiate({_id: "rs0", version: 1, members: [{ _id: 0, host : "mongo:27017" }]})''' volumes: mongo_storage: diff --git a/services/postgres.yaml b/services/postgres.yaml new file mode 100644 index 0000000..e272c0e --- /dev/null +++ b/services/postgres.yaml @@ -0,0 +1,23 @@ +services: + pg-db: + image: postgres:latest + restart: always + environment: + - POSTGRES_USER=${PG_DATABASE_USER} + - POSTGRES_DB=${PG_DATABASE_NAME} + - POSTGRES_PASSWORD=${PG_DATABASE_PASSWORD} + - PGPORT=${PG_DATABASE_PORT} + volumes: + - pg_data:/var/lib/postgresql/data + ports: + - "${PG_DATABASE_PORT}:${PG_DATABASE_PORT}" + command: ["postgres", "-c", "wal_level=logical"] + healthcheck: + test: ["CMD-SHELL", "pg_isready -U ${PG_DATABASE_USER} -d ${PG_DATABASE_NAME}"] + interval: 5s + timeout: 5s + retries: 5 + +volumes: + # Postgres data + pg_data: diff --git a/docker-compose.yaml b/services/powersync.yaml similarity index 85% rename from docker-compose.yaml rename to services/powersync.yaml index ed08f22..0555949 100644 --- a/docker-compose.yaml +++ b/services/powersync.yaml @@ -1,21 +1,6 @@ -# Include syntax requires Docker compose > 2.20.3 -# https://docs.docker.com/compose/release-notes/#2203 -include: - # Creates a standard Postgress instance - - path: ps-postgres.yaml - - # Creates the internal MongoDB replica set - - path: ps-mongo.yaml - - # Demo backend server and front-end web client - - path: ps-demo.yaml - services: - # Main PowerSync service powersync: - depends_on: - - mongo - - pg-db + restart: unless-stopped image: journeyapps/powersync-service:latest # The unified service runs an API server and replication worker in the same container. # These services can be executed in different containers by using individual entry commands e.g. @@ -36,7 +21,7 @@ services: volumes: # Mounts the specified config folder to the container # This folder should contain `powersync.yaml and sync_rules.yaml - - ./config:/config + - ../config:/config environment: # This is the path (inside the container) to the YAML config file # Alternatively the config path can be specified in the command @@ -62,7 +47,7 @@ services: PS_MONGO_URI: mongodb://mongo:27017/powersync_demo # Note that powersync.yaml->client_auth->allow_local_jwks must be true for local URLs to work - PS_JWKS_URL: http://demo-backend:${DEMO_BACKEND_PORT}/api/auth/keys + PS_JWKS_URL: ${PS_JWKS_URL} # The port which the PowerSync API server should run on PS_PORT: ${PS_PORT}