dalux-build-api 2.3.0 → 2.5.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.
Files changed (49) hide show
  1. package/README.md +52 -0
  2. package/package.json +61 -12
  3. package/src/api/CompaniesApi.js +0 -67
  4. package/src/api/CompanyCatalogApi.js +0 -129
  5. package/src/api/FileAreasApi.js +0 -57
  6. package/src/api/FileRevisionsApi.js +0 -33
  7. package/src/api/FileUploadApi.js +0 -64
  8. package/src/api/FilesApi.js +0 -721
  9. package/src/api/FoldersApi.js +0 -283
  10. package/src/api/FormsApi.js +0 -53
  11. package/src/api/InspectionPlansApi.js +0 -140
  12. package/src/api/ProjectTemplatesApi.js +0 -25
  13. package/src/api/ProjectsApi.js +0 -127
  14. package/src/api/TasksApi.js +0 -193
  15. package/src/api/TestPlansApi.js +0 -137
  16. package/src/api/UsersApi.js +0 -52
  17. package/src/api/VersionSetsApi.js +0 -75
  18. package/src/api/WorkPackagesApi.js +0 -30
  19. package/src/apiClient.js +0 -143
  20. package/src/browser.js +0 -84
  21. package/src/configuration.js +0 -39
  22. package/src/index.js +0 -133
  23. package/src/models/common.js +0 -22
  24. package/src/models/companies/index.js +0 -14
  25. package/src/models/companyCatalog/index.js +0 -19
  26. package/src/models/convert.js +0 -44
  27. package/src/models/fileAreas/index.js +0 -20
  28. package/src/models/fileRevisions/index.js +0 -12
  29. package/src/models/fileUpload/index.js +0 -12
  30. package/src/models/files/index.js +0 -97
  31. package/src/models/folders/index.js +0 -20
  32. package/src/models/forms/index.js +0 -19
  33. package/src/models/helpers.js +0 -62
  34. package/src/models/index.js +0 -178
  35. package/src/models/inspectionPlans/index.js +0 -61
  36. package/src/models/projectTemplates/index.js +0 -11
  37. package/src/models/projects/index.js +0 -57
  38. package/src/models/tasks/index.js +0 -105
  39. package/src/models/testPlans/index.js +0 -61
  40. package/src/models/users/index.js +0 -29
  41. package/src/models/versionSets/index.js +0 -22
  42. package/src/models/workPackages/index.js +0 -19
  43. package/src/next.js +0 -89
  44. package/src/utils/errors.js +0 -45
  45. package/src/utils/index.js +0 -26
  46. package/src/utils/pagination.js +0 -82
  47. package/src/utils/pathResolver.js +0 -124
  48. package/src/utils/search.js +0 -61
  49. package/src/utils/validation.js +0 -36
