@shko.online/dataverse-odata 0.1.0 → 0.1.1
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/.babelrc.js +160 -160
- package/.releaserc.yaml +23 -0
- package/CHANGELOG.md +6 -0
- package/README.md +3 -0
- package/jest.config.ts +12 -12
- package/lib/cjs/getExpandFromParser.js +3 -3
- package/lib/cjs/getFetchXmlFromParser.js +3 -3
- package/lib/cjs/getSelectFromParser.js +3 -3
- package/lib/cjs/getTopFromParser.js +3 -3
- package/lib/cjs/parseOData.js +5 -0
- package/lib/esm/getExpandFromParser.js +3 -3
- package/lib/esm/getFetchXmlFromParser.js +3 -3
- package/lib/esm/getSelectFromParser.js +3 -3
- package/lib/esm/getTopFromParser.js +3 -3
- package/lib/esm/parseOData.js +6 -0
- package/lib/getExpandFromParser.d.ts +6 -6
- package/lib/getExpandFromParser.js +96 -96
- package/lib/getFetchXmlFromParser.d.ts +6 -6
- package/lib/getFetchXmlFromParser.js +40 -40
- package/lib/getSelectFromParser.d.ts +6 -6
- package/lib/getSelectFromParser.js +11 -11
- package/lib/getTopFromParser.d.ts +6 -6
- package/lib/getTopFromParser.js +26 -26
- package/lib/index.d.ts +4 -4
- package/lib/index.js +3 -3
- package/lib/modern/getExpandFromParser.js +3 -3
- package/lib/modern/getFetchXmlFromParser.js +3 -3
- package/lib/modern/getSelectFromParser.js +3 -3
- package/lib/modern/getTopFromParser.js +3 -3
- package/lib/modern/parseOData.js +6 -0
- package/lib/parseOData.d.ts +2 -2
- package/lib/parseOData.js +21 -21
- package/lib/ts3.4/getFetchXmlFromParser.d.ts +1 -1
- package/lib/ts3.4/parseOData.d.ts +5 -0
- package/lib/ts3.9/getExpandFromParser.d.ts +6 -6
- package/lib/ts3.9/getExpandFromParser.d.ts.map +1 -1
- package/lib/ts3.9/getFetchXmlFromParser.d.ts +6 -6
- package/lib/ts3.9/getSelectFromParser.d.ts +6 -6
- package/lib/ts3.9/getTopFromParser.d.ts +6 -6
- package/lib/ts3.9/index.d.ts +4 -4
- package/lib/ts3.9/index.d.ts.map +1 -1
- package/lib/ts3.9/parseOData.d.ts +7 -2
- package/lib/ts3.9/parseOData.d.ts.map +1 -1
- package/package.json +13 -8
- package/src/OData.types.d.ts +61 -61
- package/src/getExpandFromParser.ts +106 -105
- package/src/getFetchXmlFromParser.ts +48 -48
- package/src/getSelectFromParser.ts +13 -13
- package/src/getTopFromParser.ts +27 -27
- package/src/index.ts +17 -16
- package/src/parseOData.ts +29 -23
- package/tests/OData-Parser.$expand.test.ts +39 -39
- package/tests/OData-Parser.$top.test.ts +36 -36
- package/tests/OData-Parser.fetchXml.test.ts +62 -62
- package/tests/OData-Parser.test.ts +17 -17
- package/tsconfig.build.json +8 -8
- package/tsconfig.json +35 -35
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"parseOData.d.ts","sourceRoot":"","sources":["../../src/parseOData.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,eAAe,CAAC;
|
|
1
|
+
{"version":3,"file":"parseOData.d.ts","sourceRoot":"","sources":["../../src/parseOData.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,eAAe,CAAC;AAOhD;;;;GAIG;AACH,eAAO,MAAM,UAAU,UAAW,MAAM,eAgBvC,CAAC"}
|
package/package.json
CHANGED
|
@@ -1,12 +1,13 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@shko.online/dataverse-odata",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.1",
|
|
4
4
|
"description": "This package will help parse OData strings (only the Microsoft Dataverse subset). It can be used as a validator, or you can build some javascript library which consumes the output of this library.",
|
|
5
5
|
"scripts": {
|
|
6
6
|
"build": "npm run lint && node ../scripts/build.js",
|
|
7
7
|
"lint": "eslint",
|
|
8
8
|
"tsc": "tsc --project tsconfig.build.json",
|
|
9
|
-
"test": "jest --coverage --maxWorkers=4"
|
|
9
|
+
"test": "jest --coverage --maxWorkers=4",
|
|
10
|
+
"semantic-release": "semantic-release"
|
|
10
11
|
},
|
|
11
12
|
"exports": {
|
|
12
13
|
".": {
|
|
@@ -25,10 +26,7 @@
|
|
|
25
26
|
]
|
|
26
27
|
}
|
|
27
28
|
},
|
|
28
|
-
"repository":
|
|
29
|
-
"type": "git",
|
|
30
|
-
"url": "git+https://github.com/shko.online/dataverse-odata.git"
|
|
31
|
-
},
|
|
29
|
+
"repository": "https://github.com/shko-online/dataverse-odata",
|
|
32
30
|
"keywords": [
|
|
33
31
|
"odata",
|
|
34
32
|
"dataverse",
|
|
@@ -37,9 +35,9 @@
|
|
|
37
35
|
"author": "Shko Online <sales@shko.online> (https://shko.online);Betim Beja",
|
|
38
36
|
"license": "MIT",
|
|
39
37
|
"bugs": {
|
|
40
|
-
"url": "https://github.com/shko
|
|
38
|
+
"url": "https://github.com/shko-online/dataverse-odata/issues"
|
|
41
39
|
},
|
|
42
|
-
"homepage": "https://github.com/shko
|
|
40
|
+
"homepage": "https://github.com/shko-online/dataverse-odata#readme",
|
|
43
41
|
"devDependencies": {
|
|
44
42
|
"@babel/cli": "^7.20.7",
|
|
45
43
|
"@babel/core": "^7.20.12",
|
|
@@ -57,6 +55,12 @@
|
|
|
57
55
|
"@babel/preset-typescript": "^7.18.6",
|
|
58
56
|
"@emotion/babel-plugin": "^11.10.5",
|
|
59
57
|
"@jest/globals": "^29.4.2",
|
|
58
|
+
"@semantic-release/changelog": "^6.0.2",
|
|
59
|
+
"@semantic-release/commit-analyzer": "^9.0.2",
|
|
60
|
+
"@semantic-release/exec": "^6.0.3",
|
|
61
|
+
"@semantic-release/git": "^10.0.1",
|
|
62
|
+
"@semantic-release/npm": "^9.0.2",
|
|
63
|
+
"@semantic-release/release-notes-generator": "^10.0.3",
|
|
60
64
|
"@storybook/babel-plugin-require-context-hook": "^1.0.1",
|
|
61
65
|
"@typescript-eslint/eslint-plugin": "^5.40.1",
|
|
62
66
|
"@typescript-eslint/parser": "^5.40.1",
|
|
@@ -66,6 +70,7 @@
|
|
|
66
70
|
"eslint": "^8.25.0",
|
|
67
71
|
"jest": "^29.2.1",
|
|
68
72
|
"jest-environment-jsdom": "^29.2.1",
|
|
73
|
+
"semantic-release": "^20.1.0",
|
|
69
74
|
"ts-jest": "^29.0.3",
|
|
70
75
|
"ts-node": "^10.9.1",
|
|
71
76
|
"typescript": "^4.8.4"
|
package/src/OData.types.d.ts
CHANGED
|
@@ -1,61 +1,61 @@
|
|
|
1
|
-
export interface ODataError {
|
|
2
|
-
error?: {
|
|
3
|
-
code: string;
|
|
4
|
-
message: string;
|
|
5
|
-
};
|
|
6
|
-
}
|
|
7
|
-
|
|
8
|
-
export interface ODataExpand {
|
|
9
|
-
$expand?: {
|
|
10
|
-
[relationship: string]: ODataExpandQuery;
|
|
11
|
-
};
|
|
12
|
-
}
|
|
13
|
-
|
|
14
|
-
export type ODataExpandQuery = ODataSelect & ODataExpand;
|
|
15
|
-
|
|
16
|
-
export interface ODataFilter {
|
|
17
|
-
$filter?: StandardOperator;
|
|
18
|
-
}
|
|
19
|
-
|
|
20
|
-
export interface ODataFetch {
|
|
21
|
-
fetchXml?: XMLDocument;
|
|
22
|
-
}
|
|
23
|
-
|
|
24
|
-
export interface ODataSelect {
|
|
25
|
-
/**
|
|
26
|
-
* Attributes to select.
|
|
27
|
-
* Empty array equals to all Attributes.
|
|
28
|
-
*/
|
|
29
|
-
$select?: string[];
|
|
30
|
-
}
|
|
31
|
-
|
|
32
|
-
export interface ODataTop {
|
|
33
|
-
$top?: number;
|
|
34
|
-
}
|
|
35
|
-
|
|
36
|
-
export type StandardOperators = 'eq' | 'ne' | 'gt' | 'ge' | 'lt' | 'le';
|
|
37
|
-
|
|
38
|
-
export interface StandardOperator {
|
|
39
|
-
operator: StandardOperators;
|
|
40
|
-
/**
|
|
41
|
-
* The left side of the 'X' operator must be a property of the entity.
|
|
42
|
-
*/
|
|
43
|
-
left: string;
|
|
44
|
-
/**
|
|
45
|
-
* The right side of the 'X' operator must be a constant value.
|
|
46
|
-
*/
|
|
47
|
-
right: string | number;
|
|
48
|
-
}
|
|
49
|
-
|
|
50
|
-
export interface UnaryOperator {
|
|
51
|
-
operator: 'not';
|
|
52
|
-
right: StandardOperator;
|
|
53
|
-
}
|
|
54
|
-
|
|
55
|
-
export interface BinaryOperator {
|
|
56
|
-
operator: 'and' | 'or';
|
|
57
|
-
left: StandardOperator;
|
|
58
|
-
right: StandardOperator;
|
|
59
|
-
}
|
|
60
|
-
|
|
61
|
-
export type ODataQuery = ODataError & ODataExpand & ODataFilter & ODataSelect & ODataTop & ODataFetch;
|
|
1
|
+
export interface ODataError {
|
|
2
|
+
error?: {
|
|
3
|
+
code: string;
|
|
4
|
+
message: string;
|
|
5
|
+
};
|
|
6
|
+
}
|
|
7
|
+
|
|
8
|
+
export interface ODataExpand {
|
|
9
|
+
$expand?: {
|
|
10
|
+
[relationship: string]: ODataExpandQuery;
|
|
11
|
+
};
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
export type ODataExpandQuery = ODataSelect & ODataExpand;
|
|
15
|
+
|
|
16
|
+
export interface ODataFilter {
|
|
17
|
+
$filter?: StandardOperator;
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
export interface ODataFetch {
|
|
21
|
+
fetchXml?: XMLDocument;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
export interface ODataSelect {
|
|
25
|
+
/**
|
|
26
|
+
* Attributes to select.
|
|
27
|
+
* Empty array equals to all Attributes.
|
|
28
|
+
*/
|
|
29
|
+
$select?: string[];
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
export interface ODataTop {
|
|
33
|
+
$top?: number;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
export type StandardOperators = 'eq' | 'ne' | 'gt' | 'ge' | 'lt' | 'le';
|
|
37
|
+
|
|
38
|
+
export interface StandardOperator {
|
|
39
|
+
operator: StandardOperators;
|
|
40
|
+
/**
|
|
41
|
+
* The left side of the 'X' operator must be a property of the entity.
|
|
42
|
+
*/
|
|
43
|
+
left: string;
|
|
44
|
+
/**
|
|
45
|
+
* The right side of the 'X' operator must be a constant value.
|
|
46
|
+
*/
|
|
47
|
+
right: string | number;
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
export interface UnaryOperator {
|
|
51
|
+
operator: 'not';
|
|
52
|
+
right: StandardOperator;
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
export interface BinaryOperator {
|
|
56
|
+
operator: 'and' | 'or';
|
|
57
|
+
left: StandardOperator;
|
|
58
|
+
right: StandardOperator;
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
export type ODataQuery = ODataError & ODataExpand & ODataFilter & ODataSelect & ODataTop & ODataFetch;
|
|
@@ -1,105 +1,106 @@
|
|
|
1
|
-
import type { ODataError, ODataExpand, ODataExpandQuery, ODataQuery } from './OData.types';
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
*
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
(match[0].length
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
let
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
const
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
let
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
};
|
|
1
|
+
import type { ODataError, ODataExpand, ODataExpandQuery, ODataQuery } from './OData.types';
|
|
2
|
+
|
|
3
|
+
import { getSelectFromParser } from './getSelectFromParser';
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* Parses the $expand query
|
|
7
|
+
* @returns Returns true when the parse has an error
|
|
8
|
+
*/
|
|
9
|
+
export const getExpandFromParser = (parser: URLSearchParams, result: ODataQuery): boolean => {
|
|
10
|
+
const $expand = parser.get('$expand');
|
|
11
|
+
if ($expand !== null) {
|
|
12
|
+
result.$expand = {};
|
|
13
|
+
|
|
14
|
+
if (extractExpand($expand, result)) {
|
|
15
|
+
return true;
|
|
16
|
+
}
|
|
17
|
+
}
|
|
18
|
+
return false;
|
|
19
|
+
};
|
|
20
|
+
|
|
21
|
+
const extractExpand = (value: string, $expand: ODataExpand & ODataError) => {
|
|
22
|
+
const match = value.match(/^\s*(\w(\w|\d|_)*)\s*(,|\()?\s*/);
|
|
23
|
+
if (
|
|
24
|
+
match === null ||
|
|
25
|
+
(match[0].length < value.length && match[3] === null) ||
|
|
26
|
+
(match[0].length === value.length && match[3] !== undefined)
|
|
27
|
+
) {
|
|
28
|
+
$expand.error = {
|
|
29
|
+
code: '0x0',
|
|
30
|
+
message: 'invalid expand expression',
|
|
31
|
+
};
|
|
32
|
+
return true;
|
|
33
|
+
}
|
|
34
|
+
let matchSeparator = match[3];
|
|
35
|
+
let matchLength = match[0].length;
|
|
36
|
+
if (matchSeparator !== '(') {
|
|
37
|
+
if ($expand.$expand !== undefined) {
|
|
38
|
+
$expand.$expand[match[1]] = { $select: [] };
|
|
39
|
+
}
|
|
40
|
+
} else {
|
|
41
|
+
const { index, error } = getClosingBracket(value.substring(matchLength));
|
|
42
|
+
if (error) {
|
|
43
|
+
$expand.error = {
|
|
44
|
+
code: '0x0',
|
|
45
|
+
message: error,
|
|
46
|
+
};
|
|
47
|
+
return true;
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
if ($expand.$expand !== undefined) {
|
|
51
|
+
const innerExpand = {} as ODataExpandQuery & ODataError;
|
|
52
|
+
const parser = new URLSearchParams('?' + value.substring(matchLength, matchLength + index));
|
|
53
|
+
if (getSelectFromParser(parser, innerExpand)) {
|
|
54
|
+
$expand.error = innerExpand.error;
|
|
55
|
+
return true;
|
|
56
|
+
}
|
|
57
|
+
if (getExpandFromParser(parser, innerExpand)) {
|
|
58
|
+
$expand.error = innerExpand.error;
|
|
59
|
+
return true;
|
|
60
|
+
}
|
|
61
|
+
if (innerExpand.$expand === undefined && innerExpand.$select === undefined) {
|
|
62
|
+
$expand.error = { code: '0x0', message: 'Empty expand' };
|
|
63
|
+
return true;
|
|
64
|
+
}
|
|
65
|
+
$expand.$expand[match[1]] = innerExpand;
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
matchLength = matchLength + index;
|
|
69
|
+
const secondMatch = value.substring(matchLength + 1).match(/\s*(,?)\s*d/);
|
|
70
|
+
if (secondMatch !== null) {
|
|
71
|
+
matchLength = matchLength + secondMatch[0].length;
|
|
72
|
+
if (secondMatch[1] !== null) {
|
|
73
|
+
matchSeparator = ',';
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
if (matchSeparator === ',') {
|
|
79
|
+
if (extractExpand(value.substring(matchLength), $expand)) {
|
|
80
|
+
return true;
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
return false;
|
|
85
|
+
};
|
|
86
|
+
|
|
87
|
+
const getClosingBracket = (value: string): { index: number; error?: string } => {
|
|
88
|
+
let depth = 1;
|
|
89
|
+
let startAt = 0;
|
|
90
|
+
while (depth > 0) {
|
|
91
|
+
const match = value.substring(startAt).match(/\(|\)/);
|
|
92
|
+
if (match === null) {
|
|
93
|
+
return { error: 'no closing bracket found', index: -1 };
|
|
94
|
+
}
|
|
95
|
+
if (match[0] === ')') {
|
|
96
|
+
depth -= 1;
|
|
97
|
+
if (depth === 0) {
|
|
98
|
+
return { index: match.index || 0 };
|
|
99
|
+
}
|
|
100
|
+
} else {
|
|
101
|
+
depth += 1;
|
|
102
|
+
}
|
|
103
|
+
startAt = (match.index || 0) + 1;
|
|
104
|
+
}
|
|
105
|
+
return { error: 'no closing bracket found', index: -1 };
|
|
106
|
+
};
|
|
@@ -1,48 +1,48 @@
|
|
|
1
|
-
import type { ODataQuery } from './OData.types';
|
|
2
|
-
|
|
3
|
-
/**
|
|
4
|
-
* Parses the
|
|
5
|
-
* @returns Returns true when the parse has an error
|
|
6
|
-
*/
|
|
7
|
-
export const getFetchXmlFromParser = (parser: URLSearchParams, result: ODataQuery): boolean => {
|
|
8
|
-
const fetchXml = parser.get('fetchXml');
|
|
9
|
-
if (fetchXml !== null) {
|
|
10
|
-
const serializer = new DOMParser();
|
|
11
|
-
const fetchXmlDocument = serializer.parseFromString(fetchXml, 'text/xml');
|
|
12
|
-
if (fetchXmlDocument.documentElement.tagName === 'parsererror') {
|
|
13
|
-
result.error = {
|
|
14
|
-
code: '0x80040201',
|
|
15
|
-
message: 'Invalid XML.',
|
|
16
|
-
};
|
|
17
|
-
return true;
|
|
18
|
-
}
|
|
19
|
-
const entity = fetchXmlDocument
|
|
20
|
-
.evaluate('fetch/entity', fetchXmlDocument, null, XPathResult.ANY_TYPE, null)
|
|
21
|
-
.iterateNext() as Element;
|
|
22
|
-
if (fetchXmlDocument.documentElement.children.length != 1 || !entity || !entity.getAttribute('name')) {
|
|
23
|
-
result.error = {
|
|
24
|
-
code: '0x80041102',
|
|
25
|
-
message: 'Entity Name was not specified in FetchXml String.',
|
|
26
|
-
};
|
|
27
|
-
return true;
|
|
28
|
-
}
|
|
29
|
-
const invalidAttribute = fetchXmlDocument
|
|
30
|
-
.evaluate(
|
|
31
|
-
'fetch/entity/*[not(self::filter or self::order or self::link-entity or self::attribute or self::all-attributes or self::no-attrs)]',
|
|
32
|
-
fetchXmlDocument,
|
|
33
|
-
null,
|
|
34
|
-
XPathResult.ANY_TYPE,
|
|
35
|
-
null,
|
|
36
|
-
)
|
|
37
|
-
.iterateNext() as Element;
|
|
38
|
-
if (invalidAttribute) {
|
|
39
|
-
result.error = {
|
|
40
|
-
code: '0x8004111c',
|
|
41
|
-
message: `Invalid Child Node, valid nodes are filter, order, link-entity, attribute, all-attributes, no-attrs. NodeName = ${invalidAttribute.tagName} NodeXml = ${invalidAttribute.outerHTML}`,
|
|
42
|
-
};
|
|
43
|
-
return true;
|
|
44
|
-
}
|
|
45
|
-
result.fetchXml = fetchXmlDocument;
|
|
46
|
-
}
|
|
47
|
-
return false;
|
|
48
|
-
};
|
|
1
|
+
import type { ODataQuery } from './OData.types';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Parses the fetchXml query
|
|
5
|
+
* @returns Returns true when the parse has an error
|
|
6
|
+
*/
|
|
7
|
+
export const getFetchXmlFromParser = (parser: URLSearchParams, result: ODataQuery): boolean => {
|
|
8
|
+
const fetchXml = parser.get('fetchXml');
|
|
9
|
+
if (fetchXml !== null) {
|
|
10
|
+
const serializer = new DOMParser();
|
|
11
|
+
const fetchXmlDocument = serializer.parseFromString(fetchXml, 'text/xml');
|
|
12
|
+
if (fetchXmlDocument.documentElement.tagName === 'parsererror') {
|
|
13
|
+
result.error = {
|
|
14
|
+
code: '0x80040201',
|
|
15
|
+
message: 'Invalid XML.',
|
|
16
|
+
};
|
|
17
|
+
return true;
|
|
18
|
+
}
|
|
19
|
+
const entity = fetchXmlDocument
|
|
20
|
+
.evaluate('fetch/entity', fetchXmlDocument, null, XPathResult.ANY_TYPE, null)
|
|
21
|
+
.iterateNext() as Element;
|
|
22
|
+
if (fetchXmlDocument.documentElement.children.length != 1 || !entity || !entity.getAttribute('name')) {
|
|
23
|
+
result.error = {
|
|
24
|
+
code: '0x80041102',
|
|
25
|
+
message: 'Entity Name was not specified in FetchXml String.',
|
|
26
|
+
};
|
|
27
|
+
return true;
|
|
28
|
+
}
|
|
29
|
+
const invalidAttribute = fetchXmlDocument
|
|
30
|
+
.evaluate(
|
|
31
|
+
'fetch/entity/*[not(self::filter or self::order or self::link-entity or self::attribute or self::all-attributes or self::no-attrs)]',
|
|
32
|
+
fetchXmlDocument,
|
|
33
|
+
null,
|
|
34
|
+
XPathResult.ANY_TYPE,
|
|
35
|
+
null,
|
|
36
|
+
)
|
|
37
|
+
.iterateNext() as Element;
|
|
38
|
+
if (invalidAttribute) {
|
|
39
|
+
result.error = {
|
|
40
|
+
code: '0x8004111c',
|
|
41
|
+
message: `Invalid Child Node, valid nodes are filter, order, link-entity, attribute, all-attributes, no-attrs. NodeName = ${invalidAttribute.tagName} NodeXml = ${invalidAttribute.outerHTML}`,
|
|
42
|
+
};
|
|
43
|
+
return true;
|
|
44
|
+
}
|
|
45
|
+
result.fetchXml = fetchXmlDocument;
|
|
46
|
+
}
|
|
47
|
+
return false;
|
|
48
|
+
};
|
|
@@ -1,13 +1,13 @@
|
|
|
1
|
-
import type { ODataQuery } from './OData.types';
|
|
2
|
-
|
|
3
|
-
/**
|
|
4
|
-
* Parses the $select query
|
|
5
|
-
* @returns Returns true when the parse has an error
|
|
6
|
-
*/
|
|
7
|
-
export const getSelectFromParser = (parser: URLSearchParams, result: ODataQuery): boolean => {
|
|
8
|
-
const $select = parser.get('$select');
|
|
9
|
-
if ($select !== null) {
|
|
10
|
-
result.$select = $select.split(',');
|
|
11
|
-
}
|
|
12
|
-
return false;
|
|
13
|
-
};
|
|
1
|
+
import type { ODataQuery } from './OData.types';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Parses the $select query
|
|
5
|
+
* @returns Returns true when the parse has an error
|
|
6
|
+
*/
|
|
7
|
+
export const getSelectFromParser = (parser: URLSearchParams, result: ODataQuery): boolean => {
|
|
8
|
+
const $select = parser.get('$select');
|
|
9
|
+
if ($select !== null) {
|
|
10
|
+
result.$select = $select.split(',');
|
|
11
|
+
}
|
|
12
|
+
return false;
|
|
13
|
+
};
|
package/src/getTopFromParser.ts
CHANGED
|
@@ -1,27 +1,27 @@
|
|
|
1
|
-
import type { ODataQuery } from './OData.types';
|
|
2
|
-
|
|
3
|
-
/**
|
|
4
|
-
* Parses the $top query
|
|
5
|
-
* @returns Returns true when the parse has an error
|
|
6
|
-
*/
|
|
7
|
-
export const getTopFromParser = (parser: URLSearchParams, result: ODataQuery): boolean => {
|
|
8
|
-
const $topValue = parser.get('$top');
|
|
9
|
-
if ($topValue !== null) {
|
|
10
|
-
let $top;
|
|
11
|
-
if (!$topValue.match(/^\d+$/) || ($top = parseInt($topValue)) < 0) {
|
|
12
|
-
result.error = {
|
|
13
|
-
code: '0x0',
|
|
14
|
-
message: `Invalid value '${$topValue}' for $top query option found. The $top query option requires a non-negative integer value.`,
|
|
15
|
-
};
|
|
16
|
-
return true;
|
|
17
|
-
} else if ($top === 0) {
|
|
18
|
-
result.error = {
|
|
19
|
-
code: '0x0',
|
|
20
|
-
message: `Invalid value for $top query option.`,
|
|
21
|
-
};
|
|
22
|
-
return true;
|
|
23
|
-
}
|
|
24
|
-
result.$top = $top;
|
|
25
|
-
}
|
|
26
|
-
return false;
|
|
27
|
-
};
|
|
1
|
+
import type { ODataQuery } from './OData.types';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Parses the $top query
|
|
5
|
+
* @returns Returns true when the parse has an error
|
|
6
|
+
*/
|
|
7
|
+
export const getTopFromParser = (parser: URLSearchParams, result: ODataQuery): boolean => {
|
|
8
|
+
const $topValue = parser.get('$top');
|
|
9
|
+
if ($topValue !== null) {
|
|
10
|
+
let $top;
|
|
11
|
+
if (!$topValue.match(/^\d+$/) || ($top = parseInt($topValue)) < 0) {
|
|
12
|
+
result.error = {
|
|
13
|
+
code: '0x0',
|
|
14
|
+
message: `Invalid value '${$topValue}' for $top query option found. The $top query option requires a non-negative integer value.`,
|
|
15
|
+
};
|
|
16
|
+
return true;
|
|
17
|
+
} else if ($top === 0) {
|
|
18
|
+
result.error = {
|
|
19
|
+
code: '0x0',
|
|
20
|
+
message: `Invalid value for $top query option.`,
|
|
21
|
+
};
|
|
22
|
+
return true;
|
|
23
|
+
}
|
|
24
|
+
result.$top = $top;
|
|
25
|
+
}
|
|
26
|
+
return false;
|
|
27
|
+
};
|
package/src/index.ts
CHANGED
|
@@ -1,16 +1,17 @@
|
|
|
1
|
-
export type {
|
|
2
|
-
BinaryOperator,
|
|
3
|
-
ODataError,
|
|
4
|
-
ODataExpand,
|
|
5
|
-
ODataExpandQuery,
|
|
6
|
-
ODataFetch,
|
|
7
|
-
ODataFilter,
|
|
8
|
-
ODataQuery,
|
|
9
|
-
ODataSelect,
|
|
10
|
-
ODataTop,
|
|
11
|
-
StandardOperator,
|
|
12
|
-
StandardOperators,
|
|
13
|
-
} from './OData.types';
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
1
|
+
export type {
|
|
2
|
+
BinaryOperator,
|
|
3
|
+
ODataError,
|
|
4
|
+
ODataExpand,
|
|
5
|
+
ODataExpandQuery,
|
|
6
|
+
ODataFetch,
|
|
7
|
+
ODataFilter,
|
|
8
|
+
ODataQuery,
|
|
9
|
+
ODataSelect,
|
|
10
|
+
ODataTop,
|
|
11
|
+
StandardOperator,
|
|
12
|
+
StandardOperators,
|
|
13
|
+
} from './OData.types';
|
|
14
|
+
|
|
15
|
+
export { parseOData } from './parseOData';
|
|
16
|
+
import { parseOData } from './parseOData';
|
|
17
|
+
export default parseOData;
|