@stackshift-cloud/sdk 1.1.0 → 1.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (43) hide show
  1. package/README.md +58 -1
  2. package/dist/assets-dam-types.d.ts +225 -0
  3. package/dist/assets-dam-types.js +1 -0
  4. package/dist/assets-dam.d.ts +96 -0
  5. package/dist/assets-dam.js +47 -0
  6. package/dist/assets-video-types.d.ts +116 -0
  7. package/dist/assets-video-types.js +1 -0
  8. package/dist/assets-video.d.ts +25 -0
  9. package/dist/assets-video.js +19 -0
  10. package/dist/assets.d.ts +5 -1
  11. package/dist/assets.js +11 -2
  12. package/dist/client.d.ts +4 -0
  13. package/dist/client.js +11 -0
  14. package/dist/generated/assets-contract.d.ts +246 -1
  15. package/dist/generated/assets-contract.js +49 -0
  16. package/dist/index.d.ts +14 -0
  17. package/dist/index.js +8 -0
  18. package/dist/mail-advanced-types.d.ts +9 -0
  19. package/dist/mail-billing.d.ts +34 -0
  20. package/dist/mail-billing.js +7 -0
  21. package/dist/mail-brands.d.ts +35 -0
  22. package/dist/mail-brands.js +17 -0
  23. package/dist/mail-campaigns.d.ts +72 -10
  24. package/dist/mail-campaigns.js +25 -2
  25. package/dist/mail-marketing.d.ts +84 -0
  26. package/dist/mail-marketing.js +24 -0
  27. package/dist/mail-migration.d.ts +16 -0
  28. package/dist/mail-migration.js +10 -0
  29. package/dist/mail-otp-types.d.ts +4 -0
  30. package/dist/mail-simulation.d.ts +4 -0
  31. package/dist/mail-simulation.js +1 -0
  32. package/dist/mail-subscribers.d.ts +39 -0
  33. package/dist/mail-subscribers.js +1 -0
  34. package/dist/mail-template-types.d.ts +8 -0
  35. package/dist/mail-tracking.d.ts +59 -0
  36. package/dist/mail-tracking.js +14 -0
  37. package/dist/mail-webhook-types.d.ts +4 -1
  38. package/dist/mail.d.ts +12 -0
  39. package/dist/mail.js +19 -0
  40. package/dist/types.d.ts +13 -0
  41. package/dist/workload-security.d.ts +172 -0
  42. package/dist/workload-security.js +50 -0
  43. package/package.json +2 -2
package/README.md CHANGED
@@ -2,6 +2,26 @@
2
2
 
3
3
  Official JavaScript and TypeScript SDK for StackShift.
4
4
 
5
+ ## Governed media and galleries
6
+
7
+ Use a separate server-side client for each Assets space; the namespace is fixed on that client. Project membership does not grant Assets access.
8
+
9
+ ```ts
10
+ const studio = new StackShift({
11
+ apiKey: process.env.STACKSHIFT_API_KEY,
12
+ assetSpaceId: 'your-asset-space-uuid',
13
+ })
14
+ const page = await studio.assets.dam.publications({ status: 'published' })
15
+ if (page.next_cursor) {
16
+ const next = await studio.assets.dam.publications({ status: 'published', cursor: page.next_cursor })
17
+ }
18
+ const gallery = await studio.assets.dam.resolveGallery('published-gallery-uuid')
19
+ ```
20
+
21
+ `assets.dam` also exposes collaborators, typed metadata schemas, bucket governance, publication transitions, model processing, gallery drafts and picker capabilities. Updates use explicit revisions. Submission needs `assets:write`, review needs `assets:admin`, and publication/withdrawal needs `assets:publish`, in addition to the corresponding Assets grant.
22
+
23
+ Keep account credentials on your server. Give `@stackshift-cloud/assets-picker` a short-lived, origin-restricted capability; give `@stackshift-cloud/assets-gallery` a server resolver for approved media. Store publication/gallery IDs and versions, never delivery URLs. Model processing is an explicitly enabled pilot and requires the qualified isolated worker described in `packages/assets-model-processor/README.md`.
24
+
5
25
  ## Install
6
26
 
7
27
  ```bash
@@ -276,7 +296,7 @@ const capability = await stackshift.assets.uploadCapabilities.create({
276
296
  })
277
297
  ```
278
298
 
279
- Create capabilities only in trusted backend code. Send `capability.token` to `@stackshift/assets-widget`; never put the Stackshift API key in a browser bundle.
299
+ Create capabilities only in trusted backend code. Send `capability.token` to `@stackshift-cloud/assets-widget`; never put the Stackshift API key in a browser bundle.
280
300
 
