kuzzle 2.23.0 → 2.25.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/README.md +1 -6
- package/lib/api/controllers/documentController.js +8 -0
- package/lib/cluster/idCardHandler.js +6 -1
- package/lib/cluster/workers/IDCardRenewer.js +2 -1
- package/lib/config/default.config.js +1 -0
- package/lib/config/index.js +6 -0
- package/lib/core/network/protocols/httpwsProtocol.js +5 -1
- package/lib/core/network/router.js +12 -0
- package/lib/kerror/codes/1-services.json +11 -0
- package/lib/service/storage/queryTranslator.js +68 -5
- package/lib/types/config/ServerConfiguration.d.ts +12 -0
- package/package.json +28 -28
package/README.md
CHANGED
|
@@ -111,12 +111,8 @@ Learn how to [Write an Application](https://docs.kuzzle.io/core/2/guides/getting
|
|
|
111
111
|
|
|
112
112
|
Train yourself and your teams to use Kuzzle to maximize its potential and accelerate the development of your projects.
|
|
113
113
|
Our teams will be able to meet your needs in terms of expertise and multi-technology support for IoT, mobile/web, backend/frontend, devops.
|
|
114
|
-
:point_right: [Get a quote](https://
|
|
114
|
+
:point_right: [Get a quote](https://kuzzle.io/pricing/)
|
|
115
115
|
|
|
116
|
-
## Public Roadmap
|
|
117
|
-
|
|
118
|
-
You can consult the public roadmap on Trello. Come and vote for the features you need!
|
|
119
|
-
:point_right: [Kuzzle Public Roadmap](https://trello.com/b/za9vOgRh/kuzzle-public-roadmap)
|
|
120
116
|
|
|
121
117
|
## Contributing to Kuzzle
|
|
122
118
|
|
|
@@ -132,7 +128,6 @@ Check our [contributing documentation](./CONTRIBUTING.md) to know about our codi
|
|
|
132
128
|
* Visit our [blog](https://blog.kuzzle.io/) to be informed about what we are doing
|
|
133
129
|
* Come chat with us on [Discord](http://join.discord.kuzzle.io)
|
|
134
130
|
* Ask technical questions on [stack overflow](https://stackoverflow.com/search?q=kuzzle)
|
|
135
|
-
* Check out our [public roadmap](https://trello.com/b/za9vOgRh/kuzzle-public-roadmap) and vote for the upcoming features
|
|
136
131
|
|
|
137
132
|
## License
|
|
138
133
|
|
|
@@ -131,6 +131,14 @@ class DocumentController extends NativeController {
|
|
|
131
131
|
{ from, scroll: scrollTTL, size }
|
|
132
132
|
);
|
|
133
133
|
} else {
|
|
134
|
+
if (!index) {
|
|
135
|
+
throw kerror.get("api", "assert", "missing_argument", "index");
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
if (!collection) {
|
|
139
|
+
throw kerror.get("api", "assert", "missing_argument", "collection");
|
|
140
|
+
}
|
|
141
|
+
|
|
134
142
|
result = await this.ask(
|
|
135
143
|
"core:storage:public:document:search",
|
|
136
144
|
index,
|
|
@@ -146,7 +146,12 @@ class ClusterIdCardHandler {
|
|
|
146
146
|
const childProcess = (0, child_process_1.fork)(path);
|
|
147
147
|
const exitHandler = () => {
|
|
148
148
|
if (!childProcess.killed || childProcess.connected) {
|
|
149
|
-
|
|
149
|
+
try {
|
|
150
|
+
childProcess.disconnect();
|
|
151
|
+
}
|
|
152
|
+
catch (e) {
|
|
153
|
+
// It could happens that the worker has been killed before the dispose causing disconnect to fail
|
|
154
|
+
}
|
|
150
155
|
}
|
|
151
156
|
process.exit();
|
|
152
157
|
};
|
|
@@ -136,7 +136,8 @@ process.on("message", async (message) => {
|
|
|
136
136
|
});
|
|
137
137
|
|
|
138
138
|
// When the IPC is closed on the main process side
|
|
139
|
-
process.on("disconnect", () => {
|
|
139
|
+
process.on("disconnect", async () => {
|
|
140
|
+
await idCardRenewer.dispose();
|
|
140
141
|
process.exit();
|
|
141
142
|
});
|
|
142
143
|
|
package/lib/config/index.js
CHANGED
|
@@ -236,10 +236,16 @@ function checkHttpOptions(config) {
|
|
|
236
236
|
`[http] "maxFormFileSize" parameter: cannot parse "${cfg.maxFormFileSize}"`
|
|
237
237
|
);
|
|
238
238
|
cfg.maxFormFileSize = maxFormFileSize;
|
|
239
|
+
|
|
239
240
|
assert(
|
|
240
241
|
typeof config.http.cookieAuthentication === "boolean",
|
|
241
242
|
`[http] "cookieAuthentication" parameter: invalid value "${config.http.cookieAuthentication}" (boolean expected)`
|
|
242
243
|
);
|
|
244
|
+
assert(
|
|
245
|
+
Array.isArray(cfg.additionalContentTypes) &&
|
|
246
|
+
cfg.additionalContentTypes.every((ct) => typeof ct === "string"),
|
|
247
|
+
`[http] "additionalContentTypes" parameter: invalid value "${cfg.additionalContentTypes}" (array of strings expected)`
|
|
248
|
+
);
|
|
243
249
|
}
|
|
244
250
|
|
|
245
251
|
function checkClusterOptions(config) {
|
|
@@ -502,7 +502,7 @@ class HttpWsProtocol extends Protocol {
|
|
|
502
502
|
|
|
503
503
|
if (
|
|
504
504
|
contentType &&
|
|
505
|
-
!
|
|
505
|
+
!this.httpConfig.opts.allowedContentTypes.some((allowed) =>
|
|
506
506
|
contentType.includes(allowed)
|
|
507
507
|
)
|
|
508
508
|
) {
|
|
@@ -1194,6 +1194,10 @@ class HttpWsProtocol extends Protocol {
|
|
|
1194
1194
|
headers,
|
|
1195
1195
|
opts: {
|
|
1196
1196
|
allowCompression: cfg.allowCompression,
|
|
1197
|
+
allowedContentTypes: [
|
|
1198
|
+
...HTTP_ALLOWED_CONTENT_TYPES,
|
|
1199
|
+
...cfg.additionalContentTypes,
|
|
1200
|
+
],
|
|
1197
1201
|
maxEncodingLayers: cfg.maxEncodingLayers,
|
|
1198
1202
|
maxFormFileSize: cfg.maxFormFileSize,
|
|
1199
1203
|
},
|
|
@@ -136,6 +136,18 @@ class Router {
|
|
|
136
136
|
this._executeFromHttp("post", apiRequest, cb);
|
|
137
137
|
});
|
|
138
138
|
|
|
139
|
+
this.http.get("_healthcheck", (request, cb) => {
|
|
140
|
+
request.response.configure({
|
|
141
|
+
status: 200,
|
|
142
|
+
});
|
|
143
|
+
|
|
144
|
+
/**
|
|
145
|
+
* By avoiding using the funnel, we avoid the request to be logged
|
|
146
|
+
* This is useful for ochestrators healthchecks
|
|
147
|
+
*/
|
|
148
|
+
cb(request);
|
|
149
|
+
});
|
|
150
|
+
|
|
139
151
|
for (const route of routes) {
|
|
140
152
|
const verb = route.verb.toLowerCase();
|
|
141
153
|
|
|
@@ -335,6 +335,17 @@
|
|
|
335
335
|
"class": "InternalError"
|
|
336
336
|
}
|
|
337
337
|
}
|
|
338
|
+
},
|
|
339
|
+
"koncorde": {
|
|
340
|
+
"code": 5,
|
|
341
|
+
"errors": {
|
|
342
|
+
"elastic_translation_error": {
|
|
343
|
+
"description": "An error occured while translating a Koncorde filter to an Elasticsearch query",
|
|
344
|
+
"code": 1,
|
|
345
|
+
"message": "An error occured while translating a Koncorde filter to an Elasticsearch query: %s",
|
|
346
|
+
"class": "BadRequestError"
|
|
347
|
+
}
|
|
348
|
+
}
|
|
338
349
|
}
|
|
339
350
|
}
|
|
340
351
|
}
|
|
@@ -21,6 +21,8 @@
|
|
|
21
21
|
|
|
22
22
|
"use strict";
|
|
23
23
|
|
|
24
|
+
const kerror = require("../../kerror");
|
|
25
|
+
|
|
24
26
|
class KeywordError extends Error {
|
|
25
27
|
constructor(type, name) {
|
|
26
28
|
super(
|
|
@@ -33,17 +35,78 @@ class KeywordError extends Error {
|
|
|
33
35
|
|
|
34
36
|
const KONCORDE_OPERATORS = ["and", "or", "not", "bool"];
|
|
35
37
|
|
|
38
|
+
/**
|
|
39
|
+
* Parse the Koncorde path to extract the path and the value
|
|
40
|
+
* path have the form "path.to.field[json_value]"
|
|
41
|
+
*
|
|
42
|
+
* @param {string} path
|
|
43
|
+
* @returns
|
|
44
|
+
*/
|
|
45
|
+
function parseKoncordePath(path) {
|
|
46
|
+
const firstBracket = path.indexOf("[");
|
|
47
|
+
|
|
48
|
+
if (firstBracket < 0) {
|
|
49
|
+
return {
|
|
50
|
+
path,
|
|
51
|
+
};
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
const lastBracket = path.lastIndexOf("]");
|
|
55
|
+
|
|
56
|
+
if (lastBracket < 0) {
|
|
57
|
+
throw kerror.get(
|
|
58
|
+
"services",
|
|
59
|
+
"koncorde",
|
|
60
|
+
"elastic_translation_error",
|
|
61
|
+
`Invalid exists path "${path}": missing closing bracket`
|
|
62
|
+
);
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
return {
|
|
66
|
+
path: path.slice(0, firstBracket),
|
|
67
|
+
value: JSON.parse(path.slice(firstBracket + 1, lastBracket)),
|
|
68
|
+
};
|
|
69
|
+
}
|
|
70
|
+
|
|
36
71
|
const KONCORDE_CLAUSES_TO_ES = {
|
|
37
72
|
equals: (content) => ({
|
|
38
73
|
term: {
|
|
39
74
|
...content,
|
|
40
75
|
},
|
|
41
76
|
}),
|
|
42
|
-
exists: (field) =>
|
|
43
|
-
exists: {
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
77
|
+
exists: (field) => {
|
|
78
|
+
// Support old syntax { exists: { field: "path" } } and { exists: "path" }
|
|
79
|
+
const parsedInfo = parseKoncordePath(field.field || field);
|
|
80
|
+
|
|
81
|
+
// If we have a value, we need to use a range query to be sure that the value is the same
|
|
82
|
+
if (parsedInfo.value) {
|
|
83
|
+
return {
|
|
84
|
+
bool: {
|
|
85
|
+
filter: [
|
|
86
|
+
{
|
|
87
|
+
exists: {
|
|
88
|
+
field: parsedInfo.path,
|
|
89
|
+
},
|
|
90
|
+
},
|
|
91
|
+
{
|
|
92
|
+
range: {
|
|
93
|
+
[parsedInfo.path]: {
|
|
94
|
+
gte: parsedInfo.value,
|
|
95
|
+
lte: parsedInfo.value,
|
|
96
|
+
},
|
|
97
|
+
},
|
|
98
|
+
},
|
|
99
|
+
],
|
|
100
|
+
},
|
|
101
|
+
};
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
return {
|
|
105
|
+
exists: {
|
|
106
|
+
field: parsedInfo.path,
|
|
107
|
+
},
|
|
108
|
+
};
|
|
109
|
+
},
|
|
47
110
|
geoBoundingBox: (content) => ({
|
|
48
111
|
geo_bounding_box: {
|
|
49
112
|
...content,
|
|
@@ -68,6 +68,18 @@ export type ServerConfiguration = {
|
|
|
68
68
|
*/
|
|
69
69
|
protocols: {
|
|
70
70
|
http: {
|
|
71
|
+
/**
|
|
72
|
+
* Enables Kuzzle to accept additional Content-Types.
|
|
73
|
+
* Note: This relies on the implementation of a
|
|
74
|
+
* "protocol:http:beforeParsingPayload" pipe that implements
|
|
75
|
+
* the formatting of the additional content types to JSON.
|
|
76
|
+
* The default content types are:
|
|
77
|
+
* * application/json
|
|
78
|
+
* * application/x-www-form-urlencoded
|
|
79
|
+
* * multipart/form-data
|
|
80
|
+
* @default []
|
|
81
|
+
*/
|
|
82
|
+
additionalContentTypes: string[];
|
|
71
83
|
/**
|
|
72
84
|
* Enable support for compressed requests, using the Content-Encoding header
|
|
73
85
|
* Currently supported compression algorithms: gzip, deflate, identity
|
package/package.json
CHANGED
|
@@ -1,44 +1,44 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "kuzzle",
|
|
3
3
|
"author": "The Kuzzle Team <support@kuzzle.io>",
|
|
4
|
-
"version": "2.
|
|
4
|
+
"version": "2.25.0",
|
|
5
5
|
"description": "Kuzzle is an open-source solution that handles all the data management through a secured API, with a large choice of protocols.",
|
|
6
6
|
"bin": "bin/start-kuzzle-server",
|
|
7
7
|
"scripts": {
|
|
8
|
+
"build-ts": "tsc",
|
|
9
|
+
"build": "npm run build-ts",
|
|
10
|
+
"clean": "touch index.ts && npm run build | grep TSFILE | cut -d' ' -f 2 | xargs rm",
|
|
11
|
+
"codecov": "codecov",
|
|
12
|
+
"cucumber": "cucumber.js --fail-fast",
|
|
13
|
+
"dev:test": "npm run dev -- docker/scripts/start-kuzzle-test.ts --enable-plugins functional-test-plugin",
|
|
14
|
+
"dev": "npx ergol docker/scripts/start-kuzzle-dev.ts -c ./config/ergol.config.json",
|
|
15
|
+
"doc-error-codes": "node -r ts-node/register doc/build-error-codes",
|
|
16
|
+
"docker:install": "docker-compose run kuzzle_node_1 npm install",
|
|
17
|
+
"docker:npm": "docker-compose run kuzzle_node_1 npm run --",
|
|
18
|
+
"docker:test:unit": "docker-compose run kuzzle_node_1 npm run test:unit",
|
|
8
19
|
"docker": "docker-compose run kuzzle_node_1 ",
|
|
9
20
|
"file": "npx ergol docker/scripts/start-kuzzle-dev.ts -c ./config/ergol.config.json",
|
|
10
|
-
"start:dev": "npx ergol docker/scripts/start-kuzzle-dev.ts -c ./config/ergol.config.json --script-args=--enable-plugins functional-test-plugin",
|
|
11
21
|
"prepublishOnly": "npm run build",
|
|
12
|
-
"
|
|
13
|
-
"clean": "touch index.ts && npm run build | grep TSFILE | cut -d' ' -f 2 | xargs rm",
|
|
14
|
-
"build-ts": "tsc",
|
|
22
|
+
"prettier": "npx prettier ./lib ./test ./bin ./features ./plugins/available/functional-test-plugin --write",
|
|
15
23
|
"services": "npx kourou app:start-services",
|
|
16
|
-
"dev": "npx ergol docker/scripts/start-kuzzle-dev.ts -c ./config/ergol.config.json",
|
|
17
|
-
"dev:test": "npm run dev -- docker/scripts/start-kuzzle-dev.ts --enable-plugins functional-test-plugin",
|
|
18
|
-
"test": "npm run clean && npm run --silent test:lint && npm run build && npm run test:unit:coverage && npm run test:functional",
|
|
19
|
-
"test:jest": "jest",
|
|
20
|
-
"test:unit": "DEBUG= npx --node-arg=--trace-warnings mocha --exit",
|
|
21
|
-
"test:unit:coverage": "DEBUG= nyc --reporter=text-summary --reporter=lcov mocha --exit",
|
|
22
|
-
"test:functional": "npm run test:functional:http && npm run test:functional:websocket && npm run test:jest",
|
|
24
|
+
"start:dev": "npx ergol docker/scripts/start-kuzzle-dev.ts -c ./config/ergol.config.json --script-args=--enable-plugins functional-test-plugin",
|
|
23
25
|
"test:functional:http": "KUZZLE_PROTOCOL=http npx cucumber-js --profile http",
|
|
24
|
-
"test:functional:
|
|
25
|
-
"test:functional:legacy": "npm run test:functional:legacy:http && npm run test:functional:legacy:websocket && npm run test:functional:legacy:mqtt",
|
|
26
|
+
"test:functional:jest": "npm run test:jest",
|
|
26
27
|
"test:functional:legacy:http": "npx cucumber-js --format progress-bar --profile http ./features-legacy",
|
|
27
|
-
"test:functional:legacy:websocket": "npx cucumber-js --format progress-bar --profile websocket ./features-legacy",
|
|
28
28
|
"test:functional:legacy:mqtt": "npx cucumber-js --format progress-bar --profile mqtt ./features-legacy",
|
|
29
|
-
"test:functional:
|
|
30
|
-
"
|
|
31
|
-
"
|
|
32
|
-
"
|
|
33
|
-
"test:
|
|
34
|
-
"test:lint:ts": "eslint --max-warnings=0 ./lib --ext .ts --config .eslintc-ts.json",
|
|
35
|
-
"test:lint:ts:fix": "eslint --max-warnings=0 --fix ./lib --ext .ts --config .eslintc-ts.json",
|
|
36
|
-
"test:lint:js": "eslint --max-warnings=0 ./lib ./test ./bin ./features ./plugins/available/functional-test-plugin",
|
|
29
|
+
"test:functional:legacy:websocket": "npx cucumber-js --format progress-bar --profile websocket ./features-legacy",
|
|
30
|
+
"test:functional:legacy": "npm run test:functional:legacy:http && npm run test:functional:legacy:websocket && npm run test:functional:legacy:mqtt",
|
|
31
|
+
"test:functional:websocket": "KUZZLE_PROTOCOL=websocket npx cucumber-js --profile websocket",
|
|
32
|
+
"test:functional": "npm run test:functional:http && npm run test:functional:websocket && npm run test:jest",
|
|
33
|
+
"test:jest": "jest",
|
|
37
34
|
"test:lint:js:fix": "eslint --max-warnings=0 --fix ./lib ./test ./bin ./features",
|
|
38
|
-
"
|
|
39
|
-
"
|
|
40
|
-
"
|
|
41
|
-
"
|
|
35
|
+
"test:lint:js": "eslint --max-warnings=0 ./lib ./test ./bin ./features ./plugins/available/functional-test-plugin",
|
|
36
|
+
"test:lint:ts:fix": "eslint --max-warnings=0 --fix ./lib --ext .ts --config .eslintc-ts.json",
|
|
37
|
+
"test:lint:ts": "eslint --max-warnings=0 ./lib --ext .ts --config .eslintc-ts.json",
|
|
38
|
+
"test:lint": "npm run test:lint:js && npm run test:lint:ts",
|
|
39
|
+
"test:unit:coverage": "DEBUG= nyc --reporter=text-summary --reporter=lcov mocha --exit",
|
|
40
|
+
"test:unit": "DEBUG= npx --node-arg=--trace-warnings mocha --exit",
|
|
41
|
+
"test": "npm run clean && npm run --silent test:lint && npm run build && npm run test:unit:coverage && npm run test:functional"
|
|
42
42
|
},
|
|
43
43
|
"directories": {
|
|
44
44
|
"lib": "lib"
|
|
@@ -79,7 +79,7 @@
|
|
|
79
79
|
"semver": "^7.3.8",
|
|
80
80
|
"sorted-array": "^2.0.4",
|
|
81
81
|
"uuid": "^9.0.0",
|
|
82
|
-
"uWebSockets.js": "https://github.com/uNetworking/uWebSockets.js/archive/refs/tags/v20.
|
|
82
|
+
"uWebSockets.js": "https://github.com/uNetworking/uWebSockets.js/archive/refs/tags/v20.7.0.tar.gz",
|
|
83
83
|
"validator": "^13.9.0",
|
|
84
84
|
"winston": "^3.8.2",
|
|
85
85
|
"winston-elasticsearch": "0.17.1",
|