@outs-tand-ing/postgres 0.0.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/README.md +400 -0
- package/dist/index.d.ts +2 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +2 -0
- package/dist/index.js.map +1 -0
- package/dist/schemas/account.schema.d.ts +654 -0
- package/dist/schemas/account.schema.d.ts.map +1 -0
- package/dist/schemas/account.schema.js +52 -0
- package/dist/schemas/account.schema.js.map +1 -0
- package/dist/schemas/blueprint.schema.d.ts +820 -0
- package/dist/schemas/blueprint.schema.d.ts.map +1 -0
- package/dist/schemas/blueprint.schema.js +63 -0
- package/dist/schemas/blueprint.schema.js.map +1 -0
- package/dist/schemas/calendar.schema.d.ts +772 -0
- package/dist/schemas/calendar.schema.d.ts.map +1 -0
- package/dist/schemas/calendar.schema.js +62 -0
- package/dist/schemas/calendar.schema.js.map +1 -0
- package/dist/schemas/delivery.schema.d.ts +863 -0
- package/dist/schemas/delivery.schema.d.ts.map +1 -0
- package/dist/schemas/delivery.schema.js +65 -0
- package/dist/schemas/delivery.schema.js.map +1 -0
- package/dist/schemas/entry.schema.d.ts +717 -0
- package/dist/schemas/entry.schema.d.ts.map +1 -0
- package/dist/schemas/entry.schema.js +54 -0
- package/dist/schemas/entry.schema.js.map +1 -0
- package/dist/schemas/group.schema.d.ts +910 -0
- package/dist/schemas/group.schema.d.ts.map +1 -0
- package/dist/schemas/group.schema.js +67 -0
- package/dist/schemas/group.schema.js.map +1 -0
- package/dist/schemas/index.d.ts +9 -0
- package/dist/schemas/index.d.ts.map +1 -0
- package/dist/schemas/index.js +10 -0
- package/dist/schemas/index.js.map +1 -0
- package/dist/schemas/real.schema.d.ts +1144 -0
- package/dist/schemas/real.schema.d.ts.map +1 -0
- package/dist/schemas/real.schema.js +94 -0
- package/dist/schemas/real.schema.js.map +1 -0
- package/dist/schemas/timeline.schema.d.ts +356 -0
- package/dist/schemas/timeline.schema.d.ts.map +1 -0
- package/dist/schemas/timeline.schema.js +29 -0
- package/dist/schemas/timeline.schema.js.map +1 -0
- package/package.json +102 -0
package/README.md
ADDED
|
@@ -0,0 +1,400 @@
|
|
|
1
|
+
# Outs PostgreSQL Database
|
|
2
|
+
|
|
3
|
+
PostgreSQL 18 database setup with Drizzle ORM, matching all Mongoose schemas from the original MongoDB implementation.
|
|
4
|
+
|
|
5
|
+
## Features
|
|
6
|
+
|
|
7
|
+
- 🐘 PostgreSQL 18
|
|
8
|
+
- 🔥 Drizzle ORM
|
|
9
|
+
- 🐳 Docker & Docker Compose (dev + prod)
|
|
10
|
+
- 🌱 Seed scripts with demo users
|
|
11
|
+
- 🔐 Bcrypt password hashing
|
|
12
|
+
- 📊 Pre-built query functions with CLI commands
|
|
13
|
+
- 🎯 Type-safe schemas matching Mongoose models
|
|
14
|
+
|
|
15
|
+
## Quick Start
|
|
16
|
+
|
|
17
|
+
### 1. Install Dependencies
|
|
18
|
+
|
|
19
|
+
```bash
|
|
20
|
+
bun install
|
|
21
|
+
```
|
|
22
|
+
|
|
23
|
+
### 2. Set Up Environment
|
|
24
|
+
|
|
25
|
+
```bash
|
|
26
|
+
cp .env.example .env
|
|
27
|
+
```
|
|
28
|
+
|
|
29
|
+
Edit `.env` if needed (default is fine for local development).
|
|
30
|
+
|
|
31
|
+
### 3. Start PostgreSQL with Docker
|
|
32
|
+
|
|
33
|
+
```bash
|
|
34
|
+
bun run docker:up
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
This starts PostgreSQL 18 on `localhost:5432`.
|
|
38
|
+
|
|
39
|
+
### 4. Generate and Push Database Schema
|
|
40
|
+
|
|
41
|
+
```bash
|
|
42
|
+
# Generate migration files
|
|
43
|
+
bun run db:generate
|
|
44
|
+
|
|
45
|
+
# Push schema to database
|
|
46
|
+
bun run db:push
|
|
47
|
+
```
|
|
48
|
+
|
|
49
|
+
### 5. Seed the Database
|
|
50
|
+
|
|
51
|
+
```bash
|
|
52
|
+
bun run db:seed
|
|
53
|
+
```
|
|
54
|
+
|
|
55
|
+
This creates demo users with bcrypted passwords:
|
|
56
|
+
|
|
57
|
+
- `john.doe@example.com` / `password123`
|
|
58
|
+
- `jane.smith@example.com` / `securepass456`
|
|
59
|
+
- `admin@example.com` / `admin2024!`
|
|
60
|
+
- `bob.wilson@example.com` / `mypassword789`
|
|
61
|
+
- `alice.jones@example.com` / `alicepass2024`
|
|
62
|
+
|
|
63
|
+
### 6. Test Connection
|
|
64
|
+
|
|
65
|
+
```bash
|
|
66
|
+
bun run db:test
|
|
67
|
+
```
|
|
68
|
+
|
|
69
|
+
## Schema Overview
|
|
70
|
+
|
|
71
|
+
All schemas match the Mongoose models exactly:
|
|
72
|
+
|
|
73
|
+
### Account Module
|
|
74
|
+
|
|
75
|
+
- **Users** (`account_users`) - User accounts with bcrypt passwords, push devices, settings
|
|
76
|
+
- **Subscriptions** (`account_subscriptions`) - User subscriptions to seasons
|
|
77
|
+
- **Leagues** (`account_leagues`) - Leagues with previous versions support
|
|
78
|
+
|
|
79
|
+
### Blueprint Module
|
|
80
|
+
|
|
81
|
+
- **Blueprint Seasons** (`blueprint_seasons`) - Season blueprints
|
|
82
|
+
- **Blueprint Domains** (`blueprint_domains`) - Domain configurations
|
|
83
|
+
- **Blueprint Challenges** (`blueprint_challenges`) - Challenge templates
|
|
84
|
+
- **Blueprint Tournaments** (`blueprint_tournaments`) - Tournament configurations
|
|
85
|
+
|
|
86
|
+
### Calendar Module
|
|
87
|
+
|
|
88
|
+
- **Seasons** (`calendar_seasons`) - Active seasons
|
|
89
|
+
- **Stages** (`calendar_stages`) - Season stages
|
|
90
|
+
- **Rounds** (`calendar_rounds`) - Competition rounds with relevant users
|
|
91
|
+
|
|
92
|
+
### Entry Module
|
|
93
|
+
|
|
94
|
+
- **Challenges** (`entry_challenges`) - User challenges with fixture slots
|
|
95
|
+
- **Bets** (`entry_bets`) - User bets with previous versions support
|
|
96
|
+
|
|
97
|
+
### Group Module
|
|
98
|
+
|
|
99
|
+
- **Standings** (`group_standings`) - Group standings with history
|
|
100
|
+
- **Fixtures** (`group_fixtures`) - Group fixtures
|
|
101
|
+
- **Cursors** (`group_cursors`) - Cursor tracking for groups
|
|
102
|
+
|
|
103
|
+
### Real Module
|
|
104
|
+
|
|
105
|
+
- **Real Fixtures** (`real_fixtures`) - Real-world fixture data
|
|
106
|
+
- **Real Teams** (`real_teams`) - Team information
|
|
107
|
+
- **Real Players** (`real_players`) - Player data
|
|
108
|
+
- **Real Events** (`real_events`) - Match events
|
|
109
|
+
- **Real Channels** (`real_channels`) - Data channels
|
|
110
|
+
|
|
111
|
+
### Delivery Module
|
|
112
|
+
|
|
113
|
+
- **Notifications** (`delivery_notifications`) - Push notifications
|
|
114
|
+
- **Delivery Sessions** (`delivery_sessions`) - Delivery tracking
|
|
115
|
+
- **Live Activities** (`delivery_liveactivities`) - iOS Live Activities
|
|
116
|
+
|
|
117
|
+
### Timeline Module
|
|
118
|
+
|
|
119
|
+
- **Snapshots** (`timeline_snapshots`) - Timeline snapshots
|
|
120
|
+
|
|
121
|
+
## Key Differences from MongoDB
|
|
122
|
+
|
|
123
|
+
### Relationships
|
|
124
|
+
|
|
125
|
+
- MongoDB uses string references (`_user`, `_season`, etc.)
|
|
126
|
+
- PostgreSQL maintains the same string reference pattern for compatibility
|
|
127
|
+
- Use joins in queries when needed (Drizzle makes this easy)
|
|
128
|
+
|
|
129
|
+
### Embedded Documents
|
|
130
|
+
|
|
131
|
+
- MongoDB embedded documents → PostgreSQL JSONB columns
|
|
132
|
+
- Examples: `pushDevices`, `settings`, `fixtureSlots`, `rows`
|
|
133
|
+
|
|
134
|
+
### Arrays
|
|
135
|
+
|
|
136
|
+
- MongoDB arrays → PostgreSQL JSONB arrays for complex types
|
|
137
|
+
- Simple string arrays remain as TEXT[]
|
|
138
|
+
|
|
139
|
+
### Previous Versions
|
|
140
|
+
|
|
141
|
+
- MongoDB `prevs` array → PostgreSQL JSONB with `refPrevKey`
|
|
142
|
+
- Tables: `challenges`, `bets`, `leagues`
|
|
143
|
+
|
|
144
|
+
## CLI Query Commands
|
|
145
|
+
|
|
146
|
+
Run queries directly from the command line:
|
|
147
|
+
|
|
148
|
+
```bash
|
|
149
|
+
# List all users
|
|
150
|
+
bun run query:users
|
|
151
|
+
|
|
152
|
+
# Get user by ID or email
|
|
153
|
+
bun run src/query.ts user john.doe@example.com
|
|
154
|
+
bun run src/query.ts user user-john-doe
|
|
155
|
+
|
|
156
|
+
# Get user with their subscriptions
|
|
157
|
+
bun run src/query.ts user-subscriptions user-john-doe
|
|
158
|
+
|
|
159
|
+
# List all subscriptions
|
|
160
|
+
bun run query:subscriptions
|
|
161
|
+
|
|
162
|
+
# List all seasons
|
|
163
|
+
bun run query:seasons
|
|
164
|
+
|
|
165
|
+
# Search users
|
|
166
|
+
bun run src/query.ts search john
|
|
167
|
+
|
|
168
|
+
# Show statistics
|
|
169
|
+
bun run src/query.ts stats
|
|
170
|
+
```
|
|
171
|
+
|
|
172
|
+
## Query Functions
|
|
173
|
+
|
|
174
|
+
Import and use query functions in your code:
|
|
175
|
+
|
|
176
|
+
```typescript
|
|
177
|
+
import {
|
|
178
|
+
getAllUsers,
|
|
179
|
+
getUserBy,
|
|
180
|
+
getUserWithSubscriptions,
|
|
181
|
+
getAllSubscriptions,
|
|
182
|
+
getAllSeasons,
|
|
183
|
+
getUserBetsForRound,
|
|
184
|
+
getChallengesForRound,
|
|
185
|
+
getRealFixturesByDateRange,
|
|
186
|
+
getStandingsForSeason,
|
|
187
|
+
searchUsers,
|
|
188
|
+
getUserStats,
|
|
189
|
+
} from './src/query'
|
|
190
|
+
|
|
191
|
+
// Get all active users
|
|
192
|
+
const users = await getAllUsers({ status: 'active', limit: 10 })
|
|
193
|
+
|
|
194
|
+
// Get user by email
|
|
195
|
+
const user = await getUserBy('email', 'john.doe@example.com')
|
|
196
|
+
|
|
197
|
+
// Search users
|
|
198
|
+
const results = await searchUsers('john')
|
|
199
|
+
```
|
|
200
|
+
|
|
201
|
+
## Drizzle Studio
|
|
202
|
+
|
|
203
|
+
Visual database browser:
|
|
204
|
+
|
|
205
|
+
```bash
|
|
206
|
+
bun run db:studio
|
|
207
|
+
```
|
|
208
|
+
|
|
209
|
+
Opens at `https://local.drizzle.studio`
|
|
210
|
+
|
|
211
|
+
## Docker Commands
|
|
212
|
+
|
|
213
|
+
```bash
|
|
214
|
+
# Start dev database
|
|
215
|
+
bun run docker:up
|
|
216
|
+
|
|
217
|
+
# Stop dev database
|
|
218
|
+
bun run docker:down
|
|
219
|
+
|
|
220
|
+
# View logs
|
|
221
|
+
bun run docker:logs
|
|
222
|
+
|
|
223
|
+
# Start production database
|
|
224
|
+
bun run docker:prod:up
|
|
225
|
+
|
|
226
|
+
# Stop production database
|
|
227
|
+
bun run docker:prod:down
|
|
228
|
+
```
|
|
229
|
+
|
|
230
|
+
## Database Management
|
|
231
|
+
|
|
232
|
+
```bash
|
|
233
|
+
# Generate migration files
|
|
234
|
+
bun run db:generate
|
|
235
|
+
|
|
236
|
+
# Run migrations
|
|
237
|
+
bun run db:migrate
|
|
238
|
+
|
|
239
|
+
# Push schema directly (no migrations)
|
|
240
|
+
bun run db:push
|
|
241
|
+
|
|
242
|
+
# Clear all data
|
|
243
|
+
bun run src/migrations/clear.ts
|
|
244
|
+
|
|
245
|
+
# Re-seed database
|
|
246
|
+
bun run db:seed
|
|
247
|
+
```
|
|
248
|
+
|
|
249
|
+
## Production Deployment
|
|
250
|
+
|
|
251
|
+
1. Copy `docker-compose.prod.yml` to your server
|
|
252
|
+
2. Create `.env` file with secure credentials:
|
|
253
|
+
|
|
254
|
+
```env
|
|
255
|
+
POSTGRES_USER=your_user
|
|
256
|
+
POSTGRES_PASSWORD=your_secure_password
|
|
257
|
+
POSTGRES_DB=outs_prod
|
|
258
|
+
POSTGRES_PORT=5432
|
|
259
|
+
```
|
|
260
|
+
|
|
261
|
+
3. Start production container:
|
|
262
|
+
|
|
263
|
+
```bash
|
|
264
|
+
docker-compose -f docker-compose.prod.yml up -d
|
|
265
|
+
```
|
|
266
|
+
|
|
267
|
+
4. Run migrations:
|
|
268
|
+
|
|
269
|
+
```bash
|
|
270
|
+
DATABASE_URL=postgresql://user:pass@host:5432/db bun run db:push
|
|
271
|
+
```
|
|
272
|
+
|
|
273
|
+
## Publishing to npm
|
|
274
|
+
|
|
275
|
+
This package is designed to be published to npm as a shared schema library.
|
|
276
|
+
|
|
277
|
+
```bash
|
|
278
|
+
bun run publish:npm
|
|
279
|
+
```
|
|
280
|
+
|
|
281
|
+
This will:
|
|
282
|
+
1. Clean the dist directory
|
|
283
|
+
2. Build TypeScript declarations and JS files
|
|
284
|
+
3. Publish to npm with public access
|
|
285
|
+
|
|
286
|
+
### After publishing, update consuming packages:
|
|
287
|
+
|
|
288
|
+
```json
|
|
289
|
+
{
|
|
290
|
+
"dependencies": {
|
|
291
|
+
"@outs/postgres": "^1.0.0"
|
|
292
|
+
}
|
|
293
|
+
}
|
|
294
|
+
```
|
|
295
|
+
|
|
296
|
+
## Using in Your Application
|
|
297
|
+
|
|
298
|
+
### Import all schemas (not recommended for production):
|
|
299
|
+
|
|
300
|
+
```typescript
|
|
301
|
+
import { users, subscriptions, leagues } from '@outs/postgres'
|
|
302
|
+
```
|
|
303
|
+
|
|
304
|
+
### Import specific schemas (recommended for tree-shaking):
|
|
305
|
+
|
|
306
|
+
```typescript
|
|
307
|
+
// Only import account schemas (much smaller bundle)
|
|
308
|
+
import { users, type User, type PushDevice } from '@outs/postgres/schemas/account'
|
|
309
|
+
|
|
310
|
+
// Only import calendar schemas
|
|
311
|
+
import { seasons, stages, rounds } from '@outs/postgres/schemas/calendar'
|
|
312
|
+
|
|
313
|
+
// Only import real data schemas
|
|
314
|
+
import { fixtures, teams, players } from '@outs/postgres/schemas/real'
|
|
315
|
+
```
|
|
316
|
+
|
|
317
|
+
### Available schema modules for tree-shaking:
|
|
318
|
+
|
|
319
|
+
- `@outs/postgres/schemas/account` - users, subscriptions, leagues
|
|
320
|
+
- `@outs/postgres/schemas/blueprint` - seasons, domains, challenges, tournaments
|
|
321
|
+
- `@outs/postgres/schemas/calendar` - seasons, stages, rounds
|
|
322
|
+
- `@outs/postgres/schemas/entry` - challenges, bets
|
|
323
|
+
- `@outs/postgres/schemas/group` - standings, fixtures, cursors
|
|
324
|
+
- `@outs/postgres/schemas/real` - fixtures, teams, players, events, channels
|
|
325
|
+
- `@outs/postgres/schemas/delivery` - notifications, sessions, live activities
|
|
326
|
+
- `@outs/postgres/schemas/timeline` - snapshots
|
|
327
|
+
|
|
328
|
+
### Example: Using in Cloudflare Workers
|
|
329
|
+
|
|
330
|
+
```typescript
|
|
331
|
+
import { drizzle } from 'drizzle-orm/postgres-js'
|
|
332
|
+
import postgres from 'postgres'
|
|
333
|
+
import { users } from '@outs/postgres/schemas/account'
|
|
334
|
+
import { eq } from 'drizzle-orm'
|
|
335
|
+
|
|
336
|
+
export default {
|
|
337
|
+
async fetch(request: Request, env: Env) {
|
|
338
|
+
const client = postgres(env.DATABASE_URL)
|
|
339
|
+
const db = drizzle(client)
|
|
340
|
+
|
|
341
|
+
const user = await db
|
|
342
|
+
.select()
|
|
343
|
+
.from(users)
|
|
344
|
+
.where(eq(users.email, 'test@example.com'))
|
|
345
|
+
.limit(1)
|
|
346
|
+
|
|
347
|
+
await client.end()
|
|
348
|
+
return Response.json({ user })
|
|
349
|
+
}
|
|
350
|
+
}
|
|
351
|
+
```
|
|
352
|
+
|
|
353
|
+
### Example: Local database queries
|
|
354
|
+
|
|
355
|
+
```typescript
|
|
356
|
+
import { db } from '@outs/postgres'
|
|
357
|
+
import { users, eq } from '@outs/postgres'
|
|
358
|
+
|
|
359
|
+
// Query users
|
|
360
|
+
const allUsers = await db.select().from(users)
|
|
361
|
+
|
|
362
|
+
// Query with conditions
|
|
363
|
+
const user = await db.select().from(users).where(eq(users.email, 'john@example.com'))
|
|
364
|
+
|
|
365
|
+
// Insert
|
|
366
|
+
await db.insert(users).values({
|
|
367
|
+
id: 'user-new',
|
|
368
|
+
url: '/api/users/user-new',
|
|
369
|
+
email: 'new@example.com',
|
|
370
|
+
password: hashedPassword,
|
|
371
|
+
})
|
|
372
|
+
|
|
373
|
+
// Update
|
|
374
|
+
await db.update(users).set({ name: 'New Name' }).where(eq(users.id, 'user-123'))
|
|
375
|
+
|
|
376
|
+
// Delete
|
|
377
|
+
await db.delete(users).where(eq(users.id, 'user-123'))
|
|
378
|
+
```
|
|
379
|
+
|
|
380
|
+
## Type Safety
|
|
381
|
+
|
|
382
|
+
All tables have type-safe insert and select types:
|
|
383
|
+
|
|
384
|
+
```typescript
|
|
385
|
+
import type { User, NewUser } from '@outs/postgres'
|
|
386
|
+
|
|
387
|
+
// Select type (includes all fields including defaults)
|
|
388
|
+
const user: User = await db.select().from(users).where(eq(users.id, 'user-1'))
|
|
389
|
+
|
|
390
|
+
// Insert type (only required fields)
|
|
391
|
+
const newUser: NewUser = {
|
|
392
|
+
id: 'user-new',
|
|
393
|
+
url: '/api/users/user-new',
|
|
394
|
+
email: 'new@example.com',
|
|
395
|
+
}
|
|
396
|
+
```
|
|
397
|
+
|
|
398
|
+
## License
|
|
399
|
+
|
|
400
|
+
MIT
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,WAAW,CAAA"}
|
package/dist/index.js
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,WAAW,CAAA"}
|