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.
Files changed (39) hide show
  1. package/README.md +257 -187
  2. package/package.json +11 -4
  3. package/src/api/CompaniesApi.js +19 -12
  4. package/src/api/CompanyCatalogApi.js +22 -18
  5. package/src/api/FileAreasApi.js +14 -12
  6. package/src/api/FilesApi.js +11 -7
  7. package/src/api/FoldersApi.js +14 -12
  8. package/src/api/FormsApi.js +11 -6
  9. package/src/api/InspectionPlansApi.js +87 -9
  10. package/src/api/ProjectsApi.js +22 -18
  11. package/src/api/TasksApi.js +25 -10
  12. package/src/api/TestPlansApi.js +87 -9
  13. package/src/api/UsersApi.js +11 -6
  14. package/src/api/VersionSetsApi.js +20 -12
  15. package/src/api/WorkPackagesApi.js +7 -3
  16. package/src/browser.js +84 -0
  17. package/src/index.js +5 -0
  18. package/src/models/common.js +22 -0
  19. package/src/models/companies/index.js +14 -0
  20. package/src/models/companyCatalog/index.js +19 -0
  21. package/src/models/convert.js +44 -0
  22. package/src/models/fileAreas/index.js +20 -0
  23. package/src/models/fileRevisions/index.js +12 -0
  24. package/src/models/fileUpload/index.js +12 -0
  25. package/src/models/files/index.js +97 -0
  26. package/src/models/folders/index.js +20 -0
  27. package/src/models/forms/index.js +19 -0
  28. package/src/models/helpers.js +62 -0
  29. package/src/models/index.js +178 -0
  30. package/src/models/inspectionPlans/index.js +61 -0
  31. package/src/models/projectTemplates/index.js +11 -0
  32. package/src/models/projects/index.js +57 -0
  33. package/src/models/tasks/index.js +105 -0
  34. package/src/models/testPlans/index.js +61 -0
  35. package/src/models/users/index.js +29 -0
  36. package/src/models/versionSets/index.js +22 -0
  37. package/src/models/workPackages/index.js +19 -0
  38. package/src/next.js +89 -0
  39. package/LICENSE +0 -21
