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/README.md
CHANGED
|
@@ -1,17 +1,11 @@
|
|
|
1
|
-
# Dalux Build API
|
|
1
|
+
# Dalux Build API – Node.js Client
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
A lightweight Node.js client for the [Dalux Build REST API](https://app.swaggerhub.com/apis-docs/Dalux/DaluxBuild-api/4.14).
|
|
4
4
|
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
---
|
|
11
|
-
|
|
12
|
-
# Node.js Client
|
|
13
|
-
|
|
14
|
-
A lightweight Node.js client for the Dalux Build REST API.
|
|
5
|
+
See the [repo root README](../README.md) for the Python client
|
|
6
|
+
(`dalux-build`) and the [webhook server](../webhook-server/README.md) built
|
|
7
|
+
on it — the two clients are versioned, tested, and released together; see
|
|
8
|
+
[../CONTRIBUTING.md](../CONTRIBUTING.md).
|
|
15
9
|
|
|
16
10
|
## Requirements
|
|
17
11
|
|
|
@@ -20,7 +14,7 @@ A lightweight Node.js client for the Dalux Build REST API.
|
|
|
20
14
|
## Installation
|
|
21
15
|
|
|
22
16
|
```bash
|
|
23
|
-
npm install
|
|
17
|
+
npm install dalux-build-api
|
|
24
18
|
```
|
|
25
19
|
|
|
26
20
|
## Getting Started
|
|
@@ -31,34 +25,84 @@ To access the API you need:
|
|
|
31
25
|
2. An **API key** — managed via _Settings › Integrations › API Identities_ inside the Dalux Build UI.
|
|
32
26
|
|
|
33
27
|
```js
|
|
34
|
-
const { createClient } = require(
|
|
28
|
+
const { createClient } = require("dalux-build-api");
|
|
35
29
|
|
|
36
30
|
const dalux = createClient({
|
|
37
|
-
baseUrl:
|
|
38
|
-
apiKey:
|
|
31
|
+
baseUrl: "https://<your-company>.dalux.com/api",
|
|
32
|
+
apiKey: "YOUR_API_KEY",
|
|
39
33
|
});
|
|
40
34
|
```
|
|
41
35
|
|
|
42
36
|
The returned object exposes one namespace per API group (see [API Reference](#api-reference) below).
|
|
43
37
|
|
|
38
|
+
## Next.js (browser-safe, no CORS)
|
|
39
|
+
|
|
40
|
+
Dalux API keys must stay server-side, and CORS is controlled by the Dalux API rather than this SDK.
|
|
41
|
+
For Client Components, use the package's same-origin Next.js adapter: the browser calls your own
|
|
42
|
+
App Router endpoint, and that endpoint uses the regular Dalux client on the server.
|
|
43
|
+
|
|
44
|
+
```js
|
|
45
|
+
// app/api/dalux/route.js
|
|
46
|
+
import { createClient } from "dalux-build-api";
|
|
47
|
+
import { createDaluxRouteHandler } from "dalux-build-api/next";
|
|
48
|
+
import { getCurrentUser } from "@/lib/auth";
|
|
49
|
+
|
|
50
|
+
const dalux = createClient({
|
|
51
|
+
baseUrl: process.env.DALUX_BASE_URL,
|
|
52
|
+
apiKey: process.env.DALUX_API_KEY,
|
|
53
|
+
});
|
|
54
|
+
|
|
55
|
+
export const POST = createDaluxRouteHandler({
|
|
56
|
+
client: dalux,
|
|
57
|
+
// Required: expose only the methods this application needs.
|
|
58
|
+
allowedMethods: {
|
|
59
|
+
projects: ["listProjects", "getProject"],
|
|
60
|
+
tasks: ["getProjectTasks", "getAllProjectTasks"],
|
|
61
|
+
},
|
|
62
|
+
// Recommended: connect this to your application's session/authorization.
|
|
63
|
+
authorize: async (request) => Boolean(await getCurrentUser(request)),
|
|
64
|
+
});
|
|
65
|
+
```
|
|
66
|
+
|
|
67
|
+
```js
|
|
68
|
+
// app/projects/Projects.jsx
|
|
69
|
+
"use client";
|
|
70
|
+
|
|
71
|
+
import { createBrowserClient } from "dalux-build-api/browser";
|
|
72
|
+
|
|
73
|
+
const dalux = createBrowserClient({ url: "/api/dalux" });
|
|
74
|
+
|
|
75
|
+
export async function loadProjects() {
|
|
76
|
+
return dalux.projects.listProjects();
|
|
77
|
+
}
|
|
78
|
+
```
|
|
79
|
+
|
|
80
|
+
The browser entry contains no Axios, Node.js filesystem modules, base URL, or API key. Calls use
|
|
81
|
+
same-origin `fetch`, so the browser does not make a cross-origin Dalux request. Write methods are
|
|
82
|
+
supported only when you explicitly add them to `allowedMethods`; protect the route with your app's
|
|
83
|
+
authorization before exposing them.
|
|
84
|
+
|
|
44
85
|
### Examples
|
|
45
86
|
|
|
46
87
|
**List all projects**
|
|
88
|
+
|
|
47
89
|
```js
|
|
48
90
|
const projects = await dalux.projects.listProjects();
|
|
49
91
|
console.log(projects);
|
|
50
92
|
```
|
|
51
93
|
|
|
52
94
|
**Get a specific project**
|
|
95
|
+
|
|
53
96
|
```js
|
|
54
|
-
const project = await dalux.projects.getProject(
|
|
97
|
+
const project = await dalux.projects.getProject("my-project-id");
|
|
55
98
|
console.log(project);
|
|
56
99
|
```
|
|
57
100
|
|
|
58
101
|
**List tasks on a project**
|
|
102
|
+
|
|
59
103
|
```js
|
|
60
|
-
const tasks = await dalux.tasks.getProjectTasks(
|
|
61
|
-
updatedAfter:
|
|
104
|
+
const tasks = await dalux.tasks.getProjectTasks("my-project-id", {
|
|
105
|
+
updatedAfter: "2024-01-01",
|
|
62
106
|
});
|
|
63
107
|
console.log(tasks);
|
|
64
108
|
```
|
|
@@ -68,55 +112,86 @@ console.log(tasks);
|
|
|
68
112
|
`getProjectTasks` forwards OData query options (for example `$filter`). You can also pass `typeId`; it is expanded to `$filter=data/type/typeId eq '<typeId>'` unless you already set `$filter`.
|
|
69
113
|
|
|
70
114
|
```js
|
|
71
|
-
const byType = await dalux.tasks.getProjectTasks(
|
|
115
|
+
const byType = await dalux.tasks.getProjectTasks("my-project-id", {
|
|
116
|
+
typeId: "some-type-guid",
|
|
117
|
+
});
|
|
72
118
|
|
|
73
119
|
// All pages merged (bookmark pagination; matches Python client behaviour)
|
|
74
|
-
const allTasks = await dalux.tasks.getAllProjectTasks(
|
|
120
|
+
const allTasks = await dalux.tasks.getAllProjectTasks(
|
|
121
|
+
"my-project-id",
|
|
122
|
+
{ typeId: "some-type-guid" },
|
|
123
|
+
false,
|
|
124
|
+
);
|
|
75
125
|
```
|
|
76
126
|
|
|
77
127
|
**Files: browse (6.1), fetch all pages, download**
|
|
78
128
|
|
|
79
|
-
`listFiles` and `getAllFiles` call **GET `/6.1/projects/{projectId}/file_areas/{fileAreaId}/files`** (Dalux `listFiles`).
|
|
129
|
+
`listFiles` and `getAllFiles` call **GET `/6.1/projects/{projectId}/file_areas/{fileAreaId}/files`** (Dalux `listFiles`). The documented optional query parameter is `includeProperties`; pagination uses Dalux's returned bookmark links. Single-file metadata still uses **GET `/5.0/.../files/{fileId}`** (`getFile`).
|
|
80
130
|
|
|
81
131
|
```js
|
|
82
|
-
const allFiles = await dalux.files.getAllFiles(
|
|
132
|
+
const allFiles = await dalux.files.getAllFiles(
|
|
133
|
+
"my-project-id",
|
|
134
|
+
"my-file-area-id",
|
|
135
|
+
{ folderId: "folder-guid" },
|
|
136
|
+
);
|
|
83
137
|
|
|
84
|
-
const file = await dalux.files.getFile(
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
138
|
+
const file = await dalux.files.getFile(
|
|
139
|
+
"my-project-id",
|
|
140
|
+
"my-file-area-id",
|
|
141
|
+
"file-guid",
|
|
142
|
+
{
|
|
143
|
+
download: true,
|
|
144
|
+
savePath: "./downloads",
|
|
145
|
+
},
|
|
146
|
+
);
|
|
88
147
|
|
|
89
|
-
const saved = await dalux.files.downloadFileFromLink(
|
|
148
|
+
const saved = await dalux.files.downloadFileFromLink(
|
|
149
|
+
downloadUrl,
|
|
150
|
+
"model.ifc",
|
|
151
|
+
"./downloads",
|
|
152
|
+
);
|
|
90
153
|
|
|
91
|
-
await dalux.files.bulkDownloadFolder(
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
154
|
+
await dalux.files.bulkDownloadFolder(
|
|
155
|
+
"my-project-id",
|
|
156
|
+
"my-file-area-id",
|
|
157
|
+
"folder-guid",
|
|
158
|
+
"./out",
|
|
159
|
+
{
|
|
160
|
+
filenameExtensions: [".ifc"],
|
|
161
|
+
verbose: true,
|
|
162
|
+
},
|
|
163
|
+
);
|
|
95
164
|
```
|
|
96
165
|
|
|
97
166
|
**Upload a file (chunked)**
|
|
167
|
+
|
|
98
168
|
```js
|
|
99
|
-
const fs = require(
|
|
169
|
+
const fs = require("fs");
|
|
100
170
|
|
|
101
171
|
// 1. Create an upload slot
|
|
102
172
|
const { uploadGuid } = await dalux.fileUpload.createUpload(
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
{ fileName:
|
|
173
|
+
"my-project-id",
|
|
174
|
+
"my-file-area-id",
|
|
175
|
+
{ fileName: "drawing.pdf", mimeType: "application/pdf" },
|
|
106
176
|
);
|
|
107
177
|
|
|
108
178
|
// 2. Upload the file in one chunk
|
|
109
|
-
const content = fs.readFileSync(
|
|
110
|
-
await dalux.fileUpload.uploadFilePart(
|
|
179
|
+
const content = fs.readFileSync("./drawing.pdf");
|
|
180
|
+
await dalux.fileUpload.uploadFilePart(
|
|
181
|
+
"my-project-id",
|
|
182
|
+
"my-file-area-id",
|
|
183
|
+
uploadGuid,
|
|
184
|
+
content,
|
|
185
|
+
);
|
|
111
186
|
|
|
112
187
|
// 3. Finalize the upload
|
|
113
188
|
const result = await dalux.fileUpload.finishUpload(
|
|
114
|
-
|
|
115
|
-
|
|
189
|
+
"my-project-id",
|
|
190
|
+
"my-file-area-id",
|
|
116
191
|
uploadGuid,
|
|
117
|
-
{ folderId:
|
|
192
|
+
{ folderId: "target-folder-id" },
|
|
118
193
|
);
|
|
119
|
-
console.log(
|
|
194
|
+
console.log("New file ID:", result.fileId);
|
|
120
195
|
```
|
|
121
196
|
|
|
122
197
|
## Authentication
|
|
@@ -129,7 +204,7 @@ All methods return Promises. Network or HTTP errors (4xx / 5xx) are thrown as Ax
|
|
|
129
204
|
|
|
130
205
|
```js
|
|
131
206
|
try {
|
|
132
|
-
const project = await dalux.projects.getProject(
|
|
207
|
+
const project = await dalux.projects.getProject("unknown-id");
|
|
133
208
|
} catch (err) {
|
|
134
209
|
console.error(err.response?.status, err.response?.data);
|
|
135
210
|
}
|
|
@@ -139,173 +214,178 @@ try {
|
|
|
139
214
|
|
|
140
215
|
All API namespaces are accessible on the object returned by `createClient`:
|
|
141
216
|
|
|
142
|
-
| Namespace
|
|
143
|
-
|
|
144
|
-
| `projects`
|
|
145
|
-
| `companies`
|
|
146
|
-
| `companyCatalog`
|
|
147
|
-
| `tasks`
|
|
148
|
-
| `fileAreas`
|
|
149
|
-
| `files`
|
|
150
|
-
| `folders`
|
|
151
|
-
| `fileUpload`
|
|
152
|
-
| `fileRevisions`
|
|
153
|
-
| `forms`
|
|
154
|
-
| `users`
|
|
155
|
-
| `projectTemplates` | `ProjectTemplatesApi` | Available project templates
|
|
156
|
-
| `inspectionPlans`
|
|
157
|
-
| `testPlans`
|
|
158
|
-
| `versionSets`
|
|
159
|
-
| `workPackages`
|
|
217
|
+
| Namespace | Class | Description |
|
|
218
|
+
| ------------------ | --------------------- | -------------------------------------------------------------- |
|
|
219
|
+
| `projects` | `ProjectsApi` | List, get, create and update projects; manage project metadata |
|
|
220
|
+
| `companies` | `CompaniesApi` | Project companies (CRUD) |
|
|
221
|
+
| `companyCatalog` | `CompanyCatalogApi` | Company catalog (CRUD + metadata) |
|
|
222
|
+
| `tasks` | `TasksApi` | Tasks, approvals, safety issues, observations & good practices |
|
|
223
|
+
| `fileAreas` | `FileAreasApi` | File areas on a project |
|
|
224
|
+
| `files` | `FilesApi` | Files within a file area |
|
|
225
|
+
| `folders` | `FoldersApi` | Folders within a file area |
|
|
226
|
+
| `fileUpload` | `FileUploadApi` | Chunked file upload (create slot → upload parts → finalize) |
|
|
227
|
+
| `fileRevisions` | `FileRevisionsApi` | Download file revision content |
|
|
228
|
+
| `forms` | `FormsApi` | Forms and form attachments |
|
|
229
|
+
| `users` | `UsersApi` | Company and project users |
|
|
230
|
+
| `projectTemplates` | `ProjectTemplatesApi` | Available project templates |
|
|
231
|
+
| `inspectionPlans` | `InspectionPlansApi` | Inspection plans, items, zones and registrations |
|
|
232
|
+
| `testPlans` | `TestPlansApi` | Test plans, items, zones and registrations |
|
|
233
|
+
| `versionSets` | `VersionSetsApi` | Version sets and version set files |
|
|
234
|
+
| `workPackages` | `WorkPackagesApi` | Work packages on a project |
|
|
235
|
+
|
|
236
|
+
`InspectionPlansApi` and `TestPlansApi` mirror the Python client's list behavior: their `list*`
|
|
237
|
+
methods return the typed `items` array by default and accept `fullResponse = true` as the third
|
|
238
|
+
argument to retain pagination metadata and links. Each collection also has a `getAll*` method that
|
|
239
|
+
follows Dalux bookmark pagination automatically.
|
|
160
240
|
|
|
161
241
|
### ProjectsApi
|
|
162
242
|
|
|
163
|
-
| Method
|
|
164
|
-
|
|
165
|
-
| `listProjects(params?)`
|
|
166
|
-
| `getProject(projectId)`
|
|
167
|
-
| `createProject(body)`
|
|
168
|
-
| `updateProject(projectId, body)`
|
|
169
|
-
| `listMetadataMappingsForProjects()`
|
|
170
|
-
| `listMetadataValuesForProjects(key)`
|
|
171
|
-
| `listProjectMetadata(projectId)`
|
|
172
|
-
| `listProjectMetadataMappings(projectId)`
|
|
173
|
-
| `listProjectMetadataValues(projectId, key)` | GET
|
|
243
|
+
| Method | HTTP | Path |
|
|
244
|
+
| -------------------------------------------- | ----- | ---------------------------------------------------------------- |
|
|
245
|
+
| `listProjects(params?)` | GET | `/5.1/projects` |
|
|
246
|
+
| `getProject(projectId)` | GET | `/5.0/projects/{projectId}` |
|
|
247
|
+
| `createProject(body)` | POST | `/5.0/projects` |
|
|
248
|
+
| `updateProject(projectId, body)` | PATCH | `/5.0/projects/{projectId}` |
|
|
249
|
+
| `listMetadataMappingsForProjects()` | GET | `/1.0/projects/metadata/1.0/mappings` |
|
|
250
|
+
| `listMetadataValuesForProjects(key)` | GET | `/1.0/projects/metadata/1.0/mappings/{key}/values` |
|
|
251
|
+
| `listProjectMetadata(projectId)` | GET | `/1.0/projects/{projectId}/metadata` |
|
|
252
|
+
| `listProjectMetadataMappings(projectId)` | GET | `/1.0/projects/{projectId}/metadata/1.0/mappings` |
|
|
253
|
+
| `listProjectMetadataValues(projectId, key)` | GET | `/1.0/projects/{projectId}/metadata/1.0/mappings/{key}/values` |
|
|
174
254
|
|
|
175
255
|
### CompaniesApi
|
|
176
256
|
|
|
177
|
-
| Method
|
|
178
|
-
|
|
179
|
-
| `listProjectCompanies(projectId, params?)`
|
|
180
|
-
| `getProjectCompany(projectId, companyId)`
|
|
181
|
-
| `createProjectCompany(projectId, body)`
|
|
257
|
+
| Method | HTTP | Path |
|
|
258
|
+
| -------------------------------------------------- | ----- | ------------------------------------------------- |
|
|
259
|
+
| `listProjectCompanies(projectId, params?)` | GET | `/3.1/projects/{projectId}/companies` |
|
|
260
|
+
| `getProjectCompany(projectId, companyId)` | GET | `/3.0/projects/{projectId}/companies/{companyId}` |
|
|
261
|
+
| `createProjectCompany(projectId, body)` | POST | `/3.1/projects/{projectId}/companies` |
|
|
182
262
|
| `updateProjectCompany(projectId, companyId, body)` | PATCH | `/3.0/projects/{projectId}/companies/{companyId}` |
|
|
183
263
|
|
|
184
264
|
### CompanyCatalogApi
|
|
185
265
|
|
|
186
|
-
| Method
|
|
187
|
-
|
|
188
|
-
| `getCompanies(params?)`
|
|
189
|
-
| `getCompany(catalogCompanyId)`
|
|
190
|
-
| `createCompany(body)`
|
|
191
|
-
| `updateCompany(catalogCompanyId, body)`
|
|
192
|
-
| `listCompanyMetadata(catalogCompanyId)`
|
|
193
|
-
| `listCompanyMetadataMappings(catalogCompanyId)`
|
|
194
|
-
| `listCompanyMetadataValues(catalogCompanyId, key)` | GET
|
|
195
|
-
| `listMetadataMappingsForCompanies()`
|
|
196
|
-
| `listMetadataValuesForCompanies(key)`
|
|
266
|
+
| Method | HTTP | Path |
|
|
267
|
+
| -------------------------------------------------- | ----- | ----------------------------------------------------------------------------- |
|
|
268
|
+
| `getCompanies(params?)` | GET | `/2.2/companyCatalog` |
|
|
269
|
+
| `getCompany(catalogCompanyId)` | GET | `/1.2/companyCatalog/{catalogCompanyId}` |
|
|
270
|
+
| `createCompany(body)` | POST | `/2.2/companyCatalog` |
|
|
271
|
+
| `updateCompany(catalogCompanyId, body)` | PATCH | `/2.1/companyCatalog/{catalogCompanyId}` |
|
|
272
|
+
| `listCompanyMetadata(catalogCompanyId)` | GET | `/1.0/companyCatalog/{catalogCompanyId}/metadata` |
|
|
273
|
+
| `listCompanyMetadataMappings(catalogCompanyId)` | GET | `/1.0/companyCatalog/{catalogCompanyId}/metadata/1.0/mappings` |
|
|
274
|
+
| `listCompanyMetadataValues(catalogCompanyId, key)` | GET | `/1.0/companyCatalog/{catalogCompanyId}/metadata/1.0/mappings/{key}/values` |
|
|
275
|
+
| `listMetadataMappingsForCompanies()` | GET | `/1.0/companyCatalog/metadata/1.0/mappings` |
|
|
276
|
+
| `listMetadataValuesForCompanies(key)` | GET | `/1.0/companyCatalog/metadata/1.0/mappings/{key}/values` |
|
|
197
277
|
|
|
198
278
|
### TasksApi
|
|
199
279
|
|
|
200
|
-
| Method
|
|
201
|
-
|
|
202
|
-
| `getProjectTasks(projectId, params?)`
|
|
280
|
+
| Method | HTTP | Path |
|
|
281
|
+
| -------------------------------------------------- | --------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
282
|
+
| `getProjectTasks(projectId, params?)` | GET | `/5.2/projects/{projectId}/tasks` |
|
|
203
283
|
| `getAllProjectTasks(projectId, params?, verbose?)` | GET (paginated) | `/5.2/projects/{projectId}/tasks` — collects all `items` via `nextPage` / `bookmark`; respects `metadata.totalRemainingItems` or `metadata.totalItems` (Python parity) |
|
|
204
|
-
| `getTask(projectId, taskId)`
|
|
205
|
-
| `getProjectTaskChanges(projectId, params?)`
|
|
206
|
-
| `getProjectTaskAttachments(projectId, params?)`
|
|
284
|
+
| `getTask(projectId, taskId)` | GET | `/3.3/projects/{projectId}/tasks/{taskId}` |
|
|
285
|
+
| `getProjectTaskChanges(projectId, params?)` | GET | `/2.2/projects/{projectId}/tasks/changes` |
|
|
286
|
+
| `getProjectTaskAttachments(projectId, params?)` | GET | `/1.1/projects/{projectId}/tasks/attachments` |
|
|
207
287
|
|
|
208
288
|
Query params: pass OData options on `getProjectTasks` / `getAllProjectTasks` (for example `$filter`). Shorthand: `typeId` is translated to `$filter=data/type/typeId eq '…'` when `$filter` is not set. `TasksApi.normalizeTaskParams` applies the same rules if you build requests manually.
|
|
209
289
|
|
|
210
290
|
### FileAreasApi
|
|
211
291
|
|
|
212
|
-
| Method
|
|
213
|
-
|
|
214
|
-
| `getFileAreas(projectId, params?)`
|
|
215
|
-
| `getFileArea(projectId, fileAreaId)` | GET
|
|
292
|
+
| Method | HTTP | Path |
|
|
293
|
+
| ------------------------------------- | ---- | ----------------------------------------------------- |
|
|
294
|
+
| `getFileAreas(projectId, params?)` | GET | `/5.1/projects/{projectId}/file_areas` |
|
|
295
|
+
| `getFileArea(projectId, fileAreaId)` | GET | `/1.0/projects/{projectId}/file_areas/{fileAreaId}` |
|
|
216
296
|
|
|
217
297
|
### FilesApi
|
|
218
298
|
|
|
219
299
|
Browse and paginated helpers use **route version 6.1** for the file collection. `getFile` (one file by id) uses **5.0**, as in the [Dalux Build API](https://app.swaggerhub.com/apis-docs/Dalux/DaluxBuild-api/4.14).
|
|
220
300
|
|
|
221
|
-
| Method
|
|
222
|
-
|
|
223
|
-
| `listFiles(projectId, fileAreaId, params?)`
|
|
224
|
-
| `getAllFiles(projectId, fileAreaId, params?, verbose?)`
|
|
225
|
-
| `getAllFilesInFolder(projectId, fileAreaId, folderId, params?, verbose?)` | —
|
|
226
|
-
| `getFile(projectId, fileAreaId, fileId, options?)`
|
|
227
|
-
| `downloadFileFromLink(downloadLink, fileName, savePath?)`
|
|
228
|
-
| `bulkDownloadFolder(projectId, fileAreaId, folderId, savePath?, opts?)`
|
|
229
|
-
| `bulkDownloadByIds(projectId, fileAreaId, fileIds, savePath?, options?)`
|
|
230
|
-
| `getFilePropertiesMapping(projectId, fileAreaId, fileId)`
|
|
231
|
-
| `getFilePropertyMappingValues(projectId, fileAreaId, filePropertyId)`
|
|
301
|
+
| Method | HTTP | Path |
|
|
302
|
+
| --------------------------------------------------------------------------- | --------------- | ------------------------------------------------------------------------------------------------------------------ |
|
|
303
|
+
| `listFiles(projectId, fileAreaId, params?)` | GET | `/6.1/projects/{projectId}/file_areas/{fileAreaId}/files` |
|
|
304
|
+
| `getAllFiles(projectId, fileAreaId, params?, verbose?)` | GET (paginated) | Same — all file `items` via bookmark / `metadata.totalRemainingItems` |
|
|
305
|
+
| `getAllFilesInFolder(projectId, fileAreaId, folderId, params?, verbose?)` | — | Uses `getAllFiles` then filters by `data.folderId` |
|
|
306
|
+
| `getFile(projectId, fileAreaId, fileId, options?)` | GET | `/5.0/.../files/{fileId}` — optional `{ download: true, savePath }` streams to disk (adds `downloadedFilePath`) |
|
|
307
|
+
| `downloadFileFromLink(downloadLink, fileName, savePath?)` | GET | Direct download URL with `X-API-KEY` |
|
|
308
|
+
| `bulkDownloadFolder(projectId, fileAreaId, folderId, savePath?, opts?)` | — | Optional `filenameKeywords`, `filenameKeywordsMatch` (`any` / `all`), `filenameExtensions`, `params`, `verbose` |
|
|
309
|
+
| `bulkDownloadByIds(projectId, fileAreaId, fileIds, savePath?, options?)` | GET + download | Per-id `getFile` then stream from `downloadLink` |
|
|
310
|
+
| `getFilePropertiesMapping(projectId, fileAreaId, fileId)` | GET | `/1.0/.../files/{fileId}/properties/1.0/mappings` |
|
|
311
|
+
| `getFilePropertyMappingValues(projectId, fileAreaId, filePropertyId)` | GET | `/1.0/.../files/properties/1.0/mappings/{filePropertyId}/values` |
|
|
232
312
|
|
|
233
313
|
### FoldersApi
|
|
234
314
|
|
|
235
|
-
| Method
|
|
236
|
-
|
|
237
|
-
| `listFolders(projectId, fileAreaId, params?)`
|
|
238
|
-
| `getFolder(projectId, fileAreaId, folderId)`
|
|
239
|
-
| `getFolderFilesProperties(projectId, fileAreaId, folderId)` | GET
|
|
315
|
+
| Method | HTTP | Path |
|
|
316
|
+
| ------------------------------------------------------------- | ---- | -------------------------------------------------------------------------- |
|
|
317
|
+
| `listFolders(projectId, fileAreaId, params?)` | GET | `/5.1/projects/{projectId}/file_areas/{fileAreaId}/folders` |
|
|
318
|
+
| `getFolder(projectId, fileAreaId, folderId)` | GET | `/5.0/projects/{projectId}/file_areas/{fileAreaId}/folders/{folderId}` |
|
|
319
|
+
| `getFolderFilesProperties(projectId, fileAreaId, folderId)` | GET | `/1.0/.../folders/{folderId}/files/properties/1.0/mappings` |
|
|
240
320
|
|
|
241
321
|
### FileUploadApi
|
|
242
322
|
|
|
243
|
-
| Method
|
|
244
|
-
|
|
245
|
-
| `createUpload(projectId, fileAreaId, body)`
|
|
246
|
-
| `uploadFilePart(projectId, fileAreaId, uploadGuid, chunk)` | POST | `/1.0/.../upload/{uploadGuid}`
|
|
247
|
-
| `finishUpload(projectId, fileAreaId, uploadGuid, body)`
|
|
323
|
+
| Method | HTTP | Path |
|
|
324
|
+
| ------------------------------------------------------------ | ---- | -------------------------------------------------------------- |
|
|
325
|
+
| `createUpload(projectId, fileAreaId, body)` | POST | `/1.0/projects/{projectId}/file_areas/{fileAreaId}/upload` |
|
|
326
|
+
| `uploadFilePart(projectId, fileAreaId, uploadGuid, chunk)` | POST | `/1.0/.../upload/{uploadGuid}` |
|
|
327
|
+
| `finishUpload(projectId, fileAreaId, uploadGuid, body)` | POST | `/2.0/.../upload/{uploadGuid}/finalize` |
|
|
248
328
|
|
|
249
329
|
### FileRevisionsApi
|
|
250
330
|
|
|
251
|
-
| Method
|
|
252
|
-
|
|
253
|
-
| `getFileRevisionContent(projectId, fileAreaId, fileId, fileRevisionId)` | GET
|
|
331
|
+
| Method | HTTP | Path |
|
|
332
|
+
| --------------------------------------------------------------------------- | ---- | ------------------------------------------------------------ |
|
|
333
|
+
| `getFileRevisionContent(projectId, fileAreaId, fileId, fileRevisionId)` | GET | `/2.0/.../files/{fileId}/revisions/{fileRevisionId}/content` |
|
|
254
334
|
|
|
255
335
|
### FormsApi
|
|
256
336
|
|
|
257
|
-
| Method
|
|
258
|
-
|
|
259
|
-
| `getProjectForms(projectId, params?)`
|
|
260
|
-
| `getForm(projectId, formId)`
|
|
261
|
-
| `getProjectFormAttachments(projectId, params?)` | GET
|
|
337
|
+
| Method | HTTP | Path |
|
|
338
|
+
| -------------------------------------------------- | ---- | ------------------------------------------------ |
|
|
339
|
+
| `getProjectForms(projectId, params?)` | GET | `/2.1/projects/{projectId}/forms` |
|
|
340
|
+
| `getForm(projectId, formId)` | GET | `/1.2/projects/{projectId}/forms/{formId}` |
|
|
341
|
+
| `getProjectFormAttachments(projectId, params?)` | GET | `/2.1/projects/{projectId}/forms/attachments` |
|
|
262
342
|
|
|
263
343
|
### UsersApi
|
|
264
344
|
|
|
265
|
-
| Method
|
|
266
|
-
|
|
267
|
-
| `getUser(userId)`
|
|
268
|
-
| `listProjectUsers(projectId, params?)` | GET
|
|
269
|
-
| `getProjectUser(projectId, userId)`
|
|
345
|
+
| Method | HTTP | Path |
|
|
346
|
+
| ----------------------------------------- | ---- | ---------------------------------------------- |
|
|
347
|
+
| `getUser(userId)` | GET | `/1.1/users/{userId}` |
|
|
348
|
+
| `listProjectUsers(projectId, params?)` | GET | `/1.2/projects/{projectId}/users` |
|
|
349
|
+
| `getProjectUser(projectId, userId)` | GET | `/1.1/projects/{projectId}/users/{userId}` |
|
|
270
350
|
|
|
271
351
|
### ProjectTemplatesApi
|
|
272
352
|
|
|
273
|
-
| Method
|
|
274
|
-
|
|
275
|
-
| `listProjectTemplates(params?)` | GET
|
|
353
|
+
| Method | HTTP | Path |
|
|
354
|
+
| ---------------------------------- | ---- | --------------------------- |
|
|
355
|
+
| `listProjectTemplates(params?)` | GET | `/1.1/projectTemplates` |
|
|
276
356
|
|
|
277
357
|
### InspectionPlansApi
|
|
278
358
|
|
|
279
|
-
| Method
|
|
280
|
-
|
|
281
|
-
| `listInspectionPlans(projectId, params?)`
|
|
282
|
-
| `listInspectionPlanItems(projectId, params?)`
|
|
283
|
-
| `listInspectionPlanItemZones(projectId, params?)`
|
|
284
|
-
| `listInspectionPlanRegistrations(projectId, params?)` | GET
|
|
359
|
+
| Method | HTTP | Path |
|
|
360
|
+
| -------------------------------------------------------- | ---- | ------------------------------------------------------------ |
|
|
361
|
+
| `listInspectionPlans(projectId, params?)` | GET | `/1.2/projects/{projectId}/inspectionPlans` |
|
|
362
|
+
| `listInspectionPlanItems(projectId, params?)` | GET | `/1.1/projects/{projectId}/inspectionPlanItems` |
|
|
363
|
+
| `listInspectionPlanItemZones(projectId, params?)` | GET | `/1.1/projects/{projectId}/inspectionPlanItemZones` |
|
|
364
|
+
| `listInspectionPlanRegistrations(projectId, params?)` | GET | `/2.1/projects/{projectId}/inspectionPlanRegistrations` |
|
|
285
365
|
|
|
286
366
|
### TestPlansApi
|
|
287
367
|
|
|
288
|
-
| Method
|
|
289
|
-
|
|
290
|
-
| `listTestPlans(projectId, params?)`
|
|
291
|
-
| `listTestPlanItems(projectId, params?)`
|
|
292
|
-
| `listTestPlanItemZones(projectId, params?)`
|
|
293
|
-
| `listTestPlanRegistrations(projectId, params?)` | GET
|
|
368
|
+
| Method | HTTP | Path |
|
|
369
|
+
| ---------------------------------------------------- | ---- | -------------------------------------------------- |
|
|
370
|
+
| `listTestPlans(projectId, params?)` | GET | `/1.2/projects/{projectId}/testPlans` |
|
|
371
|
+
| `listTestPlanItems(projectId, params?)` | GET | `/1.1/projects/{projectId}/testPlanItems` |
|
|
372
|
+
| `listTestPlanItemZones(projectId, params?)` | GET | `/1.1/projects/{projectId}/testPlanItemZones` |
|
|
373
|
+
| `listTestPlanRegistrations(projectId, params?)` | GET | `/1.1/projects/{projectId}/testPlanRegistrations` |
|
|
294
374
|
|
|
295
375
|
### VersionSetsApi
|
|
296
376
|
|
|
297
|
-
| Method
|
|
298
|
-
|
|
299
|
-
| `getVersionSets(projectId, params?)`
|
|
300
|
-
| `getVersionSet(projectId, versionSetId)`
|
|
301
|
-
| `listFileAreaVersionSets(projectId, fileAreaId, params?)` | GET
|
|
302
|
-
| `listVersionSetFiles(projectId, versionSetId, params?)`
|
|
377
|
+
| Method | HTTP | Path |
|
|
378
|
+
| ------------------------------------------------------------- | ---- | ---------------------------------------------------------------- |
|
|
379
|
+
| `getVersionSets(projectId, params?)` | GET | `/2.1/projects/{projectId}/version_sets` |
|
|
380
|
+
| `getVersionSet(projectId, versionSetId)` | GET | `/2.0/projects/{projectId}/version_sets/{versionSetId}` |
|
|
381
|
+
| `listFileAreaVersionSets(projectId, fileAreaId, params?)` | GET | `/2.1/projects/{projectId}/file_areas/{fileAreaId}/version_sets` |
|
|
382
|
+
| `listVersionSetFiles(projectId, versionSetId, params?)` | GET | `/3.0/projects/{projectId}/version_sets/{versionSetId}/files` |
|
|
303
383
|
|
|
304
384
|
### WorkPackagesApi
|
|
305
385
|
|
|
306
|
-
| Method
|
|
307
|
-
|
|
308
|
-
| `listWorkPackages(projectId, params?)` | GET
|
|
386
|
+
| Method | HTTP | Path |
|
|
387
|
+
| ----------------------------------------- | ---- | --------------------------------------------- |
|
|
388
|
+
| `listWorkPackages(projectId, params?)` | GET | `/1.0/projects/{projectId}/workpackages` |
|
|
309
389
|
|
|
310
390
|
## Advanced Usage
|
|
311
391
|
|
|
@@ -314,51 +394,41 @@ Browse and paginated helpers use **route version 6.1** for the file collection.
|
|
|
314
394
|
You can also instantiate API classes directly with a shared `ApiClient`:
|
|
315
395
|
|
|
316
396
|
```js
|
|
317
|
-
const {
|
|
397
|
+
const {
|
|
398
|
+
Configuration,
|
|
399
|
+
ApiClient,
|
|
400
|
+
ProjectsApi,
|
|
401
|
+
TasksApi,
|
|
402
|
+
} = require("dalux-build-api");
|
|
318
403
|
|
|
319
404
|
const config = new Configuration({
|
|
320
|
-
baseUrl:
|
|
321
|
-
apiKey:
|
|
405
|
+
baseUrl: "https://<your-company>.dalux.com/api",
|
|
406
|
+
apiKey: "YOUR_API_KEY",
|
|
322
407
|
});
|
|
323
408
|
const apiClient = new ApiClient(config);
|
|
324
409
|
|
|
325
410
|
const projects = new ProjectsApi(apiClient);
|
|
326
|
-
const tasks
|
|
411
|
+
const tasks = new TasksApi(apiClient);
|
|
327
412
|
```
|
|
328
413
|
|
|
329
|
-
##
|
|
414
|
+
## Testing
|
|
330
415
|
|
|
331
416
|
```bash
|
|
332
|
-
#
|
|
333
|
-
npm
|
|
334
|
-
|
|
335
|
-
# Run tests with coverage
|
|
336
|
-
npm test
|
|
417
|
+
npm install # from the repo root (this is an npm workspace)
|
|
418
|
+
npm test --workspace=javascript # Jest, with coverage
|
|
337
419
|
```
|
|
338
420
|
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
### Automatic (push to `main`)
|
|
342
|
-
|
|
343
|
-
1. Merge to `main` (or push directly). **CI** must pass.
|
|
344
|
-
2. After **both** the Node and Python test jobs succeed, **CI** calls **Publish npm Package** via `workflow_call` (same run as CI, so it does not depend on `workflow_run`).
|
|
345
|
-
3. The publish job only runs when that push changes `package.json`, `package-lock.json`, `src/`, or `test/`.
|
|
346
|
-
4. **Version bump** uses the same rules as the Python publisher ([commit message tokens](python/README.md#maintainer-pypi-releases)), but the **current** semver is **`max(python/pyproject.toml, package.json)`** so npm catches up when the Python package is ahead.
|
|
347
|
-
5. It runs tests again, publishes to npm, then pushes `chore: release vX.Y.Z [skip npm]`, tag `vX.Y.Z`, and a **GitHub Release** (unless the tag already exists). **`[skip npm]`** skips a second publish pass and skips **CI** on that sync commit.
|
|
348
|
-
|
|
349
|
-
### Manual
|
|
350
|
-
|
|
351
|
-
- **Actions → Publish npm Package → Run workflow** for **patch / minor / major** (same test → publish → sync commit → tag → **GitHub Release**). The entry workflow is [npm-publish.yml](.github/workflows/npm-publish.yml); it delegates to [npm-publish-reusable.yml](.github/workflows/npm-publish-reusable.yml) (GitHub requires `workflow_call` in its own file).
|
|
352
|
-
- **GitHub Release (published)** publishes the version already in `package.json` at that tag (no version bump in the workflow).
|
|
353
|
-
|
|
354
|
-
Create a GitHub **environment** named `npm` with secret **`NPM_TOKEN`**. If pushes or releases from `GITHUB_TOKEN` are blocked, set **`RELEASE_PAT`** as described in [python/README.md](python/README.md#maintainer-pypi-releases).
|
|
355
|
-
|
|
356
|
-
### First publish and `E404` on `npm publish`
|
|
421
|
+
CI runs this on Node.js 20/22/24 — see
|
|
422
|
+
[`../.github/workflows/tests.yml`](../.github/workflows/tests.yml).
|
|
357
423
|
|
|
358
|
-
|
|
424
|
+
## Releasing
|
|
359
425
|
|
|
360
|
-
|
|
361
|
-
|
|
426
|
+
This package is versioned and published together with the Python client by
|
|
427
|
+
[Changesets](https://github.com/changesets/changesets) — there is no manual
|
|
428
|
+
edit of `version` in `package.json`, and nothing publishes to npm unless the
|
|
429
|
+
full test suite (Node.js, Python, webhook server) passes first. See
|
|
430
|
+
[../CONTRIBUTING.md](../CONTRIBUTING.md#how-releases-work) for the full flow
|
|
431
|
+
and [../README.md](../README.md#releasing) for the PyPI side of it.
|
|
362
432
|
|
|
363
433
|
## License
|
|
364
434
|
|