d1-kyt 0.9.4 → 0.9.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
@@ -3,7 +3,7 @@
3
3
  Type-safe [Cloudflare D1](https://developers.cloudflare.com/d1/) toolkit built on [Kysely](https://kysely.dev/) and [Valibot](https://valibot.dev/). Define your schema once in Valibot — get SQL migrations and fully-typed queries with no code generation.
4
4
 
5
5
  ```typescript
6
- import { defineTable, InferDB, createQueryBuilder, queryAll, queryFirst, queryRun } from 'd1-kyt';
6
+ import { defineTable, defineIndex, InferDB, createQueryBuilder, queryAll, queryFirst } from 'd1-kyt';
7
7
  import * as v from 'valibot';
8
8
 
9
9
  export const users = defineTable('users', {
@@ -18,9 +18,10 @@ export const posts = defineTable('posts', {
18
18
  authorId: v.pipe(v.number(), v.integer()),
19
19
  }, {
20
20
  foreignKeys: [{ columns: ['authorId'], references: users }],
21
- indexes: [{ columns: ['title'], unique: true }],
22
21
  });
23
22
 
23
+ export const postsTitleIdx = defineIndex(posts, ['title'], { unique: true });
24
+
24
25
  export type DB = InferDB<{ users: typeof users; posts: typeof posts }>;
25
26
  export const db = createQueryBuilder<DB>();
26
27
 
@@ -127,7 +128,13 @@ export const posts = defineTable('posts', {
127
128
  title: v.string(),
128
129
  categoryId: v.pipe(v.number(), v.integer()),
129
130
  }, {
130
- foreignKeys: [{ columns: ['categoryId'], references: categories, onDelete: 'CASCADE' }],
131
+ foreignKeys: [{
132
+ columns: ['categoryId'],
133
+ references: categories,
134
+ refColumns: ['id'], // optional — defaults to the referenced table's PK
135
+ onDelete: 'CASCADE', // CASCADE | SET NULL | RESTRICT | NO ACTION
136
+ onUpdate: 'NO ACTION',
137
+ }],
131
138
  });
132
139
  ```
133
140
 
@@ -141,6 +148,30 @@ deptId: v.optional(v.pipe(v.number(), v.integer())) // ✓ nullable allows inli
141
148
 
142
149
  ---
143
150
 
151
+ ## Indexes
152
+
153
+ ```typescript
154
+ // Basic unique index
155
+ export const postsSlugIdx = defineIndex(posts, ['slug'], { unique: true });
156
+
157
+ // Composite index
158
+ export const postsAuthorViewsIdx = defineIndex(posts, ['authorId', 'views']);
159
+
160
+ // Partial index — only indexes rows matching the WHERE clause
161
+ export const postsPublishedIdx = defineIndex(posts, ['createdAt'], {
162
+ where: 'published = 1',
163
+ });
164
+
165
+ // Custom index name
166
+ export const postsSearchIdx = defineIndex(posts, ['title'], {
167
+ name: 'posts_title_fts_idx',
168
+ });
169
+ ```
170
+
171
+ Columns are type-checked against the table definition at compile time.
172
+
173
+ ---
174
+
144
175
  ## CLI
145
176
 
146
177
  ```bash
@@ -197,7 +228,7 @@ await queryAll(env.DB, query, undefined, []); // disable all checks
197
228
  | Export | Description |
198
229
  |--------|-------------|
199
230
  | `defineTable(name, columns, opts?)` | Define a table; returns `SchemaTable` with `$inferSelect` / `$inferInsert` |
200
- | `defineIndex(table, columns, opts?)` | Define an index (columns are type-checked) |
231
+ | `defineIndex(table, columns, opts?)` | Define an index; columns are type-checked. `opts`: `unique`, `name`, `where` (partial index) |
201
232
  | `defineTrigger(name, opts)` | Define a custom trigger |
202
233
  | `InferDB<Tables>` | Infer a Kysely-compatible `DB` type |
203
234
 
package/dist/cli.js CHANGED
@@ -1,7 +1,7 @@
1
1
  #!/usr/bin/env node
2
2
  import { existsSync, mkdirSync, readdirSync, readFileSync, writeFileSync } from 'node:fs';
3
3
  import { dirname, join, resolve } from 'node:path';
4
- const VERSION = '0.9.4';
4
+ const VERSION = '0.9.5';
5
5
  const HELP = `
6
6
  d1-kyt v${VERSION} - Opinionated Cloudflare D1 + Kysely toolkit
7
7
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "d1-kyt",
3
- "version": "0.9.4",
3
+ "version": "0.9.5",
4
4
  "description": "Opinionated Cloudflare D1 + Kysely toolkit",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",
@@ -16,7 +16,7 @@ schema.ts → schema:diff → .sql migration → wrangler apply → type
16
16
  ## 1. Define Schema
17
17
 
18
18
  ```typescript
19
- import { defineTable } from 'd1-kyt';
19
+ import { defineTable, defineIndex } from 'd1-kyt';
20
20
  import * as v from 'valibot';
21
21
 
22
22
  export const posts = defineTable(
@@ -33,10 +33,20 @@ export const posts = defineTable(
33
33
  categoryId: v.pipe(v.number(), v.integer()),
34
34
  },
35
35
  {
36
- foreignKeys: [{ columns: ['categoryId'], references: categories, onDelete: 'CASCADE' }],
37
- indexes: [{ columns: ['slug'], unique: true }],
36
+ foreignKeys: [{
37
+ columns: ['categoryId'],
38
+ references: categories,
39
+ refColumns: ['id'], // optional, defaults to referenced table's PK
40
+ onDelete: 'CASCADE', // CASCADE | SET NULL | RESTRICT | NO ACTION
41
+ onUpdate: 'NO ACTION', // same options
42
+ }],
38
43
  }
39
44
  );
45
+
46
+ // Indexes are defined separately with defineIndex (NOT inside defineTable options)
47
+ export const postsSlugIdx = defineIndex(posts, ['slug'], { unique: true });
48
+ export const postsPublishedIdx = defineIndex(posts, ['views'], { where: 'published = 1' }); // partial index
49
+ export const postsCustomIdx = defineIndex(posts, ['title'], { name: 'posts_title_search_idx' });
40
50
  ```
41
51
 
42
52
  **Column type mapping:**