mirror of
https://github.com/knex/knex.git
synced 2025-12-28 15:38:41 +00:00
Introduce the "infamous triplet" export (#4181)
This commit is contained in:
parent
2b1fed5434
commit
177938afeb
@ -1,4 +1,4 @@
|
||||
*.stub
|
||||
#
|
||||
lib/util/import-file.js
|
||||
test/jake-util/knexfile-imports
|
||||
#
|
||||
lib/migrations/util/import-file.js
|
||||
test/jake-util/knexfile-imports
|
||||
|
||||
6
.github/workflows/linting.yml
vendored
6
.github/workflows/linting.yml
vendored
@ -1,6 +1,6 @@
|
||||
---
|
||||
|
||||
name: Linting
|
||||
name: Linting and Types
|
||||
|
||||
on:
|
||||
push:
|
||||
@ -13,7 +13,7 @@ on:
|
||||
jobs:
|
||||
build:
|
||||
runs-on: ubuntu-latest
|
||||
name: Linting
|
||||
name: Linting and Types
|
||||
|
||||
strategy:
|
||||
matrix:
|
||||
@ -35,6 +35,6 @@ jobs:
|
||||
run: npm install
|
||||
|
||||
- name: Run lint:everything
|
||||
run: echo npm run lint:everything
|
||||
run: npm run lint:everything
|
||||
env:
|
||||
CI: true
|
||||
|
||||
28
README.md
28
README.md
@ -88,3 +88,31 @@ try {
|
||||
console.error(e);
|
||||
};
|
||||
```
|
||||
|
||||
## TypeScript example
|
||||
```
|
||||
import { Knex, knex } from 'knex'
|
||||
|
||||
interface User {
|
||||
id: number;
|
||||
age: number;
|
||||
name: string;
|
||||
active: boolean;
|
||||
departmentId: number;
|
||||
}
|
||||
|
||||
const config: Knex.Config = {
|
||||
client: 'sqlite3',
|
||||
connection: {
|
||||
filename: './data.db',
|
||||
},
|
||||
});
|
||||
|
||||
const knexInstance = knex(config);
|
||||
|
||||
try {
|
||||
const users = await knex<User>('users').select('id', 'age');
|
||||
} catch (err) {
|
||||
// error handling
|
||||
}
|
||||
```
|
||||
|
||||
10
UPGRADING.md
10
UPGRADING.md
@ -2,6 +2,16 @@
|
||||
|
||||
### Upgrading to version 0.95.0+
|
||||
|
||||
* TypeScript type exports changed significantly. While `import Knex from 'knex';` used to import the knex instantiation function, the namespace and the interface for the knex instantiation function/object, there is now a clear distinction between them:
|
||||
```
|
||||
import { knex } from 'knex' // this is a function that you call to instantiate knex
|
||||
import { Knex } from 'knex' // this is a namespace, and a type of a knex object
|
||||
import KnexTimeoutError = Knex.KnexTimeoutError; // this is a class from the Knex namespace
|
||||
|
||||
const config: Knex.Config = {} // this is a type from the Knex namespace
|
||||
const knexInstance: Knex = knex(config)
|
||||
```
|
||||
|
||||
* Connection url parsing changed from legacy [url.parse](https://nodejs.org/docs/latest-v10.x/api/url.html#url_legacy_url_api) to [WHATWG URL](https://nodejs.org/docs/latest-v10.x/api/url.html#url_the_whatwg_url_api). If you have symbols, unusual for a URL (not A-z, not digits, not dot, not dash) - check [Node.js docs](https://nodejs.org/docs/latest-v10.x/api/url.html#url_percent_encoding_in_urls) for details
|
||||
|
||||
* `Knex.raw` support dropped, use `knex.raw` (`require('knex').raw()` won't work anymore)
|
||||
|
||||
17
knex.js
17
knex.js
@ -5,4 +5,19 @@
|
||||
// For details and documentation:
|
||||
// http://knexjs.org
|
||||
|
||||
module.exports = require('./lib/index');
|
||||
const knex = require('./lib/index');
|
||||
|
||||
/**
|
||||
* These export configurations enable JS and TS developers
|
||||
* to consume knex in whatever way best suits their needs.
|
||||
* Some examples of supported import syntax includes:
|
||||
* - `const knex = require('knex')`
|
||||
* - `const { knex } = require('knex')`
|
||||
* - `import * as knex from 'knex'`
|
||||
* - `import { knex } from 'knex'`
|
||||
* - `import knex from 'knex'`
|
||||
*/
|
||||
knex.knex = knex;
|
||||
knex.default = knex;
|
||||
|
||||
module.exports = knex;
|
||||
|
||||
@ -1,4 +1,6 @@
|
||||
export const clientConfig = {
|
||||
import type { Knex } from "../types";
|
||||
|
||||
export const clientConfig: Knex.Config = {
|
||||
client: 'sqlite3',
|
||||
connection: {
|
||||
filename: './mydb.sqlite',
|
||||
|
||||
@ -1,19 +1,20 @@
|
||||
import Knex from '../types';
|
||||
import { Knex, knex } from '../types';
|
||||
import { expectType } from 'tsd';
|
||||
import { clientConfig } from './common';
|
||||
|
||||
const knex = Knex(clientConfig);
|
||||
const knexInstance = knex(clientConfig);
|
||||
|
||||
// Use:
|
||||
// import Knex from 'knex'
|
||||
// when "esModuleInterop": true
|
||||
// import { Knex } from 'knex'
|
||||
|
||||
// This would be `declare module 'knex'` in runtime code
|
||||
declare module '../types' {
|
||||
interface QueryBuilder {
|
||||
customSelect<TRecord, TResult>(
|
||||
value: number
|
||||
): QueryBuilder<TRecord, TResult>;
|
||||
namespace Knex {
|
||||
interface QueryBuilder {
|
||||
customSelect<TRecord, TResult>(
|
||||
value: number
|
||||
): Knex.QueryBuilder<TRecord, TResult>;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -22,5 +23,5 @@ Knex.QueryBuilder.extend('customSelect', function (value: number) {
|
||||
});
|
||||
|
||||
const main = async () => {
|
||||
expectType<number[]>(await knex('users').customSelect<any, number[]>(42));
|
||||
expectType<number[]>(await knexInstance('users').customSelect<any, number[]>(42));
|
||||
};
|
||||
|
||||
@ -1,8 +1,8 @@
|
||||
import Knex from '../types';
|
||||
import { knex, Knex } from '../types';
|
||||
import { clientConfig } from './common';
|
||||
import { expectType } from 'tsd';
|
||||
|
||||
const knex = Knex(clientConfig);
|
||||
const knexInstance = knex(clientConfig);
|
||||
|
||||
interface User {
|
||||
id: number;
|
||||
@ -57,39 +57,39 @@ declare module '../types/tables' {
|
||||
const main = async () => {
|
||||
// # Select:
|
||||
|
||||
expectType<any[]>(await knex('users'));
|
||||
expectType<any[]>(await knexInstance('users'));
|
||||
|
||||
// This test (others similar to it) may seem useless but they are needed
|
||||
// to test for left-to-right inference issues eg: #3260
|
||||
expectType<User[]>(await knex('users'));
|
||||
expectType<User[]>(await knex<User>('users'));
|
||||
expectType<User[]>(await knex('users_inferred'));
|
||||
expectType<User[]>(await knex('users_composite'));
|
||||
expectType<User[]>(await knexInstance('users'));
|
||||
expectType<User[]>(await knexInstance<User>('users'));
|
||||
expectType<User[]>(await knexInstance('users_inferred'));
|
||||
expectType<User[]>(await knexInstance('users_composite'));
|
||||
|
||||
expectType<any[]>(await knex('users').select('id'));
|
||||
expectType<Partial<User>[]>(await knex('users').select('id'));
|
||||
expectType<any[]>(await knexInstance('users').select('id'));
|
||||
expectType<Partial<User>[]>(await knexInstance('users').select('id'));
|
||||
|
||||
expectType<Pick<User, 'id'>[]>(await knex('users_inferred').select('id'));
|
||||
expectType<Pick<User, 'id'>[]>(await knex('users_composite').select('id'));
|
||||
expectType<Pick<User, 'id'>[]>(await knexInstance('users_inferred').select('id'));
|
||||
expectType<Pick<User, 'id'>[]>(await knexInstance('users_composite').select('id'));
|
||||
expectType<Pick<User, 'id' | 'age'>[]>(
|
||||
await knex('users_inferred').select('id').select('age')
|
||||
await knexInstance('users_inferred').select('id').select('age')
|
||||
);
|
||||
|
||||
expectType<Pick<User, 'id' | 'age'>[]>(
|
||||
await knex('users_composite').select('id').select('age')
|
||||
await knexInstance('users_composite').select('id').select('age')
|
||||
);
|
||||
|
||||
expectType<Pick<User, 'id' | 'age'>[]>(
|
||||
await knex('users_inferred').select('id', 'age')
|
||||
await knexInstance('users_inferred').select('id', 'age')
|
||||
);
|
||||
expectType<Pick<User, 'id' | 'age'>[]>(
|
||||
await knex('users_composite').select('id', 'age')
|
||||
await knexInstance('users_composite').select('id', 'age')
|
||||
);
|
||||
|
||||
expectType<Pick<User, 'id'> | undefined>(
|
||||
await knex.first('id').from('users_inferred')
|
||||
await knexInstance.first('id').from('users_inferred')
|
||||
);
|
||||
expectType<Pick<User, 'id'> | undefined>(
|
||||
await knex.first('id').from('users_composite')
|
||||
await knexInstance.first('id').from('users_composite')
|
||||
);
|
||||
};
|
||||
|
||||
@ -1,8 +1,30 @@
|
||||
import { expectAssignable, expectType } from 'tsd';
|
||||
import Knex, { QueryBuilder } from '../types';
|
||||
import { clientConfig } from './common';
|
||||
|
||||
const knex = Knex(clientConfig);
|
||||
import knexDefault, { Knex, knex } from '../types';
|
||||
import * as knexStar from '../types';
|
||||
import knexCjsImport = require('../');
|
||||
import QueryBuilder = Knex.QueryBuilder;
|
||||
import KnexTimeoutError = Knex.KnexTimeoutError;
|
||||
|
||||
const knexCjs = require('../knex');
|
||||
const { knex: knexCjsNamed } = require('../knex');
|
||||
|
||||
expectType<Knex<any, unknown[]>>(knexDefault({}));
|
||||
expectType<Knex<any, unknown[]>>(knex({}));
|
||||
expectType<Knex<any, unknown[]>>(knexStar.default({}));
|
||||
expectType<Knex<any, unknown[]>>(knexStar.knex({}));
|
||||
expectType<Knex<any, unknown[]>>(knexCjsImport.default({}));
|
||||
expectType<Knex<any, unknown[]>>(knexCjsImport.knex({}));
|
||||
expectType<KnexTimeoutError>(new KnexTimeoutError());
|
||||
expectType<KnexTimeoutError>(new KnexTimeoutError());
|
||||
|
||||
// eslint-disable-next-line
|
||||
expectType<any>(knexCjs({}));
|
||||
// eslint-disable-next-line
|
||||
expectType<any>(knexCjsNamed({}));
|
||||
|
||||
const knexInstance = knexDefault(clientConfig);
|
||||
|
||||
// ToDo remove this copy-pasted type after we can export it as a named properly
|
||||
type DeferredKeySelection<
|
||||
@ -52,7 +74,7 @@ expectType<
|
||||
DeferredKeySelection<User, never, false, {}, false, {}, never>[]
|
||||
>
|
||||
>(
|
||||
knex
|
||||
knexInstance
|
||||
.table<User>('users')
|
||||
.insert({ id: 10, active: true })
|
||||
.onConflict('id')
|
||||
@ -61,7 +83,7 @@ expectType<
|
||||
);
|
||||
|
||||
expectAssignable<QueryBuilder>(
|
||||
knex
|
||||
knexInstance
|
||||
.insert({ col: 'x' })
|
||||
.into('table')
|
||||
.onConflict('col')
|
||||
@ -70,7 +92,7 @@ expectAssignable<QueryBuilder>(
|
||||
);
|
||||
|
||||
expectAssignable<QueryBuilder>(
|
||||
knex
|
||||
knexInstance
|
||||
.insert({ id: 10, active: true })
|
||||
.into('table')
|
||||
.onConflict(['id'])
|
||||
|
||||
10
types/index.d.ts
vendored
10
types/index.d.ts
vendored
@ -335,9 +335,9 @@ interface TransactionConfig {
|
||||
userParams?: Record<string, any>;
|
||||
doNotRejectOnRollback?: boolean;
|
||||
connection?: any;
|
||||
};
|
||||
}
|
||||
|
||||
interface Knex<TRecord extends {} = any, TResult = unknown[]>
|
||||
export interface Knex<TRecord extends {} = any, TResult = unknown[]>
|
||||
extends Knex.QueryInterface<TRecord, TResult>, events.EventEmitter {
|
||||
<TTable extends Knex.TableNames>(
|
||||
tableName: TTable,
|
||||
@ -393,11 +393,11 @@ interface Knex<TRecord extends {} = any, TResult = unknown[]>
|
||||
withUserParams(params: Record<string, any>): Knex;
|
||||
}
|
||||
|
||||
declare function Knex<TRecord extends {} = any, TResult = unknown[]>(
|
||||
export declare function knex<TRecord extends {} = any, TResult = unknown[]>(
|
||||
config: Knex.Config | string
|
||||
): Knex<TRecord, TResult>;
|
||||
|
||||
declare namespace Knex {
|
||||
export declare namespace Knex {
|
||||
//
|
||||
// Utility Types
|
||||
//
|
||||
@ -2261,4 +2261,4 @@ declare namespace Knex {
|
||||
export class KnexTimeoutError extends Error {}
|
||||
}
|
||||
|
||||
export = Knex;
|
||||
export default knex;
|
||||
|
||||
1118
types/test.ts
1118
types/test.ts
File diff suppressed because it is too large
Load Diff
Loading…
x
Reference in New Issue
Block a user