dalux-build-api 1.1.5 → 2.0.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/README.md +257 -187
- package/package.json +11 -4
- package/src/api/CompaniesApi.js +19 -12
- package/src/api/CompanyCatalogApi.js +22 -18
- package/src/api/FileAreasApi.js +14 -12
- package/src/api/FilesApi.js +11 -7
- package/src/api/FoldersApi.js +14 -12
- package/src/api/FormsApi.js +11 -6
- package/src/api/InspectionPlansApi.js +87 -9
- package/src/api/ProjectsApi.js +22 -18
- package/src/api/TasksApi.js +25 -10
- package/src/api/TestPlansApi.js +87 -9
- package/src/api/UsersApi.js +11 -6
- package/src/api/VersionSetsApi.js +20 -12
- package/src/api/WorkPackagesApi.js +7 -3
- package/src/browser.js +84 -0
- package/src/index.js +5 -0
- package/src/models/common.js +22 -0
- package/src/models/companies/index.js +14 -0
- package/src/models/companyCatalog/index.js +19 -0
- package/src/models/convert.js +44 -0
- package/src/models/fileAreas/index.js +20 -0
- package/src/models/fileRevisions/index.js +12 -0
- package/src/models/fileUpload/index.js +12 -0
- package/src/models/files/index.js +97 -0
- package/src/models/folders/index.js +20 -0
- package/src/models/forms/index.js +19 -0
- package/src/models/helpers.js +62 -0
- package/src/models/index.js +178 -0
- package/src/models/inspectionPlans/index.js +61 -0
- package/src/models/projectTemplates/index.js +11 -0
- package/src/models/projects/index.js +57 -0
- package/src/models/tasks/index.js +105 -0
- package/src/models/testPlans/index.js +61 -0
- package/src/models/users/index.js +29 -0
- package/src/models/versionSets/index.js +22 -0
- package/src/models/workPackages/index.js +19 -0
- package/src/next.js +89 -0
- package/LICENSE +0 -21
package/src/api/TasksApi.js
CHANGED
|
@@ -1,5 +1,15 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
|
+
const { convertToModel, convertToModelList } = require('../models/convert');
|
|
4
|
+
const {
|
|
5
|
+
TaskSchema,
|
|
6
|
+
TaskChangeSchema,
|
|
7
|
+
TasksListResponseSchema,
|
|
8
|
+
TaskResponseSchema,
|
|
9
|
+
TaskChangesSchema,
|
|
10
|
+
TaskAttachmentsListResponseSchema,
|
|
11
|
+
} = require('../models/tasks');
|
|
12
|
+
|
|
3
13
|
/**
|
|
4
14
|
* Build query params for GET /5.2/projects/.../tasks (OData).
|
|
5
15
|
* If params contains typeId and no $filter, expands to
|
|
@@ -39,8 +49,9 @@ class TasksApi {
|
|
|
39
49
|
* OData $filter on task type, or pass $filter (and other OData options) directly.
|
|
40
50
|
* @returns {Promise<object>}
|
|
41
51
|
*/
|
|
42
|
-
getProjectTasks(projectId, params = {}) {
|
|
43
|
-
|
|
52
|
+
async getProjectTasks(projectId, params = {}) {
|
|
53
|
+
const response = await this._client.get(`/5.2/projects/${projectId}/tasks`, normalizeTaskParams(params));
|
|
54
|
+
return convertToModel(response, TasksListResponseSchema, 'TasksListResponse');
|
|
44
55
|
}
|
|
45
56
|
|
|
46
57
|
/**
|
|
@@ -119,7 +130,7 @@ class TasksApi {
|
|
|
119
130
|
if (verbose) {
|
|
120
131
|
console.log(`Done. Total tasks retrieved: ${allItems.length}`);
|
|
121
132
|
}
|
|
122
|
-
return allItems;
|
|
133
|
+
return convertToModelList(allItems, TaskSchema, 'Task');
|
|
123
134
|
}
|
|
124
135
|
|
|
125
136
|
/**
|
|
@@ -129,8 +140,9 @@ class TasksApi {
|
|
|
129
140
|
* @param {string} taskId
|
|
130
141
|
* @returns {Promise<object>}
|
|
131
142
|
*/
|
|
132
|
-
getTask(projectId, taskId) {
|
|
133
|
-
|
|
143
|
+
async getTask(projectId, taskId) {
|
|
144
|
+
const response = await this._client.get(`/3.3/projects/${projectId}/tasks/${taskId}`);
|
|
145
|
+
return convertToModel(response, TaskResponseSchema, 'TaskResponse');
|
|
134
146
|
}
|
|
135
147
|
|
|
136
148
|
/**
|
|
@@ -140,8 +152,9 @@ class TasksApi {
|
|
|
140
152
|
* @param {object} [params] - Optional filters (e.g. updatedAfter)
|
|
141
153
|
* @returns {Promise<object>}
|
|
142
154
|
*/
|
|
143
|
-
getProjectTaskChanges(projectId, params = {}) {
|
|
144
|
-
|
|
155
|
+
async getProjectTaskChanges(projectId, params = {}) {
|
|
156
|
+
const response = await this._client.get(`/2.2/projects/${projectId}/tasks/changes`, params);
|
|
157
|
+
return convertToModel(response, TaskChangesSchema, 'TaskChanges');
|
|
145
158
|
}
|
|
146
159
|
|
|
147
160
|
/**
|
|
@@ -151,8 +164,9 @@ class TasksApi {
|
|
|
151
164
|
* @param {object} [params] - Optional filters (e.g. updatedAfter)
|
|
152
165
|
* @returns {Promise<object>}
|
|
153
166
|
*/
|
|
154
|
-
getProjectTaskAttachments(projectId, params = {}) {
|
|
155
|
-
|
|
167
|
+
async getProjectTaskAttachments(projectId, params = {}) {
|
|
168
|
+
const response = await this._client.get(`/1.1/projects/${projectId}/tasks/attachments`, params);
|
|
169
|
+
return convertToModel(response, TaskAttachmentsListResponseSchema, 'TaskAttachmentsListResponse');
|
|
156
170
|
}
|
|
157
171
|
|
|
158
172
|
/**
|
|
@@ -164,12 +178,13 @@ class TasksApi {
|
|
|
164
178
|
*/
|
|
165
179
|
async getAllProjectTaskChanges(projectId, params = {}, verbose = false) {
|
|
166
180
|
const { paginate } = require('../utils/pagination');
|
|
167
|
-
|
|
181
|
+
const raw = await paginate(
|
|
168
182
|
`/2.2/projects/${projectId}/tasks/changes`,
|
|
169
183
|
this._client,
|
|
170
184
|
params,
|
|
171
185
|
verbose,
|
|
172
186
|
);
|
|
187
|
+
return convertToModelList(raw, TaskChangeSchema, 'TaskChange');
|
|
173
188
|
}
|
|
174
189
|
}
|
|
175
190
|
|
package/src/api/TestPlansApi.js
CHANGED
|
@@ -1,5 +1,18 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
|
+
const { convertToModel, convertToModelList } = require('../models/convert');
|
|
4
|
+
const { paginate } = require('../utils/pagination');
|
|
5
|
+
const {
|
|
6
|
+
TestPlanSchema,
|
|
7
|
+
TestPlanItemSchema,
|
|
8
|
+
TestPlanItemZoneSchema,
|
|
9
|
+
TestPlanRegistrationSchema,
|
|
10
|
+
TestPlansListResponseSchema,
|
|
11
|
+
TestPlanItemsListResponseSchema,
|
|
12
|
+
TestPlanItemZonesListResponseSchema,
|
|
13
|
+
TestPlanRegistrationsListResponseSchema,
|
|
14
|
+
} = require('../models/testPlans');
|
|
15
|
+
|
|
3
16
|
/**
|
|
4
17
|
* API methods for test plans.
|
|
5
18
|
*/
|
|
@@ -16,10 +29,27 @@ class TestPlansApi {
|
|
|
16
29
|
* GET /1.2/projects/{projectId}/testPlans
|
|
17
30
|
* @param {string} projectId
|
|
18
31
|
* @param {object} [params]
|
|
19
|
-
* @
|
|
32
|
+
* @param {boolean} [fullResponse=false]
|
|
33
|
+
* @returns {Promise<object[]|object>}
|
|
20
34
|
*/
|
|
21
|
-
listTestPlans(projectId, params = {}) {
|
|
22
|
-
|
|
35
|
+
async listTestPlans(projectId, params = {}, fullResponse = false) {
|
|
36
|
+
const response = await this._client.get(`/1.2/projects/${projectId}/testPlans`, params);
|
|
37
|
+
const result = convertToModel(
|
|
38
|
+
response,
|
|
39
|
+
TestPlansListResponseSchema,
|
|
40
|
+
'TestPlansListResponse',
|
|
41
|
+
);
|
|
42
|
+
return fullResponse ? result : (result?.items || []);
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
async getAllTestPlans(projectId, params = {}, verbose = false) {
|
|
46
|
+
const items = await paginate(
|
|
47
|
+
`/1.2/projects/${projectId}/testPlans`,
|
|
48
|
+
this._client,
|
|
49
|
+
params,
|
|
50
|
+
verbose,
|
|
51
|
+
);
|
|
52
|
+
return convertToModelList(items, TestPlanSchema, 'TestPlan');
|
|
23
53
|
}
|
|
24
54
|
|
|
25
55
|
/**
|
|
@@ -29,8 +59,24 @@ class TestPlansApi {
|
|
|
29
59
|
* @param {object} [params]
|
|
30
60
|
* @returns {Promise<object>}
|
|
31
61
|
*/
|
|
32
|
-
listTestPlanItems(projectId, params = {}) {
|
|
33
|
-
|
|
62
|
+
async listTestPlanItems(projectId, params = {}, fullResponse = false) {
|
|
63
|
+
const response = await this._client.get(`/1.1/projects/${projectId}/testPlanItems`, params);
|
|
64
|
+
const result = convertToModel(
|
|
65
|
+
response,
|
|
66
|
+
TestPlanItemsListResponseSchema,
|
|
67
|
+
'TestPlanItemsListResponse',
|
|
68
|
+
);
|
|
69
|
+
return fullResponse ? result : (result?.items || []);
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
async getAllTestPlanItems(projectId, params = {}, verbose = false) {
|
|
73
|
+
const items = await paginate(
|
|
74
|
+
`/1.1/projects/${projectId}/testPlanItems`,
|
|
75
|
+
this._client,
|
|
76
|
+
params,
|
|
77
|
+
verbose,
|
|
78
|
+
);
|
|
79
|
+
return convertToModelList(items, TestPlanItemSchema, 'TestPlanItem');
|
|
34
80
|
}
|
|
35
81
|
|
|
36
82
|
/**
|
|
@@ -40,8 +86,24 @@ class TestPlansApi {
|
|
|
40
86
|
* @param {object} [params]
|
|
41
87
|
* @returns {Promise<object>}
|
|
42
88
|
*/
|
|
43
|
-
listTestPlanItemZones(projectId, params = {}) {
|
|
44
|
-
|
|
89
|
+
async listTestPlanItemZones(projectId, params = {}, fullResponse = false) {
|
|
90
|
+
const response = await this._client.get(`/1.1/projects/${projectId}/testPlanItemZones`, params);
|
|
91
|
+
const result = convertToModel(
|
|
92
|
+
response,
|
|
93
|
+
TestPlanItemZonesListResponseSchema,
|
|
94
|
+
'TestPlanItemZonesListResponse',
|
|
95
|
+
);
|
|
96
|
+
return fullResponse ? result : (result?.items || []);
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
async getAllTestPlanItemZones(projectId, params = {}, verbose = false) {
|
|
100
|
+
const items = await paginate(
|
|
101
|
+
`/1.1/projects/${projectId}/testPlanItemZones`,
|
|
102
|
+
this._client,
|
|
103
|
+
params,
|
|
104
|
+
verbose,
|
|
105
|
+
);
|
|
106
|
+
return convertToModelList(items, TestPlanItemZoneSchema, 'TestPlanItemZone');
|
|
45
107
|
}
|
|
46
108
|
|
|
47
109
|
/**
|
|
@@ -51,8 +113,24 @@ class TestPlansApi {
|
|
|
51
113
|
* @param {object} [params]
|
|
52
114
|
* @returns {Promise<object>}
|
|
53
115
|
*/
|
|
54
|
-
listTestPlanRegistrations(projectId, params = {}) {
|
|
55
|
-
|
|
116
|
+
async listTestPlanRegistrations(projectId, params = {}, fullResponse = false) {
|
|
117
|
+
const response = await this._client.get(`/1.1/projects/${projectId}/testPlanRegistrations`, params);
|
|
118
|
+
const result = convertToModel(
|
|
119
|
+
response,
|
|
120
|
+
TestPlanRegistrationsListResponseSchema,
|
|
121
|
+
'TestPlanRegistrationsListResponse',
|
|
122
|
+
);
|
|
123
|
+
return fullResponse ? result : (result?.items || []);
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
async getAllTestPlanRegistrations(projectId, params = {}, verbose = false) {
|
|
127
|
+
const items = await paginate(
|
|
128
|
+
`/1.1/projects/${projectId}/testPlanRegistrations`,
|
|
129
|
+
this._client,
|
|
130
|
+
params,
|
|
131
|
+
verbose,
|
|
132
|
+
);
|
|
133
|
+
return convertToModelList(items, TestPlanRegistrationSchema, 'TestPlanRegistration');
|
|
56
134
|
}
|
|
57
135
|
}
|
|
58
136
|
|
package/src/api/UsersApi.js
CHANGED
|
@@ -1,5 +1,8 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
|
+
const { convertToModel } = require('../models/convert');
|
|
4
|
+
const { UserResponseSchema, UsersListResponseSchema } = require('../models/users');
|
|
5
|
+
|
|
3
6
|
/**
|
|
4
7
|
* API methods for users.
|
|
5
8
|
*/
|
|
@@ -15,10 +18,11 @@ class UsersApi {
|
|
|
15
18
|
* Get a specific user.
|
|
16
19
|
* GET /1.1/users/{userId}
|
|
17
20
|
* @param {string} userId
|
|
18
|
-
* @returns {Promise<object>}
|
|
21
|
+
* @returns {Promise<object>} UserResponse ({ data: User, links? })
|
|
19
22
|
*/
|
|
20
|
-
getUser(userId) {
|
|
21
|
-
|
|
23
|
+
async getUser(userId) {
|
|
24
|
+
const response = await this._client.get(`/1.1/users/${userId}`);
|
|
25
|
+
return convertToModel(response, UserResponseSchema, 'UserResponse');
|
|
22
26
|
}
|
|
23
27
|
|
|
24
28
|
/**
|
|
@@ -26,10 +30,11 @@ class UsersApi {
|
|
|
26
30
|
* GET /1.2/projects/{projectId}/users
|
|
27
31
|
* @param {string} projectId
|
|
28
32
|
* @param {object} [params]
|
|
29
|
-
* @returns {Promise<object>}
|
|
33
|
+
* @returns {Promise<object>} UsersListResponse ({ items: ProjectUser[], metadata?, links? })
|
|
30
34
|
*/
|
|
31
|
-
listProjectUsers(projectId, params = {}) {
|
|
32
|
-
|
|
35
|
+
async listProjectUsers(projectId, params = {}) {
|
|
36
|
+
const response = await this._client.get(`/1.2/projects/${projectId}/users`, params);
|
|
37
|
+
return convertToModel(response, UsersListResponseSchema, 'UsersListResponse');
|
|
33
38
|
}
|
|
34
39
|
|
|
35
40
|
/**
|
|
@@ -1,5 +1,9 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
|
+
const { convertToModel } = require('../models/convert');
|
|
4
|
+
const { VersionSetsListResponseSchema, VersionSetResponseSchema } = require('../models/versionSets');
|
|
5
|
+
const { FilesListResponseSchema } = require('../models/files');
|
|
6
|
+
|
|
3
7
|
/**
|
|
4
8
|
* API methods for version sets.
|
|
5
9
|
*/
|
|
@@ -16,10 +20,11 @@ class VersionSetsApi {
|
|
|
16
20
|
* GET /2.1/projects/{projectId}/version_sets
|
|
17
21
|
* @param {string} projectId
|
|
18
22
|
* @param {object} [params]
|
|
19
|
-
* @returns {Promise<object>}
|
|
23
|
+
* @returns {Promise<object>} VersionSetsListResponse ({ items: VersionSet[], metadata?, links? })
|
|
20
24
|
*/
|
|
21
|
-
getVersionSets(projectId, params = {}) {
|
|
22
|
-
|
|
25
|
+
async getVersionSets(projectId, params = {}) {
|
|
26
|
+
const response = await this._client.get(`/2.1/projects/${projectId}/version_sets`, params);
|
|
27
|
+
return convertToModel(response, VersionSetsListResponseSchema, 'VersionSetsListResponse');
|
|
23
28
|
}
|
|
24
29
|
|
|
25
30
|
/**
|
|
@@ -27,10 +32,11 @@ class VersionSetsApi {
|
|
|
27
32
|
* GET /2.0/projects/{projectId}/version_sets/{versionSetId}
|
|
28
33
|
* @param {string} projectId
|
|
29
34
|
* @param {string} versionSetId
|
|
30
|
-
* @returns {Promise<object>}
|
|
35
|
+
* @returns {Promise<object>} VersionSetResponse ({ data: VersionSet, links? })
|
|
31
36
|
*/
|
|
32
|
-
getVersionSet(projectId, versionSetId) {
|
|
33
|
-
|
|
37
|
+
async getVersionSet(projectId, versionSetId) {
|
|
38
|
+
const response = await this._client.get(`/2.0/projects/${projectId}/version_sets/${versionSetId}`);
|
|
39
|
+
return convertToModel(response, VersionSetResponseSchema, 'VersionSetResponse');
|
|
34
40
|
}
|
|
35
41
|
|
|
36
42
|
/**
|
|
@@ -39,13 +45,14 @@ class VersionSetsApi {
|
|
|
39
45
|
* @param {string} projectId
|
|
40
46
|
* @param {string} fileAreaId
|
|
41
47
|
* @param {object} [params]
|
|
42
|
-
* @returns {Promise<object>}
|
|
48
|
+
* @returns {Promise<object>} VersionSetsListResponse
|
|
43
49
|
*/
|
|
44
|
-
listFileAreaVersionSets(projectId, fileAreaId, params = {}) {
|
|
45
|
-
|
|
50
|
+
async listFileAreaVersionSets(projectId, fileAreaId, params = {}) {
|
|
51
|
+
const response = await this._client.get(
|
|
46
52
|
`/2.1/projects/${projectId}/file_areas/${fileAreaId}/version_sets`,
|
|
47
53
|
params,
|
|
48
54
|
);
|
|
55
|
+
return convertToModel(response, VersionSetsListResponseSchema, 'VersionSetsListResponse');
|
|
49
56
|
}
|
|
50
57
|
|
|
51
58
|
/**
|
|
@@ -54,13 +61,14 @@ class VersionSetsApi {
|
|
|
54
61
|
* @param {string} projectId
|
|
55
62
|
* @param {string} versionSetId
|
|
56
63
|
* @param {object} [params]
|
|
57
|
-
* @returns {Promise<object>}
|
|
64
|
+
* @returns {Promise<object>} FilesListResponse (cross-endpoint reuse of the Files model, matches Python)
|
|
58
65
|
*/
|
|
59
|
-
listVersionSetFiles(projectId, versionSetId, params = {}) {
|
|
60
|
-
|
|
66
|
+
async listVersionSetFiles(projectId, versionSetId, params = {}) {
|
|
67
|
+
const response = await this._client.get(
|
|
61
68
|
`/3.0/projects/${projectId}/version_sets/${versionSetId}/files`,
|
|
62
69
|
params,
|
|
63
70
|
);
|
|
71
|
+
return convertToModel(response, FilesListResponseSchema, 'FilesListResponse');
|
|
64
72
|
}
|
|
65
73
|
}
|
|
66
74
|
|
|
@@ -1,5 +1,8 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
|
+
const { convertToModel } = require('../models/convert');
|
|
4
|
+
const { WorkPackagesListResponseSchema } = require('../models/workPackages');
|
|
5
|
+
|
|
3
6
|
/**
|
|
4
7
|
* API methods for work packages on a project.
|
|
5
8
|
*/
|
|
@@ -16,10 +19,11 @@ class WorkPackagesApi {
|
|
|
16
19
|
* GET /1.0/projects/{projectId}/workpackages
|
|
17
20
|
* @param {string} projectId
|
|
18
21
|
* @param {object} [params]
|
|
19
|
-
* @returns {Promise<object>}
|
|
22
|
+
* @returns {Promise<object>} WorkPackagesListResponse ({ items: WorkPackage[], metadata?, links? })
|
|
20
23
|
*/
|
|
21
|
-
listWorkPackages(projectId, params = {}) {
|
|
22
|
-
|
|
24
|
+
async listWorkPackages(projectId, params = {}) {
|
|
25
|
+
const response = await this._client.get(`/1.0/projects/${projectId}/workpackages`, params);
|
|
26
|
+
return convertToModel(response, WorkPackagesListResponseSchema, 'WorkPackagesListResponse');
|
|
23
27
|
}
|
|
24
28
|
}
|
|
25
29
|
|
package/src/browser.js
ADDED
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
const RESOURCES = [
|
|
4
|
+
'projects',
|
|
5
|
+
'companies',
|
|
6
|
+
'companyCatalog',
|
|
7
|
+
'fileAreas',
|
|
8
|
+
'fileRevisions',
|
|
9
|
+
'fileUpload',
|
|
10
|
+
'files',
|
|
11
|
+
'folders',
|
|
12
|
+
'forms',
|
|
13
|
+
'inspectionPlans',
|
|
14
|
+
'projectTemplates',
|
|
15
|
+
'tasks',
|
|
16
|
+
'testPlans',
|
|
17
|
+
'users',
|
|
18
|
+
'versionSets',
|
|
19
|
+
'workPackages',
|
|
20
|
+
];
|
|
21
|
+
|
|
22
|
+
class DaluxProxyError extends Error {
|
|
23
|
+
constructor(message, { name = 'DaluxProxyError', status, details } = {}) {
|
|
24
|
+
super(message);
|
|
25
|
+
this.name = name;
|
|
26
|
+
this.status = status;
|
|
27
|
+
this.details = details;
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
/**
|
|
32
|
+
* Create a browser-safe Dalux client backed by a same-origin server route.
|
|
33
|
+
* The Dalux API key remains on the server; this client never accepts one.
|
|
34
|
+
*
|
|
35
|
+
* @param {object} [options]
|
|
36
|
+
* @param {string} [options.url='/api/dalux']
|
|
37
|
+
* @param {typeof fetch} [options.fetch]
|
|
38
|
+
* @param {Record<string, string>} [options.headers]
|
|
39
|
+
*/
|
|
40
|
+
function createBrowserClient({ url = '/api/dalux', fetch: fetchImpl, headers = {} } = {}) {
|
|
41
|
+
const request = fetchImpl || globalThis.fetch;
|
|
42
|
+
if (typeof request !== 'function') {
|
|
43
|
+
throw new Error('A fetch implementation is required');
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
const invoke = async (resource, method, args) => {
|
|
47
|
+
const response = await request(url, {
|
|
48
|
+
method: 'POST',
|
|
49
|
+
headers: { 'Content-Type': 'application/json', ...headers },
|
|
50
|
+
body: JSON.stringify({ resource, method, args }),
|
|
51
|
+
});
|
|
52
|
+
|
|
53
|
+
let payload;
|
|
54
|
+
try {
|
|
55
|
+
payload = await response.json();
|
|
56
|
+
} catch {
|
|
57
|
+
throw new DaluxProxyError(`Dalux proxy returned HTTP ${response.status} without JSON`, {
|
|
58
|
+
status: response.status,
|
|
59
|
+
});
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
if (!response.ok || !payload.ok) {
|
|
63
|
+
const error = payload.error || {};
|
|
64
|
+
throw new DaluxProxyError(error.message || `Dalux proxy returned HTTP ${response.status}`, {
|
|
65
|
+
name: error.name,
|
|
66
|
+
status: response.status,
|
|
67
|
+
details: error.details,
|
|
68
|
+
});
|
|
69
|
+
}
|
|
70
|
+
return payload.data;
|
|
71
|
+
};
|
|
72
|
+
|
|
73
|
+
return Object.fromEntries(RESOURCES.map((resource) => [
|
|
74
|
+
resource,
|
|
75
|
+
new Proxy({}, {
|
|
76
|
+
get(_target, method) {
|
|
77
|
+
if (typeof method !== 'string' || method === 'then') return undefined;
|
|
78
|
+
return (...args) => invoke(resource, method, args);
|
|
79
|
+
},
|
|
80
|
+
}),
|
|
81
|
+
]));
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
module.exports = { createBrowserClient, DaluxProxyError };
|
package/src/index.js
CHANGED
|
@@ -39,6 +39,8 @@ const {
|
|
|
39
39
|
resolveFolderIdFromNamedPath,
|
|
40
40
|
} = require('./utils');
|
|
41
41
|
|
|
42
|
+
const models = require('./models');
|
|
43
|
+
|
|
42
44
|
/**
|
|
43
45
|
* Create a fully configured Dalux Build API client.
|
|
44
46
|
*
|
|
@@ -125,4 +127,7 @@ module.exports = {
|
|
|
125
127
|
validateFolderId,
|
|
126
128
|
resolveFileAreaByName,
|
|
127
129
|
resolveFolderIdFromNamedPath,
|
|
130
|
+
// Data models (zod schemas) - both `models.FolderSchema` and top-level `FolderSchema` work
|
|
131
|
+
models,
|
|
132
|
+
...models,
|
|
128
133
|
};
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
const { z } = require('zod');
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* API response link. Mirrors python/dalux_build/models/common.py::Link.
|
|
7
|
+
*/
|
|
8
|
+
const LinkSchema = z.object({
|
|
9
|
+
rel: z.string(),
|
|
10
|
+
href: z.string(),
|
|
11
|
+
method: z.string().nullish(),
|
|
12
|
+
});
|
|
13
|
+
|
|
14
|
+
/**
|
|
15
|
+
* Response metadata with pagination info. Mirrors common.py::Metadata.
|
|
16
|
+
*/
|
|
17
|
+
const MetadataSchema = z.object({
|
|
18
|
+
totalItems: z.number().nullish(),
|
|
19
|
+
totalRemainingItems: z.number().nullish(),
|
|
20
|
+
});
|
|
21
|
+
|
|
22
|
+
module.exports = { LinkSchema, MetadataSchema };
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
const { ProjectCompanySchema } = require('../projects');
|
|
4
|
+
const { listResponseSchema, singleResponseSchema } = require('../helpers');
|
|
5
|
+
|
|
6
|
+
/** Mirrors models/companies/models.py, which re-exports ProjectCompany. */
|
|
7
|
+
const CompaniesListResponseSchema = listResponseSchema(ProjectCompanySchema);
|
|
8
|
+
const CompanyResponseSchema = singleResponseSchema(ProjectCompanySchema);
|
|
9
|
+
|
|
10
|
+
module.exports = {
|
|
11
|
+
ProjectCompanySchema,
|
|
12
|
+
CompaniesListResponseSchema,
|
|
13
|
+
CompanyResponseSchema,
|
|
14
|
+
};
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
const { z } = require('zod');
|
|
4
|
+
const { listResponseSchema, singleResponseSchema } = require('../helpers');
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* Mirrors models/company_catalog/responses.py. These are exported for name
|
|
8
|
+
* parity but, like their Python counterparts, are NOT what the API layer
|
|
9
|
+
* actually uses — company_catalog.py's get_companies/get_company return
|
|
10
|
+
* CompaniesListResponse/CompanyResponse (typed ProjectCompany) instead.
|
|
11
|
+
* See src/api/CompanyCatalogApi.js.
|
|
12
|
+
*/
|
|
13
|
+
const CompanyCatalogListResponseSchema = listResponseSchema(z.any());
|
|
14
|
+
const CompanyCatalogResponseSchema = singleResponseSchema(z.any());
|
|
15
|
+
|
|
16
|
+
module.exports = {
|
|
17
|
+
CompanyCatalogListResponseSchema,
|
|
18
|
+
CompanyCatalogResponseSchema,
|
|
19
|
+
};
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
const { z } = require('zod');
|
|
4
|
+
const { ValidationError } = require('../utils/errors');
|
|
5
|
+
const { unwrapData } = require('./helpers');
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* Validate and convert a raw API response into a typed model, throwing a
|
|
9
|
+
* ValidationError if the response doesn't match `schema`. Mirrors
|
|
10
|
+
* response_converter.py::convert_to_model, without its legacy-compat
|
|
11
|
+
* fallback branches (the JS test suite ships schema-valid fixtures).
|
|
12
|
+
* @param {*} response
|
|
13
|
+
* @param {import('zod').ZodTypeAny} schema
|
|
14
|
+
* @param {string} [schemaName]
|
|
15
|
+
* @returns {*}
|
|
16
|
+
*/
|
|
17
|
+
function convertToModel(response, schema, schemaName = 'model') {
|
|
18
|
+
if (response === null || response === undefined) return null;
|
|
19
|
+
try {
|
|
20
|
+
return schema.parse(response);
|
|
21
|
+
} catch (err) {
|
|
22
|
+
if (err instanceof z.ZodError) {
|
|
23
|
+
throw new ValidationError(`Failed to convert response to ${schemaName}: ${err.message}`);
|
|
24
|
+
}
|
|
25
|
+
throw err;
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
/**
|
|
30
|
+
* Validate and convert a list of raw items into typed models.
|
|
31
|
+
* Used by get_all_* pagination methods, which convert each item after
|
|
32
|
+
* pagination has already collected the raw list.
|
|
33
|
+
* @param {Array} items
|
|
34
|
+
* @param {import('zod').ZodTypeAny} itemSchema
|
|
35
|
+
* @param {string} [schemaName]
|
|
36
|
+
* @returns {Array}
|
|
37
|
+
*/
|
|
38
|
+
function convertToModelList(items, itemSchema, schemaName = 'model') {
|
|
39
|
+
if (!Array.isArray(items)) return [];
|
|
40
|
+
const wrapped = unwrapData(itemSchema);
|
|
41
|
+
return items.map((item) => convertToModel(item, wrapped, schemaName));
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
module.exports = { convertToModel, convertToModelList };
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
const { z } = require('zod');
|
|
4
|
+
const { listResponseSchema, singleResponseSchema } = require('../helpers');
|
|
5
|
+
|
|
6
|
+
/** Mirrors models/file_areas/models.py::FileArea (all fields required). */
|
|
7
|
+
const FileAreaSchema = z.object({
|
|
8
|
+
fileAreaId: z.string(),
|
|
9
|
+
fileAreaName: z.string(),
|
|
10
|
+
fileAreaType: z.string(),
|
|
11
|
+
});
|
|
12
|
+
|
|
13
|
+
const FileAreasListResponseSchema = listResponseSchema(FileAreaSchema);
|
|
14
|
+
const FileAreaResponseSchema = singleResponseSchema(FileAreaSchema);
|
|
15
|
+
|
|
16
|
+
module.exports = {
|
|
17
|
+
FileAreaSchema,
|
|
18
|
+
FileAreasListResponseSchema,
|
|
19
|
+
FileAreaResponseSchema,
|
|
20
|
+
};
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
const { z } = require('zod');
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* Mirrors models/file_revisions/models.py::FileRevision — an empty
|
|
7
|
+
* placeholder in Python too (get_file_revision_content returns raw
|
|
8
|
+
* binary/content in both packages, so there's nothing to validate).
|
|
9
|
+
*/
|
|
10
|
+
const FileRevisionSchema = z.object({}).passthrough();
|
|
11
|
+
|
|
12
|
+
module.exports = { FileRevisionSchema };
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
const { z } = require('zod');
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* Mirrors models/file_upload/models.py::FileUpload — empty placeholder in
|
|
7
|
+
* Python too; upload/part/finalize responses are provider-specific and
|
|
8
|
+
* stay raw in both packages.
|
|
9
|
+
*/
|
|
10
|
+
const FileUploadSchema = z.object({}).passthrough();
|
|
11
|
+
|
|
12
|
+
module.exports = { FileUploadSchema };
|