@twinfinity/twin 6.0.1 → 6.0.2
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/dist/BuildInfo.js +3 -3
- package/dist/TwinClient.d.ts +227 -0
- package/dist/TwinClient.d.ts.map +1 -1
- package/dist/TwinClient.js +474 -28
- package/dist/TwinClient.js.map +1 -1
- package/dist/errors.d.ts +122 -3
- package/dist/errors.d.ts.map +1 -1
- package/dist/errors.js +156 -0
- package/dist/errors.js.map +1 -1
- package/dist/tsconfig.tsbuildinfo +1 -1
- package/dist/types/asset-attachment-api.d.ts +51 -0
- package/dist/types/asset-attachment-api.d.ts.map +1 -0
- package/dist/types/asset-attachment-api.js +8 -0
- package/dist/types/asset-attachment-api.js.map +1 -0
- package/dist/types/asset-types-api.d.ts +76 -0
- package/dist/types/asset-types-api.d.ts.map +1 -0
- package/dist/types/asset-types-api.js +5 -0
- package/dist/types/asset-types-api.js.map +1 -0
- package/dist/types/index.d.ts +3 -0
- package/dist/types/index.d.ts.map +1 -1
- package/dist/types/index.js +3 -0
- package/dist/types/index.js.map +1 -1
- package/dist/types/twin-permissions-api.d.ts +20 -0
- package/dist/types/twin-permissions-api.d.ts.map +1 -0
- package/dist/types/twin-permissions-api.js +2 -0
- package/dist/types/twin-permissions-api.js.map +1 -0
- package/docs/assets/hierarchy.js +1 -1
- package/docs/assets/navigation.js +1 -1
- package/docs/assets/search.js +1 -1
- package/docs/classes/AssetAttachmentConflictError.html +3 -0
- package/docs/classes/AssetAttachmentNotFoundError.html +2 -0
- package/docs/classes/AssetBatchError.html +1 -1
- package/docs/classes/AssetCatalogTooLargeError.html +16 -0
- package/docs/classes/AssetCategoryConflictError.html +3 -0
- package/docs/classes/AssetCategoryForbiddenError.html +2 -0
- package/docs/classes/AssetCategoryNotFoundError.html +2 -0
- package/docs/classes/AssetCategoryValidationError.html +3 -0
- package/docs/classes/AssetConflictError.html +1 -1
- package/docs/classes/AssetForbiddenError.html +1 -1
- package/docs/classes/AssetNotFoundError.html +1 -1
- package/docs/classes/AssetTypeConflictError.html +3 -0
- package/docs/classes/AssetTypeForbiddenError.html +2 -0
- package/docs/classes/AssetTypeNotFoundError.html +2 -0
- package/docs/classes/AssetTypeValidationError.html +3 -0
- package/docs/classes/AssetValidationError.html +1 -1
- package/docs/classes/ProcessorNotFoundError.html +1 -1
- package/docs/classes/TwinClient.html +154 -48
- package/docs/classes/TwinConflictError.html +1 -1
- package/docs/classes/TwinFileConflictError.html +1 -1
- package/docs/classes/TwinFileNotFoundError.html +1 -1
- package/docs/classes/TwinFileValidationError.html +1 -1
- package/docs/classes/TwinNotFoundError.html +1 -1
- package/docs/classes/TwinUnauthenticatedError.html +6 -0
- package/docs/classes/TwinValidationError.html +1 -1
- package/docs/functions/isAssetCatalogTooLargeErrorBody.html +6 -0
- package/docs/functions/readErrorBody.html +10 -0
- package/docs/hierarchy.html +1 -1
- package/docs/interfaces/ApiCreateUploadSessionResponse.html +7 -0
- package/docs/interfaces/AssetAttachmentPut.html +6 -0
- package/docs/interfaces/AssetCatalogCategory.html +7 -0
- package/docs/interfaces/AssetCatalogResponse.html +6 -0
- package/docs/interfaces/AssetCatalogTooLargeErrorBody.html +15 -0
- package/docs/interfaces/AssetCategoryDelete.html +2 -0
- package/docs/interfaces/AssetCategoryGet.html +14 -0
- package/docs/interfaces/AssetCategoryPut.html +7 -0
- package/docs/interfaces/AssetTypeDelete.html +2 -0
- package/docs/interfaces/AssetTypeGet.html +16 -0
- package/docs/interfaces/AssetTypePut.html +9 -0
- package/docs/interfaces/AttachmentGet.html +20 -0
- package/docs/interfaces/AttachmentPost.html +4 -0
- package/docs/interfaces/ITwinClient.html +155 -49
- package/docs/interfaces/MyPermissions.html +7 -0
- package/docs/interfaces/TwinErrorBody.html +2 -2
- package/docs/interfaces/TwinSpecification.html +1 -1
- package/docs/interfaces/UploadStatusGet.html +3 -0
- package/docs/modules.html +1 -1
- package/docs/types/TwinCapability.html +6 -0
- package/docs/types/TwinErrorCause.html +8 -0
- package/docs/types/TwinErrorItemKind.html +4 -0
- package/docs/types/UploadStatus.html +1 -0
- package/package.json +3 -3
- package/src/BuildInfo.ts +41 -41
- package/src/TwinClient.ts +2334 -1496
- package/src/errors.ts +379 -117
- package/src/index.ts +3 -3
- package/src/types/Twin.ts +7 -7
- package/src/types/TwinGeometryInfo.ts +7 -7
- package/src/types/asset-api.ts +60 -60
- package/src/types/asset-attachment-api.ts +56 -0
- package/src/types/asset-batch-api.ts +88 -88
- package/src/types/asset-types-api.ts +86 -0
- package/src/types/common.ts +10 -10
- package/src/types/generated.ts +574 -574
- package/src/types/index.ts +9 -6
- package/src/types/twin-api.ts +99 -99
- package/src/types/twin-file-api.ts +67 -67
- package/src/types/twin-permissions-api.ts +20 -0
package/src/errors.ts
CHANGED
|
@@ -1,117 +1,379 @@
|
|
|
1
|
-
import type { TwinGet, AssetGet, TwinFileGet, AssetBatchResponse } from './types';
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
}
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
this.
|
|
109
|
-
|
|
110
|
-
}
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
1
|
+
import type { TwinGet, AssetGet, TwinFileGet, AssetBatchResponse, AssetCategoryGet, AssetTypeGet } from './types';
|
|
2
|
+
import type { AttachmentGet } from './types/asset-attachment-api';
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Closed union of `cause` values the Twin service emits on a 400 response. Mirrors
|
|
6
|
+
* `TwinBadRequestCause` in `backend/services/Twinfinity.Twin/Controllers/Model/TwinStatus.cs`.
|
|
7
|
+
* The trailing `(string & {})` keeps autocomplete on the known values while still
|
|
8
|
+
* accepting unknown causes at the type level — a forward-compat pattern: a new
|
|
9
|
+
* cause emitted by a newer server doesn't break older clients that pattern-match
|
|
10
|
+
* on the union. Matches the shape of `TwinCapability` in
|
|
11
|
+
* `types/twin-permissions-api.ts`.
|
|
12
|
+
*/
|
|
13
|
+
export type TwinErrorCause =
|
|
14
|
+
| 'NotAllowedToEditDeletedItem'
|
|
15
|
+
| 'NotAllowedToDeleteItem'
|
|
16
|
+
| 'ImmutableField'
|
|
17
|
+
| 'ReferencedItemNotFound'
|
|
18
|
+
| 'ReferencedItemDeleted'
|
|
19
|
+
| 'FileNotOwnedByTwin'
|
|
20
|
+
| 'DuplicateFileReference'
|
|
21
|
+
| 'MultipleVersionsOfSameFileOnSameNode'
|
|
22
|
+
| 'LimitOutOfRange'
|
|
23
|
+
| 'OffsetOutOfRange'
|
|
24
|
+
| 'IdMismatchBetweenUrlAndBody'
|
|
25
|
+
| 'BatchSizeEmpty'
|
|
26
|
+
| 'BatchSizeExceedsMaximum'
|
|
27
|
+
| 'InvalidParameterCombination'
|
|
28
|
+
| 'DocumentChangeNotFound'
|
|
29
|
+
| 'DeletePermissionRequired'
|
|
30
|
+
| 'CannotEditDeletedFile'
|
|
31
|
+
| 'CannotMoveFileBetweenTwins'
|
|
32
|
+
| 'ContainerDoesNotExist'
|
|
33
|
+
| 'DuplicateContainerIds'
|
|
34
|
+
| 'InsufficientPermissionsOnContainer'
|
|
35
|
+
| 'DuplicateId'
|
|
36
|
+
| 'MetadataTooLarge'
|
|
37
|
+
| 'InvalidTransform'
|
|
38
|
+
| 'InvalidFilePatches'
|
|
39
|
+
| 'MetadataValidationFailed'
|
|
40
|
+
| 'MetadataSchemaInvalid'
|
|
41
|
+
| 'AssetTypeNotFound'
|
|
42
|
+
| 'AssetCategoryAndTypeRequired'
|
|
43
|
+
| 'StringIdInUse'
|
|
44
|
+
| 'CatalogTooLarge'
|
|
45
|
+
| 'EtagRequired'
|
|
46
|
+
// Anything the server emits that this client doesn't know about yet.
|
|
47
|
+
// (string & {}) keeps the autocomplete on the listed values above.
|
|
48
|
+
// eslint-disable-next-line @typescript-eslint/ban-types
|
|
49
|
+
| (string & {});
|
|
50
|
+
|
|
51
|
+
/**
|
|
52
|
+
* Closed union of `item.kind` values the server emits. Mirrors `ItemKind` in
|
|
53
|
+
* `backend/services/Twinfinity.Twin/Model/ItemReference.cs`. Same forward-compat
|
|
54
|
+
* shape as {@link TwinErrorCause}.
|
|
55
|
+
*/
|
|
56
|
+
export type TwinErrorItemKind =
|
|
57
|
+
| 'Twin'
|
|
58
|
+
| 'Asset'
|
|
59
|
+
| 'File'
|
|
60
|
+
| 'DocumentChange'
|
|
61
|
+
| 'AssetCategory'
|
|
62
|
+
| 'AssetType'
|
|
63
|
+
// eslint-disable-next-line @typescript-eslint/ban-types
|
|
64
|
+
| (string & {});
|
|
65
|
+
|
|
66
|
+
export interface TwinErrorBody {
|
|
67
|
+
detail: string;
|
|
68
|
+
cause: TwinErrorCause;
|
|
69
|
+
item?: {
|
|
70
|
+
kind: TwinErrorItemKind;
|
|
71
|
+
id: string;
|
|
72
|
+
version?: number;
|
|
73
|
+
field?: string;
|
|
74
|
+
};
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
/**
|
|
78
|
+
* Parse a non-OK response body as a {@link TwinErrorBody}. Falls back to a
|
|
79
|
+
* synthetic body carrying the response text (or statusText) when the body
|
|
80
|
+
* isn't valid JSON — for example when a WAF or intermediate proxy injects
|
|
81
|
+
* an HTML 4xx page. Callers can therefore always pattern-match on
|
|
82
|
+
* `errorBody.cause` without an outer try/catch around a bare
|
|
83
|
+
* `response.json()`.
|
|
84
|
+
*
|
|
85
|
+
* The synthetic body uses `cause: 'Unknown'`, which is permitted by the
|
|
86
|
+
* `(string & {})` forward-compat tail on {@link TwinErrorCause}. Consumers
|
|
87
|
+
* that switch on known causes will fall through to a default arm.
|
|
88
|
+
*/
|
|
89
|
+
export async function readErrorBody(response: Response): Promise<TwinErrorBody> {
|
|
90
|
+
try {
|
|
91
|
+
const parsed = (await response.json()) as TwinErrorBody;
|
|
92
|
+
// Defensive shape check — JSON-but-not-our-shape (e.g. an upstream
|
|
93
|
+
// ProblemDetails payload from a non-Twinfinity component) should still
|
|
94
|
+
// surface usefully. `detail` is the only field every consumer reads.
|
|
95
|
+
if (parsed && typeof parsed.detail === 'string') return parsed;
|
|
96
|
+
return { detail: JSON.stringify(parsed), cause: 'Unknown' };
|
|
97
|
+
} catch {
|
|
98
|
+
const text = await response.text().catch(() => '');
|
|
99
|
+
return { detail: text || response.statusText || `HTTP ${response.status}`, cause: 'Unknown' };
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
export class TwinValidationError extends Error {
|
|
104
|
+
public readonly errorBody?: TwinErrorBody;
|
|
105
|
+
|
|
106
|
+
constructor(message: string, errorBody?: TwinErrorBody) {
|
|
107
|
+
super(message);
|
|
108
|
+
this.name = 'TwinValidationError';
|
|
109
|
+
this.errorBody = errorBody;
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
export class TwinConflictError extends Error {
|
|
114
|
+
public readonly currentTwin: TwinGet;
|
|
115
|
+
|
|
116
|
+
constructor(message: string, currentTwin: TwinGet) {
|
|
117
|
+
super(message);
|
|
118
|
+
this.name = 'TwinConflictError';
|
|
119
|
+
this.currentTwin = currentTwin;
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
export class TwinNotFoundError extends Error {
|
|
124
|
+
constructor(message: string) {
|
|
125
|
+
super(message);
|
|
126
|
+
this.name = 'TwinNotFoundError';
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
export class ProcessorNotFoundError extends Error {
|
|
131
|
+
constructor(message: string) {
|
|
132
|
+
super(message);
|
|
133
|
+
this.name = 'ProcessorNotFoundError';
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
export class AssetValidationError extends Error {
|
|
138
|
+
public readonly errorBody?: TwinErrorBody;
|
|
139
|
+
|
|
140
|
+
constructor(message: string, errorBody?: TwinErrorBody) {
|
|
141
|
+
super(message);
|
|
142
|
+
this.name = 'AssetValidationError';
|
|
143
|
+
this.errorBody = errorBody;
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
export class AssetForbiddenError extends Error {
|
|
148
|
+
constructor(message: string) {
|
|
149
|
+
super(message);
|
|
150
|
+
this.name = 'AssetForbiddenError';
|
|
151
|
+
}
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
export class AssetConflictError extends Error {
|
|
155
|
+
public readonly currentAsset: AssetGet;
|
|
156
|
+
|
|
157
|
+
constructor(message: string, currentAsset: AssetGet) {
|
|
158
|
+
super(message);
|
|
159
|
+
this.name = 'AssetConflictError';
|
|
160
|
+
this.currentAsset = currentAsset;
|
|
161
|
+
}
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
export class AssetNotFoundError extends Error {
|
|
165
|
+
constructor(message: string) {
|
|
166
|
+
super(message);
|
|
167
|
+
this.name = 'AssetNotFoundError';
|
|
168
|
+
}
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
export class AssetAttachmentConflictError extends Error {
|
|
172
|
+
public readonly currentAttachment: AttachmentGet;
|
|
173
|
+
|
|
174
|
+
constructor(message: string, currentAttachment: AttachmentGet) {
|
|
175
|
+
super(message);
|
|
176
|
+
this.name = 'AssetAttachmentConflictError';
|
|
177
|
+
this.currentAttachment = currentAttachment;
|
|
178
|
+
}
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
export class AssetAttachmentNotFoundError extends Error {
|
|
182
|
+
constructor(message: string) {
|
|
183
|
+
super(message);
|
|
184
|
+
this.name = 'AssetAttachmentNotFoundError';
|
|
185
|
+
}
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
export class AssetBatchError extends Error {
|
|
189
|
+
public readonly response: AssetBatchResponse;
|
|
190
|
+
|
|
191
|
+
constructor(message: string, response: AssetBatchResponse) {
|
|
192
|
+
super(message);
|
|
193
|
+
this.name = 'AssetBatchError';
|
|
194
|
+
this.response = response;
|
|
195
|
+
}
|
|
196
|
+
}
|
|
197
|
+
|
|
198
|
+
export class TwinFileValidationError extends Error {
|
|
199
|
+
public readonly errorBody?: TwinErrorBody;
|
|
200
|
+
|
|
201
|
+
constructor(message: string, errorBody?: TwinErrorBody) {
|
|
202
|
+
super(message);
|
|
203
|
+
this.name = 'TwinFileValidationError';
|
|
204
|
+
this.errorBody = errorBody;
|
|
205
|
+
}
|
|
206
|
+
}
|
|
207
|
+
|
|
208
|
+
export class TwinFileConflictError extends Error {
|
|
209
|
+
public readonly currentTwinFile: TwinFileGet;
|
|
210
|
+
|
|
211
|
+
constructor(message: string, currentTwinFile: TwinFileGet) {
|
|
212
|
+
super(message);
|
|
213
|
+
this.name = 'TwinFileConflictError';
|
|
214
|
+
this.currentTwinFile = currentTwinFile;
|
|
215
|
+
}
|
|
216
|
+
}
|
|
217
|
+
|
|
218
|
+
export class TwinFileNotFoundError extends Error {
|
|
219
|
+
constructor(message: string) {
|
|
220
|
+
super(message);
|
|
221
|
+
this.name = 'TwinFileNotFoundError';
|
|
222
|
+
}
|
|
223
|
+
}
|
|
224
|
+
|
|
225
|
+
// ---------- Asset categories ----------
|
|
226
|
+
|
|
227
|
+
export class AssetCategoryValidationError extends Error {
|
|
228
|
+
public readonly errorBody?: TwinErrorBody;
|
|
229
|
+
|
|
230
|
+
constructor(message: string, errorBody?: TwinErrorBody) {
|
|
231
|
+
super(message);
|
|
232
|
+
this.name = 'AssetCategoryValidationError';
|
|
233
|
+
this.errorBody = errorBody;
|
|
234
|
+
}
|
|
235
|
+
}
|
|
236
|
+
|
|
237
|
+
export class AssetCategoryConflictError extends Error {
|
|
238
|
+
public readonly currentCategory: AssetCategoryGet;
|
|
239
|
+
|
|
240
|
+
constructor(message: string, currentCategory: AssetCategoryGet) {
|
|
241
|
+
super(message);
|
|
242
|
+
this.name = 'AssetCategoryConflictError';
|
|
243
|
+
this.currentCategory = currentCategory;
|
|
244
|
+
}
|
|
245
|
+
}
|
|
246
|
+
|
|
247
|
+
export class AssetCategoryNotFoundError extends Error {
|
|
248
|
+
constructor(message: string) {
|
|
249
|
+
super(message);
|
|
250
|
+
this.name = 'AssetCategoryNotFoundError';
|
|
251
|
+
}
|
|
252
|
+
}
|
|
253
|
+
|
|
254
|
+
export class AssetCategoryForbiddenError extends Error {
|
|
255
|
+
constructor(message: string) {
|
|
256
|
+
super(message);
|
|
257
|
+
this.name = 'AssetCategoryForbiddenError';
|
|
258
|
+
}
|
|
259
|
+
}
|
|
260
|
+
|
|
261
|
+
// ---------- Asset types ----------
|
|
262
|
+
|
|
263
|
+
export class AssetTypeValidationError extends Error {
|
|
264
|
+
public readonly errorBody?: TwinErrorBody;
|
|
265
|
+
|
|
266
|
+
constructor(message: string, errorBody?: TwinErrorBody) {
|
|
267
|
+
super(message);
|
|
268
|
+
this.name = 'AssetTypeValidationError';
|
|
269
|
+
this.errorBody = errorBody;
|
|
270
|
+
}
|
|
271
|
+
}
|
|
272
|
+
|
|
273
|
+
export class AssetTypeConflictError extends Error {
|
|
274
|
+
public readonly currentType: AssetTypeGet;
|
|
275
|
+
|
|
276
|
+
constructor(message: string, currentType: AssetTypeGet) {
|
|
277
|
+
super(message);
|
|
278
|
+
this.name = 'AssetTypeConflictError';
|
|
279
|
+
this.currentType = currentType;
|
|
280
|
+
}
|
|
281
|
+
}
|
|
282
|
+
|
|
283
|
+
export class AssetTypeNotFoundError extends Error {
|
|
284
|
+
constructor(message: string) {
|
|
285
|
+
super(message);
|
|
286
|
+
this.name = 'AssetTypeNotFoundError';
|
|
287
|
+
}
|
|
288
|
+
}
|
|
289
|
+
|
|
290
|
+
export class AssetTypeForbiddenError extends Error {
|
|
291
|
+
constructor(message: string) {
|
|
292
|
+
super(message);
|
|
293
|
+
this.name = 'AssetTypeForbiddenError';
|
|
294
|
+
}
|
|
295
|
+
}
|
|
296
|
+
|
|
297
|
+
// ---------- Asset catalog ----------
|
|
298
|
+
|
|
299
|
+
/**
|
|
300
|
+
* Wire shape returned by `GET /asset-type-catalog` with a 400 when the
|
|
301
|
+
* tenant's catalog can't be served as a single round-trip — same shape as
|
|
302
|
+
* {@link TwinErrorBody} plus structured counts so picker UIs can render a
|
|
303
|
+
* precise message without parsing `detail`.
|
|
304
|
+
*
|
|
305
|
+
* Mirrors `AssetCatalogTooLargeResponse` in
|
|
306
|
+
* `backend/services/Twinfinity.Twin/Controllers/Model/AssetCatalogDtos.cs`.
|
|
307
|
+
*/
|
|
308
|
+
export interface AssetCatalogTooLargeErrorBody extends TwinErrorBody {
|
|
309
|
+
cause: 'CatalogTooLarge';
|
|
310
|
+
categoriesCount: number;
|
|
311
|
+
typesCount: number;
|
|
312
|
+
maxCatalogSize: number;
|
|
313
|
+
categoriesOverflowed: boolean;
|
|
314
|
+
typesOverflowed: boolean;
|
|
315
|
+
}
|
|
316
|
+
|
|
317
|
+
/**
|
|
318
|
+
* Thrown by `getAssetTypeCatalog` when the customer's catalog exceeds the
|
|
319
|
+
* per-customer cap. The catalog endpoint is a single-round-trip view; tenants
|
|
320
|
+
* over the cap must switch to a paginated endpoint (not yet shipped). Surfaced
|
|
321
|
+
* as a hard failure rather than silent truncation so picker UIs can render
|
|
322
|
+
* "too many rows, use search" instead of "out of types."
|
|
323
|
+
*
|
|
324
|
+
* `categoriesOverflowed` / `typesOverflowed` identify which side(s) breached
|
|
325
|
+
* the cap; both can be true. `categoriesCount` / `typesCount` are the observed
|
|
326
|
+
* counts (≥ `maxCatalogSize` for the overflowing side(s)).
|
|
327
|
+
*/
|
|
328
|
+
export class AssetCatalogTooLargeError extends Error {
|
|
329
|
+
public readonly errorBody: AssetCatalogTooLargeErrorBody;
|
|
330
|
+
public readonly categoriesCount: number;
|
|
331
|
+
public readonly typesCount: number;
|
|
332
|
+
public readonly maxCatalogSize: number;
|
|
333
|
+
public readonly categoriesOverflowed: boolean;
|
|
334
|
+
public readonly typesOverflowed: boolean;
|
|
335
|
+
|
|
336
|
+
constructor(message: string, errorBody: AssetCatalogTooLargeErrorBody) {
|
|
337
|
+
super(message);
|
|
338
|
+
this.name = 'AssetCatalogTooLargeError';
|
|
339
|
+
this.errorBody = errorBody;
|
|
340
|
+
this.categoriesCount = errorBody.categoriesCount;
|
|
341
|
+
this.typesCount = errorBody.typesCount;
|
|
342
|
+
this.maxCatalogSize = errorBody.maxCatalogSize;
|
|
343
|
+
this.categoriesOverflowed = errorBody.categoriesOverflowed;
|
|
344
|
+
this.typesOverflowed = errorBody.typesOverflowed;
|
|
345
|
+
}
|
|
346
|
+
}
|
|
347
|
+
|
|
348
|
+
/**
|
|
349
|
+
* Type guard for a {@link TwinErrorBody} that carries `CatalogTooLarge`
|
|
350
|
+
* with the structured count fields the dedicated wire shape adds on top of
|
|
351
|
+
* the standard envelope. Used by the client to decide whether to throw a
|
|
352
|
+
* typed {@link AssetCatalogTooLargeError} or fall through to a generic
|
|
353
|
+
* validation error when the server sends a malformed payload.
|
|
354
|
+
*/
|
|
355
|
+
export function isAssetCatalogTooLargeErrorBody(body: TwinErrorBody): body is AssetCatalogTooLargeErrorBody {
|
|
356
|
+
return (
|
|
357
|
+
body.cause === 'CatalogTooLarge' &&
|
|
358
|
+
typeof (body as Partial<AssetCatalogTooLargeErrorBody>).categoriesCount === 'number' &&
|
|
359
|
+
typeof (body as Partial<AssetCatalogTooLargeErrorBody>).typesCount === 'number' &&
|
|
360
|
+
typeof (body as Partial<AssetCatalogTooLargeErrorBody>).maxCatalogSize === 'number' &&
|
|
361
|
+
typeof (body as Partial<AssetCatalogTooLargeErrorBody>).categoriesOverflowed === 'boolean' &&
|
|
362
|
+
typeof (body as Partial<AssetCatalogTooLargeErrorBody>).typesOverflowed === 'boolean'
|
|
363
|
+
);
|
|
364
|
+
}
|
|
365
|
+
|
|
366
|
+
// ---------- Authentication ----------
|
|
367
|
+
|
|
368
|
+
/**
|
|
369
|
+
* Thrown when the server returns 401 (Unauthorized). Distinct from forbidden
|
|
370
|
+
* errors: 401 means "no valid auth context" (the caller should redirect to
|
|
371
|
+
* login / refresh tokens), while 403 means "authenticated but not granted"
|
|
372
|
+
* (the UI should surface a permissions hint or render disabled affordances).
|
|
373
|
+
*/
|
|
374
|
+
export class TwinUnauthenticatedError extends Error {
|
|
375
|
+
constructor(message: string) {
|
|
376
|
+
super(message);
|
|
377
|
+
this.name = 'TwinUnauthenticatedError';
|
|
378
|
+
}
|
|
379
|
+
}
|
package/src/index.ts
CHANGED
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
export { type ITwinClient, TwinClient } from './TwinClient';
|
|
2
|
-
export * from './types';
|
|
3
|
-
export * from './errors';
|
|
1
|
+
export { type ITwinClient, TwinClient } from './TwinClient';
|
|
2
|
+
export * from './types';
|
|
3
|
+
export * from './errors';
|
package/src/types/Twin.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import { T8ClientModel } from '@twinfinity/t8-client-model';
|
|
2
|
-
|
|
3
|
-
export class Twin<TProject, TProduct, TEntityType, TUnit> {
|
|
4
|
-
id: string;
|
|
5
|
-
version: number;
|
|
6
|
-
model?: T8ClientModel<TProject, TProduct, TEntityType, TUnit>;
|
|
7
|
-
}
|
|
1
|
+
import { T8ClientModel } from '@twinfinity/t8-client-model';
|
|
2
|
+
|
|
3
|
+
export class Twin<TProject, TProduct, TEntityType, TUnit> {
|
|
4
|
+
id: string;
|
|
5
|
+
version: number;
|
|
6
|
+
model?: T8ClientModel<TProject, TProduct, TEntityType, TUnit>;
|
|
7
|
+
}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import type { T8GIModelGeneric } from '@twinfinity/t8-client-model';
|
|
2
|
-
|
|
3
|
-
export interface TwinGeometryInfo<TMeshDescriptor, TStyle, TRegion> {
|
|
4
|
-
id: string;
|
|
5
|
-
version: number;
|
|
6
|
-
model?: T8GIModelGeneric<TMeshDescriptor, TStyle, TRegion>;
|
|
7
|
-
}
|
|
1
|
+
import type { T8GIModelGeneric } from '@twinfinity/t8-client-model';
|
|
2
|
+
|
|
3
|
+
export interface TwinGeometryInfo<TMeshDescriptor, TStyle, TRegion> {
|
|
4
|
+
id: string;
|
|
5
|
+
version: number;
|
|
6
|
+
model?: T8GIModelGeneric<TMeshDescriptor, TStyle, TRegion>;
|
|
7
|
+
}
|
package/src/types/asset-api.ts
CHANGED
|
@@ -1,60 +1,60 @@
|
|
|
1
|
-
export interface AssetListItem {
|
|
2
|
-
id: string;
|
|
3
|
-
name: string;
|
|
4
|
-
category?: string;
|
|
5
|
-
type?: string;
|
|
6
|
-
twinReference?: string;
|
|
7
|
-
parentIfcGid?: string;
|
|
8
|
-
ifcGid?: string;
|
|
9
|
-
etag: string;
|
|
10
|
-
createdAt: string;
|
|
11
|
-
isDeleted?: boolean;
|
|
12
|
-
}
|
|
13
|
-
|
|
14
|
-
export interface AssetPosition {
|
|
15
|
-
x?: number;
|
|
16
|
-
y?: number;
|
|
17
|
-
z?: number;
|
|
18
|
-
}
|
|
19
|
-
|
|
20
|
-
export interface AssetGet {
|
|
21
|
-
id: string;
|
|
22
|
-
name: string;
|
|
23
|
-
category?: string;
|
|
24
|
-
type?: string;
|
|
25
|
-
ifcGid?: string;
|
|
26
|
-
twinReference?: string;
|
|
27
|
-
position?: AssetPosition;
|
|
28
|
-
parentIfcGid?: string;
|
|
29
|
-
metadata?: Record<string, unknown>;
|
|
30
|
-
etag: string;
|
|
31
|
-
createdUtc: string;
|
|
32
|
-
createdBy: string;
|
|
33
|
-
modifiedUtc: string;
|
|
34
|
-
modifiedBy: string;
|
|
35
|
-
isDeleted?: boolean;
|
|
36
|
-
}
|
|
37
|
-
|
|
38
|
-
export interface AssetPost {
|
|
39
|
-
id?: string;
|
|
40
|
-
name: string;
|
|
41
|
-
category?: string;
|
|
42
|
-
type?: string;
|
|
43
|
-
ifcGid?: string;
|
|
44
|
-
position?: AssetPosition;
|
|
45
|
-
parentIfcGid?: string;
|
|
46
|
-
metadata?: Record<string, unknown>;
|
|
47
|
-
twinReference?: string;
|
|
48
|
-
}
|
|
49
|
-
|
|
50
|
-
export interface AssetPut {
|
|
51
|
-
etag: string;
|
|
52
|
-
name: string;
|
|
53
|
-
category?: string;
|
|
54
|
-
type?: string;
|
|
55
|
-
ifcGid?: string;
|
|
56
|
-
position?: AssetPosition;
|
|
57
|
-
parentIfcGid?: string;
|
|
58
|
-
metadata?: Record<string, unknown>;
|
|
59
|
-
twinReference?: string;
|
|
60
|
-
}
|
|
1
|
+
export interface AssetListItem {
|
|
2
|
+
id: string;
|
|
3
|
+
name: string;
|
|
4
|
+
category?: string;
|
|
5
|
+
type?: string;
|
|
6
|
+
twinReference?: string;
|
|
7
|
+
parentIfcGid?: string;
|
|
8
|
+
ifcGid?: string;
|
|
9
|
+
etag: string;
|
|
10
|
+
createdAt: string;
|
|
11
|
+
isDeleted?: boolean;
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
export interface AssetPosition {
|
|
15
|
+
x?: number;
|
|
16
|
+
y?: number;
|
|
17
|
+
z?: number;
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
export interface AssetGet {
|
|
21
|
+
id: string;
|
|
22
|
+
name: string;
|
|
23
|
+
category?: string;
|
|
24
|
+
type?: string;
|
|
25
|
+
ifcGid?: string;
|
|
26
|
+
twinReference?: string;
|
|
27
|
+
position?: AssetPosition;
|
|
28
|
+
parentIfcGid?: string;
|
|
29
|
+
metadata?: Record<string, unknown>;
|
|
30
|
+
etag: string;
|
|
31
|
+
createdUtc: string;
|
|
32
|
+
createdBy: string;
|
|
33
|
+
modifiedUtc: string;
|
|
34
|
+
modifiedBy: string;
|
|
35
|
+
isDeleted?: boolean;
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
export interface AssetPost {
|
|
39
|
+
id?: string;
|
|
40
|
+
name: string;
|
|
41
|
+
category?: string;
|
|
42
|
+
type?: string;
|
|
43
|
+
ifcGid?: string;
|
|
44
|
+
position?: AssetPosition;
|
|
45
|
+
parentIfcGid?: string;
|
|
46
|
+
metadata?: Record<string, unknown>;
|
|
47
|
+
twinReference?: string;
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
export interface AssetPut {
|
|
51
|
+
etag: string;
|
|
52
|
+
name: string;
|
|
53
|
+
category?: string;
|
|
54
|
+
type?: string;
|
|
55
|
+
ifcGid?: string;
|
|
56
|
+
position?: AssetPosition;
|
|
57
|
+
parentIfcGid?: string;
|
|
58
|
+
metadata?: Record<string, unknown>;
|
|
59
|
+
twinReference?: string;
|
|
60
|
+
}
|