@twinfinity/twin 6.0.2-ci.29168 → 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 +2 -2
- package/dist/TwinClient.d.ts +68 -0
- package/dist/TwinClient.d.ts.map +1 -1
- package/dist/TwinClient.js +152 -1
- package/dist/TwinClient.js.map +1 -1
- package/dist/errors.d.ts +9 -1
- package/dist/errors.d.ts.map +1 -1
- package/dist/errors.js +14 -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/index.d.ts +1 -0
- package/dist/types/index.d.ts.map +1 -1
- package/dist/types/index.js +1 -0
- package/dist/types/index.js.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 +3 -0
- package/docs/classes/AssetAttachmentNotFoundError.html +2 -0
- 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/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 +102 -69
- 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 +1 -1
- package/docs/classes/TwinValidationError.html +1 -1
- package/docs/hierarchy.html +1 -1
- package/docs/interfaces/ApiCreateUploadSessionResponse.html +7 -0
- package/docs/interfaces/AssetAttachmentPut.html +6 -0
- package/docs/interfaces/AssetCatalogTooLargeErrorBody.html +1 -1
- package/docs/interfaces/AttachmentGet.html +20 -0
- package/docs/interfaces/AttachmentPost.html +4 -0
- package/docs/interfaces/ITwinClient.html +100 -67
- package/docs/interfaces/TwinErrorBody.html +1 -1
- package/docs/interfaces/TwinSpecification.html +1 -1
- package/docs/interfaces/UploadStatusGet.html +3 -0
- package/docs/modules.html +1 -1
- package/docs/types/TwinErrorCause.html +1 -1
- package/docs/types/UploadStatus.html +1 -0
- package/package.json +3 -3
- package/src/TwinClient.ts +324 -0
- package/src/errors.ts +19 -0
- package/src/types/asset-attachment-api.ts +56 -0
- package/src/types/index.ts +1 -0
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
<!DOCTYPE html><html class="default" lang="en" data-base="../"><head><meta charset="utf-8"/><meta http-equiv="x-ua-compatible" content="IE=edge"/><title>TwinErrorCause | @twinfinity/twin</title><meta name="description" content="Documentation for @twinfinity/twin"/><meta name="viewport" content="width=device-width, initial-scale=1"/><link rel="stylesheet" href="../assets/style.css"/><link rel="stylesheet" href="../assets/highlight.css"/><script defer src="../assets/main.js"></script><script async src="../assets/icons.js" id="tsd-icons-script"></script><script async src="../assets/search.js" id="tsd-search-script"></script><script async src="../assets/navigation.js" id="tsd-nav-script"></script><script async src="../assets/hierarchy.js" id="tsd-hierarchy-script"></script></head><body><script>document.documentElement.dataset.theme = localStorage.getItem("tsd-theme") || "os";document.body.style.display="none";setTimeout(() => window.app?app.showPage():document.body.style.removeProperty("display"),500)</script><header class="tsd-page-toolbar"><div class="tsd-toolbar-contents container"><a href="../index.html" class="title">@twinfinity/twin</a><div id="tsd-toolbar-links"></div><button id="tsd-search-trigger" class="tsd-widget" aria-label="Search"><svg width="16" height="16" viewBox="0 0 16 16" fill="none" aria-hidden="true"><use href="../assets/icons.svg#icon-search"></use></svg></button><dialog id="tsd-search" aria-label="Search"><input role="combobox" id="tsd-search-input" aria-controls="tsd-search-results" aria-autocomplete="list" aria-expanded="true" autocapitalize="off" autocomplete="off" placeholder="Search the docs" maxLength="100"/><ul role="listbox" id="tsd-search-results"></ul><div id="tsd-search-status" aria-live="polite" aria-atomic="true"><div>Preparing search index...</div></div></dialog><a href="#" class="tsd-widget menu" id="tsd-toolbar-menu-trigger" data-toggle="menu" aria-label="Menu"><svg width="16" height="16" viewBox="0 0 16 16" fill="none" aria-hidden="true"><use href="../assets/icons.svg#icon-menu"></use></svg></a></div></header><div class="container container-main"><div class="col-content"><div class="tsd-page-title"><ul class="tsd-breadcrumb" aria-label="Breadcrumb"><li><a href="" aria-current="page">TwinErrorCause</a></li></ul><h1>Type Alias TwinErrorCause</h1></div><div class="tsd-signature"><span class="tsd-kind-type-alias">TwinErrorCause</span><span class="tsd-signature-symbol">:</span><br/> <span class="tsd-signature-symbol">|</span> <span class="tsd-signature-type">"NotAllowedToEditDeletedItem"</span><br/> <span class="tsd-signature-symbol">|</span> <span class="tsd-signature-type">"NotAllowedToDeleteItem"</span><br/> <span class="tsd-signature-symbol">|</span> <span class="tsd-signature-type">"ImmutableField"</span><br/> <span class="tsd-signature-symbol">|</span> <span class="tsd-signature-type">"ReferencedItemNotFound"</span><br/> <span class="tsd-signature-symbol">|</span> <span class="tsd-signature-type">"ReferencedItemDeleted"</span><br/> <span class="tsd-signature-symbol">|</span> <span class="tsd-signature-type">"FileNotOwnedByTwin"</span><br/> <span class="tsd-signature-symbol">|</span> <span class="tsd-signature-type">"DuplicateFileReference"</span><br/> <span class="tsd-signature-symbol">|</span> <span class="tsd-signature-type">"MultipleVersionsOfSameFileOnSameNode"</span><br/> <span class="tsd-signature-symbol">|</span> <span class="tsd-signature-type">"LimitOutOfRange"</span><br/> <span class="tsd-signature-symbol">|</span> <span class="tsd-signature-type">"OffsetOutOfRange"</span><br/> <span class="tsd-signature-symbol">|</span> <span class="tsd-signature-type">"IdMismatchBetweenUrlAndBody"</span><br/> <span class="tsd-signature-symbol">|</span> <span class="tsd-signature-type">"BatchSizeEmpty"</span><br/> <span class="tsd-signature-symbol">|</span> <span class="tsd-signature-type">"BatchSizeExceedsMaximum"</span><br/> <span class="tsd-signature-symbol">|</span> <span class="tsd-signature-type">"InvalidParameterCombination"</span><br/> <span class="tsd-signature-symbol">|</span> <span class="tsd-signature-type">"DocumentChangeNotFound"</span><br/> <span class="tsd-signature-symbol">|</span> <span class="tsd-signature-type">"DeletePermissionRequired"</span><br/> <span class="tsd-signature-symbol">|</span> <span class="tsd-signature-type">"CannotEditDeletedFile"</span><br/> <span class="tsd-signature-symbol">|</span> <span class="tsd-signature-type">"CannotMoveFileBetweenTwins"</span><br/> <span class="tsd-signature-symbol">|</span> <span class="tsd-signature-type">"ContainerDoesNotExist"</span><br/> <span class="tsd-signature-symbol">|</span> <span class="tsd-signature-type">"DuplicateContainerIds"</span><br/> <span class="tsd-signature-symbol">|</span> <span class="tsd-signature-type">"InsufficientPermissionsOnContainer"</span><br/> <span class="tsd-signature-symbol">|</span> <span class="tsd-signature-type">"DuplicateId"</span><br/> <span class="tsd-signature-symbol">|</span> <span class="tsd-signature-type">"MetadataTooLarge"</span><br/> <span class="tsd-signature-symbol">|</span> <span class="tsd-signature-type">"InvalidTransform"</span><br/> <span class="tsd-signature-symbol">|</span> <span class="tsd-signature-type">"InvalidFilePatches"</span><br/> <span class="tsd-signature-symbol">|</span> <span class="tsd-signature-type">"MetadataValidationFailed"</span><br/> <span class="tsd-signature-symbol">|</span> <span class="tsd-signature-type">"MetadataSchemaInvalid"</span><br/> <span class="tsd-signature-symbol">|</span> <span class="tsd-signature-type">"AssetTypeNotFound"</span><br/> <span class="tsd-signature-symbol">|</span> <span class="tsd-signature-type">"AssetCategoryAndTypeRequired"</span><br/> <span class="tsd-signature-symbol">|</span> <span class="tsd-signature-type">"StringIdInUse"</span><br/> <span class="tsd-signature-symbol">|</span> <span class="tsd-signature-type">"CatalogTooLarge"</span><br/> <span class="tsd-signature-symbol">|</span> <span class="tsd-signature-type">string</span> <span class="tsd-signature-symbol">&</span> <span class="tsd-signature-symbol">{}</span></div><div class="tsd-comment tsd-typography"><p>Closed union of <code>cause</code> values the Twin service emits on a 400 response. Mirrors
|
|
1
|
+
<!DOCTYPE html><html class="default" lang="en" data-base="../"><head><meta charset="utf-8"/><meta http-equiv="x-ua-compatible" content="IE=edge"/><title>TwinErrorCause | @twinfinity/twin</title><meta name="description" content="Documentation for @twinfinity/twin"/><meta name="viewport" content="width=device-width, initial-scale=1"/><link rel="stylesheet" href="../assets/style.css"/><link rel="stylesheet" href="../assets/highlight.css"/><script defer src="../assets/main.js"></script><script async src="../assets/icons.js" id="tsd-icons-script"></script><script async src="../assets/search.js" id="tsd-search-script"></script><script async src="../assets/navigation.js" id="tsd-nav-script"></script><script async src="../assets/hierarchy.js" id="tsd-hierarchy-script"></script></head><body><script>document.documentElement.dataset.theme = localStorage.getItem("tsd-theme") || "os";document.body.style.display="none";setTimeout(() => window.app?app.showPage():document.body.style.removeProperty("display"),500)</script><header class="tsd-page-toolbar"><div class="tsd-toolbar-contents container"><a href="../index.html" class="title">@twinfinity/twin</a><div id="tsd-toolbar-links"></div><button id="tsd-search-trigger" class="tsd-widget" aria-label="Search"><svg width="16" height="16" viewBox="0 0 16 16" fill="none" aria-hidden="true"><use href="../assets/icons.svg#icon-search"></use></svg></button><dialog id="tsd-search" aria-label="Search"><input role="combobox" id="tsd-search-input" aria-controls="tsd-search-results" aria-autocomplete="list" aria-expanded="true" autocapitalize="off" autocomplete="off" placeholder="Search the docs" maxLength="100"/><ul role="listbox" id="tsd-search-results"></ul><div id="tsd-search-status" aria-live="polite" aria-atomic="true"><div>Preparing search index...</div></div></dialog><a href="#" class="tsd-widget menu" id="tsd-toolbar-menu-trigger" data-toggle="menu" aria-label="Menu"><svg width="16" height="16" viewBox="0 0 16 16" fill="none" aria-hidden="true"><use href="../assets/icons.svg#icon-menu"></use></svg></a></div></header><div class="container container-main"><div class="col-content"><div class="tsd-page-title"><ul class="tsd-breadcrumb" aria-label="Breadcrumb"><li><a href="" aria-current="page">TwinErrorCause</a></li></ul><h1>Type Alias TwinErrorCause</h1></div><div class="tsd-signature"><span class="tsd-kind-type-alias">TwinErrorCause</span><span class="tsd-signature-symbol">:</span><br/> <span class="tsd-signature-symbol">|</span> <span class="tsd-signature-type">"NotAllowedToEditDeletedItem"</span><br/> <span class="tsd-signature-symbol">|</span> <span class="tsd-signature-type">"NotAllowedToDeleteItem"</span><br/> <span class="tsd-signature-symbol">|</span> <span class="tsd-signature-type">"ImmutableField"</span><br/> <span class="tsd-signature-symbol">|</span> <span class="tsd-signature-type">"ReferencedItemNotFound"</span><br/> <span class="tsd-signature-symbol">|</span> <span class="tsd-signature-type">"ReferencedItemDeleted"</span><br/> <span class="tsd-signature-symbol">|</span> <span class="tsd-signature-type">"FileNotOwnedByTwin"</span><br/> <span class="tsd-signature-symbol">|</span> <span class="tsd-signature-type">"DuplicateFileReference"</span><br/> <span class="tsd-signature-symbol">|</span> <span class="tsd-signature-type">"MultipleVersionsOfSameFileOnSameNode"</span><br/> <span class="tsd-signature-symbol">|</span> <span class="tsd-signature-type">"LimitOutOfRange"</span><br/> <span class="tsd-signature-symbol">|</span> <span class="tsd-signature-type">"OffsetOutOfRange"</span><br/> <span class="tsd-signature-symbol">|</span> <span class="tsd-signature-type">"IdMismatchBetweenUrlAndBody"</span><br/> <span class="tsd-signature-symbol">|</span> <span class="tsd-signature-type">"BatchSizeEmpty"</span><br/> <span class="tsd-signature-symbol">|</span> <span class="tsd-signature-type">"BatchSizeExceedsMaximum"</span><br/> <span class="tsd-signature-symbol">|</span> <span class="tsd-signature-type">"InvalidParameterCombination"</span><br/> <span class="tsd-signature-symbol">|</span> <span class="tsd-signature-type">"DocumentChangeNotFound"</span><br/> <span class="tsd-signature-symbol">|</span> <span class="tsd-signature-type">"DeletePermissionRequired"</span><br/> <span class="tsd-signature-symbol">|</span> <span class="tsd-signature-type">"CannotEditDeletedFile"</span><br/> <span class="tsd-signature-symbol">|</span> <span class="tsd-signature-type">"CannotMoveFileBetweenTwins"</span><br/> <span class="tsd-signature-symbol">|</span> <span class="tsd-signature-type">"ContainerDoesNotExist"</span><br/> <span class="tsd-signature-symbol">|</span> <span class="tsd-signature-type">"DuplicateContainerIds"</span><br/> <span class="tsd-signature-symbol">|</span> <span class="tsd-signature-type">"InsufficientPermissionsOnContainer"</span><br/> <span class="tsd-signature-symbol">|</span> <span class="tsd-signature-type">"DuplicateId"</span><br/> <span class="tsd-signature-symbol">|</span> <span class="tsd-signature-type">"MetadataTooLarge"</span><br/> <span class="tsd-signature-symbol">|</span> <span class="tsd-signature-type">"InvalidTransform"</span><br/> <span class="tsd-signature-symbol">|</span> <span class="tsd-signature-type">"InvalidFilePatches"</span><br/> <span class="tsd-signature-symbol">|</span> <span class="tsd-signature-type">"MetadataValidationFailed"</span><br/> <span class="tsd-signature-symbol">|</span> <span class="tsd-signature-type">"MetadataSchemaInvalid"</span><br/> <span class="tsd-signature-symbol">|</span> <span class="tsd-signature-type">"AssetTypeNotFound"</span><br/> <span class="tsd-signature-symbol">|</span> <span class="tsd-signature-type">"AssetCategoryAndTypeRequired"</span><br/> <span class="tsd-signature-symbol">|</span> <span class="tsd-signature-type">"StringIdInUse"</span><br/> <span class="tsd-signature-symbol">|</span> <span class="tsd-signature-type">"CatalogTooLarge"</span><br/> <span class="tsd-signature-symbol">|</span> <span class="tsd-signature-type">"EtagRequired"</span><br/> <span class="tsd-signature-symbol">|</span> <span class="tsd-signature-type">string</span> <span class="tsd-signature-symbol">&</span> <span class="tsd-signature-symbol">{}</span></div><div class="tsd-comment tsd-typography"><p>Closed union of <code>cause</code> values the Twin service emits on a 400 response. Mirrors
|
|
2
2
|
<code>TwinBadRequestCause</code> in <code>backend/services/Twinfinity.Twin/Controllers/Model/TwinStatus.cs</code>.
|
|
3
3
|
The trailing <code>(string & {})</code> keeps autocomplete on the known values while still
|
|
4
4
|
accepting unknown causes at the type level — a forward-compat pattern: a new
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
<!DOCTYPE html><html class="default" lang="en" data-base="../"><head><meta charset="utf-8"/><meta http-equiv="x-ua-compatible" content="IE=edge"/><title>UploadStatus | @twinfinity/twin</title><meta name="description" content="Documentation for @twinfinity/twin"/><meta name="viewport" content="width=device-width, initial-scale=1"/><link rel="stylesheet" href="../assets/style.css"/><link rel="stylesheet" href="../assets/highlight.css"/><script defer src="../assets/main.js"></script><script async src="../assets/icons.js" id="tsd-icons-script"></script><script async src="../assets/search.js" id="tsd-search-script"></script><script async src="../assets/navigation.js" id="tsd-nav-script"></script><script async src="../assets/hierarchy.js" id="tsd-hierarchy-script"></script></head><body><script>document.documentElement.dataset.theme = localStorage.getItem("tsd-theme") || "os";document.body.style.display="none";setTimeout(() => window.app?app.showPage():document.body.style.removeProperty("display"),500)</script><header class="tsd-page-toolbar"><div class="tsd-toolbar-contents container"><a href="../index.html" class="title">@twinfinity/twin</a><div id="tsd-toolbar-links"></div><button id="tsd-search-trigger" class="tsd-widget" aria-label="Search"><svg width="16" height="16" viewBox="0 0 16 16" fill="none" aria-hidden="true"><use href="../assets/icons.svg#icon-search"></use></svg></button><dialog id="tsd-search" aria-label="Search"><input role="combobox" id="tsd-search-input" aria-controls="tsd-search-results" aria-autocomplete="list" aria-expanded="true" autocapitalize="off" autocomplete="off" placeholder="Search the docs" maxLength="100"/><ul role="listbox" id="tsd-search-results"></ul><div id="tsd-search-status" aria-live="polite" aria-atomic="true"><div>Preparing search index...</div></div></dialog><a href="#" class="tsd-widget menu" id="tsd-toolbar-menu-trigger" data-toggle="menu" aria-label="Menu"><svg width="16" height="16" viewBox="0 0 16 16" fill="none" aria-hidden="true"><use href="../assets/icons.svg#icon-menu"></use></svg></a></div></header><div class="container container-main"><div class="col-content"><div class="tsd-page-title"><ul class="tsd-breadcrumb" aria-label="Breadcrumb"><li><a href="" aria-current="page">UploadStatus</a></li></ul><h1>Type Alias UploadStatus</h1></div><div class="tsd-signature"><span class="tsd-kind-type-alias">UploadStatus</span><span class="tsd-signature-symbol">:</span> <span class="tsd-signature-type">"NotFound"</span> <span class="tsd-signature-symbol">|</span> <span class="tsd-signature-type">"InProgress"</span> <span class="tsd-signature-symbol">|</span> <span class="tsd-signature-type">"Completed"</span> <span class="tsd-signature-symbol">|</span> <span class="tsd-signature-type">"Cancelled"</span> <span class="tsd-signature-symbol">|</span> <span class="tsd-signature-type">"Failed"</span></div></div><div class="col-sidebar"><div class="page-menu"><div class="tsd-navigation settings"><details class="tsd-accordion"><summary class="tsd-accordion-summary"><svg width="20" height="20" viewBox="0 0 24 24" fill="none" aria-hidden="true"><use href="../assets/icons.svg#icon-chevronDown"></use></svg><h3>Settings</h3></summary><div class="tsd-accordion-details"><div class="tsd-filter-visibility"><span class="settings-label">Member Visibility</span><ul id="tsd-filter-options"><li class="tsd-filter-item"><label class="tsd-filter-input"><input type="checkbox" id="tsd-filter-protected" name="protected"/><svg width="32" height="32" viewBox="0 0 32 32" aria-hidden="true"><rect class="tsd-checkbox-background" width="30" height="30" x="1" y="1" rx="6" fill="none"></rect><path class="tsd-checkbox-checkmark" d="M8.35422 16.8214L13.2143 21.75L24.6458 10.25" stroke="none" stroke-width="3.5" stroke-linejoin="round" fill="none"></path></svg><span>Protected</span></label></li><li class="tsd-filter-item"><label class="tsd-filter-input"><input type="checkbox" id="tsd-filter-inherited" name="inherited" checked/><svg width="32" height="32" viewBox="0 0 32 32" aria-hidden="true"><rect class="tsd-checkbox-background" width="30" height="30" x="1" y="1" rx="6" fill="none"></rect><path class="tsd-checkbox-checkmark" d="M8.35422 16.8214L13.2143 21.75L24.6458 10.25" stroke="none" stroke-width="3.5" stroke-linejoin="round" fill="none"></path></svg><span>Inherited</span></label></li></ul></div><div class="tsd-theme-toggle"><label class="settings-label" for="tsd-theme">Theme</label><select id="tsd-theme"><option value="os">OS</option><option value="light">Light</option><option value="dark">Dark</option></select></div></div></details></div></div><div class="site-menu"><nav class="tsd-navigation"><a href="../modules.html">@twinfinity/twin</a><ul class="tsd-small-nested-navigation" id="tsd-nav-container"><li>Loading...</li></ul></nav></div></div></div><footer></footer><div class="overlay"></div></body></html>
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@twinfinity/twin",
|
|
3
|
-
"version": "6.0.2
|
|
3
|
+
"version": "6.0.2",
|
|
4
4
|
"description": "Twinfinity Twin Service client",
|
|
5
5
|
"source": "src/index.ts",
|
|
6
6
|
"main": "dist/index.js",
|
|
@@ -39,8 +39,8 @@
|
|
|
39
39
|
"docs"
|
|
40
40
|
],
|
|
41
41
|
"peerDependencies": {
|
|
42
|
-
"@twinfinity/authentication": "6.0.2
|
|
43
|
-
"@twinfinity/t8-client-model": "6.0.2-
|
|
42
|
+
"@twinfinity/authentication": "6.0.2",
|
|
43
|
+
"@twinfinity/t8-client-model": "6.0.2-beta"
|
|
44
44
|
},
|
|
45
45
|
"devDependencies": {
|
|
46
46
|
"@vitest/coverage-v8": "^3.2.3",
|
package/src/TwinClient.ts
CHANGED
|
@@ -56,6 +56,8 @@ import {
|
|
|
56
56
|
AssetForbiddenError,
|
|
57
57
|
AssetConflictError,
|
|
58
58
|
AssetNotFoundError,
|
|
59
|
+
AssetAttachmentConflictError,
|
|
60
|
+
AssetAttachmentNotFoundError,
|
|
59
61
|
AssetBatchError,
|
|
60
62
|
TwinFileValidationError,
|
|
61
63
|
TwinFileConflictError,
|
|
@@ -80,6 +82,13 @@ import type {
|
|
|
80
82
|
AssetTypeGet,
|
|
81
83
|
AssetTypePut
|
|
82
84
|
} from './types/asset-types-api';
|
|
85
|
+
import type {
|
|
86
|
+
AttachmentGet,
|
|
87
|
+
AttachmentPost,
|
|
88
|
+
AssetAttachmentPut,
|
|
89
|
+
ApiCreateUploadSessionResponse,
|
|
90
|
+
UploadStatusGet
|
|
91
|
+
} from './types/asset-attachment-api';
|
|
83
92
|
import type { MyPermissions } from './types/twin-permissions-api';
|
|
84
93
|
import { Twin } from './types/Twin';
|
|
85
94
|
import { TwinGeometryInfo } from './types/TwinGeometryInfo';
|
|
@@ -319,6 +328,102 @@ export interface ITwinClient {
|
|
|
319
328
|
*/
|
|
320
329
|
batchGetAssets(twinId: string, ids: string[], signal?: AbortSignal): Promise<AssetBatchGetResponse>;
|
|
321
330
|
|
|
331
|
+
/** Lists attachments for a single asset. */
|
|
332
|
+
listAssetAttachments(
|
|
333
|
+
twinId: string,
|
|
334
|
+
assetId: string,
|
|
335
|
+
options?: { includeDeleted?: boolean; offset?: number; limit?: number; page?: string },
|
|
336
|
+
signal?: AbortSignal
|
|
337
|
+
): Promise<PaginatedResponse<AttachmentGet>>;
|
|
338
|
+
|
|
339
|
+
/**
|
|
340
|
+
* Downloads an attachment's blob as a `Response`. The caller decides
|
|
341
|
+
* whether to consume it as text, ArrayBuffer, or Blob.
|
|
342
|
+
* @throws {AssetAttachmentNotFoundError} When the attachment does not exist (404).
|
|
343
|
+
*/
|
|
344
|
+
getAssetAttachmentBlob(
|
|
345
|
+
twinId: string,
|
|
346
|
+
assetId: string,
|
|
347
|
+
attachmentId: string,
|
|
348
|
+
signal?: AbortSignal
|
|
349
|
+
): Promise<Response>;
|
|
350
|
+
|
|
351
|
+
/**
|
|
352
|
+
* Creates an upload session for a new attachment. The actual file bytes
|
|
353
|
+
* are uploaded out-of-band to {@link ApiCreateUploadSessionResponse.uploadUrl};
|
|
354
|
+
* use {@link uploadAssetAttachmentFile} for the canonical chunked-upload flow.
|
|
355
|
+
* The attachment row is materialized server-side when the blob lands.
|
|
356
|
+
* @throws {AssetAttachmentConflictError} When an attachment already exists
|
|
357
|
+
* for the given id (409); retries must use a new attachmentId.
|
|
358
|
+
*/
|
|
359
|
+
createAssetAttachmentUploadSession(
|
|
360
|
+
twinId: string,
|
|
361
|
+
assetId: string,
|
|
362
|
+
attachmentId: string,
|
|
363
|
+
body: AttachmentPost,
|
|
364
|
+
signal?: AbortSignal
|
|
365
|
+
): Promise<ApiCreateUploadSessionResponse>;
|
|
366
|
+
|
|
367
|
+
/**
|
|
368
|
+
* Uploads a `File` / `Blob` to an existing upload session in one or more
|
|
369
|
+
* chunks, then resolves the upload token so the caller can poll
|
|
370
|
+
* {@link getAssetAttachmentUploadStatus}.
|
|
371
|
+
*/
|
|
372
|
+
uploadAssetAttachmentFile(
|
|
373
|
+
session: ApiCreateUploadSessionResponse,
|
|
374
|
+
file: Blob,
|
|
375
|
+
signal?: AbortSignal
|
|
376
|
+
): Promise<{ token: string }>;
|
|
377
|
+
|
|
378
|
+
/** Polls the in-memory upload-session cache for an attachment that's being uploaded. */
|
|
379
|
+
getAssetAttachmentUploadStatus(
|
|
380
|
+
twinId: string,
|
|
381
|
+
assetId: string,
|
|
382
|
+
token: string,
|
|
383
|
+
signal?: AbortSignal
|
|
384
|
+
): Promise<UploadStatusGet>;
|
|
385
|
+
|
|
386
|
+
/**
|
|
387
|
+
* Updates an attachment's description / soft-delete flag. `documentId`
|
|
388
|
+
* is immutable — rebinding is rejected.
|
|
389
|
+
* @throws {AssetAttachmentConflictError} On etag mismatch (409). The
|
|
390
|
+
* error's `currentAttachment` carries the server's current state.
|
|
391
|
+
* @throws {AssetAttachmentNotFoundError} When the attachment does not exist (404).
|
|
392
|
+
*/
|
|
393
|
+
putAssetAttachment(
|
|
394
|
+
twinId: string,
|
|
395
|
+
assetId: string,
|
|
396
|
+
attachmentId: string,
|
|
397
|
+
body: AssetAttachmentPut,
|
|
398
|
+
signal?: AbortSignal
|
|
399
|
+
): Promise<AttachmentGet>;
|
|
400
|
+
|
|
401
|
+
/**
|
|
402
|
+
* Soft-deletes an attachment.
|
|
403
|
+
* @throws {AssetAttachmentConflictError} On etag mismatch (409).
|
|
404
|
+
* @throws {AssetAttachmentNotFoundError} When the attachment does not exist (404).
|
|
405
|
+
*/
|
|
406
|
+
deleteAssetAttachment(
|
|
407
|
+
twinId: string,
|
|
408
|
+
assetId: string,
|
|
409
|
+
attachmentId: string,
|
|
410
|
+
etag: string,
|
|
411
|
+
signal?: AbortSignal
|
|
412
|
+
): Promise<AttachmentGet>;
|
|
413
|
+
|
|
414
|
+
/**
|
|
415
|
+
* Restores a soft-deleted attachment.
|
|
416
|
+
* @throws {AssetAttachmentConflictError} On etag mismatch (409).
|
|
417
|
+
* @throws {AssetAttachmentNotFoundError} When the attachment does not exist (404).
|
|
418
|
+
*/
|
|
419
|
+
restoreAssetAttachment(
|
|
420
|
+
twinId: string,
|
|
421
|
+
assetId: string,
|
|
422
|
+
attachmentId: string,
|
|
423
|
+
etag: string,
|
|
424
|
+
signal?: AbortSignal
|
|
425
|
+
): Promise<AttachmentGet>;
|
|
426
|
+
|
|
322
427
|
/**
|
|
323
428
|
* @throws {TwinNotFoundError} When the twin does not exist (404).
|
|
324
429
|
* @throws {TwinConflictError} On etag mismatch (409). The error's `currentTwin` contains the server's current state.
|
|
@@ -1376,6 +1481,225 @@ export class TwinClient implements ITwinClient {
|
|
|
1376
1481
|
throw new Error(`Failed to batch-get assets: ${response.status} ${response.statusText} - ${errorText}`);
|
|
1377
1482
|
}
|
|
1378
1483
|
|
|
1484
|
+
// ────────── Asset attachments ──────────
|
|
1485
|
+
|
|
1486
|
+
async listAssetAttachments(
|
|
1487
|
+
twinId: string,
|
|
1488
|
+
assetId: string,
|
|
1489
|
+
options?: { includeDeleted?: boolean; offset?: number; limit?: number; page?: string },
|
|
1490
|
+
signal?: AbortSignal
|
|
1491
|
+
): Promise<PaginatedResponse<AttachmentGet>> {
|
|
1492
|
+
const params = new URLSearchParams();
|
|
1493
|
+
if (options?.includeDeleted) params.set('includeDeleted', 'true');
|
|
1494
|
+
if (options?.offset !== undefined) params.set('offset', String(options.offset));
|
|
1495
|
+
if (options?.limit !== undefined) params.set('limit', String(options.limit));
|
|
1496
|
+
if (options?.page) params.set('page', options.page);
|
|
1497
|
+
|
|
1498
|
+
const url = `${this._baseUrl}/${twinId}/assets/${assetId}/attachments${params.toString() ? `?${params}` : ''}`;
|
|
1499
|
+
const response = await this._httpClient.fetch(HttpMethod.Get, url, {
|
|
1500
|
+
headers: { Accept: 'application/json' },
|
|
1501
|
+
signal
|
|
1502
|
+
});
|
|
1503
|
+
|
|
1504
|
+
if (response.ok) return (await response.json()) as PaginatedResponse<AttachmentGet>;
|
|
1505
|
+
if (response.status === 404) throw new AssetNotFoundError(`Asset ${assetId} not found`);
|
|
1506
|
+
if (response.status === 400) {
|
|
1507
|
+
const errorBody = await readErrorBody(response);
|
|
1508
|
+
throw new AssetValidationError(`Attachment listing failed: ${errorBody.detail}`, errorBody);
|
|
1509
|
+
}
|
|
1510
|
+
const errorText = await response.text();
|
|
1511
|
+
throw new Error(`Failed to list attachments: ${response.status} ${response.statusText} - ${errorText}`);
|
|
1512
|
+
}
|
|
1513
|
+
|
|
1514
|
+
async getAssetAttachmentBlob(
|
|
1515
|
+
twinId: string,
|
|
1516
|
+
assetId: string,
|
|
1517
|
+
attachmentId: string,
|
|
1518
|
+
signal?: AbortSignal
|
|
1519
|
+
): Promise<Response> {
|
|
1520
|
+
const response = await this._httpClient.fetch(
|
|
1521
|
+
HttpMethod.Get,
|
|
1522
|
+
`${this._baseUrl}/${twinId}/assets/${assetId}/attachments/${attachmentId}`,
|
|
1523
|
+
{ signal }
|
|
1524
|
+
);
|
|
1525
|
+
if (response.ok) return response;
|
|
1526
|
+
if (response.status === 404) throw new AssetAttachmentNotFoundError(`Attachment ${attachmentId} not found`);
|
|
1527
|
+
const errorText = await response.text();
|
|
1528
|
+
throw new Error(`Failed to fetch attachment blob: ${response.status} ${response.statusText} - ${errorText}`);
|
|
1529
|
+
}
|
|
1530
|
+
|
|
1531
|
+
async createAssetAttachmentUploadSession(
|
|
1532
|
+
twinId: string,
|
|
1533
|
+
assetId: string,
|
|
1534
|
+
attachmentId: string,
|
|
1535
|
+
body: AttachmentPost,
|
|
1536
|
+
signal?: AbortSignal
|
|
1537
|
+
): Promise<ApiCreateUploadSessionResponse> {
|
|
1538
|
+
const response = await this._httpClient.fetch(
|
|
1539
|
+
HttpMethod.Post,
|
|
1540
|
+
`${this._baseUrl}/${twinId}/assets/${assetId}/attachments/${attachmentId}/createAttachmentUploadSession`,
|
|
1541
|
+
{
|
|
1542
|
+
headers: { 'Content-Type': 'application/json' },
|
|
1543
|
+
body: JSON.stringify(body),
|
|
1544
|
+
signal
|
|
1545
|
+
}
|
|
1546
|
+
);
|
|
1547
|
+
if (response.ok) return (await response.json()) as ApiCreateUploadSessionResponse;
|
|
1548
|
+
if (response.status === 409) {
|
|
1549
|
+
const conflicted = (await response.json()) as AttachmentGet;
|
|
1550
|
+
throw new AssetAttachmentConflictError(
|
|
1551
|
+
`Attachment ${attachmentId} already exists; pick a new id for retries`,
|
|
1552
|
+
conflicted
|
|
1553
|
+
);
|
|
1554
|
+
}
|
|
1555
|
+
if (response.status === 404) throw new AssetNotFoundError(`Asset ${assetId} not found`);
|
|
1556
|
+
if (response.status === 400) {
|
|
1557
|
+
const errorBody = await readErrorBody(response);
|
|
1558
|
+
throw new AssetValidationError(`Upload session creation failed: ${errorBody.detail}`, errorBody);
|
|
1559
|
+
}
|
|
1560
|
+
const errorText = await response.text();
|
|
1561
|
+
throw new Error(`Failed to create upload session: ${response.status} ${response.statusText} - ${errorText}`);
|
|
1562
|
+
}
|
|
1563
|
+
|
|
1564
|
+
async uploadAssetAttachmentFile(
|
|
1565
|
+
session: ApiCreateUploadSessionResponse,
|
|
1566
|
+
file: Blob,
|
|
1567
|
+
signal?: AbortSignal
|
|
1568
|
+
): Promise<{ token: string }> {
|
|
1569
|
+
// The token is encoded as a query param on the upload URL; we lift it
|
|
1570
|
+
// out for the caller so they can poll uploadStatus without re-parsing.
|
|
1571
|
+
const tokenMatch = session.uploadUrl.match(/token=([^&]+)/);
|
|
1572
|
+
if (!tokenMatch) {
|
|
1573
|
+
throw new Error(`Upload session URL is missing a token query parameter: ${session.uploadUrl}`);
|
|
1574
|
+
}
|
|
1575
|
+
const token = tokenMatch[1];
|
|
1576
|
+
|
|
1577
|
+
const chunkSize = Math.max(1, session.maxChunkSize || file.size);
|
|
1578
|
+
const total = file.size;
|
|
1579
|
+
let offset = 0;
|
|
1580
|
+
|
|
1581
|
+
// Even an empty file needs at least one PUT so the upload session
|
|
1582
|
+
// gets a finalize signal. uploadChunks() in the integration tests
|
|
1583
|
+
// unconditionally PUTs at least one chunk too.
|
|
1584
|
+
do {
|
|
1585
|
+
const end = Math.min(offset + chunkSize, total);
|
|
1586
|
+
const chunk = file.slice(offset, end);
|
|
1587
|
+
const lastByte = Math.max(0, end - 1);
|
|
1588
|
+
const response = await this._httpClient.fetch(HttpMethod.Put, session.uploadUrl, {
|
|
1589
|
+
headers: { 'Content-Range': `bytes ${offset}-${lastByte}/${total}` },
|
|
1590
|
+
body: chunk,
|
|
1591
|
+
signal
|
|
1592
|
+
});
|
|
1593
|
+
if (!response.ok) {
|
|
1594
|
+
const errorText = await response.text();
|
|
1595
|
+
throw new Error(
|
|
1596
|
+
`Upload chunk failed at offset ${offset}: ${response.status} ${response.statusText} - ${errorText}`
|
|
1597
|
+
);
|
|
1598
|
+
}
|
|
1599
|
+
offset = end;
|
|
1600
|
+
} while (offset < total);
|
|
1601
|
+
|
|
1602
|
+
return { token };
|
|
1603
|
+
}
|
|
1604
|
+
|
|
1605
|
+
async getAssetAttachmentUploadStatus(
|
|
1606
|
+
twinId: string,
|
|
1607
|
+
assetId: string,
|
|
1608
|
+
token: string,
|
|
1609
|
+
signal?: AbortSignal
|
|
1610
|
+
): Promise<UploadStatusGet> {
|
|
1611
|
+
const response = await this._httpClient.fetch(
|
|
1612
|
+
HttpMethod.Get,
|
|
1613
|
+
`${this._baseUrl}/${twinId}/assets/${assetId}/attachments/uploadStatus/${encodeURIComponent(token)}`,
|
|
1614
|
+
{ headers: { Accept: 'application/json' }, signal }
|
|
1615
|
+
);
|
|
1616
|
+
if (response.ok) return (await response.json()) as UploadStatusGet;
|
|
1617
|
+
if (response.status === 404) return { status: 'NotFound' };
|
|
1618
|
+
const errorText = await response.text();
|
|
1619
|
+
throw new Error(`Failed to get upload status: ${response.status} ${response.statusText} - ${errorText}`);
|
|
1620
|
+
}
|
|
1621
|
+
|
|
1622
|
+
async putAssetAttachment(
|
|
1623
|
+
twinId: string,
|
|
1624
|
+
assetId: string,
|
|
1625
|
+
attachmentId: string,
|
|
1626
|
+
body: AssetAttachmentPut,
|
|
1627
|
+
signal?: AbortSignal
|
|
1628
|
+
): Promise<AttachmentGet> {
|
|
1629
|
+
const response = await this._httpClient.fetch(
|
|
1630
|
+
HttpMethod.Put,
|
|
1631
|
+
`${this._baseUrl}/${twinId}/assets/${assetId}/attachments/${attachmentId}`,
|
|
1632
|
+
{
|
|
1633
|
+
headers: { 'Content-Type': 'application/json' },
|
|
1634
|
+
body: JSON.stringify(body),
|
|
1635
|
+
signal
|
|
1636
|
+
}
|
|
1637
|
+
);
|
|
1638
|
+
if (response.ok) return (await response.json()) as AttachmentGet;
|
|
1639
|
+
if (response.status === 409) {
|
|
1640
|
+
const conflicted = (await response.json()) as AttachmentGet;
|
|
1641
|
+
throw new AssetAttachmentConflictError('Attachment has been modified by another user', conflicted);
|
|
1642
|
+
}
|
|
1643
|
+
if (response.status === 404) throw new AssetAttachmentNotFoundError(`Attachment ${attachmentId} not found`);
|
|
1644
|
+
if (response.status === 400) {
|
|
1645
|
+
const errorBody = await readErrorBody(response);
|
|
1646
|
+
throw new AssetValidationError(`Attachment update failed: ${errorBody.detail}`, errorBody);
|
|
1647
|
+
}
|
|
1648
|
+
const errorText = await response.text();
|
|
1649
|
+
throw new Error(`Failed to update attachment: ${response.status} ${response.statusText} - ${errorText}`);
|
|
1650
|
+
}
|
|
1651
|
+
|
|
1652
|
+
async deleteAssetAttachment(
|
|
1653
|
+
twinId: string,
|
|
1654
|
+
assetId: string,
|
|
1655
|
+
attachmentId: string,
|
|
1656
|
+
etag: string,
|
|
1657
|
+
signal?: AbortSignal
|
|
1658
|
+
): Promise<AttachmentGet> {
|
|
1659
|
+
const response = await this._httpClient.fetch(
|
|
1660
|
+
HttpMethod.Delete,
|
|
1661
|
+
`${this._baseUrl}/${twinId}/assets/${assetId}/attachments/${attachmentId}`,
|
|
1662
|
+
{
|
|
1663
|
+
headers: { 'If-Match': etag },
|
|
1664
|
+
signal
|
|
1665
|
+
}
|
|
1666
|
+
);
|
|
1667
|
+
if (response.ok) return (await response.json()) as AttachmentGet;
|
|
1668
|
+
if (response.status === 409) {
|
|
1669
|
+
const conflicted = (await response.json()) as AttachmentGet;
|
|
1670
|
+
throw new AssetAttachmentConflictError('Attachment has been modified by another user', conflicted);
|
|
1671
|
+
}
|
|
1672
|
+
if (response.status === 404) throw new AssetAttachmentNotFoundError(`Attachment ${attachmentId} not found`);
|
|
1673
|
+
const errorText = await response.text();
|
|
1674
|
+
throw new Error(`Failed to delete attachment: ${response.status} ${response.statusText} - ${errorText}`);
|
|
1675
|
+
}
|
|
1676
|
+
|
|
1677
|
+
async restoreAssetAttachment(
|
|
1678
|
+
twinId: string,
|
|
1679
|
+
assetId: string,
|
|
1680
|
+
attachmentId: string,
|
|
1681
|
+
etag: string,
|
|
1682
|
+
signal?: AbortSignal
|
|
1683
|
+
): Promise<AttachmentGet> {
|
|
1684
|
+
const response = await this._httpClient.fetch(
|
|
1685
|
+
HttpMethod.Put,
|
|
1686
|
+
`${this._baseUrl}/${twinId}/assets/${assetId}/attachments/${attachmentId}/restore`,
|
|
1687
|
+
{
|
|
1688
|
+
headers: { 'Content-Type': 'application/json' },
|
|
1689
|
+
body: JSON.stringify({ etag }),
|
|
1690
|
+
signal
|
|
1691
|
+
}
|
|
1692
|
+
);
|
|
1693
|
+
if (response.ok) return (await response.json()) as AttachmentGet;
|
|
1694
|
+
if (response.status === 409) {
|
|
1695
|
+
const conflicted = (await response.json()) as AttachmentGet;
|
|
1696
|
+
throw new AssetAttachmentConflictError('Attachment has been modified by another user', conflicted);
|
|
1697
|
+
}
|
|
1698
|
+
if (response.status === 404) throw new AssetAttachmentNotFoundError(`Attachment ${attachmentId} not found`);
|
|
1699
|
+
const errorText = await response.text();
|
|
1700
|
+
throw new Error(`Failed to restore attachment: ${response.status} ${response.statusText} - ${errorText}`);
|
|
1701
|
+
}
|
|
1702
|
+
|
|
1379
1703
|
async listTwinFiles(
|
|
1380
1704
|
twinId: string,
|
|
1381
1705
|
options: TwinFileListOptions = {},
|
package/src/errors.ts
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import type { TwinGet, AssetGet, TwinFileGet, AssetBatchResponse, AssetCategoryGet, AssetTypeGet } from './types';
|
|
2
|
+
import type { AttachmentGet } from './types/asset-attachment-api';
|
|
2
3
|
|
|
3
4
|
/**
|
|
4
5
|
* Closed union of `cause` values the Twin service emits on a 400 response. Mirrors
|
|
@@ -41,6 +42,7 @@ export type TwinErrorCause =
|
|
|
41
42
|
| 'AssetCategoryAndTypeRequired'
|
|
42
43
|
| 'StringIdInUse'
|
|
43
44
|
| 'CatalogTooLarge'
|
|
45
|
+
| 'EtagRequired'
|
|
44
46
|
// Anything the server emits that this client doesn't know about yet.
|
|
45
47
|
// (string & {}) keeps the autocomplete on the listed values above.
|
|
46
48
|
// eslint-disable-next-line @typescript-eslint/ban-types
|
|
@@ -166,6 +168,23 @@ export class AssetNotFoundError extends Error {
|
|
|
166
168
|
}
|
|
167
169
|
}
|
|
168
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
|
+
|
|
169
188
|
export class AssetBatchError extends Error {
|
|
170
189
|
public readonly response: AssetBatchResponse;
|
|
171
190
|
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Wire types for asset attachments. Mirrors the C# DTOs in
|
|
3
|
+
* `Twinfinity.Twin.Controllers.Model.Attachment`. The (asset, document)
|
|
4
|
+
* pair is fixed at upload-finalize time; the only way to replace a file
|
|
5
|
+
* is to delete the attachment and create a new one with a fresh upload.
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
export interface AttachmentGet {
|
|
9
|
+
twinId: string;
|
|
10
|
+
assetId: string;
|
|
11
|
+
id: string;
|
|
12
|
+
documentId: string;
|
|
13
|
+
createdUtc: string;
|
|
14
|
+
modifiedUtc: string;
|
|
15
|
+
createdBy: string;
|
|
16
|
+
modifiedBy: string;
|
|
17
|
+
etag: string;
|
|
18
|
+
/** `[REDACTED]` on soft-deleted rows. */
|
|
19
|
+
fileName: string;
|
|
20
|
+
/** `[REDACTED]` on soft-deleted rows. */
|
|
21
|
+
description: string | null;
|
|
22
|
+
/** Present and `true` on soft-deleted rows; omitted from the wire payload otherwise. */
|
|
23
|
+
isDeleted?: boolean;
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
/** Body for `POST .../createAttachmentUploadSession`. */
|
|
27
|
+
export interface AttachmentPost {
|
|
28
|
+
fileName: string;
|
|
29
|
+
description?: string | null;
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
/**
|
|
33
|
+
* Body for `PUT .../{attachmentId}` (metadata-only update). Soft-delete and
|
|
34
|
+
* restore go through `DELETE` / `PUT /restore`, not this endpoint.
|
|
35
|
+
*/
|
|
36
|
+
export interface AssetAttachmentPut {
|
|
37
|
+
documentId: string;
|
|
38
|
+
description?: string | null;
|
|
39
|
+
etag: string;
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
/** Response from `createAttachmentUploadSession`. */
|
|
43
|
+
export interface ApiCreateUploadSessionResponse {
|
|
44
|
+
/** Maximum bytes per `PUT` chunk. */
|
|
45
|
+
maxChunkSize: number;
|
|
46
|
+
/** URL the client uploads the file to. The token is encoded as a query parameter. */
|
|
47
|
+
uploadUrl: string;
|
|
48
|
+
expiresUtc: string;
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
/** Polling shape returned by `uploadStatus/{token}`. */
|
|
52
|
+
export interface UploadStatusGet {
|
|
53
|
+
status: UploadStatus;
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
export type UploadStatus = 'NotFound' | 'InProgress' | 'Completed' | 'Cancelled' | 'Failed';
|
package/src/types/index.ts
CHANGED
|
@@ -3,6 +3,7 @@ export * from './twin-api';
|
|
|
3
3
|
export * from './asset-api';
|
|
4
4
|
export * from './asset-batch-api';
|
|
5
5
|
export * from './asset-types-api';
|
|
6
|
+
export * from './asset-attachment-api';
|
|
6
7
|
export * from './twin-permissions-api';
|
|
7
8
|
export * from './twin-file-api';
|
|
8
9
|
export * from './generated';
|