@twinfinity/twin 6.1.1 → 6.1.2-ci.31342
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 +63 -2
- package/dist/BuildInfo.js +3 -3
- package/dist/TwinClient.d.ts +312 -9
- package/dist/TwinClient.d.ts.map +1 -1
- package/dist/TwinClient.js +321 -6
- package/dist/TwinClient.js.map +1 -1
- package/dist/errors.d.ts +120 -5
- package/dist/errors.d.ts.map +1 -1
- package/dist/errors.js +116 -2
- package/dist/errors.js.map +1 -1
- package/dist/tsconfig.tsbuildinfo +1 -1
- package/dist/types/generated.d.ts +95 -33
- package/dist/types/generated.d.ts.map +1 -1
- package/dist/types/twin-api.d.ts +54 -1
- package/dist/types/twin-api.d.ts.map +1 -1
- package/dist/types/twin-permissions-api.d.ts +226 -6
- package/dist/types/twin-permissions-api.d.ts.map +1 -1
- 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 +1 -1
- package/docs/classes/AssetAttachmentNotFoundError.html +1 -1
- package/docs/classes/AssetBatchError.html +1 -1
- package/docs/classes/AssetCatalogTooLargeError.html +1 -1
- package/docs/classes/AssetCategoryConflictError.html +1 -1
- package/docs/classes/AssetCategoryForbiddenError.html +1 -1
- package/docs/classes/AssetCategoryNotFoundError.html +1 -1
- package/docs/classes/AssetCategoryValidationError.html +1 -1
- package/docs/classes/AssetConflictError.html +1 -1
- package/docs/classes/AssetForbiddenError.html +1 -1
- package/docs/classes/AssetNotFoundError.html +1 -1
- package/docs/classes/AssetPermissionsConflictError.html +16 -0
- package/docs/classes/AssetTypeConflictError.html +1 -1
- package/docs/classes/AssetTypeForbiddenError.html +1 -1
- package/docs/classes/AssetTypeNotFoundError.html +1 -1
- package/docs/classes/AssetTypeValidationError.html +1 -1
- package/docs/classes/AssetValidationError.html +1 -1
- package/docs/classes/ProcessorNotFoundError.html +1 -1
- package/docs/classes/TwinClient.html +251 -73
- 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 +4 -2
- package/docs/classes/TwinPermissionsConflictError.html +19 -0
- package/docs/classes/TwinPermissionsForbiddenError.html +12 -0
- package/docs/classes/TwinPrincipalNotFoundError.html +5 -0
- package/docs/classes/TwinTemporarilyUnavailableError.html +10 -0
- package/docs/classes/TwinUnauthenticatedError.html +1 -1
- package/docs/classes/TwinValidationError.html +1 -1
- package/docs/hierarchy.html +1 -1
- package/docs/index.html +56 -4
- package/docs/interfaces/AssetCatalogTooLargeErrorBody.html +2 -2
- package/docs/interfaces/AssetGroupGet.html +9 -0
- package/docs/interfaces/AssetGroupsGet.html +3 -0
- package/docs/interfaces/AssetPermissionsConflictErrorBody.html +12 -0
- package/docs/interfaces/AssetPermissionsPut.html +9 -0
- package/docs/interfaces/AssetPrincipalPermissionsGet.html +23 -0
- package/docs/interfaces/Coordinates.html +6 -0
- package/docs/interfaces/EntityCollection.html +7 -2
- package/docs/interfaces/EntityRepresentation.html +12 -0
- package/docs/interfaces/Facility.html +8 -3
- package/docs/interfaces/FacilityPart.html +5 -3
- package/docs/interfaces/ITwinClient.html +251 -73
- package/docs/interfaces/InheritedPermissions.html +8 -0
- package/docs/interfaces/ListTwinItem.html +18 -2
- package/docs/interfaces/Location.html +4 -1
- package/docs/interfaces/MyPermissions.html +2 -2
- package/docs/interfaces/MyTwinPermissions.html +5 -0
- package/docs/interfaces/Site.html +11 -4
- package/docs/interfaces/Space.html +6 -3
- package/docs/interfaces/TwinErrorBody.html +2 -2
- package/docs/interfaces/TwinGet.html +29 -11
- package/docs/interfaces/TwinGroupGet.html +10 -0
- package/docs/interfaces/TwinGroupsGet.html +3 -0
- package/docs/interfaces/TwinPermissionsConflictErrorBody.html +8 -0
- package/docs/interfaces/TwinPermissionsPut.html +11 -0
- package/docs/interfaces/TwinPrincipalPermissionsGet.html +34 -0
- package/docs/interfaces/TwinPut.html +8 -10
- package/docs/interfaces/TwinReference.html +4 -0
- package/docs/interfaces/TwinSpecification.html +7 -9
- package/docs/media/twin-management.md +197 -0
- package/docs/modules.html +1 -1
- package/docs/types/SinglePropertyValueType.html +1 -1
- package/docs/types/TwinBoundCapabilityName.html +8 -0
- package/docs/types/TwinCapability.html +11 -5
- package/docs/types/TwinCapabilityName.html +8 -0
- package/docs/types/TwinDiagnosticCode.html +1 -1
- package/docs/types/TwinErrorCause.html +1 -1
- package/docs/types/TwinErrorItemKind.html +1 -1
- package/docs/types/TwinPermissionsConflictCause.html +6 -0
- package/docs/types/TwinScopedCapability.html +9 -0
- package/docs/types/TwinScopedCapabilityName.html +8 -0
- package/package.json +3 -3
- package/src/TwinClient.ts +776 -15
- package/src/errors.ts +191 -4
- package/src/types/generated.ts +105 -35
- package/src/types/twin-api.ts +55 -1
- package/src/types/twin-permissions-api.ts +243 -6
package/src/errors.ts
CHANGED
|
@@ -1,4 +1,13 @@
|
|
|
1
|
-
import type {
|
|
1
|
+
import type {
|
|
2
|
+
TwinGet,
|
|
3
|
+
AssetGet,
|
|
4
|
+
TwinFileGet,
|
|
5
|
+
AssetBatchResponse,
|
|
6
|
+
AssetCategoryGet,
|
|
7
|
+
AssetTypeGet,
|
|
8
|
+
TwinPrincipalPermissionsGet,
|
|
9
|
+
AssetPrincipalPermissionsGet
|
|
10
|
+
} from './types';
|
|
2
11
|
import type { AttachmentGet } from './types/asset-attachment-api';
|
|
3
12
|
|
|
4
13
|
/**
|
|
@@ -43,6 +52,10 @@ export type TwinErrorCause =
|
|
|
43
52
|
| 'StringIdInUse'
|
|
44
53
|
| 'CatalogTooLarge'
|
|
45
54
|
| 'EtagRequired'
|
|
55
|
+
| 'InvalidPaginationToken'
|
|
56
|
+
| 'SystemPrincipalImmutable'
|
|
57
|
+
| 'ManagePermissionsNotGrantableToAllAuthenticated'
|
|
58
|
+
| 'ValidationFailed'
|
|
46
59
|
// Anything the server emits that this client doesn't know about yet.
|
|
47
60
|
// (string & {}) keeps the autocomplete on the listed values above.
|
|
48
61
|
// eslint-disable-next-line @typescript-eslint/ban-types
|
|
@@ -60,6 +73,10 @@ export type TwinErrorItemKind =
|
|
|
60
73
|
| 'DocumentChange'
|
|
61
74
|
| 'AssetCategory'
|
|
62
75
|
| 'AssetType'
|
|
76
|
+
| 'Attachment'
|
|
77
|
+
| 'Document'
|
|
78
|
+
| 'Principal'
|
|
79
|
+
| 'Request'
|
|
63
80
|
// eslint-disable-next-line @typescript-eslint/ban-types
|
|
64
81
|
| (string & {});
|
|
65
82
|
|
|
@@ -68,7 +85,9 @@ export interface TwinErrorBody {
|
|
|
68
85
|
cause: TwinErrorCause;
|
|
69
86
|
item?: {
|
|
70
87
|
kind: TwinErrorItemKind;
|
|
71
|
-
id
|
|
88
|
+
// Absent when the reference names something that has no id — a `Request` kind
|
|
89
|
+
// carries only `field`, the request member that failed validation.
|
|
90
|
+
id?: string;
|
|
72
91
|
version?: number;
|
|
73
92
|
field?: string;
|
|
74
93
|
};
|
|
@@ -87,8 +106,12 @@ export interface TwinErrorBody {
|
|
|
87
106
|
* that switch on known causes will fall through to a default arm.
|
|
88
107
|
*/
|
|
89
108
|
export async function readErrorBody(response: Response): Promise<TwinErrorBody> {
|
|
109
|
+
// Parse a clone, so that a body which turns out not to be JSON can still be read as text below.
|
|
110
|
+
// `json()` consumes the stream: on a real Response, reading the original here would leave the
|
|
111
|
+
// fallback unreachable and every non-JSON diagnostic would degrade to `statusText`.
|
|
112
|
+
const parseFrom = typeof response.clone === 'function' ? response.clone() : response;
|
|
90
113
|
try {
|
|
91
|
-
const parsed = (await
|
|
114
|
+
const parsed = (await parseFrom.json()) as TwinErrorBody;
|
|
92
115
|
// Defensive shape check — JSON-but-not-our-shape (e.g. an upstream
|
|
93
116
|
// ProblemDetails payload from a non-Twinfinity component) should still
|
|
94
117
|
// surface usefully. `detail` is the only field every consumer reads.
|
|
@@ -121,9 +144,13 @@ export class TwinConflictError extends Error {
|
|
|
121
144
|
}
|
|
122
145
|
|
|
123
146
|
export class TwinNotFoundError extends Error {
|
|
124
|
-
|
|
147
|
+
/** The server's envelope, when there was one — `item.kind` names what was not found. */
|
|
148
|
+
public readonly errorBody?: TwinErrorBody;
|
|
149
|
+
|
|
150
|
+
constructor(message: string, errorBody?: TwinErrorBody) {
|
|
125
151
|
super(message);
|
|
126
152
|
this.name = 'TwinNotFoundError';
|
|
153
|
+
this.errorBody = errorBody;
|
|
127
154
|
}
|
|
128
155
|
}
|
|
129
156
|
|
|
@@ -377,3 +404,163 @@ export class TwinUnauthenticatedError extends Error {
|
|
|
377
404
|
this.name = 'TwinUnauthenticatedError';
|
|
378
405
|
}
|
|
379
406
|
}
|
|
407
|
+
|
|
408
|
+
// ---------- Twin-scoped permissions ----------
|
|
409
|
+
|
|
410
|
+
/**
|
|
411
|
+
* The `cause` values the twin-scoped permission routes emit on a 409. A subset of
|
|
412
|
+
* `TwinConflictCause` in `backend/services/Twinfinity.Twin/Controllers/Model/TwinStatus.cs`:
|
|
413
|
+
* that enum's `GroupIdAlreadyInUse` and `ScopeIdAlreadyInUse` are raised by twin *creation*,
|
|
414
|
+
* which answers through {@link TwinConflictError}, never through this surface. Carries the same
|
|
415
|
+
* forward-compat tail as {@link TwinErrorCause}.
|
|
416
|
+
*/
|
|
417
|
+
export type TwinPermissionsConflictCause =
|
|
418
|
+
| 'EtagMismatch'
|
|
419
|
+
| 'EtagRequired'
|
|
420
|
+
| 'ScopesNotProvisioned'
|
|
421
|
+
// eslint-disable-next-line @typescript-eslint/ban-types
|
|
422
|
+
| (string & {});
|
|
423
|
+
|
|
424
|
+
/**
|
|
425
|
+
* The 409 envelope of the twin-scoped permission surface: the standard
|
|
426
|
+
* {@link TwinErrorBody} plus the server's view of the entry the caller lost a race on,
|
|
427
|
+
* whenever the service could report it.
|
|
428
|
+
*/
|
|
429
|
+
export interface TwinPermissionsConflictErrorBody extends TwinErrorBody {
|
|
430
|
+
cause: TwinPermissionsConflictCause;
|
|
431
|
+
currentState?: TwinPrincipalPermissionsGet;
|
|
432
|
+
}
|
|
433
|
+
|
|
434
|
+
/**
|
|
435
|
+
* Thrown by the twin permission mutation and listing methods on a 409.
|
|
436
|
+
*
|
|
437
|
+
* The three causes need different handling, which is why they are distinguishable
|
|
438
|
+
* rather than collapsed into one "modified by another user":
|
|
439
|
+
* - `EtagMismatch` — the etag is stale; re-read (or use {@link currentState}) and retry.
|
|
440
|
+
* - `EtagRequired` — the write omitted an etag but the principal already held an entry,
|
|
441
|
+
* so it would have replaced state the caller never read. Retried by reading at all.
|
|
442
|
+
* - `ScopesNotProvisioned` — the twin owns no Twinfinity scope, so there is no permission
|
|
443
|
+
* state to read or write. Nothing provisions on read, so retrying will not help.
|
|
444
|
+
*/
|
|
445
|
+
export class TwinPermissionsConflictError extends Error {
|
|
446
|
+
/**
|
|
447
|
+
* Which of the three conflicts this is. Named `conflictCause` rather than `cause` so the
|
|
448
|
+
* standard `Error.cause` — whose consumers expect a wrapped error, not a string — is left
|
|
449
|
+
* alone; the same value is on {@link errorBody}`.cause`.
|
|
450
|
+
*/
|
|
451
|
+
public readonly conflictCause: TwinPermissionsConflictCause;
|
|
452
|
+
/** The entry as the server holds it, including the etag to retry with. */
|
|
453
|
+
public readonly currentState?: TwinPrincipalPermissionsGet;
|
|
454
|
+
public readonly errorBody: TwinPermissionsConflictErrorBody;
|
|
455
|
+
|
|
456
|
+
constructor(message: string, errorBody: TwinPermissionsConflictErrorBody) {
|
|
457
|
+
super(message);
|
|
458
|
+
this.name = 'TwinPermissionsConflictError';
|
|
459
|
+
this.conflictCause = errorBody.cause;
|
|
460
|
+
this.currentState = errorBody.currentState;
|
|
461
|
+
this.errorBody = errorBody;
|
|
462
|
+
}
|
|
463
|
+
}
|
|
464
|
+
|
|
465
|
+
/**
|
|
466
|
+
* Thrown on a 403 from the twin-scoped permission surface: the caller can see the twin
|
|
467
|
+
* but does not hold `ManageTwinPermissions` on it. Distinct from
|
|
468
|
+
* {@link TwinNotFoundError}, which is what a twin the caller cannot see at all answers —
|
|
469
|
+
* the surface refuses to confirm such a twin exists.
|
|
470
|
+
*/
|
|
471
|
+
export class TwinPermissionsForbiddenError extends Error {
|
|
472
|
+
/**
|
|
473
|
+
* The server's envelope, when there was one. Its presence is load-bearing: a genuine refusal
|
|
474
|
+
* carries `cause: 'InsufficientPermissions'`, while a Twin service that could not evaluate the
|
|
475
|
+
* request at all (a customer-database lookup that threw, a missing twin feature) falls through
|
|
476
|
+
* to the framework's default forbid handler and answers a 403 with no body. Without this a
|
|
477
|
+
* caller cannot tell "you may not" from "we could not tell", and would report the first.
|
|
478
|
+
*/
|
|
479
|
+
public readonly errorBody?: TwinErrorBody;
|
|
480
|
+
|
|
481
|
+
constructor(message: string, errorBody?: TwinErrorBody) {
|
|
482
|
+
super(message);
|
|
483
|
+
this.name = 'TwinPermissionsForbiddenError';
|
|
484
|
+
this.errorBody = errorBody;
|
|
485
|
+
}
|
|
486
|
+
}
|
|
487
|
+
|
|
488
|
+
/**
|
|
489
|
+
* Thrown when a 404 names the principal rather than the twin — an id that no principal
|
|
490
|
+
* in the tenant carries, or one holding nothing on the twin for a `DELETE` to revoke.
|
|
491
|
+
*/
|
|
492
|
+
export class TwinPrincipalNotFoundError extends Error {
|
|
493
|
+
public readonly errorBody?: TwinErrorBody;
|
|
494
|
+
|
|
495
|
+
constructor(message: string, errorBody?: TwinErrorBody) {
|
|
496
|
+
super(message);
|
|
497
|
+
this.name = 'TwinPrincipalNotFoundError';
|
|
498
|
+
this.errorBody = errorBody;
|
|
499
|
+
}
|
|
500
|
+
}
|
|
501
|
+
|
|
502
|
+
/**
|
|
503
|
+
* Thrown on a 503: the Twin service could neither carry out the request nor answer it
|
|
504
|
+
* truthfully. The request is unchanged and safe to retry as-is — unlike
|
|
505
|
+
* {@link TwinPermissionsConflictError}, which never clears on its own.
|
|
506
|
+
*/
|
|
507
|
+
export class TwinTemporarilyUnavailableError extends Error {
|
|
508
|
+
public readonly errorBody?: TwinErrorBody;
|
|
509
|
+
/**
|
|
510
|
+
* The `Retry-After` the service sent, in seconds, when it sent one. The Twin service pairs the
|
|
511
|
+
* status with this header deliberately, so that "retrying is worthwhile" does not rest on the
|
|
512
|
+
* status alone — pass it to whatever backoff the caller uses instead of inventing a delay.
|
|
513
|
+
*/
|
|
514
|
+
public readonly retryAfterSeconds?: number;
|
|
515
|
+
|
|
516
|
+
constructor(message: string, errorBody?: TwinErrorBody, retryAfterSeconds?: number) {
|
|
517
|
+
super(message);
|
|
518
|
+
this.name = 'TwinTemporarilyUnavailableError';
|
|
519
|
+
this.errorBody = errorBody;
|
|
520
|
+
this.retryAfterSeconds = retryAfterSeconds;
|
|
521
|
+
}
|
|
522
|
+
}
|
|
523
|
+
|
|
524
|
+
// ---------- Asset-domain permissions ----------
|
|
525
|
+
|
|
526
|
+
/**
|
|
527
|
+
* The 409 envelope of the customer-wide asset permission surface. The same shape as
|
|
528
|
+
* {@link TwinPermissionsConflictErrorBody}, but `currentState` is a domain entry rather than a
|
|
529
|
+
* twin's: the two carry different identity fields (`id` versus `principalId`) and different
|
|
530
|
+
* capability vocabularies, so a caller that acts on the state it was handed has to know which it
|
|
531
|
+
* has.
|
|
532
|
+
*
|
|
533
|
+
* `ScopesNotProvisioned` never appears here — the asset management scope is seeded once per
|
|
534
|
+
* customer rather than provisioned per resource.
|
|
535
|
+
*/
|
|
536
|
+
export interface AssetPermissionsConflictErrorBody extends TwinErrorBody {
|
|
537
|
+
cause: TwinPermissionsConflictCause;
|
|
538
|
+
currentState?: AssetPrincipalPermissionsGet;
|
|
539
|
+
}
|
|
540
|
+
|
|
541
|
+
/**
|
|
542
|
+
* Thrown by the asset permission mutation methods on a 409, which on this surface is always an
|
|
543
|
+
* etag failure:
|
|
544
|
+
* - `EtagMismatch` — the etag is stale; re-read (or use {@link currentState}) and retry. Expect
|
|
545
|
+
* this routinely: the scope's etag is customer-wide, so any administrator's write invalidates it.
|
|
546
|
+
* - `EtagRequired` — the write omitted an etag but the principal already held capabilities, so it
|
|
547
|
+
* would have replaced state the caller never read.
|
|
548
|
+
*/
|
|
549
|
+
export class AssetPermissionsConflictError extends Error {
|
|
550
|
+
/**
|
|
551
|
+
* Which of the two conflicts this is. Named `conflictCause` rather than `cause` so the standard
|
|
552
|
+
* `Error.cause` — whose consumers expect a wrapped error, not a string — is left alone.
|
|
553
|
+
*/
|
|
554
|
+
public readonly conflictCause: TwinPermissionsConflictCause;
|
|
555
|
+
/** The entry as the server holds it, including the etag to retry with. */
|
|
556
|
+
public readonly currentState?: AssetPrincipalPermissionsGet;
|
|
557
|
+
public readonly errorBody: AssetPermissionsConflictErrorBody;
|
|
558
|
+
|
|
559
|
+
constructor(message: string, errorBody: AssetPermissionsConflictErrorBody) {
|
|
560
|
+
super(message);
|
|
561
|
+
this.name = 'AssetPermissionsConflictError';
|
|
562
|
+
this.conflictCause = errorBody.cause;
|
|
563
|
+
this.currentState = errorBody.currentState;
|
|
564
|
+
this.errorBody = errorBody;
|
|
565
|
+
}
|
|
566
|
+
}
|
package/src/types/generated.ts
CHANGED
|
@@ -143,7 +143,11 @@ export type TwinDiagnosticCode =
|
|
|
143
143
|
| 'InvalidStructure'
|
|
144
144
|
| 'MissingElement'
|
|
145
145
|
| 'MissingFile'
|
|
146
|
-
| 'PatchTargetNotFound'
|
|
146
|
+
| 'PatchTargetNotFound'
|
|
147
|
+
| 'DuplicateGlobalId'
|
|
148
|
+
| 'NonFiniteTransform'
|
|
149
|
+
| 'NonFiniteGeometryItemTransform'
|
|
150
|
+
| 'ArtifactMergeFailed';
|
|
147
151
|
|
|
148
152
|
/**
|
|
149
153
|
* Specification of a Twinfinity Twin
|
|
@@ -153,10 +157,6 @@ export interface TwinSpecification {
|
|
|
153
157
|
* Spaces that are not part of any facility
|
|
154
158
|
*/
|
|
155
159
|
aggregatedSpaces?: string[];
|
|
156
|
-
/**
|
|
157
|
-
* Ids of Twins that are part of this Twin
|
|
158
|
-
*/
|
|
159
|
-
aggregatedTwins?: string[];
|
|
160
160
|
elementQuantities?: ElementQuantities[];
|
|
161
161
|
/**
|
|
162
162
|
* Collection of entities that are part of the twin
|
|
@@ -170,17 +170,15 @@ export interface TwinSpecification {
|
|
|
170
170
|
* Unique identifier for the twin
|
|
171
171
|
*/
|
|
172
172
|
id?: string;
|
|
173
|
+
propertySets?: PropertySet[];
|
|
173
174
|
/**
|
|
174
|
-
* Twin
|
|
175
|
-
|
|
176
|
-
location?: Location;
|
|
177
|
-
/**
|
|
178
|
-
* Name of the Twin
|
|
175
|
+
* Id of the entity that is the root (top) node of the Twin's entity tree. Must reference a
|
|
176
|
+
* site or facility present in the EntityCollection.
|
|
179
177
|
*/
|
|
180
|
-
|
|
181
|
-
propertySets?: PropertySet[];
|
|
178
|
+
rootEntity: string;
|
|
182
179
|
/**
|
|
183
|
-
* The site of the Twin
|
|
180
|
+
* Legacy. The site of the Twin. Deprecated: use rootEntity, which is authoritative for the
|
|
181
|
+
* root of the Twin's entity tree.
|
|
184
182
|
*/
|
|
185
183
|
site?: string;
|
|
186
184
|
}
|
|
@@ -228,6 +226,11 @@ export interface EntityCollection {
|
|
|
228
226
|
* Facility part entities in the Twin
|
|
229
227
|
*/
|
|
230
228
|
facilityParts?: { [key: string]: FacilityPart };
|
|
229
|
+
/**
|
|
230
|
+
* Representation relations declaring that a twin entity is represented by an entity in a
|
|
231
|
+
* model file, keyed by relation id
|
|
232
|
+
*/
|
|
233
|
+
representations?: { [key: string]: EntityRepresentation };
|
|
231
234
|
/**
|
|
232
235
|
* Site entities in the Twin
|
|
233
236
|
*/
|
|
@@ -236,6 +239,10 @@ export interface EntityCollection {
|
|
|
236
239
|
* Space entities in the Twin
|
|
237
240
|
*/
|
|
238
241
|
spaces?: { [key: string]: Space };
|
|
242
|
+
/**
|
|
243
|
+
* Twin reference entities in the Twin
|
|
244
|
+
*/
|
|
245
|
+
twinReferences?: { [key: string]: TwinReference };
|
|
239
246
|
[property: string]: any;
|
|
240
247
|
}
|
|
241
248
|
|
|
@@ -259,11 +266,18 @@ export interface Facility {
|
|
|
259
266
|
* Type of facility (e.g. IfcBuilding)
|
|
260
267
|
*/
|
|
261
268
|
class: FacilityClass;
|
|
269
|
+
description?: string;
|
|
262
270
|
elementQuantities?: ElementQuantities[];
|
|
263
271
|
/**
|
|
264
272
|
* Unique identifier for the building
|
|
265
273
|
*/
|
|
266
274
|
id: string;
|
|
275
|
+
/**
|
|
276
|
+
* Location of the facility in WGS84. When the facility is the twin's root entity, this is
|
|
277
|
+
* the twin's location.
|
|
278
|
+
*/
|
|
279
|
+
location?: Location;
|
|
280
|
+
longName?: string;
|
|
267
281
|
name?: string;
|
|
268
282
|
propertySets?: PropertySet[];
|
|
269
283
|
}
|
|
@@ -275,6 +289,31 @@ export interface Facility {
|
|
|
275
289
|
*/
|
|
276
290
|
export type FacilityClass = 'IfcBridge' | 'IfcBuilding' | 'IfcMarineFacility' | 'IfcRailway' | 'IfcRoad';
|
|
277
291
|
|
|
292
|
+
/**
|
|
293
|
+
* Location of the facility in WGS84. When the facility is the twin's root entity, this is
|
|
294
|
+
* the twin's location.
|
|
295
|
+
*
|
|
296
|
+
* A location in WGS84
|
|
297
|
+
*
|
|
298
|
+
* Location of the site in WGS84. When the site is the twin's root entity, this is the
|
|
299
|
+
* twin's location.
|
|
300
|
+
*/
|
|
301
|
+
export interface Location {
|
|
302
|
+
/**
|
|
303
|
+
* Metres above sea level
|
|
304
|
+
*/
|
|
305
|
+
elevation?: number;
|
|
306
|
+
epsg: EpsgType;
|
|
307
|
+
latitude: number;
|
|
308
|
+
longitude: number;
|
|
309
|
+
/**
|
|
310
|
+
* Vector pointing to the true north
|
|
311
|
+
*/
|
|
312
|
+
trueNorth?: number[];
|
|
313
|
+
}
|
|
314
|
+
|
|
315
|
+
export type EpsgType = '4326';
|
|
316
|
+
|
|
278
317
|
export interface PropertySet {
|
|
279
318
|
name: string;
|
|
280
319
|
/**
|
|
@@ -412,7 +451,13 @@ export type SinglePropertyValueType =
|
|
|
412
451
|
| 'IfcVolumeMeasure'
|
|
413
452
|
| 'IfcVolumetricFlowRateMeasure'
|
|
414
453
|
| 'IfcWarpingConstantMeasure'
|
|
415
|
-
| 'IfcWarpingMomentMeasure'
|
|
454
|
+
| 'IfcWarpingMomentMeasure'
|
|
455
|
+
| 'IfcAreaDensityMeasure'
|
|
456
|
+
| 'IfcContextDependentMeasure'
|
|
457
|
+
| 'IfcCurvatureMeasure'
|
|
458
|
+
| 'IfcSectionalAreaIntegralMeasure'
|
|
459
|
+
| 'IfcShearModulusMeasure'
|
|
460
|
+
| 'IfcSoundPowerLevelMeasure';
|
|
416
461
|
|
|
417
462
|
/**
|
|
418
463
|
* Distinct part of the facility (e.g. storey or railway part)
|
|
@@ -431,11 +476,13 @@ export interface FacilityPart {
|
|
|
431
476
|
* Type of facility part (e.g. IfcBuildingStorey)
|
|
432
477
|
*/
|
|
433
478
|
class: FacilityPartClass;
|
|
479
|
+
description?: string;
|
|
434
480
|
elementQuantities?: ElementQuantities[];
|
|
435
481
|
/**
|
|
436
482
|
* Unique identifier for the facility part
|
|
437
483
|
*/
|
|
438
484
|
id: string;
|
|
485
|
+
longName?: string;
|
|
439
486
|
name?: string;
|
|
440
487
|
propertySets?: PropertySet[];
|
|
441
488
|
}
|
|
@@ -452,6 +499,26 @@ export type FacilityPartClass =
|
|
|
452
499
|
| 'IfcRailwayPart'
|
|
453
500
|
| 'IfcRoadPart';
|
|
454
501
|
|
|
502
|
+
/**
|
|
503
|
+
* An objectified relation declaring that a twin entity is represented by another entity.
|
|
504
|
+
* Modelled as a relation (not an inline attribute) so it stays addressable and extensible,
|
|
505
|
+
* mirroring how twinReferences objectifies twin-to-twin relations.
|
|
506
|
+
*/
|
|
507
|
+
export interface EntityRepresentation {
|
|
508
|
+
/**
|
|
509
|
+
* Reference to the entity that is represented, e.g. twin~twin:{twinId}.entity:{entityId}
|
|
510
|
+
* for an entity in a twin. Must name an entity: the shared grammar also admits a bare
|
|
511
|
+
* domain (a scope, not an entity), which the service refuses here
|
|
512
|
+
*/
|
|
513
|
+
relatingEntity: string;
|
|
514
|
+
/**
|
|
515
|
+
* Reference to the entity that provides this entity's representation, e.g.
|
|
516
|
+
* twin~twin:{twinId}.file:{fileId}/entities/{ifcGid} for an IFC product within one of the
|
|
517
|
+
* twin's model files. Must name an entity, as relatingEntity must
|
|
518
|
+
*/
|
|
519
|
+
representedBy: string;
|
|
520
|
+
}
|
|
521
|
+
|
|
455
522
|
/**
|
|
456
523
|
* A site is a defined area of land, possibly covered with water, upon which constructions
|
|
457
524
|
* are located
|
|
@@ -469,15 +536,26 @@ export interface Site {
|
|
|
469
536
|
* Spaces that are not part of any facility
|
|
470
537
|
*/
|
|
471
538
|
aggregatedSpaces?: string[];
|
|
539
|
+
/**
|
|
540
|
+
* Twin references nested directly under this site
|
|
541
|
+
*/
|
|
542
|
+
aggregatedTwinReferences?: string[];
|
|
472
543
|
/**
|
|
473
544
|
* Type of site (i.e. IfcSite)
|
|
474
545
|
*/
|
|
475
546
|
class?: SiteType;
|
|
547
|
+
description?: string;
|
|
476
548
|
elementQuantities?: ElementQuantities[];
|
|
477
549
|
/**
|
|
478
550
|
* Unique identifier for the site
|
|
479
551
|
*/
|
|
480
552
|
id?: string;
|
|
553
|
+
/**
|
|
554
|
+
* Location of the site in WGS84. When the site is the twin's root entity, this is the
|
|
555
|
+
* twin's location.
|
|
556
|
+
*/
|
|
557
|
+
location?: Location;
|
|
558
|
+
longName?: string;
|
|
481
559
|
/**
|
|
482
560
|
* Name of the site
|
|
483
561
|
*/
|
|
@@ -507,12 +585,15 @@ export interface Space {
|
|
|
507
585
|
* Type of space (e.g. IfcSpace)
|
|
508
586
|
*/
|
|
509
587
|
class: SpaceType;
|
|
588
|
+
description?: string;
|
|
510
589
|
elementQuantities?: ElementQuantities[];
|
|
511
590
|
/**
|
|
512
591
|
* Unique identifier for the space
|
|
513
592
|
*/
|
|
514
593
|
id: string;
|
|
594
|
+
longName?: string;
|
|
515
595
|
name?: string;
|
|
596
|
+
objectType?: string;
|
|
516
597
|
propertySets?: PropertySet[];
|
|
517
598
|
}
|
|
518
599
|
|
|
@@ -521,6 +602,16 @@ export interface Space {
|
|
|
521
602
|
*/
|
|
522
603
|
export type SpaceType = 'IfcSpace';
|
|
523
604
|
|
|
605
|
+
/**
|
|
606
|
+
* A reference to another Twin nested within this Twin's spatial hierarchy
|
|
607
|
+
*/
|
|
608
|
+
export interface TwinReference {
|
|
609
|
+
/**
|
|
610
|
+
* Id of the referenced (nested) Twin
|
|
611
|
+
*/
|
|
612
|
+
twin: string;
|
|
613
|
+
}
|
|
614
|
+
|
|
524
615
|
export interface FilePatchSet {
|
|
525
616
|
/**
|
|
526
617
|
* Ordered list of patch operations to apply
|
|
@@ -551,24 +642,3 @@ export interface FilePatch {
|
|
|
551
642
|
* The patch operation type
|
|
552
643
|
*/
|
|
553
644
|
export type Op = 'replace' | 'remove';
|
|
554
|
-
|
|
555
|
-
/**
|
|
556
|
-
* Twin location in WGS84
|
|
557
|
-
*
|
|
558
|
-
* A location in WGS84
|
|
559
|
-
*/
|
|
560
|
-
export interface Location {
|
|
561
|
-
/**
|
|
562
|
-
* Metres above sea level
|
|
563
|
-
*/
|
|
564
|
-
elevation?: number;
|
|
565
|
-
epsg: EpsgType;
|
|
566
|
-
latitude: number;
|
|
567
|
-
longitude: number;
|
|
568
|
-
/**
|
|
569
|
-
* Vector pointing to the true north
|
|
570
|
-
*/
|
|
571
|
-
trueNorth?: number[];
|
|
572
|
-
}
|
|
573
|
-
|
|
574
|
-
export type EpsgType = '4326';
|
package/src/types/twin-api.ts
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
import type { PropertySet, ElementQuantities, TwinSpecification, Diagnostics } from './generated';
|
|
1
|
+
import type { PropertySet, ElementQuantities, TwinSpecification, Diagnostics, EpsgType, Location } from './generated';
|
|
2
|
+
import type { TwinBoundCapabilityName } from './twin-permissions-api';
|
|
2
3
|
|
|
3
4
|
export interface TwinFileReference {
|
|
4
5
|
fileId: string;
|
|
@@ -6,6 +7,14 @@ export interface TwinFileReference {
|
|
|
6
7
|
twinNodeId?: string;
|
|
7
8
|
}
|
|
8
9
|
|
|
10
|
+
/** WGS84 coordinates of a twin, as returned on the list endpoint (coordinates only — the full
|
|
11
|
+
* Location, including elevation and trueNorth, is available on the single-twin GET). */
|
|
12
|
+
export interface Coordinates {
|
|
13
|
+
epsg: EpsgType;
|
|
14
|
+
latitude: number;
|
|
15
|
+
longitude: number;
|
|
16
|
+
}
|
|
17
|
+
|
|
9
18
|
export interface ListTwinItem {
|
|
10
19
|
id: string;
|
|
11
20
|
name: string;
|
|
@@ -20,8 +29,32 @@ export interface ListTwinItem {
|
|
|
20
29
|
createdUtc: string;
|
|
21
30
|
modifiedBy: string;
|
|
22
31
|
modifiedUtc: string;
|
|
32
|
+
/** Ids of the Twins nested within this Twin, derived by the service from its twin references. */
|
|
33
|
+
aggregatedTwins: string[];
|
|
34
|
+
/** Deduplicated, sorted set of IFC entity classes the twin contains (e.g. IfcBuilding, IfcSpace),
|
|
35
|
+
* computed by the service from the specification's entity collection. */
|
|
36
|
+
classes: string[];
|
|
37
|
+
/** Id of the Twin that references this Twin (its parent), or omitted for a root Twin. */
|
|
38
|
+
parentTwin?: string;
|
|
39
|
+
/** WGS84 coordinates, present only when the twin's specification declares a location. */
|
|
40
|
+
location?: Coordinates;
|
|
41
|
+
/**
|
|
42
|
+
* What the *calling principal* may do with this twin — the whole affordance decision for the
|
|
43
|
+
* row, so a list of a thousand twins needs no probe per row. Never the twin's access-control
|
|
44
|
+
* list: that is `listTwinPermissions(twinId)`, which is administration-gated.
|
|
45
|
+
*
|
|
46
|
+
* Mixes both capability vocabularies, as the twin-scoped probe does. Where each capability was
|
|
47
|
+
* granted is answered by `listTwinPermissions(twinId)`, whose rows split `permissions` from
|
|
48
|
+
* `inheritedPermissions`. Absent on `listTwinVersions`, which does not resolve it.
|
|
49
|
+
*/
|
|
50
|
+
effectivePermissions?: TwinBoundCapabilityName[];
|
|
23
51
|
}
|
|
24
52
|
|
|
53
|
+
/**
|
|
54
|
+
* A twin as returned by the service — by `getTwin` and `getTwinVersion`, and by the write methods
|
|
55
|
+
* (`createOrUpdateTwin`, `deleteTwin`, `restoreTwin`), which answer with the same shape. Writing a
|
|
56
|
+
* twin and re-rendering it therefore needs no second fetch.
|
|
57
|
+
*/
|
|
25
58
|
export interface TwinGet extends TwinSpecification {
|
|
26
59
|
id: string;
|
|
27
60
|
etag: string;
|
|
@@ -34,6 +67,27 @@ export interface TwinGet extends TwinSpecification {
|
|
|
34
67
|
modifiedUtc: string;
|
|
35
68
|
fileReferences: TwinFileReference[];
|
|
36
69
|
computedPropertySets?: PropertySet[];
|
|
70
|
+
/** Ids of the Twins nested within this Twin, derived by the service from its twin references. */
|
|
71
|
+
aggregatedTwins: string[];
|
|
72
|
+
/** Id of the Twin that references this Twin (its parent), or omitted for a root Twin. */
|
|
73
|
+
parentTwin?: string;
|
|
74
|
+
/** Name of the Twin, derived by the service from the root entity. Read-only; not part of the
|
|
75
|
+
* stored specification. */
|
|
76
|
+
name: string;
|
|
77
|
+
/** Full WGS84 location of the Twin (including elevation and trueNorth), derived by the service
|
|
78
|
+
* from the root entity. Read-only; not part of the stored specification. */
|
|
79
|
+
location?: Location;
|
|
80
|
+
/**
|
|
81
|
+
* Everything the *calling principal* may do with this twin: the capabilities its own scopes
|
|
82
|
+
* confer, unioned with the twin-bound asset ones held customer-wide. Calculated by the service on
|
|
83
|
+
* every read, never stored, and never accepted in a `TwinPut` body.
|
|
84
|
+
*
|
|
85
|
+
* The verdict, without its provenance — a fetched twin says no more than a listing row does.
|
|
86
|
+
* Which capabilities are granted here and which come from elsewhere is answered by
|
|
87
|
+
* `listTwinPermissions(twinId)`, where they are administered. Never the twin's access-control
|
|
88
|
+
* list either: this describes the caller, not every principal.
|
|
89
|
+
*/
|
|
90
|
+
effectivePermissions: TwinBoundCapabilityName[];
|
|
37
91
|
}
|
|
38
92
|
|
|
39
93
|
export interface TwinPut extends TwinSpecification {
|