Skip to content

Commit 33d8676

Browse files
committed
packages: add new quickstart package.
1 parent 8aaeb36 commit 33d8676

22 files changed

+5618
-307
lines changed

packages/quickstart/.eslintrc.cjs

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
module.exports = {
2+
env: {
3+
browser: true,
4+
es2021: true,
5+
node: true,
6+
},
7+
extends: [
8+
`eslint:recommended`,
9+
`plugin:@typescript-eslint/recommended`,
10+
`plugin:prettier/recommended`,
11+
],
12+
parserOptions: {
13+
ecmaVersion: 2022,
14+
requireConfigFile: false,
15+
sourceType: `module`,
16+
ecmaFeatures: {
17+
jsx: true,
18+
},
19+
},
20+
parser: `@typescript-eslint/parser`,
21+
plugins: [`prettier`],
22+
rules: {
23+
quotes: [`error`, `backtick`],
24+
'no-unused-vars': `off`,
25+
'@typescript-eslint/no-unused-vars': [
26+
`error`,
27+
{
28+
argsIgnorePattern: `^_`,
29+
varsIgnorePattern: `^_`,
30+
caughtErrorsIgnorePattern: `^_`,
31+
},
32+
],
33+
},
34+
ignorePatterns: [
35+
'**/node_modules/**',
36+
'**/dist/**',
37+
'tsup.config.ts',
38+
'vitest.config.ts',
39+
'.eslintrc.js',
40+
],
41+
}

packages/quickstart/.prettierrc

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
{
2+
"trailingComma": "es5",
3+
"semi": false,
4+
"tabWidth": 2,
5+
"singleQuote": true
6+
}

