Skip to content

Commit 3949623

Browse files
authored
Merge pull request #36 from dev-five-git/claude/update-skill-readme-indexes-P2lFF
Update documentation to prefer inline constraints over table-level indexes
2 parents c90e2cb + 80e9a9a commit 3949623

2 files changed

Lines changed: 35 additions & 30 deletions

File tree

README.md

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -64,12 +64,11 @@ Models are JSON files in the `models/` directory:
6464
"name": "user",
6565
"columns": [
6666
{ "name": "id", "type": "integer", "nullable": false, "primary_key": true },
67-
{ "name": "email", "type": "text", "nullable": false, "unique": true },
67+
{ "name": "email", "type": "text", "nullable": false, "unique": true, "index": true },
6868
{ "name": "name", "type": "text", "nullable": false },
6969
{ "name": "created_at", "type": "timestamptz", "nullable": false, "default": "NOW()" }
7070
],
71-
"constraints": [],
72-
"indexes": []
71+
"constraints": []
7372
}
7473
```
7574

SKILL.md

Lines changed: 33 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
---
22
name: vespertide
3-
description: Define database schemas in JSON and generate migration plans. Use this skill when creating or modifying database models, defining tables with columns, constraints, indexes, and foreign keys for Vespertide-based projects.
3+
description: Define database schemas in JSON and generate migration plans. Use this skill when creating or modifying database models, defining tables with columns and inline constraints (primary_key, unique, index, foreign_key) for Vespertide-based projects.
44
---
55

66
# Vespertide Database Schema Definition
@@ -34,8 +34,7 @@ Models are JSON files in the `models/` directory:
3434
"$schema": "https://raw.githubusercontent.com/dev-five-git/vespertide/refs/heads/main/schemas/model.schema.json",
3535
"name": "table_name",
3636
"columns": [],
37-
"constraints": [],
38-
"indexes": []
37+
"constraints": []
3938
}
4039
```
4140

@@ -46,7 +45,8 @@ Models are JSON files in the `models/` directory:
4645
| `name` | string | Table name (snake_case) |
4746
| `columns` | array | Column definitions |
4847
| `constraints` | array | Table-level constraints (can be empty `[]`) |
49-
| `indexes` | array | Index definitions (can be empty `[]`) |
48+
49+
**Note**: The `indexes` field has been removed. Use inline `index` fields on columns instead (see Inline Constraints below).
5050

5151
## Column Definition
5252

@@ -188,13 +188,24 @@ Reference actions: `"Cascade"`, `"Restrict"`, `"SetNull"`, `"SetDefault"`, `"NoA
188188
]
189189
```
190190

191-
## Table-Level Indexes
191+
## Indexes
192+
193+
**Prefer inline indexes** on column definitions instead of table-level indexes:
192194

193195
```json
194-
"indexes": [
195-
{ "name": "idx_user_email", "columns": ["email"], "unique": false },
196-
{ "name": "idx_composite", "columns": ["user_id", "created_at"], "unique": false }
197-
]
196+
{
197+
"name": "email",
198+
"type": "text",
199+
"nullable": false,
200+
"index": true
201+
}
202+
```
203+
204+
For composite indexes, use the same index name on multiple columns:
205+
206+
```json
207+
{ "name": "user_id", "type": "integer", "nullable": false, "index": ["idx_user_date"] },
208+
{ "name": "created_at", "type": "timestamp", "nullable": false, "index": ["idx_user_date"] }
198209
```
199210

200211
## Examples
@@ -211,8 +222,7 @@ Reference actions: `"Cascade"`, `"Restrict"`, `"SetNull"`, `"SetDefault"`, `"NoA
211222
{ "name": "name", "type": "text", "nullable": false },
212223
{ "name": "created_at", "type": "timestamptz", "nullable": false, "default": "NOW()" }
213224
],
214-
"constraints": [],
215-
"indexes": []
225+
"constraints": []
216226
}
217227
```
218228

@@ -230,8 +240,7 @@ Reference actions: `"Cascade"`, `"Restrict"`, `"SetNull"`, `"SetDefault"`, `"NoA
230240
{ "name": "published", "type": "boolean", "nullable": false, "default": "false" },
231241
{ "name": "created_at", "type": "timestamptz", "nullable": false, "default": "NOW()" }
232242
],
233-
"constraints": [],
234-
"indexes": []
243+
"constraints": []
235244
}
236245
```
237246

@@ -251,8 +260,7 @@ Reference actions: `"Cascade"`, `"Restrict"`, `"SetNull"`, `"SetDefault"`, `"NoA
251260
],
252261
"constraints": [
253262
{ "type": "check", "name": "check_total_positive", "expr": "total_amount >= 0" }
254-
],
255-
"indexes": []
263+
]
256264
}
257265
```
258266

@@ -264,32 +272,30 @@ Reference actions: `"Cascade"`, `"Restrict"`, `"SetNull"`, `"SetDefault"`, `"NoA
264272
"name": "user_role",
265273
"columns": [
266274
{ "name": "user_id", "type": "integer", "nullable": false, "primary_key": true, "foreign_key": { "ref_table": "user", "ref_columns": ["id"], "on_delete": "Cascade" } },
267-
{ "name": "role_id", "type": "integer", "nullable": false, "primary_key": true, "foreign_key": { "ref_table": "role", "ref_columns": ["id"], "on_delete": "Cascade" } },
275+
{ "name": "role_id", "type": "integer", "nullable": false, "primary_key": true, "foreign_key": { "ref_table": "role", "ref_columns": ["id"], "on_delete": "Cascade" }, "index": true },
268276
{ "name": "assigned_at", "type": "timestamptz", "nullable": false, "default": "NOW()" }
269277
],
270-
"constraints": [],
271-
"indexes": [
272-
{ "name": "idx_user_role_role", "columns": ["role_id"], "unique": false }
273-
]
278+
"constraints": []
274279
}
275280
```
276281

277282
## Guidelines
278283

279284
1. **Always include `$schema`** for IDE validation and autocompletion
280285
2. **Always specify `nullable`** on every column
281-
3. **Always include empty arrays** for `constraints` and `indexes` even if unused
282-
4. **Add indexes on foreign key columns** for query performance
283-
5. **Use named constraints** (especially CHECK) for easier management
284-
6. **Naming conventions**:
286+
3. **Always include empty array** for `constraints` even if unused
287+
4. **Prefer inline constraints** (`primary_key`, `unique`, `index`, `foreign_key`) over table-level definitions
288+
5. **Use inline `index` on foreign key columns** for query performance (e.g., `"index": true`)
289+
6. **Use named constraints** (especially CHECK) for easier management
290+
7. **Naming conventions**:
285291
- Tables: `snake_case` (e.g., `user_role`)
286292
- Columns: `snake_case` (e.g., `created_at`)
287293
- Indexes: `idx_{table}_{columns}`
288294
- Unique constraints: `uq_{table}_{columns}`
289295
- Foreign keys: `fk_{table}_{ref_table}`
290296
- Check constraints: `check_{description}`
291-
7. **Timestamp columns**:
297+
8. **Timestamp columns**:
292298
- `created_at`: `"default": "NOW()"`, `nullable: false`
293299
- `updated_at`: `nullable: true` (managed by application)
294-
8. **Boolean defaults**: Use string format `"true"` or `"false"`
295-
9. **Adding NOT NULL columns** to existing tables requires either a `default` value or `fill_with` in migration
300+
9. **Boolean defaults**: Use string format `"true"` or `"false"`
301+
10. **Adding NOT NULL columns** to existing tables requires either a `default` value or `fill_with` in migration

0 commit comments

Comments
 (0)