kysely 0.29.0-rc.0 → 0.29.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/dist/dialect/database-introspector.d.ts +0 -13
- package/dist/dialect/mssql/mssql-dialect-config.d.ts +1 -11
- package/dist/dialect/mssql/mssql-driver.js +3 -7
- package/dist/dialect/mssql/mssql-introspector.d.ts +1 -7
- package/dist/dialect/mssql/mssql-introspector.js +0 -5
- package/dist/dialect/mysql/mysql-introspector.d.ts +1 -7
- package/dist/dialect/mysql/mysql-introspector.js +0 -5
- package/dist/dialect/mysql/mysql-query-compiler.d.ts +6 -0
- package/dist/dialect/mysql/mysql-query-compiler.js +10 -1
- package/dist/dialect/postgres/postgres-introspector.d.ts +1 -7
- package/dist/dialect/postgres/postgres-introspector.js +18 -17
- package/dist/dialect/sqlite/sqlite-introspector.d.ts +1 -7
- package/dist/dialect/sqlite/sqlite-introspector.js +0 -5
- package/dist/dialect/sqlite/sqlite-query-compiler.d.ts +1 -0
- package/dist/dialect/sqlite/sqlite-query-compiler.js +4 -0
- package/dist/expression/expression-builder.d.ts +0 -6
- package/dist/expression/expression-builder.js +0 -4
- package/dist/operation-node/drop-table-node.d.ts +7 -3
- package/dist/operation-node/insert-query-node.d.ts +0 -2
- package/dist/operation-node/operation-node-transformer.js +0 -1
- package/dist/operation-node/primary-key-constraint-node.d.ts +0 -10
- package/dist/operation-node/primary-key-constraint-node.js +0 -6
- package/dist/plugin/parse-json-results/parse-json-results-plugin.d.ts +2 -2
- package/dist/plugin/parse-json-results/parse-json-results-plugin.js +12 -12
- package/dist/query-builder/json-path-builder.js +8 -0
- package/dist/query-builder/update-query-builder.js +1 -1
- package/dist/query-compiler/default-query-compiler.d.ts +1 -0
- package/dist/query-compiler/default-query-compiler.js +12 -10
- package/package.json +11 -12
|
@@ -10,12 +10,6 @@ export interface DatabaseIntrospector {
|
|
|
10
10
|
* Get tables and views metadata.
|
|
11
11
|
*/
|
|
12
12
|
getTables(options?: DatabaseMetadataOptions): Promise<TableMetadata[]>;
|
|
13
|
-
/**
|
|
14
|
-
* Get the database metadata such as table and column names.
|
|
15
|
-
*
|
|
16
|
-
* @deprecated Use getTables() instead.
|
|
17
|
-
*/
|
|
18
|
-
getMetadata(options?: DatabaseMetadataOptions): Promise<DatabaseMetadata>;
|
|
19
13
|
}
|
|
20
14
|
export interface DatabaseMetadataOptions {
|
|
21
15
|
/**
|
|
@@ -27,13 +21,6 @@ export interface DatabaseMetadataOptions {
|
|
|
27
21
|
export interface SchemaMetadata {
|
|
28
22
|
readonly name: string;
|
|
29
23
|
}
|
|
30
|
-
export interface DatabaseMetadata {
|
|
31
|
-
/**
|
|
32
|
-
* The tables and views found in the database.
|
|
33
|
-
* The propery isView can be used to tell them apart.
|
|
34
|
-
*/
|
|
35
|
-
readonly tables: TableMetadata[];
|
|
36
|
-
}
|
|
37
24
|
export interface TableMetadata {
|
|
38
25
|
readonly name: string;
|
|
39
26
|
readonly isView: boolean;
|
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
import type { KyselyTypeError } from '../../util/type-error.js';
|
|
2
1
|
export interface MssqlDialectConfig {
|
|
3
2
|
/**
|
|
4
3
|
* When `true`, connections are reset to their initial states when released
|
|
@@ -74,10 +73,6 @@ export interface Tedious {
|
|
|
74
73
|
connectionFactory: () => TediousConnection | Promise<TediousConnection>;
|
|
75
74
|
ISOLATION_LEVEL: TediousIsolationLevel;
|
|
76
75
|
Request: TediousRequestClass;
|
|
77
|
-
/**
|
|
78
|
-
* @deprecated use {@link MssqlDialectConfig.resetConnectionsOnRelease} instead.
|
|
79
|
-
*/
|
|
80
|
-
resetConnectionOnRelease?: KyselyTypeError<'deprecated: use `MssqlDialectConfig.resetConnectionsOnRelease` instead'>;
|
|
81
76
|
TYPES: TediousTypes;
|
|
82
77
|
}
|
|
83
78
|
export interface TediousConnection {
|
|
@@ -142,12 +137,7 @@ export interface Tarn {
|
|
|
142
137
|
* Tarn.js' pool options, excluding `create`, `destroy` and `validate` functions,
|
|
143
138
|
* which must be implemented by this dialect.
|
|
144
139
|
*/
|
|
145
|
-
options: Omit<TarnPoolOptions<any>, 'create' | 'destroy' | 'validate'
|
|
146
|
-
/**
|
|
147
|
-
* @deprecated use {@link MssqlDialectConfig.validateConnections} instead.
|
|
148
|
-
*/
|
|
149
|
-
validateConnections?: KyselyTypeError<'deprecated: use `MssqlDialectConfig.validateConnections` instead'>;
|
|
150
|
-
};
|
|
140
|
+
options: Omit<TarnPoolOptions<any>, 'create' | 'destroy' | 'validate'>;
|
|
151
141
|
/**
|
|
152
142
|
* Tarn.js' Pool class.
|
|
153
143
|
*/
|
|
@@ -13,9 +13,8 @@ export class MssqlDriver {
|
|
|
13
13
|
constructor(config) {
|
|
14
14
|
this.#config = freeze({ ...config });
|
|
15
15
|
const { tarn, tedious, validateConnections } = this.#config;
|
|
16
|
-
const { validateConnections: deprecatedValidateConnections, ...poolOptions } = tarn.options;
|
|
17
16
|
this.#pool = new tarn.Pool({
|
|
18
|
-
...
|
|
17
|
+
...tarn.options,
|
|
19
18
|
create: async () => {
|
|
20
19
|
const connection = await tedious.connectionFactory();
|
|
21
20
|
return await new MssqlConnection(connection, tedious).connect();
|
|
@@ -25,8 +24,7 @@ export class MssqlDriver {
|
|
|
25
24
|
},
|
|
26
25
|
// @ts-ignore `tarn` accepts a function that returns a promise here, but
|
|
27
26
|
// the types are not aligned and it type errors.
|
|
28
|
-
validate: validateConnections === false
|
|
29
|
-
deprecatedValidateConnections === false
|
|
27
|
+
validate: validateConnections === false
|
|
30
28
|
? undefined
|
|
31
29
|
: (connection) => connection[PRIVATE_VALIDATE_METHOD](),
|
|
32
30
|
});
|
|
@@ -53,8 +51,7 @@ export class MssqlDriver {
|
|
|
53
51
|
await connection.rollbackTransaction(savepointName);
|
|
54
52
|
}
|
|
55
53
|
async releaseConnection(connection) {
|
|
56
|
-
if (this.#config.resetConnectionsOnRelease
|
|
57
|
-
this.#config.tedious.resetConnectionOnRelease) {
|
|
54
|
+
if (this.#config.resetConnectionsOnRelease) {
|
|
58
55
|
await connection[PRIVATE_RESET_METHOD]();
|
|
59
56
|
}
|
|
60
57
|
this.#pool.release(connection);
|
|
@@ -68,7 +65,6 @@ class MssqlConnection {
|
|
|
68
65
|
#hasSocketError;
|
|
69
66
|
#tedious;
|
|
70
67
|
#inflightRequest;
|
|
71
|
-
#sessionId;
|
|
72
68
|
constructor(connection, tedious) {
|
|
73
69
|
this.#connection = connection;
|
|
74
70
|
this.#hasSocketError = false;
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import type { Kysely } from '../../kysely.js';
|
|
2
|
-
import type { DatabaseIntrospector,
|
|
2
|
+
import type { DatabaseIntrospector, DatabaseMetadataOptions, SchemaMetadata, TableMetadata } from '../database-introspector.js';
|
|
3
3
|
export declare class MssqlIntrospector implements DatabaseIntrospector {
|
|
4
4
|
#private;
|
|
5
5
|
constructor(db: Kysely<any>);
|
|
@@ -11,10 +11,4 @@ export declare class MssqlIntrospector implements DatabaseIntrospector {
|
|
|
11
11
|
* Get tables and views metadata.
|
|
12
12
|
*/
|
|
13
13
|
getTables(options?: DatabaseMetadataOptions): Promise<TableMetadata[]>;
|
|
14
|
-
/**
|
|
15
|
-
* Get the database metadata such as table and column names.
|
|
16
|
-
*
|
|
17
|
-
* @deprecated Use getTables() instead.
|
|
18
|
-
*/
|
|
19
|
-
getMetadata(options?: DatabaseMetadataOptions): Promise<DatabaseMetadata>;
|
|
20
14
|
}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { DatabaseIntrospector,
|
|
1
|
+
import type { DatabaseIntrospector, DatabaseMetadataOptions, SchemaMetadata, TableMetadata } from '../database-introspector.js';
|
|
2
2
|
import type { Kysely } from '../../kysely.js';
|
|
3
3
|
export declare class MysqlIntrospector implements DatabaseIntrospector {
|
|
4
4
|
#private;
|
|
@@ -11,10 +11,4 @@ export declare class MysqlIntrospector implements DatabaseIntrospector {
|
|
|
11
11
|
* Get tables and views metadata.
|
|
12
12
|
*/
|
|
13
13
|
getTables(options?: DatabaseMetadataOptions): Promise<TableMetadata[]>;
|
|
14
|
-
/**
|
|
15
|
-
* Get the database metadata such as table and column names.
|
|
16
|
-
*
|
|
17
|
-
* @deprecated Use getTables() instead.
|
|
18
|
-
*/
|
|
19
|
-
getMetadata(options?: DatabaseMetadataOptions): Promise<DatabaseMetadata>;
|
|
20
14
|
}
|
|
@@ -46,11 +46,6 @@ export class MysqlIntrospector {
|
|
|
46
46
|
const rawColumns = await query.execute();
|
|
47
47
|
return this.#parseTableMetadata(rawColumns);
|
|
48
48
|
}
|
|
49
|
-
async getMetadata(options) {
|
|
50
|
-
return {
|
|
51
|
-
tables: await this.getTables(options),
|
|
52
|
-
};
|
|
53
|
-
}
|
|
54
49
|
#parseTableMetadata(columns) {
|
|
55
50
|
return columns.reduce((tables, it) => {
|
|
56
51
|
let table = tables.find((tbl) => tbl.name === it.TABLE_NAME);
|
|
@@ -17,5 +17,11 @@ export declare class MysqlQueryCompiler extends DefaultQueryCompiler {
|
|
|
17
17
|
* @see https://dev.mysql.com/doc/refman/9.6/en/string-literals.html
|
|
18
18
|
*/
|
|
19
19
|
protected sanitizeStringLiteral(value: string): string;
|
|
20
|
+
/**
|
|
21
|
+
* Member values appear inside `"..."` in the JSON path, which itself sits
|
|
22
|
+
* inside a SQL string literal. They must therefore be escaped twice — once
|
|
23
|
+
* for the JSON path grammar, then again for MySQL's string literal parser.
|
|
24
|
+
*/
|
|
25
|
+
protected sanitizeJSONPathMemberValue(value: string): string;
|
|
20
26
|
protected visitCreateIndex(node: CreateIndexNode): void;
|
|
21
27
|
}
|
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
/// <reference types="./mysql-query-compiler.d.ts" />
|
|
2
2
|
import { DefaultQueryCompiler } from '../../query-compiler/default-query-compiler.js';
|
|
3
|
-
const LITERAL_ESCAPE_REGEX =
|
|
3
|
+
const LITERAL_ESCAPE_REGEX = /[\\']/g;
|
|
4
4
|
const ID_WRAP_REGEX = /`/g;
|
|
5
|
+
const JSON_PATH_MEMBER_ESCAPE_REGEX = /[\\'"]/g;
|
|
5
6
|
export class MysqlQueryCompiler extends DefaultQueryCompiler {
|
|
6
7
|
getCurrentParameterPlaceholder() {
|
|
7
8
|
return '?';
|
|
@@ -37,6 +38,14 @@ export class MysqlQueryCompiler extends DefaultQueryCompiler {
|
|
|
37
38
|
sanitizeStringLiteral(value) {
|
|
38
39
|
return value.replace(LITERAL_ESCAPE_REGEX, (char) => char === '\\' ? '\\\\' : "''");
|
|
39
40
|
}
|
|
41
|
+
/**
|
|
42
|
+
* Member values appear inside `"..."` in the JSON path, which itself sits
|
|
43
|
+
* inside a SQL string literal. They must therefore be escaped twice — once
|
|
44
|
+
* for the JSON path grammar, then again for MySQL's string literal parser.
|
|
45
|
+
*/
|
|
46
|
+
sanitizeJSONPathMemberValue(value) {
|
|
47
|
+
return value.replace(JSON_PATH_MEMBER_ESCAPE_REGEX, (char) => char === '\\' ? '\\\\\\\\' : char === "'" ? "''" : '\\\\"');
|
|
48
|
+
}
|
|
40
49
|
visitCreateIndex(node) {
|
|
41
50
|
this.append('create ');
|
|
42
51
|
if (node.unique) {
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { DatabaseIntrospector,
|
|
1
|
+
import type { DatabaseIntrospector, DatabaseMetadataOptions, SchemaMetadata, TableMetadata } from '../database-introspector.js';
|
|
2
2
|
import type { Kysely } from '../../kysely.js';
|
|
3
3
|
export declare class PostgresIntrospector implements DatabaseIntrospector {
|
|
4
4
|
#private;
|
|
@@ -11,10 +11,4 @@ export declare class PostgresIntrospector implements DatabaseIntrospector {
|
|
|
11
11
|
* Get tables and views metadata.
|
|
12
12
|
*/
|
|
13
13
|
getTables(options?: DatabaseMetadataOptions): Promise<TableMetadata[]>;
|
|
14
|
-
/**
|
|
15
|
-
* Get the database metadata such as table and column names.
|
|
16
|
-
*
|
|
17
|
-
* @deprecated Use getTables() instead.
|
|
18
|
-
*/
|
|
19
|
-
getMetadata(options?: DatabaseMetadataOptions): Promise<DatabaseMetadata>;
|
|
20
14
|
}
|
|
@@ -66,27 +66,28 @@ export class PostgresIntrospector {
|
|
|
66
66
|
const rawColumns = await query.execute();
|
|
67
67
|
return this.#parseTableMetadata(rawColumns);
|
|
68
68
|
}
|
|
69
|
-
async getMetadata(options) {
|
|
70
|
-
return {
|
|
71
|
-
tables: await this.getTables(options),
|
|
72
|
-
};
|
|
73
|
-
}
|
|
74
69
|
#parseTableMetadata(columns) {
|
|
75
|
-
const
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
70
|
+
const tables = [];
|
|
71
|
+
const schemas = new Map();
|
|
72
|
+
for (const column of columns) {
|
|
73
|
+
let schema = schemas.get(column.schema);
|
|
74
|
+
if (!schema) {
|
|
75
|
+
schema = new Map();
|
|
76
|
+
schemas.set(column.schema, schema);
|
|
77
|
+
}
|
|
78
|
+
let table = schema.get(column.table);
|
|
79
|
+
if (!table) {
|
|
80
|
+
table = freeze({
|
|
82
81
|
columns: [],
|
|
83
82
|
isForeign: column.table_type === 'f',
|
|
84
83
|
isView: column.table_type === 'v',
|
|
85
|
-
name: table,
|
|
86
|
-
schema,
|
|
87
|
-
})
|
|
84
|
+
name: column.table,
|
|
85
|
+
schema: column.schema,
|
|
86
|
+
});
|
|
87
|
+
schema.set(column.table, table);
|
|
88
|
+
tables.push(table);
|
|
88
89
|
}
|
|
89
|
-
|
|
90
|
+
table.columns.push(freeze({
|
|
90
91
|
comment: column.column_description ?? undefined,
|
|
91
92
|
dataType: column.type,
|
|
92
93
|
dataTypeSchema: column.type_schema,
|
|
@@ -96,6 +97,6 @@ export class PostgresIntrospector {
|
|
|
96
97
|
name: column.column,
|
|
97
98
|
}));
|
|
98
99
|
}
|
|
99
|
-
return
|
|
100
|
+
return tables;
|
|
100
101
|
}
|
|
101
102
|
}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { DatabaseIntrospector,
|
|
1
|
+
import type { DatabaseIntrospector, DatabaseMetadataOptions, SchemaMetadata, TableMetadata } from '../database-introspector.js';
|
|
2
2
|
import type { Kysely } from '../../kysely.js';
|
|
3
3
|
export declare class SqliteIntrospector implements DatabaseIntrospector {
|
|
4
4
|
#private;
|
|
@@ -11,10 +11,4 @@ export declare class SqliteIntrospector implements DatabaseIntrospector {
|
|
|
11
11
|
* Get tables and views metadata.
|
|
12
12
|
*/
|
|
13
13
|
getTables(options?: DatabaseMetadataOptions): Promise<TableMetadata[]>;
|
|
14
|
-
/**
|
|
15
|
-
* Get the database metadata such as table and column names.
|
|
16
|
-
*
|
|
17
|
-
* @deprecated Use getTables() instead.
|
|
18
|
-
*/
|
|
19
|
-
getMetadata(options?: DatabaseMetadataOptions): Promise<DatabaseMetadata>;
|
|
20
14
|
}
|
|
@@ -13,11 +13,6 @@ export class SqliteIntrospector {
|
|
|
13
13
|
async getTables(options = { withInternalKyselyTables: false }) {
|
|
14
14
|
return await this.#getTableMetadata(options);
|
|
15
15
|
}
|
|
16
|
-
async getMetadata(options) {
|
|
17
|
-
return {
|
|
18
|
-
tables: await this.getTables(options),
|
|
19
|
-
};
|
|
20
|
-
}
|
|
21
16
|
#tablesQuery(qb, options) {
|
|
22
17
|
let tablesQuery = qb
|
|
23
18
|
.selectFrom('sqlite_master')
|
|
@@ -10,5 +10,6 @@ export declare class SqliteQueryCompiler extends DefaultQueryCompiler {
|
|
|
10
10
|
protected getRightIdentifierWrapper(): string;
|
|
11
11
|
protected getAutoIncrement(): string;
|
|
12
12
|
protected sanitizeIdentifier(identifier: string): string;
|
|
13
|
+
protected sanitizeJSONPathMemberValue(value: string): string;
|
|
13
14
|
protected visitDefaultInsertValue(_: DefaultInsertValueNode): void;
|
|
14
15
|
}
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
/// <reference types="./sqlite-query-compiler.d.ts" />
|
|
2
2
|
import { DefaultQueryCompiler } from '../../query-compiler/default-query-compiler.js';
|
|
3
3
|
const ID_WRAP_REGEX = /"/g;
|
|
4
|
+
const JSON_PATH_MEMBER_ESCAPE_REGEX = /[\\'"]/g;
|
|
4
5
|
export class SqliteQueryCompiler extends DefaultQueryCompiler {
|
|
5
6
|
visitOrAction(node) {
|
|
6
7
|
this.append('or ');
|
|
@@ -27,6 +28,9 @@ export class SqliteQueryCompiler extends DefaultQueryCompiler {
|
|
|
27
28
|
sanitizeIdentifier(identifier) {
|
|
28
29
|
return identifier.replace(ID_WRAP_REGEX, '""');
|
|
29
30
|
}
|
|
31
|
+
sanitizeJSONPathMemberValue(value) {
|
|
32
|
+
return value.replace(JSON_PATH_MEMBER_ESCAPE_REGEX, (char) => char === '\\' ? '\\\\' : char === "'" ? "''" : '\\"');
|
|
33
|
+
}
|
|
30
34
|
visitDefaultInsertValue(_) {
|
|
31
35
|
// sqlite doesn't support the `default` keyword in inserts.
|
|
32
36
|
this.append('null');
|
|
@@ -908,12 +908,6 @@ export interface ExpressionBuilder<DB, TB extends keyof DB> {
|
|
|
908
908
|
* ```
|
|
909
909
|
*/
|
|
910
910
|
cast<T, RE extends ReferenceExpression<DB, TB> = ReferenceExpression<DB, TB>>(expr: RE, dataType: DataTypeExpression): ExpressionWrapper<DB, TB, T>;
|
|
911
|
-
/**
|
|
912
|
-
* See {@link QueryCreator.withSchema}
|
|
913
|
-
*
|
|
914
|
-
* @deprecated Will be removed in kysely 0.25.0.
|
|
915
|
-
*/
|
|
916
|
-
withSchema(schema: string): ExpressionBuilder<DB, TB>;
|
|
917
911
|
}
|
|
918
912
|
export declare function createExpressionBuilder<DB, TB extends keyof DB>(executor?: QueryExecutor): ExpressionBuilder<DB, TB>;
|
|
919
913
|
export declare function expressionBuilder<DB, TB extends keyof DB>(_: SelectQueryBuilder<DB, TB, any>): ExpressionBuilder<DB, TB>;
|
|
@@ -2,7 +2,6 @@
|
|
|
2
2
|
import { createSelectQueryBuilder, } from '../query-builder/select-query-builder.js';
|
|
3
3
|
import { SelectQueryNode } from '../operation-node/select-query-node.js';
|
|
4
4
|
import { parseTableExpressionOrList, parseTable, } from '../parser/table-parser.js';
|
|
5
|
-
import { WithSchemaPlugin } from '../plugin/with-schema/with-schema-plugin.js';
|
|
6
5
|
import { createQueryId } from '../util/query-id.js';
|
|
7
6
|
import { createFunctionModule, } from '../query-builder/function-module.js';
|
|
8
7
|
import { parseJSONReference, parseReferenceExpression, parseStringReference, } from '../parser/reference-parser.js';
|
|
@@ -112,9 +111,6 @@ export function createExpressionBuilder(executor = NOOP_QUERY_EXECUTOR) {
|
|
|
112
111
|
cast(expr, dataType) {
|
|
113
112
|
return new ExpressionWrapper(CastNode.create(parseReferenceExpression(expr), parseDataTypeExpression(dataType)));
|
|
114
113
|
},
|
|
115
|
-
withSchema(schema) {
|
|
116
|
-
return createExpressionBuilder(executor.withPluginAtFront(new WithSchemaPlugin(schema)));
|
|
117
|
-
},
|
|
118
114
|
});
|
|
119
115
|
eb.fn = createFunctionModule();
|
|
120
116
|
eb.eb = eb;
|
|
@@ -1,6 +1,10 @@
|
|
|
1
1
|
import type { OperationNode } from './operation-node.js';
|
|
2
2
|
import type { TableNode } from './table-node.js';
|
|
3
|
-
export type
|
|
3
|
+
export type DropTableNodeParams = Omit<Partial<DropTableNode>, 'kind' | 'table'>;
|
|
4
|
+
/**
|
|
5
|
+
* @deprecated use {@link DropTableNodeParams} instead.
|
|
6
|
+
*/
|
|
7
|
+
export type DropTablexNodeParams = DropTableNodeParams;
|
|
4
8
|
export interface DropTableNode extends OperationNode {
|
|
5
9
|
readonly kind: 'DropTableNode';
|
|
6
10
|
readonly table: TableNode;
|
|
@@ -10,8 +14,8 @@ export interface DropTableNode extends OperationNode {
|
|
|
10
14
|
}
|
|
11
15
|
type DropTableNodeFactory = Readonly<{
|
|
12
16
|
is(node: OperationNode): node is DropTableNode;
|
|
13
|
-
create(table: TableNode, params?:
|
|
14
|
-
cloneWith(dropIndex: DropTableNode, params:
|
|
17
|
+
create(table: TableNode, params?: DropTableNodeParams): Readonly<DropTableNode>;
|
|
18
|
+
cloneWith(dropIndex: DropTableNode, params: DropTableNodeParams): Readonly<DropTableNode>;
|
|
15
19
|
}>;
|
|
16
20
|
/**
|
|
17
21
|
* @internal
|
|
@@ -19,8 +19,6 @@ export interface InsertQueryNode extends OperationNode {
|
|
|
19
19
|
readonly onConflict?: OnConflictNode;
|
|
20
20
|
readonly onDuplicateKey?: OnDuplicateKeyNode;
|
|
21
21
|
readonly with?: WithNode;
|
|
22
|
-
/** @deprecated use {@link orAction} instead. */
|
|
23
|
-
readonly ignore?: boolean;
|
|
24
22
|
readonly orAction?: OrActionNode;
|
|
25
23
|
readonly replace?: boolean;
|
|
26
24
|
readonly explain?: ExplainNode;
|
|
@@ -275,7 +275,6 @@ export class OperationNodeTransformer {
|
|
|
275
275
|
onDuplicateKey: this.transformNode(node.onDuplicateKey, queryId),
|
|
276
276
|
endModifiers: this.transformNodeList(node.endModifiers, queryId),
|
|
277
277
|
with: this.transformNode(node.with, queryId),
|
|
278
|
-
ignore: node.ignore,
|
|
279
278
|
orAction: this.transformNode(node.orAction, queryId),
|
|
280
279
|
replace: node.replace,
|
|
281
280
|
explain: this.transformNode(node.explain, queryId),
|
|
@@ -18,14 +18,4 @@ type PrimaryKeyConstraintNodeFactory = Readonly<{
|
|
|
18
18
|
* @internal
|
|
19
19
|
*/
|
|
20
20
|
export declare const PrimaryKeyConstraintNode: PrimaryKeyConstraintNodeFactory;
|
|
21
|
-
/**
|
|
22
|
-
* Backwards compatibility for a typo in the codebase.
|
|
23
|
-
*
|
|
24
|
-
* @deprecated Use {@link PrimaryKeyConstraintNode} instead.
|
|
25
|
-
*/
|
|
26
|
-
export declare const PrimaryConstraintNode: Readonly<{
|
|
27
|
-
is(node: OperationNode): node is PrimaryKeyConstraintNode;
|
|
28
|
-
create(columns: string[], constraintName?: string): Readonly<PrimaryKeyConstraintNode>;
|
|
29
|
-
cloneWith(node: PrimaryKeyConstraintNode, props: PrimaryKeyConstraintNodeProps): Readonly<PrimaryKeyConstraintNode>;
|
|
30
|
-
}>;
|
|
31
21
|
export {};
|
|
@@ -22,9 +22,3 @@ export const PrimaryKeyConstraintNode = freeze({
|
|
|
22
22
|
return freeze({ ...node, ...props });
|
|
23
23
|
},
|
|
24
24
|
});
|
|
25
|
-
/**
|
|
26
|
-
* Backwards compatibility for a typo in the codebase.
|
|
27
|
-
*
|
|
28
|
-
* @deprecated Use {@link PrimaryKeyConstraintNode} instead.
|
|
29
|
-
*/
|
|
30
|
-
export const PrimaryConstraintNode = PrimaryKeyConstraintNode;
|
|
@@ -9,10 +9,10 @@ export interface ParseJSONResultsPluginOptions {
|
|
|
9
9
|
* Defaults to a function that checks if the string starts and ends with `{}` or `[]` - meaning anything that might be a JSON string, is attempted to be parsed - and if fails, proceeds.
|
|
10
10
|
*
|
|
11
11
|
* @param value - The string value to check.
|
|
12
|
-
* @param
|
|
12
|
+
* @param jsonPath - The JSON path leading to this value. e.g. `$[0]."users"[0]."profile"`
|
|
13
13
|
* @return `true` if the string should be JSON parsed.
|
|
14
14
|
*/
|
|
15
|
-
shouldParse?: (value: string,
|
|
15
|
+
shouldParse?: (value: string, jsonPath: string) => boolean;
|
|
16
16
|
/**
|
|
17
17
|
* When `'in-place'`, arrays' and objects' values are parsed in-place. This is
|
|
18
18
|
* the most time and space efficient option.
|
|
@@ -54,7 +54,7 @@ export class ParseJSONResultsPlugin {
|
|
|
54
54
|
objectStrategy: options.objectStrategy || 'in-place',
|
|
55
55
|
reviver: options.reviver || ((_, value) => value),
|
|
56
56
|
shouldParse: shouldParse
|
|
57
|
-
? (value,
|
|
57
|
+
? (value, jsonPath) => maybeJson(value) && shouldParse(value, jsonPath)
|
|
58
58
|
: maybeJson,
|
|
59
59
|
});
|
|
60
60
|
}
|
|
@@ -69,28 +69,28 @@ export class ParseJSONResultsPlugin {
|
|
|
69
69
|
};
|
|
70
70
|
}
|
|
71
71
|
}
|
|
72
|
-
function parseArray(arr,
|
|
72
|
+
function parseArray(arr, jsonPath, options) {
|
|
73
73
|
const target = options.objectStrategy === 'create' ? new Array(arr.length) : arr;
|
|
74
74
|
for (let i = 0; i < arr.length; ++i) {
|
|
75
|
-
target[i] = parse(arr[i], `${
|
|
75
|
+
target[i] = parse(arr[i], `${jsonPath}[${i}]`, options);
|
|
76
76
|
}
|
|
77
77
|
return target;
|
|
78
78
|
}
|
|
79
|
-
function parse(value,
|
|
79
|
+
function parse(value, jsonPath, options) {
|
|
80
80
|
if (isString(value)) {
|
|
81
|
-
return parseString(value,
|
|
81
|
+
return parseString(value, jsonPath, options);
|
|
82
82
|
}
|
|
83
83
|
if (Array.isArray(value)) {
|
|
84
|
-
return parseArray(value,
|
|
84
|
+
return parseArray(value, jsonPath, options);
|
|
85
85
|
}
|
|
86
86
|
if (isPlainObject(value)) {
|
|
87
|
-
return parseObject(value,
|
|
87
|
+
return parseObject(value, jsonPath, options);
|
|
88
88
|
}
|
|
89
89
|
return value;
|
|
90
90
|
}
|
|
91
|
-
function parseString(str,
|
|
91
|
+
function parseString(str, jsonPath, options) {
|
|
92
92
|
const { shouldParse } = options;
|
|
93
|
-
if (!shouldParse(str,
|
|
93
|
+
if (!shouldParse(str, jsonPath)) {
|
|
94
94
|
return str;
|
|
95
95
|
}
|
|
96
96
|
try {
|
|
@@ -106,7 +106,7 @@ function parseString(str, path, options) {
|
|
|
106
106
|
delete value.prototype;
|
|
107
107
|
}
|
|
108
108
|
return options.reviver(key, value, ...otherArgs);
|
|
109
|
-
}),
|
|
109
|
+
}), jsonPath, { ...options, objectStrategy: 'in-place' });
|
|
110
110
|
}
|
|
111
111
|
catch (error) {
|
|
112
112
|
// custom JSON detection should expose parsing errors.
|
|
@@ -122,7 +122,7 @@ function maybeJson(value) {
|
|
|
122
122
|
return ((value.startsWith('{') && value.endsWith('}')) ||
|
|
123
123
|
(value.startsWith('[') && value.endsWith(']')));
|
|
124
124
|
}
|
|
125
|
-
function parseObject(obj,
|
|
125
|
+
function parseObject(obj, jsonPath, options) {
|
|
126
126
|
const { objectStrategy } = options;
|
|
127
127
|
const target = objectStrategy === 'create' ? {} : obj;
|
|
128
128
|
for (const key of Object.keys(obj)) {
|
|
@@ -130,7 +130,7 @@ function parseObject(obj, path, options) {
|
|
|
130
130
|
if (key === '__proto__') {
|
|
131
131
|
continue;
|
|
132
132
|
}
|
|
133
|
-
const parsed = parse(obj[key], `${
|
|
133
|
+
const parsed = parse(obj[key], `${jsonPath}."${key}"`, options);
|
|
134
134
|
// prevent prototype pollution
|
|
135
135
|
if (key === 'constructor' &&
|
|
136
136
|
isPlainObject(parsed) &&
|
|
@@ -7,6 +7,7 @@ import { JSONPathNode } from '../operation-node/json-path-node.js';
|
|
|
7
7
|
import { JSONReferenceNode } from '../operation-node/json-reference-node.js';
|
|
8
8
|
import { isOperationNodeSource } from '../operation-node/operation-node-source.js';
|
|
9
9
|
import { ValueNode } from '../operation-node/value-node.js';
|
|
10
|
+
const HASH_NEGATIVE_INDEX_REGEX = /^#-\d+$/;
|
|
10
11
|
export class JSONPathBuilder {
|
|
11
12
|
#node;
|
|
12
13
|
constructor(node) {
|
|
@@ -80,6 +81,13 @@ export class JSONPathBuilder {
|
|
|
80
81
|
* ```
|
|
81
82
|
*/
|
|
82
83
|
at(index) {
|
|
84
|
+
if ((typeof index !== 'number' && typeof index !== 'string') ||
|
|
85
|
+
(typeof index === 'number' && !Number.isInteger(index)) ||
|
|
86
|
+
(typeof index === 'string' &&
|
|
87
|
+
index !== 'last' &&
|
|
88
|
+
!HASH_NEGATIVE_INDEX_REGEX.test(index))) {
|
|
89
|
+
throw new Error(`Unexpected index value in .at(...): ${index}`);
|
|
90
|
+
}
|
|
83
91
|
return this.#createBuilderWithPathLeg('ArrayLocation', index);
|
|
84
92
|
}
|
|
85
93
|
/**
|
|
@@ -8,7 +8,7 @@ import { UpdateQueryNode } from '../operation-node/update-query-node.js';
|
|
|
8
8
|
import { parseUpdate, } from '../parser/update-set-parser.js';
|
|
9
9
|
import { freeze } from '../util/object-utils.js';
|
|
10
10
|
import { UpdateResult } from './update-result.js';
|
|
11
|
-
import { isNoResultErrorConstructor, NoResultError
|
|
11
|
+
import { isNoResultErrorConstructor, NoResultError } from './no-result-error.js';
|
|
12
12
|
import { parseReferentialBinaryOperation, parseValueBinaryOperationOrExpression, } from '../parser/binary-operation-parser.js';
|
|
13
13
|
import { parseValueExpression, } from '../parser/value-parser.js';
|
|
14
14
|
import { LimitNode } from '../operation-node/limit-node.js';
|
|
@@ -229,6 +229,7 @@ export declare class DefaultQueryCompiler extends OperationNodeVisitor implement
|
|
|
229
229
|
protected getRightExplainOptionsWrapper(): string;
|
|
230
230
|
protected sanitizeIdentifier(identifier: string): string;
|
|
231
231
|
protected sanitizeStringLiteral(value: string): string;
|
|
232
|
+
protected sanitizeJSONPathMemberValue(value: string): string;
|
|
232
233
|
protected addParameter(parameter: unknown): void;
|
|
233
234
|
protected appendImmediateValue(value: unknown): void;
|
|
234
235
|
protected appendStringLiteral(value: string): void;
|
|
@@ -9,8 +9,8 @@ import { freeze, isString, isNumber, isBoolean, isNull, isDate, isBigInt, } from
|
|
|
9
9
|
import { CreateViewNode } from '../operation-node/create-view-node.js';
|
|
10
10
|
import { SetOperationNode } from '../operation-node/set-operation-node.js';
|
|
11
11
|
import { WhenNode } from '../operation-node/when-node.js';
|
|
12
|
-
import { logOnce } from '../util/log-once.js';
|
|
13
12
|
const LIT_WRAP_REGEX = /'/g;
|
|
13
|
+
const JSON_PATH_MEMBER_WRAP_REGEX = /['"]/g;
|
|
14
14
|
export class DefaultQueryCompiler extends OperationNodeVisitor {
|
|
15
15
|
#sql = '';
|
|
16
16
|
#parameters = [];
|
|
@@ -164,11 +164,6 @@ export class DefaultQueryCompiler extends OperationNodeVisitor {
|
|
|
164
164
|
this.append(' ');
|
|
165
165
|
}
|
|
166
166
|
this.append(node.replace ? 'replace' : 'insert');
|
|
167
|
-
// TODO: remove in 0.29.
|
|
168
|
-
if (node.ignore) {
|
|
169
|
-
logOnce('`InsertQueryNode.ignore` is deprecated. Use `InsertQueryNode.orAction` instead.');
|
|
170
|
-
this.append(' ignore');
|
|
171
|
-
}
|
|
172
167
|
if (node.orAction) {
|
|
173
168
|
this.append(' ');
|
|
174
169
|
this.visitNode(node.orAction);
|
|
@@ -1220,13 +1215,17 @@ export class DefaultQueryCompiler extends OperationNodeVisitor {
|
|
|
1220
1215
|
}
|
|
1221
1216
|
visitJSONPathLeg(node) {
|
|
1222
1217
|
const isArrayLocation = node.type === 'ArrayLocation';
|
|
1223
|
-
|
|
1224
|
-
this.append(typeof node.value === 'string'
|
|
1225
|
-
? this.sanitizeStringLiteral(node.value)
|
|
1226
|
-
: String(node.value));
|
|
1218
|
+
const value = String(node.value);
|
|
1227
1219
|
if (isArrayLocation) {
|
|
1220
|
+
this.append('[');
|
|
1221
|
+
this.append(this.sanitizeStringLiteral(value));
|
|
1228
1222
|
this.append(']');
|
|
1229
1223
|
}
|
|
1224
|
+
else {
|
|
1225
|
+
this.append('."');
|
|
1226
|
+
this.append(this.sanitizeJSONPathMemberValue(value));
|
|
1227
|
+
this.append('"');
|
|
1228
|
+
}
|
|
1230
1229
|
}
|
|
1231
1230
|
visitJSONOperatorChain(node) {
|
|
1232
1231
|
for (let i = 0, len = node.values.length; i < len; i++) {
|
|
@@ -1375,6 +1374,9 @@ export class DefaultQueryCompiler extends OperationNodeVisitor {
|
|
|
1375
1374
|
sanitizeStringLiteral(value) {
|
|
1376
1375
|
return value.replace(LIT_WRAP_REGEX, "''");
|
|
1377
1376
|
}
|
|
1377
|
+
sanitizeJSONPathMemberValue(value) {
|
|
1378
|
+
return value.replace(JSON_PATH_MEMBER_WRAP_REGEX, (char) => char === "'" ? "''" : '\\"');
|
|
1379
|
+
}
|
|
1378
1380
|
addParameter(parameter) {
|
|
1379
1381
|
this.#parameters.push(parameter);
|
|
1380
1382
|
}
|
package/package.json
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "kysely",
|
|
3
|
-
"version": "0.29.0
|
|
3
|
+
"version": "0.29.0",
|
|
4
4
|
"description": "Type safe SQL query builder",
|
|
5
5
|
"repository": {
|
|
6
6
|
"type": "git",
|
|
7
|
-
"url": "git://github.com/kysely-org/kysely.git"
|
|
7
|
+
"url": "git+https://github.com/kysely-org/kysely.git"
|
|
8
8
|
},
|
|
9
9
|
"homepage": "https://kysely.dev",
|
|
10
10
|
"keywords": [
|
|
@@ -25,7 +25,7 @@
|
|
|
25
25
|
"plugins"
|
|
26
26
|
],
|
|
27
27
|
"engines": {
|
|
28
|
-
"node": ">=
|
|
28
|
+
"node": ">=22.0.0"
|
|
29
29
|
},
|
|
30
30
|
"type": "module",
|
|
31
31
|
"main": "dist/index.js",
|
|
@@ -63,40 +63,39 @@
|
|
|
63
63
|
"devDependencies": {
|
|
64
64
|
"@arethetypeswrong/cli": "0.18.2",
|
|
65
65
|
"@ark/attest": "0.56.0",
|
|
66
|
-
"@electric-sql/pglite": "0.4.
|
|
66
|
+
"@electric-sql/pglite": "0.4.5",
|
|
67
67
|
"@types/better-sqlite3": "7.6.13",
|
|
68
68
|
"@types/chai": "5.2.3",
|
|
69
69
|
"@types/chai-as-promised": "8.0.2",
|
|
70
70
|
"@types/mocha": "10.0.10",
|
|
71
|
-
"@types/node": "25.
|
|
71
|
+
"@types/node": "25.6.1",
|
|
72
72
|
"@types/pg": "8.20.0",
|
|
73
73
|
"@types/pg-cursor": "2.7.2",
|
|
74
74
|
"@types/prototype-pollution-vulnerable-lodash.merge-dont-upgrade": "npm:@types/lodash.merge@4.6.1",
|
|
75
75
|
"@types/semver": "7.7.1",
|
|
76
76
|
"@types/sinon": "21.0.1",
|
|
77
|
-
"better-sqlite3": "12.
|
|
77
|
+
"better-sqlite3": "12.9.0",
|
|
78
78
|
"chai": "6.2.2",
|
|
79
79
|
"chai-as-promised": "8.0.2",
|
|
80
80
|
"esbuild": "0.28.0",
|
|
81
81
|
"jsr": "0.14.3",
|
|
82
82
|
"lodash": "4.18.1",
|
|
83
83
|
"mocha": "11.7.5",
|
|
84
|
-
"mysql2": "3.
|
|
84
|
+
"mysql2": "3.22.3",
|
|
85
85
|
"pathe": "2.0.3",
|
|
86
86
|
"pg": "8.20.0",
|
|
87
87
|
"pg-cursor": "2.19.0",
|
|
88
|
-
"pkg-types": "2.3.0",
|
|
89
88
|
"playwright": "1.59.1",
|
|
90
|
-
"prettier": "3.8.
|
|
89
|
+
"prettier": "3.8.3",
|
|
91
90
|
"prototype-pollution-vulnerable-lodash.merge-dont-upgrade": "npm:lodash.merge@4.6.1",
|
|
92
91
|
"semver": "7.7.4",
|
|
93
|
-
"sinon": "
|
|
94
|
-
"std-env": "4.
|
|
92
|
+
"sinon": "22.0.0",
|
|
93
|
+
"std-env": "4.1.0",
|
|
95
94
|
"tarn": "3.0.2",
|
|
96
95
|
"tedious": "19.2.1",
|
|
97
96
|
"tsd": "0.33.0",
|
|
98
97
|
"tsx": "4.21.0",
|
|
99
|
-
"typescript": "6.0.
|
|
98
|
+
"typescript": "6.0.3"
|
|
100
99
|
},
|
|
101
100
|
"scripts": {
|
|
102
101
|
"clean": "rm -rf dist & rm -rf test/node/dist & rm -rf test/browser/bundle.js",
|