281
301
  For larger uploads, create a signed upload URL on your NestJS server and let the browser upload directly.
282
302
 
@@ -307,3 +327,40 @@ await fetch(upload.url, {
307
327
  This is the recommended pattern for React, Next.js, TanStack Start, and any browser app. The browser never receives your StackShift API key.
308
328
 
309
329
  StackShift chooses storage nodes, writes to StackShift-owned disks, replicates internally, and returns CDN-ready asset URLs. SDK users never choose storage nodes and never receive disk paths.
330
+
331
+ ### Campaign drafts and engagement
332
+
333
+ Create campaigns with `content: { subject, html, text, editorMode: 'code' }`, or keep using a template/version. `mail.campaigns.update(id, { ...draft, revision })` saves a full draft; `preview`, `test`, `send(id, revision)`, and `schedule(id, sendAt, revision)` support review and dispatch. A stale revision returns 409.
334
+
335
+ Mail send inputs accept `tracking: { opens: false, clicks: true }`. Each omitted setting inherits the workspace default. Use `mail.tracking.settings()` / `updateSettings()`, `message(id)` / `campaign(id)` for reports, and `domains()` / `createDomain()` / `verifyDomain()` / `updateDomain()` for branded hosts. Features must be enabled on the deployment. Opens are approximate; suspected automation is reported separately. Detailed activity expires after 90 days. Tests and OTPs never track.
336
+
337
+ ### Isolated testing, brands, migration, and spending
338
+
339
+ Use a `sspat_test_` credential with `simulation: { scenario: 'delayed' }` for a 60-second simulated delay. Other outcomes are delivered, bounced, and complained. Test resources are isolated; no real email is delivered.
340
+
341
+ ```ts
342
+ const brand = await client.mail.brands.create({ name: 'Product', editableFields: ['company'] })
343
+ const audience = await client.mail.audiences.create({ brandId: brand.id, name: 'Product news' })
344
+ ```
345
+
346
+ Every audience requires an explicit brand. Contact names/attributes are shared within that brand while consent stays per audience. `mail.automations`, `mail.forms`, and `mail.segments` expose audience-owned resources.
347
+
348
+ `mail.migration` supports public DNS audits/plans and authenticated checklists. `mail.billing.summary()` and `mail.campaigns.estimate(id)` expose allowance, credit, and blocking reasons. Pass approved maximum kobo as the third argument to `send(id, revision, approvedMaxKobo)` or the fourth to `schedule(id, sendAt, revision, approvedMaxKobo)`. Zero is a valid hard maximum. Billing is inactive until a rate card is explicitly published and activated; funding and prepaid opt-in are separate owner-only dashboard actions.
349
+
350
+ ## Native video, governed DAM and product rendering
351
+
352
+ Use the space-scoped DAM and video clients for collaborators, metadata schemas, bucket governance, reviewed publications, picker capabilities, model preparation, product rendering, galleries, version-pinned encoding, captions and playback sessions.
353
+
354
+ ```ts
355
+ const dam = sdk.assets.dam
356
+ const video = sdk.assets.video
357
+ const schema = await dam.createMetadataSchema({ name: 'Products', fields: [{
358
+ key: 'product_name', label: 'Product name', type: 'text', required: true,
359
+ }] })
360
+ const published = await dam.publishMetadataSchema(schema.id, schema.revision)
361
+ const workspace = await video.workspace(assetId)
362
+ ```
363
+
364
+ Mutations carry the supplied revision in `If-Match`. Model preparation and rendering carry an idempotency key; render submission also carries the accepted maximum units. Playback renewal and events authenticate with the session credential, not the account key. Keep these clients on your backend and return grants with `Cache-Control: private, no-store`.
365
+
366
+ See the [Assets SDK guide](https://docs.stackshift.cloud/assets/sdk-media-workflows) and its linked feature guides for complete language examples, inputs, permissions, review transitions and browser callbacks.
@@ -0,0 +1,225 @@
1
+ export type AssetAction = 'read' | 'upload' | 'edit_metadata' | 'process' | 'review' | 'publish' | 'download_original' | 'curate' | 'manage_policy' | 'manage_access';
2
+ export interface AssetSpaceAccess {
3
+ id: string;
4
+ owner_id: string;
5
+ name: string;
6
+ actions: AssetAction[];
7
+ collection_ids: string[];
8
+ }
9
+ export interface AssetCollaborator {
10
+ id: string;
11
+ asset_space_id: string;
12
+ email: string;
13
+ user_id?: string;
14
+ collection_id?: string;
15
+ actions: AssetAction[];
16
+ status: string;
17
+ revision: number;
18
+ expires_at: string;
19
+ }
20
+ export interface AssetMetadataField {
21
+ key: string;
22
+ label: string;
23
+ type: 'text' | 'integer' | 'decimal' | 'boolean' | 'date' | 'single_choice' | 'multiple_choice';
24
+ required?: boolean;
25
+ searchable?: boolean;
26
+ options?: string[];
27
+ minimum?: number;
28
+ maximum?: number;
29
+ max_length?: number;
30
+ }
31
+ export interface AssetMetadataSchema {
32
+ id: string;
33
+ name: string;
34
+ revision: number;
35
+ published_revision?: number;
36
+ fields: AssetMetadataField[];
37
+ }
38
+ export interface AssetBucketGovernance {
39
+ bucket_id: string;
40
+ revision: number;
41
+ enabled: boolean;
42
+ migrating: boolean;
43
+ schema_id?: string;
44
+ schema_revision?: number;
45
+ require_other_reviewer: boolean;
46
+ allow_ar: boolean;
47
+ channels: string[];
48
+ }
49
+ export interface AssetMediaReference {
50
+ render_set_id?: string;
51
+ render_role?: string;
52
+ spin_frame?: number;
53
+ language?: string;
54
+ label?: string;
55
+ caption_kind?: 'captions' | 'subtitles';
56
+ is_default?: boolean;
57
+ asset_id: string;
58
+ version_id: string;
59
+ rendition_id: string;
60
+ kind: 'image' | 'video' | 'model' | 'usdz' | 'caption';
61
+ role: 'media' | 'poster' | 'fallback' | 'caption' | 'usdz' | 'spin_frame';
62
+ output_checksum_sha256?: string;
63
+ policy_revision?: number;
64
+ }
65
+ export interface AssetPublicationRights {
66
+ owner: string;
67
+ attribution: string;
68
+ starts_at?: string;
69
+ expires_at?: string;
70
+ }
71
+ export type AssetPublicationStatus = 'draft' | 'in_review' | 'approved' | 'published' | 'withdrawn';
72
+ export interface AssetPublicationInput {
73
+ asset_id: string;
74
+ asset_revision: number;
75
+ channel: string;
76
+ renditions: AssetMediaReference[];
77
+ rights: AssetPublicationRights;
78
+ }
79
+ export interface AssetPublication {
80
+ id: string;
81
+ asset_id: string;
82
+ version_id: string;
83
+ channel: string;
84
+ status: AssetPublicationStatus;
85
+ revision: number;
86
+ metadata_revision: number;
87
+ metadata: Record<string, unknown>;
88
+ renditions: AssetMediaReference[];
89
+ rights: AssetPublicationRights;
90
+ reviewed_by?: string;
91
+ review_note?: string;
92
+ }
93
+ export interface AssetPublicationDelivery {
94
+ publication_id: string;
95
+ expires_at: string;
96
+ attribution: string;
97
+ ar_allowed: boolean;
98
+ renditions: Array<{
99
+ reference: AssetMediaReference;
100
+ url: string;
101
+ mp4_url?: string;
102
+ poster_url?: string;
103
+ }>;
104
+ }
105
+ export interface AssetPickerCapabilityInput {
106
+ buckets?: string[];
107
+ collections?: string[];
108
+ origins: string[];
109
+ channel: string;
110
+ result_limit?: number;
111
+ expires_in_seconds?: number;
112
+ actions?: ('search' | 'select')[];
113
+ }
114
+ export interface AssetPickerCapability {
115
+ id: string;
116
+ expires_at: string;
117
+ origins: string[];
118
+ channel: string;
119
+ result_limit: number;
120
+ }
121
+ export interface AssetModelPackage {
122
+ id: string;
123
+ asset_id: string;
124
+ version_id: string;
125
+ kind: 'glb' | 'usdz';
126
+ status: 'queued' | 'processing' | 'ready' | 'failed';
127
+ rendition_id?: string;
128
+ failure_reason?: string;
129
+ report: Record<string, unknown>;
130
+ updated_at: string;
131
+ }
132
+ export interface AssetGalleryEntryInput {
133
+ publication_id: string;
134
+ fallback_publication_id?: string;
135
+ role: 'hero' | 'detail' | 'media';
136
+ locale: string;
137
+ alt: string;
138
+ }
139
+ export interface AssetGalleryEntry extends AssetGalleryEntryInput {
140
+ asset_id: string;
141
+ version_id: string;
142
+ publication_revision: number;
143
+ fallback_revision?: number;
144
+ }
145
+ export interface AssetGallery {
146
+ id: string;
147
+ name: string;
148
+ revision: number;
149
+ published_revision?: number;
150
+ entries: AssetGalleryEntry[];
151
+ }
152
+ export interface AssetGalleryDelivery {
153
+ gallery_id: string;
154
+ name: string;
155
+ revision: number;
156
+ entries: Array<{
157
+ reference: AssetGalleryEntry;
158
+ delivery?: AssetPublicationDelivery;
159
+ fallback_delivery?: AssetPublicationDelivery;
160
+ unavailable?: boolean;
161
+ }>;
162
+ }
163
+ export interface AssetRenderRecipe {
164
+ environment: 'neutral' | 'pillars';
165
+ orbit: number;
166
+ elevation: number;
167
+ zoom: number;
168
+ exposure: number;
169
+ shadow: number;
170
+ background: string;
171
+ size: 512 | 1024;
172
+ }
173
+ export type AssetRenderOutput = 'proof' | 'poster' | 'spin' | 'turntable';
174
+ export interface AssetRenderInput {
175
+ version_id: string;
176
+ source_checksum: string;
177
+ recipe: AssetRenderRecipe;
178
+ outputs: AssetRenderOutput[];
179
+ }
180
+ export interface AssetRenderEstimate {
181
+ units: number;
182
+ remaining: number;
183
+ reused: boolean;
184
+ set_id?: string;
185
+ }
186
+ export interface AssetRenderSubmission {
187
+ set_id: string;
188
+ status: string;
189
+ job_id?: string;
190
+ units?: number;
191
+ reused?: boolean;
192
+ }
193
+ export interface AssetRenderSet {
194
+ id: string;
195
+ asset_id: string;
196
+ version_id: string;
197
+ source_checksum: string;
198
+ recipe: AssetRenderRecipe;
199
+ requested: AssetRenderOutput[];
200
+ status: 'queued' | 'processing' | 'ready' | 'failed';
201
+ can_retry: boolean;
202
+ units: number;
203
+ outputs: Array<{
204
+ role: AssetRenderOutput;
205
+ frame: number;
206
+ reference: AssetMediaReference;
207
+ }>;
208
+ created_at: string;
209
+ updated_at: string;
210
+ failure_reason?: string;
211
+ }
212
+ export interface AssetRenderingInfo {
213
+ enabled: boolean;
214
+ reason: string;
215
+ remaining: number;
216
+ qualified_outputs: AssetRenderOutput[];
217
+ source?: {
218
+ assetId: string;
219
+ versionId: string;
220
+ checksum: string;
221
+ };
222
+ delivery?: AssetPublicationDelivery;
223
+ sets: AssetRenderSet[];
224
+ deliveries: Record<string, AssetPublicationDelivery>;
225
+ }
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,96 @@
1
+ import type { StackShift } from './client.js';
2
+ import type { AssetJobSubmission } from './types.js';
3
+ import type { AssetRenderInput, AssetRenderEstimate, AssetRenderSubmission, AssetRenderingInfo } from './assets-dam-types.js';
4
+ import type { AssetAction, AssetSpaceAccess, AssetCollaborator, AssetMetadataSchema, AssetMetadataField, AssetBucketGovernance, AssetPublication, AssetPublicationInput, AssetPublicationStatus, AssetPublicationDelivery, AssetMediaReference, AssetPickerCapability, AssetPickerCapabilityInput, AssetModelPackage, AssetGallery, AssetGalleryEntryInput, AssetGalleryDelivery } from './assets-dam-types.js';
5
+ export declare class AssetDAMClient {
6
+ private readonly client;
7
+ constructor(client: StackShift);
8
+ spaces(): Promise<{
9
+ spaces: AssetSpaceAccess[];
10
+ }>;
11
+ collaborators(): Promise<{
12
+ collaborators: AssetCollaborator[];
13
+ }>;
14
+ invite(input: {
15
+ email: string;
16
+ actions: AssetAction[];
17
+ collection_id?: string;
18
+ expires_at: string;
19
+ }): Promise<AssetCollaborator>;
20
+ acceptInvitation(id: string): Promise<AssetCollaborator>;
21
+ updateCollaborator(id: string, revision: number, actions: AssetAction[]): Promise<{
22
+ saved: boolean;
23
+ }>;
24
+ revokeCollaborator(id: string, revision: number): Promise<{
25
+ saved: boolean;
26
+ }>;
27
+ metadataSchemas(): Promise<{
28
+ schemas: AssetMetadataSchema[];
29
+ }>;
30
+ metadataEditor(assetId: string): Promise<{
31
+ fields: AssetMetadataField[];
32
+ metadata: Record<string, unknown>;
33
+ revision: number;
34
+ metadata_revision: number;
35
+ can_edit: boolean;
36
+ }>;
37
+ createMetadataSchema(input: {
38
+ name: string;
39
+ fields: AssetMetadataField[];
40
+ }): Promise<AssetMetadataSchema>;
41
+ updateMetadataSchema(id: string, revision: number, input: {
42
+ name: string;
43
+ fields: AssetMetadataField[];
44
+ }): Promise<AssetMetadataSchema>;
45
+ publishMetadataSchema(id: string, revision: number): Promise<AssetMetadataSchema>;
46
+ bucketGovernance(id: string): Promise<AssetBucketGovernance>;
47
+ saveBucketGovernance(id: string, input: Omit<AssetBucketGovernance, 'bucket_id' | 'migrating'>): Promise<AssetBucketGovernance>;
48
+ migrateBucketGovernance(id: string, revision: number): Promise<AssetBucketGovernance>;
49
+ publications(options?: {
50
+ asset_id?: string;
51
+ status?: AssetPublicationStatus;
52
+ cursor?: string;
53
+ }): Promise<{
54
+ publications: AssetPublication[];
55
+ next_cursor: string;
56
+ }>;
57
+ publicationRenditions(assetId: string): Promise<{
58
+ renditions: AssetMediaReference[];
59
+ }>;
60
+ createPublication(input: AssetPublicationInput): Promise<AssetPublication>;
61
+ updatePublication(id: string, revision: number, input: AssetPublicationInput): Promise<AssetPublication>;
62
+ transitionPublication(id: string, revision: number, action: 'submit' | 'approve' | 'request-changes' | 'publish' | 'withdraw', note?: string): Promise<AssetPublication>;
63
+ resolvePublication(id: string, preview?: boolean): Promise<AssetPublicationDelivery>;
64
+ resolvePublicationAR(id: string): Promise<AssetPublicationDelivery>;
65
+ createPickerCapability(input: AssetPickerCapabilityInput): Promise<{
66
+ token: string;
67
+ capability: AssetPickerCapability;
68
+ }>;
69
+ revokePickerCapability(id: string): Promise<{
70
+ revoked: boolean;
71
+ }>;
72
+ models(assetId: string): Promise<{
73
+ packages: AssetModelPackage[];
74
+ pilot_enabled: boolean;
75
+ daily_jobs: number;
76
+ rendering: AssetRenderingInfo;
77
+ }>;
78
+ estimateRender(assetId: string, revision: number, input: AssetRenderInput): Promise<AssetRenderEstimate>;
79
+ renderProduct(assetId: string, revision: number, idempotencyKey: string, input: AssetRenderInput, maximumUnits: number): Promise<AssetRenderSubmission>;
80
+ processModel(assetId: string, revision: number, idempotencyKey: string): Promise<AssetJobSubmission>;
81
+ galleries(cursor?: string): Promise<{
82
+ galleries: AssetGallery[];
83
+ next_cursor: string;
84
+ }>;
85
+ createGallery(input: {
86
+ name: string;
87
+ entries: AssetGalleryEntryInput[];
88
+ }): Promise<AssetGallery>;
89
+ updateGallery(id: string, revision: number, input: {
90
+ name: string;
91
+ entries: AssetGalleryEntryInput[];
92
+ }): Promise<AssetGallery>;
93
+ transitionGallery(id: string, revision: number, action: 'publish' | 'withdraw'): Promise<AssetGallery>;
94
+ resolveGallery(id: string, preview?: boolean): Promise<AssetGalleryDelivery>;
95
+ resolveGalleryAR(id: string, publicationId: string): Promise<AssetPublicationDelivery>;
96
+ }
@@ -0,0 +1,47 @@
1
+ const path = (group, id) => `/assets/${group}/${encodeURIComponent(id)}`;
2
+ const revisionHeaders = (revision) => ({ 'If-Match': `"${revision}"` });
3
+ export class AssetDAMClient {
4
+ client;
5
+ constructor(client) {
6
+ this.client = client;
7
+ }
8
+ spaces() { return this.client.request('/assets/spaces'); }
9
+ collaborators() { return this.client.request('/assets/collaborators'); }
10
+ invite(input) { return this.client.request('/assets/collaborators', { method: 'POST', body: input }); }
11
+ acceptInvitation(id) { return this.client.request(`${path('invitations', id)}/accept`, { method: 'POST' }); }
12
+ updateCollaborator(id, revision, actions) { return this.client.request(path('collaborators', id), { method: 'PUT', headers: revisionHeaders(revision), body: { actions } }); }
13
+ revokeCollaborator(id, revision) { return this.client.request(path('collaborators', id), { method: 'DELETE', headers: revisionHeaders(revision) }); }
14
+ metadataSchemas() { return this.client.request('/assets/metadata-schemas'); }
15
+ metadataEditor(assetId) { return this.client.request(`/assets/${encodeURIComponent(assetId)}/metadata-editor`); }
16
+ createMetadataSchema(input) { return this.client.request('/assets/metadata-schemas', { method: 'POST', body: input }); }
17
+ updateMetadataSchema(id, revision, input) { return this.client.request(path('metadata-schemas', id), { method: 'PUT', headers: revisionHeaders(revision), body: input }); }
18
+ publishMetadataSchema(id, revision) { return this.client.request(`${path('metadata-schemas', id)}/publish`, { method: 'POST', headers: revisionHeaders(revision) }); }
19
+ bucketGovernance(id) { return this.client.request(`${path('buckets', id)}/governance`); }
20
+ saveBucketGovernance(id, input) { return this.client.request(`${path('buckets', id)}/governance`, { method: 'PUT', body: input }); }
21
+ migrateBucketGovernance(id, revision) { return this.client.request(`${path('buckets', id)}/governance/migrate`, { method: 'POST', headers: revisionHeaders(revision) }); }
22
+ publications(options = {}) {
23
+ const query = new URLSearchParams();
24
+ for (const [key, value] of Object.entries(options))
25
+ if (value)
26
+ query.set(key, value);
27
+ return this.client.request(`/assets/publications?${query}`);
28
+ }
29
+ publicationRenditions(assetId) { return this.client.request(`/assets/${encodeURIComponent(assetId)}/publication-renditions`); }
30
+ createPublication(input) { return this.client.request('/assets/publications', { method: 'POST', body: input }); }
31
+ updatePublication(id, revision, input) { return this.client.request(path('publications', id), { method: 'PUT', headers: revisionHeaders(revision), body: input }); }
32
+ transitionPublication(id, revision, action, note = '') { return this.client.request(`${path('publications', id)}/${action}`, { method: 'POST', headers: revisionHeaders(revision), body: { note } }); }
33
+ resolvePublication(id, preview = false) { return this.client.request(`${path('publications', id)}/${preview ? 'preview' : 'resolve'}`); }
34
+ resolvePublicationAR(id) { return this.client.request(`${path('publications', id)}/ar`, { method: 'POST' }); }
35
+ createPickerCapability(input) { return this.client.request('/assets/picker-capabilities', { method: 'POST', body: input }); }
36
+ revokePickerCapability(id) { return this.client.request(path('picker-capabilities', id), { method: 'DELETE' }); }
37
+ models(assetId) { return this.client.request(`/assets/${encodeURIComponent(assetId)}/models`); }
38
+ estimateRender(assetId, revision, input) { return this.client.request(`/assets/${encodeURIComponent(assetId)}/models`, { method: 'POST', headers: revisionHeaders(revision), body: { ...input, operation: 'estimate' } }); }
39
+ renderProduct(assetId, revision, idempotencyKey, input, maximumUnits) { return this.client.request(`/assets/${encodeURIComponent(assetId)}/models`, { method: 'POST', headers: { ...revisionHeaders(revision), 'Idempotency-Key': idempotencyKey }, body: { ...input, operation: 'render', maximum_units: maximumUnits } }); }
40
+ processModel(assetId, revision, idempotencyKey) { return this.client.request(`/assets/${encodeURIComponent(assetId)}/models`, { method: 'POST', headers: { ...revisionHeaders(revision), 'Idempotency-Key': idempotencyKey } }); }
41
+ galleries(cursor) { return this.client.request(`/assets/galleries${cursor ? '?cursor=' + encodeURIComponent(cursor) : ''}`); }
42
+ createGallery(input) { return this.client.request('/assets/galleries', { method: 'POST', body: input }); }
43
+ updateGallery(id, revision, input) { return this.client.request(path('galleries', id), { method: 'PUT', headers: revisionHeaders(revision), body: input }); }
44
+ transitionGallery(id, revision, action) { return this.client.request(`${path('galleries', id)}/${action}`, { method: 'POST', headers: revisionHeaders(revision) }); }
45
+ resolveGallery(id, preview = false) { return this.client.request(`${path('galleries', id)}/resolve${preview ? '?preview=true' : ''}`); }
46
+ resolveGalleryAR(id, publicationId) { return this.client.request(`${path('galleries', id)}/ar`, { method: 'POST', body: { publication_id: publicationId } }); }
47
+ }
@@ -0,0 +1,116 @@
1
+ export interface AssetVideoPackage {
2
+ id: string;
3
+ asset_space_id: string;
4
+ asset_id: string;
5
+ version_id: string;
6
+ source_checksum_sha256: string;
7
+ recipe_hash: string;
8
+ recipe: string;
9
+ processor_revision: string;
10
+ status: 'queued' | 'processing' | 'ready' | 'degraded' | 'failed' | 'cancelled';
11
+ phase: string;
12
+ progress_percent: number;
13
+ job_id?: string;
14
+ published_attempt?: string;
15
+ admitted_at?: string;
16
+ created_at: string;
17
+ updated_at: string;
18
+ failure_code: string;
19
+ metadata: {
20
+ asset_id: string;
21
+ duration_seconds: number;
22
+ width: number;
23
+ height: number;
24
+ codec: string;
25
+ bitrate: number;
26
+ frame_rate: number;
27
+ has_audio: boolean;
28
+ rotation: number;
29
+ created_at: string;
30
+ updated_at: string;
31
+ };
32
+ }
33
+ export interface AssetVideoWorkspace {
34
+ active?: AssetVideoPackage;
35
+ pending?: AssetVideoPackage;
36
+ source?: {
37
+ version_id: string;
38
+ scan_status: 'pending' | 'clean' | 'infected' | 'failed';
39
+ review_status: 'not_required' | 'pending' | 'approved' | 'rejected';
40
+ review_reason: string;
41
+ };
42
+ renditions: Array<{
43
+ id: string;
44
+ package_id?: string;
45
+ asset_id: string;
46
+ source_checksum_sha256: string;
47
+ kind: 'hls' | 'mp4' | 'poster';
48
+ profile: string;
49
+ width: number;
50
+ height: number;
51
+ size: number;
52
+ mime_type: string;
53
+ status: string;
54
+ created_at: string;
55
+ updated_at: string;
56
+ }>;
57
+ admission_enabled: boolean;
58
+ }
59
+ export interface AssetVideoCaptionInput {
60
+ /** Atomically replace this active track; the new reference receives a new ID. */
61
+ replace_caption_id?: string;
62
+ caption_asset_id: string;
63
+ caption_version_id: string;
64
+ language: string;
65
+ label: string;
66
+ kind: 'captions' | 'subtitles';
67
+ is_default?: boolean;
68
+ }
69
+ export interface AssetVideoCaption extends AssetVideoCaptionInput {
70
+ id: string;
71
+ asset_space_id: string;
72
+ asset_id: string;
73
+ version_id: string;
74
+ is_default: boolean;
75
+ }
76
+ export interface AssetPlaybackGrant {
77
+ has_audio: boolean;
78
+ session: {
79
+ id: string;
80
+ asset_space_id: string;
81
+ asset_id: string;
82
+ package_id: string;
83
+ version_id: string;
84
+ owner_id?: string;
85
+ is_private: boolean;
86
+ expires_at: string;
87
+ maximum_expires_at: string;
88
+ revoked_at?: string;
89
+ created_at: string;
90
+ };
91
+ credential: string;
92
+ hls: string;
93
+ mp4: string;
94
+ poster?: string;
95
+ captions: Array<{
96
+ id: string;
97
+ url: string;
98
+ language: string;
99
+ label: string;
100
+ kind: 'captions' | 'subtitles';
101
+ is_default: boolean;
102
+ }>;
103
+ }
104
+ export interface AssetPlaybackEvent {
105
+ sequence: number;
106
+ kind: 'startup' | 'rebuffer' | 'error' | 'quality' | 'watched' | 'completed';
107
+ value: number;
108
+ }
109
+ export interface AssetPlaybackAnalytics {
110
+ starts: number;
111
+ completions: number;
112
+ errors: number;
113
+ startup_ms: number;
114
+ rebuffer_ms: number;
115
+ watched_ms: number;
116
+ }
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,25 @@
1
+ import type { StackShift } from './client.js';
2
+ import type { AssetVideoWorkspace, AssetVideoPackage, AssetVideoCaption, AssetVideoCaptionInput, AssetPlaybackGrant, AssetPlaybackEvent, AssetPlaybackAnalytics } from './assets-video-types.js';
3
+ export declare class AssetVideoClient {
4
+ private readonly client;
5
+ constructor(client: StackShift);
6
+ workspace(assetId: string): Promise<AssetVideoWorkspace>;
7
+ process(assetId: string, versionId: string): Promise<AssetVideoPackage>;
8
+ createSession(assetId: string): Promise<AssetPlaybackGrant>;
9
+ renewSession(credential: string): Promise<AssetPlaybackGrant>;
10
+ revokeSession(assetId: string, sessionId: string): Promise<{
11
+ revoked: boolean;
12
+ }>;
13
+ captions(assetId: string, versionId: string): Promise<AssetVideoCaption[]>;
14
+ addCaption(assetId: string, versionId: string, input: AssetVideoCaptionInput): Promise<AssetVideoCaption>;
15
+ removeCaption(assetId: string, versionId: string, captionId: string): Promise<{
16
+ removed: boolean;
17
+ }>;
18
+ review(assetId: string, versionId: string, decision: 'approved' | 'rejected', reason: string): Promise<{
19
+ reviewed: boolean;
20
+ }>;
21
+ events(credential: string, events: AssetPlaybackEvent[]): Promise<{
22
+ accepted: boolean;
23
+ }>;
24
+ analytics(assetId: string): Promise<AssetPlaybackAnalytics>;
25
+ }
@@ -0,0 +1,19 @@
1
+ const assetPath = (id) => `/assets/${encodeURIComponent(id)}`;
2
+ const versionPath = (id, version) => `${assetPath(id)}/versions/${encodeURIComponent(version)}/video`;
3
+ export class AssetVideoClient {
4
+ client;
5
+ constructor(client) {
6
+ this.client = client;
7
+ }
8
+ workspace(assetId) { return this.client.request(`${assetPath(assetId)}/video`); }
9
+ process(assetId, versionId) { return this.client.request(versionPath(assetId, versionId), { method: 'POST' }); }
10
+ createSession(assetId) { return this.client.request(`${assetPath(assetId)}/playback-sessions`, { method: 'POST' }); }
11
+ renewSession(credential) { return this.client.playbackRequest('/sessions/renew', credential, {}); }
12
+ revokeSession(assetId, sessionId) { return this.client.request(`${assetPath(assetId)}/playback-sessions/${encodeURIComponent(sessionId)}`, { method: 'DELETE' }); }
13
+ captions(assetId, versionId) { return this.client.request(`${versionPath(assetId, versionId)}/captions`); }
14
+ addCaption(assetId, versionId, input) { return this.client.request(`${versionPath(assetId, versionId)}/captions`, { method: 'POST', body: input }); }
15
+ removeCaption(assetId, versionId, captionId) { return this.client.request(`${versionPath(assetId, versionId)}/captions/${encodeURIComponent(captionId)}`, { method: 'DELETE' }); }
16
+ review(assetId, versionId, decision, reason) { return this.client.request(`${versionPath(assetId, versionId)}/review`, { method: 'POST', body: { decision, reason } }); }
17
+ events(credential, events) { return this.client.playbackRequest('/events', credential, { events }); }
18
+ analytics(assetId) { return this.client.request(`${assetPath(assetId)}/video/analytics`); }
19
+ }
package/dist/assets.d.ts CHANGED
@@ -1,3 +1,5 @@
1
+ import { AssetDAMClient } from './assets-dam.js';
2
+ import { AssetVideoClient } from './assets-video.js';
1
3
  import type { StackShift } from './client.js';
2
4
  import { AssetConnectionsClient, AssetMigrationsClient, AssetStorageClient, AssetTextClient, AssetUploadCapabilitiesClient } from './assets-platform.js';
3
5
  import { AssetWorkflowsClient } from './asset-workflows.js';
@@ -9,6 +11,8 @@ export declare function assetTransformOptions(preset: AssetTransformPreset): Ass
9
11
  export declare function assetTransformSpec(options: AssetTransformOptions): string;
10
12
  export declare class AssetsClient {
11
13
  private readonly client;
14
+ readonly dam: AssetDAMClient;
15
+ readonly video: AssetVideoClient;
12
16
  readonly connections: AssetConnectionsClient;
13
17
  readonly storage: AssetStorageClient;
14
18
  readonly migrations: AssetMigrationsClient;
@@ -79,7 +83,7 @@ export declare class AssetsClient {
79
83
  description?: string;
80
84
  asset_ids?: string[];
81
85
  }): Promise<AssetCollection>;
82
- updateCollection(collectionId: string, input: {
86
+ updateCollection(collectionId: string, revision: number, input: {
83
87
  name: string;
84
88
  description?: string;
85
89
  asset_ids?: string[];