packages/quickstart/README.md

Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,65 @@
1+
# @electric-sql/quickstart
2+
3+
CLI package for the [ElectricSQL Quickstart](https://electric-sql.com/docs/quickstart).
4+
5+
## Usage
6+
7+
Create a new app using [Electric](https://electric-sql.com/product/electric) with [TanStack DB](https://tanstack.com/db), based on the [examples/tanstack-db-web-starter](https://github.com/electric-sql/electric/tree/main/examples/tanstack-db-web-starter) [TanStack Start](http://tanstack.com/start) template app:
8+
9+
```bash
10+
pnpx @electric-sql/quickstart my-electric-app
11+
```
12+
13+
This command will:
14+
15+
1. pull in the template app using gitpick
16+
2. provision cloud resources
17+
- a Postgres database using Neon
18+
- an Electric sync service using Electric Cloud
19+
- fetch their access credentials
20+
3. configure the local `.env` to use the credentials
21+
4. add `psql`, `claim` and `deploy` commands to the package.json
22+
- also using the generated credentials
23+
24+
## Environment Variables
25+
26+
The CLI automatically generates these environment variables:
27+
28+
- `DATABASE_URL` - PostgreSQL connection string
29+
- `ELECTRIC_SECRET` - Electric Cloud authentication secret
30+
- `ELECTRIC_SOURCE_ID` - Electric sync service identifier
31+
32+
## Commands
33+
34+
```bash
35+
pnpm dev # Start development server
36+
pnpm psql # Connect to PostgreSQL database
37+
pnpm claim # Claim temporary resources
38+
pnpm deploy # Deploy to Netlify
39+
```
40+
41+
### `pnpm psql`
42+
43+
Connect directly to your PostgreSQL database using the configured `DATABASE_URL`:
44+
45+
### `pnpm claim`
46+
47+
Claim temporary resources to move them to your permanent Electric Cloud and Neon accounts.
48+
49+
### `pnpm deploy`
50+
51+
Deploy your app to Netlify with all environment variables configured.
52+
53+
## Development
54+
55+
This package is part of the Electric monorepo. To work on it:
56+
57+
```bash
58+
# From the monorepo root
59+
pnpm install # Install all workspace dependencies
60+
pnpm build # Build all packages
61+
62+
# From packages/quickstart
63+
pnpm build # Compile TypeScript
64+
pnpm dev # Build and test locally
65+
```

packages/quickstart/package.json

Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,71 @@
1+
{
2+
"name": "@electric-sql/quickstart",
3+
"version": "1.0.0",
4+
"description": "CLI package for the ElectricSQL Quickstart.",
5+
"type": "module",
6+
"main": "./dist/index.js",
7+
"bin": {
8+
"quickstart": "./dist/cli.js"
9+
},
10+
"exports": {
11+
"./package.json": "./package.json",
12+
".": {
13+
"import": {
14+
"types": "./dist/index.d.ts",
15+
"default": "./dist/index.js"
16+
}
17+
}
18+
},
19+
"scripts": {
20+
"build": "shx rm -rf dist && tsup",
21+
"prepack": "pnpm build",
22+
"dev": "pnpm run build && node dist/cli.js",
23+
"format": "eslint . --fix",
24+
"stylecheck": "eslint . --quiet",
25+
"test": "pnpm exec vitest",
26+
"coverage": "pnpm exec vitest --coverage",
27+
"typecheck": "tsc -p tsconfig.json"
28+
},
29+
"dependencies": {
30+
"node-fetch": "^2.7.0"
31+
},
32+
"devDependencies": {
33+
"@types/node": "^20.10.0",
34+
"@types/node-fetch": "^2.6.11",
35+
"@typescript-eslint/eslint-plugin": "^7.14.1",
36+
"@typescript-eslint/parser": "^7.14.1",
37+
"@vitest/coverage-istanbul": "2.1.4",
38+
"eslint": "^8.57.0",
39+
"eslint-config-prettier": "^9.1.0",
40+
"eslint-plugin-prettier": "^5.1.3",
41+
"netlify-cli": "^23.5.1",
42+
"prettier": "^3.3.2",
43+
"shx": "^0.3.4",
44+
"tsup": "^8.0.1",
45+
"typescript": "^5.5.2",
46+
"vitest": "^3.0.0"
47+
},
48+
"files": [
49+
"dist",
50+
"src"
51+
],
52+
"keywords": [
53+
"cli",
54+
"db",
55+
"electric",
56+
"electric-sql",
57+
"quickstart",
58+
"starter",
59+
"tanstack"
60+
],
61+
"author": "ElectricSQL team and contributors.",
62+
"license": "Apache-2.0",
63+
"repository": {
64+
"type": "git",
65+
"url": "git+https://github.com/electric-sql/electric.git"
66+
},
67+
"bugs": {
68+
"url": "https://github.com/electric-sql/electric/issues"
69+
},
70+
"homepage": "https://electric-sql.com"
71+
}

packages/quickstart/src/cli.ts

Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,65 @@
1+
#!/usr/bin/env node
2+
3+
import { provisionElectricResources } from './electric-api.js'
4+
import { setupTemplate } from './template-setup.js'
5+
6+
async function main() {
7+
const args = process.argv.slice(2)
8+
9+
if (args.length === 0) {
10+
console.error(`Usage: quickstart <app-name>`)
11+
12+
process.exit(1)
13+
}
14+
15+
const appName = args[0]
16+
17+
// Validate app name
18+
if (!/^[a-zA-Z0-9-_]+$/.test(appName)) {
19+
console.error(
20+
`App name must contain only letters, numbers, hyphens, and underscores`
21+
)
22+
23+
process.exit(1)
24+
}
25+
26+
console.log(`Creating app: ${appName}`)
27+
28+
try {
29+
console.log(`Provisioning resources...`)
30+
const credentials = await provisionElectricResources()
31+
32+
// Step 2: Setup TanStack Start template
33+
console.log(`Setting up template...`)
34+
await setupTemplate(appName, credentials)
35+
36+
// Step 3: Display completion message
37+
console.log(`Setup complete`)
38+
console.log(``)
39+
console.log(`Next steps:`)
40+
console.log(` cd ${appName}`)
41+
console.log(` pnpm dev`)
42+
console.log(``)
43+
console.log(`Commands:`)
44+
console.log(` pnpm psql # Connect to database`)
45+
console.log(` pnpm claim # Claim resources`)
46+
console.log(` pnpm deploy # Deploy to Netlify`)
47+
console.log(``)
48+
console.log(`Tutorial: https://electric-sql.com/docs`)
49+
} catch (error) {
50+
console.error(
51+
`Setup failed:`,
52+
error instanceof Error ? error.message : error
53+
)
54+
process.exit(1)
55+
}
56+
}
57+
58+
if (import.meta.url === `file://${process.argv[1]}`) {
59+
main().catch((error) => {
60+
console.error(`Unexpected error:`, error)
61+
process.exit(1)
62+
})
63+
}
64+
65+
export { main }
Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
import { claimResources } from '../electric-api'
2+
3+
export async function claimCommand(): Promise<void> {
4+
const sourceId = process.env.ELECTRIC_SOURCE_ID
5+
const secret = process.env.ELECTRIC_SECRET
6+
7+
if (!sourceId || !secret) {
8+
console.error(
9+
`Missing ELECTRIC_SOURCE_ID or ELECTRIC_SECRET environment variables`
10+
)
11+
console.error(`Ensure .env file exists with Electric credentials`)
12+
process.exit(1)
13+
}
14+
15+
console.log(`Initiating resource claim...`)
16+
17+
try {
18+
const result = await claimResources(sourceId, secret)
19+
20+
console.log(`Resource claim initiated`)
21+
console.log(``)
22+
console.log(`Open URL to complete claim:`)
23+
console.log(result.claimUrl)
24+
console.log(``)
25+
console.log(`This will:`)
26+
console.log(`- Link Electric Cloud account`)
27+
console.log(`- Link Neon database account`)
28+
console.log(`- Transfer temporary resources`)
29+
console.log(``)
30+
console.log(
31+
`Warning: Temporary resources expire if not claimed within days`
32+
)
33+
} catch (error) {
34+
console.error(
35+
`Failed to initiate resource claim:`,
36+
error instanceof Error ? error.message : error
37+
)
38+
console.error(``)
39+
console.error(`Common issues:`)
40+
console.error(`- Invalid credentials (check .env file)`)
41+
console.error(`- Resources already claimed`)
42+
console.error(`- Network connectivity`)
43+
process.exit(1)
44+
}
45+
}
Lines changed: 81 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,81 @@
1+
import { execSync } from 'child_process'
2+
3+
export function deployCommand(): void {
4+
const requiredEnvVars = [
5+
`ELECTRIC_SOURCE_ID`,
6+
`ELECTRIC_SECRET`,
7+
`DATABASE_URL`,
8+
]
9+
const missingVars = requiredEnvVars.filter((varName) => !process.env[varName])
10+
11+
if (missingVars.length > 0) {
12+
console.error(
13+
`Missing required environment variables:`,
14+
missingVars.join(`, `)
15+
)
16+
console.error(`Ensure .env file contains all Electric credentials`)
17+
process.exit(1)
18+
}
19+
20+
console.log(`Starting deployment...`)
21+
console.log(``)
22+
23+
try {
24+
// Set Nitro preset for Netlify
25+
process.env.NITRO_PRESET = `netlify`
26+
27+
console.log(`Building application...`)
28+
execSync(`pnpm build`, {
29+
stdio: `inherit`,
30+
env: {
31+
...process.env,
32+
NITRO_PRESET: `netlify`,
33+
},
34+
})
35+
36+
console.log(`Deploying to Netlify...`)
37+
38+
// Deploy with environment variables
39+
const deployCommand = [
40+
`netlify deploy`,
41+
`--prod`,
42+
`--dir=dist`,
43+
`--functions=.netlify/functions-internal`,
44+
].join(` `)
45+
46+
execSync(deployCommand, {
47+
stdio: `inherit`,
48+
env: {
49+
...process.env,
50+
// Ensure all Electric credentials are available during deployment
51+
ELECTRIC_SOURCE_ID: process.env.ELECTRIC_SOURCE_ID,
52+
ELECTRIC_SECRET: process.env.ELECTRIC_SECRET,
53+
DATABASE_URL: process.env.DATABASE_URL,
54+
},
55+
})
56+
57+
console.log(``)
58+
console.log(`Deployment completed`)
59+
console.log(``)
60+
console.log(`App is live on Netlify with all environment variables.`)
61+
} catch (error) {
62+
console.error(
63+
`Deployment failed:`,
64+
error instanceof Error ? error.message : error
65+
)
66+
console.error(``)
67+
console.error(`Common issues:`)
68+
console.error(
69+
`- Netlify CLI not installed (run: npm install -g netlify-cli)`
70+
)
71+
console.error(`- Not logged in (run: netlify login)`)
72+
console.error(`- Build errors`)
73+
console.error(`- Missing environment variables in Netlify`)
74+
console.error(``)
75+
console.error(`Required environment variables in Netlify settings:`)
76+
console.error(`- ELECTRIC_SOURCE_ID`)
77+
console.error(`- ELECTRIC_SECRET`)
78+
console.error(`- DATABASE_URL`)
79+
process.exit(1)
80+
}
81+
}

0 commit comments

Comments
 (0)