@stackshift-cloud/sdk 0.1.4 → 1.1.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 (39) hide show
  1. package/README.md +63 -3
  2. package/dist/asset-media-v2.d.ts +65 -0
  3. package/dist/asset-workflows.d.ts +269 -0
  4. package/dist/asset-workflows.js +69 -0
  5. package/dist/assets-platform-types.d.ts +218 -0
  6. package/dist/assets-platform-types.js +1 -0
  7. package/dist/assets-platform.d.ts +55 -0
  8. package/dist/assets-platform.js +90 -0
  9. package/dist/assets.d.ts +16 -0
  10. package/dist/assets.js +74 -130
  11. package/dist/client.d.ts +6 -0
  12. package/dist/client.js +15 -6
  13. package/dist/generated/assets-contract.d.ts +267 -2
  14. package/dist/generated/assets-contract.js +53 -0
  15. package/dist/index.d.ts +17 -5
  16. package/dist/index.js +5 -1
  17. package/dist/mail-advanced-types.d.ts +25 -3
  18. package/dist/mail-advanced.d.ts +8 -1
  19. package/dist/mail-advanced.js +9 -0
  20. package/dist/mail-campaigns.d.ts +76 -0
  21. package/dist/mail-campaigns.js +42 -0
  22. package/dist/mail-delivery-types.js +1 -0
  23. package/dist/mail-diagnostics.d.ts +23 -0
  24. package/dist/mail-diagnostics.js +1 -0
  25. package/dist/mail-events-webhooks.d.ts +3 -2
  26. package/dist/mail-events-webhooks.js +10 -2
  27. package/dist/mail-exports.d.ts +32 -0
  28. package/dist/mail-exports.js +18 -0
  29. package/dist/mail-streams.d.ts +27 -0
  30. package/dist/mail-streams.js +12 -0
  31. package/dist/mail-webhook-types.d.ts +12 -1
  32. package/dist/mail.d.ts +14 -2
  33. package/dist/mail.js +22 -2
  34. package/dist/types.d.ts +56 -3
  35. package/dist/upload-controller.d.ts +70 -0
  36. package/dist/upload-controller.js +223 -0
  37. package/package.json +2 -2
  38. /package/dist/{mail-phase4-types.js → asset-media-v2.js} +0 -0
  39. /package/dist/{mail-phase4-types.d.ts → mail-delivery-types.d.ts} +0 -0
