postgresdk 0.1.1-alpha.0 → 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/README.md CHANGED
@@ -1,15 +1,414 @@
1
- # /workspace
1
+ # postgresdk
2
2
 
3
- To install dependencies:
3
+ Generate a fully-typed, production-ready SDK from your PostgreSQL database schema. Automatically creates both server-side REST API routes and client-side SDK with TypeScript types, Zod validation, and support for complex relationships.
4
+
5
+ ## Features
6
+
7
+ - 🚀 **Instant SDK Generation** - Point at your PostgreSQL database and get a complete SDK
8
+ - 🔒 **Type Safety** - Full TypeScript types derived from your database schema
9
+ - ✅ **Runtime Validation** - Zod schemas for request/response validation
10
+ - 🔗 **Smart Relationships** - Automatic handling of 1:N and M:N relationships with eager loading
11
+ - 🔐 **Built-in Auth** - API key and JWT authentication with zero configuration
12
+ - 🎯 **Zero Config** - Works out of the box with sensible defaults
13
+ - 🏗️ **Framework Ready** - Server routes built for Hono, client SDK works anywhere
14
+ - 📦 **Lightweight** - Minimal dependencies, optimized for production
15
+
16
+ ## Installation
17
+
18
+ ```bash
19
+ npm install -g postgresdk
20
+ # or
21
+ npx postgresdk
22
+ ```
23
+
24
+ ## Quick Start
25
+
26
+ 1. Create a configuration file `postgresdk.config.ts`:
27
+
28
+ ```typescript
29
+ export default {
30
+ connectionString: "postgres://user:pass@localhost:5432/mydb",
31
+ schema: "public",
32
+ outServer: "./generated/server",
33
+ outClient: "./generated/client",
34
+ };
35
+ ```
36
+
37
+ 2. Run the generator:
4
38
 
