@shko.online/dataverse-odata 0.1.4 → 0.1.6
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/.editorconfig +8 -0
- package/.github/workflows/publish.yml +44 -0
- package/.prettierrc.json +7 -7
- package/.releaserc.yaml +23 -23
- package/CHANGELOG.md +14 -0
- package/LICENSE +21 -0
- package/azure-pipelines.yml +32 -0
- package/lib/cjs/getAliasedProperty.js +36 -0
- package/lib/cjs/getExpandFromParser.js +1 -1
- package/lib/cjs/getFilterFromParser.js +31 -0
- package/lib/cjs/getOrderByFromParser.js +41 -10
- package/lib/cjs/index.js +1 -2
- package/lib/cjs/parseOData.js +2 -1
- package/lib/cjs/validators/atMostOnce.js +6 -6
- package/lib/cjs/validators/differentFromEmptyString.js +5 -5
- package/lib/cjs/validators/hasContent.js +6 -6
- package/lib/cjs/validators/isGuid.js +5 -5
- package/lib/cjs/validators/recognizedGuid.js +5 -5
- package/lib/esm/getAliasedProperty.js +29 -0
- package/lib/esm/getExpandFromParser.js +1 -1
- package/lib/esm/getFilterFromParser.js +24 -0
- package/lib/esm/getOrderByFromParser.js +41 -10
- package/lib/esm/parseOData.js +2 -1
- package/lib/esm/validators/atMostOnce.js +6 -6
- package/lib/esm/validators/differentFromEmptyString.js +5 -5
- package/lib/esm/validators/hasContent.js +6 -6
- package/lib/esm/validators/isGuid.js +5 -5
- package/lib/esm/validators/recognizedGuid.js +5 -5
- package/lib/modern/getAliasedProperty.js +29 -0
- package/lib/modern/getExpandFromParser.js +1 -1
- package/lib/modern/getFilterFromParser.js +24 -0
- package/lib/modern/getOrderByFromParser.js +42 -11
- package/lib/modern/parseOData.js +2 -1
- package/lib/modern/validators/atMostOnce.js +6 -6
- package/lib/modern/validators/differentFromEmptyString.js +5 -5
- package/lib/modern/validators/hasContent.js +6 -6
- package/lib/modern/validators/isGuid.js +5 -5
- package/lib/modern/validators/recognizedGuid.js +5 -5
- package/lib/ts3.4/OData.types.d.ts +29 -6
- package/lib/ts3.4/getAliasedProperty.d.ts +10 -0
- package/lib/ts3.4/getFilterFromParser.d.ts +7 -0
- package/lib/ts3.4/getXQueryFromParser.d.ts +1 -1
- package/lib/ts3.4/validators/atMostOnce.d.ts +1 -1
- package/lib/ts3.9/OData.types.d.ts +141 -154
- package/lib/ts3.9/getAliasedProperty.d.ts +10 -0
- package/lib/ts3.9/getExpandFromParser.d.ts +7 -7
- package/lib/ts3.9/getFetchXmlFromParser.d.ts +7 -7
- package/lib/ts3.9/getFilterFromParser.d.ts +7 -0
- package/lib/ts3.9/getOrderByFromParser.d.ts +7 -7
- package/lib/ts3.9/getSelectFromParser.d.ts +7 -7
- package/lib/ts3.9/getTopFromParser.d.ts +7 -7
- package/lib/ts3.9/getXQueryFromParser.d.ts +8 -8
- package/lib/ts3.9/index.d.ts +11 -11
- package/lib/ts3.9/parseOData.d.ts +8 -8
- package/lib/ts3.9/validators/atMostOnce.d.ts +10 -10
- package/lib/ts3.9/validators/differentFromEmptyString.d.ts +9 -9
- package/lib/ts3.9/validators/hasContent.d.ts +10 -10
- package/lib/ts3.9/validators/isGuid.d.ts +9 -9
- package/lib/ts3.9/validators/recognizedGuid.d.ts +9 -9
- package/lib/ts4.2/OData.types.d.ts +183 -0
- package/lib/ts4.2/getAliasedProperty.d.ts +10 -0
- package/lib/ts4.2/getAliasedProperty.d.ts.map +1 -0
- package/lib/ts4.2/getExpandFromParser.d.ts +7 -0
- package/lib/{ts3.9 → ts4.2}/getExpandFromParser.d.ts.map +1 -1
- package/lib/ts4.2/getFetchXmlFromParser.d.ts +7 -0
- package/lib/{ts3.9 → ts4.2}/getFetchXmlFromParser.d.ts.map +1 -1
- package/lib/ts4.2/getFilterFromParser.d.ts +7 -0
- package/lib/ts4.2/getFilterFromParser.d.ts.map +1 -0
- package/lib/ts4.2/getOrderByFromParser.d.ts +7 -0
- package/lib/ts4.2/getOrderByFromParser.d.ts.map +1 -0
- package/lib/ts4.2/getSelectFromParser.d.ts +7 -0
- package/lib/{ts3.9 → ts4.2}/getSelectFromParser.d.ts.map +1 -1
- package/lib/ts4.2/getTopFromParser.d.ts +7 -0
- package/lib/{ts3.9 → ts4.2}/getTopFromParser.d.ts.map +1 -1
- package/lib/ts4.2/getXQueryFromParser.d.ts +8 -0
- package/lib/{ts3.9 → ts4.2}/getXQueryFromParser.d.ts.map +1 -1
- package/lib/ts4.2/index.d.ts +11 -0
- package/lib/ts4.2/parseOData.d.ts +8 -0
- package/lib/{ts3.9 → ts4.2}/parseOData.d.ts.map +1 -1
- package/lib/ts4.2/validators/atMostOnce.d.ts +10 -0
- package/lib/{ts3.9 → ts4.2}/validators/atMostOnce.d.ts.map +1 -1
- package/lib/ts4.2/validators/differentFromEmptyString.d.ts +9 -0
- package/lib/{ts3.9 → ts4.2}/validators/differentFromEmptyString.d.ts.map +1 -1
- package/lib/ts4.2/validators/hasContent.d.ts +10 -0
- package/lib/{ts3.9 → ts4.2}/validators/hasContent.d.ts.map +1 -1
- package/lib/ts4.2/validators/isGuid.d.ts +9 -0
- package/lib/{ts3.9 → ts4.2}/validators/isGuid.d.ts.map +1 -1
- package/lib/ts4.2/validators/recognizedGuid.d.ts +9 -0
- package/lib/{ts3.9 → ts4.2}/validators/recognizedGuid.d.ts.map +1 -1
- package/package.json +20 -11
- package/src/OData.types.d.ts +35 -6
- package/src/getAliasedProperty.ts +34 -0
- package/src/getExpandFromParser.ts +1 -1
- package/src/getFilterFromParser.ts +23 -0
- package/src/getOrderByFromParser.ts +46 -10
- package/src/parseOData.ts +3 -1
- package/src/validators/atMostOnce.ts +19 -19
- package/src/validators/differentFromEmptyString.ts +18 -18
- package/src/validators/hasContent.ts +19 -19
- package/src/validators/isGuid.ts +20 -20
- package/src/validators/recognizedGuid.ts +18 -18
- package/lib/ts3.9/getOrderByFromParser.d.ts.map +0 -1
- /package/lib/{ts3.9 → ts4.2}/index.d.ts.map +0 -0
|
@@ -1,9 +1,9 @@
|
|
|
1
|
+
import { getAliasedProperty } from './getAliasedProperty';
|
|
1
2
|
import type { ODataQuery, ODataOrderBy } from './OData.types';
|
|
2
3
|
import { atMostOnce } from './validators/atMostOnce';
|
|
3
4
|
import { hasContent } from './validators/hasContent';
|
|
4
5
|
|
|
5
6
|
const option = '$orderby';
|
|
6
|
-
const edmProperty = /\w{1-255}/gi;
|
|
7
7
|
|
|
8
8
|
/**
|
|
9
9
|
* Parses the {@link ODataOrderBy.$orderby $orderby} query
|
|
@@ -18,27 +18,63 @@ export const getOrderByFromParser = (parser: URLSearchParams, result: ODataQuery
|
|
|
18
18
|
return false;
|
|
19
19
|
}
|
|
20
20
|
let $orderby = value[0].trimEnd();
|
|
21
|
+
let $orderbyParts = $orderby.split(',');
|
|
21
22
|
const orderByArray: ODataOrderBy['$orderby'] = [];
|
|
22
|
-
|
|
23
|
-
|
|
23
|
+
let position = 0;
|
|
24
|
+
for (const element of $orderbyParts) {
|
|
25
|
+
const parts = Array.from(element.matchAll(/\s*(\S+)/gi));
|
|
26
|
+
|
|
27
|
+
if (parts.length > 2) {
|
|
28
|
+
position = position + parts[0][0].length + parts[1][0].length + parts[2][0].length;
|
|
24
29
|
result.error = {
|
|
25
|
-
code: '
|
|
26
|
-
message: `Syntax error at position ${
|
|
30
|
+
code: '0x80060888',
|
|
31
|
+
message: `Syntax error at position ${position} in '${$orderby}'.`,
|
|
27
32
|
};
|
|
28
33
|
|
|
29
34
|
return false;
|
|
30
35
|
}
|
|
31
|
-
}
|
|
32
36
|
|
|
33
|
-
|
|
34
|
-
|
|
37
|
+
if (!/^[@a-zA-Z]\w+/gi.test(parts[0][1])) {
|
|
38
|
+
position = position + parts[0][0].length;
|
|
35
39
|
result.error = {
|
|
36
40
|
code: '0x80060888',
|
|
37
|
-
message:
|
|
41
|
+
message: `Syntax error at position ${position} in '${$orderby}'.`,
|
|
38
42
|
};
|
|
39
43
|
return false;
|
|
40
44
|
}
|
|
41
|
-
|
|
45
|
+
|
|
46
|
+
const orderBy: ODataOrderBy['$orderby'][0] = {
|
|
47
|
+
column: parts[0][1],
|
|
48
|
+
asc: true, // default is ascending
|
|
49
|
+
};
|
|
50
|
+
|
|
51
|
+
if (parts[0][1].startsWith('@')) {
|
|
52
|
+
orderBy.column = getAliasedProperty(parser, result, parts[0][1]);
|
|
53
|
+
if (!orderBy.column) {
|
|
54
|
+
return false;
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
if (parts.length === 1) {
|
|
59
|
+
orderByArray.push(orderBy);
|
|
60
|
+
continue;
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
if (parts[1][1].toLowerCase() === 'asc') {
|
|
64
|
+
orderBy.asc = true;
|
|
65
|
+
orderByArray.push(orderBy);
|
|
66
|
+
} else if (parts[1][1].toLowerCase() === 'desc') {
|
|
67
|
+
orderBy.asc = false;
|
|
68
|
+
orderByArray.push(orderBy);
|
|
69
|
+
} else {
|
|
70
|
+
position = position + parts[0][0].length + parts[1][0].length;
|
|
71
|
+
result.error = {
|
|
72
|
+
code: '0x80060888',
|
|
73
|
+
message: `Syntax error at position ${position} in '${$orderby}'.`,
|
|
74
|
+
};
|
|
75
|
+
return false;
|
|
76
|
+
}
|
|
77
|
+
}
|
|
42
78
|
|
|
43
79
|
result.$orderby = orderByArray;
|
|
44
80
|
|
package/src/parseOData.ts
CHANGED
|
@@ -6,6 +6,7 @@ import { getExpandFromParser } from './getExpandFromParser';
|
|
|
6
6
|
import { getFetchXmlFromParser } from './getFetchXmlFromParser';
|
|
7
7
|
import { getXQueryFromParser } from './getXQueryFromParser';
|
|
8
8
|
import { getOrderByFromParser } from './getOrderByFromParser';
|
|
9
|
+
import { getFilterFromParser } from './getFilterFromParser';
|
|
9
10
|
|
|
10
11
|
/**
|
|
11
12
|
* parses the OData query and applies some Dataverse validations
|
|
@@ -17,9 +18,10 @@ export const parseOData = (query: string) => {
|
|
|
17
18
|
const result = {} as ODataQuery;
|
|
18
19
|
|
|
19
20
|
getExpandFromParser(parser, result) &&
|
|
21
|
+
getFetchXmlFromParser(parser, result) &&
|
|
22
|
+
getFilterFromParser(parser, result) &&
|
|
20
23
|
getSelectFromParser(parser, result) &&
|
|
21
24
|
getTopFromParser(parser, result) &&
|
|
22
|
-
getFetchXmlFromParser(parser, result) &&
|
|
23
25
|
getXQueryFromParser('savedQuery', parser, result) &&
|
|
24
26
|
getXQueryFromParser('userQuery', parser, result) &&
|
|
25
27
|
getOrderByFromParser(parser, result);
|
|
@@ -1,19 +1,19 @@
|
|
|
1
|
-
import type { ODataQuery } from '../OData.types';
|
|
2
|
-
|
|
3
|
-
/**
|
|
4
|
-
* Options of this type must be specified at most once.
|
|
5
|
-
* @param option The option being validated (ex. $top)
|
|
6
|
-
* @param value The result of {@link URLSearchParams.getAll getAll}
|
|
7
|
-
* @param result The {@link ODataQuery} to append the error to
|
|
8
|
-
* @returns {boolean} Returns `false` when the parse has an error
|
|
9
|
-
*/
|
|
10
|
-
export const atMostOnce = (option: string, value: string[], result: ODataQuery) => {
|
|
11
|
-
if (value.length > 1) {
|
|
12
|
-
result.error = {
|
|
13
|
-
code: '0x0',
|
|
14
|
-
message: `Query option '${option}' was specified more than once, but it must be specified at most once.`,
|
|
15
|
-
};
|
|
16
|
-
return false;
|
|
17
|
-
}
|
|
18
|
-
return true;
|
|
19
|
-
};
|
|
1
|
+
import type { ODataQuery } from '../OData.types';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Options of this type must be specified at most once.
|
|
5
|
+
* @param option The option being validated (ex. $top)
|
|
6
|
+
* @param value The result of {@link URLSearchParams.prototype.getAll URLSearchParams.getAll}
|
|
7
|
+
* @param result The {@link ODataQuery} to append the error to
|
|
8
|
+
* @returns {boolean} Returns `false` when the parse has an error
|
|
9
|
+
*/
|
|
10
|
+
export const atMostOnce = (option: string, value: string[], result: ODataQuery) => {
|
|
11
|
+
if (value.length > 1) {
|
|
12
|
+
result.error = {
|
|
13
|
+
code: '0x0',
|
|
14
|
+
message: `Query option '${option}' was specified more than once, but it must be specified at most once.`,
|
|
15
|
+
};
|
|
16
|
+
return false;
|
|
17
|
+
}
|
|
18
|
+
return true;
|
|
19
|
+
};
|
|
@@ -1,18 +1,18 @@
|
|
|
1
|
-
import type { ODataQuery } from '../OData.types';
|
|
2
|
-
|
|
3
|
-
/**
|
|
4
|
-
*
|
|
5
|
-
* @param value The result of {@link URLSearchParams.getAll getAll}
|
|
6
|
-
* @param result The {@link ODataQuery} to append the error to
|
|
7
|
-
* @returns {boolean} Returns `false` when the parse has an error
|
|
8
|
-
*/
|
|
9
|
-
export const differentFromEmptyString = (value: string[], result: ODataQuery) => {
|
|
10
|
-
if (value[0] === '') {
|
|
11
|
-
result.error = {
|
|
12
|
-
code: '0x80040203',
|
|
13
|
-
message: 'Expected non-empty string.',
|
|
14
|
-
};
|
|
15
|
-
return false;
|
|
16
|
-
}
|
|
17
|
-
return true;
|
|
18
|
-
};
|
|
1
|
+
import type { ODataQuery } from '../OData.types';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
*
|
|
5
|
+
* @param value The result of {@link URLSearchParams.getAll getAll}
|
|
6
|
+
* @param result The {@link ODataQuery} to append the error to
|
|
7
|
+
* @returns {boolean} Returns `false` when the parse has an error
|
|
8
|
+
*/
|
|
9
|
+
export const differentFromEmptyString = (value: string[], result: ODataQuery) => {
|
|
10
|
+
if (value[0] === '') {
|
|
11
|
+
result.error = {
|
|
12
|
+
code: '0x80040203',
|
|
13
|
+
message: 'Expected non-empty string.',
|
|
14
|
+
};
|
|
15
|
+
return false;
|
|
16
|
+
}
|
|
17
|
+
return true;
|
|
18
|
+
};
|
|
@@ -1,19 +1,19 @@
|
|
|
1
|
-
import type { ODataQuery } from '../OData.types';
|
|
2
|
-
|
|
3
|
-
/**
|
|
4
|
-
* Options of this type must be specified at most once.
|
|
5
|
-
* @param option The option being validated (ex. $top)
|
|
6
|
-
* @param value The result of {@link URLSearchParams.getAll getAll}
|
|
7
|
-
* @param result The {@link ODataQuery} to append the error to
|
|
8
|
-
* @returns {boolean} Returns `false` when the parse has an error
|
|
9
|
-
*/
|
|
10
|
-
export const hasContent = (query: string, value: string[], result: ODataQuery) => {
|
|
11
|
-
if (!value[0].trim()) {
|
|
12
|
-
result.error = {
|
|
13
|
-
code: '0x0',
|
|
14
|
-
message: `The value for OData query '${query}' cannot be empty.`,
|
|
15
|
-
};
|
|
16
|
-
return false;
|
|
17
|
-
}
|
|
18
|
-
return true;
|
|
19
|
-
};
|
|
1
|
+
import type { ODataQuery } from '../OData.types';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Options of this type must be specified at most once.
|
|
5
|
+
* @param option The option being validated (ex. $top)
|
|
6
|
+
* @param value The result of {@link URLSearchParams.getAll getAll}
|
|
7
|
+
* @param result The {@link ODataQuery} to append the error to
|
|
8
|
+
* @returns {boolean} Returns `false` when the parse has an error
|
|
9
|
+
*/
|
|
10
|
+
export const hasContent = (query: string, value: string[], result: ODataQuery) => {
|
|
11
|
+
if (!value[0].trim()) {
|
|
12
|
+
result.error = {
|
|
13
|
+
code: '0x0',
|
|
14
|
+
message: `The value for OData query '${query}' cannot be empty.`,
|
|
15
|
+
};
|
|
16
|
+
return false;
|
|
17
|
+
}
|
|
18
|
+
return true;
|
|
19
|
+
};
|
package/src/validators/isGuid.ts
CHANGED
|
@@ -1,20 +1,20 @@
|
|
|
1
|
-
import type { ODataQuery } from '../OData.types';
|
|
2
|
-
|
|
3
|
-
const guidRegex = /[0-9A-F]{8}\-[0-9A-F]{4}-[0-9A-F]{4}-[0-9A-F]{4}-[0-9A-F]{12}/gi;
|
|
4
|
-
|
|
5
|
-
/**
|
|
6
|
-
*
|
|
7
|
-
* @param value The result of {@link URLSearchParams.getAll getAll}
|
|
8
|
-
* @param result The {@link ODataQuery} to append the error to
|
|
9
|
-
* @returns {boolean} Returns `false` when the parse has an error
|
|
10
|
-
*/
|
|
11
|
-
export const isGuid = (value: string[], result: ODataQuery) => {
|
|
12
|
-
if (!value[0].match(guidRegex)) {
|
|
13
|
-
result.error = {
|
|
14
|
-
code: '0x0',
|
|
15
|
-
message: 'Guid should contain 32 digits with 4 dashes (xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx).',
|
|
16
|
-
};
|
|
17
|
-
return false;
|
|
18
|
-
}
|
|
19
|
-
return true;
|
|
20
|
-
};
|
|
1
|
+
import type { ODataQuery } from '../OData.types';
|
|
2
|
+
|
|
3
|
+
const guidRegex = /[0-9A-F]{8}\-[0-9A-F]{4}-[0-9A-F]{4}-[0-9A-F]{4}-[0-9A-F]{12}/gi;
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
*
|
|
7
|
+
* @param value The result of {@link URLSearchParams.getAll getAll}
|
|
8
|
+
* @param result The {@link ODataQuery} to append the error to
|
|
9
|
+
* @returns {boolean} Returns `false` when the parse has an error
|
|
10
|
+
*/
|
|
11
|
+
export const isGuid = (value: string[], result: ODataQuery) => {
|
|
12
|
+
if (!value[0].match(guidRegex)) {
|
|
13
|
+
result.error = {
|
|
14
|
+
code: '0x0',
|
|
15
|
+
message: 'Guid should contain 32 digits with 4 dashes (xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx).',
|
|
16
|
+
};
|
|
17
|
+
return false;
|
|
18
|
+
}
|
|
19
|
+
return true;
|
|
20
|
+
};
|
|
@@ -1,18 +1,18 @@
|
|
|
1
|
-
import type { ODataQuery } from '../OData.types';
|
|
2
|
-
|
|
3
|
-
/**
|
|
4
|
-
*
|
|
5
|
-
* @param value The result of {@link URLSearchParams.getAll getAll}
|
|
6
|
-
* @param result The {@link ODataQuery} to append the error to
|
|
7
|
-
* @returns {boolean} Returns `false` when the parse has an error
|
|
8
|
-
*/
|
|
9
|
-
export const recognizedGuid = (value: string[], result: ODataQuery) => {
|
|
10
|
-
if (!value[0].trim()) {
|
|
11
|
-
result.error = {
|
|
12
|
-
code: '0x0',
|
|
13
|
-
message: 'Unrecognized Guid format.',
|
|
14
|
-
};
|
|
15
|
-
return false;
|
|
16
|
-
}
|
|
17
|
-
return true;
|
|
18
|
-
};
|
|
1
|
+
import type { ODataQuery } from '../OData.types';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
*
|
|
5
|
+
* @param value The result of {@link URLSearchParams.getAll getAll}
|
|
6
|
+
* @param result The {@link ODataQuery} to append the error to
|
|
7
|
+
* @returns {boolean} Returns `false` when the parse has an error
|
|
8
|
+
*/
|
|
9
|
+
export const recognizedGuid = (value: string[], result: ODataQuery) => {
|
|
10
|
+
if (!value[0].trim()) {
|
|
11
|
+
result.error = {
|
|
12
|
+
code: '0x0',
|
|
13
|
+
message: 'Unrecognized Guid format.',
|
|
14
|
+
};
|
|
15
|
+
return false;
|
|
16
|
+
}
|
|
17
|
+
return true;
|
|
18
|
+
};
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"getOrderByFromParser.d.ts","sourceRoot":"","sources":["../../src/getOrderByFromParser.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAgB,MAAM,eAAe,CAAC;AAO9D;;;GAGG;AACH,eAAO,MAAM,oBAAoB,WAAY,eAAe,UAAU,UAAU,KAAG,OAkClF,CAAC"}
|
|
File without changes
|