d1-kyt 0.1.3 → 0.2.0
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 +79 -103
- package/dist/cli.js +1 -1
- package/dist/migrate.d.ts +33 -42
- package/dist/migrate.d.ts.map +1 -1
- package/dist/migrate.js +48 -72
- package/dist/migrate.js.map +1 -1
- package/package.json +9 -13
package/README.md
CHANGED
|
@@ -1,50 +1,68 @@
|
|
|
1
1
|
# d1-kyt
|
|
2
2
|
|
|
3
|
-
[](https://developers.cloudflare.com/d1/)
|
|
4
|
-
[](https://kysely.dev/)
|
|
5
|
-
[](https://www.npmjs.com/package/d1-kyt)
|
|
6
|
-
|
|
7
3
|
Opinionated [Cloudflare D1](https://developers.cloudflare.com/d1/) + [Kysely](https://kysely.dev/) toolkit.
|
|
8
4
|
|
|
9
|
-
Not an ORM, no magic, no runtime overhead. Just a wrapper with helpers that relies on Kysely's type inference.
|
|
10
|
-
|
|
11
5
|
**ky**(sely) + **t**(oolkit) = **kyt**
|
|
12
6
|
|
|
7
|
+
> **Not an ORM.** Thin wrapper with helpers that relies on Kysely's type inference. No magic, no runtime overhead.
|
|
13
8
|
|
|
14
|
-
##
|
|
9
|
+
## Migration DSL
|
|
15
10
|
|
|
16
|
-
```
|
|
17
|
-
|
|
11
|
+
```typescript
|
|
12
|
+
// d1-kyt/migrations/0001_create_user_table.ts
|
|
13
|
+
|
|
14
|
+
import { defineTable, createIndex } from 'd1-kyt/migrate';
|
|
15
|
+
|
|
16
|
+
const User = defineTable('User', (col) => ({
|
|
17
|
+
externalId: col.text().notNull(),
|
|
18
|
+
email: col.text().notNull(),
|
|
19
|
+
name: col.text(),
|
|
20
|
+
}));
|
|
21
|
+
|
|
22
|
+
export const migration = () => [
|
|
23
|
+
...User.sql,
|
|
24
|
+
createIndex(User, ['externalId'], { unique: true }),
|
|
25
|
+
createIndex(User, ['email'], { unique: true }),
|
|
26
|
+
];
|
|
18
27
|
```
|
|
19
28
|
|
|
20
|
-
|
|
29
|
+
### Customizing Auto Columns
|
|
21
30
|
|
|
22
|
-
```
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
31
|
+
```typescript
|
|
32
|
+
// Disable all auto columns
|
|
33
|
+
const Event = defineTable('Event', (col) => ({
|
|
34
|
+
uuid: col.text().notNull(),
|
|
35
|
+
name: col.text().notNull(),
|
|
36
|
+
}), { id: false, createdAt: false, updatedAt: false });
|
|
37
|
+
|
|
38
|
+
// Custom column names (snake_case)
|
|
39
|
+
const User = defineTable('user', (col) => ({
|
|
40
|
+
email: col.text().notNull(),
|
|
41
|
+
}), {
|
|
42
|
+
idColumn: 'user_id',
|
|
43
|
+
createdAtColumn: 'created_at',
|
|
44
|
+
updatedAtColumn: 'updated_at',
|
|
45
|
+
});
|
|
27
46
|
```
|
|
28
47
|
|
|
29
|
-
|
|
48
|
+
### Later Migrations
|
|
30
49
|
|
|
31
|
-
|
|
50
|
+
Use `createUseTable` for type-safe references to existing tables:
|
|
32
51
|
|
|
33
52
|
```typescript
|
|
34
|
-
|
|
53
|
+
import type { DB } from '../../db/generated';
|
|
54
|
+
import { createUseTable, addColumn, createIndex } from 'd1-kyt/migrate';
|
|
35
55
|
|
|
36
|
-
|
|
56
|
+
const useTable = createUseTable<DB>();
|
|
57
|
+
const User = useTable('User');
|
|
37
58
|
|
|
38
|
-
export
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
});
|
|
59
|
+
export const migration = () => [
|
|
60
|
+
addColumn(User, 'age', (col) => col.integer()),
|
|
61
|
+
createIndex(User, ['age']),
|
|
62
|
+
];
|
|
43
63
|
```
|
|
44
64
|
|
|
45
|
-
##
|
|
46
|
-
|
|
47
|
-
### Query Builder
|
|
65
|
+
## Query Builder
|
|
48
66
|
|
|
49
67
|
```typescript
|
|
50
68
|
// src/queries.ts
|
|
@@ -91,101 +109,59 @@ app.post('/users', async (c) => {
|
|
|
91
109
|
});
|
|
92
110
|
```
|
|
93
111
|
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
```typescript
|
|
97
|
-
// d1-kyt/migrations/0001_create_user_table.ts
|
|
98
|
-
|
|
99
|
-
import { defineTable, createIndex } from 'd1-kyt/migrate';
|
|
100
|
-
|
|
101
|
-
const User = defineTable('User', (col) => ({
|
|
102
|
-
externalId: col.text().notNull(), // ULID or similar
|
|
103
|
-
email: col.text().notNull(),
|
|
104
|
-
name: col.text(),
|
|
105
|
-
}));
|
|
112
|
+
## Install
|
|
106
113
|
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
createIndex(User, ['externalId'], { unique: true }),
|
|
110
|
-
createIndex(User, ['email'], { unique: true }),
|
|
111
|
-
];
|
|
114
|
+
```bash
|
|
115
|
+
npm install d1-kyt kysely kysely-codegen
|
|
112
116
|
```
|
|
113
117
|
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
Import `useTable` from the generated `db/index.ts`:
|
|
117
|
-
|
|
118
|
-
```typescript
|
|
119
|
-
// d1-kyt/migrations/0042_add_age_to_user_table.ts
|
|
120
|
-
|
|
121
|
-
import { useTable } from '../../db';
|
|
122
|
-
import { addColumn, createIndex } from 'd1-kyt/migrate';
|
|
123
|
-
|
|
124
|
-
const User = useTable('User');
|
|
118
|
+
## CLI
|
|
125
119
|
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
120
|
+
```bash
|
|
121
|
+
d1-kyt init # creates d1-kyt/ folder with config
|
|
122
|
+
d1-kyt migrate:create <name> # creates d1-kyt/migrations/0001_<name>.ts
|
|
123
|
+
d1-kyt migrate:build # compiles *.ts → db/migrations/*.sql
|
|
124
|
+
d1-kyt typegen # runs kysely-codegen
|
|
130
125
|
```
|
|
131
126
|
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
```typescript
|
|
135
|
-
import { useTable } from '../../db';
|
|
136
|
-
import { createTrigger, dropTrigger } from 'd1-kyt/migrate';
|
|
137
|
-
|
|
138
|
-
const Merchant = useTable('Merchant');
|
|
139
|
-
|
|
140
|
-
export const migration = () => [
|
|
141
|
-
createTrigger('merchant_fts_insert', 'AFTER INSERT', Merchant, `
|
|
142
|
-
INSERT INTO "MerchantFts"(rowid, name) VALUES (NEW.id, NEW.name);
|
|
143
|
-
`),
|
|
144
|
-
];
|
|
145
|
-
|
|
146
|
-
// To drop a trigger:
|
|
147
|
-
// dropTrigger('merchant_fts_insert')
|
|
148
|
-
```
|
|
127
|
+
Reads `wrangler.jsonc` to detect `migrations_dir` automatically.
|
|
149
128
|
|
|
150
|
-
###
|
|
129
|
+
### Configuration
|
|
151
130
|
|
|
152
131
|
```typescript
|
|
153
|
-
|
|
154
|
-
import { insert } from 'd1-kyt/migrate';
|
|
132
|
+
// d1-kyt/config.ts
|
|
155
133
|
|
|
156
|
-
|
|
134
|
+
import { defineConfig } from 'd1-kyt/config';
|
|
157
135
|
|
|
158
|
-
export
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
];
|
|
136
|
+
export default defineConfig({
|
|
137
|
+
migrationsDir: 'db/migrations',
|
|
138
|
+
dbDir: 'db',
|
|
139
|
+
namingStrategy: 'sequential', // or 'timestamp'
|
|
140
|
+
});
|
|
164
141
|
```
|
|
165
142
|
|
|
166
143
|
## Conventions
|
|
167
144
|
|
|
168
|
-
- Auto `id`, `createdAt`, `updatedAt` on every table
|
|
145
|
+
- Auto `id`, `createdAt`, `updatedAt` on every table (configurable)
|
|
169
146
|
- Auto trigger for `updatedAt`
|
|
147
|
+
- Index naming: `{table}_{cols}_idx`, `{table}_{cols}_uq`
|
|
148
|
+
- Trigger naming: `{table}_{col}_trg`
|
|
170
149
|
|
|
171
150
|
## API
|
|
172
151
|
|
|
173
|
-
| Function
|
|
174
|
-
|
|
|
175
|
-
| `
|
|
176
|
-
| `
|
|
177
|
-
| `
|
|
178
|
-
| `
|
|
179
|
-
| `
|
|
180
|
-
| `
|
|
181
|
-
| `
|
|
182
|
-
| `
|
|
183
|
-
| `
|
|
184
|
-
| `
|
|
185
|
-
| `
|
|
186
|
-
| `createTrigger(name, timing, table, body)` | Create trigger |
|
|
187
|
-
| `dropTrigger(name)` | Drop trigger |
|
|
188
|
-
| `insert(table, rows)` | Insert seed data |
|
|
152
|
+
| Function | Description |
|
|
153
|
+
| -------------------------------------- | --------------------------------- |
|
|
154
|
+
| `defineTable(name, fn, opts?)` | Define new table |
|
|
155
|
+
| `createUseTable<DB>()` | Factory for typed table refs |
|
|
156
|
+
| `useTable<T>(name)` | Reference table (manual typing) |
|
|
157
|
+
| `createIndex(table, cols, opts?)` | Create index |
|
|
158
|
+
| `addColumn(table, col, fn)` | Add column |
|
|
159
|
+
| `dropTable(table, updatedAtCol?)` | Drop table + trigger |
|
|
160
|
+
| `dropIndex(name)` | Drop index |
|
|
161
|
+
| `queryAll(db, query)` | Execute, return all rows |
|
|
162
|
+
| `queryFirst(db, query)` | Execute, return first row or null |
|
|
163
|
+
| `queryRun(db, query)` | Execute mutation |
|
|
164
|
+
| `queryBatch(db, queries)` | Execute batch |
|
|
189
165
|
|
|
190
166
|
## License
|
|
191
167
|
|
package/dist/cli.js
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
import { existsSync, mkdirSync, readdirSync, readFileSync, writeFileSync } from 'node:fs';
|
|
3
3
|
import { join, resolve } from 'node:path';
|
|
4
4
|
import { execSync } from 'node:child_process';
|
|
5
|
-
const VERSION = '0.1.
|
|
5
|
+
const VERSION = '0.1.4';
|
|
6
6
|
const HELP = `
|
|
7
7
|
d1-kyt v${VERSION} - Opinionated Cloudflare D1 + Kysely toolkit
|
|
8
8
|
|
package/dist/migrate.d.ts
CHANGED
|
@@ -30,13 +30,33 @@ export interface ColumnBuilder {
|
|
|
30
30
|
blob(): ColumnDef;
|
|
31
31
|
}
|
|
32
32
|
/**
|
|
33
|
-
*
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
33
|
+
* Options for auto-generated columns in defineTable.
|
|
34
|
+
* All options default to true for backwards compatibility.
|
|
35
|
+
*/
|
|
36
|
+
export interface TableOptions {
|
|
37
|
+
/** Add "id" INTEGER PRIMARY KEY AUTOINCREMENT column. Default: true */
|
|
38
|
+
id?: boolean;
|
|
39
|
+
/** Add "createdAt" TEXT column with default datetime('now'). Default: true */
|
|
40
|
+
createdAt?: boolean;
|
|
41
|
+
/** Add "updatedAt" TEXT column with trigger. Default: true */
|
|
42
|
+
updatedAt?: boolean;
|
|
43
|
+
/** Custom name for id column. Default: "id" */
|
|
44
|
+
idColumn?: string;
|
|
45
|
+
/** Custom name for createdAt column. Default: "createdAt" */
|
|
46
|
+
createdAtColumn?: string;
|
|
47
|
+
/** Custom name for updatedAt column. Default: "updatedAt" */
|
|
48
|
+
updatedAtColumn?: string;
|
|
39
49
|
}
|
|
50
|
+
/**
|
|
51
|
+
* Auto-generated columns - conditional based on options.
|
|
52
|
+
*/
|
|
53
|
+
type AutoColumns<O extends TableOptions, IdCol extends string = O['idColumn'] extends string ? O['idColumn'] : 'id', CreatedCol extends string = O['createdAtColumn'] extends string ? O['createdAtColumn'] : 'createdAt', UpdatedCol extends string = O['updatedAtColumn'] extends string ? O['updatedAtColumn'] : 'updatedAt'> = (O['id'] extends false ? {} : {
|
|
54
|
+
[K in IdCol]: unknown;
|
|
55
|
+
}) & (O['createdAt'] extends false ? {} : {
|
|
56
|
+
[K in CreatedCol]: unknown;
|
|
57
|
+
}) & (O['updatedAt'] extends false ? {} : {
|
|
58
|
+
[K in UpdatedCol]: unknown;
|
|
59
|
+
});
|
|
40
60
|
/**
|
|
41
61
|
* Table reference - carries type information for column names.
|
|
42
62
|
*/
|
|
@@ -52,12 +72,13 @@ export interface DefinedTable<T> extends Table<T> {
|
|
|
52
72
|
}
|
|
53
73
|
type TableDefFn<T extends Record<string, ColumnDef>> = (col: ColumnBuilder) => T;
|
|
54
74
|
/**
|
|
55
|
-
* Define a table with auto-generated
|
|
56
|
-
*
|
|
75
|
+
* Define a table with configurable auto-generated columns.
|
|
76
|
+
* By default adds id, createdAt, updatedAt columns.
|
|
77
|
+
* Returns a Table object with sql property containing CREATE TABLE + optional CREATE TRIGGER.
|
|
57
78
|
*/
|
|
58
|
-
export declare function defineTable<T extends Record<string, ColumnDef
|
|
79
|
+
export declare function defineTable<T extends Record<string, ColumnDef>, O extends TableOptions = {}>(name: string, fn: TableDefFn<T>, options?: O): DefinedTable<{
|
|
59
80
|
[K in keyof T]: unknown;
|
|
60
|
-
} & AutoColumns
|
|
81
|
+
} & AutoColumns<O>>;
|
|
61
82
|
/**
|
|
62
83
|
* Reference an existing table for type-safe operations.
|
|
63
84
|
* Use with kysely-codegen types: useTable<DB['Place']>('Place')
|
|
@@ -102,38 +123,8 @@ export declare function dropIndex(name: string): string;
|
|
|
102
123
|
export declare function addColumn<T, K extends string>(table: Table<T>, column: K, fn: (col: ColumnBuilder) => ColumnDef): string;
|
|
103
124
|
/**
|
|
104
125
|
* Drop a table and its updatedAt trigger.
|
|
126
|
+
* @param updatedAtColumn - Custom updatedAt column name if using custom naming. Default: "updatedAt"
|
|
105
127
|
*/
|
|
106
|
-
export declare function dropTable<T>(table: Table<T
|
|
107
|
-
type TriggerTiming = 'BEFORE INSERT' | 'AFTER INSERT' | 'BEFORE UPDATE' | 'AFTER UPDATE' | 'BEFORE DELETE' | 'AFTER DELETE';
|
|
108
|
-
/**
|
|
109
|
-
* Create a trigger on a table.
|
|
110
|
-
* Body should contain the SQL statements without BEGIN/END.
|
|
111
|
-
*
|
|
112
|
-
* @example
|
|
113
|
-
* ```typescript
|
|
114
|
-
* createTrigger('merchant_fts_insert', 'AFTER INSERT', Merchant, `
|
|
115
|
-
* INSERT INTO "MerchantFts"(rowid, name) VALUES (NEW.id, NEW.name);
|
|
116
|
-
* `)
|
|
117
|
-
* ```
|
|
118
|
-
*/
|
|
119
|
-
export declare function createTrigger<T>(name: string, timing: TriggerTiming, table: Table<T>, body: string): string;
|
|
120
|
-
/**
|
|
121
|
-
* Drop a trigger by name.
|
|
122
|
-
*/
|
|
123
|
-
export declare function dropTrigger(name: string): string;
|
|
124
|
-
type InsertValue = string | number | boolean | null;
|
|
125
|
-
/**
|
|
126
|
-
* Insert rows into a table.
|
|
127
|
-
* Values are automatically quoted based on type.
|
|
128
|
-
*
|
|
129
|
-
* @example
|
|
130
|
-
* ```typescript
|
|
131
|
-
* insert(AdImageType, [
|
|
132
|
-
* { name: 'merchant' },
|
|
133
|
-
* { name: 'blogDesktop' },
|
|
134
|
-
* ])
|
|
135
|
-
* ```
|
|
136
|
-
*/
|
|
137
|
-
export declare function insert<T>(table: Table<T>, rows: Record<string, InsertValue>[]): string;
|
|
128
|
+
export declare function dropTable<T>(table: Table<T>, updatedAtColumn?: string): string[];
|
|
138
129
|
export {};
|
|
139
130
|
//# sourceMappingURL=migrate.d.ts.map
|
package/dist/migrate.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"migrate.d.ts","sourceRoot":"","sources":["../src/migrate.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAMH,KAAK,UAAU,GAAG,MAAM,GAAG,SAAS,GAAG,MAAM,GAAG,MAAM,CAAC;AAEvD,UAAU,iBAAiB;IACzB,IAAI,EAAE,UAAU,CAAC;IACjB,SAAS,EAAE,OAAO,CAAC;IACnB,YAAY,EAAE,MAAM,GAAG,IAAI,CAAC;CAC7B;AAED;;;;GAIG;AACH,MAAM,WAAW,SAAS;IACxB,OAAO,IAAI,SAAS,CAAC;IACrB,OAAO,CAAC,KAAK,EAAE,MAAM,GAAG,SAAS,CAAC;IAClC,gBAAgB;IAChB,IAAI,EAAE,iBAAiB,CAAC;CACzB;AAwBD;;;GAGG;AACH,MAAM,WAAW,aAAa;IAC5B,IAAI,IAAI,SAAS,CAAC;IAClB,OAAO,IAAI,SAAS,CAAC;IACrB,IAAI,IAAI,SAAS,CAAC;IAClB,IAAI,IAAI,SAAS,CAAC;CACnB;AAaD
|
|
1
|
+
{"version":3,"file":"migrate.d.ts","sourceRoot":"","sources":["../src/migrate.ts"],"names":[],"mappings":"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"}
|
package/dist/migrate.js
CHANGED
|
@@ -27,15 +27,29 @@ const columnBuilder = {
|
|
|
27
27
|
real: () => createColumnDef('REAL'),
|
|
28
28
|
blob: () => createColumnDef('BLOB'),
|
|
29
29
|
};
|
|
30
|
+
/** Default options for defineTable */
|
|
31
|
+
const defaultTableOptions = {
|
|
32
|
+
id: true,
|
|
33
|
+
createdAt: true,
|
|
34
|
+
updatedAt: true,
|
|
35
|
+
idColumn: 'id',
|
|
36
|
+
createdAtColumn: 'createdAt',
|
|
37
|
+
updatedAtColumn: 'updatedAt',
|
|
38
|
+
};
|
|
30
39
|
/**
|
|
31
|
-
* Define a table with auto-generated
|
|
32
|
-
*
|
|
40
|
+
* Define a table with configurable auto-generated columns.
|
|
41
|
+
* By default adds id, createdAt, updatedAt columns.
|
|
42
|
+
* Returns a Table object with sql property containing CREATE TABLE + optional CREATE TRIGGER.
|
|
33
43
|
*/
|
|
34
|
-
export function defineTable(name, fn) {
|
|
44
|
+
export function defineTable(name, fn, options) {
|
|
45
|
+
const opts = { ...defaultTableOptions, ...options };
|
|
35
46
|
const columns = fn(columnBuilder);
|
|
36
47
|
const columnDefs = [];
|
|
48
|
+
const sqlStatements = [];
|
|
37
49
|
// Auto id column
|
|
38
|
-
|
|
50
|
+
if (opts.id) {
|
|
51
|
+
columnDefs.push(` "${opts.idColumn}" INTEGER PRIMARY KEY AUTOINCREMENT`);
|
|
52
|
+
}
|
|
39
53
|
// User-defined columns
|
|
40
54
|
for (const [colName, colDef] of Object.entries(columns)) {
|
|
41
55
|
let sql = ` "${colName}" ${colDef._def.type}`;
|
|
@@ -48,20 +62,41 @@ export function defineTable(name, fn) {
|
|
|
48
62
|
columnDefs.push(sql);
|
|
49
63
|
}
|
|
50
64
|
// Auto timestamp columns
|
|
51
|
-
|
|
52
|
-
|
|
65
|
+
if (opts.createdAt) {
|
|
66
|
+
columnDefs.push(` "${opts.createdAtColumn}" TEXT NOT NULL DEFAULT (datetime('now'))`);
|
|
67
|
+
}
|
|
68
|
+
if (opts.updatedAt) {
|
|
69
|
+
columnDefs.push(` "${opts.updatedAtColumn}" TEXT NOT NULL DEFAULT (datetime('now'))`);
|
|
70
|
+
}
|
|
53
71
|
const createTableSql = `CREATE TABLE "${name}" (\n${columnDefs.join(',\n')}\n);`;
|
|
54
|
-
|
|
72
|
+
sqlStatements.push(createTableSql);
|
|
73
|
+
// Only create trigger if updatedAt is enabled
|
|
74
|
+
if (opts.updatedAt) {
|
|
75
|
+
// Determine primary key column for WHERE clause
|
|
76
|
+
const pkColumn = opts.id ? opts.idColumn : findPrimaryKeyColumn(columns);
|
|
77
|
+
if (pkColumn) {
|
|
78
|
+
const createTriggerSql = `CREATE TRIGGER "${name}_${opts.updatedAtColumn}_trg"
|
|
55
79
|
AFTER UPDATE ON "${name}"
|
|
56
80
|
FOR EACH ROW
|
|
57
81
|
BEGIN
|
|
58
|
-
UPDATE "${name}" SET "
|
|
82
|
+
UPDATE "${name}" SET "${opts.updatedAtColumn}" = datetime('now') WHERE "${pkColumn}" = NEW."${pkColumn}";
|
|
59
83
|
END;`;
|
|
84
|
+
sqlStatements.push(createTriggerSql);
|
|
85
|
+
}
|
|
86
|
+
}
|
|
60
87
|
return {
|
|
61
88
|
_name: name,
|
|
62
|
-
sql:
|
|
89
|
+
sql: sqlStatements,
|
|
63
90
|
};
|
|
64
91
|
}
|
|
92
|
+
/**
|
|
93
|
+
* Find a column that could serve as primary key (first column if no id).
|
|
94
|
+
* Returns null if no suitable column found.
|
|
95
|
+
*/
|
|
96
|
+
function findPrimaryKeyColumn(columns) {
|
|
97
|
+
const keys = Object.keys(columns);
|
|
98
|
+
return keys.length > 0 ? keys[0] : null;
|
|
99
|
+
}
|
|
65
100
|
/**
|
|
66
101
|
* Reference an existing table for type-safe operations.
|
|
67
102
|
* Use with kysely-codegen types: useTable<DB['Place']>('Place')
|
|
@@ -99,7 +134,7 @@ export function createUseTable() {
|
|
|
99
134
|
export function createIndex(table, columns, options) {
|
|
100
135
|
const tableName = table._name;
|
|
101
136
|
const unique = options?.unique ?? false;
|
|
102
|
-
const suffix = unique ? '
|
|
137
|
+
const suffix = unique ? 'uq' : 'idx';
|
|
103
138
|
const indexName = options?.name ?? `${tableName}_${columns.join('_')}_${suffix}`;
|
|
104
139
|
const columnList = columns.map((c) => `"${c}"`).join(', ');
|
|
105
140
|
const uniqueKeyword = unique ? 'UNIQUE ' : '';
|
|
@@ -134,72 +169,13 @@ export function addColumn(table, column, fn) {
|
|
|
134
169
|
// ----------------------------------------------------------------------------
|
|
135
170
|
/**
|
|
136
171
|
* Drop a table and its updatedAt trigger.
|
|
172
|
+
* @param updatedAtColumn - Custom updatedAt column name if using custom naming. Default: "updatedAt"
|
|
137
173
|
*/
|
|
138
|
-
export function dropTable(table) {
|
|
174
|
+
export function dropTable(table, updatedAtColumn = 'updatedAt') {
|
|
139
175
|
const name = table._name;
|
|
140
176
|
return [
|
|
141
177
|
`DROP TABLE "${name}";`,
|
|
142
|
-
`DROP TRIGGER IF EXISTS "${name}
|
|
178
|
+
`DROP TRIGGER IF EXISTS "${name}_${updatedAtColumn}_trg";`,
|
|
143
179
|
];
|
|
144
180
|
}
|
|
145
|
-
/**
|
|
146
|
-
* Create a trigger on a table.
|
|
147
|
-
* Body should contain the SQL statements without BEGIN/END.
|
|
148
|
-
*
|
|
149
|
-
* @example
|
|
150
|
-
* ```typescript
|
|
151
|
-
* createTrigger('merchant_fts_insert', 'AFTER INSERT', Merchant, `
|
|
152
|
-
* INSERT INTO "MerchantFts"(rowid, name) VALUES (NEW.id, NEW.name);
|
|
153
|
-
* `)
|
|
154
|
-
* ```
|
|
155
|
-
*/
|
|
156
|
-
export function createTrigger(name, timing, table, body) {
|
|
157
|
-
const trimmedBody = body.trim();
|
|
158
|
-
return `CREATE TRIGGER "${name}"
|
|
159
|
-
${timing} ON "${table._name}"
|
|
160
|
-
FOR EACH ROW
|
|
161
|
-
BEGIN
|
|
162
|
-
${trimmedBody}
|
|
163
|
-
END;`;
|
|
164
|
-
}
|
|
165
|
-
/**
|
|
166
|
-
* Drop a trigger by name.
|
|
167
|
-
*/
|
|
168
|
-
export function dropTrigger(name) {
|
|
169
|
-
return `DROP TRIGGER IF EXISTS "${name}";`;
|
|
170
|
-
}
|
|
171
|
-
/**
|
|
172
|
-
* Insert rows into a table.
|
|
173
|
-
* Values are automatically quoted based on type.
|
|
174
|
-
*
|
|
175
|
-
* @example
|
|
176
|
-
* ```typescript
|
|
177
|
-
* insert(AdImageType, [
|
|
178
|
-
* { name: 'merchant' },
|
|
179
|
-
* { name: 'blogDesktop' },
|
|
180
|
-
* ])
|
|
181
|
-
* ```
|
|
182
|
-
*/
|
|
183
|
-
export function insert(table, rows) {
|
|
184
|
-
if (rows.length === 0)
|
|
185
|
-
return '';
|
|
186
|
-
const columns = Object.keys(rows[0]);
|
|
187
|
-
const columnList = columns.map((c) => `"${c}"`).join(', ');
|
|
188
|
-
const valuesList = rows
|
|
189
|
-
.map((row) => {
|
|
190
|
-
const values = columns.map((col) => {
|
|
191
|
-
const val = row[col];
|
|
192
|
-
if (val === null)
|
|
193
|
-
return 'NULL';
|
|
194
|
-
if (typeof val === 'string')
|
|
195
|
-
return `'${val.replace(/'/g, "''")}'`;
|
|
196
|
-
if (typeof val === 'boolean')
|
|
197
|
-
return val ? '1' : '0';
|
|
198
|
-
return String(val);
|
|
199
|
-
});
|
|
200
|
-
return `(${values.join(', ')})`;
|
|
201
|
-
})
|
|
202
|
-
.join(',\n ');
|
|
203
|
-
return `INSERT INTO "${table._name}" (${columnList}) VALUES\n ${valuesList};`;
|
|
204
|
-
}
|
|
205
181
|
//# sourceMappingURL=migrate.js.map
|
package/dist/migrate.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"migrate.js","sourceRoot":"","sources":["../src/migrate.ts"],"names":[],"mappings":"AAAA;;;GAGG;AA0BH,SAAS,eAAe,CAAC,IAAgB;IACvC,MAAM,GAAG,GAAsB;QAC7B,IAAI;QACJ,SAAS,EAAE,KAAK;QAChB,YAAY,EAAE,IAAI;KACnB,CAAC;IAEF,MAAM,SAAS,GAAc;QAC3B,IAAI,EAAE,GAAG;QACT,OAAO;YACL,GAAG,CAAC,SAAS,GAAG,IAAI,CAAC;YACrB,OAAO,SAAS,CAAC;QACnB,CAAC;QACD,OAAO,CAAC,KAAa;YACnB,GAAG,CAAC,YAAY,GAAG,KAAK,CAAC;YACzB,OAAO,SAAS,CAAC;QACnB,CAAC;KACF,CAAC;IAEF,OAAO,SAAS,CAAC;AACnB,CAAC;AAaD,MAAM,aAAa,GAAkB;IACnC,IAAI,EAAE,GAAG,EAAE,CAAC,eAAe,CAAC,MAAM,CAAC;IACnC,OAAO,EAAE,GAAG,EAAE,CAAC,eAAe,CAAC,SAAS,CAAC;IACzC,IAAI,EAAE,GAAG,EAAE,CAAC,eAAe,CAAC,MAAM,CAAC;IACnC,IAAI,EAAE,GAAG,EAAE,CAAC,eAAe,CAAC,MAAM,CAAC;CACpC,CAAC;
|
|
1
|
+
{"version":3,"file":"migrate.js","sourceRoot":"","sources":["../src/migrate.ts"],"names":[],"mappings":"AAAA;;;GAGG;AA0BH,SAAS,eAAe,CAAC,IAAgB;IACvC,MAAM,GAAG,GAAsB;QAC7B,IAAI;QACJ,SAAS,EAAE,KAAK;QAChB,YAAY,EAAE,IAAI;KACnB,CAAC;IAEF,MAAM,SAAS,GAAc;QAC3B,IAAI,EAAE,GAAG;QACT,OAAO;YACL,GAAG,CAAC,SAAS,GAAG,IAAI,CAAC;YACrB,OAAO,SAAS,CAAC;QACnB,CAAC;QACD,OAAO,CAAC,KAAa;YACnB,GAAG,CAAC,YAAY,GAAG,KAAK,CAAC;YACzB,OAAO,SAAS,CAAC;QACnB,CAAC;KACF,CAAC;IAEF,OAAO,SAAS,CAAC;AACnB,CAAC;AAaD,MAAM,aAAa,GAAkB;IACnC,IAAI,EAAE,GAAG,EAAE,CAAC,eAAe,CAAC,MAAM,CAAC;IACnC,OAAO,EAAE,GAAG,EAAE,CAAC,eAAe,CAAC,SAAS,CAAC;IACzC,IAAI,EAAE,GAAG,EAAE,CAAC,eAAe,CAAC,MAAM,CAAC;IACnC,IAAI,EAAE,GAAG,EAAE,CAAC,eAAe,CAAC,MAAM,CAAC;CACpC,CAAC;AA8DF,sCAAsC;AACtC,MAAM,mBAAmB,GAA2B;IAClD,EAAE,EAAE,IAAI;IACR,SAAS,EAAE,IAAI;IACf,SAAS,EAAE,IAAI;IACf,QAAQ,EAAE,IAAI;IACd,eAAe,EAAE,WAAW;IAC5B,eAAe,EAAE,WAAW;CAC7B,CAAC;AAEF;;;;GAIG;AACH,MAAM,UAAU,WAAW,CACzB,IAAY,EACZ,EAAiB,EACjB,OAAW;IAEX,MAAM,IAAI,GAAG,EAAE,GAAG,mBAAmB,EAAE,GAAG,OAAO,EAAE,CAAC;IACpD,MAAM,OAAO,GAAG,EAAE,CAAC,aAAa,CAAC,CAAC;IAClC,MAAM,UAAU,GAAa,EAAE,CAAC;IAChC,MAAM,aAAa,GAAa,EAAE,CAAC;IAEnC,iBAAiB;IACjB,IAAI,IAAI,CAAC,EAAE,EAAE,CAAC;QACZ,UAAU,CAAC,IAAI,CAAC,MAAM,IAAI,CAAC,QAAQ,qCAAqC,CAAC,CAAC;IAC5E,CAAC;IAED,uBAAuB;IACvB,KAAK,MAAM,CAAC,OAAO,EAAE,MAAM,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,OAAO,CAAC,EAAE,CAAC;QACxD,IAAI,GAAG,GAAG,MAAM,OAAO,KAAK,MAAM,CAAC,IAAI,CAAC,IAAI,EAAE,CAAC;QAC/C,IAAI,MAAM,CAAC,IAAI,CAAC,SAAS,EAAE,CAAC;YAC1B,GAAG,IAAI,WAAW,CAAC;QACrB,CAAC;QACD,IAAI,MAAM,CAAC,IAAI,CAAC,YAAY,KAAK,IAAI,EAAE,CAAC;YACtC,GAAG,IAAI,YAAY,MAAM,CAAC,IAAI,CAAC,YAAY,EAAE,CAAC;QAChD,CAAC;QACD,UAAU,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;IACvB,CAAC;IAED,yBAAyB;IACzB,IAAI,IAAI,CAAC,SAAS,EAAE,CAAC;QACnB,UAAU,CAAC,IAAI,CAAC,MAAM,IAAI,CAAC,eAAe,2CAA2C,CAAC,CAAC;IACzF,CAAC;IACD,IAAI,IAAI,CAAC,SAAS,EAAE,CAAC;QACnB,UAAU,CAAC,IAAI,CAAC,MAAM,IAAI,CAAC,eAAe,2CAA2C,CAAC,CAAC;IACzF,CAAC;IAED,MAAM,cAAc,GAAG,iBAAiB,IAAI,QAAQ,UAAU,CAAC,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC;IACjF,aAAa,CAAC,IAAI,CAAC,cAAc,CAAC,CAAC;IAEnC,8CAA8C;IAC9C,IAAI,IAAI,CAAC,SAAS,EAAE,CAAC;QACnB,gDAAgD;QAChD,MAAM,QAAQ,GAAG,IAAI,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC,CAAC,oBAAoB,CAAC,OAAO,CAAC,CAAC;QACzE,IAAI,QAAQ,EAAE,CAAC;YACb,MAAM,gBAAgB,GAAG,mBAAmB,IAAI,IAAI,IAAI,CAAC,eAAe;mBAC3D,IAAI;;;YAGX,IAAI,UAAU,IAAI,CAAC,eAAe,8BAA8B,QAAQ,YAAY,QAAQ;KACnG,CAAC;YACA,aAAa,CAAC,IAAI,CAAC,gBAAgB,CAAC,CAAC;QACvC,CAAC;IACH,CAAC;IAED,OAAO;QACL,KAAK,EAAE,IAAI;QACX,GAAG,EAAE,aAAa;KAC2C,CAAC;AAClE,CAAC;AAED;;;GAGG;AACH,SAAS,oBAAoB,CAAC,OAAkC;IAC9D,MAAM,IAAI,GAAG,MAAM,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;IAClC,OAAO,IAAI,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC;AAC1C,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,QAAQ,CAAI,IAAY;IACtC,OAAO,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC;AACzB,CAAC;AAED;;;;;;;;;;;;;;;;GAgBG;AACH,MAAM,UAAU,cAAc;IAC5B,OAAO,UAAuC,IAAO;QACnD,OAAO,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC;IACzB,CAAC,CAAC;AACJ,CAAC;AAWD;;;;GAIG;AACH,MAAM,UAAU,WAAW,CACzB,KAAe,EACf,OAA6B,EAC7B,OAAsB;IAEtB,MAAM,SAAS,GAAG,KAAK,CAAC,KAAK,CAAC;IAC9B,MAAM,MAAM,GAAG,OAAO,EAAE,MAAM,IAAI,KAAK,CAAC;IACxC,MAAM,MAAM,GAAG,MAAM,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,KAAK,CAAC;IACrC,MAAM,SAAS,GAAG,OAAO,EAAE,IAAI,IAAI,GAAG,SAAS,IAAI,OAAO,CAAC,IAAI,CAAC,GAAG,CAAC,IAAI,MAAM,EAAE,CAAC;IACjF,MAAM,UAAU,GAAG,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IAC3D,MAAM,aAAa,GAAG,MAAM,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,EAAE,CAAC;IAE9C,OAAO,UAAU,aAAa,UAAU,SAAS,SAAS,SAAS,KAAK,UAAU,IAAI,CAAC;AACzF,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,SAAS,CAAC,IAAY;IACpC,OAAO,eAAe,IAAI,IAAI,CAAC;AACjC,CAAC;AAED,+EAA+E;AAC/E,oBAAoB;AACpB,+EAA+E;AAE/E;;;GAGG;AACH,MAAM,UAAU,SAAS,CACvB,KAAe,EACf,MAAS,EACT,EAAqC;IAErC,MAAM,MAAM,GAAG,EAAE,CAAC,aAAa,CAAC,CAAC;IACjC,IAAI,GAAG,GAAG,gBAAgB,KAAK,CAAC,KAAK,iBAAiB,MAAM,KAAK,MAAM,CAAC,IAAI,CAAC,IAAI,EAAE,CAAC;IACpF,IAAI,MAAM,CAAC,IAAI,CAAC,SAAS,EAAE,CAAC;QAC1B,GAAG,IAAI,WAAW,CAAC;IACrB,CAAC;IACD,IAAI,MAAM,CAAC,IAAI,CAAC,YAAY,KAAK,IAAI,EAAE,CAAC;QACtC,GAAG,IAAI,YAAY,MAAM,CAAC,IAAI,CAAC,YAAY,EAAE,CAAC;IAChD,CAAC;IACD,OAAO,GAAG,GAAG,GAAG,CAAC;AACnB,CAAC;AAED,+EAA+E;AAC/E,mBAAmB;AACnB,+EAA+E;AAE/E;;;GAGG;AACH,MAAM,UAAU,SAAS,CAAI,KAAe,EAAE,kBAA0B,WAAW;IACjF,MAAM,IAAI,GAAG,KAAK,CAAC,KAAK,CAAC;IACzB,OAAO;QACL,eAAe,IAAI,IAAI;QACvB,2BAA2B,IAAI,IAAI,eAAe,QAAQ;KAC3D,CAAC;AACJ,CAAC"}
|
package/package.json
CHANGED
|
@@ -1,11 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "d1-kyt",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.2.0",
|
|
4
4
|
"description": "Opinionated Cloudflare D1 + Kysely toolkit",
|
|
5
|
-
"repository": {
|
|
6
|
-
"url": "https://github.com/sher/d1-kyt"
|
|
7
|
-
},
|
|
8
|
-
"homepage": "https://github.com/sher/d1-kyt",
|
|
9
5
|
"type": "module",
|
|
10
6
|
"main": "dist/index.js",
|
|
11
7
|
"types": "dist/index.d.ts",
|
|
@@ -29,12 +25,6 @@
|
|
|
29
25
|
"files": [
|
|
30
26
|
"dist"
|
|
31
27
|
],
|
|
32
|
-
"scripts": {
|
|
33
|
-
"build": "tsc",
|
|
34
|
-
"test": "vitest",
|
|
35
|
-
"typecheck": "tsc --noEmit",
|
|
36
|
-
"prepublishOnly": "pnpm build"
|
|
37
|
-
},
|
|
38
28
|
"keywords": [
|
|
39
29
|
"cloudflare",
|
|
40
30
|
"d1",
|
|
@@ -51,7 +41,13 @@
|
|
|
51
41
|
"devDependencies": {
|
|
52
42
|
"@types/node": "22.15.29",
|
|
53
43
|
"kysely": "0.28.8",
|
|
54
|
-
"typescript": "5.9.3",
|
|
55
44
|
"vitest": "4.0.15"
|
|
45
|
+
},
|
|
46
|
+
"scripts": {
|
|
47
|
+
"build": "tsc",
|
|
48
|
+
"dev": "tsc --watch",
|
|
49
|
+
"test": "vitest",
|
|
50
|
+
"lint": "echo noop",
|
|
51
|
+
"typecheck": "tsc --noEmit"
|
|
56
52
|
}
|
|
57
|
-
}
|
|
53
|
+
}
|