Skip to content

Commit

Permalink
examples: add public deployment of LinearLite
Browse files Browse the repository at this point in the history
  • Loading branch information
KyleAMathews authored and balegas committed Nov 5, 2024
1 parent 3775f1c commit 704b347
Show file tree
Hide file tree
Showing 7 changed files with 156 additions and 11 deletions.
16 changes: 9 additions & 7 deletions examples/linearlite/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -5,18 +5,19 @@
"private": true,
"type": "module",
"scripts": {
"backend:up": "PROJECT_NAME=linearlite pnpm -C ../../ run example-backend:up && pnpm db:migrate && pnpm db:load-data",
"backend:down": "PROJECT_NAME=linearlite pnpm -C ../../ run example-backend:down",
"db:migrate": "dotenv -e ../../.env.dev -- pnpm exec pg-migrations apply --directory ./db/migrations",
"backend:up": "PROJECT_NAME=linearlite pnpm -C ../../ run example-backend:up && pnpm db:migrate && pnpm db:load-data",
"build": "vite build",
"db:load-data": "dotenv -e ../../.env.dev -- node ./db/load_data.js",
"db:migrate": "dotenv -e ../../.env.dev -- pnpm exec pg-migrations apply --directory ./db/migrations",
"dev": "vite",
"build": "vite build",
"stylecheck": "eslint . --ext ts,tsx --report-unused-disable-directives --max-warnings 0",
"preview": "vite preview",
"typecheck": "tsc --noEmit",
"process-data": "node ./db/process_data.js"
"process-data": "node ./db/process_data.js",
"stylecheck": "eslint . --ext ts,tsx --report-unused-disable-directives --max-warnings 0",
"typecheck": "tsc --noEmit"
},
"dependencies": {
"@electric-sql/client": "workspace:*",
"@electric-sql/react": "workspace:*",
"@firefox-devtools/react-contextmenu": "^5.1.1",
"@headlessui/react": "^1.7.17",
Expand All @@ -35,7 +36,6 @@
"classnames": "^2.5.1",
"dayjs": "^1.11.11",
"dotenv": "^16.4.5",
"@electric-sql/client": "workspace:*",
"fractional-indexing": "^3.2.0",
"jsonwebtoken": "^9.0.2",
"lodash.debounce": "^4.0.8",
Expand All @@ -48,6 +48,7 @@
"react-toastify": "^9.1.3",
"react-virtualized-auto-sizer": "^1.0.24",
"react-window": "^1.8.10",
"sst": "3.2.70",
"tiptap-markdown": "^0.8.2",
"uuid": "^9.0.0",
"vite-plugin-svgr": "^3.2.0"
Expand All @@ -57,6 +58,7 @@
"@databases/pg-migrations": "^5.0.3",
"@faker-js/faker": "^8.4.1",
"@tailwindcss/typography": "^0.5.10",
"@types/aws-lambda": "8.10.145",
"@types/jest": "^29.5.12",
"@types/lodash.debounce": "^4.0.9",
"@types/node": "^20.14.10",
Expand Down
4 changes: 3 additions & 1 deletion examples/linearlite/src/electric.tsx
Original file line number Diff line number Diff line change
@@ -1 +1,3 @@
export const baseUrl = import.meta.env.ELECTRIC_URL ?? `http://localhost:3000`
export const baseUrl = import.meta.env.VITE_ELECTRIC_URL ? new URL(import.meta.env.VITE_ELECTRIC_URL).origin : `http://localhost:3000`
export const token = import.meta.env.VITE_ELECTRIC_TOKEN ?? ``
export const databaseId = import.meta.env.VITE_DATABASE_ID ?? ``
6 changes: 5 additions & 1 deletion examples/linearlite/src/pages/Issue/Comments.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ import { formatDate } from '../../utils/date'
import { showWarning } from '../../utils/notification'
import { Comment, Issue } from '../../types/types'
import { useShape } from '@electric-sql/react'
import { baseUrl } from '../../electric'
import { baseUrl, databaseId, token } from '../../electric'

export interface CommentsProps {
issue: Issue
Expand All @@ -18,6 +18,10 @@ function Comments(commentProps: CommentsProps) {
const [newCommentBody, setNewCommentBody] = useState<string>(``)
const allComments = useShape({
url: `${baseUrl}/v1/shape/comment`,
databaseId,
headers: {
Authorization: `Bearer ${token}`,
},
})! as Comment[]

const comments = allComments.data.filter(
Expand Down
9 changes: 7 additions & 2 deletions examples/linearlite/src/shapes.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,10 @@
import { baseUrl } from './electric'
import { ShapeStreamOptions } from '@electric-sql/next'
import { baseUrl, databaseId, token } from './electric'

export const issueShape = {
export const issueShape: ShapeStreamOptions = {
url: `${baseUrl}/v1/shape/issue`,
databaseId,
headers: {
Authorization: `Bearer ${token}`,
},
}
12 changes: 12 additions & 0 deletions examples/linearlite/src/sst-env.d.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
/* This file is auto-generated by SST. Do not edit. */
/* tslint:disable */
/* eslint-disable */
/// <reference types="vite/client" />
interface ImportMetaEnv {
readonly VITE_ELECTRIC_URL: string
readonly VITE_ELECTRIC_TOKEN: string
readonly VITE_DATABASE_ID: string
}
interface ImportMeta {
readonly env: ImportMetaEnv
}
14 changes: 14 additions & 0 deletions examples/linearlite/sst-env.d.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
/* This file is auto-generated by SST. Do not edit. */
/* tslint:disable */
/* eslint-disable */
/* deno-fmt-ignore-file */
import "sst"
export {}
declare module "sst" {
export interface Resource {
"linearlite-example": {
"type": "sst.aws.StaticSite"
"url": string
}
}
}
106 changes: 106 additions & 0 deletions examples/linearlite/sst.config.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,106 @@
/// <reference path="./.sst/platform/config.d.ts" />

import { execSync } from 'child_process'

export default $config({
app(input) {
return {
name: `linearlite`,
removal: input?.stage === `production` ? `retain` : `remove`,
home: `aws`,
providers: { neon: `0.6.3` },
}
},
async run() {
const project = neon.getProjectOutput({ id: process.env.NEON_PROJECT_ID! })
const base = {
projectId: project.id,
branchId: project.defaultBranchId,
}

const db = new neon.Database(`linearlite`, {
...base,
ownerName: `neondb_owner`,
})

const databaseUri = getNeonDbUri(project, db)

databaseUri.apply(applyMigrations)

const electricInfo = databaseUri.apply((uri) => addDatabaseToElectric(uri))

const website = deployLinearLite(electricInfo)

return {
databaseUri,
database_id: electricInfo.id,
electric_token: electricInfo.token,
website: website.url,
}
},
})

function applyMigrations(uri: string) {
execSync(`pnpm exec pg-migrations apply --directory ./db/migrations`, {
env: {
...process.env,
DATABASE_URL: uri,
},
})
}

function deployLinearLite(
electricInfo: $util.Output<{ id: string; token: string }>
) {
return new sst.aws.StaticSite(`linearlite-example`, {
environment: {
VITE_ELECTRIC_URL: process.env.ELECTRIC_API!,
VITE_ELECTRIC_TOKEN: electricInfo.token,
VITE_DATABASE_ID: electricInfo.id,
},
build: {
command: `pnpm run build`,
output: `dist`,
},
domain: {
name: `linearlite-example${$app.stage === `production` ? `` : `-stage-${$app.stage}`}.electric-sql.com`,
dns: sst.cloudflare.dns(),
},
})
}

function getNeonDbUri(
project: $util.Output<neon.GetProjectResult>,
db: neon.Database
) {
const passwordOutput = neon.getBranchRolePasswordOutput({
projectId: project.id,
branchId: project.defaultBranchId,
roleName: db.ownerName,
})

return $interpolate`postgresql://${passwordOutput.roleName}:${passwordOutput.password}@${project.databaseHost}/${db.name}?sslmode=require`
}

async function addDatabaseToElectric(
uri: string
): Promise<{ id: string; token: string }> {
const adminApi = process.env.ELECTRIC_ADMIN_HOST

const result = await fetch(`${adminApi}/v1/databases`, {
method: `PUT`,
headers: { 'Content-Type': `application/json` },
body: JSON.stringify({
database_url: uri,
region: `us-east-1`,
}),
})

if (!result.ok) {
throw new Error(
`Could not add database to Electric (${result.status}): ${await result.text()}`
)
}

return await result.json()
}

0 comments on commit 704b347

Please sign in to comment.