@balena/pinejs 21.1.0-build-odata-metadata-json-395a55cb54e7b9ce0960ab93aad5f69d6c0e0462-2 → 21.1.0-build-key-left-join-890e86b168483d6158e251ab2c0d7e41b8bd50ae-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/.pinejs-cache.json +1 -1
- package/.versionbot/CHANGELOG.yml +95 -11
- package/CHANGELOG.md +24 -2
- package/out/odata-metadata/odata-metadata-generator.d.ts +1 -61
- package/out/odata-metadata/odata-metadata-generator.js +97 -186
- package/out/odata-metadata/odata-metadata-generator.js.map +1 -1
- package/out/sbvr-api/permissions.d.ts +0 -4
- package/out/sbvr-api/permissions.js +1 -1
- package/out/sbvr-api/permissions.js.map +1 -1
- package/out/sbvr-api/sbvr-utils.js +3 -18
- package/out/sbvr-api/sbvr-utils.js.map +1 -1
- package/out/sbvr-api/uri-parser.js +1 -1
- package/out/sbvr-api/uri-parser.js.map +1 -1
- package/package.json +3 -5
- package/src/odata-metadata/odata-metadata-generator.ts +126 -344
- package/src/sbvr-api/permissions.ts +2 -2
- package/src/sbvr-api/sbvr-utils.ts +3 -33
- package/src/sbvr-api/uri-parser.ts +1 -1
- package/out/odata-metadata/open-api-specification-generator.d.ts +0 -2
- package/out/odata-metadata/open-api-specification-generator.js +0 -50
- package/out/odata-metadata/open-api-specification-generator.js.map +0 -1
- package/src/odata-metadata/open-api-specification-generator.ts +0 -98
- package/typings/odata-openapi.d.ts +0 -6
@@ -1,21 +1,105 @@
|
|
1
1
|
- commits:
|
2
|
-
- subject:
|
3
|
-
hash:
|
2
|
+
- subject: Support $orderby based on a unique reverse navigation resource
|
3
|
+
hash: 890e86b168483d6158e251ab2c0d7e41b8bd50ae
|
4
4
|
body: |
|
5
|
-
|
6
|
-
Specs are scoped to the request permissions.
|
7
|
-
Different users (roles) will receive different metadata endpoints
|
8
|
-
and resources.
|
5
|
+
Update @balena/odata-to-abstract-sql from 7.1.6 to 7.2.0
|
9
6
|
footer:
|
7
|
+
Depends-on: https://github.com/balena-io-modules/odata-to-abstract-sql/pull/166
|
8
|
+
depends-on: https://github.com/balena-io-modules/odata-to-abstract-sql/pull/166
|
10
9
|
Change-type: minor
|
11
10
|
change-type: minor
|
12
|
-
|
13
|
-
|
14
|
-
author:
|
15
|
-
nested:
|
11
|
+
See: https://balena.fibery.io/Work/Project/Shape--Build-Add-support-for-sorting-on-user-selected-tag-columns-in-the-server-side-paginated-devic-912
|
12
|
+
see: https://balena.fibery.io/Work/Project/Shape--Build-Add-support-for-sorting-on-user-selected-tag-columns-in-the-server-side-paginated-devic-912
|
13
|
+
author: Thodoris Greasidis
|
14
|
+
nested:
|
15
|
+
- commits:
|
16
|
+
- subject: Support ORDER BY a Collection Navigation property using the Key
|
17
|
+
notation
|
18
|
+
hash: cc2bfbe7558b252855ccb2289d771a0ed92a365d
|
19
|
+
body: ""
|
20
|
+
footer:
|
21
|
+
Depends-on: https://github.com/balena-io-modules/odata-parser/pull/96
|
22
|
+
depends-on: https://github.com/balena-io-modules/odata-parser/pull/96
|
23
|
+
Change-type: minor
|
24
|
+
change-type: minor
|
25
|
+
See: https://balena.fibery.io/Work/Project/Shape--Build-Add-support-for-sorting-on-user-selected-tag-columns-in-the-server-side-paginated-devic-912
|
26
|
+
see: https://balena.fibery.io/Work/Project/Shape--Build-Add-support-for-sorting-on-user-selected-tag-columns-in-the-server-side-paginated-devic-912
|
27
|
+
author: Thodoris Greasidis
|
28
|
+
nested: []
|
29
|
+
version: odata-to-abstract-sql-7.2.0
|
30
|
+
title: ""
|
31
|
+
date: 2025-04-03T12:35:50.097Z
|
32
|
+
- commits:
|
33
|
+
- subject: "Tests: convert test/filterby to typescript"
|
34
|
+
hash: 92d206795a7e7f60da03a874785f364d995a2180
|
35
|
+
body: ""
|
36
|
+
footer:
|
37
|
+
Change-type: patch
|
38
|
+
change-type: patch
|
39
|
+
author: Pagan Gazzard
|
40
|
+
nested: []
|
41
|
+
- subject: "Tests: convert test/expand to typescript"
|
42
|
+
hash: 04c310f3383173b67d69af394582c48e8724feb0
|
43
|
+
body: ""
|
44
|
+
footer:
|
45
|
+
Change-type: patch
|
46
|
+
change-type: patch
|
47
|
+
author: Pagan Gazzard
|
48
|
+
nested: []
|
49
|
+
- subject: "Tests: convert test/orderby to typescript"
|
50
|
+
hash: a95840abc03109b1c719bed30b1e388c31fa69e0
|
51
|
+
body: ""
|
52
|
+
footer:
|
53
|
+
Change-type: patch
|
54
|
+
change-type: patch
|
55
|
+
author: Pagan Gazzard
|
56
|
+
nested: []
|
57
|
+
- subject: "Tests: convert test/resource_parsing to typescript"
|
58
|
+
hash: e70202afdfa112c4e182abaf8ab7ff843faf56a8
|
59
|
+
body: ""
|
60
|
+
footer:
|
61
|
+
Change-type: patch
|
62
|
+
change-type: patch
|
63
|
+
author: Pagan Gazzard
|
64
|
+
nested: []
|
65
|
+
- subject: "Tests: convert test/select to typescript"
|
66
|
+
hash: 12d873a51539f043143738fb632fb0d44952c6bc
|
67
|
+
body: ""
|
68
|
+
footer:
|
69
|
+
Change-type: patch
|
70
|
+
change-type: patch
|
71
|
+
author: Pagan Gazzard
|
72
|
+
nested: []
|
73
|
+
- subject: "Tests: convert test/paging to typescript"
|
74
|
+
hash: a74eb53a5c4f0728d5aabb6e6e9748bd6ef28a86
|
75
|
+
body: ""
|
76
|
+
footer:
|
77
|
+
Change-type: patch
|
78
|
+
change-type: patch
|
79
|
+
author: Pagan Gazzard
|
80
|
+
nested: []
|
81
|
+
- subject: "Tests: convert test/stress to typescript"
|
82
|
+
hash: 43402fa7238daa8c200781bdd42a29a409676fbc
|
83
|
+
body: ""
|
84
|
+
footer:
|
85
|
+
Change-type: patch
|
86
|
+
change-type: patch
|
87
|
+
author: Pagan Gazzard
|
88
|
+
nested: []
|
89
|
+
- subject: "Tests: convert test/chai-sql to typescript"
|
90
|
+
hash: d9d203864ef9d29f7a993c69b4951e575bf8a0c1
|
91
|
+
body: ""
|
92
|
+
footer:
|
93
|
+
Change-type: patch
|
94
|
+
change-type: patch
|
95
|
+
author: Pagan Gazzard
|
96
|
+
nested: []
|
97
|
+
version: odata-to-abstract-sql-7.1.7
|
98
|
+
title: ""
|
99
|
+
date: 2025-04-02T14:08:06.831Z
|
16
100
|
version: 21.1.0
|
17
101
|
title: ""
|
18
|
-
date: 2025-04-
|
102
|
+
date: 2025-04-03T13:55:18.812Z
|
19
103
|
- commits:
|
20
104
|
- subject: Update minio/mc Docker tag to RELEASE.2024-11-21T17-21-54Z
|
21
105
|
hash: dcb916fe5dbfd46de8284678eed69ce91a04ea42
|
package/CHANGELOG.md
CHANGED
@@ -5,9 +5,31 @@ automatically by Versionist. DO NOT EDIT THIS FILE MANUALLY!
|
|
5
5
|
This project adheres to [Semantic Versioning](http://semver.org/).
|
6
6
|
|
7
7
|
# v21.1.0
|
8
|
-
## (2025-04-
|
8
|
+
## (2025-04-03)
|
9
9
|
|
10
|
-
|
10
|
+
|
11
|
+
<details>
|
12
|
+
<summary> Support $orderby based on a unique reverse navigation resource [Thodoris Greasidis] </summary>
|
13
|
+
|
14
|
+
> ## odata-to-abstract-sql-7.2.0
|
15
|
+
> ### (2025-04-03)
|
16
|
+
>
|
17
|
+
> * Support ORDER BY a Collection Navigation property using the Key notation [Thodoris Greasidis]
|
18
|
+
>
|
19
|
+
> ## odata-to-abstract-sql-7.1.7
|
20
|
+
> ### (2025-04-02)
|
21
|
+
>
|
22
|
+
> * Tests: convert test/filterby to typescript [Pagan Gazzard]
|
23
|
+
> * Tests: convert test/expand to typescript [Pagan Gazzard]
|
24
|
+
> * Tests: convert test/orderby to typescript [Pagan Gazzard]
|
25
|
+
> * Tests: convert test/resource_parsing to typescript [Pagan Gazzard]
|
26
|
+
> * Tests: convert test/select to typescript [Pagan Gazzard]
|
27
|
+
> * Tests: convert test/paging to typescript [Pagan Gazzard]
|
28
|
+
> * Tests: convert test/stress to typescript [Pagan Gazzard]
|
29
|
+
> * Tests: convert test/chai-sql to typescript [Pagan Gazzard]
|
30
|
+
>
|
31
|
+
|
32
|
+
</details>
|
11
33
|
|
12
34
|
# v21.0.4
|
13
35
|
## (2025-03-31)
|
@@ -1,65 +1,5 @@
|
|
1
1
|
import type { AbstractSqlModel } from '@balena/abstract-sql-compiler';
|
2
|
-
import type { PermissionLookup } from '../sbvr-api/permissions.js';
|
3
|
-
type ODataCsdlV4References = {
|
4
|
-
[URI: string]: {
|
5
|
-
$Include: Array<{
|
6
|
-
$Namespace: string;
|
7
|
-
$Alias: string;
|
8
|
-
[annotation: string]: string | boolean;
|
9
|
-
}>;
|
10
|
-
};
|
11
|
-
};
|
12
|
-
type ODataCsdlV4BaseProperty = {
|
13
|
-
[annotation: string]: string | boolean | undefined;
|
14
|
-
$Type?: string;
|
15
|
-
$Nullable?: boolean;
|
16
|
-
};
|
17
|
-
type ODataCsdlV4StructuralProperty = ODataCsdlV4BaseProperty & {
|
18
|
-
$Kind?: 'Property';
|
19
|
-
};
|
20
|
-
type ODataCsdlV4NavigationProperty = ODataCsdlV4BaseProperty & {
|
21
|
-
$Kind: 'NavigationProperty';
|
22
|
-
$Partner?: string;
|
23
|
-
};
|
24
|
-
type ODataCsdlV4Property = ODataCsdlV4BaseProperty | ODataCsdlV4StructuralProperty | ODataCsdlV4NavigationProperty;
|
25
|
-
type ODataCsdlV4EntityType = {
|
26
|
-
$Kind: 'EntityType';
|
27
|
-
$Key: string[];
|
28
|
-
[property: string]: true | string[] | string | ODataCsdlV4Property;
|
29
|
-
};
|
30
|
-
type ODataCsdlV4EntityContainerEntries = {
|
31
|
-
$Type: string;
|
32
|
-
[property: string]: true | string | ODataCapabilitiesUDIRRestrictionsMethod;
|
33
|
-
};
|
34
|
-
type ODataCsdlV4EntityContainer = {
|
35
|
-
$Kind: 'EntityContainer';
|
36
|
-
'@Capabilities.BatchSupported'?: boolean;
|
37
|
-
[resourceOrAnnotation: string]: boolean | string | ODataCsdlV4EntityContainerEntries | undefined;
|
38
|
-
};
|
39
|
-
type ODataCsdlV4Schema = {
|
40
|
-
$Alias: string;
|
41
|
-
'@Core.DefaultNamespace': true;
|
42
|
-
[resource: string]: string | boolean | ODataCsdlV4EntityContainer | ODataCsdlV4EntityType;
|
43
|
-
};
|
44
|
-
type OdataCsdlV4 = {
|
45
|
-
$Version: string;
|
46
|
-
$Reference: ODataCsdlV4References;
|
47
|
-
$EntityContainer: string;
|
48
|
-
[schema: string]: string | ODataCsdlV4References | ODataCsdlV4Schema;
|
49
|
-
};
|
50
|
-
type ODataCapabilitiesUDIRRestrictionsMethod = {
|
51
|
-
Updatable: boolean;
|
52
|
-
} | {
|
53
|
-
Deletable: boolean;
|
54
|
-
} | {
|
55
|
-
Insertable: boolean;
|
56
|
-
} | {
|
57
|
-
Readable: boolean;
|
58
|
-
} | {
|
59
|
-
Filterable: boolean;
|
60
|
-
};
|
61
2
|
export declare const generateODataMetadata: {
|
62
|
-
(vocabulary: string, abstractSqlModel: AbstractSqlModel
|
3
|
+
(vocabulary: string, abstractSqlModel: AbstractSqlModel): string;
|
63
4
|
version: any;
|
64
5
|
};
|
65
|
-
export {};
|
@@ -1,84 +1,5 @@
|
|
1
1
|
import { sbvrTypes } from '../sbvr-api/sbvr-utils.js';
|
2
2
|
import { version } from '../config-loader/env.js';
|
3
|
-
const odataVocabularyReferences = {
|
4
|
-
'https://oasis-tcs.github.io/odata-vocabularies/vocabularies/Org.OData.Core.V1.json': {
|
5
|
-
$Include: [
|
6
|
-
{
|
7
|
-
$Namespace: 'Org.OData.Core.V1',
|
8
|
-
$Alias: 'Core',
|
9
|
-
'@Core.DefaultNamespace': true,
|
10
|
-
},
|
11
|
-
],
|
12
|
-
},
|
13
|
-
'https://oasis-tcs.github.io/odata-vocabularies/vocabularies/Org.OData.Measures.V1.json': {
|
14
|
-
$Include: [
|
15
|
-
{
|
16
|
-
$Namespace: 'Org.OData.Measures.V1',
|
17
|
-
$Alias: 'Measures',
|
18
|
-
},
|
19
|
-
],
|
20
|
-
},
|
21
|
-
'https://oasis-tcs.github.io/odata-vocabularies/vocabularies/Org.OData.Aggregation.V1.json': {
|
22
|
-
$Include: [
|
23
|
-
{
|
24
|
-
$Namespace: 'Org.OData.Aggregation.V1',
|
25
|
-
$Alias: 'Aggregation',
|
26
|
-
},
|
27
|
-
],
|
28
|
-
},
|
29
|
-
'https://oasis-tcs.github.io/odata-vocabularies/vocabularies/Org.OData.Capabilities.V1.json': {
|
30
|
-
$Include: [
|
31
|
-
{
|
32
|
-
$Namespace: 'Org.OData.Capabilities.V1',
|
33
|
-
$Alias: 'Capabilities',
|
34
|
-
},
|
35
|
-
],
|
36
|
-
},
|
37
|
-
};
|
38
|
-
const restrictionsLookup = (method, value) => {
|
39
|
-
const lookup = {
|
40
|
-
update: {
|
41
|
-
'@Capabilities.UpdateRestrictions': {
|
42
|
-
Updatable: value,
|
43
|
-
},
|
44
|
-
'@Capabilities.FilterRestrictions': {
|
45
|
-
Filterable: true,
|
46
|
-
},
|
47
|
-
},
|
48
|
-
delete: {
|
49
|
-
'@Capabilities.DeleteRestrictions': {
|
50
|
-
Deletable: value,
|
51
|
-
},
|
52
|
-
'@Capabilities.FilterRestrictions': {
|
53
|
-
Filterable: true,
|
54
|
-
},
|
55
|
-
},
|
56
|
-
create: {
|
57
|
-
'@Capabilities.InsertRestrictions': {
|
58
|
-
Insertable: value,
|
59
|
-
},
|
60
|
-
},
|
61
|
-
read: {
|
62
|
-
'@Capabilities.ReadRestrictions': {
|
63
|
-
Readable: value,
|
64
|
-
},
|
65
|
-
'@Capabilities.FilterRestrictions': {
|
66
|
-
Filterable: true,
|
67
|
-
},
|
68
|
-
},
|
69
|
-
};
|
70
|
-
if (method === 'all') {
|
71
|
-
return {
|
72
|
-
...lookup['update'],
|
73
|
-
...lookup['delete'],
|
74
|
-
...lookup['create'],
|
75
|
-
...lookup['read'],
|
76
|
-
};
|
77
|
-
}
|
78
|
-
else {
|
79
|
-
return lookup[method] ?? {};
|
80
|
-
}
|
81
|
-
};
|
82
3
|
const getResourceName = (resourceName) => resourceName
|
83
4
|
.split('-')
|
84
5
|
.map((namePart) => namePart.split(' ').join('_'))
|
@@ -86,47 +7,17 @@ const getResourceName = (resourceName) => resourceName
|
|
86
7
|
const forEachUniqueTable = (model, callback) => {
|
87
8
|
const usedTableNames = {};
|
88
9
|
const result = [];
|
89
|
-
for (const key of Object.
|
90
|
-
const table = model.abstractSqlModel.tables[key];
|
10
|
+
for (const [key, table] of Object.entries(model)) {
|
91
11
|
if (typeof table !== 'string' &&
|
92
12
|
!table.primitive &&
|
93
|
-
!usedTableNames[table.name]
|
94
|
-
model.preparedPermissionLookup) {
|
13
|
+
!usedTableNames[table.name]) {
|
95
14
|
usedTableNames[table.name] = true;
|
96
15
|
result.push(callback(key, table));
|
97
16
|
}
|
98
17
|
}
|
99
18
|
return result;
|
100
19
|
};
|
101
|
-
const
|
102
|
-
const resourcesAndOps = {};
|
103
|
-
for (const resourceOpsAuths of Object.keys(permissionLookup)) {
|
104
|
-
const [vocabulary, resource, rule] = resourceOpsAuths.split('.');
|
105
|
-
resourcesAndOps[vocabulary] ??= {};
|
106
|
-
resourcesAndOps[vocabulary][resource] ??= {
|
107
|
-
['read']: false,
|
108
|
-
['create']: false,
|
109
|
-
['update']: false,
|
110
|
-
['delete']: false,
|
111
|
-
};
|
112
|
-
if (rule === 'all' || (resource === 'all' && rule === undefined)) {
|
113
|
-
resourcesAndOps[vocabulary][resource] = {
|
114
|
-
['read']: true,
|
115
|
-
['create']: true,
|
116
|
-
['update']: true,
|
117
|
-
['delete']: true,
|
118
|
-
};
|
119
|
-
}
|
120
|
-
else if (rule === 'read' ||
|
121
|
-
rule === 'create' ||
|
122
|
-
rule === 'update' ||
|
123
|
-
rule === 'delete') {
|
124
|
-
resourcesAndOps[vocabulary][resource][rule] = true;
|
125
|
-
}
|
126
|
-
}
|
127
|
-
return resourcesAndOps;
|
128
|
-
};
|
129
|
-
export const generateODataMetadata = (vocabulary, abstractSqlModel, permissionsLookup) => {
|
20
|
+
export const generateODataMetadata = (vocabulary, abstractSqlModel) => {
|
130
21
|
const complexTypes = {};
|
131
22
|
const resolveDataType = (fieldType) => {
|
132
23
|
if (sbvrTypes[fieldType] == null) {
|
@@ -139,83 +30,103 @@ export const generateODataMetadata = (vocabulary, abstractSqlModel, permissionsL
|
|
139
30
|
}
|
140
31
|
return sbvrTypes[fieldType].types.odata.name;
|
141
32
|
};
|
142
|
-
const
|
143
|
-
|
144
|
-
|
145
|
-
const model = {
|
146
|
-
vocabulary,
|
147
|
-
abstractSqlModel,
|
148
|
-
preparedPermissionLookup: prepPermissionsLookup,
|
149
|
-
};
|
150
|
-
const metaBalenaEntries = {};
|
151
|
-
const entityContainer = {
|
152
|
-
$Kind: 'EntityContainer',
|
153
|
-
'@Capabilities.KeyAsSegmentSupported': false,
|
154
|
-
};
|
155
|
-
forEachUniqueTable(model, (_key, { idField, name: resourceName, fields }) => {
|
33
|
+
const model = abstractSqlModel.tables;
|
34
|
+
const associations = [];
|
35
|
+
forEachUniqueTable(model, (_key, { name: resourceName, fields }) => {
|
156
36
|
resourceName = getResourceName(resourceName);
|
157
|
-
const
|
158
|
-
|
159
|
-
|
160
|
-
|
161
|
-
|
162
|
-
|
163
|
-
|
164
|
-
|
165
|
-
|
166
|
-
|
167
|
-
|
168
|
-
.filter(({ dataType }) => dataType !== 'ForeignKey')
|
169
|
-
.map(({ dataType, fieldName, required }) => {
|
170
|
-
dataType = resolveDataType(dataType);
|
171
|
-
fieldName = getResourceName(fieldName);
|
172
|
-
uniqueTable[fieldName] = {
|
173
|
-
$Type: dataType,
|
174
|
-
$Nullable: !required,
|
175
|
-
'@Core.Computed': fieldName === 'created_at' || fieldName === 'modified_at'
|
176
|
-
? true
|
177
|
-
: false,
|
178
|
-
};
|
179
|
-
});
|
180
|
-
fields
|
181
|
-
.filter(({ dataType, references }) => dataType === 'ForeignKey' && references != null)
|
182
|
-
.map(({ fieldName, references, required }) => {
|
183
|
-
const { resourceName: referencedResource } = references;
|
184
|
-
const referencedResourceName = model.abstractSqlModel.tables[referencedResource]?.name;
|
185
|
-
const typeReference = referencedResourceName || referencedResource;
|
186
|
-
fieldName = getResourceName(fieldName);
|
187
|
-
uniqueTable[fieldName] = {
|
188
|
-
$Kind: 'NavigationProperty',
|
189
|
-
$Partner: resourceName,
|
190
|
-
$Nullable: !required,
|
191
|
-
$Type: vocabulary + '.' + getResourceName(typeReference),
|
192
|
-
};
|
193
|
-
});
|
194
|
-
metaBalenaEntries[resourceName] = uniqueTable;
|
195
|
-
let entityCon = {
|
196
|
-
$Collection: true,
|
197
|
-
$Type: vocabulary + '.' + resourceName,
|
198
|
-
};
|
199
|
-
for (const [resKey, resValue] of Object.entries(permissions)) {
|
200
|
-
entityCon = { ...entityCon, ...restrictionsLookup(resKey, resValue) };
|
37
|
+
for (const { dataType, required, references } of fields) {
|
38
|
+
if (dataType === 'ForeignKey' && references != null) {
|
39
|
+
const { resourceName: referencedResource } = references;
|
40
|
+
associations.push({
|
41
|
+
name: resourceName + referencedResource,
|
42
|
+
ends: [
|
43
|
+
{ resourceName, cardinality: required ? '1' : '0..1' },
|
44
|
+
{ resourceName: referencedResource, cardinality: '*' },
|
45
|
+
],
|
46
|
+
});
|
47
|
+
}
|
201
48
|
}
|
202
|
-
entityContainer[resourceName] = entityCon;
|
203
49
|
});
|
204
|
-
|
205
|
-
|
206
|
-
|
207
|
-
|
208
|
-
|
209
|
-
|
210
|
-
|
211
|
-
|
212
|
-
|
213
|
-
|
214
|
-
|
215
|
-
|
216
|
-
|
217
|
-
|
218
|
-
|
50
|
+
return (`
|
51
|
+
<?xml version="1.0" encoding="iso-8859-1" standalone="yes"?>
|
52
|
+
<edmx:Edmx Version="1.0" xmlns:edmx="http://schemas.microsoft.com/ado/2007/06/edmx">
|
53
|
+
<edmx:DataServices xmlns:m="http://schemas.microsoft.com/ado/2007/08/dataservices/metadata" m:DataServiceVersion="2.0">
|
54
|
+
<Schema Namespace="${vocabulary}"
|
55
|
+
xmlns:d="http://schemas.microsoft.com/ado/2007/08/dataservices"
|
56
|
+
xmlns:m="http://schemas.microsoft.com/ado/2007/08/dataservices/metadata"
|
57
|
+
xmlns="http://schemas.microsoft.com/ado/2008/09/edm">
|
58
|
+
|
59
|
+
` +
|
60
|
+
forEachUniqueTable(model, (_key, { idField, name: resourceName, fields }) => {
|
61
|
+
resourceName = getResourceName(resourceName);
|
62
|
+
return (`
|
63
|
+
<EntityType Name="${resourceName}">
|
64
|
+
<Key>
|
65
|
+
<PropertyRef Name="${idField}" />
|
66
|
+
</Key>
|
67
|
+
|
68
|
+
` +
|
69
|
+
fields
|
70
|
+
.filter(({ dataType }) => dataType !== 'ForeignKey')
|
71
|
+
.map(({ dataType, fieldName, required }) => {
|
72
|
+
dataType = resolveDataType(dataType);
|
73
|
+
fieldName = getResourceName(fieldName);
|
74
|
+
return `<Property Name="${fieldName}" Type="${dataType}" Nullable="${!required}" />`;
|
75
|
+
})
|
76
|
+
.join('\n') +
|
77
|
+
'\n' +
|
78
|
+
fields
|
79
|
+
.filter(({ dataType, references }) => dataType === 'ForeignKey' && references != null)
|
80
|
+
.map(({ fieldName, references }) => {
|
81
|
+
const { resourceName: referencedResource } = references;
|
82
|
+
fieldName = getResourceName(fieldName);
|
83
|
+
return `<NavigationProperty Name="${fieldName}" Relationship="${vocabulary}.${resourceName + referencedResource}" FromRole="${resourceName}" ToRole="${referencedResource}" />`;
|
84
|
+
})
|
85
|
+
.join('\n') +
|
86
|
+
'\n' +
|
87
|
+
`
|
88
|
+
</EntityType>`);
|
89
|
+
}).join('\n\n') +
|
90
|
+
associations
|
91
|
+
.map(({ name, ends }) => {
|
92
|
+
name = getResourceName(name);
|
93
|
+
return (`<Association Name="${name}">` +
|
94
|
+
'\n\t' +
|
95
|
+
ends
|
96
|
+
.map(({ resourceName, cardinality }) => `<End Role="${resourceName}" Type="${vocabulary}.${resourceName}" Multiplicity="${cardinality}" />`)
|
97
|
+
.join('\n\t') +
|
98
|
+
'\n' +
|
99
|
+
`</Association>`);
|
100
|
+
})
|
101
|
+
.join('\n') +
|
102
|
+
`
|
103
|
+
<EntityContainer Name="${vocabulary}Service" m:IsDefaultEntityContainer="true">
|
104
|
+
|
105
|
+
` +
|
106
|
+
forEachUniqueTable(model, (_key, { name: resourceName }) => {
|
107
|
+
resourceName = getResourceName(resourceName);
|
108
|
+
return `<EntitySet Name="${resourceName}" EntityType="${vocabulary}.${resourceName}" />`;
|
109
|
+
}).join('\n') +
|
110
|
+
'\n' +
|
111
|
+
associations
|
112
|
+
.map(({ name, ends }) => {
|
113
|
+
name = getResourceName(name);
|
114
|
+
return (`<AssociationSet Name="${name}" Association="${vocabulary}.${name}">` +
|
115
|
+
'\n\t' +
|
116
|
+
ends
|
117
|
+
.map(({ resourceName }) => `<End Role="${resourceName}" EntitySet="${vocabulary}.${resourceName}" />`)
|
118
|
+
.join('\n\t') +
|
119
|
+
`
|
120
|
+
</AssociationSet>`);
|
121
|
+
})
|
122
|
+
.join('\n') +
|
123
|
+
`
|
124
|
+
</EntityContainer>` +
|
125
|
+
Object.values(complexTypes).join('\n') +
|
126
|
+
`
|
127
|
+
</Schema>
|
128
|
+
</edmx:DataServices>
|
129
|
+
</edmx:Edmx>`);
|
219
130
|
};
|
220
131
|
generateODataMetadata.version = version;
|
221
132
|
//# sourceMappingURL=odata-metadata-generator.js.map
|
@@ -1 +1 @@
|
|
1
|
-
{"version":3,"file":"odata-metadata-generator.js","sourceRoot":"","sources":["../../src/odata-metadata/odata-metadata-generator.ts"],"names":[],"mappings":"AAMA,OAAO,EAAE,SAAS,EAAE,MAAM,2BAA2B,CAAC;AACtD,OAAO,EAAE,OAAO,EAAE,MAAM,yBAAyB,CAAC;
|
1
|
+
{"version":3,"file":"odata-metadata-generator.js","sourceRoot":"","sources":["../../src/odata-metadata/odata-metadata-generator.ts"],"names":[],"mappings":"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"}
|
@@ -1,10 +1,8 @@
|
|
1
1
|
import type AuthModel from './user.js';
|
2
2
|
import './express-extension.js';
|
3
3
|
import type Express from 'express';
|
4
|
-
import type { ODataBinds } from '@balena/odata-parser';
|
5
4
|
import type { Tx } from '../database-layer/db.js';
|
6
5
|
import type { ApiKey, User } from '../sbvr-api/sbvr-utils.js';
|
7
|
-
import type { Dictionary } from './common-types.js';
|
8
6
|
import { type HookReq } from './hooks.js';
|
9
7
|
import { PermissionError, PermissionParsingError } from './errors.js';
|
10
8
|
import { type ODataRequest } from './uri-parser.js';
|
@@ -29,7 +27,6 @@ type MappedNestedCheck<T extends NestedCheck<I>, I, O> = T extends NestedCheckOr
|
|
29
27
|
export declare function nestedCheck<I extends string, O>(check: I, stringCallback: (s: string) => O): O;
|
30
28
|
export declare function nestedCheck<I extends boolean, O>(check: I, stringCallback: (s: string) => O): boolean;
|
31
29
|
export declare function nestedCheck<I extends NonNullable<unknown>, O>(check: NestedCheck<I>, stringCallback: (s: string) => O): Exclude<I, string> | O | MappedNestedCheck<typeof check, I, O>;
|
32
|
-
export type PermissionLookup = Dictionary<true | string[]>;
|
33
30
|
export declare const checkPassword: (username: string, password: string) => Promise<{
|
34
31
|
id: number;
|
35
32
|
actor: number;
|
@@ -53,7 +50,6 @@ export declare const customApiKeyMiddleware: (paramName?: string) => (req: HookR
|
|
53
50
|
export declare const apiKeyMiddleware: (req: HookReq | Express.Request, _res?: Express.Response, next?: Express.NextFunction) => Promise<void>;
|
54
51
|
export declare const checkPermissions: (req: PermissionReq, actionList: PermissionCheck, resourceName?: string, vocabulary?: string) => Promise<boolean | NestedCheck<string>>;
|
55
52
|
export declare const checkPermissionsMiddleware: (action: PermissionCheck) => Express.RequestHandler;
|
56
|
-
export declare const getReqPermissions: (req: PermissionReq, odataBinds?: ODataBinds) => Promise<PermissionLookup>;
|
57
53
|
export declare const addPermissions: (req: PermissionReq, request: ODataRequest & {
|
58
54
|
permissionType?: PermissionCheck;
|
59
55
|
}) => Promise<void>;
|
@@ -1055,7 +1055,7 @@ const getGuestPermissions = memoize(async () => {
|
|
1055
1055
|
guestPermissionsInitialized = true;
|
1056
1056
|
return guestPermissions;
|
1057
1057
|
}, { promise: true });
|
1058
|
-
|
1058
|
+
const getReqPermissions = async (req, odataBinds = []) => {
|
1059
1059
|
const guestPermissions = await (async () => {
|
1060
1060
|
if (guestPermissionsInitialized === false &&
|
1061
1061
|
(req.user === root.user || req.user === rootRead.user)) {
|