@canonmsg/backend-contracts 6.0.0 → 6.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.
@@ -135,6 +135,24 @@
135
135
  "durationMs": {
136
136
  "type": "number",
137
137
  "minimum": 0
138
+ },
139
+ "thumbnailUrl": {
140
+ "type": "string",
141
+ "minLength": 1
142
+ },
143
+ "processingStatus": {
144
+ "enum": [
145
+ "processing",
146
+ "ready",
147
+ "failed"
148
+ ]
149
+ },
150
+ "processingErrorCode": {
151
+ "enum": [
152
+ "invalid_video",
153
+ "video_limits_exceeded",
154
+ "video_processing_failed"
155
+ ]
138
156
  }
139
157
  }
140
158
  },
package/dist/cjs/media.js CHANGED
@@ -92,6 +92,20 @@ function normalizeStoredAttachments(value) {
92
92
  const width = normalizeAttachmentNumber(candidate.width);
93
93
  const height = normalizeAttachmentNumber(candidate.height);
94
94
  const durationMs = normalizeAttachmentNumber(candidate.durationMs);
95
+ const processingStatus = candidate.processingStatus;
96
+ if (processingStatus !== undefined
97
+ && processingStatus !== 'processing'
98
+ && processingStatus !== 'ready'
99
+ && processingStatus !== 'failed') {
100
+ return null;
101
+ }
102
+ const processingErrorCode = candidate.processingErrorCode;
103
+ if (processingErrorCode !== undefined
104
+ && processingErrorCode !== 'invalid_video'
105
+ && processingErrorCode !== 'video_limits_exceeded'
106
+ && processingErrorCode !== 'video_processing_failed') {
107
+ return null;
108
+ }
95
109
  attachments.push({
96
110
  kind: candidate.kind,
97
111
  url: candidate.url,
@@ -102,6 +116,11 @@ function normalizeStoredAttachments(value) {
102
116
  ...(width !== undefined ? { width } : {}),
103
117
  ...(height !== undefined ? { height } : {}),
104
118
  ...(durationMs !== undefined ? { durationMs } : {}),
119
+ ...(typeof candidate.thumbnailUrl === 'string' && candidate.thumbnailUrl
120
+ ? { thumbnailUrl: candidate.thumbnailUrl }
121
+ : {}),
122
+ ...(processingStatus !== undefined ? { processingStatus } : {}),
123
+ ...(processingErrorCode !== undefined ? { processingErrorCode } : {}),
105
124
  });
106
125
  }
107
126
  return attachments.length > 0 ? attachments : [];
@@ -108,6 +108,11 @@ const mediaAttachmentDef = {
108
108
  width: { type: 'number', minimum: 0 },
109
109
  height: { type: 'number', minimum: 0 },
110
110
  durationMs: { type: 'number', minimum: 0 },
111
+ thumbnailUrl: { type: 'string', minLength: 1 },
112
+ processingStatus: { enum: ['processing', 'ready', 'failed'] },
113
+ processingErrorCode: {
114
+ enum: ['invalid_video', 'video_limits_exceeded', 'video_processing_failed'],
115
+ },
111
116
  },
112
117
  };