@@ -0,0 +1,97 @@
1
+ 'use strict';
2
+
3
+ const { z } = require('zod');
4
+ const { listResponseSchema, singleResponseSchema, nullableDefault } = require('../helpers');
5
+
6
+ /** Mirrors models/files/models.py::Reference. */
7
+ const ReferenceSchema = z.object({
8
+ key: z.string(),
9
+ value: z.string(),
10
+ });
11
+
12
+ /** Mirrors models/files/models.py::FileIntegerProperty. */
13
+ const FileIntegerPropertySchema = z.object({
14
+ integer: z.number().nullish(),
15
+ });
16
+
17
+ /** Mirrors models/files/models.py::FileDateProperty. */
18
+ const FileDatePropertySchema = z.object({
19
+ date: z.string().nullish(),
20
+ });
21
+
22
+ /** Mirrors models/files/models.py::FileTextProperty. */
23
+ const FileTextPropertySchema = z.object({
24
+ text: z.string().nullish(),
25
+ });
26
+
27
+ /** Mirrors models/files/models.py::FileReferenceProperty. */
28
+ const FileReferencePropertySchema = z.object({
29
+ reference: ReferenceSchema.nullish(),
30
+ });
31
+
32
+ /** Mirrors models/files/models.py::FilePropertyField. */
33
+ const FilePropertyFieldSchema = z.object({
34
+ key: z.string(),
35
+ name: z.string(),
36
+ values: z.array(z.any()).nullish(),
37
+ });
38
+
39
+ /**
40
+ * Mirrors models/files/models.py::FileNameFilter. Client-side filter params
41
+ * (not part of any API response), so field names stay plain camelCase with
42
+ * no aliasing concerns on either side.
43
+ */
44
+ const FileNameFilterSchema = z.object({
45
+ contains: z.array(z.string()).optional(),
46
+ containsMatch: z.enum(['any', 'all']).default('any'),
47
+ notContains: z.array(z.string()).optional(),
48
+ startswith: z.array(z.string()).optional(),
49
+ notStartswith: z.array(z.string()).optional(),
50
+ endswith: z.array(z.string()).optional(),
51
+ notEndswith: z.array(z.string()).optional(),
52
+ extensions: z.array(z.string()).optional(),
53
+ notExtensions: z.array(z.string()).optional(),
54
+ });
55
+
56
+ /**
57
+ * Mirrors models/files/models.py::File. `uploaded`/`lastModified` are kept
58
+ * as ISO date strings (not coerced to JS Date) so JSON round-tripping and
59
+ * existing string-based consumer code keeps working.
60
+ */
61
+ const FileSchema = z.object({
62
+ fileId: z.string(),
63
+ fileRevisionId: z.string().nullish(),
64
+ fileName: z.string(),
65
+ fileAreaId: z.string(),
66
+ folderId: z.string().nullish(),
67
+ uploadedByUserId: z.string().nullish(),
68
+ uploaded: z.string().nullish(),
69
+ lastModifiedByUserId: z.string().nullish(),
70
+ lastModified: z.string().nullish(),
71
+ version: z.string().nullish(),
72
+ deleted: nullableDefault(z.boolean(), false),
73
+ fileType: z.string().nullish(),
74
+ fileSize: z.number().nullish(),
75
+ contentHash: z.string().nullish(),
76
+ downloadLink: z.string().nullish(),
77
+ properties: z.array(FilePropertyFieldSchema).nullish(),
78
+ // Local-only fields set by bulk-download helpers, not present in raw API responses.
79
+ savedFilePath: z.string().nullish(),
80
+ savedMetadataPath: z.string().nullish(),
81
+ });
82
+
83
+ const FilesListResponseSchema = listResponseSchema(FileSchema);
84
+ const FileResponseSchema = singleResponseSchema(FileSchema);
85
+
86
+ module.exports = {
87
+ ReferenceSchema,
88
+ FileIntegerPropertySchema,
89
+ FileDatePropertySchema,
90
+ FileTextPropertySchema,
91
+ FileReferencePropertySchema,
92
+ FilePropertyFieldSchema,
93
+ FileNameFilterSchema,
94
+ FileSchema,
95
+ FilesListResponseSchema,
96
+ FileResponseSchema,
97
+ };
@@ -0,0 +1,20 @@
1
+ 'use strict';
2
+
3
+ const { z } = require('zod');
4
+ const { listResponseSchema, singleResponseSchema } = require('../helpers');
5
+
6
+ /** Mirrors models/folders/models.py::Folder. */
7
+ const FolderSchema = z.object({
8
+ folderId: z.string(),
9
+ folderName: z.string(),
10
+ parentFolderId: z.string().nullish(),
11
+ });
12
+
13
+ const FoldersListResponseSchema = listResponseSchema(FolderSchema);
14
+ const FolderResponseSchema = singleResponseSchema(FolderSchema);
15
+
16
+ module.exports = {
17
+ FolderSchema,
18
+ FoldersListResponseSchema,
19
+ FolderResponseSchema,
20
+ };
@@ -0,0 +1,19 @@
1
+ 'use strict';
2
+
3
+ const { z } = require('zod');
4
+ const { listResponseSchema, singleResponseSchema } = require('../helpers');
5
+
6
+ /**
7
+ * Mirrors models/forms/models.py::Form — empty placeholder in Python, so
8
+ * items stay untyped.
9
+ */
10
+ const FormSchema = z.any();
11
+
12
+ const FormsListResponseSchema = listResponseSchema(FormSchema);
13
+ const FormResponseSchema = singleResponseSchema(FormSchema);
14
+
15
+ module.exports = {
16
+ FormSchema,
17
+ FormsListResponseSchema,
18
+ FormResponseSchema,
19
+ };
@@ -0,0 +1,62 @@
1
+ 'use strict';
2
+
3
+ const { z } = require('zod');
4
+ const { LinkSchema, MetadataSchema } = require('./common');
5
+
6
+ /**
7
+ * Unwraps a `{ data: {...} }` wrapper before validating against `schema`.
8
+ * Bare objects (no `data` wrapper) pass straight through.
9
+ * Mirrors the `unwrap_and_convert_items` field_validator repeated across
10
+ * every Python `responses.py` file.
11
+ * @param {import('zod').ZodTypeAny} schema
12
+ */
13
+ function unwrapData(schema) {
14
+ return z.preprocess((value) => {
15
+ if (value && typeof value === 'object' && !Array.isArray(value) && 'data' in value) {
16
+ return value.data;
17
+ }
18
+ return value;
19
+ }, schema);
20
+ }
21
+
22
+ /**
23
+ * Builds a `{ items, metadata?, links? }` list-response schema.
24
+ * Accepts a bare array payload too (wraps it as `{ items: [...] }`) —
25
+ * mirrors TaskChanges' `wrap_list_payloads` model_validator.
26
+ * @param {import('zod').ZodTypeAny} itemSchema
27
+ */
28
+ function listResponseSchema(itemSchema) {
29
+ return z.preprocess(
30
+ (value) => (Array.isArray(value) ? { items: value } : value),
31
+ z.object({
32
+ items: z.array(unwrapData(itemSchema)).default([]),
33
+ metadata: MetadataSchema.optional(),
34
+ links: z.array(LinkSchema).optional(),
35
+ }),
36
+ );
37
+ }
38
+
39
+ /**
40
+ * Builds a `{ data, links? }` single-item response schema.
41
+ * @param {import('zod').ZodTypeAny} itemSchema
42
+ */
43
+ function singleResponseSchema(itemSchema) {
44
+ return z.object({
45
+ data: itemSchema,
46
+ links: z.array(LinkSchema).optional(),
47
+ });
48
+ }
49
+
50
+ /**
51
+ * A defaulted field that also accepts an explicit JSON `null` (treated the
52
+ * same as an absent field) — mirrors Pydantic's `Optional[T] = default`,
53
+ * which accepts both a missing key and an explicit `null`. Plain
54
+ * `schema.default(x)` alone only fires on `undefined`, not `null`.
55
+ * @param {import('zod').ZodTypeAny} schema
56
+ * @param {*} defaultValue
57
+ */
58
+ function nullableDefault(schema, defaultValue) {
59
+ return z.preprocess((v) => (v === null ? undefined : v), schema.default(defaultValue));
60
+ }
61
+
62
+ module.exports = { unwrapData, listResponseSchema, singleResponseSchema, nullableDefault };
@@ -0,0 +1,178 @@
1
+ 'use strict';
2
+
3
+ /**
4
+ * Zod schemas for Dalux Build API responses. Mirrors the public surface of
5
+ * python/dalux_build/models/__init__.py, with a `Schema` suffix on every
6
+ * export name (these are zod schema objects, not constructible classes).
7
+ */
8
+
9
+ const { LinkSchema, MetadataSchema } = require('./common');
10
+
11
+ const {
12
+ ProjectSchema,
13
+ ProjectModuleSchema,
14
+ ProjectMetadataSchema,
15
+ ProjectTemplateSchema,
16
+ ProjectCompanySchema,
17
+ ProjectsListResponseSchema,
18
+ ProjectResponseSchema,
19
+ } = require('./projects');
20
+
21
+ const { FileAreaSchema, FileAreasListResponseSchema, FileAreaResponseSchema } = require('./fileAreas');
22
+
23
+ const { FolderSchema, FoldersListResponseSchema, FolderResponseSchema } = require('./folders');
24
+
25
+ const {
26
+ FileSchema,
27
+ ReferenceSchema,
28
+ FileNameFilterSchema,
29
+ FileIntegerPropertySchema,
30
+ FileDatePropertySchema,
31
+ FileTextPropertySchema,
32
+ FileReferencePropertySchema,
33
+ FilePropertyFieldSchema,
34
+ FilesListResponseSchema,
35
+ FileResponseSchema,
36
+ } = require('./files');
37
+
38
+ const { VersionSetSchema, VersionSetsListResponseSchema, VersionSetResponseSchema } = require('./versionSets');
39
+
40
+ const { UserSchema, ProjectUserSchema, UsersListResponseSchema, UserResponseSchema } = require('./users');
41
+
42
+ const { CompaniesListResponseSchema, CompanyResponseSchema } = require('./companies');
43
+
44
+ const { CompanyCatalogListResponseSchema, CompanyCatalogResponseSchema } = require('./companyCatalog');
45
+
46
+ const {
47
+ InspectionPlanSchema,
48
+ InspectionPlanItemSchema,
49
+ InspectionPlanItemZoneSchema,
50
+ InspectionPlanRegistrationSchema,
51
+ InspectionPlansListResponseSchema,
52
+ InspectionPlanItemsListResponseSchema,
53
+ InspectionPlanItemZonesListResponseSchema,
54
+ InspectionPlanRegistrationsListResponseSchema,
55
+ } = require('./inspectionPlans');
56
+
57
+ const {
58
+ TestPlanSchema,
59
+ TestPlanItemSchema,
60
+ TestPlanItemZoneSchema,
61
+ TestPlanRegistrationSchema,
62
+ TestPlansListResponseSchema,
63
+ TestPlanItemsListResponseSchema,
64
+ TestPlanItemZonesListResponseSchema,
65
+ TestPlanRegistrationsListResponseSchema,
66
+ } = require('./testPlans');
67
+
68
+ const { FormSchema, FormsListResponseSchema, FormResponseSchema } = require('./forms');
69
+
70
+ const {
71
+ TaskSchema,
72
+ TaskAttachmentSchema,
73
+ TaskChangeSchema,
74
+ TaskChangeActorSchema,
75
+ TaskChangeFieldsSchema,
76
+ TaskChangeLocationSchema,
77
+ TaskListParamsSchema,
78
+ TasksListResponseSchema,
79
+ TaskResponseSchema,
80
+ TaskChangeResponseSchema,
81
+ TaskChangesSchema,
82
+ TaskAttachmentsListResponseSchema,
83
+ } = require('./tasks');
84
+
85
+ const { FileRevisionSchema } = require('./fileRevisions');
86
+ const { FileUploadSchema } = require('./fileUpload');
87
+ const { WorkPackageSchema, WorkPackagesListResponseSchema } = require('./workPackages');
88
+
89
+ module.exports = {
90
+ // Base
91
+ LinkSchema,
92
+ MetadataSchema,
93
+ // Projects
94
+ ProjectSchema,
95
+ ProjectModuleSchema,
96
+ ProjectMetadataSchema,
97
+ ProjectTemplateSchema,
98
+ ProjectCompanySchema,
99
+ ProjectsListResponseSchema,
100
+ ProjectResponseSchema,
101
+ // File Areas
102
+ FileAreaSchema,
103
+ FileAreasListResponseSchema,
104
+ FileAreaResponseSchema,
105
+ // Folders
106
+ FolderSchema,
107
+ FoldersListResponseSchema,
108
+ FolderResponseSchema,
109
+ // Files
110
+ FileSchema,
111
+ ReferenceSchema,
112
+ FileNameFilterSchema,
113
+ FileIntegerPropertySchema,
114
+ FileDatePropertySchema,
115
+ FileTextPropertySchema,
116
+ FileReferencePropertySchema,
117
+ FilePropertyFieldSchema,
118
+ FilesListResponseSchema,
119
+ FileResponseSchema,
120
+ // Version Sets
121
+ VersionSetSchema,
122
+ VersionSetsListResponseSchema,
123
+ VersionSetResponseSchema,
124
+ // Users
125
+ UserSchema,
126
+ ProjectUserSchema,
127
+ UsersListResponseSchema,
128
+ UserResponseSchema,
129
+ // Companies
130
+ CompaniesListResponseSchema,
131
+ CompanyResponseSchema,
132
+ // Company Catalog
133
+ CompanyCatalogListResponseSchema,
134
+ CompanyCatalogResponseSchema,
135
+ // Inspection Plans
136
+ InspectionPlanSchema,
137
+ InspectionPlanItemSchema,
138
+ InspectionPlanItemZoneSchema,
139
+ InspectionPlanRegistrationSchema,
140
+ InspectionPlansListResponseSchema,
141
+ InspectionPlanItemsListResponseSchema,
142
+ InspectionPlanItemZonesListResponseSchema,
143
+ InspectionPlanRegistrationsListResponseSchema,
144
+ // Test Plans
145
+ TestPlanSchema,
146
+ TestPlanItemSchema,
147
+ TestPlanItemZoneSchema,
148
+ TestPlanRegistrationSchema,
149
+ TestPlansListResponseSchema,
150
+ TestPlanItemsListResponseSchema,
151
+ TestPlanItemZonesListResponseSchema,
152
+ TestPlanRegistrationsListResponseSchema,
153
+ // Forms
154
+ FormSchema,
155
+ FormsListResponseSchema,
156
+ FormResponseSchema,
157
+ // Tasks
158
+ TaskSchema,
159
+ TaskAttachmentSchema,
160
+ TaskChangeSchema,
161
+ TaskChangeActorSchema,
162
+ TaskChangeFieldsSchema,
163
+ TaskChangeLocationSchema,
164
+ TaskListParamsSchema,
165
+ TasksListResponseSchema,
166
+ TaskResponseSchema,
167
+ TaskChangeResponseSchema,
168
+ TaskChangesSchema,
169
+ TaskAttachmentsListResponseSchema,
170
+ // Project Templates (same ProjectTemplateSchema as Projects, re-exported above)
171
+ // File Revisions
172
+ FileRevisionSchema,
173
+ // File Upload
174
+ FileUploadSchema,
175
+ // Work Packages
176
+ WorkPackageSchema,
177
+ WorkPackagesListResponseSchema,
178
+ };
@@ -0,0 +1,61 @@
1
+ 'use strict';
2
+
3
+ const { z } = require('zod');
4
+ const { listResponseSchema } = require('../helpers');
5
+
6
+ const optionalString = z.string().nullish();
7
+ const optionalInteger = z.number().int().nullish();
8
+
9
+ const InspectionPlanSchema = z.object({
10
+ inspectionPlanId: optionalString,
11
+ name: optionalString,
12
+ workpackageId: optionalString,
13
+ }).passthrough();
14
+
15
+ const InspectionPlanItemSchema = z.object({
16
+ inspectionPlanItemId: optionalString,
17
+ inspectionPlanId: optionalString,
18
+ number: optionalString,
19
+ subject: optionalString,
20
+ heading: optionalString,
21
+ subHeading: optionalString,
22
+ extentType: optionalString,
23
+ planned: optionalInteger,
24
+ ongoing: optionalInteger,
25
+ completed: optionalInteger,
26
+ nonPlannedOngoing: optionalInteger,
27
+ nonPlannedCompleted: optionalInteger,
28
+ }).passthrough();
29
+
30
+ const InspectionPlanItemZoneSchema = z.object({
31
+ inspectionPlanItemId: optionalString,
32
+ inspectionPlanItemZoneId: optionalString,
33
+ name: optionalString,
34
+ planned: optionalInteger,
35
+ ongoing: optionalInteger,
36
+ completed: optionalInteger,
37
+ }).passthrough();
38
+
39
+ const InspectionPlanRegistrationSchema = z.object({
40
+ status: optionalString,
41
+ formId: optionalString,
42
+ taskId: optionalString,
43
+ inspectionPlanItemId: optionalString,
44
+ inspectionPlanItemZoneId: optionalString,
45
+ }).passthrough();
46
+
47
+ const InspectionPlansListResponseSchema = listResponseSchema(InspectionPlanSchema);
48
+ const InspectionPlanItemsListResponseSchema = listResponseSchema(InspectionPlanItemSchema);
49
+ const InspectionPlanItemZonesListResponseSchema = listResponseSchema(InspectionPlanItemZoneSchema);
50
+ const InspectionPlanRegistrationsListResponseSchema = listResponseSchema(InspectionPlanRegistrationSchema);
51
+
52
+ module.exports = {
53
+ InspectionPlanSchema,
54
+ InspectionPlanItemSchema,
55
+ InspectionPlanItemZoneSchema,
56
+ InspectionPlanRegistrationSchema,
57
+ InspectionPlansListResponseSchema,
58
+ InspectionPlanItemsListResponseSchema,
59
+ InspectionPlanItemZonesListResponseSchema,
60
+ InspectionPlanRegistrationsListResponseSchema,
61
+ };
@@ -0,0 +1,11 @@
1
+ 'use strict';
2
+
3
+ const { ProjectTemplateSchema } = require('../projects');
4
+
5
+ /**
6
+ * Mirrors models/project_templates/models.py::ProjectTemplate — identical
7
+ * shape to projects/models.py::ProjectTemplate, so it's reused rather than
8
+ * duplicated. listProjectTemplates returns raw/unmodeled data in Python too
9
+ * (company-wide endpoint), so no response wrapper is defined here.
10
+ */
11
+ module.exports = { ProjectTemplateSchema };
@@ -0,0 +1,57 @@
1
+ 'use strict';
2
+
3
+ const { z } = require('zod');
4
+ const { listResponseSchema, singleResponseSchema } = require('../helpers');
5
+
6
+ /** Mirrors models/projects/models.py::ProjectModule (empty placeholder, passthrough). */
7
+ const ProjectModuleSchema = z.object({}).passthrough();
8
+
9
+ /** Mirrors models/projects/models.py::Project. Note: `type` is the real JSON key (Python aliases project_type -> "type"). */
10
+ const ProjectSchema = z.object({
11
+ projectId: z.string(),
12
+ projectName: z.string(),
13
+ type: z.string().nullish(),
14
+ projectTemplateId: z.string().nullish(),
15
+ address: z.string().nullish(),
16
+ number: z.string().nullish(),
17
+ created: z.string().nullish(),
18
+ closing: z.string().nullish(),
19
+ modules: z.array(ProjectModuleSchema).nullish(),
20
+ });
21
+
22
+ /** Mirrors models/projects/models.py::ProjectMetadata. */
23
+ const ProjectMetadataSchema = z.object({
24
+ key: z.string(),
25
+ value: z.string().nullish(),
26
+ });
27
+
28
+ /** Mirrors models/projects/models.py::ProjectTemplate (also duplicated in project_templates/models.py — same shape). */
29
+ const ProjectTemplateSchema = z.object({
30
+ projectTemplateId: z.string(),
31
+ name: z.string(),
32
+ });
33
+
34
+ /** Mirrors models/projects/models.py::ProjectCompany. */
35
+ const ProjectCompanySchema = z.object({
36
+ companyId: z.string().nullish(),
37
+ name: z.string().nullish(),
38
+ vatNumber: z.string().nullish(),
39
+ address: z.string().nullish(),
40
+ city: z.string().nullish(),
41
+ postalCode: z.string().nullish(),
42
+ country: z.string().nullish(),
43
+ catalogCompanyId: z.string().nullish(),
44
+ });
45
+
46
+ const ProjectsListResponseSchema = listResponseSchema(ProjectSchema);
47
+ const ProjectResponseSchema = singleResponseSchema(ProjectSchema);
48
+
49
+ module.exports = {
50
+ ProjectModuleSchema,
51
+ ProjectSchema,
52
+ ProjectMetadataSchema,
53
+ ProjectTemplateSchema,
54
+ ProjectCompanySchema,
55
+ ProjectsListResponseSchema,
56
+ ProjectResponseSchema,
57
+ };
@@ -0,0 +1,105 @@
1
+ 'use strict';
2
+
3
+ const { z } = require('zod');
4
+ const { listResponseSchema, singleResponseSchema } = require('../helpers');
5
+
6
+ /** Mirrors models/tasks/models.py::Task (extra="allow" -> passthrough; only taskId is typed). */
7
+ const TaskSchema = z.object({
8
+ taskId: z.string().nullish(),
9
+ }).passthrough();
10
+
11
+ /**
12
+ * Mirrors models/tasks/models.py::TaskListParams. Field names are the
13
+ * actual OData query keys (matches what src/api/TasksApi.js's
14
+ * normalizeTaskParams reads/writes) rather than Python's snake_case
15
+ * attribute names, since JS has no alias layer to bridge the two. These are
16
+ * developer-supplied query params (not API responses), so plain `.optional()`
17
+ * is fine.
18
+ */
19
+ const TaskListParamsSchema = z.object({
20
+ typeId: z.string().optional(),
21
+ $filter: z.string().optional(),
22
+ $select: z.string().optional(),
23
+ $orderby: z.string().optional(),
24
+ $top: z.number().optional(),
25
+ $skip: z.number().optional(),
26
+ bookmark: z.string().optional(),
27
+ }).passthrough();
28
+
29
+ /** Mirrors models/tasks/models.py::TaskChangeActor. */
30
+ const TaskChangeActorSchema = z.object({
31
+ userId: z.string().nullish(),
32
+ roleId: z.string().nullish(),
33
+ roleName: z.string().nullish(),
34
+ userName: z.string().nullish(),
35
+ name: z.string().nullish(),
36
+ }).passthrough();
37
+
38
+ /** Mirrors models/tasks/models.py::TaskChangeLocation (empty passthrough). */
39
+ const TaskChangeLocationSchema = z.object({}).passthrough();
40
+
41
+ /**
42
+ * Preprocesses the deadline field the same way Python's
43
+ * `normalize_deadline` field_validator does: unwraps API payloads where
44
+ * deadline is returned as an object instead of a bare string.
45
+ */
46
+ const deadlineSchema = z.preprocess((value) => {
47
+ if (value && typeof value === 'object' && !Array.isArray(value)) {
48
+ if (value.empty === true) return undefined;
49
+ if ('value' in value) return value.value;
50
+ if ('date' in value) return value.date;
51
+ if ('datetime' in value) return value.datetime;
52
+ }
53
+ return value;
54
+ }, z.string().nullish());
55
+
56
+ /** Mirrors models/tasks/models.py::TaskChangeFields. */
57
+ const TaskChangeFieldsSchema = z.object({
58
+ currentResponsible: TaskChangeActorSchema.nullish(),
59
+ assignedTo: TaskChangeActorSchema.nullish(),
60
+ title: z.string().nullish(),
61
+ deadline: deadlineSchema,
62
+ status: z.string().nullish(),
63
+ modifiedBy: TaskChangeActorSchema.nullish(),
64
+ userDefinedFields: z.record(z.any()).nullish(),
65
+ workpackageId: z.string().nullish(),
66
+ location: TaskChangeLocationSchema.nullish(),
67
+ }).passthrough();
68
+
69
+ /** Mirrors models/tasks/models.py::TaskChange. */
70
+ const TaskChangeSchema = z.object({
71
+ taskId: z.string(),
72
+ description: z.string().nullish(),
73
+ timestamp: z.string(),
74
+ action: z.string(),
75
+ fields: TaskChangeFieldsSchema.nullish(),
76
+ });
77
+
78
+ /** Mirrors models/tasks/models.py::TaskAttachment. */
79
+ const TaskAttachmentSchema = z.object({
80
+ attachmentId: z.string().nullish(),
81
+ taskId: z.string().nullish(),
82
+ fileId: z.string().nullish(),
83
+ }).passthrough();
84
+
85
+ const TasksListResponseSchema = listResponseSchema(TaskSchema);
86
+ const TaskResponseSchema = singleResponseSchema(TaskSchema);
87
+ const TaskChangeResponseSchema = singleResponseSchema(TaskChangeSchema);
88
+ /** Bare-list payloads (`[...]` instead of `{items: [...]}`) are handled by listResponseSchema's preprocessor. */
89
+ const TaskChangesSchema = listResponseSchema(TaskChangeSchema);
90
+ const TaskAttachmentsListResponseSchema = listResponseSchema(TaskAttachmentSchema);
91
+
92
+ module.exports = {
93
+ TaskSchema,
94
+ TaskListParamsSchema,
95
+ TaskChangeActorSchema,
96
+ TaskChangeLocationSchema,
97
+ TaskChangeFieldsSchema,
98
+ TaskChangeSchema,
99
+ TaskAttachmentSchema,
100
+ TasksListResponseSchema,
101
+ TaskResponseSchema,
102
+ TaskChangeResponseSchema,
103
+ TaskChangesSchema,
104
+ TaskAttachmentsListResponseSchema,
105
+ };
@@ -0,0 +1,61 @@
1
+ 'use strict';
2
+
3
+ const { z } = require('zod');
4
+ const { listResponseSchema } = require('../helpers');
5
+
6
+ const optionalString = z.string().nullish();
7
+ const optionalInteger = z.number().int().nullish();
8
+
9
+ const TestPlanSchema = z.object({
10
+ testPlanId: optionalString,
11
+ name: optionalString,
12
+ workpackageId: optionalString,
13
+ }).passthrough();
14
+
15
+ const TestPlanItemSchema = z.object({
16
+ testPlanItemId: optionalString,
17
+ testPlanId: optionalString,
18
+ number: optionalString,
19
+ subject: optionalString,
20
+ heading: optionalString,
21
+ subHeading: optionalString,
22
+ extentType: optionalString,
23
+ planned: optionalInteger,
24
+ ongoing: optionalInteger,
25
+ completed: optionalInteger,
26
+ nonPlannedOngoing: optionalInteger,
27
+ nonPlannedCompleted: optionalInteger,
28
+ }).passthrough();
29
+
30
+ const TestPlanItemZoneSchema = z.object({
31
+ testPlanItemId: optionalString,
32
+ testPlanItemZoneId: optionalString,
33
+ name: optionalString,
34
+ planned: optionalInteger,
35
+ ongoing: optionalInteger,
36
+ completed: optionalInteger,
37
+ }).passthrough();
38
+
39
+ const TestPlanRegistrationSchema = z.object({
40
+ status: optionalString,
41
+ formId: optionalString,
42
+ taskId: optionalString,
43
+ testPlanItemId: optionalString,
44
+ testPlanItemZoneId: optionalString,
45
+ }).passthrough();
46
+
47
+ const TestPlansListResponseSchema = listResponseSchema(TestPlanSchema);
48
+ const TestPlanItemsListResponseSchema = listResponseSchema(TestPlanItemSchema);
49
+ const TestPlanItemZonesListResponseSchema = listResponseSchema(TestPlanItemZoneSchema);
50
+ const TestPlanRegistrationsListResponseSchema = listResponseSchema(TestPlanRegistrationSchema);
51
+
52
+ module.exports = {
53
+ TestPlanSchema,
54
+ TestPlanItemSchema,
55
+ TestPlanItemZoneSchema,
56
+ TestPlanRegistrationSchema,
57
+ TestPlansListResponseSchema,
58
+ TestPlanItemsListResponseSchema,
59
+ TestPlanItemZonesListResponseSchema,
60
+ TestPlanRegistrationsListResponseSchema,
61
+ };