package/README.md CHANGED
@@ -44,16 +44,16 @@ const message = await stackshift.mail.send({
44
44
  console.log(message.id, message.status, message.idempotencyStatus)
45
45
  ```
46
46
 
47
- Inspect sent messages:
47
+ Inspect MTA-accepted messages:
48
48
 
49
49
  ```ts
50
- const messages = await stackshift.mail.messages.list({ status: 'sent', limit: 20 })
50
+ const messages = await stackshift.mail.messages.list({ status: 'mta_accepted', limit: 20 })
51
51
  const detail = await stackshift.mail.messages.get(messages.data[0].id)
52
52
  const attempts = await stackshift.mail.messages.attempts(detail.id)
53
53
  const logs = await stackshift.mail.messages.logs(detail.id)
54
54
  ```
55
55
 
56
- In this MVP, `sent` means the message was accepted by StackShift's outbound MTA. It does not mean inbox delivery, opens, clicks, or spam placement. A `sent` message can later become `bounced` if StackShift receives a delivery-status notification.
56
+ `mta_accepted` means StackShift's outbound MTA accepted the message. `delivered` means the recipient MX accepted a recipient; it does not claim inbox placement or human receipt. Recipient records remain authoritative for mixed outcomes.
57
57
 
58
58
  ## Send a template
59
59
 
@@ -218,6 +218,66 @@ export class AssetsService {
218
218
  }
219
219
  ```
220
220
 
221
+ ## Storage connections and migrations
222
+
223
+ Use AWS AssumeRole for S3 whenever possible. The returned `external_id` belongs in the role trust policy; credentials are write-only and are never returned by Stackshift.
224
+
225
+ ```ts
226
+ const connection = await stackshift.assets.connections.create({
227
+ provider: 'aws_s3',
228
+ name: 'Production media',
229
+ configuration: {
230
+ bucket: 'acme-media',
231
+ region: 'us-east-1',
232
+ role_arn: 'arn:aws:iam::123456789012:role/StackshiftAssets',
233
+ auth_type: 'assume_role',
234
+ },
235
+ })
236
+
237
+ await stackshift.assets.connections.verify(connection.id)
238
+
239
+ const dryRun = await stackshift.assets.migrations.start({
240
+ source_connection_id: connection.id,
241
+ destination_bucket_id: 'assets_bucket_id',
242
+ source_prefix: 'legacy',
243
+ conflict_policy: 'skip',
244
+ dry_run: true,
245
+ })
246
+
247
+ const report = await stackshift.assets.migrations.downloadReport(dryRun.id, 'csv')
248
+ ```
249
+
250
+ Native Stackshift S2 storage uses a bucket reference and internal authorization, never copied S2 access keys:
251
+
252
+ ```ts
253
+ const s2 = await stackshift.assets.storage.createS2Bucket({ name: 'asset-originals', region: 'us-east-1' })
254
+ await stackshift.assets.storage.configure('assets_bucket_id', 3, {
255
+ storage_mode: 'stackshift_s2',
256
+ s2_bucket_id: s2.id,
257
+ object_prefix: 'originals',
258
+ derivative_prefix: 'derived',
259
+ auto_extract_text: true,
260
+ })
261
+ ```
262
+
263
+ ## OCR and browser upload capabilities
264
+
265
+ ```ts
266
+ const extraction = await stackshift.assets.text.start('asset_id', { language: 'eng' })
267
+ const current = await stackshift.assets.text.get('asset_id')
268
+
269
+ const capability = await stackshift.assets.uploadCapabilities.create({
270
+ bucket: 'uploads',
271
+ key_prefix: 'customers/user_123',
272
+ allowed_mime_types: ['image/png', 'image/jpeg'],
273
+ allowed_origins: ['https://app.example.com'],
274
+ max_bytes: 25 * 1024 * 1024,
275
+ expires_in: '15m',
276
+ })
277
+ ```
278
+
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.
280
+
221
281
  For larger uploads, create a signed upload URL on your NestJS server and let the browser upload directly.
222
282
 
223
283
  ## Direct browser uploads
@@ -0,0 +1,65 @@
1
+ export type AssetMediaKind = 'image' | 'video';
2
+ export type AssetTransformOutputKind = 'image' | 'video' | 'audio' | 'thumbnail';
3
+ export type AssetAnimationPolicy = 'first' | 'preserve' | 'reject';
4
+ export interface AssetTransformOperation {
5
+ type: 'crop' | 'resize' | 'rotate' | 'blur' | 'radius' | 'dpr' | 'background' | 'overlay' | 'trim' | 'fps' | 'timestamp';
6
+ mode?: 'explicit' | 'fit' | 'fill' | 'pad';
7
+ gravity?: 'northwest' | 'north' | 'northeast' | 'west' | 'centre' | 'east' | 'southwest' | 'south' | 'southeast';
8
+ width?: number;
9
+ height?: number;
10
+ x?: number;
11
+ y?: number;
12
+ degrees?: number;
13
+ sigma?: number;
14
+ radius?: number;
15
+ dpr?: number;
16
+ color?: string;
17
+ asset_id?: string;
18
+ opacity?: number;
19
+ start_seconds?: number;
20
+ end_seconds?: number;
21
+ fps?: number;
22
+ timestamp_seconds?: number;
23
+ }
24
+ export interface AssetTransformDefinition {
25
+ version: 2;
26
+ media_kind: AssetMediaKind;
27
+ animation?: AssetAnimationPolicy;
28
+ operations: AssetTransformOperation[];
29
+ output: {
30
+ kind: AssetTransformOutputKind;
31
+ format: 'jpeg' | 'png' | 'webp' | 'avif' | 'mp4' | 'mp3' | 'aac' | 'wav';
32
+ quality?: number;
33
+ };
34
+ }
35
+ export type AssetTransformMaterializeInput = {
36
+ definition: AssetTransformDefinition;
37
+ preset?: never;
38
+ } | {
39
+ preset: string;
40
+ definition?: never;
41
+ };
42
+ export interface AssetDerivedAsset {
43
+ id: string;
44
+ asset_id: string;
45
+ source_checksum_sha256: string;
46
+ transform_hash: string;
47
+ normalized_spec: string;
48
+ definition_version: number;
49
+ output_kind: AssetTransformOutputKind;
50
+ dependency_checksum_sha256?: string;
51
+ processor_revision: string;
52
+ mime_type: string;
53
+ size: number;
54
+ status: string;
55
+ created_at: string;
56
+ updated_at: string;
57
+ last_accessed_at?: string;
58
+ }
59
+ export interface AssetImageGenerationInput {
60
+ prompt: string;
61
+ size: string;
62
+ format: 'png' | 'jpeg' | 'webp';
63
+ bucket: string;
64
+ key?: string;
65
+ }
@@ -0,0 +1,269 @@
1
+ import type { StackShift } from './client.js';
2
+ export interface AssetWorkflowDefinition {
3
+ version: 1;
4
+ nodes: AssetWorkflowNode[];
5
+ edges: AssetWorkflowEdge[];
6
+ }
7
+ export interface AssetWorkflowNode {
8
+ id: string;
9
+ type: string;
10
+ action?: string;
11
+ action_version?: string;
12
+ config?: Record<string, unknown>;
13
+ retry?: {
14
+ max_attempts?: number;
15
+ backoff_seconds?: number;
16
+ };
17
+ timeout_seconds?: number;
18
+ failure_policy?: string;
19
+ }
20
+ export interface AssetWorkflowEdge {
21
+ id: string;
22
+ source: string;
23
+ source_port?: string;
24
+ target: string;
25
+ target_port?: string;
26
+ }
27
+ export interface AssetWorkflowLayout {
28
+ nodes: Array<{
29
+ id: string;
30
+ x: number;
31
+ y: number;
32
+ width?: number;
33
+ height?: number;
34
+ }>;
35
+ viewport: {
36
+ x: number;
37
+ y: number;
38
+ zoom: number;
39
+ };
40
+ groups?: Array<{
41
+ id: string;
42
+ label: string;
43
+ node_ids: string[];
44
+ }>;
45
+ }
46
+ export interface AssetWorkflow {
47
+ id: string;
48
+ name: string;
49
+ description?: string;
50
+ status: 'draft' | 'active' | 'disabled';
51
+ revision: number;
52
+ execution_principal_id: string;
53
+ draft_definition: AssetWorkflowDefinition;
54
+ draft_layout: AssetWorkflowLayout;
55
+ current_version_id?: string;
56
+ active_version_id?: string;
57
+ created_at: string;
58
+ updated_at: string;
59
+ }
60
+ export interface AssetWorkflowVersion {
61
+ id: string;
62
+ workflow_id: string;
63
+ version: number;
64
+ semantic_digest: string;
65
+ definition: AssetWorkflowDefinition;
66
+ layout: AssetWorkflowLayout;
67
+ created_by: string;
68
+ created_at: string;
69
+ }
70
+ export interface AssetWorkflowRun {
71
+ id: string;
72
+ workflow_id: string;
73
+ version_id: string;
74
+ durable_run_id?: string;
75
+ trigger_type: string;
76
+ trigger_key?: string;
77
+ status: 'queued' | 'running' | 'waiting' | 'completed' | 'completed_with_warning' | 'failed' | 'canceled';
78
+ input: unknown;
79
+ output?: unknown;
80
+ error?: unknown;
81
+ started_at?: string;
82
+ completed_at?: string;
83
+ created_at: string;
84
+ updated_at: string;
85
+ }
86
+ export interface AssetWorkflowNodeExecution {
87
+ id: string;
88
+ run_id: string;
89
+ node_id: string;
90
+ node_type: string;
91
+ status: string;
92
+ attempt: number;
93
+ input?: unknown;
94
+ output?: unknown;
95
+ error?: unknown;
96
+ selected_ports: string[];
97
+ wait_event?: string;
98
+ wait_correlation?: string;
99
+ wait_until?: string;
100
+ started_at?: string;
101
+ completed_at?: string;
102
+ stackie_activity?: Array<Record<string, unknown>>;
103
+ }
104
+ export interface AssetWorkflowValidation {
105
+ valid: boolean;
106
+ semantic_digest?: string;
107
+ definition: AssetWorkflowDefinition;
108
+ issues: Array<{
109
+ code: string;
110
+ message: string;
111
+ node_id?: string;
112
+ edge_id?: string;
113
+ }>;
114
+ }
115
+ export interface AssetWorkflowNodeDefinition {
116
+ type: string;
117
+ version: string;
118
+ name: string;
119
+ category: string;
120
+ description: string;
121
+ input_ports: Array<{
122
+ name: string;
123
+ data_type: string;
124
+ required?: boolean;
125
+ }>;
126
+ output_ports: Array<{
127
+ name: string;
128
+ data_type: string;
129
+ required?: boolean;
130
+ }>;
131
+ config_schema: Record<string, unknown>;
132
+ risk: 'read' | 'reversible' | 'costly' | 'production' | 'external';
133
+ requires_approval: boolean;
134
+ approval_mode: 'none' | 'version' | 'per_run';
135
+ }
136
+ export interface AssetWorkflowTemplate {
137
+ key: string;
138
+ name: string;
139
+ description: string;
140
+ definition: AssetWorkflowDefinition;
141
+ layout: AssetWorkflowLayout;
142
+ valid: boolean;
143
+ issues: AssetWorkflowValidation['issues'];
144
+ }
145
+ export interface AssetWorkflowApproval {
146
+ id: string;
147
+ workflow_id: string;
148
+ version_id: string;
149
+ run_id?: string;
150
+ node_id?: string;
151
+ approval_mode: 'version' | 'per_run';
152
+ semantic_digest: string;
153
+ status: 'pending' | 'approved' | 'rejected';
154
+ risk_summary: unknown;
155
+ constraints: unknown;
156
+ requested_by: string;
157
+ decided_by?: string;
158
+ decision_reason?: string;
159
+ expires_at?: string;
160
+ created_at: string;
161
+ updated_at: string;
162
+ }
163
+ export interface AssetWorkflowHTTPConnection {
164
+ id?: string;
165
+ name: string;
166
+ host: string;
167
+ allowed_path_prefixes: string[];
168
+ credential_reference?: string;
169
+ credential?: AssetWorkflowHTTPCredentialInput;
170
+ default_headers: Record<string, string>;
171
+ revision?: number;
172
+ created_at?: string;
173
+ updated_at?: string;
174
+ }
175
+ export interface AssetWorkflowHTTPCredentialInput {
176
+ name: string;
177
+ header: string;
178
+ prefix?: string;
179
+ value: string;
180
+ }
181
+ export interface AssetAutomationOverview {
182
+ mcp_endpoint: '/api/v1/assets/mcp';
183
+ auth_method: 'pat';
184
+ tools: Array<{
185
+ name: string;
186
+ description: string;
187
+ required_scope: string;
188
+ required_scopes?: string[];
189
+ risk: string;
190
+ }>;
191
+ recent_executions: Array<{
192
+ id: string;
193
+ tool: string;
194
+ transport: string;
195
+ status: string;
196
+ created_at: string;
197
+ }>;
198
+ }
199
+ export declare class AssetWorkflowsClient {
200
+ private readonly client;
201
+ constructor(client: StackShift);
202
+ catalog(): Promise<{
203
+ nodes: AssetWorkflowNodeDefinition[];
204
+ templates: AssetWorkflowTemplate[];
205
+ }>;
206
+ create(input: {
207
+ name: string;
208
+ description?: string;
209
+ template_key?: string;
210
+ definition?: AssetWorkflowDefinition;
211
+ layout?: AssetWorkflowLayout;
212
+ }): Promise<AssetWorkflow>;
213
+ list(page?: number, perPage?: number): Promise<AssetWorkflow[]>;
214
+ get(workflowId: string): Promise<AssetWorkflow>;
215
+ updateDraft(workflowId: string, input: {
216
+ name: string;
217
+ description?: string;
218
+ definition: AssetWorkflowDefinition;
219
+ layout: AssetWorkflowLayout;
220
+ expected_revision: number;
221
+ }): Promise<AssetWorkflow>;
222
+ validate(workflowId: string): Promise<AssetWorkflowValidation>;
223
+ publish(workflowId: string, expectedRevision: number): Promise<AssetWorkflowVersion>;
224
+ activate(workflowId: string, versionId: string, expectedRevision: number): Promise<void>;
225
+ versions(workflowId: string): Promise<AssetWorkflowVersion[]>;
226
+ run(workflowId: string, input?: {
227
+ version_id?: string;
228
+ input?: unknown;
229
+ idempotency_key?: string;
230
+ }): Promise<AssetWorkflowRun>;
231
+ runs(workflowId: string, page?: number, perPage?: number): Promise<AssetWorkflowRun[]>;
232
+ runDetail(runId: string): Promise<{
233
+ run: AssetWorkflowRun;
234
+ nodes: AssetWorkflowNodeExecution[];
235
+ }>;
236
+ cancelRun(runId: string): Promise<AssetWorkflowRun>;
237
+ retryRun(runId: string): Promise<AssetWorkflowRun>;
238
+ approvals(status?: AssetWorkflowApproval['status']): Promise<AssetWorkflowApproval[]>;
239
+ decideApproval(approvalId: string, approved: boolean, input?: {
240
+ reason?: string;
241
+ expires_at?: string;
242
+ }): Promise<AssetWorkflowApproval>;
243
+ approve(approvalId: string, input?: {
244
+ reason?: string;
245
+ expires_at?: string;
246
+ }): Promise<AssetWorkflowApproval>;
247
+ reject(approvalId: string, input?: {
248
+ reason?: string;
249
+ }): Promise<AssetWorkflowApproval>;
250
+ connections(): Promise<AssetWorkflowHTTPConnection[]>;
251
+ createConnection(input: AssetWorkflowHTTPConnection): Promise<AssetWorkflowHTTPConnection>;
252
+ rotateConnectionCredential(connectionId: string, input: AssetWorkflowHTTPCredentialInput): Promise<{
253
+ id: string;
254
+ name: string;
255
+ header: string;
256
+ prefix?: string;
257
+ revision: number;
258
+ }>;
259
+ rotateInboundHook(workflowId: string): Promise<{
260
+ hook: {
261
+ id: string;
262
+ workflow_id: string;
263
+ secret_version: number;
264
+ enabled: boolean;
265
+ };
266
+ token: string;
267
+ secret: string;
268
+ }>;
269
+ }
@@ -0,0 +1,69 @@
1
+ export class AssetWorkflowsClient {
2
+ client;
3
+ constructor(client) {
4
+ this.client = client;
5
+ }
6
+ catalog() {
7
+ return this.client.request('/assets/workflows/catalog');
8
+ }
9
+ create(input) {
10
+ return this.client.request('/assets/workflows', { method: 'POST', body: input });
11
+ }
12
+ list(page = 1, perPage = 20) {
13
+ return this.client.request(`/assets/workflows?page=${page}&per_page=${perPage}`);
14
+ }
15
+ get(workflowId) { return this.client.request(`/assets/workflows/${encodeURIComponent(workflowId)}`); }
16
+ updateDraft(workflowId, input) {
17
+ return this.client.request(`/assets/workflows/${encodeURIComponent(workflowId)}/draft`, { method: 'PUT', body: input });
18
+ }
19
+ validate(workflowId) {
20
+ return this.client.request(`/assets/workflows/${encodeURIComponent(workflowId)}/validate`, { method: 'POST' });
21
+ }
22
+ publish(workflowId, expectedRevision) {
23
+ return this.client.request(`/assets/workflows/${encodeURIComponent(workflowId)}/publish`, { method: 'POST', body: { expected_revision: expectedRevision } });
24
+ }
25
+ activate(workflowId, versionId, expectedRevision) {
26
+ return this.client.request(`/assets/workflows/${encodeURIComponent(workflowId)}/activate`, { method: 'POST', body: { version_id: versionId, expected_revision: expectedRevision } });
27
+ }
28
+ versions(workflowId) { return this.client.request(`/assets/workflows/${encodeURIComponent(workflowId)}/versions`); }
29
+ run(workflowId, input = {}) {
30
+ return this.client.request(`/assets/workflows/${encodeURIComponent(workflowId)}/run`, {
31
+ method: 'POST', body: input,
32
+ headers: input.idempotency_key ? { 'Idempotency-Key': input.idempotency_key } : undefined,
33
+ });
34
+ }
35
+ runs(workflowId, page = 1, perPage = 20) {
36
+ return this.client.request(`/assets/workflows/${encodeURIComponent(workflowId)}/runs?page=${page}&per_page=${perPage}`);
37
+ }
38
+ runDetail(runId) {
39
+ return this.client.request(`/assets/workflows/runs/${encodeURIComponent(runId)}`);
40
+ }
41
+ cancelRun(runId) {
42
+ return this.client.request(`/assets/workflows/runs/${encodeURIComponent(runId)}/cancel`, { method: 'POST' });
43
+ }
44
+ retryRun(runId) {
45
+ return this.client.request(`/assets/workflows/runs/${encodeURIComponent(runId)}/retry`, { method: 'POST' });
46
+ }
47
+ approvals(status) {
48
+ if (status)
49
+ return this.client.request(`/assets/workflows/approvals?status=${encodeURIComponent(status)}`);
50
+ return this.client.request('/assets/workflows/approvals');
51
+ }
52
+ decideApproval(approvalId, approved, input = {}) {
53
+ return approved ? this.approve(approvalId, input) : this.reject(approvalId, input);
54
+ }
55
+ approve(approvalId, input = {}) {
56
+ return this.client.request(`/assets/workflows/approvals/${encodeURIComponent(approvalId)}/approve`, { method: 'POST', body: input });
57
+ }
58
+ reject(approvalId, input = {}) {
59
+ return this.client.request(`/assets/workflows/approvals/${encodeURIComponent(approvalId)}/reject`, { method: 'POST', body: input });
60
+ }
61
+ connections() { return this.client.request('/assets/workflows/connections'); }
62
+ createConnection(input) { return this.client.request('/assets/workflows/connections', { method: 'POST', body: input }); }
63
+ rotateConnectionCredential(connectionId, input) {
64
+ return this.client.request(`/assets/workflows/connections/${encodeURIComponent(connectionId)}/credential/rotate`, { method: 'POST', body: input });
65
+ }
66
+ rotateInboundHook(workflowId) {
67
+ return this.client.request(`/assets/workflows/${encodeURIComponent(workflowId)}/inbound-hook/rotate`, { method: 'POST' });
68
+ }
69
+ }