@kamod-ch/otok-kysely 2.0.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/LICENSE +21 -0
- package/README.md +86 -0
- package/dist/cli/index.d.ts +12 -0
- package/dist/cli/index.d.ts.map +1 -0
- package/dist/cli/index.js +66 -0
- package/dist/cli/index.js.map +1 -0
- package/dist/context.d.ts +5 -0
- package/dist/context.d.ts.map +1 -0
- package/dist/context.js +17 -0
- package/dist/context.js.map +1 -0
- package/dist/dialects/index.d.ts +2 -0
- package/dist/dialects/index.d.ts.map +1 -0
- package/dist/dialects/index.js +2 -0
- package/dist/dialects/index.js.map +1 -0
- package/dist/dialects/mysql.d.ts +13 -0
- package/dist/dialects/mysql.d.ts.map +1 -0
- package/dist/dialects/mysql.js +38 -0
- package/dist/dialects/mysql.js.map +1 -0
- package/dist/index.d.ts +7 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +6 -0
- package/dist/index.js.map +1 -0
- package/dist/kysely.test-d.d.ts +2 -0
- package/dist/kysely.test-d.d.ts.map +1 -0
- package/dist/kysely.test-d.js +9 -0
- package/dist/kysely.test-d.js.map +1 -0
- package/dist/loader.d.ts +26 -0
- package/dist/loader.d.ts.map +1 -0
- package/dist/loader.js +34 -0
- package/dist/loader.js.map +1 -0
- package/dist/migrations/index.d.ts +3 -0
- package/dist/migrations/index.d.ts.map +1 -0
- package/dist/migrations/index.js +2 -0
- package/dist/migrations/index.js.map +1 -0
- package/dist/migrations/runner.d.ts +10 -0
- package/dist/migrations/runner.d.ts.map +1 -0
- package/dist/migrations/runner.js +105 -0
- package/dist/migrations/runner.js.map +1 -0
- package/dist/plugin.d.ts +7 -0
- package/dist/plugin.d.ts.map +1 -0
- package/dist/plugin.js +77 -0
- package/dist/plugin.js.map +1 -0
- package/dist/pool.d.ts +8 -0
- package/dist/pool.d.ts.map +1 -0
- package/dist/pool.js +55 -0
- package/dist/pool.js.map +1 -0
- package/dist/registry.d.ts +7 -0
- package/dist/registry.d.ts.map +1 -0
- package/dist/registry.js +18 -0
- package/dist/registry.js.map +1 -0
- package/dist/seeds/index.d.ts +2 -0
- package/dist/seeds/index.d.ts.map +1 -0
- package/dist/seeds/index.js +2 -0
- package/dist/seeds/index.js.map +1 -0
- package/dist/seeds/runner.d.ts +7 -0
- package/dist/seeds/runner.d.ts.map +1 -0
- package/dist/seeds/runner.js +40 -0
- package/dist/seeds/runner.js.map +1 -0
- package/dist/setup.d.ts +3 -0
- package/dist/setup.d.ts.map +1 -0
- package/dist/setup.js +56 -0
- package/dist/setup.js.map +1 -0
- package/dist/test/index.d.ts +19 -0
- package/dist/test/index.d.ts.map +1 -0
- package/dist/test/index.js +28 -0
- package/dist/test/index.js.map +1 -0
- package/dist/transaction.d.ts +7 -0
- package/dist/transaction.d.ts.map +1 -0
- package/dist/transaction.js +8 -0
- package/dist/transaction.js.map +1 -0
- package/dist/types.d.ts +67 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +2 -0
- package/dist/types.js.map +1 -0
- package/package.json +106 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Kamod
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
# @kamod-ch/otok-kysely
|
|
2
|
+
|
|
3
|
+
Kysely database integration for [Otok](https://github.com/kamod-ch/otok) — typed `db` in route actions, connection pooling, migrations, seeds, and CLI commands.
|
|
4
|
+
|
|
5
|
+
## Setup
|
|
6
|
+
|
|
7
|
+
```ts
|
|
8
|
+
import { defineConfig } from "@kamod-ch/otok";
|
|
9
|
+
import kysely from "@kamod-ch/otok-kysely";
|
|
10
|
+
|
|
11
|
+
export default defineConfig({
|
|
12
|
+
plugins: [
|
|
13
|
+
kysely({
|
|
14
|
+
dialect: "postgres",
|
|
15
|
+
connectionString: process.env.DATABASE_URL,
|
|
16
|
+
}),
|
|
17
|
+
],
|
|
18
|
+
});
|
|
19
|
+
```
|
|
20
|
+
|
|
21
|
+
Install dialect drivers in your app:
|
|
22
|
+
|
|
23
|
+
| Dialect | Package |
|
|
24
|
+
|----------|------------------|
|
|
25
|
+
| postgres | `pg` |
|
|
26
|
+
| sqlite | `better-sqlite3` |
|
|
27
|
+
| mysql | `mysql2` + adapter |
|
|
28
|
+
|
|
29
|
+
```ts
|
|
30
|
+
import kysely from "@kamod-ch/otok-kysely";
|
|
31
|
+
import { mysqlDialect } from "@kamod-ch/otok-kysely/dialects";
|
|
32
|
+
|
|
33
|
+
kysely({ dialect: mysqlDialect(), connectionString: env.DATABASE_URL })
|
|
34
|
+
```
|
|
35
|
+
|
|
36
|
+
## Route actions
|
|
37
|
+
|
|
38
|
+
```ts
|
|
39
|
+
import { defineAction, defineLoader } from "@kamod-ch/otok-kysely/loader";
|
|
40
|
+
|
|
41
|
+
export const loader = defineLoader(async ({ db }) => {
|
|
42
|
+
return db.selectFrom("contacts").selectAll().execute();
|
|
43
|
+
});
|
|
44
|
+
|
|
45
|
+
export const action = defineAction(async ({ db, input }) => {
|
|
46
|
+
return db.insertInto("contacts").values(input).returningAll().executeTakeFirstOrThrow();
|
|
47
|
+
});
|
|
48
|
+
```
|
|
49
|
+
|
|
50
|
+
`DATABASE_URL` is validated server-side via `envSchema` — credentials never reach the client bundle.
|
|
51
|
+
|
|
52
|
+
## Migrations
|
|
53
|
+
|
|
54
|
+
Migration files live in `migrations/` using the naming convention `YYYYMMDDHHMMSS_name.up.sql` / `.down.sql`.
|
|
55
|
+
|
|
56
|
+
```bash
|
|
57
|
+
otok db:migrate # apply pending migrations
|
|
58
|
+
otok db:rollback # roll back last migration (--steps N)
|
|
59
|
+
otok db:status # show applied/pending
|
|
60
|
+
otok db:seed # run seed files
|
|
61
|
+
```
|
|
62
|
+
|
|
63
|
+
## Transactions
|
|
64
|
+
|
|
65
|
+
```ts
|
|
66
|
+
import { withTransaction } from "@kamod-ch/otok-kysely";
|
|
67
|
+
|
|
68
|
+
await withTransaction(db, async (trx) => {
|
|
69
|
+
await trx.insertInto("contacts").values({ name: "Ada" }).execute();
|
|
70
|
+
await trx.insertInto("audit_log").values({ action: "create" }).execute();
|
|
71
|
+
});
|
|
72
|
+
```
|
|
73
|
+
|
|
74
|
+
## Test utilities
|
|
75
|
+
|
|
76
|
+
```ts
|
|
77
|
+
import { createTestDatabase } from "@kamod-ch/otok-kysely/test";
|
|
78
|
+
|
|
79
|
+
const { db, cleanup } = await createTestDatabase({ migrationsDirectory: "./migrations" });
|
|
80
|
+
// ... run tests
|
|
81
|
+
await cleanup();
|
|
82
|
+
```
|
|
83
|
+
|
|
84
|
+
## Edge runtime
|
|
85
|
+
|
|
86
|
+
SQLite (`better-sqlite3`) is edge-capable in worker contexts that support native modules. PostgreSQL and MySQL require Node.js runtimes with connection pooling.
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import type { KyselyPluginOptions } from "../types.js";
|
|
2
|
+
export interface DbCliContext {
|
|
3
|
+
root: string;
|
|
4
|
+
options: KyselyPluginOptions;
|
|
5
|
+
}
|
|
6
|
+
export declare function runDbMigrate(ctx: DbCliContext): Promise<string[]>;
|
|
7
|
+
export declare function runDbRollback(ctx: DbCliContext, steps?: number): Promise<string[]>;
|
|
8
|
+
export declare function runDbSeed(ctx: DbCliContext): Promise<string[]>;
|
|
9
|
+
export declare function runDbStatus(ctx: DbCliContext): Promise<import("../types.js").MigrationStatus[]>;
|
|
10
|
+
/** Resolve kysely plugin options from a registered runtime (for in-process CLI). */
|
|
11
|
+
export declare function resolveDbCliFromRuntime(root: string): DbCliContext;
|
|
12
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/cli/index.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,aAAa,CAAC;AAEvD,MAAM,WAAW,YAAY;IAC3B,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,mBAAmB,CAAC;CAC9B;AAED,wBAAsB,YAAY,CAAC,GAAG,EAAE,YAAY,GAAG,OAAO,CAAC,MAAM,EAAE,CAAC,CAWvE;AAED,wBAAsB,aAAa,CAAC,GAAG,EAAE,YAAY,EAAE,KAAK,SAAI,GAAG,OAAO,CAAC,MAAM,EAAE,CAAC,CAWnF;AAED,wBAAsB,SAAS,CAAC,GAAG,EAAE,YAAY,GAAG,OAAO,CAAC,MAAM,EAAE,CAAC,CAUpE;AAED,wBAAsB,WAAW,CAAC,GAAG,EAAE,YAAY,oDAWlD;AAED,oFAAoF;AACpF,wBAAgB,uBAAuB,CAAC,IAAI,EAAE,MAAM,GAAG,YAAY,CAWlE"}
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
import { join } from "node:path";
|
|
2
|
+
import { getKyselyRuntime } from "../registry.js";
|
|
3
|
+
import { getMigrationStatus, migrateDown, migrateUp } from "../migrations/runner.js";
|
|
4
|
+
import { runSeeds } from "../seeds/runner.js";
|
|
5
|
+
import { createKyselyInstance, destroyKyselyInstance, resolveConnectionString } from "../pool.js";
|
|
6
|
+
export async function runDbMigrate(ctx) {
|
|
7
|
+
const connectionString = resolveConnectionString(ctx.options.connectionString);
|
|
8
|
+
const db = await createKyselyInstance(ctx.options.dialect, connectionString, ctx.options.pool);
|
|
9
|
+
const migrationsDir = join(ctx.root, ctx.options.migrations?.directory ?? "migrations");
|
|
10
|
+
const tableName = ctx.options.migrations?.tableName ?? "otok_migrations";
|
|
11
|
+
try {
|
|
12
|
+
return await migrateUp(db, migrationsDir, tableName);
|
|
13
|
+
}
|
|
14
|
+
finally {
|
|
15
|
+
await destroyKyselyInstance(db);
|
|
16
|
+
}
|
|
17
|
+
}
|
|
18
|
+
export async function runDbRollback(ctx, steps = 1) {
|
|
19
|
+
const connectionString = resolveConnectionString(ctx.options.connectionString);
|
|
20
|
+
const db = await createKyselyInstance(ctx.options.dialect, connectionString, ctx.options.pool);
|
|
21
|
+
const migrationsDir = join(ctx.root, ctx.options.migrations?.directory ?? "migrations");
|
|
22
|
+
const tableName = ctx.options.migrations?.tableName ?? "otok_migrations";
|
|
23
|
+
try {
|
|
24
|
+
return await migrateDown(db, migrationsDir, tableName, steps);
|
|
25
|
+
}
|
|
26
|
+
finally {
|
|
27
|
+
await destroyKyselyInstance(db);
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
export async function runDbSeed(ctx) {
|
|
31
|
+
const connectionString = resolveConnectionString(ctx.options.connectionString);
|
|
32
|
+
const db = await createKyselyInstance(ctx.options.dialect, connectionString, ctx.options.pool);
|
|
33
|
+
const seedsDir = join(ctx.root, ctx.options.seeds?.directory ?? "seeds");
|
|
34
|
+
try {
|
|
35
|
+
return await runSeeds(db, seedsDir);
|
|
36
|
+
}
|
|
37
|
+
finally {
|
|
38
|
+
await destroyKyselyInstance(db);
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
export async function runDbStatus(ctx) {
|
|
42
|
+
const connectionString = resolveConnectionString(ctx.options.connectionString);
|
|
43
|
+
const db = await createKyselyInstance(ctx.options.dialect, connectionString, ctx.options.pool);
|
|
44
|
+
const migrationsDir = join(ctx.root, ctx.options.migrations?.directory ?? "migrations");
|
|
45
|
+
const tableName = ctx.options.migrations?.tableName ?? "otok_migrations";
|
|
46
|
+
try {
|
|
47
|
+
return await getMigrationStatus(db, migrationsDir, tableName);
|
|
48
|
+
}
|
|
49
|
+
finally {
|
|
50
|
+
await destroyKyselyInstance(db);
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
/** Resolve kysely plugin options from a registered runtime (for in-process CLI). */
|
|
54
|
+
export function resolveDbCliFromRuntime(root) {
|
|
55
|
+
const runtime = getKyselyRuntime();
|
|
56
|
+
return {
|
|
57
|
+
root,
|
|
58
|
+
options: {
|
|
59
|
+
dialect: runtime.dialect,
|
|
60
|
+
connectionString: runtime.connectionString,
|
|
61
|
+
migrations: runtime.migrations,
|
|
62
|
+
seeds: runtime.seeds,
|
|
63
|
+
},
|
|
64
|
+
};
|
|
65
|
+
}
|
|
66
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/cli/index.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
import type { Context } from "hono";
|
|
2
|
+
import type { Kysely } from "kysely";
|
|
3
|
+
export declare function dbFromHono<DB = unknown>(hono: Context, contextKey?: string): Kysely<DB>;
|
|
4
|
+
export declare function getDb<DB = unknown>(): Kysely<DB>;
|
|
5
|
+
//# sourceMappingURL=context.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"context.d.ts","sourceRoot":"","sources":["../src/context.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,MAAM,CAAC;AACpC,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,QAAQ,CAAC;AAGrC,wBAAgB,UAAU,CAAC,EAAE,GAAG,OAAO,EAAE,IAAI,EAAE,OAAO,EAAE,UAAU,CAAC,EAAE,MAAM,GAAG,MAAM,CAAC,EAAE,CAAC,CAavF;AAED,wBAAgB,KAAK,CAAC,EAAE,GAAG,OAAO,KAAK,MAAM,CAAC,EAAE,CAAC,CAEhD"}
|
package/dist/context.js
ADDED
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import { getKyselyRuntime, tryGetKyselyRuntime } from "./registry.js";
|
|
2
|
+
export function dbFromHono(hono, contextKey) {
|
|
3
|
+
const runtime = tryGetKyselyRuntime();
|
|
4
|
+
if (!runtime) {
|
|
5
|
+
throw new Error("otok-kysely: no database runtime registered. Add kysely() to otok.config.ts plugins.");
|
|
6
|
+
}
|
|
7
|
+
const key = contextKey ?? runtime.contextKey;
|
|
8
|
+
const db = hono.get(key);
|
|
9
|
+
if (!db) {
|
|
10
|
+
throw new Error(`otok-kysely: db not found on Hono context key "${key}".`);
|
|
11
|
+
}
|
|
12
|
+
return db;
|
|
13
|
+
}
|
|
14
|
+
export function getDb() {
|
|
15
|
+
return getKyselyRuntime().db;
|
|
16
|
+
}
|
|
17
|
+
//# sourceMappingURL=context.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"context.js","sourceRoot":"","sources":["../src/context.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,gBAAgB,EAAE,mBAAmB,EAAE,MAAM,eAAe,CAAC;AAEtE,MAAM,UAAU,UAAU,CAAe,IAAa,EAAE,UAAmB;IACzE,MAAM,OAAO,GAAG,mBAAmB,EAAM,CAAC;IAC1C,IAAI,CAAC,OAAO,EAAE,CAAC;QACb,MAAM,IAAI,KAAK,CACb,sFAAsF,CACvF,CAAC;IACJ,CAAC;IACD,MAAM,GAAG,GAAG,UAAU,IAAI,OAAO,CAAC,UAAU,CAAC;IAC7C,MAAM,EAAE,GAAG,IAAI,CAAC,GAAG,CAAC,GAAG,CAA2B,CAAC;IACnD,IAAI,CAAC,EAAE,EAAE,CAAC;QACR,MAAM,IAAI,KAAK,CAAC,kDAAkD,GAAG,IAAI,CAAC,CAAC;IAC7E,CAAC;IACD,OAAO,EAAE,CAAC;AACZ,CAAC;AAED,MAAM,UAAU,KAAK;IACnB,OAAO,gBAAgB,EAAM,CAAC,EAAE,CAAC;AACnC,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/dialects/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,YAAY,IAAI,OAAO,EAAE,MAAM,YAAY,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/dialects/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,YAAY,IAAI,OAAO,EAAE,MAAM,YAAY,CAAC"}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* MySQL dialect adapter — install `mysql2` in your app.
|
|
3
|
+
*
|
|
4
|
+
* ```ts
|
|
5
|
+
* import kysely from "@kamod-ch/otok-kysely";
|
|
6
|
+
* import { mysqlDialect } from "@kamod-ch/otok-kysely/dialects";
|
|
7
|
+
*
|
|
8
|
+
* kysely({ dialect: mysqlDialect(), connectionString: env.DATABASE_URL })
|
|
9
|
+
* ```
|
|
10
|
+
*/
|
|
11
|
+
export declare function mysqlDialect(): import("../types.js").DialectAdapter;
|
|
12
|
+
export { mysqlDialect as default };
|
|
13
|
+
//# sourceMappingURL=mysql.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"mysql.d.ts","sourceRoot":"","sources":["../../src/dialects/mysql.ts"],"names":[],"mappings":"AAEA;;;;;;;;;GASG;AACH,wBAAgB,YAAY,IAAI,OAAO,aAAa,EAAE,cAAc,CAQnE;AAmBD,OAAO,EAAE,YAAY,IAAI,OAAO,EAAE,CAAC"}
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* MySQL dialect adapter — install `mysql2` in your app.
|
|
3
|
+
*
|
|
4
|
+
* ```ts
|
|
5
|
+
* import kysely from "@kamod-ch/otok-kysely";
|
|
6
|
+
* import { mysqlDialect } from "@kamod-ch/otok-kysely/dialects";
|
|
7
|
+
*
|
|
8
|
+
* kysely({ dialect: mysqlDialect(), connectionString: env.DATABASE_URL })
|
|
9
|
+
* ```
|
|
10
|
+
*/
|
|
11
|
+
export function mysqlDialect() {
|
|
12
|
+
return {
|
|
13
|
+
edgeCapable: false,
|
|
14
|
+
createDialect(options) {
|
|
15
|
+
// Lazy require pattern — mysql2 is an optional peer dependency.
|
|
16
|
+
return createMysqlDialect(options);
|
|
17
|
+
},
|
|
18
|
+
};
|
|
19
|
+
}
|
|
20
|
+
async function createMysqlDialect(options) {
|
|
21
|
+
const { MysqlDialect } = await import("kysely");
|
|
22
|
+
let createPool;
|
|
23
|
+
try {
|
|
24
|
+
// @ts-expect-error mysql2 is an optional peer dependency
|
|
25
|
+
const mysql = await import("mysql2");
|
|
26
|
+
createPool = mysql.createPool;
|
|
27
|
+
}
|
|
28
|
+
catch {
|
|
29
|
+
throw new Error("otok-kysely: install `mysql2` to use the mysql dialect adapter.");
|
|
30
|
+
}
|
|
31
|
+
const pool = createPool({
|
|
32
|
+
uri: options.connectionString,
|
|
33
|
+
connectionLimit: options.pool?.max ?? 10,
|
|
34
|
+
});
|
|
35
|
+
return new MysqlDialect({ pool: pool });
|
|
36
|
+
}
|
|
37
|
+
export { mysqlDialect as default };
|
|
38
|
+
//# sourceMappingURL=mysql.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"mysql.js","sourceRoot":"","sources":["../../src/dialects/mysql.ts"],"names":[],"mappings":"AAEA;;;;;;;;;GASG;AACH,MAAM,UAAU,YAAY;IAC1B,OAAO;QACL,WAAW,EAAE,KAAK;QAClB,aAAa,CAAC,OAA8B;YAC1C,gEAAgE;YAChE,OAAO,kBAAkB,CAAC,OAAO,CAAC,CAAC;QACrC,CAAC;KACF,CAAC;AACJ,CAAC;AAED,KAAK,UAAU,kBAAkB,CAAC,OAA8B;IAC9D,MAAM,EAAE,YAAY,EAAE,GAAG,MAAM,MAAM,CAAC,QAAQ,CAAC,CAAC;IAChD,IAAI,UAAyE,CAAC;IAC9E,IAAI,CAAC;QACH,yDAAyD;QACzD,MAAM,KAAK,GAAG,MAAM,MAAM,CAAC,QAAQ,CAAC,CAAC;QACrC,UAAU,GAAG,KAAK,CAAC,UAAU,CAAC;IAChC,CAAC;IAAC,MAAM,CAAC;QACP,MAAM,IAAI,KAAK,CAAC,iEAAiE,CAAC,CAAC;IACrF,CAAC;IACD,MAAM,IAAI,GAAG,UAAU,CAAC;QACtB,GAAG,EAAE,OAAO,CAAC,gBAAgB;QAC7B,eAAe,EAAE,OAAO,CAAC,IAAI,EAAE,GAAG,IAAI,EAAE;KACzC,CAAC,CAAC;IACH,OAAO,IAAI,YAAY,CAAC,EAAE,IAAI,EAAE,IAAa,EAAE,CAAC,CAAC;AACnD,CAAC;AAED,OAAO,EAAE,YAAY,IAAI,OAAO,EAAE,CAAC"}
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
export { default, default as kysely } from "./plugin.js";
|
|
2
|
+
export { configureKyselyApp, dbFromHono, getDb } from "./plugin.js";
|
|
3
|
+
export { registerKyselyRuntime, getKyselyRuntime, tryGetKyselyRuntime, resetKyselyRuntimeForTests } from "./registry.js";
|
|
4
|
+
export { createKyselyInstance, destroyKyselyInstance, resolveConnectionString } from "./pool.js";
|
|
5
|
+
export { withTransaction } from "./transaction.js";
|
|
6
|
+
export type { BuiltInDialect, DialectAdapter, KyselyPluginOptions, KyselyRuntime, MigrationFile, MigrationRecord, MigrationStatus, PoolOptions, SeedsConfig, MigrationsConfig, Kysely, } from "./types.js";
|
|
7
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,OAAO,IAAI,MAAM,EAAE,MAAM,aAAa,CAAC;AACzD,OAAO,EAAE,kBAAkB,EAAE,UAAU,EAAE,KAAK,EAAE,MAAM,aAAa,CAAC;AACpE,OAAO,EAAE,qBAAqB,EAAE,gBAAgB,EAAE,mBAAmB,EAAE,0BAA0B,EAAE,MAAM,eAAe,CAAC;AACzH,OAAO,EAAE,oBAAoB,EAAE,qBAAqB,EAAE,uBAAuB,EAAE,MAAM,WAAW,CAAC;AACjG,OAAO,EAAE,eAAe,EAAE,MAAM,kBAAkB,CAAC;AACnD,YAAY,EACV,cAAc,EACd,cAAc,EACd,mBAAmB,EACnB,aAAa,EACb,aAAa,EACb,eAAe,EACf,eAAe,EACf,WAAW,EACX,WAAW,EACX,gBAAgB,EAChB,MAAM,GACP,MAAM,YAAY,CAAC"}
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
export { default, default as kysely } from "./plugin.js";
|
|
2
|
+
export { configureKyselyApp, dbFromHono, getDb } from "./plugin.js";
|
|
3
|
+
export { registerKyselyRuntime, getKyselyRuntime, tryGetKyselyRuntime, resetKyselyRuntimeForTests } from "./registry.js";
|
|
4
|
+
export { createKyselyInstance, destroyKyselyInstance, resolveConnectionString } from "./pool.js";
|
|
5
|
+
export { withTransaction } from "./transaction.js";
|
|
6
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,OAAO,IAAI,MAAM,EAAE,MAAM,aAAa,CAAC;AACzD,OAAO,EAAE,kBAAkB,EAAE,UAAU,EAAE,KAAK,EAAE,MAAM,aAAa,CAAC;AACpE,OAAO,EAAE,qBAAqB,EAAE,gBAAgB,EAAE,mBAAmB,EAAE,0BAA0B,EAAE,MAAM,eAAe,CAAC;AACzH,OAAO,EAAE,oBAAoB,EAAE,qBAAqB,EAAE,uBAAuB,EAAE,MAAM,WAAW,CAAC;AACjG,OAAO,EAAE,eAAe,EAAE,MAAM,kBAAkB,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"kysely.test-d.d.ts","sourceRoot":"","sources":["../src/kysely.test-d.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import { expectTypeOf, it } from "vitest";
|
|
2
|
+
import { defineLoader } from "./loader.js";
|
|
3
|
+
it("defineLoader infers db type", () => {
|
|
4
|
+
defineLoader(async ({ db }) => {
|
|
5
|
+
expectTypeOf(db).toEqualTypeOf();
|
|
6
|
+
return { ok: true };
|
|
7
|
+
});
|
|
8
|
+
});
|
|
9
|
+
//# sourceMappingURL=kysely.test-d.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"kysely.test-d.js","sourceRoot":"","sources":["../src/kysely.test-d.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,EAAE,EAAE,MAAM,QAAQ,CAAC;AAE1C,OAAO,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAM3C,EAAE,CAAC,6BAA6B,EAAE,GAAG,EAAE;IACrC,YAAY,CAA8B,KAAK,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE;QACzD,YAAY,CAAC,EAAE,CAAC,CAAC,aAAa,EAAsB,CAAC;QACrD,OAAO,EAAE,EAAE,EAAE,IAAI,EAAE,CAAC;IACtB,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC"}
|
package/dist/loader.d.ts
ADDED
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import type { LoaderResult, OtokActionContext, OtokContext, OtokLoader } from "@kamod-ch/otok/server";
|
|
2
|
+
import type { LoaderEnhancer } from "@kamod-ch/otok/route";
|
|
3
|
+
import type { Kysely } from "kysely";
|
|
4
|
+
import { dbFromHono } from "./context.js";
|
|
5
|
+
type LoaderDbContext<DB> = {
|
|
6
|
+
db: Kysely<DB>;
|
|
7
|
+
};
|
|
8
|
+
type ActionDbContext<DB> = LoaderDbContext<DB>;
|
|
9
|
+
/**
|
|
10
|
+
* Wrap a loader with typed `db` from the registered otok-kysely runtime.
|
|
11
|
+
*
|
|
12
|
+
* ```ts
|
|
13
|
+
* export const loader = defineLoader(async ({ db }) => {
|
|
14
|
+
* return db.selectFrom("contacts").selectAll().execute();
|
|
15
|
+
* });
|
|
16
|
+
* ```
|
|
17
|
+
*/
|
|
18
|
+
export declare function defineLoader<Data extends LoaderResult, DB = unknown>(handler: (ctx: OtokContext & LoaderDbContext<DB>) => Data | Promise<Data>): OtokLoader<Data>;
|
|
19
|
+
/** Loader enhancer that injects `db` from the otok-kysely runtime (outermost in composeLoader). */
|
|
20
|
+
export declare function withDb<DB>(): LoaderEnhancer;
|
|
21
|
+
/**
|
|
22
|
+
* Wrap an action with typed `db` from the registered otok-kysely runtime.
|
|
23
|
+
*/
|
|
24
|
+
export declare function defineAction<Result, DB = unknown>(handler: (ctx: OtokActionContext & ActionDbContext<DB>) => Result | Promise<Result>): (context: OtokActionContext) => Result | Promise<Result>;
|
|
25
|
+
export { dbFromHono };
|
|
26
|
+
//# sourceMappingURL=loader.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"loader.d.ts","sourceRoot":"","sources":["../src/loader.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,iBAAiB,EAAE,WAAW,EAAE,UAAU,EAAE,MAAM,uBAAuB,CAAC;AACtG,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAC;AAC3D,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,QAAQ,CAAC;AACrC,OAAO,EAAE,UAAU,EAAE,MAAM,cAAc,CAAC;AAG1C,KAAK,eAAe,CAAC,EAAE,IAAI;IACzB,EAAE,EAAE,MAAM,CAAC,EAAE,CAAC,CAAC;CAChB,CAAC;AAEF,KAAK,eAAe,CAAC,EAAE,IAAI,eAAe,CAAC,EAAE,CAAC,CAAC;AAa/C;;;;;;;;GAQG;AACH,wBAAgB,YAAY,CAAC,IAAI,SAAS,YAAY,EAAE,EAAE,GAAG,OAAO,EAClE,OAAO,EAAE,CAAC,GAAG,EAAE,WAAW,GAAG,eAAe,CAAC,EAAE,CAAC,KAAK,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,GACxE,UAAU,CAAC,IAAI,CAAC,CAElB;AAED,mGAAmG;AACnG,wBAAgB,MAAM,CAAC,EAAE,KAAK,cAAc,CAG3C;AAED;;GAEG;AACH,wBAAgB,YAAY,CAAC,MAAM,EAAE,EAAE,GAAG,OAAO,EAC/C,OAAO,EAAE,CAAC,GAAG,EAAE,iBAAiB,GAAG,eAAe,CAAC,EAAE,CAAC,KAAK,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,GAClF,CAAC,OAAO,EAAE,iBAAiB,KAAK,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAE1D;AAED,OAAO,EAAE,UAAU,EAAE,CAAC"}
|
package/dist/loader.js
ADDED
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import { dbFromHono } from "./context.js";
|
|
2
|
+
import { tryGetKyselyRuntime } from "./registry.js";
|
|
3
|
+
function resolveDb(hono) {
|
|
4
|
+
const runtime = tryGetKyselyRuntime();
|
|
5
|
+
if (!runtime) {
|
|
6
|
+
throw new Error("otok-kysely: defineLoader requires kysely() plugin or registerKyselyRuntime(). " +
|
|
7
|
+
"Use loader: ({ hono }) => dbFromHono(hono) for manual wiring.");
|
|
8
|
+
}
|
|
9
|
+
return dbFromHono(hono, runtime.contextKey);
|
|
10
|
+
}
|
|
11
|
+
/**
|
|
12
|
+
* Wrap a loader with typed `db` from the registered otok-kysely runtime.
|
|
13
|
+
*
|
|
14
|
+
* ```ts
|
|
15
|
+
* export const loader = defineLoader(async ({ db }) => {
|
|
16
|
+
* return db.selectFrom("contacts").selectAll().execute();
|
|
17
|
+
* });
|
|
18
|
+
* ```
|
|
19
|
+
*/
|
|
20
|
+
export function defineLoader(handler) {
|
|
21
|
+
return (context) => handler({ ...context, db: resolveDb(context.hono) });
|
|
22
|
+
}
|
|
23
|
+
/** Loader enhancer that injects `db` from the otok-kysely runtime (outermost in composeLoader). */
|
|
24
|
+
export function withDb() {
|
|
25
|
+
return (loader) => (context) => loader({ ...context, db: resolveDb(context.hono) });
|
|
26
|
+
}
|
|
27
|
+
/**
|
|
28
|
+
* Wrap an action with typed `db` from the registered otok-kysely runtime.
|
|
29
|
+
*/
|
|
30
|
+
export function defineAction(handler) {
|
|
31
|
+
return (context) => handler({ ...context, db: resolveDb(context.hono) });
|
|
32
|
+
}
|
|
33
|
+
export { dbFromHono };
|
|
34
|
+
//# sourceMappingURL=loader.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"loader.js","sourceRoot":"","sources":["../src/loader.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,UAAU,EAAE,MAAM,cAAc,CAAC;AAC1C,OAAO,EAAE,mBAAmB,EAAE,MAAM,eAAe,CAAC;AAQpD,SAAS,SAAS,CAAK,IAAyB;IAC9C,MAAM,OAAO,GAAG,mBAAmB,EAAM,CAAC;IAC1C,IAAI,CAAC,OAAO,EAAE,CAAC;QACb,MAAM,IAAI,KAAK,CACb,iFAAiF;YAC/E,+DAA+D,CAClE,CAAC;IACJ,CAAC;IACD,OAAO,UAAU,CAAK,IAAI,EAAE,OAAO,CAAC,UAAU,CAAC,CAAC;AAClD,CAAC;AAED;;;;;;;;GAQG;AACH,MAAM,UAAU,YAAY,CAC1B,OAAyE;IAEzE,OAAO,CAAC,OAAO,EAAE,EAAE,CAAC,OAAO,CAAC,EAAE,GAAG,OAAO,EAAE,EAAE,EAAE,SAAS,CAAK,OAAO,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;AAC/E,CAAC;AAED,mGAAmG;AACnG,MAAM,UAAU,MAAM;IACpB,OAAO,CAAC,MAAM,EAAE,EAAE,CAAC,CAAC,OAAO,EAAE,EAAE,CAC7B,MAAM,CAAC,EAAE,GAAG,OAAO,EAAE,EAAE,EAAE,SAAS,CAAK,OAAO,CAAC,IAAI,CAAC,EAAiB,CAAC,CAAC;AAC3E,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,YAAY,CAC1B,OAAmF;IAEnF,OAAO,CAAC,OAAO,EAAE,EAAE,CAAC,OAAO,CAAC,EAAE,GAAG,OAAO,EAAE,EAAE,EAAE,SAAS,CAAK,OAAO,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;AAC/E,CAAC;AAED,OAAO,EAAE,UAAU,EAAE,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/migrations/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,oBAAoB,EACpB,kBAAkB,EAClB,kBAAkB,EAClB,WAAW,EACX,SAAS,GACV,MAAM,aAAa,CAAC;AACrB,YAAY,EAAE,aAAa,EAAE,eAAe,EAAE,eAAe,EAAE,MAAM,aAAa,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/migrations/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,oBAAoB,EACpB,kBAAkB,EAClB,kBAAkB,EAClB,WAAW,EACX,SAAS,GACV,MAAM,aAAa,CAAC"}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import type { Kysely } from "kysely";
|
|
2
|
+
import type { MigrationFile, MigrationRecord, MigrationStatus } from "../types.js";
|
|
3
|
+
export declare function loadMigrationFiles(directory: string): Promise<MigrationFile[]>;
|
|
4
|
+
export declare function ensureMigrationsTable(db: Kysely<unknown>, tableName: string): Promise<void>;
|
|
5
|
+
export declare function getAppliedMigrations(db: Kysely<unknown>, tableName: string): Promise<MigrationRecord[]>;
|
|
6
|
+
export declare function getMigrationStatus(db: Kysely<unknown>, directory: string, tableName: string): Promise<MigrationStatus[]>;
|
|
7
|
+
export declare function migrateUp(db: Kysely<unknown>, directory: string, tableName: string): Promise<string[]>;
|
|
8
|
+
export declare function migrateDown(db: Kysely<unknown>, directory: string, tableName: string, steps?: number): Promise<string[]>;
|
|
9
|
+
export type { MigrationFile, MigrationRecord, MigrationStatus };
|
|
10
|
+
//# sourceMappingURL=runner.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"runner.d.ts","sourceRoot":"","sources":["../../src/migrations/runner.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,QAAQ,CAAC;AAErC,OAAO,KAAK,EAAE,aAAa,EAAE,eAAe,EAAE,eAAe,EAAE,MAAM,aAAa,CAAC;AAInF,wBAAsB,kBAAkB,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,aAAa,EAAE,CAAC,CA8BpF;AAED,wBAAsB,qBAAqB,CAAC,EAAE,EAAE,MAAM,CAAC,OAAO,CAAC,EAAE,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAOjG;AAED,wBAAsB,oBAAoB,CACxC,EAAE,EAAE,MAAM,CAAC,OAAO,CAAC,EACnB,SAAS,EAAE,MAAM,GAChB,OAAO,CAAC,eAAe,EAAE,CAAC,CAY5B;AAED,wBAAsB,kBAAkB,CACtC,EAAE,EAAE,MAAM,CAAC,OAAO,CAAC,EACnB,SAAS,EAAE,MAAM,EACjB,SAAS,EAAE,MAAM,GAChB,OAAO,CAAC,eAAe,EAAE,CAAC,CAa5B;AAED,wBAAsB,SAAS,CAC7B,EAAE,EAAE,MAAM,CAAC,OAAO,CAAC,EACnB,SAAS,EAAE,MAAM,EACjB,SAAS,EAAE,MAAM,GAChB,OAAO,CAAC,MAAM,EAAE,CAAC,CAiBnB;AAED,wBAAsB,WAAW,CAC/B,EAAE,EAAE,MAAM,CAAC,OAAO,CAAC,EACnB,SAAS,EAAE,MAAM,EACjB,SAAS,EAAE,MAAM,EACjB,KAAK,SAAI,GACR,OAAO,CAAC,MAAM,EAAE,CAAC,CAoBnB;AAED,YAAY,EAAE,aAAa,EAAE,eAAe,EAAE,eAAe,EAAE,CAAC"}
|
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
import { readdir, readFile } from "node:fs/promises";
|
|
2
|
+
import { join } from "node:path";
|
|
3
|
+
import { sql } from "kysely";
|
|
4
|
+
const MIGRATION_FILE_PATTERN = /^(\d{14})_(.+)\.(up|down)\.sql$/;
|
|
5
|
+
export async function loadMigrationFiles(directory) {
|
|
6
|
+
let entries;
|
|
7
|
+
try {
|
|
8
|
+
entries = await readdir(directory);
|
|
9
|
+
}
|
|
10
|
+
catch {
|
|
11
|
+
return [];
|
|
12
|
+
}
|
|
13
|
+
const groups = new Map();
|
|
14
|
+
for (const entry of entries) {
|
|
15
|
+
const match = MIGRATION_FILE_PATTERN.exec(entry);
|
|
16
|
+
if (!match)
|
|
17
|
+
continue;
|
|
18
|
+
const [, timestamp, slug, direction] = match;
|
|
19
|
+
const name = `${timestamp}_${slug}`;
|
|
20
|
+
const content = await readFile(join(directory, entry), "utf8");
|
|
21
|
+
const group = groups.get(name) ?? {};
|
|
22
|
+
if (direction === "up")
|
|
23
|
+
group.up = content;
|
|
24
|
+
if (direction === "down")
|
|
25
|
+
group.down = content;
|
|
26
|
+
groups.set(name, group);
|
|
27
|
+
}
|
|
28
|
+
return [...groups.entries()]
|
|
29
|
+
.filter(([, group]) => group.up && group.down)
|
|
30
|
+
.sort(([a], [b]) => a.localeCompare(b))
|
|
31
|
+
.map(([name, group]) => ({
|
|
32
|
+
name,
|
|
33
|
+
up: group.up,
|
|
34
|
+
down: group.down,
|
|
35
|
+
}));
|
|
36
|
+
}
|
|
37
|
+
export async function ensureMigrationsTable(db, tableName) {
|
|
38
|
+
await sql `
|
|
39
|
+
CREATE TABLE IF NOT EXISTS ${sql.ref(tableName)} (
|
|
40
|
+
name TEXT PRIMARY KEY,
|
|
41
|
+
applied_at TEXT NOT NULL
|
|
42
|
+
)
|
|
43
|
+
`.execute(db);
|
|
44
|
+
}
|
|
45
|
+
export async function getAppliedMigrations(db, tableName) {
|
|
46
|
+
await ensureMigrationsTable(db, tableName);
|
|
47
|
+
const rows = await db
|
|
48
|
+
.selectFrom(tableName)
|
|
49
|
+
.select(["name", "applied_at"])
|
|
50
|
+
.orderBy("name")
|
|
51
|
+
.execute();
|
|
52
|
+
return rows.map((row) => {
|
|
53
|
+
const record = row;
|
|
54
|
+
return { name: record.name, appliedAt: new Date(record.applied_at) };
|
|
55
|
+
});
|
|
56
|
+
}
|
|
57
|
+
export async function getMigrationStatus(db, directory, tableName) {
|
|
58
|
+
const files = await loadMigrationFiles(directory);
|
|
59
|
+
const applied = await getAppliedMigrations(db, tableName);
|
|
60
|
+
const appliedMap = new Map(applied.map((record) => [record.name, record]));
|
|
61
|
+
return files.map((file) => {
|
|
62
|
+
const record = appliedMap.get(file.name);
|
|
63
|
+
return {
|
|
64
|
+
name: file.name,
|
|
65
|
+
applied: Boolean(record),
|
|
66
|
+
appliedAt: record?.appliedAt,
|
|
67
|
+
};
|
|
68
|
+
});
|
|
69
|
+
}
|
|
70
|
+
export async function migrateUp(db, directory, tableName) {
|
|
71
|
+
const files = await loadMigrationFiles(directory);
|
|
72
|
+
const applied = await getAppliedMigrations(db, tableName);
|
|
73
|
+
const appliedNames = new Set(applied.map((record) => record.name));
|
|
74
|
+
const migrated = [];
|
|
75
|
+
for (const file of files) {
|
|
76
|
+
if (appliedNames.has(file.name))
|
|
77
|
+
continue;
|
|
78
|
+
await sql.raw(file.up).execute(db);
|
|
79
|
+
await db
|
|
80
|
+
.insertInto(tableName)
|
|
81
|
+
.values({ name: file.name, applied_at: new Date().toISOString() })
|
|
82
|
+
.execute();
|
|
83
|
+
migrated.push(file.name);
|
|
84
|
+
}
|
|
85
|
+
return migrated;
|
|
86
|
+
}
|
|
87
|
+
export async function migrateDown(db, directory, tableName, steps = 1) {
|
|
88
|
+
const files = await loadMigrationFiles(directory);
|
|
89
|
+
const applied = await getAppliedMigrations(db, tableName);
|
|
90
|
+
const rolledBack = [];
|
|
91
|
+
const toRollback = applied
|
|
92
|
+
.sort((a, b) => b.name.localeCompare(a.name))
|
|
93
|
+
.slice(0, steps);
|
|
94
|
+
for (const record of toRollback) {
|
|
95
|
+
const file = files.find((entry) => entry.name === record.name);
|
|
96
|
+
if (!file) {
|
|
97
|
+
throw new Error(`otok-kysely: migration "${record.name}" has no down file.`);
|
|
98
|
+
}
|
|
99
|
+
await sql.raw(file.down).execute(db);
|
|
100
|
+
await db.deleteFrom(tableName).where("name", "=", record.name).execute();
|
|
101
|
+
rolledBack.push(record.name);
|
|
102
|
+
}
|
|
103
|
+
return rolledBack;
|
|
104
|
+
}
|
|
105
|
+
//# sourceMappingURL=runner.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"runner.js","sourceRoot":"","sources":["../../src/migrations/runner.ts"],"names":[],"mappings":"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"}
|
package/dist/plugin.d.ts
ADDED
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import type { Hono } from "hono";
|
|
2
|
+
import type { KyselyPluginOptions, KyselyRuntime } from "./types.js";
|
|
3
|
+
export declare function configureKyselyApp(app: Hono, options: KyselyPluginOptions): Promise<KyselyRuntime>;
|
|
4
|
+
/** Otok plugin factory — register in otok.config.ts plugins array. */
|
|
5
|
+
export default function kysely(options: KyselyPluginOptions): import("@kamod-ch/otok-config").OtokPlugin<unknown>;
|
|
6
|
+
export { dbFromHono, getDb } from "./context.js";
|
|
7
|
+
//# sourceMappingURL=plugin.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"plugin.d.ts","sourceRoot":"","sources":["../src/plugin.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,MAAM,CAAC;AAIjC,OAAO,KAAK,EAAE,mBAAmB,EAAE,aAAa,EAAE,MAAM,YAAY,CAAC;AAerE,wBAAsB,kBAAkB,CAAC,GAAG,EAAE,IAAI,EAAE,OAAO,EAAE,mBAAmB,GAAG,OAAO,CAAC,aAAa,CAAC,CAuBxG;AA4BD,sEAAsE;AACtE,MAAM,CAAC,OAAO,UAAU,MAAM,CAAC,OAAO,EAAE,mBAAmB,uDAgB1D;AAED,OAAO,EAAE,UAAU,EAAE,KAAK,EAAE,MAAM,cAAc,CAAC"}
|