package/README.md CHANGED
@@ -202,6 +202,58 @@ const result = await dalux.fileUpload.finishUpload(
202
202
  console.log("New file ID:", result.fileId);
203
203
  ```
204
204
 
205
+ ## Browser and plugin hosts (`/web`)
206
+
207
+ When the API key legitimately lives where the code runs — a desktop app, an extension, a plugin
208
+ host that already proxies Dalux — `dalux-build-api/web` gives you every endpoint group over a
209
+ `fetch` you supply:
210
+
211
+ ```ts
212
+ import { createWebClient } from "dalux-build-api/web";
213
+
214
+ const dalux = createWebClient({
215
+ baseUrl: "https://node1.field.dalux.com/service/api",
216
+ apiKey,
217
+ fetch: ctx.fetch, // the host's own fetch
218
+ defaultParams: { daluxNode: "node2" }, // base-origin requests only
219
+ });
220
+
221
+ const sets = await dalux.versionSets.getVersionSets(projectId);
222
+ ```
223
+
224
+ `fetch` is required and never falls back to `globalThis.fetch`. A sandboxed host hands its own
225
+ fetch down because that wrapper is where the outbound-host allow-list, the same-origin relay for
226
+ an API that sends no CORS headers, redirect refusal and credential omission are enforced; silently
227
+ using the global would take all of that off without the caller noticing. `defaultParams` are added
228
+ only to requests on the configured base URL, and never override a parameter the caller or the URL
229
+ already set — a `downloadLink` can carry a signature computed over its query string.
230
+
231
+ This entry reaches no Axios, no `fs`/`path`/`readline`, no `process.env` — enforced by a test over
232
+ the module graph, not by a build flag. The one omission is `FilesApi`: its bulk-download and
233
+ interactive-selection helpers stream to disk and read stdin. Its pure HTTP reads, including
234
+ `downloadFileBytes`, are on `FilesReadApi` and exposed as `dalux.files`.
235
+
236
+ ### Bringing your own HTTP client
237
+
238
+ If your host already has a Dalux client — with its own relay, retries, logging or pagination rules
239
+ — implement `DaluxHttpClient` over it and keep all of that while still getting the endpoint
240
+ catalogue and its zod models:
241
+
242
+ ```ts
243
+ import { createWebClientFrom, type DaluxHttpClient } from "dalux-build-api/web";
244
+
245
+ const http: DaluxHttpClient = {
246
+ configuration: { baseUrl, apiKey },
247
+ get: (path, params, config) => host.get(path, params, config?.signal),
248
+ post: (path, body, params) => host.post(path, body, params),
249
+ patch: (path, body, params) => host.patch(path, body, params),
250
+ delete: (path, params) => host.delete(path, params),
251
+ binary: async (url, config) => ({ bytes: await host.getBinary(url, config?.signal) }),
252
+ };
253
+
254
+ const dalux = createWebClientFrom(http);
255
+ ```
256
+
205
257
  ## Authentication
206
258
 
207
259
  Every request automatically includes the `X-API-KEY` header with the API key supplied to `createClient`. No additional configuration is required.
package/package.json CHANGED
@@ -1,22 +1,61 @@
1
1
  {
2
2
  "name": "dalux-build-api",
3
- "version": "2.3.0",
3
+ "version": "2.5.0",
4
4
  "description": "Node.js client for the Dalux Build API",
5
- "main": "src/index.js",
5
+ "main": "dist/index.js",
6
+ "types": "dist/index.d.ts",
6
7
  "exports": {
7
- ".": "./src/index.js",
8
- "./browser": "./src/browser.js",
9
- "./next": "./src/next.js"
8
+ ".": {
9
+ "import": {
10
+ "types": "./dist/index.d.mts",
11
+ "default": "./dist/index.mjs"
12
+ },
13
+ "require": {
14
+ "types": "./dist/index.d.ts",
15
+ "default": "./dist/index.js"
16
+ }
17
+ },
18
+ "./browser": {
19
+ "import": {
20
+ "types": "./dist/browser.d.mts",
21
+ "default": "./dist/browser.mjs"
22
+ },
23
+ "require": {
24
+ "types": "./dist/browser.d.ts",
25
+ "default": "./dist/browser.js"
26
+ }
27
+ },
28
+ "./next": {
29
+ "import": {
30
+ "types": "./dist/next.d.mts",
31
+ "default": "./dist/next.mjs"
32
+ },
33
+ "require": {
34
+ "types": "./dist/next.d.ts",
35
+ "default": "./dist/next.js"
36
+ }
37
+ },
38
+ "./web": {
39
+ "import": {
40
+ "types": "./dist/web.d.mts",
41
+ "default": "./dist/web.mjs"
42
+ },
43
+ "require": {
44
+ "types": "./dist/web.d.ts",
45
+ "default": "./dist/web.js"
46
+ }
47
+ }
10
48
  },
11
49
  "files": [
12
- "src",
50
+ "dist",
13
51
  "README.md"
14
52
  ],
15
53
  "scripts": {
54
+ "build": "tsup",
55
+ "typecheck": "tsc --noEmit",
16
56
  "test": "jest --coverage",
17
- "build": "npm pack",
18
- "pack:check": "npm pack --dry-run",
19
- "release:check": "npm test && npm run pack:check"
57
+ "pack:check": "npm run build && npm pack --dry-run",
58
+ "release:check": "npm run typecheck && npm test && npm run pack:check"
20
59
  },
21
60
  "keywords": [
22
61
  "dalux",
@@ -44,10 +83,20 @@
44
83
  "zod": "^4.4.3"
45
84
  },
46
85
  "devDependencies": {
86
+ "@types/jest": "^30.0.0",
87
+ "@types/node": "^22.0.0",
47
88
  "axios-mock-adapter": "^2.1.0",
48
- "jest": "^30.4.2"
89
+ "jest": "^30.4.2",
90
+ "ts-jest": "^29.2.5",
91
+ "tsup": "^8.3.5",
92
+ "typescript": "^5.7.2"
49
93
  },
50
94
  "jest": {
51
- "testEnvironment": "node"
52
- }
95
+ "testEnvironment": "node",
96
+ "preset": "ts-jest",
97
+ "testMatch": [
98
+ "**/test/**/*.test.ts"
99
+ ]
100
+ },
101
+ "module": "dist/index.mjs"
53
102
  }
@@ -1,67 +0,0 @@
1
- 'use strict';
2
-
3
- const { convertToModel } = require('../models/convert');
4
- const { CompaniesListResponseSchema, CompanyResponseSchema } = require('../models/companies');
5
-
6
- /**
7
- * API methods for managing companies on a project.
8
- */
9
- class CompaniesApi {
10
- /**
11
- * @param {import('../apiClient')} apiClient
12
- */
13
- constructor(apiClient) {
14
- this._client = apiClient;
15
- }
16
-
17
- /**
18
- * Get companies on a project.
19
- * GET /3.1/projects/{projectId}/companies
20
- * @param {string} projectId
21
- * @param {object} [params]
22
- * @returns {Promise<object>} CompaniesListResponse ({ items: ProjectCompany[], metadata?, links? })
23
- */
24
- async listProjectCompanies(projectId, params = {}) {
25
- const response = await this._client.get(`/3.1/projects/${projectId}/companies`, params);
26
- return convertToModel(response, CompaniesListResponseSchema, 'CompaniesListResponse');
27
- }
28
-
29
- /**
30
- * Get a specific company on a project.
31
- * GET /3.0/projects/{projectId}/companies/{companyId}
32
- * @param {string} projectId
33
- * @param {string} companyId
34
- * @returns {Promise<object>} CompanyResponse ({ data: ProjectCompany, links? })
35
- */
36
- async getProjectCompany(projectId, companyId) {
37
- const response = await this._client.get(`/3.0/projects/${projectId}/companies/${companyId}`);
38
- return convertToModel(response, CompanyResponseSchema, 'CompanyResponse');
39
- }
40
-
41
- /**
42
- * Add a company to a project.
43
- * POST /3.1/projects/{projectId}/companies
44
- * @param {string} projectId
45
- * @param {object} body
46
- * @returns {Promise<object>} CompanyResponse
47
- */
48
- async createProjectCompany(projectId, body) {
49
- const response = await this._client.post(`/3.1/projects/${projectId}/companies`, body);
50
- return convertToModel(response, CompanyResponseSchema, 'CompanyResponse');
51
- }
52
-
53
- /**
54
- * Update a company on a project.
55
- * PATCH /3.0/projects/{projectId}/companies/{companyId}
56
- * @param {string} projectId
57
- * @param {string} companyId
58
- * @param {object} body
59
- * @returns {Promise<object>} CompanyResponse
60
- */
61
- async updateProjectCompany(projectId, companyId, body) {
62
- const response = await this._client.patch(`/3.0/projects/${projectId}/companies/${companyId}`, body);
63
- return convertToModel(response, CompanyResponseSchema, 'CompanyResponse');
64
- }
65
- }
66
-
67
- module.exports = CompaniesApi;
@@ -1,129 +0,0 @@
1
- 'use strict';
2
-
3
- const { findByField } = require('../utils/search');
4
- const { convertToModel } = require('../models/convert');
5
- const { CompaniesListResponseSchema, CompanyResponseSchema } = require('../models/companies');
6
-
7
- /**
8
- * API methods for the company catalog.
9
- */
10
- class CompanyCatalogApi {
11
- /**
12
- * @param {import('../apiClient')} apiClient
13
- */
14
- constructor(apiClient) {
15
- this._client = apiClient;
16
- }
17
-
18
- /**
19
- * Get companies registered in the company catalog.
20
- * GET /2.2/companyCatalog
21
- * @param {object} [params]
22
- * @returns {Promise<object>} CompaniesListResponse ({ items: ProjectCompany[], metadata?, links? })
23
- */
24
- async getCompanies(params = {}) {
25
- const response = await this._client.get('/2.2/companyCatalog', params);
26
- return convertToModel(response, CompaniesListResponseSchema, 'CompaniesListResponse');
27
- }
28
-
29
- /**
30
- * Get a specific company from the catalog.
31
- * GET /1.2/companyCatalog/{catalogCompanyId}
32
- * @param {string} catalogCompanyId
33
- * @returns {Promise<object>} CompanyResponse ({ data: ProjectCompany, links? })
34
- */
35
- async getCompany(catalogCompanyId) {
36
- const response = await this._client.get(`/1.2/companyCatalog/${catalogCompanyId}`);
37
- return convertToModel(response, CompanyResponseSchema, 'CompanyResponse');
38
- }
39
-
40
- /**
41
- * Add a company to the catalog.
42
- * POST /2.2/companyCatalog
43
- * @param {object} body
44
- * @returns {Promise<object>} CompanyResponse
45
- */
46
- async createCompany(body) {
47
- const response = await this._client.post('/2.2/companyCatalog', body);
48
- return convertToModel(response, CompanyResponseSchema, 'CompanyResponse');
49
- }
50
-
51
- /**
52
- * Update a company in the catalog.
53
- * PATCH /2.1/companyCatalog/{catalogCompanyId}
54
- * @param {string} catalogCompanyId
55
- * @param {object} body
56
- * @returns {Promise<object>} CompanyResponse
57
- */
58
- async updateCompany(catalogCompanyId, body) {
59
- const response = await this._client.patch(`/2.1/companyCatalog/${catalogCompanyId}`, body);
60
- return convertToModel(response, CompanyResponseSchema, 'CompanyResponse');
61
- }
62
-
63
- /**
64
- * Get metadata of a specific company from the catalog.
65
- * GET /1.0/companyCatalog/{catalogCompanyId}/metadata
66
- * @param {string} catalogCompanyId
67
- * @returns {Promise<object>}
68
- */
69
- listCompanyMetadata(catalogCompanyId) {
70
- return this._client.get(`/1.0/companyCatalog/${catalogCompanyId}/metadata`);
71
- }
72
-
73
- /**
74
- * Get all metadata available for a PATCH company-catalog operation.
75
- * GET /1.0/companyCatalog/{catalogCompanyId}/metadata/1.0/mappings
76
- * @param {string} catalogCompanyId
77
- * @returns {Promise<object>}
78
- */
79
- listCompanyMetadataMappings(catalogCompanyId) {
80
- return this._client.get(`/1.0/companyCatalog/${catalogCompanyId}/metadata/1.0/mappings`);
81
- }
82
-
83
- /**
84
- * Get available values for metadata in a PATCH company-catalog operation.
85
- * GET /1.0/companyCatalog/{catalogCompanyId}/metadata/1.0/mappings/{key}/values
86
- * @param {string} catalogCompanyId
87
- * @param {string} key
88
- * @returns {Promise<object>}
89
- */
90
- listCompanyMetadataValues(catalogCompanyId, key) {
91
- return this._client.get(
92
- `/1.0/companyCatalog/${catalogCompanyId}/metadata/1.0/mappings/${key}/values`,
93
- );
94
- }
95
-
96
- /**
97
- * Get all metadata available for a POST company-catalog operation.
98
- * GET /1.0/companyCatalog/metadata/1.0/mappings
99
- * @returns {Promise<object>}
100
- */
101
- listMetadataMappingsForCompanies() {
102
- return this._client.get('/1.0/companyCatalog/metadata/1.0/mappings');
103
- }
104
-
105
- /**
106
- * Get available values for metadata in a POST company-catalog operation.
107
- * GET /1.0/companyCatalog/metadata/1.0/mappings/{key}/values
108
- * @param {string} key
109
- * @returns {Promise<object>}
110
- */
111
- listMetadataValuesForCompanies(key) {
112
- return this._client.get(`/1.0/companyCatalog/metadata/1.0/mappings/${key}/values`);
113
- }
114
-
115
- /**
116
- * Get a company ID by its name from the catalog.
117
- * @param {string} companyName
118
- * @returns {Promise<string|null>} The catalogCompanyId, or null if not found.
119
- */
120
- async getCompanyByName(companyName) {
121
- const response = await this.getCompanies();
122
- const items = (response && response.items) || [];
123
- const company = findByField(items, 'name', companyName);
124
- if (!company) return null;
125
- return company.catalogCompanyId || null;
126
- }
127
- }
128
-
129
- module.exports = CompanyCatalogApi;
@@ -1,57 +0,0 @@
1
- 'use strict';
2
-
3
- const { findByField } = require('../utils/search');
4
- const { convertToModel } = require('../models/convert');
5
- const { FileAreaSchema, FileAreasListResponseSchema } = require('../models/fileAreas');
6
-
7
- /**
8
- * API methods for file areas on a project.
9
- */
10
- class FileAreasApi {
11
- /**
12
- * @param {import('../apiClient')} apiClient
13
- */
14
- constructor(apiClient) {
15
- this._client = apiClient;
16
- }
17
-
18
- /**
19
- * Retrieve the file areas on the given project.
20
- * GET /5.1/projects/{projectId}/file_areas
21
- * @param {string} projectId
22
- * @param {object} [params]
23
- * @returns {Promise<object>} FileAreasListResponse ({ items: FileArea[], metadata?, links? })
24
- */
25
- async getFileAreas(projectId, params = {}) {
26
- const response = await this._client.get(`/5.1/projects/${projectId}/file_areas`, params);
27
- return convertToModel(response, FileAreasListResponseSchema, 'FileAreasListResponse');
28
- }
29
-
30
- /**
31
- * Retrieve a specific file area.
32
- * GET /1.0/projects/{projectId}/file_areas/{fileAreaId}
33
- * @param {string} projectId
34
- * @param {string} fileAreaId
35
- * @returns {Promise<object>} FileArea (not wrapped in a data envelope, matches Python)
36
- */
37
- async getFileArea(projectId, fileAreaId) {
38
- const response = await this._client.get(`/1.0/projects/${projectId}/file_areas/${fileAreaId}`);
39
- return convertToModel(response, FileAreaSchema, 'FileArea');
40
- }
41
-
42
- /**
43
- * Get a file area ID by its name for a project.
44
- * @param {string} projectId
45
- * @param {string} fileAreaName
46
- * @returns {Promise<string|null>} The fileAreaId, or null if not found.
47
- */
48
- async getFileAreaByName(projectId, fileAreaName) {
49
- const response = await this.getFileAreas(projectId);
50
- const items = (response && response.items) || [];
51
- const area = findByField(items, 'fileAreaName', fileAreaName);
52
- if (!area) return null;
53
- return area.fileAreaId || null;
54
- }
55
- }
56
-
57
- module.exports = FileAreasApi;
@@ -1,33 +0,0 @@
1
- 'use strict';
2
-
3
- /**
4
- * API methods for file revision content.
5
- */
6
- class FileRevisionsApi {
7
- /**
8
- * @param {import('../apiClient')} apiClient
9
- */
10
- constructor(apiClient) {
11
- this._client = apiClient;
12
- }
13
-
14
- /**
15
- * Retrieve content of a specific file revision.
16
- * GET /2.0/projects/{projectId}/file_areas/{fileAreaId}/files/{fileId}/revisions/{fileRevisionId}/content
17
- * @param {string} projectId
18
- * @param {string} fileAreaId
19
- * @param {string} fileId
20
- * @param {string} fileRevisionId
21
- * @returns {Promise<Buffer>} Raw binary content
22
- */
23
- async getFileRevisionContent(projectId, fileAreaId, fileId, fileRevisionId) {
24
- const data = await this._client.get(
25
- `/2.0/projects/${projectId}/file_areas/${fileAreaId}/files/${fileId}/revisions/${fileRevisionId}/content`,
26
- {},
27
- { responseType: 'arraybuffer' },
28
- );
29
- return Buffer.from(data);
30
- }
31
- }
32
-
33
- module.exports = FileRevisionsApi;
@@ -1,64 +0,0 @@
1
- 'use strict';
2
-
3
- /**
4
- * API methods for chunked file uploads.
5
- */
6
- class FileUploadApi {
7
- /**
8
- * @param {import('../apiClient')} apiClient
9
- */
10
- constructor(apiClient) {
11
- this._client = apiClient;
12
- }
13
-
14
- /**
15
- * Create a new upload slot and return a GUID pointing to that slot.
16
- * POST /1.0/projects/{projectId}/file_areas/{fileAreaId}/upload
17
- * @param {string} projectId
18
- * @param {string} fileAreaId
19
- * @param {object} body
20
- * @returns {Promise<object>}
21
- */
22
- createUpload(projectId, fileAreaId, body) {
23
- return this._client.post(
24
- `/1.0/projects/${projectId}/file_areas/${fileAreaId}/upload`,
25
- body,
26
- );
27
- }
28
-
29
- /**
30
- * Upload a part of a file.
31
- * POST /1.0/projects/{projectId}/file_areas/{fileAreaId}/upload/{uploadGuid}
32
- * @param {string} projectId
33
- * @param {string} fileAreaId
34
- * @param {string} uploadGuid
35
- * @param {Buffer|Uint8Array} chunk - Binary file chunk
36
- * @returns {Promise<object>}
37
- */
38
- uploadFilePart(projectId, fileAreaId, uploadGuid, chunk) {
39
- return this._client.post(
40
- `/1.0/projects/${projectId}/file_areas/${fileAreaId}/upload/${uploadGuid}`,
41
- chunk,
42
- {},
43
- { headers: { 'Content-Type': 'application/octet-stream' } },
44
- );
45
- }
46
-
47
- /**
48
- * Finish uploading a file (finalize the upload).
49
- * POST /2.0/projects/{projectId}/file_areas/{fileAreaId}/upload/{uploadGuid}/finalize
50
- * @param {string} projectId
51
- * @param {string} fileAreaId
52
- * @param {string} uploadGuid
53
- * @param {object} body
54
- * @returns {Promise<object>}
55
- */
56
- finishUpload(projectId, fileAreaId, uploadGuid, body) {
57
- return this._client.post(
58
- `/2.0/projects/${projectId}/file_areas/${fileAreaId}/upload/${uploadGuid}/finalize`,
59
- body,
60
- );
61
- }
62
- }
63
-
64
- module.exports = FileUploadApi;