@shyk/kadak 0.1.0 → 0.1.5

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,8 +1,8 @@
1
1
  # Kadak ☕️
2
2
 
3
- **The strongest TypeScript ORM for PostgreSQL. Period.**
3
+ **The PostgreSQL ORM that feels invisible to beginners and intelligent to experts.**
4
4
 
5
- Kadak (pronounced *Ka-dak*) is built for developers who find Drizzle too verbose and Prisma too heavy. It's a thin, type-safe layer over PostgreSQL that prioritizes **Developer Experience (DX)** above everything else.
5
+ Kadak (pronounced *Ka-dak*) is built for developers who want plain JavaScript ergonomics with production-grade PostgreSQL power. It keeps the common path simple, but still exposes raw SQL and typed validators when you need to push harder.
6
6
 
7
7
  [kadak.shyk.in](https://kadak.shyk.in) | [Documentation](https://kadak.shyk.in/docs) | [npm](https://www.npmjs.com/package/kadak)
8
8
 
@@ -14,13 +14,12 @@ Drizzle is great, but it has friction. Drizzle makes you repeat yourself (`'id',
14
14
 
15
15
  **Kadak solves this.**
16
16
 
17
- * **Required by Default**: Columns are NOT NULL unless you explicitly say `.optional()`.
18
- * **Zero Repetition**: No more writing column names twice.
19
- * **Built-in Zod**: Table schemas auto-generate Zod validators for Insert, Update, and Select.
20
- * **Modern PostgreSQL**: Defaults to `IDENTITY` columns (modern standard) instead of legacy `SERIAL`.
21
- * **Automatic Mapping**: Write `camelCase` in TS, get `snake_case` in PG. No mapping manual effort.
22
- * **Soft Deletes & AutoUpdate**: First-class support for `deleted_at` and `updated_at` patterns.
23
- * **Lightweight**: Only two runtime dependencies: `postgres.js` and `zod`.
17
+ * **Simple Mode First**: Define tables with string shorthand like `id`, `email`, and `int?`.
18
+ * **Hybrid Escape Hatch**: Mix simple strings with builders like `kadak.email().unique()`.
19
+ * **Plain Object Queries**: `db.users.findMany({ active: true, $limit: 50 })`
20
+ * **Built-in Zod**: Table schemas generate insert, update, and select validators.
21
+ * **Analyzer Warnings**: Kadak warns on risky queries without blocking them.
22
+ * **Raw SQL Always Available**: `db.sql\`SELECT * FROM users\``
24
23
 
25
24
  ---
26
25
 
@@ -36,14 +35,15 @@ pnpm add @shyk/kadak postgres zod
36
35
  import { table, kadak, type Infer } from '@shyk/kadak'
37
36
 
38
37
  export const users = table('users', {
39
- id: kadak.id(), // IDENTITY Primary Key
40
- name: kadak.text().required().max(100),
41
- email: kadak.email().unique(),
42
- age: kadak.int().optional(),
43
- balance: kadak.decimal(), // Precision safe (returns string)
44
- createdAt: kadak.timestamp().default('now'),
45
- updatedAt: kadak.timestamp().autoUpdate(),
46
- deletedAt: kadak.timestamp().softDelete(),
38
+ id: 'id',
39
+ email: 'email',
40
+ name: 'text',
41
+ age: 'int?',
42
+ balance: kadak.decimal(),
43
+ isActive: 'boolean',
44
+ }, {
45
+ timestamps: true,
46
+ softDelete: true,
47
47
  })
48
48
 
49
49
  export type User = Infer<typeof users>
@@ -57,34 +57,108 @@ import { users } from './schema'
57
57
 
58
58
  const db = connect(process.env.DATABASE_URL!, { users })
59
59
 
60
- // Type-safe queries with automatic snake_case mapping
60
+ // Top-level object = filter
61
61
  const allUsers = await db.users.findMany({
62
- where: { isActive: true },
63
- orderBy: { createdAt: 'desc' },
64
- limit: 10
62
+ isActive: true,
63
+ $order: { createdAt: 'desc' },
64
+ $limit: 10,
65
65
  })
66
66
 
67
- // Validation included
68
- const result = users.validator().safeParse(somePayload)
69
- if (result.success) {
70
- await db.users.insert(result.data)
71
- }
67
+ const firstUser = await db.users.findFirst({ email: 'hello@kadak.dev' })
68
+ const updated = await db.users.update({ id: 1 }, { isActive: false })
69
+ await db.users.delete({ id: 1 })
70
+
71
+ const result = users.insertValidator().safeParse(somePayload)
72
+ if (result.success) await db.users.insert(result.data)
73
+
74
+ await db.transaction(async (tx) => {
75
+ await tx.users.update({ id: 1 }, { isActive: false })
76
+ await tx.users.insert({ email: 'new@kadak.dev', name: 'New User', isActive: true })
77
+ })
78
+ ```
79
+
80
+ ### 3. Runtime Controls
81
+
82
+ ```ts
83
+ const db = connect({
84
+ url: process.env.DATABASE_URL!,
85
+ readReplicas: [process.env.READ_REPLICA_URL!],
86
+ debug: true,
87
+ warnings: 'relaxed', // 'relaxed' | 'strict' | 'silent'
88
+ retryAttempts: 2,
89
+ retryDelayMs: 200,
90
+ retryOnCodes: ['08006', '08001', '57P01'],
91
+ retryWrites: false,
92
+ defaultLimit: 100,
93
+ validateResults: true,
94
+ slowQueryMs: 250,
95
+ largeResultRows: 1000,
96
+ repeatedQueryThreshold: 25,
97
+ }, { users })
72
98
  ```
73
99
 
100
+ `retryAttempts` defaults to `0` (no retry). `retryWrites` defaults to `false`, so only `SELECT` retries are enabled unless you explicitly opt in.
101
+
102
+ ### 4. Migrations
103
+
104
+ ```ts
105
+ import { createMigration, runMigrations } from '@shyk/kadak'
106
+
107
+ const filePath = await createMigration('create_users_table')
108
+ console.log('Created:', filePath)
109
+
110
+ await runMigrations({
111
+ url: process.env.DATABASE_URL!,
112
+ dir: './migrations',
113
+ })
114
+ ```
115
+
116
+ ### 5. Observability
117
+
118
+ ```ts
119
+ import { KadakMetrics, connect } from '@shyk/kadak'
120
+
121
+ const metrics = new KadakMetrics()
122
+
123
+ const db = connect({
124
+ url: process.env.DATABASE_URL!,
125
+ metrics,
126
+ onQuery: (event) => {
127
+ if (event.durationMs > 300) console.log('slow query', event.sql)
128
+ },
129
+ explainAnalyze: true,
130
+ explainThresholdMs: 300,
131
+ }, { users })
132
+
133
+ console.log(metrics.snapshot())
134
+ console.log(metrics.exportPrometheus())
135
+ ```
136
+
137
+ ### 6. Soak Benchmark
138
+
139
+ ```bash
140
+ BENCH_TOTAL=1000 BENCH_CONCURRENCY=50 pnpm exec tsx benchmark/soak.ts
141
+ ```
142
+
143
+ ### 7. Compatibility and Production Checklist
144
+
145
+ See [PRODUCTION_CHECKLIST.md](./PRODUCTION_CHECKLIST.md) before launch.
146
+ See [COMPATIBILITY.md](./COMPATIBILITY.md) for versioning guarantees.
147
+
74
148
  ---
75
149
 
76
150
  ## Features
77
151
 
78
152
  | Feature | Kadak | Drizzle |
79
153
  | --- | --- | --- |
80
- | **Default Context** | Required (Safe) | Nullable (Prone to bugs) |
81
- | **Column Naming** | Auto `snake_case` | Manual `name('name')` |
154
+ | **Schema Start** | String shorthand | Builder-heavy |
155
+ | **Column Naming** | Auto `snake_case` | Manual mapping |
82
156
  | **Validation** | First-class Zod | Separate packages |
83
- | **Soft Delete** | Native `.softDelete()` | Manual WHERE clauses |
84
- | **Primary Keys** | `IDENTITY` (Modern) | `SERIAL` (Legacy) |
157
+ | **Query Shape** | Plain object filters | More ceremony |
158
+ | **Escape Hatch** | Raw `postgres.js` | Varies |
85
159
 
86
160
  ---
87
161
 
88
162
  ## License
89
163
 
90
- MIT © [Shyam](https://github.com/shyk)
164
+ MIT © [Shyam](https://github.com/shyamkuldiya)