5
39
  ```bash
40
+ postgresdk
41
+ ```
42
+
43
+ 3. Use the generated SDK:
44
+
45
+ ```typescript
46
+ // Server (Hono)
47
+ import { Hono } from "hono";
48
+ import { Client } from "pg";
49
+ import { registerUsersRoutes } from "./generated/server/routes/users";
50
+
51
+ const app = new Hono();
52
+ const pg = new Client({ connectionString: "..." });
53
+ await pg.connect();
54
+
55
+ registerUsersRoutes(app, { pg });
56
+
57
+ // Client
58
+ import { SDK } from "./generated/client";
59
+
60
+ const sdk = new SDK({ baseUrl: "http://localhost:3000" });
61
+
62
+ // Full CRUD operations with TypeScript types
63
+ const user = await sdk.users.create({ name: "Alice", email: "alice@example.com" });
64
+ const users = await sdk.users.list({ include: { posts: true } });
65
+ await sdk.users.update(user.id, { name: "Alice Smith" });
66
+ await sdk.users.delete(user.id);
67
+ ```
68
+
69
+ ## Configuration
70
+
71
+ Create a `postgresdk.config.ts` file in your project root:
72
+
73
+ ```typescript
74
+ export default {
75
+ // Required
76
+ connectionString: process.env.DATABASE_URL || "postgres://user:pass@localhost:5432/dbname",
77
+
78
+ // Optional (with defaults)
79
+ schema: "public", // Database schema to introspect
80
+ outServer: "./generated/server", // Server code output directory
81
+ outClient: "./generated/client", // Client SDK output directory
82
+ softDeleteColumn: null, // Column name for soft deletes (e.g., "deleted_at")
83
+ includeDepthLimit: 3, // Max depth for nested includes
84
+ dateType: "date", // "date" | "string" - How to handle timestamps
85
+
86
+ // Authentication (optional)
87
+ auth: {
88
+ strategy: "none" | "api-key" | "jwt-hs256", // Default: "none"
89
+
90
+ // For API key auth
91
+ apiKeyHeader: "x-api-key", // Header name for API key
92
+ apiKeys: ["key1", "key2"], // Array of valid keys
93
+
94
+ // For JWT auth (HS256)
95
+ jwt: {
96
+ sharedSecret: "your-secret", // Shared secret for HS256
97
+ issuer: "your-app", // Optional: validate issuer claim
98
+ audience: "your-audience" // Optional: validate audience claim
99
+ }
100
+ }
101
+ };
102
+ ```
103
+
104
+ Environment variables work directly in the config file - no function wrapper needed.
105
+
106
+ ## Generated SDK Features
107
+
108
+ ### CRUD Operations
109
+
110
+ Every table gets a complete set of CRUD operations:
111
+
112
+ ```typescript
113
+ // Create
114
+ const user = await sdk.users.create({ name: "Bob", email: "bob@example.com" });
115
+
116
+ // Read
117
+ const user = await sdk.users.getByPk(123);
118
+ const users = await sdk.users.list();
119
+
120
+ // Update
121
+ const updated = await sdk.users.update(123, { name: "Robert" });
122
+
123
+ // Delete
124
+ const deleted = await sdk.users.delete(123);
125
+ ```
126
+
127
+ ### Relationships & Eager Loading
128
+
129
+ Automatically handles relationships with the `include` parameter:
130
+
131
+ ```typescript
132
+ // 1:N relationship - Get authors with their books
133
+ const authors = await sdk.authors.list({
134
+ include: { books: true }
135
+ });
136
+
137
+ // M:N relationship - Get books with their tags
138
+ const books = await sdk.books.list({
139
+ include: { tags: true }
140
+ });
141
+
142
+ // Nested includes - Get authors with books and their tags
143
+ const authors = await sdk.authors.list({
144
+ include: {
145
+ books: {
146
+ include: {
147
+ tags: true
148
+ }
149
+ }
150
+ }
151
+ });
152
+ ```
153
+
154
+ ### Filtering & Pagination
155
+
156
+ ```typescript
157
+ const users = await sdk.users.list({
158
+ where: { status: "active" },
159
+ orderBy: "created_at",
160
+ order: "desc",
161
+ limit: 20,
162
+ offset: 40
163
+ });
164
+ ```
165
+
166
+ ### Type Safety
167
+
168
+ All operations are fully typed based on your database schema:
169
+
170
+ ```typescript
171
+ // TypeScript will enforce correct types
172
+ const user = await sdk.users.create({
173
+ name: "Alice", // ✅ string required
174
+ email: "alice@...", // ✅ string required
175
+ age: "30" // ❌ Type error: should be number
176
+ });
177
+ ```
178
+
179
+ ## Authentication
180
+
181
+ postgresdk supports three authentication strategies out of the box:
182
+
183
+ ### No Authentication (Default)
184
+
185
+ ```typescript
186
+ // postgresdk.config.ts
187
+ export default {
188
+ connectionString: "...",
189
+ // No auth config needed - routes are unprotected
190
+ };
191
+ ```
192
+
193
+ ### API Key Authentication
194
+
195
+ ```typescript
196
+ // postgresdk.config.ts
197
+ export default {
198
+ connectionString: "...",
199
+ auth: {
200
+ strategy: "api-key",
201
+ apiKeyHeader: "x-api-key", // Optional, defaults to "x-api-key"
202
+ apiKeys: [
203
+ "your-api-key-1",
204
+ "your-api-key-2",
205
+ // Can also use environment variables
206
+ "env:API_KEYS" // Reads comma-separated keys from process.env.API_KEYS
207
+ ]
208
+ }
209
+ };
210
+
211
+ // Client SDK usage
212
+ const sdk = new SDK({
213
+ baseUrl: "http://localhost:3000",
214
+ auth: { apiKey: "your-api-key-1" }
215
+ });
216
+ ```
217
+
218
+ ### JWT Authentication (HS256)
219
+
220
+ ```typescript
221
+ // postgresdk.config.ts
222
+ export default {
223
+ connectionString: "...",
224
+ auth: {
225
+ strategy: "jwt-hs256",
226
+ jwt: {
227
+ sharedSecret: process.env.JWT_SECRET || "your-secret-key",
228
+ issuer: "my-app", // Optional: validates 'iss' claim
229
+ audience: "my-users" // Optional: validates 'aud' claim
230
+ }
231
+ }
232
+ };
233
+
234
+ // Client SDK usage with static token
235
+ const sdk = new SDK({
236
+ baseUrl: "http://localhost:3000",
237
+ auth: { jwt: "eyJhbGciOiJIUzI1NiIs..." }
238
+ });
239
+
240
+ // Or with dynamic token provider
241
+ const sdk = new SDK({
242
+ baseUrl: "http://localhost:3000",
243
+ auth: {
244
+ jwt: async () => {
245
+ // Refresh token if needed
246
+ return await getAccessToken();
247
+ }
248
+ }
249
+ });
250
+
251
+ // Or with custom auth headers
252
+ const sdk = new SDK({
253
+ baseUrl: "http://localhost:3000",
254
+ auth: async () => ({
255
+ "Authorization": `Bearer ${await getToken()}`,
256
+ "X-Tenant-ID": "tenant-123"
257
+ })
258
+ });
259
+ ```
260
+
261
+ ### Environment Variables in Auth Config
262
+
263
+ The auth configuration supports environment variables with the `env:` prefix:
264
+
265
+ ```typescript
266
+ export default {
267
+ auth: {
268
+ strategy: "api-key",
269
+ apiKeys: ["env:API_KEYS"], // Reads from process.env.API_KEYS
270
+
271
+ // Or for JWT
272
+ strategy: "jwt-hs256",
273
+ jwt: {
274
+ sharedSecret: "env:JWT_SECRET" // Reads from process.env.JWT_SECRET
275
+ }
276
+ }
277
+ };
278
+ ```
279
+
280
+ ### How Auth Works
281
+
282
+ When authentication is configured:
283
+
284
+ 1. **Server Side**: All generated routes are automatically protected with the configured auth middleware
285
+ 2. **Client Side**: The SDK handles auth headers transparently
286
+ 3. **Type Safety**: Auth configuration is fully typed
287
+ 4. **Zero Overhead**: When `strategy: "none"`, no auth code is included
288
+
289
+ ### JWT Token Generation Example
290
+
291
+ ```typescript
292
+ // Install jose for JWT generation: npm install jose
293
+ import { SignJWT } from 'jose';
294
+
295
+ const secret = new TextEncoder().encode('your-secret-key');
296
+
297
+ const token = await new SignJWT({
298
+ sub: 'user123',
299
+ email: 'user@example.com',
300
+ roles: ['admin']
301
+ })
302
+ .setProtectedHeader({ alg: 'HS256' })
303
+ .setIssuer('my-app')
304
+ .setAudience('my-users')
305
+ .setExpirationTime('2h')
306
+ .sign(secret);
307
+
308
+ // Use with SDK
309
+ const sdk = new SDK({
310
+ baseUrl: "http://localhost:3000",
311
+ auth: { jwt: token }
312
+ });
313
+ ```
314
+
315
+ ## Server Integration
316
+
317
+ The generated server code is designed for [Hono](https://hono.dev/) but can be adapted to other frameworks:
318
+
319
+ ```typescript
320
+ import { Hono } from "hono";
321
+ import { serve } from "@hono/node-server";
322
+ import { Client } from "pg";
323
+
324
+ // Import generated route registrations
325
+ import { registerUsersRoutes } from "./generated/server/routes/users";
326
+ import { registerPostsRoutes } from "./generated/server/routes/posts";
327
+
328
+ const app = new Hono();
329
+ const pg = new Client({ connectionString: process.env.DATABASE_URL });
330
+ await pg.connect();
331
+
332
+ // Register routes
333
+ registerUsersRoutes(app, { pg });
334
+ registerPostsRoutes(app, { pg });
335
+
336
+ // Start server
337
+ serve({ fetch: app.fetch, port: 3000 });
338
+ ```
339
+
340
+ ## CLI Options
341
+
342
+ ```bash
343
+ postgresdk [options]
344
+
345
+ Options:
346
+ -c, --config <path> Path to config file (default: postgresdk.config.ts)
347
+ -v, --version Show version
348
+ -h, --help Show help
349
+ ```
350
+
351
+ ## How It Works
352
+
353
+ 1. **Introspection** - Connects to your PostgreSQL database and reads the schema
354
+ 2. **Relationship Detection** - Analyzes foreign keys to understand table relationships
355
+ 3. **Code Generation** - Generates TypeScript code for:
356
+ - Type definitions from table schemas
357
+ - Zod validation schemas
358
+ - REST API route handlers
359
+ - Client SDK with full typing
360
+ - Include/eager-loading system
361
+ 4. **Output** - Writes generated files to specified directories
362
+
363
+ ## Requirements
364
+
365
+ - Node.js 20+
366
+ - PostgreSQL 12+
367
+ - TypeScript project (for using generated code)
368
+ - Optional: `jose` package for JWT authentication (auto-installed when using JWT auth)
369
+
370
+ ## Development
371
+
372
+ ```bash
373
+ # Clone the repository
374
+ git clone https://github.com/adpharm/postgresdk.git
375
+ cd postgresdk
376
+
377
+ # Install dependencies
6
378
  bun install
379
+
380
+ # Run tests (starts PostgreSQL in Docker)
381
+ bun test
382
+
383
+ # Build
384
+ bun run build
385
+
386
+ # Publish new version
387
+ ./publish.sh
7
388
  ```
8
389
 
9
- To run:
390
+ ## Testing
391
+
392
+ The test suite automatically manages a PostgreSQL Docker container:
10
393
 
11
394
  ```bash
12
- bun run index.ts
395
+ bun test
13
396
  ```
14
397
 
15
- This project was created using `bun init` in bun v1.2.19. [Bun](https://bun.com) is a fast all-in-one JavaScript runtime.
398
+ Tests cover:
399
+ - CRUD operations for all entities
400
+ - 1:N and M:N relationships
401
+ - Nested includes
402
+ - Validation and error handling
403
+
404
+ ## License
405
+
406
+ MIT
407
+
408
+ ## Contributing
409
+
410
+ Contributions are welcome! Please feel free to submit a Pull Request.
411
+
412
+ ## Support
413
+
414
+ For issues and feature requests, please [create an issue](https://github.com/adpharm/postgresdk/issues).