@proveanything/smartlinks 1.15.15 → 1.15.16
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/api/asset.d.ts +24 -1
- package/dist/api/asset.js +178 -0
- package/dist/docs/API_SUMMARY.md +45 -1
- package/dist/openapi.yaml +35 -0
- package/dist/types/asset.d.ts +56 -0
- package/docs/API_SUMMARY.md +45 -1
- package/openapi.yaml +35 -0
- package/package.json +1 -1
package/dist/api/asset.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { Asset, AssetResponse, UploadAssetOptions, UploadFromUrlOptions, ListAssetsOptions, GetAssetOptions, RemoveAssetOptions, AdminListAssetsOptions, AdminListAssetsResponse, UpdateAssetOptions, ReplaceAssetFileOptions, DeleteAssetOptions, BulkDeleteAssetsOptions, RequestUploadTokenOptions, UploadTokenResponse, PublicTokenUploadOptions } from "../types/asset";
|
|
1
|
+
import { Asset, AssetResponse, UploadAssetOptions, UploadFromUrlOptions, ListAssetsOptions, GetAssetOptions, RemoveAssetOptions, AdminListAssetsOptions, AdminListAssetsResponse, UpdateAssetOptions, ReplaceAssetFileOptions, DeleteAssetOptions, BulkDeleteAssetsOptions, RequestUploadTokenOptions, UploadTokenResponse, PublicTokenUploadOptions, CreateResumableUploadOptions, ResumableUploadHandle } from "../types/asset";
|
|
2
2
|
export declare namespace asset {
|
|
3
3
|
/**
|
|
4
4
|
* Error type for asset uploads
|
|
@@ -136,4 +136,27 @@ export declare namespace asset {
|
|
|
136
136
|
* has `reviewRequired: true`.
|
|
137
137
|
*/
|
|
138
138
|
function publicUploadWithToken(options: PublicTokenUploadOptions): Promise<Asset>;
|
|
139
|
+
/** Thrown by a resumable `start()`/`resume()` when the caller pauses mid-transfer. */
|
|
140
|
+
class UploadPausedError extends Error {
|
|
141
|
+
constructor();
|
|
142
|
+
}
|
|
143
|
+
/**
|
|
144
|
+
* Open a resumable upload for a large file (e.g. video). The bytes are chunked
|
|
145
|
+
* directly to storage and can be paused/resumed — including after a page reload
|
|
146
|
+
* or app restart, by persisting `handle.id` and calling {@link resumeUpload}.
|
|
147
|
+
*
|
|
148
|
+
* @example
|
|
149
|
+
* ```ts
|
|
150
|
+
* const handle = await asset.createResumableUpload({ file, scope, appId })
|
|
151
|
+
* localStorage.setItem('pendingUpload', handle.id) // survives reload
|
|
152
|
+
* const uploaded = await handle.start({ onProgress: p => setPct(p) })
|
|
153
|
+
* ```
|
|
154
|
+
*/
|
|
155
|
+
function createResumableUpload(options: CreateResumableUploadOptions): Promise<ResumableUploadHandle>;
|
|
156
|
+
/**
|
|
157
|
+
* Resume a previously-created resumable upload after a reload/app restart.
|
|
158
|
+
* Pass the persisted `handle.id` and the same `File`; the transfer continues
|
|
159
|
+
* from the offset storage already holds rather than restarting.
|
|
160
|
+
*/
|
|
161
|
+
function resumeUpload(handleId: string, file: File): Promise<ResumableUploadHandle>;
|
|
139
162
|
}
|
package/dist/api/asset.js
CHANGED
|
@@ -104,6 +104,14 @@ export var asset;
|
|
|
104
104
|
}
|
|
105
105
|
};
|
|
106
106
|
xhr.onerror = () => reject(new AssetUploadError("Network error during asset upload", 'NETWORK_ERROR'));
|
|
107
|
+
if (options.signal) {
|
|
108
|
+
if (options.signal.aborted) {
|
|
109
|
+
xhr.abort();
|
|
110
|
+
return reject(new AssetUploadError("Upload aborted", 'NETWORK_ERROR'));
|
|
111
|
+
}
|
|
112
|
+
options.signal.addEventListener('abort', () => xhr.abort(), { once: true });
|
|
113
|
+
xhr.onabort = () => reject(new AssetUploadError("Upload aborted", 'NETWORK_ERROR'));
|
|
114
|
+
}
|
|
107
115
|
xhr.send(formData);
|
|
108
116
|
});
|
|
109
117
|
}
|
|
@@ -529,4 +537,174 @@ export var asset;
|
|
|
529
537
|
return response.json();
|
|
530
538
|
}
|
|
531
539
|
asset.publicUploadWithToken = publicUploadWithToken;
|
|
540
|
+
// ---------------------------------------------------------------------------
|
|
541
|
+
// Resumable uploads (large files, e.g. video) — GCS-backed, chunked, resumable
|
|
542
|
+
// ---------------------------------------------------------------------------
|
|
543
|
+
const RESUMABLE_CHUNK_SIZE = 8 * 1024 * 1024; // 8 MiB — must be a multiple of 256 KiB (GCS rule)
|
|
544
|
+
const RESUMABLE_MAX_RETRIES = 5;
|
|
545
|
+
/** Thrown by a resumable `start()`/`resume()` when the caller pauses mid-transfer. */
|
|
546
|
+
class UploadPausedError extends Error {
|
|
547
|
+
constructor() { super('Upload paused'); this.name = 'UploadPausedError'; }
|
|
548
|
+
}
|
|
549
|
+
asset.UploadPausedError = UploadPausedError;
|
|
550
|
+
function backoff(attempt) {
|
|
551
|
+
const ms = Math.min(30000, 1000 * Math.pow(2, attempt - 1));
|
|
552
|
+
return new Promise(r => setTimeout(r, ms));
|
|
553
|
+
}
|
|
554
|
+
class ResumableUpload {
|
|
555
|
+
constructor(uploadId, // signed JWT — capability for finalize
|
|
556
|
+
sessionUrl, // GCS resumable session URI
|
|
557
|
+
file, finalizePath, finalizeBody) {
|
|
558
|
+
this.uploadId = uploadId;
|
|
559
|
+
this.sessionUrl = sessionUrl;
|
|
560
|
+
this.file = file;
|
|
561
|
+
this.finalizePath = finalizePath;
|
|
562
|
+
this.finalizeBody = finalizeBody;
|
|
563
|
+
this._paused = false;
|
|
564
|
+
this._offset = 0;
|
|
565
|
+
}
|
|
566
|
+
get id() {
|
|
567
|
+
const st = { u: this.uploadId, s: this.sessionUrl, n: this.file.name, z: this.file.size, f: this.finalizePath };
|
|
568
|
+
return JSON.stringify(st);
|
|
569
|
+
}
|
|
570
|
+
get size() { return this.file.size; }
|
|
571
|
+
pause() { this._paused = true; }
|
|
572
|
+
resume(options) {
|
|
573
|
+
this._paused = false;
|
|
574
|
+
return this.start(options);
|
|
575
|
+
}
|
|
576
|
+
async start(options) {
|
|
577
|
+
this._paused = false;
|
|
578
|
+
const onProgress = options === null || options === void 0 ? void 0 : options.onProgress;
|
|
579
|
+
const signal = options === null || options === void 0 ? void 0 : options.signal;
|
|
580
|
+
// Probe the storage offset first — this is what makes resume work after a reload.
|
|
581
|
+
this._offset = await this.probeOffset(signal);
|
|
582
|
+
while (this._offset < this.file.size) {
|
|
583
|
+
if (signal === null || signal === void 0 ? void 0 : signal.aborted)
|
|
584
|
+
throw new AssetUploadError('Upload aborted', 'NETWORK_ERROR');
|
|
585
|
+
if (this._paused)
|
|
586
|
+
throw new UploadPausedError();
|
|
587
|
+
const end = Math.min(this._offset + RESUMABLE_CHUNK_SIZE, this.file.size);
|
|
588
|
+
const complete = await this.putChunk(this._offset, end, signal);
|
|
589
|
+
this._offset = end;
|
|
590
|
+
if (onProgress)
|
|
591
|
+
onProgress(Math.round((this._offset / this.file.size) * 100));
|
|
592
|
+
if (complete)
|
|
593
|
+
break;
|
|
594
|
+
}
|
|
595
|
+
return post(this.finalizePath, this.finalizeBody);
|
|
596
|
+
}
|
|
597
|
+
// PUT with `bytes * /total` returns the current stored offset (or completion).
|
|
598
|
+
async probeOffset(signal) {
|
|
599
|
+
const res = await this.putWithRetry({ 'Content-Range': `bytes */${this.file.size}` }, undefined, signal);
|
|
600
|
+
if (res.status === 200 || res.status === 201)
|
|
601
|
+
return this.file.size;
|
|
602
|
+
if (res.status === 308) {
|
|
603
|
+
const range = res.headers.get('Range');
|
|
604
|
+
const m = range && /bytes=0-(\d+)/.exec(range);
|
|
605
|
+
return m ? parseInt(m[1], 10) + 1 : 0;
|
|
606
|
+
}
|
|
607
|
+
if (res.status === 404 || res.status === 410)
|
|
608
|
+
throw new AssetUploadError('Upload session expired', 'UNKNOWN');
|
|
609
|
+
throw new AssetUploadError(`Unexpected resume-probe status ${res.status}`, 'UNKNOWN');
|
|
610
|
+
}
|
|
611
|
+
// Returns true when the final chunk completed the upload (2xx from GCS).
|
|
612
|
+
async putChunk(start, end, signal) {
|
|
613
|
+
const blob = this.file.slice(start, end);
|
|
614
|
+
const res = await this.putWithRetry({ 'Content-Range': `bytes ${start}-${end - 1}/${this.file.size}` }, blob, signal);
|
|
615
|
+
if (res.status === 200 || res.status === 201)
|
|
616
|
+
return true;
|
|
617
|
+
if (res.status === 308)
|
|
618
|
+
return false;
|
|
619
|
+
throw new AssetUploadError(`Chunk upload failed (${res.status})`, res.status === 413 ? 'FILE_TOO_LARGE' : 'UNKNOWN');
|
|
620
|
+
}
|
|
621
|
+
async putWithRetry(headers, body, signal) {
|
|
622
|
+
let attempt = 0;
|
|
623
|
+
while (true) {
|
|
624
|
+
if (signal === null || signal === void 0 ? void 0 : signal.aborted)
|
|
625
|
+
throw new AssetUploadError('Upload aborted', 'NETWORK_ERROR');
|
|
626
|
+
try {
|
|
627
|
+
const res = await fetch(this.sessionUrl, { method: 'PUT', headers, body, signal });
|
|
628
|
+
if (res.status >= 500 && attempt < RESUMABLE_MAX_RETRIES) {
|
|
629
|
+
attempt++;
|
|
630
|
+
await backoff(attempt);
|
|
631
|
+
continue;
|
|
632
|
+
}
|
|
633
|
+
return res;
|
|
634
|
+
}
|
|
635
|
+
catch (err) {
|
|
636
|
+
if (signal === null || signal === void 0 ? void 0 : signal.aborted)
|
|
637
|
+
throw new AssetUploadError('Upload aborted', 'NETWORK_ERROR');
|
|
638
|
+
if (attempt < RESUMABLE_MAX_RETRIES) {
|
|
639
|
+
attempt++;
|
|
640
|
+
await backoff(attempt);
|
|
641
|
+
continue;
|
|
642
|
+
}
|
|
643
|
+
throw new AssetUploadError('Network error during resumable upload', 'NETWORK_ERROR');
|
|
644
|
+
}
|
|
645
|
+
}
|
|
646
|
+
}
|
|
647
|
+
}
|
|
648
|
+
function resumableBasePath(opts) {
|
|
649
|
+
const prefix = (opts.admin && !opts.token) ? '/admin' : '/public';
|
|
650
|
+
return `${prefix}/collection/${encodeURIComponent(opts.collectionId)}/asset/resumable`;
|
|
651
|
+
}
|
|
652
|
+
/**
|
|
653
|
+
* Open a resumable upload for a large file (e.g. video). The bytes are chunked
|
|
654
|
+
* directly to storage and can be paused/resumed — including after a page reload
|
|
655
|
+
* or app restart, by persisting `handle.id` and calling {@link resumeUpload}.
|
|
656
|
+
*
|
|
657
|
+
* @example
|
|
658
|
+
* ```ts
|
|
659
|
+
* const handle = await asset.createResumableUpload({ file, scope, appId })
|
|
660
|
+
* localStorage.setItem('pendingUpload', handle.id) // survives reload
|
|
661
|
+
* const uploaded = await handle.start({ onProgress: p => setPct(p) })
|
|
662
|
+
* ```
|
|
663
|
+
*/
|
|
664
|
+
async function createResumableUpload(options) {
|
|
665
|
+
const { file, scope, name, appId, token, admin } = options;
|
|
666
|
+
const base = resumableBasePath({ admin, token, collectionId: scope.collectionId });
|
|
667
|
+
const startBody = {
|
|
668
|
+
filename: name || file.name,
|
|
669
|
+
mime: file.type || 'application/octet-stream',
|
|
670
|
+
appId,
|
|
671
|
+
};
|
|
672
|
+
if (scope.type !== 'collection')
|
|
673
|
+
startBody.productId = scope.productId;
|
|
674
|
+
if (scope.type === 'proof')
|
|
675
|
+
startBody.proofId = scope.proofId;
|
|
676
|
+
const started = await post(base, startBody, token ? { 'X-Upload-Token': token } : undefined);
|
|
677
|
+
const finalizePath = `${base}/${encodeURIComponent(started.uploadId)}/complete`;
|
|
678
|
+
const finalizeBody = {};
|
|
679
|
+
if (name)
|
|
680
|
+
finalizeBody.name = name;
|
|
681
|
+
if (options.metadata)
|
|
682
|
+
finalizeBody.metadata = options.metadata;
|
|
683
|
+
return new ResumableUpload(started.uploadId, started.sessionUrl, file, finalizePath, finalizeBody);
|
|
684
|
+
}
|
|
685
|
+
asset.createResumableUpload = createResumableUpload;
|
|
686
|
+
/**
|
|
687
|
+
* Resume a previously-created resumable upload after a reload/app restart.
|
|
688
|
+
* Pass the persisted `handle.id` and the same `File`; the transfer continues
|
|
689
|
+
* from the offset storage already holds rather than restarting.
|
|
690
|
+
*/
|
|
691
|
+
async function resumeUpload(handleId, file) {
|
|
692
|
+
let st;
|
|
693
|
+
try {
|
|
694
|
+
st = JSON.parse(handleId);
|
|
695
|
+
}
|
|
696
|
+
catch (_b) {
|
|
697
|
+
throw new AssetUploadError('Invalid resumable upload handle', 'UNKNOWN');
|
|
698
|
+
}
|
|
699
|
+
if (!st.u || !st.s || !st.f)
|
|
700
|
+
throw new AssetUploadError('Invalid resumable upload handle', 'UNKNOWN');
|
|
701
|
+
if (typeof st.z === 'number' && file.size !== st.z) {
|
|
702
|
+
throw new AssetUploadError('Resumed file does not match the original upload', 'UNKNOWN');
|
|
703
|
+
}
|
|
704
|
+
const finalizeBody = {};
|
|
705
|
+
if (st.n)
|
|
706
|
+
finalizeBody.name = st.n;
|
|
707
|
+
return new ResumableUpload(st.u, st.s, file, st.f, finalizeBody);
|
|
708
|
+
}
|
|
709
|
+
asset.resumeUpload = resumeUpload;
|
|
532
710
|
})(asset || (asset = {}));
|
package/dist/docs/API_SUMMARY.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# Smartlinks API Summary
|
|
2
2
|
|
|
3
|
-
Version: 1.15.
|
|
3
|
+
Version: 1.15.16 | Generated: 2026-08-15T11:42:50.997Z
|
|
4
4
|
|
|
5
5
|
This is a concise summary of all available API functions and types.
|
|
6
6
|
|
|
@@ -2459,6 +2459,7 @@ interface UploadAssetOptions {
|
|
|
2459
2459
|
onProgress?: (percent: number) => void
|
|
2460
2460
|
appId?: string
|
|
2461
2461
|
admin?: boolean
|
|
2462
|
+
signal?: AbortSignal
|
|
2462
2463
|
}
|
|
2463
2464
|
```
|
|
2464
2465
|
|
|
@@ -2639,6 +2640,43 @@ interface PublicTokenUploadOptions {
|
|
|
2639
2640
|
}
|
|
2640
2641
|
```
|
|
2641
2642
|
|
|
2643
|
+
**CreateResumableUploadOptions** (interface)
|
|
2644
|
+
```typescript
|
|
2645
|
+
interface CreateResumableUploadOptions {
|
|
2646
|
+
file: File
|
|
2647
|
+
scope:
|
|
2648
|
+
| { type: 'collection'; collectionId: string }
|
|
2649
|
+
| { type: 'product'; collectionId: string; productId: string }
|
|
2650
|
+
| { type: 'proof'; collectionId: string; productId: string; proofId: string }
|
|
2651
|
+
name?: string
|
|
2652
|
+
metadata?: Record<string, any>
|
|
2653
|
+
appId?: string
|
|
2654
|
+
admin?: boolean
|
|
2655
|
+
* Upload token id (from {@link requestUploadToken}) for public/unauthenticated
|
|
2656
|
+
* uploads. When provided, the public resumable route is used.
|
|
2657
|
+
token?: string
|
|
2658
|
+
}
|
|
2659
|
+
```
|
|
2660
|
+
|
|
2661
|
+
**ResumableStartOptions** (interface)
|
|
2662
|
+
```typescript
|
|
2663
|
+
interface ResumableStartOptions {
|
|
2664
|
+
onProgress?: (percent: number) => void
|
|
2665
|
+
signal?: AbortSignal
|
|
2666
|
+
}
|
|
2667
|
+
```
|
|
2668
|
+
|
|
2669
|
+
**ResumableUploadHandle** (interface)
|
|
2670
|
+
```typescript
|
|
2671
|
+
interface ResumableUploadHandle {
|
|
2672
|
+
readonly id: string
|
|
2673
|
+
readonly size: number
|
|
2674
|
+
start(options?: ResumableStartOptions): Promise<Asset>
|
|
2675
|
+
pause(): void
|
|
2676
|
+
resume(options?: ResumableStartOptions): Promise<Asset>
|
|
2677
|
+
}
|
|
2678
|
+
```
|
|
2679
|
+
|
|
2642
2680
|
**AssetResponse** = `Asset`
|
|
2643
2681
|
|
|
2644
2682
|
### attestation
|
|
@@ -8479,6 +8517,12 @@ Request a single-use upload token for a public (unauthenticated) upload. The tok
|
|
|
8479
8517
|
**publicUploadWithToken**(options: PublicTokenUploadOptions) → `Promise<Asset>`
|
|
8480
8518
|
Upload a file using a single-use upload token (no admin auth required). Assets are created with `status: 'pending_review'` when the token policy has `reviewRequired: true`.
|
|
8481
8519
|
|
|
8520
|
+
**createResumableUpload**(options: CreateResumableUploadOptions) → `Promise<ResumableUploadHandle>`
|
|
8521
|
+
Open a resumable upload for a large file (e.g. video). The bytes are chunked directly to storage and can be paused/resumed — including after a page reload or app restart, by persisting `handle.id` and calling {@link resumeUpload}. ```ts const handle = await asset.createResumableUpload({ file, scope, appId }) localStorage.setItem('pendingUpload', handle.id) // survives reload const uploaded = await handle.start({ onProgress: p => setPct(p) }) ```
|
|
8522
|
+
|
|
8523
|
+
**resumeUpload**(handleId: string, file: File) → `Promise<ResumableUploadHandle>`
|
|
8524
|
+
Resume a previously-created resumable upload after a reload/app restart. Pass the persisted `handle.id` and the same `File`; the transfer continues from the offset storage already holds rather than restarting.
|
|
8525
|
+
|
|
8482
8526
|
### async
|
|
8483
8527
|
|
|
8484
8528
|
**enqueueAsyncJob**(collectionId: string,
|
package/dist/openapi.yaml
CHANGED
|
@@ -17731,6 +17731,8 @@ components:
|
|
|
17731
17731
|
type: string
|
|
17732
17732
|
admin:
|
|
17733
17733
|
type: boolean
|
|
17734
|
+
signal:
|
|
17735
|
+
$ref: "#/components/schemas/AbortSignal"
|
|
17734
17736
|
required:
|
|
17735
17737
|
- file
|
|
17736
17738
|
UploadFromUrlOptions:
|
|
@@ -17996,6 +17998,39 @@ components:
|
|
|
17996
17998
|
- collectionId
|
|
17997
17999
|
- tokenId
|
|
17998
18000
|
- file
|
|
18001
|
+
CreateResumableUploadOptions:
|
|
18002
|
+
type: object
|
|
18003
|
+
properties:
|
|
18004
|
+
file:
|
|
18005
|
+
$ref: "#/components/schemas/File"
|
|
18006
|
+
name:
|
|
18007
|
+
type: string
|
|
18008
|
+
metadata:
|
|
18009
|
+
type: object
|
|
18010
|
+
additionalProperties: true
|
|
18011
|
+
appId:
|
|
18012
|
+
type: string
|
|
18013
|
+
admin:
|
|
18014
|
+
type: boolean
|
|
18015
|
+
token:
|
|
18016
|
+
type: string
|
|
18017
|
+
required:
|
|
18018
|
+
- file
|
|
18019
|
+
ResumableStartOptions:
|
|
18020
|
+
type: object
|
|
18021
|
+
properties:
|
|
18022
|
+
signal:
|
|
18023
|
+
$ref: "#/components/schemas/AbortSignal"
|
|
18024
|
+
ResumableUploadHandle:
|
|
18025
|
+
type: object
|
|
18026
|
+
properties:
|
|
18027
|
+
id:
|
|
18028
|
+
type: string
|
|
18029
|
+
size:
|
|
18030
|
+
type: number
|
|
18031
|
+
required:
|
|
18032
|
+
- id
|
|
18033
|
+
- size
|
|
17999
18034
|
AttestationResponse:
|
|
18000
18035
|
type: object
|
|
18001
18036
|
properties:
|
package/dist/types/asset.d.ts
CHANGED
|
@@ -122,6 +122,8 @@ export interface UploadAssetOptions {
|
|
|
122
122
|
appId?: string;
|
|
123
123
|
/** Optional: Upload via admin route instead of public */
|
|
124
124
|
admin?: boolean;
|
|
125
|
+
/** Optional: Abort the in-flight upload (browser fetch/XHR only) */
|
|
126
|
+
signal?: AbortSignal;
|
|
125
127
|
}
|
|
126
128
|
/**
|
|
127
129
|
* Options for uploading an asset from a URL.
|
|
@@ -304,3 +306,57 @@ export interface PublicTokenUploadOptions {
|
|
|
304
306
|
metadata?: Record<string, any>;
|
|
305
307
|
onProgress?: (percent: number) => void;
|
|
306
308
|
}
|
|
309
|
+
/**
|
|
310
|
+
* Options for opening a resumable upload. Mirrors {@link UploadAssetOptions}
|
|
311
|
+
* but the transfer is chunked directly to storage and can be paused/resumed,
|
|
312
|
+
* including after a page reload or app restart.
|
|
313
|
+
*/
|
|
314
|
+
export interface CreateResumableUploadOptions {
|
|
315
|
+
file: File;
|
|
316
|
+
scope: {
|
|
317
|
+
type: 'collection';
|
|
318
|
+
collectionId: string;
|
|
319
|
+
} | {
|
|
320
|
+
type: 'product';
|
|
321
|
+
collectionId: string;
|
|
322
|
+
productId: string;
|
|
323
|
+
} | {
|
|
324
|
+
type: 'proof';
|
|
325
|
+
collectionId: string;
|
|
326
|
+
productId: string;
|
|
327
|
+
proofId: string;
|
|
328
|
+
};
|
|
329
|
+
name?: string;
|
|
330
|
+
metadata?: Record<string, any>;
|
|
331
|
+
appId?: string;
|
|
332
|
+
/** Upload via admin route (default) or, when set, the public token route. */
|
|
333
|
+
admin?: boolean;
|
|
334
|
+
/**
|
|
335
|
+
* Upload token id (from {@link requestUploadToken}) for public/unauthenticated
|
|
336
|
+
* uploads. When provided, the public resumable route is used.
|
|
337
|
+
*/
|
|
338
|
+
token?: string;
|
|
339
|
+
}
|
|
340
|
+
export interface ResumableStartOptions {
|
|
341
|
+
/** Progress callback (0-100), driven by bytes confirmed by storage. */
|
|
342
|
+
onProgress?: (percent: number) => void;
|
|
343
|
+
/** Abort the in-flight transfer. */
|
|
344
|
+
signal?: AbortSignal;
|
|
345
|
+
}
|
|
346
|
+
/**
|
|
347
|
+
* A handle to a resumable upload. `id` is durable — persist it (e.g. in
|
|
348
|
+
* IndexedDB) alongside a reference to the file and pass it to
|
|
349
|
+
* {@link asset.resumeUpload} after a reload to continue mid-file.
|
|
350
|
+
*/
|
|
351
|
+
export interface ResumableUploadHandle {
|
|
352
|
+
/** Durable, persistable upload id (survives reload/app restart). */
|
|
353
|
+
readonly id: string;
|
|
354
|
+
/** Total bytes of the file being uploaded. */
|
|
355
|
+
readonly size: number;
|
|
356
|
+
/** Begin (or continue) uploading, resuming from the storage offset. */
|
|
357
|
+
start(options?: ResumableStartOptions): Promise<Asset>;
|
|
358
|
+
/** Pause after the current chunk. */
|
|
359
|
+
pause(): void;
|
|
360
|
+
/** Resume a paused transfer. */
|
|
361
|
+
resume(options?: ResumableStartOptions): Promise<Asset>;
|
|
362
|
+
}
|
package/docs/API_SUMMARY.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# Smartlinks API Summary
|
|
2
2
|
|
|
3
|
-
Version: 1.15.
|
|
3
|
+
Version: 1.15.16 | Generated: 2026-08-15T11:42:50.997Z
|
|
4
4
|
|
|
5
5
|
This is a concise summary of all available API functions and types.
|
|
6
6
|
|
|
@@ -2459,6 +2459,7 @@ interface UploadAssetOptions {
|
|
|
2459
2459
|
onProgress?: (percent: number) => void
|
|
2460
2460
|
appId?: string
|
|
2461
2461
|
admin?: boolean
|
|
2462
|
+
signal?: AbortSignal
|
|
2462
2463
|
}
|
|
2463
2464
|
```
|
|
2464
2465
|
|
|
@@ -2639,6 +2640,43 @@ interface PublicTokenUploadOptions {
|
|
|
2639
2640
|
}
|
|
2640
2641
|
```
|
|
2641
2642
|
|
|
2643
|
+
**CreateResumableUploadOptions** (interface)
|
|
2644
|
+
```typescript
|
|
2645
|
+
interface CreateResumableUploadOptions {
|
|
2646
|
+
file: File
|
|
2647
|
+
scope:
|
|
2648
|
+
| { type: 'collection'; collectionId: string }
|
|
2649
|
+
| { type: 'product'; collectionId: string; productId: string }
|
|
2650
|
+
| { type: 'proof'; collectionId: string; productId: string; proofId: string }
|
|
2651
|
+
name?: string
|
|
2652
|
+
metadata?: Record<string, any>
|
|
2653
|
+
appId?: string
|
|
2654
|
+
admin?: boolean
|
|
2655
|
+
* Upload token id (from {@link requestUploadToken}) for public/unauthenticated
|
|
2656
|
+
* uploads. When provided, the public resumable route is used.
|
|
2657
|
+
token?: string
|
|
2658
|
+
}
|
|
2659
|
+
```
|
|
2660
|
+
|
|
2661
|
+
**ResumableStartOptions** (interface)
|
|
2662
|
+
```typescript
|
|
2663
|
+
interface ResumableStartOptions {
|
|
2664
|
+
onProgress?: (percent: number) => void
|
|
2665
|
+
signal?: AbortSignal
|
|
2666
|
+
}
|
|
2667
|
+
```
|
|
2668
|
+
|
|
2669
|
+
**ResumableUploadHandle** (interface)
|
|
2670
|
+
```typescript
|
|
2671
|
+
interface ResumableUploadHandle {
|
|
2672
|
+
readonly id: string
|
|
2673
|
+
readonly size: number
|
|
2674
|
+
start(options?: ResumableStartOptions): Promise<Asset>
|
|
2675
|
+
pause(): void
|
|
2676
|
+
resume(options?: ResumableStartOptions): Promise<Asset>
|
|
2677
|
+
}
|
|
2678
|
+
```
|
|
2679
|
+
|
|
2642
2680
|
**AssetResponse** = `Asset`
|
|
2643
2681
|
|
|
2644
2682
|
### attestation
|
|
@@ -8479,6 +8517,12 @@ Request a single-use upload token for a public (unauthenticated) upload. The tok
|
|
|
8479
8517
|
**publicUploadWithToken**(options: PublicTokenUploadOptions) → `Promise<Asset>`
|
|
8480
8518
|
Upload a file using a single-use upload token (no admin auth required). Assets are created with `status: 'pending_review'` when the token policy has `reviewRequired: true`.
|
|
8481
8519
|
|
|
8520
|
+
**createResumableUpload**(options: CreateResumableUploadOptions) → `Promise<ResumableUploadHandle>`
|
|
8521
|
+
Open a resumable upload for a large file (e.g. video). The bytes are chunked directly to storage and can be paused/resumed — including after a page reload or app restart, by persisting `handle.id` and calling {@link resumeUpload}. ```ts const handle = await asset.createResumableUpload({ file, scope, appId }) localStorage.setItem('pendingUpload', handle.id) // survives reload const uploaded = await handle.start({ onProgress: p => setPct(p) }) ```
|
|
8522
|
+
|
|
8523
|
+
**resumeUpload**(handleId: string, file: File) → `Promise<ResumableUploadHandle>`
|
|
8524
|
+
Resume a previously-created resumable upload after a reload/app restart. Pass the persisted `handle.id` and the same `File`; the transfer continues from the offset storage already holds rather than restarting.
|
|
8525
|
+
|
|
8482
8526
|
### async
|
|
8483
8527
|
|
|
8484
8528
|
**enqueueAsyncJob**(collectionId: string,
|
package/openapi.yaml
CHANGED
|
@@ -17731,6 +17731,8 @@ components:
|
|
|
17731
17731
|
type: string
|
|
17732
17732
|
admin:
|
|
17733
17733
|
type: boolean
|
|
17734
|
+
signal:
|
|
17735
|
+
$ref: "#/components/schemas/AbortSignal"
|
|
17734
17736
|
required:
|
|
17735
17737
|
- file
|
|
17736
17738
|
UploadFromUrlOptions:
|
|
@@ -17996,6 +17998,39 @@ components:
|
|
|
17996
17998
|
- collectionId
|
|
17997
17999
|
- tokenId
|
|
17998
18000
|
- file
|
|
18001
|
+
CreateResumableUploadOptions:
|
|
18002
|
+
type: object
|
|
18003
|
+
properties:
|
|
18004
|
+
file:
|
|
18005
|
+
$ref: "#/components/schemas/File"
|
|
18006
|
+
name:
|
|
18007
|
+
type: string
|
|
18008
|
+
metadata:
|
|
18009
|
+
type: object
|
|
18010
|
+
additionalProperties: true
|
|
18011
|
+
appId:
|
|
18012
|
+
type: string
|
|
18013
|
+
admin:
|
|
18014
|
+
type: boolean
|
|
18015
|
+
token:
|
|
18016
|
+
type: string
|
|
18017
|
+
required:
|
|
18018
|
+
- file
|
|
18019
|
+
ResumableStartOptions:
|
|
18020
|
+
type: object
|
|
18021
|
+
properties:
|
|
18022
|
+
signal:
|
|
18023
|
+
$ref: "#/components/schemas/AbortSignal"
|
|
18024
|
+
ResumableUploadHandle:
|
|
18025
|
+
type: object
|
|
18026
|
+
properties:
|
|
18027
|
+
id:
|
|
18028
|
+
type: string
|
|
18029
|
+
size:
|
|
18030
|
+
type: number
|
|
18031
|
+
required:
|
|
18032
|
+
- id
|
|
18033
|
+
- size
|
|
17999
18034
|
AttestationResponse:
|
|
18000
18035
|
type: object
|
|
18001
18036
|
properties:
|