|
| 1 | +--- |
| 2 | +title: "TypeScript + Node.js + PowerSync" |
| 3 | +description: "A guide for creating a new Node.js application using TypeScript with PowerSync for offline/local first functionality" |
| 4 | +keywords: ["clientsdk", "node.js"] |
| 5 | +--- |
| 6 | + |
| 7 | +## Introduction |
| 8 | +In this tutorial, we’ll explore how to create a new Node.js applicaiton with TypeScript and PowerSync for offline-first capabilities. In the following sections, we’ll walk through the process of integrating PowerSync into a Node.js application, setting up local-first storage, and handling synchronization efficiently. |
| 9 | + |
| 10 | +## Prerequisits |
| 11 | + |
| 12 | +In this guide we'll be using Node.js 22.4.0 and pnpm. |
| 13 | + |
| 14 | +## Setup |
| 15 | + |
| 16 | +### Creating a new project |
| 17 | + |
| 18 | +Create a new directory and init your Node.js project |
| 19 | +```shell |
| 20 | +pnpm init |
| 21 | +``` |
| 22 | + |
| 23 | +Install TypeScript |
| 24 | +```shell |
| 25 | +pnpm install typescript -D |
| 26 | +``` |
| 27 | + |
| 28 | +Install PowerSync |
| 29 | +```shell |
| 30 | +pnpm install @powersync/node @powersync/better-sqlite3 |
| 31 | +``` |
| 32 | + |
| 33 | +Update TypeScript Compiler Options |
| 34 | +```json tsconfig.json |
| 35 | +{ |
| 36 | + "compilerOptions": { |
| 37 | + "target": "ES2022", |
| 38 | + "module": "ESNext", |
| 39 | + "moduleResolution": "node", |
| 40 | + "outDir": "./dist", |
| 41 | + "esModuleInterop": true, |
| 42 | + "strict": true, |
| 43 | + "skipLibCheck": true |
| 44 | + }, |
| 45 | + "include": [ |
| 46 | + "src/**/*.ts" |
| 47 | + ], |
| 48 | + "exclude": [ |
| 49 | + "node_modules" |
| 50 | + ] |
| 51 | +} |
| 52 | +``` |
| 53 | + |
| 54 | +Update your package.json |
| 55 | +```json package.json |
| 56 | + ... |
| 57 | + "type": "module", |
| 58 | + "scripts": { |
| 59 | + "build": "pnpm exec tsc", |
| 60 | + "start": "node ./dist/index.js" |
| 61 | + } |
| 62 | + ... |
| 63 | +``` |
| 64 | + |
| 65 | +<Note>The PowerSync Node.js SDK requires `@powersync/better-sqlite3` to be installed</Note> |
| 66 | + |
| 67 | +## Project Setup |
| 68 | + |
| 69 | +### Adding PowerSync |
| 70 | + |
| 71 | +Create a `src` directory and add three files: |
| 72 | +* AppSchema.ts |
| 73 | +* Connector.ts |
| 74 | +* index.ts |
| 75 | + |
| 76 | +#### AppSchema.ts |
| 77 | +This file essentially contains the table definitions for your local database and would look something like this: |
| 78 | +```typescript AppSchema.ts |
| 79 | +import { Schema, Table, column } from '@powersync/node'; |
| 80 | + |
| 81 | +const todos = new Table( |
| 82 | + { |
| 83 | + list_id: column.text, |
| 84 | + created_at: column.text, |
| 85 | + completed_at: column.text, |
| 86 | + description: column.text, |
| 87 | + created_by: column.text, |
| 88 | + completed_by: column.text, |
| 89 | + completed: column.integer, |
| 90 | + photo_id: column.text |
| 91 | + }, |
| 92 | + { indexes: { list: ['list_id'] } } |
| 93 | +); |
| 94 | + |
| 95 | +const lists = new Table({ |
| 96 | + created_at: column.text, |
| 97 | + name: column.text, |
| 98 | + owner_id: column.text |
| 99 | +}); |
| 100 | + |
| 101 | +export const AppSchema = new Schema({ |
| 102 | + lists, |
| 103 | + todos |
| 104 | +}); |
| 105 | +``` |
| 106 | + |
| 107 | +#### Connector.ts |
| 108 | +This file will be the connector which will fetch a JWT used by PowerSync for authentication and another function which will handle uploads to the backend source database. |
| 109 | +```typescript Connector.ts |
| 110 | +import { PowerSyncBackendConnector, AbstractPowerSyncDatabase } from '@powersync/node'; |
| 111 | + |
| 112 | +export class Connector implements PowerSyncBackendConnector { |
| 113 | + constructor() { |
| 114 | + // Setup a connection to your server for uploads |
| 115 | + // this.serverConnectionClient = TODO; |
| 116 | + } |
| 117 | + |
| 118 | + async fetchCredentials() { |
| 119 | + // Implement fetchCredentials to obtain a JWT from your authentication service. |
| 120 | + // See https://docs.powersync.com/installation/authentication-setup |
| 121 | + // If you're using Supabase or Firebase, you can re-use the JWT from those clients, see |
| 122 | + // - https://docs.powersync.com/installation/authentication-setup/supabase-auth |
| 123 | + // - https://docs.powersync.com/installation/authentication-setup/firebase-auth |
| 124 | + return { |
| 125 | + endpoint: '[Your PowerSync instance URL or self-hosted endpoint]', |
| 126 | + // Use a development token (see Authentication Setup https://docs.powersync.com/installation/authentication-setup/development-tokens) to get up and running quickly |
| 127 | + token: 'An authentication token' |
| 128 | + }; |
| 129 | + } |
| 130 | + |
| 131 | + async uploadData(database: AbstractPowerSyncDatabase) { |
| 132 | + // Implement uploadData to send local changes to your backend service. |
| 133 | + // You can omit this method if you only want to sync data from the database to the client |
| 134 | + |
| 135 | + // See example implementation here: https://docs.powersync.com/client-sdk-references/javascript-web#3-integrate-with-your-backend |
| 136 | + } |
| 137 | +} |
| 138 | +``` |
| 139 | + |
| 140 | +#### index.ts |
| 141 | +The main application file used in this guide to show you how to set up and initialize PowerSync. |
| 142 | +```typescript index.ts |
| 143 | +import { PowerSyncDatabase } from '@powersync/node'; |
| 144 | +import { Connector } from './Connector.js'; |
| 145 | +import { AppSchema } from './AppSchema.js'; |
| 146 | + |
| 147 | +export const db = new PowerSyncDatabase({ |
| 148 | + schema: AppSchema, |
| 149 | + database: { |
| 150 | + dbFilename: 'powersync.db' |
| 151 | + }, |
| 152 | +}); |
| 153 | + |
| 154 | +(async () => { |
| 155 | + await db.connect(new Connector()); |
| 156 | + console.log(db.currentStatus); |
| 157 | +})() |
| 158 | + |
| 159 | +``` |
| 160 | + |
| 161 | +## Run the App |
| 162 | +``` |
| 163 | +pnpm start |
| 164 | +``` |
| 165 | +This will start the app, initialize the database and connect to the PowerSync instance. |
| 166 | + |
| 167 | +<Warning> |
| 168 | + Depending on what you set for `dbFilename`, the app start (and all is working correctly) three files will be created; `<dbFilename>.db`, `<dbFilename>.db-shm` and `<dbFilename>.db-wal`. You should exclude these from version control when creating the project so make sure to update your `.gitignore` accordingly. |
| 169 | +</Warning> |
0 commit comments