@ndustrial/contxt-sdk 4.3.4 → 5.1.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/.gitattributes +1 -0
- package/.nvmrc +1 -1
- package/CHANGELOG.md +8 -0
- package/docs/Facilities.md +0 -144
- package/docs/FacilityGroupings.md +0 -160
- package/docs/Nionic.md +63 -0
- package/docs/README.md +3 -29
- package/docs/Typedefs.md +0 -101
- package/esm/config/audiences.js +13 -13
- package/esm/config/audiences.js.map +1 -1
- package/esm/index.js +3 -6
- package/esm/index.js.map +1 -1
- package/esm/nionic/index.js +126 -0
- package/esm/nionic/index.js.map +1 -0
- package/lib/config/audiences.js +13 -13
- package/lib/config/audiences.js.map +1 -1
- package/lib/index.js +19 -13
- package/lib/index.js.map +1 -1
- package/lib/nionic/index.js +130 -0
- package/lib/nionic/index.js.map +1 -0
- package/meta.yaml +11 -0
- package/package.json +9 -10
- package/src/bus/index.spec.js +3 -2
- package/src/bus/webSocketConnection.spec.js +31 -31
- package/src/config/audiences.js +13 -13
- package/src/config/index.spec.js +6 -6
- package/src/coordinator/applications.spec.js +8 -8
- package/src/coordinator/consent.spec.js +1 -1
- package/src/coordinator/edgeNodes.spec.js +3 -3
- package/src/coordinator/organizations.spec.js +4 -4
- package/src/coordinator/permissions.spec.js +4 -4
- package/src/coordinator/roles.spec.js +3 -3
- package/src/coordinator/users.spec.js +14 -15
- package/src/events/index.spec.js +16 -16
- package/src/files/index.spec.js +7 -7
- package/src/index.js +3 -6
- package/src/index.spec.js +8 -22
- package/src/iot/feeds.spec.js +4 -4
- package/src/iot/fieldCategories.spec.js +4 -4
- package/src/iot/fieldGroupings.spec.js +5 -5
- package/src/iot/outputs.spec.js +6 -6
- package/src/nionic/index.js +151 -0
- package/src/request.spec.js +3 -3
- package/src/sessionTypes/auth0WebAuth.spec.js +2 -2
- package/src/sessionTypes/index.spec.js +3 -3
- package/src/sessionTypes/machineAuth.spec.js +3 -3
- package/src/sessionTypes/passwordGrantAuth.spec.js +1 -1
- package/src/utils/iot/formatOutputFieldDataFromServer.spec.js +6 -6
- package/src/utils/iot/parseOutputFieldNextPageUrlMetadata.spec.js +2 -2
- package/src/utils/pagination/formatPaginatedDataFromServer.spec.js +2 -2
- package/src/utils/url/stringifyParams.spec.js +2 -3
- package/support/fixtures/factories/IOSDevice.js +3 -3
- package/support/fixtures/factories/applicationGrouping.js +4 -4
- package/support/fixtures/factories/applicationModule.js +2 -2
- package/support/fixtures/factories/asset.js +1 -1
- package/support/fixtures/factories/assetAttribute.js +2 -2
- package/support/fixtures/factories/assetAttributeValue.js +2 -2
- package/support/fixtures/factories/assetMetric.js +1 -1
- package/support/fixtures/factories/assetMetricValue.js +3 -3
- package/support/fixtures/factories/assetMetricValueCompact.js +2 -2
- package/support/fixtures/factories/assetType.js +1 -1
- package/support/fixtures/factories/authResults.js +3 -3
- package/support/fixtures/factories/channel.js +1 -1
- package/support/fixtures/factories/contxtApplication.js +5 -5
- package/support/fixtures/factories/contxtOrganization.js +2 -2
- package/support/fixtures/factories/contxtOrganizationFeaturedApplication.js +3 -3
- package/support/fixtures/factories/contxtProject.js +2 -2
- package/support/fixtures/factories/contxtProjectEnvironment.js +2 -2
- package/support/fixtures/factories/contxtRole.js +3 -3
- package/support/fixtures/factories/contxtRoleApplication.js +1 -1
- package/support/fixtures/factories/contxtRoleProjectEnvironment.js +1 -1
- package/support/fixtures/factories/contxtUser.js +2 -2
- package/support/fixtures/factories/contxtUserApplication.js +1 -1
- package/support/fixtures/factories/contxtUserFavoriteApplication.js +2 -2
- package/support/fixtures/factories/contxtUserPermissions.js +5 -5
- package/support/fixtures/factories/contxtUserProjectEnvironment.js +1 -1
- package/support/fixtures/factories/contxtUserRole.js +2 -2
- package/support/fixtures/factories/costCenter.js +2 -2
- package/support/fixtures/factories/costCenterFacility.js +3 -3
- package/support/fixtures/factories/edgeNode.js +1 -1
- package/support/fixtures/factories/event.js +5 -5
- package/support/fixtures/factories/eventType.js +4 -4
- package/support/fixtures/factories/eventUser.js +5 -5
- package/support/fixtures/factories/facility.js +4 -4
- package/support/fixtures/factories/facilityGrouping.js +3 -3
- package/support/fixtures/factories/facilityGroupingFacility.js +3 -3
- package/support/fixtures/factories/facilityInfo.js +2 -2
- package/support/fixtures/factories/facilityTag.js +1 -1
- package/support/fixtures/factories/feedStatus.js +1 -1
- package/support/fixtures/factories/feedType.js +1 -1
- package/support/fixtures/factories/feeds.js +5 -5
- package/support/fixtures/factories/fieldCategory.js +3 -3
- package/support/fixtures/factories/fieldGrouping.js +4 -4
- package/support/fixtures/factories/fieldGroupingField.js +3 -3
- package/support/fixtures/factories/fieldGroupingStatus.js +1 -1
- package/support/fixtures/factories/file.js +1 -1
- package/support/fixtures/factories/fileUploadInfo.js +1 -1
- package/support/fixtures/factories/organization.js +1 -1
- package/support/fixtures/factories/outputField.js +10 -10
- package/support/fixtures/factories/outputFieldData.js +1 -1
- package/support/fixtures/factories/owner.js +2 -2
- package/support/fixtures/factories/paginationMetadata.js +2 -2
- package/support/fixtures/factories/triggeredEvent.js +4 -4
- package/support/fixtures/factories/userEventSubscription.js +1 -1
- package/support/fixtures/factories/userMobileNumber.js +1 -1
- package/support/fixtures/factories/userPermissionsMap.js +2 -2
- package/.envrc +0 -0
- package/.huskyrc.js +0 -11
- package/.nycrc +0 -12
- package/esm/assets/assetAttributes.js +0 -574
- package/esm/assets/assetAttributes.js.map +0 -1
- package/esm/assets/assetMetrics.js +0 -690
- package/esm/assets/assetMetrics.js.map +0 -1
- package/esm/assets/assetTypes.js +0 -273
- package/esm/assets/assetTypes.js.map +0 -1
- package/esm/assets/index.js +0 -283
- package/esm/assets/index.js.map +0 -1
- package/esm/facilities/costCenters.js +0 -306
- package/esm/facilities/costCenters.js.map +0 -1
- package/esm/facilities/groupings.js +0 -323
- package/esm/facilities/groupings.js.map +0 -1
- package/esm/facilities/index.js +0 -343
- package/esm/facilities/index.js.map +0 -1
- package/esm/health/index.js +0 -229
- package/esm/health/index.js.map +0 -1
- package/esm/utils/facilities/formatFacilityWithInfoFromServer.js +0 -65
- package/esm/utils/facilities/formatFacilityWithInfoFromServer.js.map +0 -1
- package/esm/utils/facilities/index.js +0 -4
- package/esm/utils/facilities/index.js.map +0 -1
- package/lib/assets/assetAttributes.js +0 -588
- package/lib/assets/assetAttributes.js.map +0 -1
- package/lib/assets/assetMetrics.js +0 -705
- package/lib/assets/assetMetrics.js.map +0 -1
- package/lib/assets/assetTypes.js +0 -287
- package/lib/assets/assetTypes.js.map +0 -1
- package/lib/assets/index.js +0 -302
- package/lib/assets/index.js.map +0 -1
- package/lib/facilities/costCenters.js +0 -316
- package/lib/facilities/costCenters.js.map +0 -1
- package/lib/facilities/groupings.js +0 -333
- package/lib/facilities/groupings.js.map +0 -1
- package/lib/facilities/index.js +0 -360
- package/lib/facilities/index.js.map +0 -1
- package/lib/health/index.js +0 -232
- package/lib/health/index.js.map +0 -1
- package/lib/utils/facilities/formatFacilityWithInfoFromServer.js +0 -71
- package/lib/utils/facilities/formatFacilityWithInfoFromServer.js.map +0 -1
- package/lib/utils/facilities/index.js +0 -15
- package/lib/utils/facilities/index.js.map +0 -1
- package/src/assets/assetAttributes.js +0 -619
- package/src/assets/assetAttributes.spec.js +0 -1143
- package/src/assets/assetMetrics.js +0 -736
- package/src/assets/assetMetrics.spec.js +0 -1180
- package/src/assets/assetTypes.js +0 -260
- package/src/assets/assetTypes.spec.js +0 -556
- package/src/assets/index.js +0 -271
- package/src/assets/index.spec.js +0 -515
- package/src/facilities/costCenters.js +0 -295
- package/src/facilities/costCenters.spec.js +0 -529
- package/src/facilities/groupings.js +0 -320
- package/src/facilities/groupings.spec.js +0 -567
- package/src/facilities/index.js +0 -343
- package/src/facilities/index.spec.js +0 -551
- package/src/health/index.js +0 -200
- package/src/health/index.spec.js +0 -501
- package/src/utils/facilities/formatFacilityWithInfoFromServer.js +0 -62
- package/src/utils/facilities/formatFacilityWithInfoFromServer.spec.js +0 -73
- package/src/utils/facilities/index.js +0 -3
- package/tmp/package.json +0 -11
|
@@ -1,295 +0,0 @@
|
|
|
1
|
-
import isPlainObject from 'lodash.isplainobject';
|
|
2
|
-
import { toCamelCase, toSnakeCase } from '../utils/objects';
|
|
3
|
-
|
|
4
|
-
/**
|
|
5
|
-
* @typedef {Object} CostCenter
|
|
6
|
-
* @param {string} createdAt ISO 8601 Extended Format date/time string
|
|
7
|
-
* @param {string} [description]
|
|
8
|
-
* @param {string} id UUID
|
|
9
|
-
* @param {string} name
|
|
10
|
-
* @param {string} organizationId UUID
|
|
11
|
-
* @param {string} updatedAt ISO 8601 Extended Format date/time string
|
|
12
|
-
*/
|
|
13
|
-
|
|
14
|
-
/**
|
|
15
|
-
* @typedef {Object} CostCenterFacility
|
|
16
|
-
* @param {string} costCenterId UUID
|
|
17
|
-
* @param {string} createdAt ISO 8601 Extended Format date/time string
|
|
18
|
-
* @param {number} facilityId
|
|
19
|
-
* @param {string} id UUID
|
|
20
|
-
* @param {string} updatedAt ISO 8601 Extended Format date/time string
|
|
21
|
-
*/
|
|
22
|
-
|
|
23
|
-
/**
|
|
24
|
-
* Module that provides access to cost centers, and helps manage
|
|
25
|
-
* the relationship between those cost centers and facilities
|
|
26
|
-
*
|
|
27
|
-
* @typicalname contxtSdk.facilities.costCenters
|
|
28
|
-
*/
|
|
29
|
-
class CostCenters {
|
|
30
|
-
/**
|
|
31
|
-
* @param {Object} sdk An instance of the SDK so the module can communicate with other modules
|
|
32
|
-
* @param {Object} request An instance of the request module tied to this module's audience.
|
|
33
|
-
* @param {string} baseUrl The base URL provided by the parent module
|
|
34
|
-
*/
|
|
35
|
-
constructor(sdk, request, baseUrl) {
|
|
36
|
-
this._baseUrl = baseUrl;
|
|
37
|
-
this._request = request;
|
|
38
|
-
this._sdk = sdk;
|
|
39
|
-
}
|
|
40
|
-
|
|
41
|
-
/**
|
|
42
|
-
* Adds a facility to a cost center
|
|
43
|
-
*
|
|
44
|
-
* API Endpoint: '/costcenters/:costCenterId/facility/:facilityId'
|
|
45
|
-
* Method: POST
|
|
46
|
-
*
|
|
47
|
-
* @param {string} costCenterId UUID corresponding with a cost center
|
|
48
|
-
* @param {number} facilityId The ID of a facility
|
|
49
|
-
*
|
|
50
|
-
* @returns {Promise}
|
|
51
|
-
* @fulfill {CostCenterFacility} Information about the new cost center facility relationship
|
|
52
|
-
* @reject {Error}
|
|
53
|
-
*
|
|
54
|
-
* @example
|
|
55
|
-
* contxtSdk.facilities.costCenters
|
|
56
|
-
* .addFacility('b3dbaae3-25dd-475b-80dc-66296630a8d0', 4)
|
|
57
|
-
* .then((costCenter) => console.log(costCenter))
|
|
58
|
-
* .catch((err) => console.log(err));
|
|
59
|
-
*/
|
|
60
|
-
addFacility(costCenterId, facilityId) {
|
|
61
|
-
let errorMsg;
|
|
62
|
-
|
|
63
|
-
if (!costCenterId) {
|
|
64
|
-
errorMsg =
|
|
65
|
-
'A costCenterId is required to create a relationship between a cost center and a facility.';
|
|
66
|
-
} else if (!facilityId) {
|
|
67
|
-
errorMsg =
|
|
68
|
-
'A facilityId is required to create a relationship between a cost center and a facility.';
|
|
69
|
-
}
|
|
70
|
-
|
|
71
|
-
if (errorMsg) {
|
|
72
|
-
return Promise.reject(new Error(errorMsg));
|
|
73
|
-
}
|
|
74
|
-
|
|
75
|
-
return this._request
|
|
76
|
-
.post(
|
|
77
|
-
`${this._baseUrl}/costcenters/${costCenterId}/facility/${facilityId}`
|
|
78
|
-
)
|
|
79
|
-
.then((costCenterFacility) => toCamelCase(costCenterFacility));
|
|
80
|
-
}
|
|
81
|
-
|
|
82
|
-
/**
|
|
83
|
-
* Creates a new cost center
|
|
84
|
-
*
|
|
85
|
-
* API Endpoint: '/costcenters'
|
|
86
|
-
* Method: POST
|
|
87
|
-
*
|
|
88
|
-
* @param {Object} costCenter
|
|
89
|
-
* @param {string} [costCenter.description]
|
|
90
|
-
* @param {string} costCenter.name
|
|
91
|
-
* @param {string} costCenter.organizationId UUID
|
|
92
|
-
*
|
|
93
|
-
* @returns {Promise}
|
|
94
|
-
* @fulfill {CostCenter} Information about the new cost center
|
|
95
|
-
* @reject {Error}
|
|
96
|
-
*
|
|
97
|
-
* @example
|
|
98
|
-
* contxtSdk.facilities.costCenters
|
|
99
|
-
* .create({
|
|
100
|
-
* decsription: 'Cost center number 1',
|
|
101
|
-
* name: 'North Carolina, USA',
|
|
102
|
-
* organizationId: '61f5fe1d-d202-4ae7-af76-8f37f5bbeec5'
|
|
103
|
-
* })
|
|
104
|
-
* .then((costCenter) => console.log(costCenter))
|
|
105
|
-
* .catch((err) => console.log(err));
|
|
106
|
-
*/
|
|
107
|
-
create(costCenter = {}) {
|
|
108
|
-
const requiredFields = ['name', 'organizationId'];
|
|
109
|
-
|
|
110
|
-
for (let i = 0; i < requiredFields.length; i++) {
|
|
111
|
-
const field = requiredFields[i];
|
|
112
|
-
|
|
113
|
-
if (!costCenter[field]) {
|
|
114
|
-
return Promise.reject(
|
|
115
|
-
new Error(`A ${field} is required to create a new cost center.`)
|
|
116
|
-
);
|
|
117
|
-
}
|
|
118
|
-
}
|
|
119
|
-
|
|
120
|
-
return this._request
|
|
121
|
-
.post(`${this._baseUrl}/costcenters`, toSnakeCase(costCenter))
|
|
122
|
-
.then((costCenter) => toCamelCase(costCenter));
|
|
123
|
-
}
|
|
124
|
-
|
|
125
|
-
/**
|
|
126
|
-
* Delete a cost center
|
|
127
|
-
*
|
|
128
|
-
* API Endpoint: '/costcenters/:costCenterId'
|
|
129
|
-
* Method: DELETE
|
|
130
|
-
*
|
|
131
|
-
* @param {string} costCenterId The ID of the cost center (formatted as a UUID)
|
|
132
|
-
*
|
|
133
|
-
* @returns {Promise}
|
|
134
|
-
* @fulfill {undefined}
|
|
135
|
-
* @reject {Error}
|
|
136
|
-
*
|
|
137
|
-
* @example
|
|
138
|
-
* contxtSdk.facilities.costCenters.delete(
|
|
139
|
-
* 'e4fec739-56aa-4b50-8dab-e9d6b9c91a5d'
|
|
140
|
-
* );
|
|
141
|
-
*/
|
|
142
|
-
delete(costCenterId) {
|
|
143
|
-
if (!costCenterId) {
|
|
144
|
-
return Promise.reject(
|
|
145
|
-
new Error('A cost center id is required for deleting a cost center.')
|
|
146
|
-
);
|
|
147
|
-
}
|
|
148
|
-
|
|
149
|
-
return this._request.delete(`${this._baseUrl}/costcenters/${costCenterId}`);
|
|
150
|
-
}
|
|
151
|
-
|
|
152
|
-
/**
|
|
153
|
-
* Get a listing of all cost centers
|
|
154
|
-
*
|
|
155
|
-
* API Endpoint: '/costcenters'
|
|
156
|
-
* METHOD: GET
|
|
157
|
-
*
|
|
158
|
-
* @returns {Promise}
|
|
159
|
-
* @fulfill {CostCenter[]}
|
|
160
|
-
* @reject {Error}
|
|
161
|
-
*
|
|
162
|
-
* @example
|
|
163
|
-
* contxtSdk.facilities.costCenters
|
|
164
|
-
* .getAll()
|
|
165
|
-
* .then((costCenters) => console.log(costCenters))
|
|
166
|
-
* .catch((err) => console.log(err));
|
|
167
|
-
*/
|
|
168
|
-
getAll() {
|
|
169
|
-
return this._request
|
|
170
|
-
.get(`${this._baseUrl}/costcenters`)
|
|
171
|
-
.then((costCenters) => toCamelCase(costCenters));
|
|
172
|
-
}
|
|
173
|
-
|
|
174
|
-
/**
|
|
175
|
-
* Get a listing of all cost centers for an organization
|
|
176
|
-
*
|
|
177
|
-
* API Endpoint: '/organizations/:organizationId/costcenters'
|
|
178
|
-
* METHOD: GET
|
|
179
|
-
*
|
|
180
|
-
* @param {string} organizationId The ID of the organization (formatted as a UUID)
|
|
181
|
-
*
|
|
182
|
-
* @returns {Promise}
|
|
183
|
-
* @fulfill {CostCenter[]}
|
|
184
|
-
* @reject {Error}
|
|
185
|
-
*
|
|
186
|
-
* @example
|
|
187
|
-
* contxtSdk.facilities.costCenters
|
|
188
|
-
* .getAllByOrganizationId('59270c25-4de9-4b22-8e0b-ab287ac344ce')
|
|
189
|
-
* .then((costCenters) => console.log(costCenters))
|
|
190
|
-
* .catch((err) => console.log(err));
|
|
191
|
-
*/
|
|
192
|
-
getAllByOrganizationId(organizationId) {
|
|
193
|
-
if (!organizationId) {
|
|
194
|
-
return Promise.reject(
|
|
195
|
-
new Error(
|
|
196
|
-
"An organization id is required for getting a list of an organization's cost centers."
|
|
197
|
-
)
|
|
198
|
-
);
|
|
199
|
-
}
|
|
200
|
-
|
|
201
|
-
return this._request
|
|
202
|
-
.get(`${this._baseUrl}/organizations/${organizationId}/costcenters`)
|
|
203
|
-
.then((costCenters) => toCamelCase(costCenters));
|
|
204
|
-
}
|
|
205
|
-
|
|
206
|
-
/**
|
|
207
|
-
* Removes a facility from a cost center
|
|
208
|
-
*
|
|
209
|
-
* API Endpoint: '/costcenters/:costCenterId/facility/:facilityId'
|
|
210
|
-
* Method: DELETE
|
|
211
|
-
*
|
|
212
|
-
* @param {string} costCenterId UUID corresponding with a cost center
|
|
213
|
-
* @param {number} facilityId ID corresponding with the facility
|
|
214
|
-
*
|
|
215
|
-
* @returns {Promise}
|
|
216
|
-
* @fulfill {undefined}
|
|
217
|
-
* @reject {Error}
|
|
218
|
-
*
|
|
219
|
-
* @example
|
|
220
|
-
* contxtSdk.facilities.costCenters
|
|
221
|
-
* .removeFacility('b3dbaae3-25dd-475b-80dc-66296630a8d0', 4)
|
|
222
|
-
* .catch((err) => console.log(err));
|
|
223
|
-
*/
|
|
224
|
-
removeFacility(costCenterId, facilityId) {
|
|
225
|
-
let errorMsg;
|
|
226
|
-
|
|
227
|
-
if (!costCenterId) {
|
|
228
|
-
errorMsg =
|
|
229
|
-
'A costCenterId is required to remove a relationship between a cost center and a facility.';
|
|
230
|
-
} else if (!facilityId) {
|
|
231
|
-
errorMsg =
|
|
232
|
-
'A facilityId is required to remove a relationship between a cost center and a facility.';
|
|
233
|
-
}
|
|
234
|
-
|
|
235
|
-
if (errorMsg) {
|
|
236
|
-
return Promise.reject(new Error(errorMsg));
|
|
237
|
-
}
|
|
238
|
-
|
|
239
|
-
return this._request.delete(
|
|
240
|
-
`${this._baseUrl}/costcenters/${costCenterId}/facility/${facilityId}`
|
|
241
|
-
);
|
|
242
|
-
}
|
|
243
|
-
|
|
244
|
-
/**
|
|
245
|
-
* Updates an existing cost center
|
|
246
|
-
*
|
|
247
|
-
* API Endpoint: '/costcenters/:costCenterId'
|
|
248
|
-
* Method: PUT
|
|
249
|
-
*
|
|
250
|
-
* @param {String} costCenterId
|
|
251
|
-
* @param {Object} update
|
|
252
|
-
* @param {string} [update.description]
|
|
253
|
-
* @param {string} [update.name]
|
|
254
|
-
*
|
|
255
|
-
* @returns {Promise}
|
|
256
|
-
* @fulfill {FacilityGrouping} Information about the updated cost center
|
|
257
|
-
* @reject {Error}
|
|
258
|
-
*
|
|
259
|
-
* @example
|
|
260
|
-
* contxtSdk.facilities.costCenters
|
|
261
|
-
* .update({
|
|
262
|
-
* description: 'Refrigeration compressors throughout the facility',
|
|
263
|
-
* name: 'Compressors',
|
|
264
|
-
* })
|
|
265
|
-
* .then((costCenter) => console.log(costCenter))
|
|
266
|
-
* .catch((err) => console.log(err));
|
|
267
|
-
*/
|
|
268
|
-
update(costCenterId, update) {
|
|
269
|
-
if (!costCenterId) {
|
|
270
|
-
return Promise.reject(
|
|
271
|
-
new Error('A cost center id is required to update a cost center.')
|
|
272
|
-
);
|
|
273
|
-
}
|
|
274
|
-
|
|
275
|
-
if (!update) {
|
|
276
|
-
return Promise.reject(
|
|
277
|
-
new Error('An update is required to update a cost center.')
|
|
278
|
-
);
|
|
279
|
-
}
|
|
280
|
-
|
|
281
|
-
if (!isPlainObject(update)) {
|
|
282
|
-
return Promise.reject(
|
|
283
|
-
new Error(
|
|
284
|
-
'The cost center update must be a well-formed object with the data you wish to update.'
|
|
285
|
-
)
|
|
286
|
-
);
|
|
287
|
-
}
|
|
288
|
-
|
|
289
|
-
return this._request
|
|
290
|
-
.put(`${this._baseUrl}/costcenters/${costCenterId}`, toSnakeCase(update))
|
|
291
|
-
.then((costCenter) => toCamelCase(costCenter));
|
|
292
|
-
}
|
|
293
|
-
}
|
|
294
|
-
|
|
295
|
-
export default CostCenters;
|