@feathersjs/knex 5.0.0-pre.24
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/CHANGELOG.md +11 -0
- package/LICENSE +22 -0
- package/README.md +22 -0
- package/lib/adapter.d.ts +64 -0
- package/lib/adapter.js +239 -0
- package/lib/adapter.js.map +1 -0
- package/lib/error-handler.d.ts +2 -0
- package/lib/error-handler.js +96 -0
- package/lib/error-handler.js.map +1 -0
- package/lib/hooks.d.ts +0 -0
- package/lib/hooks.js +82 -0
- package/lib/hooks.js.map +1 -0
- package/lib/index.d.ts +22 -0
- package/lib/index.js +43 -0
- package/lib/index.js.map +1 -0
- package/package.json +71 -0
- package/src/adapter.ts +314 -0
- package/src/declarations.ts +23 -0
- package/src/error-handler.ts +95 -0
- package/src/hooks.ts +101 -0
- package/src/index.ts +47 -0
package/CHANGELOG.md
ADDED
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
# Change Log
|
|
2
|
+
|
|
3
|
+
All notable changes to this project will be documented in this file.
|
|
4
|
+
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
|
5
|
+
|
|
6
|
+
# [5.0.0-pre.24](https://github.com/feathersjs/feathers/compare/v5.0.0-pre.23...v5.0.0-pre.24) (2022-06-21)
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
### Features
|
|
10
|
+
|
|
11
|
+
* **knex:** Add KnexJS SQL database adapter to core ([#2671](https://github.com/feathersjs/feathers/issues/2671)) ([9380fff](https://github.com/feathersjs/feathers/commit/9380fff58596e8bb90b8bb098d2795b7eadfec20))
|
package/LICENSE
ADDED
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
The MIT License (MIT)
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2022 Feathers
|
|
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.
|
|
22
|
+
|
package/README.md
ADDED
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
# @feathersjs/knex
|
|
2
|
+
|
|
3
|
+
[](https://github.com/feathersjs/feathers/actions?query=workflow%3ACI)
|
|
4
|
+
[](https://www.npmjs.com/package/@feathersjs/mongodb)
|
|
5
|
+
|
|
6
|
+
> Feathers SQL service adapter using KnexJS
|
|
7
|
+
|
|
8
|
+
## Installation
|
|
9
|
+
|
|
10
|
+
```
|
|
11
|
+
npm install @feathersjs/knex --save
|
|
12
|
+
```
|
|
13
|
+
|
|
14
|
+
## Documentation
|
|
15
|
+
|
|
16
|
+
Refer to the [Feathers documentation](https://docs.feathersjs.com) for more details.
|
|
17
|
+
|
|
18
|
+
## License
|
|
19
|
+
|
|
20
|
+
Copyright (c) 2022 [Feathers contributors](https://github.com/feathersjs/feathers/graphs/contributors)
|
|
21
|
+
|
|
22
|
+
Licensed under the [MIT license](LICENSE).
|
package/lib/adapter.d.ts
ADDED
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
import { Id, NullableId, Paginated, Query } from '@feathersjs/feathers';
|
|
2
|
+
import { AdapterBase, AdapterServiceOptions, AdapterParams, AdapterQuery, PaginationOptions } from '@feathersjs/adapter-commons';
|
|
3
|
+
import { Knex } from 'knex';
|
|
4
|
+
export interface KnexAdapterOptions extends AdapterServiceOptions {
|
|
5
|
+
Model: Knex;
|
|
6
|
+
name: string;
|
|
7
|
+
schema?: string;
|
|
8
|
+
}
|
|
9
|
+
export interface KnexAdapterParams<Q = AdapterQuery> extends AdapterParams<Q, Partial<KnexAdapterOptions>> {
|
|
10
|
+
knex?: Knex.QueryBuilder;
|
|
11
|
+
transaction?: Knex.Transaction;
|
|
12
|
+
}
|
|
13
|
+
export declare class KnexAdapter<T, D = Partial<T>, P extends KnexAdapterParams<any> = KnexAdapterParams> extends AdapterBase<T, D, P, KnexAdapterOptions> {
|
|
14
|
+
table: string;
|
|
15
|
+
schema?: string;
|
|
16
|
+
constructor(options: KnexAdapterOptions);
|
|
17
|
+
get Model(): Knex<any, any[]>;
|
|
18
|
+
get fullName(): string;
|
|
19
|
+
db(_params?: P): Knex.QueryBuilder<any, {
|
|
20
|
+
_base: any;
|
|
21
|
+
_hasSelection: false;
|
|
22
|
+
_keys: never;
|
|
23
|
+
_aliases: {};
|
|
24
|
+
_single: false;
|
|
25
|
+
_intersectProps: {};
|
|
26
|
+
_unionProps: never;
|
|
27
|
+
}[]>;
|
|
28
|
+
knexify(knexQuery: Knex.QueryBuilder, query?: Query, parentKey?: string): Knex.QueryBuilder;
|
|
29
|
+
createQuery(params: P): Knex.QueryBuilder<any, {
|
|
30
|
+
_base: any;
|
|
31
|
+
_hasSelection: false;
|
|
32
|
+
_keys: never;
|
|
33
|
+
_aliases: {};
|
|
34
|
+
_single: false;
|
|
35
|
+
_intersectProps: {};
|
|
36
|
+
_unionProps: never;
|
|
37
|
+
}[]>;
|
|
38
|
+
filterQuery(params: P): {
|
|
39
|
+
filters: {
|
|
40
|
+
[key: string]: any;
|
|
41
|
+
};
|
|
42
|
+
query: Query;
|
|
43
|
+
paginate: import("@feathersjs/adapter-commons").PaginationParams;
|
|
44
|
+
};
|
|
45
|
+
$find(params?: P & {
|
|
46
|
+
paginate?: PaginationOptions;
|
|
47
|
+
}): Promise<Paginated<T>>;
|
|
48
|
+
$find(params?: P & {
|
|
49
|
+
paginate: false;
|
|
50
|
+
}): Promise<T[]>;
|
|
51
|
+
$find(params?: P): Promise<Paginated<T> | T[]>;
|
|
52
|
+
_findOrGet(id: NullableId, params?: P): Promise<T[]>;
|
|
53
|
+
$get(id: Id, params?: P): Promise<T>;
|
|
54
|
+
$create(data: Partial<D>, params?: P): Promise<T>;
|
|
55
|
+
$create(data: Partial<D>[], params?: P): Promise<T[]>;
|
|
56
|
+
$create(data: Partial<D> | Partial<D>[], _params?: P): Promise<T | T[]>;
|
|
57
|
+
$patch(id: null, data: Partial<D>, params?: P): Promise<T[]>;
|
|
58
|
+
$patch(id: Id, data: Partial<D>, params?: P): Promise<T>;
|
|
59
|
+
$patch(id: NullableId, data: Partial<D>, _params?: P): Promise<T | T[]>;
|
|
60
|
+
$update(id: Id, _data: D, params?: P): Promise<T>;
|
|
61
|
+
$remove(id: null, params?: P): Promise<T[]>;
|
|
62
|
+
$remove(id: Id, params?: P): Promise<T>;
|
|
63
|
+
$remove(id: NullableId, _params?: P): Promise<T | T[]>;
|
|
64
|
+
}
|
package/lib/adapter.js
ADDED
|
@@ -0,0 +1,239 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.KnexAdapter = void 0;
|
|
4
|
+
const commons_1 = require("@feathersjs/commons");
|
|
5
|
+
const adapter_commons_1 = require("@feathersjs/adapter-commons");
|
|
6
|
+
const errors_1 = require("@feathersjs/errors");
|
|
7
|
+
const error_handler_1 = require("./error-handler");
|
|
8
|
+
const METHODS = {
|
|
9
|
+
$ne: 'whereNot',
|
|
10
|
+
$in: 'whereIn',
|
|
11
|
+
$nin: 'whereNotIn',
|
|
12
|
+
$or: 'orWhere',
|
|
13
|
+
$and: 'andWhere'
|
|
14
|
+
};
|
|
15
|
+
const OPERATORS = {
|
|
16
|
+
$lt: '<',
|
|
17
|
+
$lte: '<=',
|
|
18
|
+
$gt: '>',
|
|
19
|
+
$gte: '>=',
|
|
20
|
+
$like: 'like',
|
|
21
|
+
$notlike: 'not like',
|
|
22
|
+
$ilike: 'ilike'
|
|
23
|
+
};
|
|
24
|
+
class KnexAdapter extends adapter_commons_1.AdapterBase {
|
|
25
|
+
constructor(options) {
|
|
26
|
+
if (!options || !options.Model) {
|
|
27
|
+
throw new Error('You must provide a Model (the initialized knex object)');
|
|
28
|
+
}
|
|
29
|
+
if (typeof options.name !== 'string') {
|
|
30
|
+
throw new Error('No table name specified.');
|
|
31
|
+
}
|
|
32
|
+
super({
|
|
33
|
+
id: 'id',
|
|
34
|
+
...options,
|
|
35
|
+
filters: {
|
|
36
|
+
...options.filters,
|
|
37
|
+
$and: (value) => value
|
|
38
|
+
},
|
|
39
|
+
operators: [...(options.operators || []), '$like', '$notlike', '$ilike', '$and', '$or']
|
|
40
|
+
});
|
|
41
|
+
this.table = options.name;
|
|
42
|
+
this.schema = options.schema;
|
|
43
|
+
}
|
|
44
|
+
get Model() {
|
|
45
|
+
return this.options.Model;
|
|
46
|
+
}
|
|
47
|
+
get fullName() {
|
|
48
|
+
return this.schema ? `${this.schema}.${this.table}` : this.table;
|
|
49
|
+
}
|
|
50
|
+
db(_params) {
|
|
51
|
+
// const { Model, table, schema, fullName } = this
|
|
52
|
+
// if (params && params.transaction) {
|
|
53
|
+
// const { trx, id } = params.transaction
|
|
54
|
+
// debug('ran %s with transaction %s', fullName, id)
|
|
55
|
+
// return schema ? trx.withSchema(schema).table(table) : trx(table)
|
|
56
|
+
// }
|
|
57
|
+
// return schema ? Model.withSchema(schema).table(table) : Model(table)
|
|
58
|
+
return this.Model(this.table);
|
|
59
|
+
}
|
|
60
|
+
knexify(knexQuery, query = {}, parentKey) {
|
|
61
|
+
const knexify = this.knexify.bind(this);
|
|
62
|
+
return Object.keys(query || {}).reduce((currentQuery, key) => {
|
|
63
|
+
const value = query[key];
|
|
64
|
+
if (commons_1._.isObject(value)) {
|
|
65
|
+
return knexify(currentQuery, value, key);
|
|
66
|
+
}
|
|
67
|
+
const column = parentKey || key;
|
|
68
|
+
const method = METHODS[key];
|
|
69
|
+
if (method) {
|
|
70
|
+
if (key === '$or' || key === '$and') {
|
|
71
|
+
// This will create a nested query
|
|
72
|
+
currentQuery.where(function () {
|
|
73
|
+
for (const condition of value) {
|
|
74
|
+
this[method](function () {
|
|
75
|
+
knexify(this, condition);
|
|
76
|
+
});
|
|
77
|
+
}
|
|
78
|
+
});
|
|
79
|
+
return currentQuery;
|
|
80
|
+
}
|
|
81
|
+
return currentQuery[method](column, value);
|
|
82
|
+
}
|
|
83
|
+
const operator = OPERATORS[key] || '=';
|
|
84
|
+
return operator === '='
|
|
85
|
+
? currentQuery.where(column, value)
|
|
86
|
+
: currentQuery.where(column, operator, value);
|
|
87
|
+
}, knexQuery);
|
|
88
|
+
}
|
|
89
|
+
createQuery(params) {
|
|
90
|
+
const { table, id } = this;
|
|
91
|
+
const { filters, query } = this.filterQuery(params);
|
|
92
|
+
const builder = this.db(params);
|
|
93
|
+
// $select uses a specific find syntax, so it has to come first.
|
|
94
|
+
if (filters.$select) {
|
|
95
|
+
// always select the id field, but make sure we only select it once
|
|
96
|
+
builder.select(...new Set([...filters.$select, `${table}.${id}`]));
|
|
97
|
+
}
|
|
98
|
+
else {
|
|
99
|
+
builder.select(`${table}.*`);
|
|
100
|
+
}
|
|
101
|
+
// build up the knex query out of the query params, include $and and $or filters
|
|
102
|
+
this.knexify(builder, {
|
|
103
|
+
...query,
|
|
104
|
+
...commons_1._.pick(filters, '$and', '$or')
|
|
105
|
+
});
|
|
106
|
+
// Handle $sort
|
|
107
|
+
if (filters.$sort) {
|
|
108
|
+
return Object.keys(filters.$sort).reduce((currentQuery, key) => currentQuery.orderBy(key, filters.$sort[key] === 1 ? 'asc' : 'desc'), builder);
|
|
109
|
+
}
|
|
110
|
+
return builder;
|
|
111
|
+
}
|
|
112
|
+
filterQuery(params) {
|
|
113
|
+
const options = this.getOptions(params);
|
|
114
|
+
const { filters, query } = (0, adapter_commons_1.filterQuery)((params === null || params === void 0 ? void 0 : params.query) || {}, options);
|
|
115
|
+
return { filters, query, paginate: options.paginate };
|
|
116
|
+
}
|
|
117
|
+
async $find(params = {}) {
|
|
118
|
+
const { filters, paginate } = this.filterQuery(params);
|
|
119
|
+
const builder = params.knex ? params.knex.clone() : this.createQuery(params);
|
|
120
|
+
const countBuilder = builder.clone().count(`${this.table}.${this.id} as total`);
|
|
121
|
+
// Handle $limit
|
|
122
|
+
if (filters.$limit) {
|
|
123
|
+
builder.limit(filters.$limit);
|
|
124
|
+
}
|
|
125
|
+
// Handle $skip
|
|
126
|
+
if (filters.$skip) {
|
|
127
|
+
builder.offset(filters.$skip);
|
|
128
|
+
}
|
|
129
|
+
// provide default sorting if its not set
|
|
130
|
+
if (!filters.$sort) {
|
|
131
|
+
builder.orderBy(`${this.table}.${this.id}`, 'asc');
|
|
132
|
+
}
|
|
133
|
+
const data = filters.$limit === 0 ? [] : await builder;
|
|
134
|
+
if (paginate && paginate.default) {
|
|
135
|
+
return {
|
|
136
|
+
total: await countBuilder.then((count) => (count[0] ? count[0].total : 0)),
|
|
137
|
+
limit: filters.$limit,
|
|
138
|
+
skip: filters.$skip || 0,
|
|
139
|
+
data
|
|
140
|
+
};
|
|
141
|
+
}
|
|
142
|
+
return data;
|
|
143
|
+
}
|
|
144
|
+
async _findOrGet(id, params) {
|
|
145
|
+
const findParams = {
|
|
146
|
+
...params,
|
|
147
|
+
paginate: false,
|
|
148
|
+
query: {
|
|
149
|
+
...params === null || params === void 0 ? void 0 : params.query,
|
|
150
|
+
...(id !== null ? { [`${this.table}.${this.id}`]: id } : {})
|
|
151
|
+
}
|
|
152
|
+
};
|
|
153
|
+
return this.$find(findParams);
|
|
154
|
+
}
|
|
155
|
+
async $get(id, params = {}) {
|
|
156
|
+
const data = await this._findOrGet(id, params);
|
|
157
|
+
if (data.length !== 1) {
|
|
158
|
+
throw new errors_1.NotFound(`No record found for id '${id}'`);
|
|
159
|
+
}
|
|
160
|
+
return data[0];
|
|
161
|
+
}
|
|
162
|
+
async $create(_data, params = {}) {
|
|
163
|
+
const data = _data;
|
|
164
|
+
if (Array.isArray(data)) {
|
|
165
|
+
return Promise.all(data.map((current) => this.$create(current, params)));
|
|
166
|
+
}
|
|
167
|
+
const client = this.db(params).client.config.client;
|
|
168
|
+
const returning = client === 'pg' || client === 'oracledb' || client === 'mssql' ? [this.id] : [];
|
|
169
|
+
const rows = await this.db(params).insert(data, returning).catch(error_handler_1.errorHandler);
|
|
170
|
+
const id = data[this.id] || rows[0][this.id] || rows[0];
|
|
171
|
+
if (!id) {
|
|
172
|
+
return rows;
|
|
173
|
+
}
|
|
174
|
+
return this.$get(id, params);
|
|
175
|
+
}
|
|
176
|
+
async $patch(id, raw, params = {}) {
|
|
177
|
+
var _a, _b;
|
|
178
|
+
const data = commons_1._.omit(raw, this.id);
|
|
179
|
+
const results = await this._findOrGet(id, {
|
|
180
|
+
...params,
|
|
181
|
+
query: {
|
|
182
|
+
...params === null || params === void 0 ? void 0 : params.query,
|
|
183
|
+
$select: [`${this.table}.${this.id}`]
|
|
184
|
+
}
|
|
185
|
+
});
|
|
186
|
+
const idList = results.map((current) => current[this.id]);
|
|
187
|
+
const updateParams = {
|
|
188
|
+
...params,
|
|
189
|
+
query: {
|
|
190
|
+
[`${this.table}.${this.id}`]: { $in: idList },
|
|
191
|
+
...(((_a = params === null || params === void 0 ? void 0 : params.query) === null || _a === void 0 ? void 0 : _a.$select) ? { $select: (_b = params === null || params === void 0 ? void 0 : params.query) === null || _b === void 0 ? void 0 : _b.$select } : {})
|
|
192
|
+
}
|
|
193
|
+
};
|
|
194
|
+
const builder = this.createQuery(updateParams);
|
|
195
|
+
await builder.update(data);
|
|
196
|
+
const items = await this._findOrGet(null, updateParams);
|
|
197
|
+
if (id !== null) {
|
|
198
|
+
if (items.length === 1) {
|
|
199
|
+
return items[0];
|
|
200
|
+
}
|
|
201
|
+
else {
|
|
202
|
+
throw new errors_1.NotFound(`No record found for id '${id}'`);
|
|
203
|
+
}
|
|
204
|
+
}
|
|
205
|
+
return items;
|
|
206
|
+
}
|
|
207
|
+
async $update(id, _data, params = {}) {
|
|
208
|
+
const data = commons_1._.omit(_data, this.id);
|
|
209
|
+
const oldData = await this.$get(id, params);
|
|
210
|
+
const newObject = Object.keys(oldData).reduce((result, key) => {
|
|
211
|
+
if (key !== this.id) {
|
|
212
|
+
// We don't want the id field to be changed
|
|
213
|
+
result[key] = data[key] === undefined ? null : data[key];
|
|
214
|
+
}
|
|
215
|
+
return result;
|
|
216
|
+
}, {});
|
|
217
|
+
await this.db(params).update(newObject, '*').where(this.id, id);
|
|
218
|
+
return this.$get(id, params);
|
|
219
|
+
}
|
|
220
|
+
async $remove(id, params = {}) {
|
|
221
|
+
const items = await this._findOrGet(id, params);
|
|
222
|
+
const { query } = this.filterQuery(params);
|
|
223
|
+
const q = this.db(params);
|
|
224
|
+
const idList = items.map((current) => current[this.id]);
|
|
225
|
+
query[this.id] = { $in: idList };
|
|
226
|
+
// build up the knex query out of the query params
|
|
227
|
+
this.knexify(q, query);
|
|
228
|
+
await q.del().catch(error_handler_1.errorHandler);
|
|
229
|
+
if (id !== null) {
|
|
230
|
+
if (items.length === 1) {
|
|
231
|
+
return items[0];
|
|
232
|
+
}
|
|
233
|
+
throw new errors_1.NotFound(`No record found for id '${id}'`);
|
|
234
|
+
}
|
|
235
|
+
return items;
|
|
236
|
+
}
|
|
237
|
+
}
|
|
238
|
+
exports.KnexAdapter = KnexAdapter;
|
|
239
|
+
//# sourceMappingURL=adapter.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"adapter.js","sourceRoot":"","sources":["../src/adapter.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.errorHandler = exports.ERROR = void 0;
|
|
4
|
+
const errors_1 = require("@feathersjs/errors");
|
|
5
|
+
exports.ERROR = Symbol('@feathersjs/knex/error');
|
|
6
|
+
function errorHandler(error) {
|
|
7
|
+
const { message } = error;
|
|
8
|
+
let feathersError = error;
|
|
9
|
+
if (error.sqlState && error.sqlState.length) {
|
|
10
|
+
// remove SQLSTATE marker (#) and pad/truncate SQLSTATE to 5 chars
|
|
11
|
+
const sqlState = ('00000' + error.sqlState.replace('#', '')).slice(-5);
|
|
12
|
+
switch (sqlState.slice(0, 2)) {
|
|
13
|
+
case '02':
|
|
14
|
+
feathersError = new errors_1.errors.NotFound(message);
|
|
15
|
+
break;
|
|
16
|
+
case '28':
|
|
17
|
+
feathersError = new errors_1.errors.Forbidden(message);
|
|
18
|
+
break;
|
|
19
|
+
case '08':
|
|
20
|
+
case '0A':
|
|
21
|
+
case '0K':
|
|
22
|
+
feathersError = new errors_1.errors.Unavailable(message);
|
|
23
|
+
break;
|
|
24
|
+
case '20':
|
|
25
|
+
case '21':
|
|
26
|
+
case '22':
|
|
27
|
+
case '23':
|
|
28
|
+
case '24':
|
|
29
|
+
case '25':
|
|
30
|
+
case '40':
|
|
31
|
+
case '42':
|
|
32
|
+
case '70':
|
|
33
|
+
feathersError = new errors_1.errors.BadRequest(message);
|
|
34
|
+
break;
|
|
35
|
+
default:
|
|
36
|
+
feathersError = new errors_1.errors.GeneralError(message);
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
else if (error.code === 'SQLITE_ERROR') {
|
|
40
|
+
// NOTE (EK): Error codes taken from
|
|
41
|
+
// https://www.sqlite.org/c3ref/c_abort.html
|
|
42
|
+
switch (error.errno) {
|
|
43
|
+
case 1:
|
|
44
|
+
case 8:
|
|
45
|
+
case 18:
|
|
46
|
+
case 19:
|
|
47
|
+
case 20:
|
|
48
|
+
feathersError = new errors_1.errors.BadRequest(message);
|
|
49
|
+
break;
|
|
50
|
+
case 2:
|
|
51
|
+
feathersError = new errors_1.errors.Unavailable(message);
|
|
52
|
+
break;
|
|
53
|
+
case 3:
|
|
54
|
+
case 23:
|
|
55
|
+
feathersError = new errors_1.errors.Forbidden(message);
|
|
56
|
+
break;
|
|
57
|
+
case 12:
|
|
58
|
+
feathersError = new errors_1.errors.NotFound(message);
|
|
59
|
+
break;
|
|
60
|
+
default:
|
|
61
|
+
feathersError = new errors_1.errors.GeneralError(message);
|
|
62
|
+
break;
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
else if (typeof error.code === 'string' && error.severity && error.routine) {
|
|
66
|
+
// NOTE: Error codes taken from
|
|
67
|
+
// https://www.postgresql.org/docs/9.6/static/errcodes-appendix.html
|
|
68
|
+
// Omit query information
|
|
69
|
+
const messages = error.message.split('-');
|
|
70
|
+
error.message = messages[messages.length - 1];
|
|
71
|
+
switch (error.code.slice(0, 2)) {
|
|
72
|
+
case '22':
|
|
73
|
+
case '23':
|
|
74
|
+
feathersError = new errors_1.errors.BadRequest(message);
|
|
75
|
+
break;
|
|
76
|
+
case '28':
|
|
77
|
+
feathersError = new errors_1.errors.Forbidden(message);
|
|
78
|
+
break;
|
|
79
|
+
case '3D':
|
|
80
|
+
case '3F':
|
|
81
|
+
case '42':
|
|
82
|
+
feathersError = new errors_1.errors.Unprocessable(message);
|
|
83
|
+
break;
|
|
84
|
+
default:
|
|
85
|
+
feathersError = new errors_1.errors.GeneralError(message);
|
|
86
|
+
break;
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
else if (!(error instanceof errors_1.errors.FeathersError)) {
|
|
90
|
+
feathersError = new errors_1.errors.GeneralError(message);
|
|
91
|
+
}
|
|
92
|
+
feathersError[exports.ERROR] = error;
|
|
93
|
+
throw feathersError;
|
|
94
|
+
}
|
|
95
|
+
exports.errorHandler = errorHandler;
|
|
96
|
+
//# sourceMappingURL=error-handler.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"error-handler.js","sourceRoot":"","sources":["../src/error-handler.ts"],"names":[],"mappings":"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"}
|
package/lib/hooks.d.ts
ADDED
|
File without changes
|
package/lib/hooks.js
ADDED
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
// import { createDebug } from '@feathersjs/commons'
|
|
3
|
+
// import { HookContext } from '@feathersjs/feathers'
|
|
4
|
+
// const debug = createDebug('feathers-knex-transaction')
|
|
5
|
+
// const ROLLBACK = { rollback: true }
|
|
6
|
+
// export const getKnex = (context: HookContext) => {
|
|
7
|
+
// const knex = context.service.Model
|
|
8
|
+
// return knex && typeof knex.transaction === 'function' ? knex : undefined
|
|
9
|
+
// }
|
|
10
|
+
// export const start = (options = {}) => {
|
|
11
|
+
// options = Object.assign({ getKnex }, options)
|
|
12
|
+
// return (context: HookContext) => {
|
|
13
|
+
// const { transaction } = context.params
|
|
14
|
+
// const parent = transaction
|
|
15
|
+
// const knex = transaction ? transaction.trx : options.getKnex(context)
|
|
16
|
+
// if (!knex) {
|
|
17
|
+
// return
|
|
18
|
+
// }
|
|
19
|
+
// return new Promise((resolve, reject) => {
|
|
20
|
+
// const transaction = {}
|
|
21
|
+
// if (parent) {
|
|
22
|
+
// transaction.parent = parent
|
|
23
|
+
// transaction.committed = parent.committed
|
|
24
|
+
// } else {
|
|
25
|
+
// transaction.committed = new Promise((resolve) => {
|
|
26
|
+
// transaction.resolve = resolve
|
|
27
|
+
// })
|
|
28
|
+
// }
|
|
29
|
+
// transaction.starting = true
|
|
30
|
+
// transaction.promise = knex
|
|
31
|
+
// .transaction((trx) => {
|
|
32
|
+
// transaction.trx = trx
|
|
33
|
+
// transaction.id = Date.now()
|
|
34
|
+
// context.params = { ...context.params, transaction }
|
|
35
|
+
// debug('started a new transaction %s', transaction.id)
|
|
36
|
+
// resolve()
|
|
37
|
+
// })
|
|
38
|
+
// .catch((error) => {
|
|
39
|
+
// if (transaction.starting) {
|
|
40
|
+
// reject(error)
|
|
41
|
+
// } else if (error !== ROLLBACK) {
|
|
42
|
+
// throw error
|
|
43
|
+
// }
|
|
44
|
+
// })
|
|
45
|
+
// })
|
|
46
|
+
// }
|
|
47
|
+
// }
|
|
48
|
+
// export const end = () => {
|
|
49
|
+
// return (hook) => {
|
|
50
|
+
// const { transaction } = hook.params
|
|
51
|
+
// if (!transaction) {
|
|
52
|
+
// return
|
|
53
|
+
// }
|
|
54
|
+
// const { trx, id, promise, parent } = transaction
|
|
55
|
+
// hook.params = { ...hook.params, transaction: parent }
|
|
56
|
+
// transaction.starting = false
|
|
57
|
+
// return trx
|
|
58
|
+
// .commit()
|
|
59
|
+
// .then(() => promise)
|
|
60
|
+
// .then(() => transaction.resolve && transaction.resolve(true))
|
|
61
|
+
// .then(() => debug('ended transaction %s', id))
|
|
62
|
+
// .then(() => hook)
|
|
63
|
+
// }
|
|
64
|
+
// }
|
|
65
|
+
// export const rollback = () => {
|
|
66
|
+
// return (hook) => {
|
|
67
|
+
// const { transaction } = hook.params
|
|
68
|
+
// if (!transaction) {
|
|
69
|
+
// return
|
|
70
|
+
// }
|
|
71
|
+
// const { trx, id, promise, parent } = transaction
|
|
72
|
+
// hook.params = { ...hook.params, transaction: parent }
|
|
73
|
+
// transaction.starting = false
|
|
74
|
+
// return trx
|
|
75
|
+
// .rollback(ROLLBACK)
|
|
76
|
+
// .then(() => promise)
|
|
77
|
+
// .then(() => transaction.resolve && transaction.resolve(false))
|
|
78
|
+
// .then(() => debug('rolled back transaction %s', id))
|
|
79
|
+
// .then(() => hook)
|
|
80
|
+
// }
|
|
81
|
+
// }
|
|
82
|
+
//# sourceMappingURL=hooks.js.map
|
package/lib/hooks.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"hooks.js","sourceRoot":"","sources":["../src/hooks.ts"],"names":[],"mappings":";AAAA,oDAAoD;AACpD,qDAAqD;AAErD,yDAAyD;AAEzD,sCAAsC;AAEtC,qDAAqD;AACrD,uCAAuC;AAEvC,6EAA6E;AAC7E,IAAI;AAEJ,2CAA2C;AAC3C,kDAAkD;AAElD,uCAAuC;AACvC,6CAA6C;AAC7C,iCAAiC;AACjC,4EAA4E;AAE5E,mBAAmB;AACnB,eAAe;AACf,QAAQ;AAER,gDAAgD;AAChD,+BAA+B;AAE/B,sBAAsB;AACtB,sCAAsC;AACtC,mDAAmD;AACnD,iBAAiB;AACjB,6DAA6D;AAC7D,0CAA0C;AAC1C,aAAa;AACb,UAAU;AAEV,oCAAoC;AACpC,mCAAmC;AACnC,kCAAkC;AAClC,kCAAkC;AAClC,wCAAwC;AAExC,gEAAgE;AAEhE,kEAAkE;AAElE,sBAAsB;AACtB,aAAa;AACb,8BAA8B;AAC9B,wCAAwC;AACxC,4BAA4B;AAC5B,6CAA6C;AAC7C,0BAA0B;AAC1B,cAAc;AACd,aAAa;AACb,SAAS;AACT,MAAM;AACN,IAAI;AAEJ,6BAA6B;AAC7B,uBAAuB;AACvB,0CAA0C;AAE1C,0BAA0B;AAC1B,eAAe;AACf,QAAQ;AAER,uDAAuD;AAEvD,4DAA4D;AAC5D,mCAAmC;AAEnC,iBAAiB;AACjB,kBAAkB;AAClB,6BAA6B;AAC7B,sEAAsE;AACtE,uDAAuD;AACvD,0BAA0B;AAC1B,MAAM;AACN,IAAI;AAEJ,kCAAkC;AAClC,uBAAuB;AACvB,0CAA0C;AAE1C,0BAA0B;AAC1B,eAAe;AACf,QAAQ;AAER,uDAAuD;AAEvD,4DAA4D;AAC5D,mCAAmC;AAEnC,iBAAiB;AACjB,4BAA4B;AAC5B,6BAA6B;AAC7B,uEAAuE;AACvE,6DAA6D;AAC7D,0BAA0B;AAC1B,MAAM;AACN,IAAI"}
|
package/lib/index.d.ts
ADDED
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import { PaginationOptions } from '@feathersjs/adapter-commons';
|
|
2
|
+
import { Paginated, ServiceMethods, Id } from '@feathersjs/feathers';
|
|
3
|
+
import { KnexAdapter, KnexAdapterParams } from './adapter';
|
|
4
|
+
export * from './adapter';
|
|
5
|
+
export * from './error-handler';
|
|
6
|
+
export declare class KnexService<T = any, D = Partial<T>, P extends KnexAdapterParams<any> = KnexAdapterParams> extends KnexAdapter<T, D, P> implements ServiceMethods<T | Paginated<T>, D, P> {
|
|
7
|
+
find(params?: P & {
|
|
8
|
+
paginate?: PaginationOptions;
|
|
9
|
+
}): Promise<Paginated<T>>;
|
|
10
|
+
find(params?: P & {
|
|
11
|
+
paginate: false;
|
|
12
|
+
}): Promise<T[]>;
|
|
13
|
+
find(params?: P): Promise<Paginated<T> | T[]>;
|
|
14
|
+
get(id: Id, params?: P): Promise<T>;
|
|
15
|
+
create(data: Partial<D>, params?: P): Promise<T>;
|
|
16
|
+
create(data: Partial<D>[], params?: P): Promise<T[]>;
|
|
17
|
+
update(id: Id, data: D, params?: P): Promise<T>;
|
|
18
|
+
patch(id: Id, data: Partial<D>, params?: P): Promise<T>;
|
|
19
|
+
patch(id: null, data: Partial<D>, params?: P): Promise<T[]>;
|
|
20
|
+
remove(id: Id, params?: P): Promise<T>;
|
|
21
|
+
remove(id: null, params?: P): Promise<T[]>;
|
|
22
|
+
}
|
package/lib/index.js
ADDED
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __exportStar = (this && this.__exportStar) || function(m, exports) {
|
|
14
|
+
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
|
|
15
|
+
};
|
|
16
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
17
|
+
exports.KnexService = void 0;
|
|
18
|
+
const adapter_1 = require("./adapter");
|
|
19
|
+
__exportStar(require("./adapter"), exports);
|
|
20
|
+
__exportStar(require("./error-handler"), exports);
|
|
21
|
+
// export * from './hooks'
|
|
22
|
+
class KnexService extends adapter_1.KnexAdapter {
|
|
23
|
+
async find(params) {
|
|
24
|
+
return this._find(params);
|
|
25
|
+
}
|
|
26
|
+
async get(id, params) {
|
|
27
|
+
return this._get(id, params);
|
|
28
|
+
}
|
|
29
|
+
async create(data, params) {
|
|
30
|
+
return this._create(data, params);
|
|
31
|
+
}
|
|
32
|
+
async update(id, data, params) {
|
|
33
|
+
return this._update(id, data, params);
|
|
34
|
+
}
|
|
35
|
+
async patch(id, data, params) {
|
|
36
|
+
return this._patch(id, data, params);
|
|
37
|
+
}
|
|
38
|
+
async remove(id, params) {
|
|
39
|
+
return this._remove(id, params);
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
exports.KnexService = KnexService;
|
|
43
|
+
//# sourceMappingURL=index.js.map
|
package/lib/index.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;AAEA,uCAA0D;AAE1D,4CAAyB;AACzB,kDAA+B;AAC/B,0BAA0B;AAE1B,MAAa,WACX,SAAQ,qBAAoB;IAM5B,KAAK,CAAC,IAAI,CAAC,MAAU;QACnB,OAAO,IAAI,CAAC,KAAK,CAAC,MAAM,CAAQ,CAAA;IAClC,CAAC;IAED,KAAK,CAAC,GAAG,CAAC,EAAM,EAAE,MAAU;QAC1B,OAAO,IAAI,CAAC,IAAI,CAAC,EAAE,EAAE,MAAM,CAAC,CAAA;IAC9B,CAAC;IAID,KAAK,CAAC,MAAM,CAAC,IAA+B,EAAE,MAAU;QACtD,OAAO,IAAI,CAAC,OAAO,CAAC,IAAI,EAAE,MAAM,CAAC,CAAA;IACnC,CAAC;IAED,KAAK,CAAC,MAAM,CAAC,EAAM,EAAE,IAAO,EAAE,MAAU;QACtC,OAAO,IAAI,CAAC,OAAO,CAAC,EAAE,EAAE,IAAI,EAAE,MAAM,CAAC,CAAA;IACvC,CAAC;IAID,KAAK,CAAC,KAAK,CAAC,EAAc,EAAE,IAAgB,EAAE,MAAU;QACtD,OAAO,IAAI,CAAC,MAAM,CAAC,EAAE,EAAE,IAAI,EAAE,MAAM,CAAC,CAAA;IACtC,CAAC;IAID,KAAK,CAAC,MAAM,CAAC,EAAc,EAAE,MAAU;QACrC,OAAO,IAAI,CAAC,OAAO,CAAC,EAAE,EAAE,MAAM,CAAC,CAAA;IACjC,CAAC;CACF;AApCD,kCAoCC"}
|
package/package.json
ADDED
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@feathersjs/knex",
|
|
3
|
+
"description": "Feathers SQL service adapter using KnexJS",
|
|
4
|
+
"version": "5.0.0-pre.24",
|
|
5
|
+
"homepage": "https://feathersjs.com",
|
|
6
|
+
"main": "lib/",
|
|
7
|
+
"keywords": [
|
|
8
|
+
"feathers",
|
|
9
|
+
"feathers-plugin"
|
|
10
|
+
],
|
|
11
|
+
"license": "MIT",
|
|
12
|
+
"funding": {
|
|
13
|
+
"type": "github",
|
|
14
|
+
"url": "https://github.com/sponsors/daffl"
|
|
15
|
+
},
|
|
16
|
+
"repository": {
|
|
17
|
+
"type": "git",
|
|
18
|
+
"url": "git://github.com/feathersjs/feathers.git"
|
|
19
|
+
},
|
|
20
|
+
"author": {
|
|
21
|
+
"name": "Feathers contributors",
|
|
22
|
+
"email": "hello@feathersjs.com",
|
|
23
|
+
"url": "https://feathersjs.com"
|
|
24
|
+
},
|
|
25
|
+
"contributors": [],
|
|
26
|
+
"bugs": {
|
|
27
|
+
"url": "https://github.com/feathersjs/feathers/issues"
|
|
28
|
+
},
|
|
29
|
+
"engines": {
|
|
30
|
+
"node": ">= 14"
|
|
31
|
+
},
|
|
32
|
+
"files": [
|
|
33
|
+
"CHANGELOG.md",
|
|
34
|
+
"LICENSE",
|
|
35
|
+
"README.md",
|
|
36
|
+
"src/**",
|
|
37
|
+
"lib/**",
|
|
38
|
+
"*.d.ts",
|
|
39
|
+
"*.js"
|
|
40
|
+
],
|
|
41
|
+
"scripts": {
|
|
42
|
+
"compile": "shx rm -rf lib/ && tsc",
|
|
43
|
+
"test": "mocha --config ../../.mocharc.json --recursive test/**.test.ts test/**/*.test.ts"
|
|
44
|
+
},
|
|
45
|
+
"directories": {
|
|
46
|
+
"lib": "lib"
|
|
47
|
+
},
|
|
48
|
+
"publishConfig": {
|
|
49
|
+
"access": "public"
|
|
50
|
+
},
|
|
51
|
+
"dependencies": {
|
|
52
|
+
"@feathersjs/adapter-commons": "^5.0.0-pre.24",
|
|
53
|
+
"@feathersjs/commons": "^5.0.0-pre.24",
|
|
54
|
+
"@feathersjs/errors": "^5.0.0-pre.24",
|
|
55
|
+
"@feathersjs/feathers": "^5.0.0-pre.24"
|
|
56
|
+
},
|
|
57
|
+
"peerDependencies": {
|
|
58
|
+
"knex": "^2.1.0"
|
|
59
|
+
},
|
|
60
|
+
"devDependencies": {
|
|
61
|
+
"@feathersjs/adapter-tests": "^5.0.0-pre.24",
|
|
62
|
+
"@types/mocha": "^9.1.1",
|
|
63
|
+
"@types/node": "^17.0.40",
|
|
64
|
+
"knex": "^2.1.0",
|
|
65
|
+
"mocha": "^10.0.0",
|
|
66
|
+
"shx": "^0.3.4",
|
|
67
|
+
"sqlite3": "^5.0.8",
|
|
68
|
+
"typescript": "^4.7.3"
|
|
69
|
+
},
|
|
70
|
+
"gitHead": "72779fa2938f43d7b345b6861ff0035481a07de3"
|
|
71
|
+
}
|
package/src/adapter.ts
ADDED
|
@@ -0,0 +1,314 @@
|
|
|
1
|
+
import { Id, NullableId, Paginated, Query } from '@feathersjs/feathers'
|
|
2
|
+
import { _ } from '@feathersjs/commons'
|
|
3
|
+
import { AdapterBase, PaginationOptions, filterQuery } from '@feathersjs/adapter-commons'
|
|
4
|
+
import { NotFound } from '@feathersjs/errors'
|
|
5
|
+
import { Knex } from 'knex'
|
|
6
|
+
|
|
7
|
+
import { errorHandler } from './error-handler'
|
|
8
|
+
import { KnexAdapterOptions, KnexAdapterParams } from './declarations'
|
|
9
|
+
const METHODS = {
|
|
10
|
+
$ne: 'whereNot',
|
|
11
|
+
$in: 'whereIn',
|
|
12
|
+
$nin: 'whereNotIn',
|
|
13
|
+
$or: 'orWhere',
|
|
14
|
+
$and: 'andWhere'
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
const OPERATORS = {
|
|
18
|
+
$lt: '<',
|
|
19
|
+
$lte: '<=',
|
|
20
|
+
$gt: '>',
|
|
21
|
+
$gte: '>=',
|
|
22
|
+
$like: 'like',
|
|
23
|
+
$notlike: 'not like',
|
|
24
|
+
$ilike: 'ilike'
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
export class KnexAdapter<
|
|
28
|
+
T,
|
|
29
|
+
D = Partial<T>,
|
|
30
|
+
P extends KnexAdapterParams<any> = KnexAdapterParams
|
|
31
|
+
> extends AdapterBase<T, D, P, KnexAdapterOptions> {
|
|
32
|
+
table: string
|
|
33
|
+
schema?: string
|
|
34
|
+
|
|
35
|
+
constructor(options: KnexAdapterOptions) {
|
|
36
|
+
if (!options || !options.Model) {
|
|
37
|
+
throw new Error('You must provide a Model (the initialized knex object)')
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
if (typeof options.name !== 'string') {
|
|
41
|
+
throw new Error('No table name specified.')
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
super({
|
|
45
|
+
id: 'id',
|
|
46
|
+
...options,
|
|
47
|
+
filters: {
|
|
48
|
+
...options.filters,
|
|
49
|
+
$and: (value: any) => value
|
|
50
|
+
},
|
|
51
|
+
operators: [...(options.operators || []), '$like', '$notlike', '$ilike', '$and', '$or']
|
|
52
|
+
})
|
|
53
|
+
|
|
54
|
+
this.table = options.name
|
|
55
|
+
this.schema = options.schema
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
get Model() {
|
|
59
|
+
return this.options.Model
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
get fullName() {
|
|
63
|
+
return this.schema ? `${this.schema}.${this.table}` : this.table
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
db(params?: P) {
|
|
67
|
+
const { Model, table, schema } = this
|
|
68
|
+
|
|
69
|
+
if (params && params.transaction && params.transaction.trx) {
|
|
70
|
+
const { trx } = params.transaction
|
|
71
|
+
// debug('ran %s with transaction %s', fullName, id)
|
|
72
|
+
return schema ? (trx.withSchema(schema).table(table) as Knex.QueryBuilder) : trx(table)
|
|
73
|
+
}
|
|
74
|
+
return schema ? (Model.withSchema(schema).table(table) as Knex.QueryBuilder) : Model(table)
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
knexify(knexQuery: Knex.QueryBuilder, query: Query = {}, parentKey?: string): Knex.QueryBuilder {
|
|
78
|
+
const knexify = this.knexify.bind(this)
|
|
79
|
+
|
|
80
|
+
return Object.keys(query || {}).reduce((currentQuery, key) => {
|
|
81
|
+
const value = query[key]
|
|
82
|
+
|
|
83
|
+
if (_.isObject(value)) {
|
|
84
|
+
return knexify(currentQuery, value, key)
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
const column = parentKey || key
|
|
88
|
+
const method = METHODS[key as keyof typeof METHODS]
|
|
89
|
+
|
|
90
|
+
if (method) {
|
|
91
|
+
if (key === '$or' || key === '$and') {
|
|
92
|
+
// This will create a nested query
|
|
93
|
+
currentQuery.where(function (this: any) {
|
|
94
|
+
for (const condition of value) {
|
|
95
|
+
this[method](function (this: Knex.QueryBuilder) {
|
|
96
|
+
knexify(this, condition)
|
|
97
|
+
})
|
|
98
|
+
}
|
|
99
|
+
})
|
|
100
|
+
|
|
101
|
+
return currentQuery
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
return (currentQuery as any)[method](column, value)
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
const operator = OPERATORS[key as keyof typeof OPERATORS] || '='
|
|
108
|
+
|
|
109
|
+
return operator === '='
|
|
110
|
+
? currentQuery.where(column, value)
|
|
111
|
+
: currentQuery.where(column, operator, value)
|
|
112
|
+
}, knexQuery)
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
createQuery(params: P) {
|
|
116
|
+
const { table, id } = this
|
|
117
|
+
const { filters, query } = this.filterQuery(params)
|
|
118
|
+
const builder = this.db(params)
|
|
119
|
+
|
|
120
|
+
// $select uses a specific find syntax, so it has to come first.
|
|
121
|
+
if (filters.$select) {
|
|
122
|
+
// always select the id field, but make sure we only select it once
|
|
123
|
+
builder.select(...new Set([...filters.$select, `${table}.${id}`]))
|
|
124
|
+
} else {
|
|
125
|
+
builder.select(`${table}.*`)
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
// build up the knex query out of the query params, include $and and $or filters
|
|
129
|
+
this.knexify(builder, {
|
|
130
|
+
...query,
|
|
131
|
+
..._.pick(filters, '$and', '$or')
|
|
132
|
+
})
|
|
133
|
+
|
|
134
|
+
// Handle $sort
|
|
135
|
+
if (filters.$sort) {
|
|
136
|
+
return Object.keys(filters.$sort).reduce(
|
|
137
|
+
(currentQuery, key) => currentQuery.orderBy(key, filters.$sort[key] === 1 ? 'asc' : 'desc'),
|
|
138
|
+
builder
|
|
139
|
+
)
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
return builder
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
filterQuery(params: P) {
|
|
146
|
+
const options = this.getOptions(params)
|
|
147
|
+
const { filters, query } = filterQuery(params?.query || {}, options)
|
|
148
|
+
|
|
149
|
+
return { filters, query, paginate: options.paginate }
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
async $find(params?: P & { paginate?: PaginationOptions }): Promise<Paginated<T>>
|
|
153
|
+
async $find(params?: P & { paginate: false }): Promise<T[]>
|
|
154
|
+
async $find(params?: P): Promise<Paginated<T> | T[]>
|
|
155
|
+
async $find(params: P = {} as P): Promise<Paginated<T> | T[]> {
|
|
156
|
+
const { filters, paginate } = this.filterQuery(params)
|
|
157
|
+
const builder = params.knex ? params.knex.clone() : this.createQuery(params)
|
|
158
|
+
const countBuilder = builder.clone().count(`${this.table}.${this.id} as total`)
|
|
159
|
+
|
|
160
|
+
// Handle $limit
|
|
161
|
+
if (filters.$limit) {
|
|
162
|
+
builder.limit(filters.$limit)
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
// Handle $skip
|
|
166
|
+
if (filters.$skip) {
|
|
167
|
+
builder.offset(filters.$skip)
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
// provide default sorting if its not set
|
|
171
|
+
if (!filters.$sort) {
|
|
172
|
+
builder.orderBy(`${this.table}.${this.id}`, 'asc')
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
const data = filters.$limit === 0 ? [] : await builder
|
|
176
|
+
|
|
177
|
+
if (paginate && paginate.default) {
|
|
178
|
+
return {
|
|
179
|
+
total: await countBuilder.then((count) => (count[0] ? count[0].total : 0)),
|
|
180
|
+
limit: filters.$limit,
|
|
181
|
+
skip: filters.$skip || 0,
|
|
182
|
+
data
|
|
183
|
+
}
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
return data
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
async _findOrGet(id: NullableId, params?: P) {
|
|
190
|
+
const findParams = {
|
|
191
|
+
...params,
|
|
192
|
+
paginate: false,
|
|
193
|
+
query: {
|
|
194
|
+
...params?.query,
|
|
195
|
+
...(id !== null ? { [`${this.table}.${this.id}`]: id } : {})
|
|
196
|
+
}
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
return this.$find(findParams as any) as any as Promise<T[]>
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
async $get(id: Id, params: P = {} as P): Promise<T> {
|
|
203
|
+
const data = await this._findOrGet(id, params)
|
|
204
|
+
|
|
205
|
+
if (data.length !== 1) {
|
|
206
|
+
throw new NotFound(`No record found for id '${id}'`)
|
|
207
|
+
}
|
|
208
|
+
|
|
209
|
+
return data[0]
|
|
210
|
+
}
|
|
211
|
+
|
|
212
|
+
async $create(data: Partial<D>, params?: P): Promise<T>
|
|
213
|
+
async $create(data: Partial<D>[], params?: P): Promise<T[]>
|
|
214
|
+
async $create(data: Partial<D> | Partial<D>[], _params?: P): Promise<T | T[]>
|
|
215
|
+
async $create(_data: Partial<D> | Partial<D>[], params: P = {} as P): Promise<T | T[]> {
|
|
216
|
+
const data = _data as any
|
|
217
|
+
|
|
218
|
+
if (Array.isArray(data)) {
|
|
219
|
+
return Promise.all(data.map((current) => this.$create(current, params)))
|
|
220
|
+
}
|
|
221
|
+
|
|
222
|
+
const client = this.db(params).client.config.client
|
|
223
|
+
const returning = client === 'pg' || client === 'oracledb' || client === 'mssql' ? [this.id] : []
|
|
224
|
+
const rows: any = await this.db(params).insert(data, returning).catch(errorHandler)
|
|
225
|
+
const id = data[this.id] || rows[0][this.id] || rows[0]
|
|
226
|
+
|
|
227
|
+
if (!id) {
|
|
228
|
+
return rows as T[]
|
|
229
|
+
}
|
|
230
|
+
|
|
231
|
+
return this.$get(id, params)
|
|
232
|
+
}
|
|
233
|
+
|
|
234
|
+
async $patch(id: null, data: Partial<D>, params?: P): Promise<T[]>
|
|
235
|
+
async $patch(id: Id, data: Partial<D>, params?: P): Promise<T>
|
|
236
|
+
async $patch(id: NullableId, data: Partial<D>, _params?: P): Promise<T | T[]>
|
|
237
|
+
async $patch(id: NullableId, raw: Partial<D>, params: P = {} as P): Promise<T | T[]> {
|
|
238
|
+
const data = _.omit(raw, this.id)
|
|
239
|
+
const results = await this._findOrGet(id, {
|
|
240
|
+
...params,
|
|
241
|
+
query: {
|
|
242
|
+
...params?.query,
|
|
243
|
+
$select: [`${this.table}.${this.id}`]
|
|
244
|
+
}
|
|
245
|
+
})
|
|
246
|
+
const idList = results.map((current: any) => current[this.id])
|
|
247
|
+
const updateParams = {
|
|
248
|
+
...params,
|
|
249
|
+
query: {
|
|
250
|
+
[`${this.table}.${this.id}`]: { $in: idList },
|
|
251
|
+
...(params?.query?.$select ? { $select: params?.query?.$select } : {})
|
|
252
|
+
}
|
|
253
|
+
}
|
|
254
|
+
const builder = this.createQuery(updateParams)
|
|
255
|
+
|
|
256
|
+
await builder.update(data)
|
|
257
|
+
|
|
258
|
+
const items = await this._findOrGet(null, updateParams)
|
|
259
|
+
|
|
260
|
+
if (id !== null) {
|
|
261
|
+
if (items.length === 1) {
|
|
262
|
+
return items[0]
|
|
263
|
+
} else {
|
|
264
|
+
throw new NotFound(`No record found for id '${id}'`)
|
|
265
|
+
}
|
|
266
|
+
}
|
|
267
|
+
|
|
268
|
+
return items
|
|
269
|
+
}
|
|
270
|
+
|
|
271
|
+
async $update(id: Id, _data: D, params: P = {} as P): Promise<T> {
|
|
272
|
+
const data = _.omit(_data, this.id)
|
|
273
|
+
const oldData = await this.$get(id, params)
|
|
274
|
+
const newObject = Object.keys(oldData).reduce((result: any, key) => {
|
|
275
|
+
if (key !== this.id) {
|
|
276
|
+
// We don't want the id field to be changed
|
|
277
|
+
result[key] = data[key] === undefined ? null : data[key]
|
|
278
|
+
}
|
|
279
|
+
|
|
280
|
+
return result
|
|
281
|
+
}, {})
|
|
282
|
+
|
|
283
|
+
await this.db(params).update(newObject, '*').where(this.id, id)
|
|
284
|
+
|
|
285
|
+
return this.$get(id, params)
|
|
286
|
+
}
|
|
287
|
+
|
|
288
|
+
async $remove(id: null, params?: P): Promise<T[]>
|
|
289
|
+
async $remove(id: Id, params?: P): Promise<T>
|
|
290
|
+
async $remove(id: NullableId, _params?: P): Promise<T | T[]>
|
|
291
|
+
async $remove(id: NullableId, params: P = {} as P): Promise<T | T[]> {
|
|
292
|
+
const items = await this._findOrGet(id, params)
|
|
293
|
+
const { query } = this.filterQuery(params)
|
|
294
|
+
const q = this.db(params)
|
|
295
|
+
const idList = items.map((current: any) => current[this.id])
|
|
296
|
+
|
|
297
|
+
query[this.id] = { $in: idList }
|
|
298
|
+
|
|
299
|
+
// build up the knex query out of the query params
|
|
300
|
+
this.knexify(q, query)
|
|
301
|
+
|
|
302
|
+
await q.del().catch(errorHandler)
|
|
303
|
+
|
|
304
|
+
if (id !== null) {
|
|
305
|
+
if (items.length === 1) {
|
|
306
|
+
return items[0]
|
|
307
|
+
}
|
|
308
|
+
|
|
309
|
+
throw new NotFound(`No record found for id '${id}'`)
|
|
310
|
+
}
|
|
311
|
+
|
|
312
|
+
return items
|
|
313
|
+
}
|
|
314
|
+
}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import { Knex } from 'knex'
|
|
2
|
+
import { AdapterServiceOptions, AdapterParams, AdapterQuery } from '@feathersjs/adapter-commons'
|
|
3
|
+
|
|
4
|
+
export interface KnexAdapterOptions extends AdapterServiceOptions {
|
|
5
|
+
Model: Knex
|
|
6
|
+
name: string
|
|
7
|
+
schema?: string
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
export interface KnexAdapterTransaction {
|
|
11
|
+
starting: boolean
|
|
12
|
+
parent?: KnexAdapterTransaction
|
|
13
|
+
committed?: any
|
|
14
|
+
resolve?: any
|
|
15
|
+
trx?: Knex.Transaction
|
|
16
|
+
id?: number
|
|
17
|
+
promise?: Promise<any>
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
export interface KnexAdapterParams<Q = AdapterQuery> extends AdapterParams<Q, Partial<KnexAdapterOptions>> {
|
|
21
|
+
knex?: Knex.QueryBuilder
|
|
22
|
+
transaction?: KnexAdapterTransaction
|
|
23
|
+
}
|
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
import { errors } from '@feathersjs/errors'
|
|
2
|
+
|
|
3
|
+
export const ERROR = Symbol('@feathersjs/knex/error')
|
|
4
|
+
|
|
5
|
+
export function errorHandler(error: any) {
|
|
6
|
+
const { message } = error
|
|
7
|
+
let feathersError = error
|
|
8
|
+
|
|
9
|
+
if (error.sqlState && error.sqlState.length) {
|
|
10
|
+
// remove SQLSTATE marker (#) and pad/truncate SQLSTATE to 5 chars
|
|
11
|
+
const sqlState = ('00000' + error.sqlState.replace('#', '')).slice(-5)
|
|
12
|
+
|
|
13
|
+
switch (sqlState.slice(0, 2)) {
|
|
14
|
+
case '02':
|
|
15
|
+
feathersError = new errors.NotFound(message)
|
|
16
|
+
break
|
|
17
|
+
case '28':
|
|
18
|
+
feathersError = new errors.Forbidden(message)
|
|
19
|
+
break
|
|
20
|
+
case '08':
|
|
21
|
+
case '0A':
|
|
22
|
+
case '0K':
|
|
23
|
+
feathersError = new errors.Unavailable(message)
|
|
24
|
+
break
|
|
25
|
+
case '20':
|
|
26
|
+
case '21':
|
|
27
|
+
case '22':
|
|
28
|
+
case '23':
|
|
29
|
+
case '24':
|
|
30
|
+
case '25':
|
|
31
|
+
case '40':
|
|
32
|
+
case '42':
|
|
33
|
+
case '70':
|
|
34
|
+
feathersError = new errors.BadRequest(message)
|
|
35
|
+
break
|
|
36
|
+
default:
|
|
37
|
+
feathersError = new errors.GeneralError(message)
|
|
38
|
+
}
|
|
39
|
+
} else if (error.code === 'SQLITE_ERROR') {
|
|
40
|
+
// NOTE (EK): Error codes taken from
|
|
41
|
+
// https://www.sqlite.org/c3ref/c_abort.html
|
|
42
|
+
switch (error.errno) {
|
|
43
|
+
case 1:
|
|
44
|
+
case 8:
|
|
45
|
+
case 18:
|
|
46
|
+
case 19:
|
|
47
|
+
case 20:
|
|
48
|
+
feathersError = new errors.BadRequest(message)
|
|
49
|
+
break
|
|
50
|
+
case 2:
|
|
51
|
+
feathersError = new errors.Unavailable(message)
|
|
52
|
+
break
|
|
53
|
+
case 3:
|
|
54
|
+
case 23:
|
|
55
|
+
feathersError = new errors.Forbidden(message)
|
|
56
|
+
break
|
|
57
|
+
case 12:
|
|
58
|
+
feathersError = new errors.NotFound(message)
|
|
59
|
+
break
|
|
60
|
+
default:
|
|
61
|
+
feathersError = new errors.GeneralError(message)
|
|
62
|
+
break
|
|
63
|
+
}
|
|
64
|
+
} else if (typeof error.code === 'string' && error.severity && error.routine) {
|
|
65
|
+
// NOTE: Error codes taken from
|
|
66
|
+
// https://www.postgresql.org/docs/9.6/static/errcodes-appendix.html
|
|
67
|
+
// Omit query information
|
|
68
|
+
const messages = error.message.split('-')
|
|
69
|
+
error.message = messages[messages.length - 1]
|
|
70
|
+
|
|
71
|
+
switch (error.code.slice(0, 2)) {
|
|
72
|
+
case '22':
|
|
73
|
+
case '23':
|
|
74
|
+
feathersError = new errors.BadRequest(message)
|
|
75
|
+
break
|
|
76
|
+
case '28':
|
|
77
|
+
feathersError = new errors.Forbidden(message)
|
|
78
|
+
break
|
|
79
|
+
case '3D':
|
|
80
|
+
case '3F':
|
|
81
|
+
case '42':
|
|
82
|
+
feathersError = new errors.Unprocessable(message)
|
|
83
|
+
break
|
|
84
|
+
default:
|
|
85
|
+
feathersError = new errors.GeneralError(message)
|
|
86
|
+
break
|
|
87
|
+
}
|
|
88
|
+
} else if (!(error instanceof errors.FeathersError)) {
|
|
89
|
+
feathersError = new errors.GeneralError(message)
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
feathersError[ERROR] = error
|
|
93
|
+
|
|
94
|
+
throw feathersError
|
|
95
|
+
}
|
package/src/hooks.ts
ADDED
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
import { createDebug } from '@feathersjs/commons'
|
|
2
|
+
import { HookContext } from '@feathersjs/feathers'
|
|
3
|
+
import { Knex } from 'knex'
|
|
4
|
+
import { KnexAdapterTransaction } from './declarations'
|
|
5
|
+
|
|
6
|
+
const debug = createDebug('feathers-knex-transaction')
|
|
7
|
+
|
|
8
|
+
const ROLLBACK = { rollback: true }
|
|
9
|
+
|
|
10
|
+
export const getKnex = (context: HookContext): Knex => {
|
|
11
|
+
const knex = context.service.Model
|
|
12
|
+
|
|
13
|
+
return knex && typeof knex.transaction === 'function' ? knex : undefined
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
export const start =
|
|
17
|
+
() =>
|
|
18
|
+
async (context: HookContext): Promise<void> => {
|
|
19
|
+
const { transaction } = context.params
|
|
20
|
+
const parent = transaction
|
|
21
|
+
const knex: Knex = transaction ? transaction.trx : getKnex(context)
|
|
22
|
+
|
|
23
|
+
if (!knex) {
|
|
24
|
+
return
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
return new Promise<void>((resolve, reject) => {
|
|
28
|
+
const transaction: KnexAdapterTransaction = {
|
|
29
|
+
starting: true
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
if (parent) {
|
|
33
|
+
transaction.parent = parent
|
|
34
|
+
transaction.committed = parent.committed
|
|
35
|
+
} else {
|
|
36
|
+
transaction.committed = new Promise((resolve) => {
|
|
37
|
+
transaction.resolve = resolve
|
|
38
|
+
})
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
transaction.starting = true
|
|
42
|
+
transaction.promise = knex
|
|
43
|
+
.transaction((trx) => {
|
|
44
|
+
transaction.trx = trx
|
|
45
|
+
transaction.id = Date.now()
|
|
46
|
+
|
|
47
|
+
context.params = { ...context.params, transaction }
|
|
48
|
+
|
|
49
|
+
debug('started a new transaction %s', transaction.id)
|
|
50
|
+
|
|
51
|
+
resolve()
|
|
52
|
+
})
|
|
53
|
+
.catch((error) => {
|
|
54
|
+
if (transaction.starting) {
|
|
55
|
+
reject(error)
|
|
56
|
+
} else if (error !== ROLLBACK) {
|
|
57
|
+
throw error
|
|
58
|
+
}
|
|
59
|
+
})
|
|
60
|
+
})
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
export const end = () => (context: HookContext) => {
|
|
64
|
+
const { transaction } = context.params
|
|
65
|
+
|
|
66
|
+
if (!transaction) {
|
|
67
|
+
return
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
const { trx, id, promise, parent } = transaction
|
|
71
|
+
|
|
72
|
+
context.params = { ...context.params, transaction: parent }
|
|
73
|
+
transaction.starting = false
|
|
74
|
+
|
|
75
|
+
return trx
|
|
76
|
+
.commit()
|
|
77
|
+
.then(() => promise)
|
|
78
|
+
.then(() => transaction.resolve && transaction.resolve(true))
|
|
79
|
+
.then(() => debug('ended transaction %s', id))
|
|
80
|
+
.then(() => context)
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
export const rollback = () => (context: HookContext) => {
|
|
84
|
+
const { transaction } = context.params
|
|
85
|
+
|
|
86
|
+
if (!transaction) {
|
|
87
|
+
return
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
const { trx, id, promise, parent } = transaction
|
|
91
|
+
|
|
92
|
+
context.params = { ...context.params, transaction: parent }
|
|
93
|
+
transaction.starting = false
|
|
94
|
+
|
|
95
|
+
return trx
|
|
96
|
+
.rollback(ROLLBACK)
|
|
97
|
+
.then(() => promise)
|
|
98
|
+
.then(() => transaction.resolve && transaction.resolve(false))
|
|
99
|
+
.then(() => debug('rolled back transaction %s', id))
|
|
100
|
+
.then(() => context)
|
|
101
|
+
}
|
package/src/index.ts
ADDED
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
import { PaginationOptions } from '@feathersjs/adapter-commons'
|
|
2
|
+
import { Paginated, ServiceMethods, Id, NullableId } from '@feathersjs/feathers'
|
|
3
|
+
import { KnexAdapter } from './adapter'
|
|
4
|
+
import { KnexAdapterParams } from './declarations'
|
|
5
|
+
|
|
6
|
+
export * from './declarations'
|
|
7
|
+
export * from './adapter'
|
|
8
|
+
export * from './error-handler'
|
|
9
|
+
export * as transaction from './hooks'
|
|
10
|
+
|
|
11
|
+
export class KnexService<T = any, D = Partial<T>, P extends KnexAdapterParams<any> = KnexAdapterParams>
|
|
12
|
+
extends KnexAdapter<T, D, P>
|
|
13
|
+
implements ServiceMethods<T | Paginated<T>, D, P>
|
|
14
|
+
{
|
|
15
|
+
async find(params?: P & { paginate?: PaginationOptions }): Promise<Paginated<T>>
|
|
16
|
+
async find(params?: P & { paginate: false }): Promise<T[]>
|
|
17
|
+
async find(params?: P): Promise<Paginated<T> | T[]>
|
|
18
|
+
async find(params?: P): Promise<Paginated<T> | T[]> {
|
|
19
|
+
return this._find(params) as any
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
async get(id: Id, params?: P): Promise<T> {
|
|
23
|
+
return this._get(id, params)
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
async create(data: Partial<D>, params?: P): Promise<T>
|
|
27
|
+
async create(data: Partial<D>[], params?: P): Promise<T[]>
|
|
28
|
+
async create(data: Partial<D> | Partial<D>[], params?: P): Promise<T | T[]> {
|
|
29
|
+
return this._create(data, params)
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
async update(id: Id, data: D, params?: P): Promise<T> {
|
|
33
|
+
return this._update(id, data, params)
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
async patch(id: Id, data: Partial<D>, params?: P): Promise<T>
|
|
37
|
+
async patch(id: null, data: Partial<D>, params?: P): Promise<T[]>
|
|
38
|
+
async patch(id: NullableId, data: Partial<D>, params?: P): Promise<T | T[]> {
|
|
39
|
+
return this._patch(id, data, params)
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
async remove(id: Id, params?: P): Promise<T>
|
|
43
|
+
async remove(id: null, params?: P): Promise<T[]>
|
|
44
|
+
async remove(id: NullableId, params?: P): Promise<T | T[]> {
|
|
45
|
+
return this._remove(id, params)
|
|
46
|
+
}
|
|
47
|
+
}
|