113
118
  const turnMetadataDef = {
package/dist/media.d.ts CHANGED
@@ -1,4 +1,8 @@
1
1
  export type MediaAttachmentKind = 'image' | 'audio' | 'video' | 'file';
2
+ /** Lifecycle for newly uploaded videos that are normalized server-side. */
3
+ export type VideoProcessingStatus = 'processing' | 'ready' | 'failed';
4
+ /** Stable, display-safe reasons for a terminal video processing failure. */
5
+ export type VideoProcessingErrorCode = 'invalid_video' | 'video_limits_exceeded' | 'video_processing_failed';
2
6
  export interface MediaAttachment {
3
7
  kind: MediaAttachmentKind;
4
8
  url: string;
@@ -14,6 +18,11 @@ export interface MediaAttachment {
14
18
  width?: number;
15
19
  height?: number;
16
20
  durationMs?: number;
21
+ /** Server-generated poster for a normalized video. */
22
+ thumbnailUrl?: string;
23
+ /** Missing means a legacy attachment that is immediately playable. */
24
+ processingStatus?: VideoProcessingStatus;
25
+ processingErrorCode?: VideoProcessingErrorCode;
17
26
  }
18
27
  export declare function inferMediaAttachmentKind(mimeType: string): MediaAttachmentKind;
19
28
  export declare function getStoredFileExtension(input: {
package/dist/media.js CHANGED
@@ -84,6 +84,20 @@ export function normalizeStoredAttachments(value) {
84
84
  const width = normalizeAttachmentNumber(candidate.width);
85
85
  const height = normalizeAttachmentNumber(candidate.height);
86
86
  const durationMs = normalizeAttachmentNumber(candidate.durationMs);
87
+ const processingStatus = candidate.processingStatus;
88
+ if (processingStatus !== undefined
89
+ && processingStatus !== 'processing'
90
+ && processingStatus !== 'ready'
91
+ && processingStatus !== 'failed') {
92
+ return null;
93
+ }
94
+ const processingErrorCode = candidate.processingErrorCode;
95
+ if (processingErrorCode !== undefined
96
+ && processingErrorCode !== 'invalid_video'
97
+ && processingErrorCode !== 'video_limits_exceeded'
98
+ && processingErrorCode !== 'video_processing_failed') {
99
+ return null;
100
+ }
87
101
  attachments.push({
88
102
  kind: candidate.kind,
89
103
  url: candidate.url,
@@ -94,6 +108,11 @@ export function normalizeStoredAttachments(value) {
94
108
  ...(width !== undefined ? { width } : {}),
95
109
  ...(height !== undefined ? { height } : {}),
96
110
  ...(durationMs !== undefined ? { durationMs } : {}),
111
+ ...(typeof candidate.thumbnailUrl === 'string' && candidate.thumbnailUrl
112
+ ? { thumbnailUrl: candidate.thumbnailUrl }
113
+ : {}),
114
+ ...(processingStatus !== undefined ? { processingStatus } : {}),
115
+ ...(processingErrorCode !== undefined ? { processingErrorCode } : {}),
97
116
  });
98
117
  }
99
118
  return attachments.length > 0 ? attachments : [];
@@ -258,6 +258,9 @@ export interface VerbMediaAttachment {
258
258
  width?: number;
259
259
  height?: number;
260
260
  durationMs?: number;
261
+ thumbnailUrl?: string;
262
+ processingStatus?: 'processing' | 'ready' | 'failed';
263
+ processingErrorCode?: 'invalid_video' | 'video_limits_exceeded' | 'video_processing_failed';
261
264
  }
262
265
  /**
263
266
  * Well-known turn-protocol keys inside the free-form metadata envelope
@@ -280,6 +280,16 @@ export declare const CANON_VERBS_JSON_SCHEMA: {
280
280
  readonly type: "number";
281
281
  readonly minimum: 0;
282
282
  };
283
+ readonly thumbnailUrl: {
284
+ readonly type: "string";
285
+ readonly minLength: 1;
286
+ };
287
+ readonly processingStatus: {
288
+ readonly enum: readonly ["processing", "ready", "failed"];
289
+ };
290
+ readonly processingErrorCode: {
291
+ readonly enum: readonly ["invalid_video", "video_limits_exceeded", "video_processing_failed"];
292
+ };
283
293
  };
284
294
  };
285
295
  readonly turnMetadata: {
@@ -103,6 +103,11 @@ const mediaAttachmentDef = {
103
103
  width: { type: 'number', minimum: 0 },
104
104
  height: { type: 'number', minimum: 0 },
105
105
  durationMs: { type: 'number', minimum: 0 },
106
+ thumbnailUrl: { type: 'string', minLength: 1 },
107
+ processingStatus: { enum: ['processing', 'ready', 'failed'] },
108
+ processingErrorCode: {
109
+ enum: ['invalid_video', 'video_limits_exceeded', 'video_processing_failed'],
110
+ },
106
111
  },
107
112
  };
108
113
  const turnMetadataDef = {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@canonmsg/backend-contracts",
3
- "version": "6.0.0",
3
+ "version": "6.1.0",
4
4
  "description": "Canon backend contract helpers shared by Functions and stream-service",
5
5
  "type": "module",
6
6
  "main": "dist/cjs/index.js",