pgserve 0.1.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.genie/AGENTS.md +13 -0
- package/.genie/agents/README.md +110 -0
- package/.genie/agents/analyze.md +176 -0
- package/.genie/agents/forge.md +290 -0
- package/.genie/agents/garbage-cleaner.md +324 -0
- package/.genie/agents/garbage-collector.md +596 -0
- package/.genie/agents/github-issue-gc.md +618 -0
- package/.genie/agents/review.md +380 -0
- package/.genie/agents/semantic-analyzer/find-duplicates.md +90 -0
- package/.genie/agents/semantic-analyzer/find-orphans.md +99 -0
- package/.genie/agents/semantic-analyzer.md +101 -0
- package/.genie/agents/update.md +182 -0
- package/.genie/agents/wish.md +357 -0
- package/.genie/code/AGENTS.md +692 -0
- package/.genie/code/agents/audit/risk.md +173 -0
- package/.genie/code/agents/audit/security.md +189 -0
- package/.genie/code/agents/audit.md +145 -0
- package/.genie/code/agents/challenge.md +230 -0
- package/.genie/code/agents/change-reviewer.md +295 -0
- package/.genie/code/agents/code-garbage-collector.md +425 -0
- package/.genie/code/agents/code-quality.md +410 -0
- package/.genie/code/agents/commit-suggester.md +255 -0
- package/.genie/code/agents/commit.md +124 -0
- package/.genie/code/agents/consensus.md +204 -0
- package/.genie/code/agents/daily-standup.md +722 -0
- package/.genie/code/agents/docgen.md +48 -0
- package/.genie/code/agents/explore.md +79 -0
- package/.genie/code/agents/fix.md +100 -0
- package/.genie/code/agents/git/commit-advisory.md +219 -0
- package/.genie/code/agents/git/workflows/issue.md +244 -0
- package/.genie/code/agents/git/workflows/pr.md +179 -0
- package/.genie/code/agents/git/workflows/release.md +460 -0
- package/.genie/code/agents/git/workflows/report.md +342 -0
- package/.genie/code/agents/git.md +432 -0
- package/.genie/code/agents/implementor.md +161 -0
- package/.genie/code/agents/install.md +515 -0
- package/.genie/code/agents/issue-creator.md +344 -0
- package/.genie/code/agents/polish.md +116 -0
- package/.genie/code/agents/qa.md +653 -0
- package/.genie/code/agents/refactor.md +294 -0
- package/.genie/code/agents/release.md +1129 -0
- package/.genie/code/agents/roadmap.md +885 -0
- package/.genie/code/agents/tests.md +557 -0
- package/.genie/code/agents/tracer.md +50 -0
- package/.genie/code/agents/update/upstream-update.md +85 -0
- package/.genie/code/agents/update/versions/generic-update.md +305 -0
- package/.genie/code/agents/vibe.md +1317 -0
- package/.genie/code/spells/agent-configuration.md +58 -0
- package/.genie/code/spells/automated-rc-publishing.md +106 -0
- package/.genie/code/spells/branch-tracker-guidance.md +28 -0
- package/.genie/code/spells/debug.md +320 -0
- package/.genie/code/spells/emoji-naming-convention.md +303 -0
- package/.genie/code/spells/evidence-storage.md +26 -0
- package/.genie/code/spells/file-naming-rules.md +35 -0
- package/.genie/code/spells/forge-code-blueprints.md +195 -0
- package/.genie/code/spells/genie-integration.md +153 -0
- package/.genie/code/spells/publishing-protocol.md +61 -0
- package/.genie/code/spells/team-consultation-protocol.md +284 -0
- package/.genie/code/spells/tool-requirements.md +20 -0
- package/.genie/code/spells/triad-maintenance-protocol.md +154 -0
- package/.genie/code/teams/tech-council/council.md +328 -0
- package/.genie/code/teams/tech-council/jt.md +352 -0
- package/.genie/code/teams/tech-council/nayr.md +305 -0
- package/.genie/code/teams/tech-council/oettam.md +375 -0
- package/.genie/neurons/README.md +193 -0
- package/.genie/neurons/forge.md +106 -0
- package/.genie/neurons/genie.md +63 -0
- package/.genie/neurons/review.md +106 -0
- package/.genie/neurons/wish.md +104 -0
- package/.genie/product/README.md +20 -0
- package/.genie/product/cli-automation.md +359 -0
- package/.genie/product/environment.md +60 -0
- package/.genie/product/mission.md +60 -0
- package/.genie/product/roadmap.md +44 -0
- package/.genie/product/tech-stack.md +34 -0
- package/.genie/product/templates/context-template.md +218 -0
- package/.genie/product/templates/qa-done-report-template.md +68 -0
- package/.genie/product/templates/review-report-template.md +89 -0
- package/.genie/product/templates/wish-template.md +120 -0
- package/.genie/scripts/helpers/analyze-commit.js +195 -0
- package/.genie/scripts/helpers/bullet-counter.js +194 -0
- package/.genie/scripts/helpers/bullet-find.js +289 -0
- package/.genie/scripts/helpers/bullet-id.js +244 -0
- package/.genie/scripts/helpers/check-secrets.js +237 -0
- package/.genie/scripts/helpers/count-tokens.js +200 -0
- package/.genie/scripts/helpers/create-frontmatter.js +456 -0
- package/.genie/scripts/helpers/detect-markers.js +293 -0
- package/.genie/scripts/helpers/detect-todos.js +267 -0
- package/.genie/scripts/helpers/detect-unlabeled-blocks.js +135 -0
- package/.genie/scripts/helpers/embeddings.js +344 -0
- package/.genie/scripts/helpers/find-empty-sections.js +158 -0
- package/.genie/scripts/helpers/index.js +319 -0
- package/.genie/scripts/helpers/validate-frontmatter.js +578 -0
- package/.genie/scripts/helpers/validate-links.js +207 -0
- package/.genie/scripts/helpers/validate-paths.js +373 -0
- package/.genie/spells/README.md +9 -0
- package/.genie/spells/ace-protocol.md +118 -0
- package/.genie/spells/ask-one-at-a-time.md +175 -0
- package/.genie/spells/backup-analyzer.md +542 -0
- package/.genie/spells/blocker.md +12 -0
- package/.genie/spells/break-things-move-fast.md +56 -0
- package/.genie/spells/context-candidates.md +72 -0
- package/.genie/spells/context-critic.md +51 -0
- package/.genie/spells/defer-to-expertise.md +278 -0
- package/.genie/spells/delegate-dont-do.md +292 -0
- package/.genie/spells/error-investigation-protocol.md +328 -0
- package/.genie/spells/evidence-based-completion.md +273 -0
- package/.genie/spells/experiment.md +65 -0
- package/.genie/spells/file-creation-protocol.md +229 -0
- package/.genie/spells/forge-integration.md +281 -0
- package/.genie/spells/forge-orchestration.md +514 -0
- package/.genie/spells/gather-context.md +18 -0
- package/.genie/spells/global-health-check.md +34 -0
- package/.genie/spells/global-noop-roundtrip.md +25 -0
- package/.genie/spells/install-genie.md +1232 -0
- package/.genie/spells/install.md +82 -0
- package/.genie/spells/investigate-before-commit.md +112 -0
- package/.genie/spells/know-yourself.md +288 -0
- package/.genie/spells/learn.md +828 -0
- package/.genie/spells/mcp-diagnostic-protocol.md +246 -0
- package/.genie/spells/mcp-first.md +124 -0
- package/.genie/spells/multi-step-execution.md +67 -0
- package/.genie/spells/orchestration-boundary-protocol.md +256 -0
- package/.genie/spells/orchestrator-not-implementor.md +189 -0
- package/.genie/spells/prompt.md +746 -0
- package/.genie/spells/reflect.md +404 -0
- package/.genie/spells/routing-decision-matrix.md +368 -0
- package/.genie/spells/run-in-parallel.md +12 -0
- package/.genie/spells/session-state-updater-example.md +196 -0
- package/.genie/spells/session-state-updater.md +220 -0
- package/.genie/spells/track-long-running-tasks.md +133 -0
- package/.genie/spells/troubleshoot-infrastructure.md +176 -0
- package/.genie/spells/upgrade-genie.md +415 -0
- package/.genie/spells/url-presentation-protocol.md +301 -0
- package/.genie/spells/wish-initiation.md +158 -0
- package/.genie/spells/wish-issue-linkage.md +410 -0
- package/.genie/spells/wish-lifecycle.md +100 -0
- package/.genie/state/provider-status.json +3 -0
- package/.genie/state/version.json +16 -0
- package/AGENTS.md +422 -0
- package/CLAUDE.md +1 -0
- package/LICENSE +21 -0
- package/Makefile +235 -0
- package/README.md +323 -0
- package/bin/pglite-server.js +457 -0
- package/ecosystem.config.cjs +23 -0
- package/examples/multi-tenant-demo.js +104 -0
- package/package.json +47 -0
- package/src/detector.js +105 -0
- package/src/index.js +177 -0
- package/src/pool.js +320 -0
- package/src/ports.js +114 -0
- package/src/protocol.js +216 -0
- package/src/registry.js +134 -0
- package/src/router.js +289 -0
- package/src/server.js +265 -0
- package/tests/benchmarks/runner.js +489 -0
- package/tests/multi-tenant.test.js +201 -0
package/README.md
ADDED
|
@@ -0,0 +1,323 @@
|
|
|
1
|
+
# pgserve
|
|
2
|
+
|
|
3
|
+
**Multi-tenant PostgreSQL router using PGlite** - Single port, auto-provisioning, zero config.
|
|
4
|
+
|
|
5
|
+
Perfect for multi-user apps, AI agents, and embedded databases.
|
|
6
|
+
|
|
7
|
+
## ✨ Features
|
|
8
|
+
|
|
9
|
+
- 🎯 **Multi-Tenant** - Single port, multiple isolated databases (one per user/app)
|
|
10
|
+
- 🚀 **Auto-Provisioning** - Databases created on demand from connection string
|
|
11
|
+
- 🔌 **Single Endpoint** - `postgresql://localhost:8432/dbname` routes to correct PGlite instance
|
|
12
|
+
- ⚡ **High Performance** - MVCC, row-level locking, concurrent writes
|
|
13
|
+
- 🎛️ **Zero Configuration** - Auto-tuned for your hardware (CPU, RAM)
|
|
14
|
+
- 📦 **PostgreSQL Compatible** - Works with any PostgreSQL client (psql, Prisma, pg, etc.)
|
|
15
|
+
- 🛡️ **Data Isolation** - Each database = separate PGlite instance
|
|
16
|
+
- 💾 **Persistent** - Data survives restarts
|
|
17
|
+
|
|
18
|
+
## 🎯 Use Cases
|
|
19
|
+
|
|
20
|
+
### Perfect For
|
|
21
|
+
|
|
22
|
+
- 🤖 **AI Agents** - Each agent gets isolated database (sessions, memory, state)
|
|
23
|
+
- 👥 **Multi-User Apps** - One database per user, single endpoint
|
|
24
|
+
- 🏢 **SaaS Applications** - Tenant isolation without infrastructure complexity
|
|
25
|
+
- 🧪 **Development** - Local PostgreSQL without Docker
|
|
26
|
+
- 📱 **Desktop Apps** - Electron, Tauri with embedded multi-tenant DB
|
|
27
|
+
|
|
28
|
+
### Real-World Examples
|
|
29
|
+
|
|
30
|
+
- **AI Agent Swarms**: 100+ agents, each with isolated database
|
|
31
|
+
- **Multi-Tenant SaaS**: Single endpoint, automatic tenant provisioning
|
|
32
|
+
- **Desktop Apps**: Embedded PostgreSQL with multi-user support
|
|
33
|
+
|
|
34
|
+
## 🚀 Quick Start
|
|
35
|
+
|
|
36
|
+
### Installation
|
|
37
|
+
|
|
38
|
+
```bash
|
|
39
|
+
npm install pgserve
|
|
40
|
+
# or
|
|
41
|
+
pnpm add pgserve
|
|
42
|
+
```
|
|
43
|
+
|
|
44
|
+
### Multi-Tenant Mode (Recommended)
|
|
45
|
+
|
|
46
|
+
```javascript
|
|
47
|
+
import { startMultiTenantServer } from 'pgserve';
|
|
48
|
+
|
|
49
|
+
// Start multi-tenant router on single port
|
|
50
|
+
const router = await startMultiTenantServer({
|
|
51
|
+
port: 8432, // Single port for all databases
|
|
52
|
+
baseDir: './data', // Base directory (creates ./data/dbname/ per DB)
|
|
53
|
+
autoProvision: true, // Auto-create databases (default: true)
|
|
54
|
+
maxInstances: 100, // Max concurrent databases
|
|
55
|
+
logLevel: 'info'
|
|
56
|
+
});
|
|
57
|
+
|
|
58
|
+
// Clients connect like normal PostgreSQL:
|
|
59
|
+
// postgresql://localhost:8432/user123 → ./data/user123/
|
|
60
|
+
// postgresql://localhost:8432/app456 → ./data/app456/
|
|
61
|
+
```
|
|
62
|
+
|
|
63
|
+
### Usage with PostgreSQL Clients
|
|
64
|
+
|
|
65
|
+
```javascript
|
|
66
|
+
import pg from 'pg';
|
|
67
|
+
|
|
68
|
+
// Connect to database "user123" (auto-created)
|
|
69
|
+
const client1 = new pg.Client({
|
|
70
|
+
connectionString: 'postgresql://localhost:8432/user123'
|
|
71
|
+
});
|
|
72
|
+
|
|
73
|
+
await client1.connect();
|
|
74
|
+
await client1.query('CREATE TABLE users (id SERIAL, name TEXT)');
|
|
75
|
+
await client1.query("INSERT INTO users (name) VALUES ('Alice')");
|
|
76
|
+
|
|
77
|
+
// Connect to database "app456" (different isolated instance)
|
|
78
|
+
const client2 = new pg.Client({
|
|
79
|
+
connectionString: 'postgresql://localhost:8432/app456'
|
|
80
|
+
});
|
|
81
|
+
|
|
82
|
+
await client2.connect();
|
|
83
|
+
await client2.query('CREATE TABLE posts (id SERIAL, title TEXT)');
|
|
84
|
+
|
|
85
|
+
// Each database is completely isolated!
|
|
86
|
+
```
|
|
87
|
+
|
|
88
|
+
### With Prisma
|
|
89
|
+
|
|
90
|
+
```javascript
|
|
91
|
+
// prisma/schema.prisma
|
|
92
|
+
datasource db {
|
|
93
|
+
provider = "postgresql"
|
|
94
|
+
url = env("DATABASE_URL")
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
// .env
|
|
98
|
+
DATABASE_URL="postgresql://localhost:8432/myapp"
|
|
99
|
+
```
|
|
100
|
+
|
|
101
|
+
```bash
|
|
102
|
+
# Auto-provisions "myapp" database
|
|
103
|
+
npx prisma migrate dev
|
|
104
|
+
```
|
|
105
|
+
|
|
106
|
+
## 📖 API Reference
|
|
107
|
+
|
|
108
|
+
### `startMultiTenantServer(options)`
|
|
109
|
+
|
|
110
|
+
Start multi-tenant router server.
|
|
111
|
+
|
|
112
|
+
```javascript
|
|
113
|
+
const router = await startMultiTenantServer({
|
|
114
|
+
port: 8432, // Port to listen on (default: 8432)
|
|
115
|
+
host: '127.0.0.1', // Host to bind (default: 127.0.0.1)
|
|
116
|
+
baseDir: './data', // Base data directory (default: './data')
|
|
117
|
+
autoProvision: true, // Auto-create databases (default: true)
|
|
118
|
+
maxInstances: 100, // Max concurrent databases (default: 100)
|
|
119
|
+
logLevel: 'info', // Log level: error, warn, info, debug (default: 'info')
|
|
120
|
+
inspect: false // Enable wire protocol debugging (default: false)
|
|
121
|
+
});
|
|
122
|
+
|
|
123
|
+
// Returns MultiTenantRouter instance
|
|
124
|
+
```
|
|
125
|
+
|
|
126
|
+
### Router Methods
|
|
127
|
+
|
|
128
|
+
```javascript
|
|
129
|
+
// Get router stats
|
|
130
|
+
const stats = router.getStats();
|
|
131
|
+
// {
|
|
132
|
+
// port: 8432,
|
|
133
|
+
// activeConnections: 2,
|
|
134
|
+
// pool: {
|
|
135
|
+
// totalInstances: 3,
|
|
136
|
+
// maxInstances: 100,
|
|
137
|
+
// instances: [...]
|
|
138
|
+
// }
|
|
139
|
+
// }
|
|
140
|
+
|
|
141
|
+
// List all databases
|
|
142
|
+
const databases = router.listDatabases();
|
|
143
|
+
// [
|
|
144
|
+
// { dbName: 'user123', locked: false, queueLength: 0, ... },
|
|
145
|
+
// { dbName: 'app456', locked: true, queueLength: 1, ... }
|
|
146
|
+
// ]
|
|
147
|
+
|
|
148
|
+
// Stop router (closes all instances)
|
|
149
|
+
await router.stop();
|
|
150
|
+
```
|
|
151
|
+
|
|
152
|
+
## 🏗️ Architecture
|
|
153
|
+
|
|
154
|
+
### Single Port, Multi-Tenant Routing
|
|
155
|
+
|
|
156
|
+
```
|
|
157
|
+
Client 1: postgresql://localhost:8432/user123
|
|
158
|
+
Client 2: postgresql://localhost:8432/app456
|
|
159
|
+
Client 3: postgresql://localhost:8432/tenant789
|
|
160
|
+
↓
|
|
161
|
+
┌────────────────────────────────────────┐
|
|
162
|
+
│ Multi-Tenant Router (port 8432) │
|
|
163
|
+
│ - Parses connection database name │
|
|
164
|
+
│ - Routes to correct PGlite instance │
|
|
165
|
+
│ - Auto-provisions new databases │
|
|
166
|
+
└────────────────────────────────────────┘
|
|
167
|
+
↓
|
|
168
|
+
┌────────────────────────────────────────┐
|
|
169
|
+
│ Instance Pool │
|
|
170
|
+
│ ├─ user123 → PGlite('./data/user123') │
|
|
171
|
+
│ ├─ app456 → PGlite('./data/app456') │
|
|
172
|
+
│ └─ tenant789 → PGlite('./data/tenant789') │
|
|
173
|
+
└────────────────────────────────────────┘
|
|
174
|
+
```
|
|
175
|
+
|
|
176
|
+
### How It Works
|
|
177
|
+
|
|
178
|
+
1. **Client connects**: `postgresql://localhost:8432/myapp`
|
|
179
|
+
2. **Router parses** PostgreSQL startup message → extracts database name: `myapp`
|
|
180
|
+
3. **Pool checks** for existing PGlite instance for `myapp`
|
|
181
|
+
4. **Auto-provision** creates `./data/myapp/` if doesn't exist
|
|
182
|
+
5. **Route connection** to PGlite instance
|
|
183
|
+
6. **Client communicates** with isolated database
|
|
184
|
+
|
|
185
|
+
### Connection Lifecycle
|
|
186
|
+
|
|
187
|
+
- **First connection to DB**: PGlite instance created, database initialized
|
|
188
|
+
- **Subsequent connections**: Reuses existing PGlite instance
|
|
189
|
+
- **Concurrent connections**: Queued (PGlite is single-connection per instance)
|
|
190
|
+
- **Connection closes**: Instance unlocked, ready for next connection
|
|
191
|
+
|
|
192
|
+
## 📊 Performance
|
|
193
|
+
|
|
194
|
+
### vs Multiple Port Approach
|
|
195
|
+
|
|
196
|
+
| Approach | Ports Used | Management | Scalability |
|
|
197
|
+
|----------|-----------|------------|-------------|
|
|
198
|
+
| **Multi-tenant** | 1 | Auto | ✅ Excellent (100+ DBs) |
|
|
199
|
+
| Multi-port | 1 per DB | Manual | ⚠️ Limited (port exhaustion) |
|
|
200
|
+
|
|
201
|
+
### Benchmarks
|
|
202
|
+
|
|
203
|
+
- **DB creation**: ~50ms per database (lazy initialization)
|
|
204
|
+
- **Connection routing**: < 1ms overhead
|
|
205
|
+
- **Concurrent databases**: Tested with 100+ isolated instances
|
|
206
|
+
- **Memory**: ~10-30MB per PGlite instance (depends on data)
|
|
207
|
+
|
|
208
|
+
## 🔧 CLI Usage
|
|
209
|
+
|
|
210
|
+
### Install Globally
|
|
211
|
+
|
|
212
|
+
```bash
|
|
213
|
+
npm install -g pgserve
|
|
214
|
+
```
|
|
215
|
+
|
|
216
|
+
### Commands
|
|
217
|
+
|
|
218
|
+
```bash
|
|
219
|
+
# Start multi-tenant router
|
|
220
|
+
pgserve start --port 8432 --dir ./data
|
|
221
|
+
|
|
222
|
+
# Check router status
|
|
223
|
+
pgserve router-stats
|
|
224
|
+
|
|
225
|
+
# List all databases
|
|
226
|
+
pgserve list-databases
|
|
227
|
+
|
|
228
|
+
# Stop router
|
|
229
|
+
pgserve stop-router
|
|
230
|
+
```
|
|
231
|
+
|
|
232
|
+
## 🛠️ Advanced Usage
|
|
233
|
+
|
|
234
|
+
### Custom Instance Pool
|
|
235
|
+
|
|
236
|
+
```javascript
|
|
237
|
+
import { InstancePool } from 'pgserve';
|
|
238
|
+
|
|
239
|
+
const pool = new InstancePool({
|
|
240
|
+
baseDir: './databases',
|
|
241
|
+
maxInstances: 50,
|
|
242
|
+
autoProvision: true
|
|
243
|
+
});
|
|
244
|
+
|
|
245
|
+
// Get or create instance
|
|
246
|
+
const instance = await pool.getOrCreate('mydb');
|
|
247
|
+
|
|
248
|
+
// Access PGlite directly
|
|
249
|
+
const result = await instance.db.query('SELECT version()');
|
|
250
|
+
```
|
|
251
|
+
|
|
252
|
+
### Connection Queueing
|
|
253
|
+
|
|
254
|
+
PGlite is **single-connection** per instance. When multiple clients connect to the same database:
|
|
255
|
+
|
|
256
|
+
```javascript
|
|
257
|
+
// Client 1 connects to "mydb" → locks instance
|
|
258
|
+
const client1 = new pg.Client({ database: 'mydb', ... });
|
|
259
|
+
await client1.connect(); // ✅ Connected
|
|
260
|
+
|
|
261
|
+
// Client 2 tries to connect to "mydb" → queued
|
|
262
|
+
const client2 = new pg.Client({ database: 'mydb', ... });
|
|
263
|
+
await client2.connect(); // ⏳ Waits for client1 to disconnect
|
|
264
|
+
|
|
265
|
+
// Client 1 disconnects
|
|
266
|
+
await client1.end();
|
|
267
|
+
|
|
268
|
+
// Client 2 auto-connects
|
|
269
|
+
// ✅ Connected
|
|
270
|
+
```
|
|
271
|
+
|
|
272
|
+
Default timeout: **30 seconds**. Customize in `pool.acquire()`:
|
|
273
|
+
|
|
274
|
+
```javascript
|
|
275
|
+
await pool.acquire('mydb', socket, timeout = 60000); // 60s timeout
|
|
276
|
+
```
|
|
277
|
+
|
|
278
|
+
## 🔐 Security Notes
|
|
279
|
+
|
|
280
|
+
- **No authentication**: PGlite doesn't support auth (embedded use case)
|
|
281
|
+
- **Bind to localhost**: Default `127.0.0.1` (local only)
|
|
282
|
+
- **Production**: Use proper PostgreSQL for external access
|
|
283
|
+
|
|
284
|
+
## 📁 File Structure
|
|
285
|
+
|
|
286
|
+
```
|
|
287
|
+
./data/
|
|
288
|
+
├─ user123/ (PGlite data for "user123" database)
|
|
289
|
+
│ ├─ base/
|
|
290
|
+
│ ├─ pg_wal/
|
|
291
|
+
│ └─ PG_VERSION
|
|
292
|
+
├─ app456/ (PGlite data for "app456" database)
|
|
293
|
+
└─ tenant789/ (PGlite data for "tenant789" database)
|
|
294
|
+
```
|
|
295
|
+
|
|
296
|
+
## 🤝 Contributing
|
|
297
|
+
|
|
298
|
+
Contributions welcome! Please:
|
|
299
|
+
|
|
300
|
+
1. Fork the repository
|
|
301
|
+
2. Create a feature branch
|
|
302
|
+
3. Add tests for new features
|
|
303
|
+
4. Submit a pull request
|
|
304
|
+
|
|
305
|
+
## 📄 License
|
|
306
|
+
|
|
307
|
+
MIT License - Copyright (c) 2025 Namastex Labs
|
|
308
|
+
|
|
309
|
+
## 🙏 Credits
|
|
310
|
+
|
|
311
|
+
Built on top of:
|
|
312
|
+
- [@electric-sql/pglite](https://pglite.dev) - PostgreSQL WASM
|
|
313
|
+
- [@electric-sql/pglite-socket](https://www.npmjs.com/package/@electric-sql/pglite-socket) - Wire protocol server
|
|
314
|
+
|
|
315
|
+
## 📧 Support
|
|
316
|
+
|
|
317
|
+
- **Issues**: [GitHub Issues](https://github.com/namastexlabs/pglite-embedded-server/issues)
|
|
318
|
+
- **Email**: labs@namastex.com
|
|
319
|
+
- **Website**: [namastex.com](https://namastex.com)
|
|
320
|
+
|
|
321
|
+
---
|
|
322
|
+
|
|
323
|
+
**Made with ❤️ by [Namastex Labs](https://namastex.com)**
|