Skip to content

Commit

Permalink
feat: add Kysely adapter. (#374)
Browse files Browse the repository at this point in the history
* install kysely.

* add createKysely @ LibAdapters.

* remove unused import.

* implement createKysely @ Adapters.

* add Kysely sample.

* add Kysely test suite.

* add Kysely to readme.

* blankline

* blankline

* actually it is supported..

* add keywords to package.json.
  • Loading branch information
igalklebanov committed Dec 20, 2023
1 parent 37549b5 commit 40a0018
Show file tree
Hide file tree
Showing 7 changed files with 164 additions and 5 deletions.
24 changes: 22 additions & 2 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

11 changes: 9 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,9 @@
"ut",
"sql",
"pgsql",
"postgresql"
"postgresql",
"knex",
"kysely"
],
"license": "MIT",
"dependencies": {
Expand Down Expand Up @@ -77,6 +79,7 @@
"html-webpack-plugin": "^4.3.0",
"istanbul-instrumenter-loader": "^2.0.0",
"knex": "^0.21.15",
"kysely": "^0.26.3",
"mocha": "^8.0.1",
"mochapack": "^2.0.6",
"monaco-editor": "^0.20.0",
Expand Down Expand Up @@ -107,6 +110,7 @@
},
"peerDependencies": {
"knex": ">=0.20",
"kysely": ">=0.26",
"pg-promise": ">=10.8.7",
"slonik": ">=23.0.1",
"typeorm": ">=0.2.29"
Expand All @@ -124,6 +128,9 @@
"knex": {
"optional": true
},
"kysely": {
"optional": true
},
"mikro-orm": {
"optional": true
}
Expand All @@ -138,4 +145,4 @@
"instrument": false,
"sourceMap": false
}
}
}
1 change: 1 addition & 0 deletions readme.md
Original file line number Diff line number Diff line change
Expand Up @@ -181,6 +181,7 @@ pg-mem provides handy shortcuts to create instances of popular libraries that wi
- slonik
- typeorm
- knex
- kysely
- mikro-orm

[See the wiki for more details](https://github.com/oguimbal/pg-mem/wiki/Libraries-adapters)
Expand Down
82 changes: 82 additions & 0 deletions samples/kysely/kysely.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
import { expect } from 'chai';
import { newDb } from '../../src/db';

type GeneratedAlways<T> = import('kysely').GeneratedAlways<T>;

interface DB {
users: {
id: GeneratedAlways<number>;
user_name: string | null;
};
accounts: {
id: GeneratedAlways<number>;
account_name: string | null;
user_id: number | null;
};
}

export async function kyselySample() {

// ========= CONNECT ==========

// Create a new DB instance
const mem = newDb();

// create a Kysely instance bound to this db
// => This replaces new require('kysely').Kysely({ ... })
const kysely = mem.adapters.createKysely() as import('kysely').Kysely<DB>;


// ========= USE AS USUAL ==========

// Create a table
await kysely.schema
.createTable('users')
.addColumn('id', 'serial', (cb) => cb.primaryKey())
.addColumn('user_name', 'varchar(255)')
.execute();

// ...and another
await kysely.schema
.createTable('accounts')
.addColumn('id', 'serial', (cb) => cb.primaryKey())
.addColumn('account_name', 'varchar(255)')
.addColumn('user_id', 'integer', (cb) => cb.references('users.id'))
.addForeignKeyConstraint('fk_user_id', ['user_id'], 'users', ['id'])
.execute();

// Then query user table...
await kysely.insertInto('users').values({ user_name: 'Tim' }).execute();

// ... and check
expect(mem.public.many('select * from users'))
.to.deep.equal([{
id: 1,
user_name: 'Tim',
}]);

// Then insert into account table...
await kysely
.insertInto('accounts')
.values({ account_name: 'kysely', user_id: 1 })
.execute();

// ... and check
expect(mem.public.many('select * from accounts'))
.to.deep.equal([{
id: 1,
account_name: 'kysely',
user_id: 1,
}]);

// Try to run a join
const selectedRows = await kysely.selectFrom('users')
.innerJoin('accounts', 'users.id', 'accounts.user_id')
.select(['users.user_name as user', 'accounts.account_name as account'])
.execute();

expect(selectedRows)
.to.deep.equal([
{ user: 'Tim', account: 'kysely' },
]);
}
12 changes: 11 additions & 1 deletion src/adapters/adapters.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { LibAdapters, IMemoryDb, NotSupported, QueryResult, DataType } from '../interfaces';
import { LibAdapters, IMemoryDb, NotSupported, QueryResult } from '../interfaces';
import lru from 'lru-cache';
import { compareVersions } from '../utils';
import { toLiteral } from '../misc/pg-utils';
Expand Down Expand Up @@ -324,6 +324,16 @@ export class Adapters implements LibAdapters {
return knex;
}

createKysely(queryLatency?: number, kyselyConfig?: object): any {
const { Kysely, PostgresDialect } = __non_webpack_require__('kysely');
const pg = this.createPg(queryLatency);
return new Kysely({
...kyselyConfig,
dialect: new PostgresDialect({
pool: new pg.Pool(),
}),
});
}

async createMikroOrm(mikroOrmOptions: any, queryLatency?: number) {

Expand Down
3 changes: 3 additions & 0 deletions src/interfaces.ts
Original file line number Diff line number Diff line change
Expand Up @@ -219,6 +219,9 @@ export interface LibAdapters {
/** Create a Knex.js instance bound to this db */
createKnex(queryLatency?: number, knexConfig?: object): any;

/** Create a Kysely instance bound to this db */
createKysely(queryLatency?: number, kyselyConfig?: object): any;

/** Create a mikro-orm instance bound to this db */
createMikroOrm(mikroOrmOptions: any, queryLatency?: number): Promise<any>
}
Expand Down
36 changes: 36 additions & 0 deletions src/tests/kysely-real.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
import { newDb } from '../db';
import { kyselySample } from '../../samples/kysely/kysely';
import { expect } from 'chai';

describe('Kysely', () => {
it('can perform sample', async () => {
await kyselySample();
});

it('should use kysely config from parameter', async () => {
const mem = newDb();
const camelCasePlugin = new (await import('kysely')).CamelCasePlugin();
const kysely = mem.adapters.createKysely(
undefined,
{
plugins: [camelCasePlugin]
}
) as import('kysely').Kysely<any>;
const executor = kysely.getExecutor();
expect(executor.plugins).to.deep.equal([camelCasePlugin]);
});

it('should ignore dialect prop in kysely config', async () => {
const mem = newDb();
const kysely = mem.adapters.createKysely(
undefined,
{
dialect: new (await import('kysely')).MysqlDialect({
pool: {} as any,
})
}
) as import('kysely').Kysely<any>;
const executor = kysely.getExecutor();
expect(executor.adapter).to.be.instanceOf((await import('kysely')).PostgresAdapter);
});
});

0 comments on commit 40a0018

Please sign in to comment.