@editframe/api 0.15.0-beta.9 → 0.16.0-beta.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.
@@ -21,5 +21,6 @@ export declare class CompletionIterator extends BaseEventIterator<CompleteEvent
21
21
  private currentProgress;
22
22
  constructor(eventSource: StreamEventSource);
23
23
  private initializeListeners;
24
+ abort(): void;
24
25
  }
25
26
  export {};
@@ -107,6 +107,9 @@ class CompletionIterator extends BaseEventIterator {
107
107
  this.resolversNext.reject(error);
108
108
  });
109
109
  }
110
+ abort() {
111
+ this.eventSource.abort();
112
+ }
110
113
  }
111
114
  export {
112
115
  CompletionIterator,
@@ -49,11 +49,13 @@ export declare class StreamEventSource {
49
49
  private decoder;
50
50
  private parser;
51
51
  private listeners;
52
- constructor(stream: ReadableStream);
52
+ private abortController;
53
+ constructor(stream: ReadableStream, abortController: AbortController);
53
54
  on<K extends keyof StreamEventSourceEventMap>(event: K, callback: EventCallback<StreamEventSourceEventMap[K]>): this;
54
55
  off<K extends keyof StreamEventSourceEventMap>(event: K, callback: EventCallback<StreamEventSourceEventMap[K]>): this;
55
56
  protected emit<K extends keyof StreamEventSourceEventMap>(event: K, data: StreamEventSourceEventMap[K]): void;
56
57
  whenClosed(): Promise<void>;
57
58
  private startReading;
58
59
  close(): void;
60
+ abort(): void;
59
61
  }
@@ -2,7 +2,7 @@ import debug from "debug";
2
2
  import { createParser } from "eventsource-parser";
3
3
  const log = debug("ef:StreamEventSource");
4
4
  class StreamEventSource {
5
- constructor(stream) {
5
+ constructor(stream, abortController) {
6
6
  this.activeReader = null;
7
7
  this.decoder = new TextDecoder();
8
8
  this.listeners = {};
@@ -11,6 +11,7 @@ class StreamEventSource {
11
11
  throw new Error("Stream is required");
12
12
  }
13
13
  this.stream = stream;
14
+ this.abortController = abortController;
14
15
  this.parser = createParser({
15
16
  onError: (err) => {
16
17
  console.error("StreamEventSource: Parser error:", err);
@@ -71,6 +72,9 @@ class StreamEventSource {
71
72
  console.error("StreamEventSource: Error in startReading:", error);
72
73
  this.emit("error", error);
73
74
  });
75
+ this.abortController.signal.addEventListener("abort", () => {
76
+ this.close();
77
+ });
74
78
  }
75
79
  on(event, callback) {
76
80
  if (!this.listeners[event]) {
@@ -128,6 +132,9 @@ class StreamEventSource {
128
132
  }
129
133
  this.parser.reset();
130
134
  }
135
+ abort() {
136
+ this.abortController.abort();
137
+ }
131
138
  }
132
139
  export {
133
140
  StreamEventSource
package/dist/client.js CHANGED
@@ -4,11 +4,15 @@ const log = debug("ef:api:client");
4
4
  class Client {
5
5
  constructor(token, efHost = "https://editframe.dev") {
6
6
  this.authenticatedEventSource = async (path, init = {}) => {
7
- const response = await this.authenticatedFetch(path, init);
7
+ const abortController = new AbortController();
8
+ const response = await this.authenticatedFetch(path, {
9
+ ...init,
10
+ signal: abortController.signal
11
+ });
8
12
  if (response.body === null) {
9
13
  throw new Error("Could not create event source. Response body is null.");
10
14
  }
11
- return new StreamEventSource(response.body);
15
+ return new StreamEventSource(response.body, abortController);
12
16
  };
13
17
  this.authenticatedFetch = async (path, init = {}) => {
14
18
  init.headers ||= {};
package/dist/index.d.ts CHANGED
@@ -1,13 +1,13 @@
1
- export { createCaptionFile, CreateCaptionFilePayload, type CreateCaptionFileResult, uploadCaptionFile, type LookupCaptionFileByMd5Result, lookupCaptionFileByMd5, } from './resources/caption-file.js';
2
- export { createImageFile, CreateImageFilePayload, type CreateImageFileResult, uploadImageFile, type LookupImageFileByMd5Result, lookupImageFileByMd5, } from './resources/image-file.js';
3
- export { createISOBMFFFile, CreateISOBMFFFilePayload, type CreateISOBMFFFileResult, uploadFragmentIndex, type LookupISOBMFFFileByMd5Result, lookupISOBMFFFileByMd5, type GetISOBMFFFileTranscriptionResult, getISOBMFFFileTranscription, type TranscribeISOBMFFFileResult, transcribeISOBMFFFile, TranscribeISOBMFFFilePayload, } from './resources/isobmff-file.js';
4
- export { createISOBMFFTrack, CreateISOBMFFTrackPayload, type CreateISOBMFFTrackResult, uploadISOBMFFTrack, AudioTrackPayload, type AudioStreamSchema, VideoTrackPayload, type VideoStreamSchema, } from './resources/isobmff-track.js';
5
- export { createRender, CreateRenderPayload, type CreateRenderResult, uploadRender, type LookupRenderByMd5Result, lookupRenderByMd5, getRenderProgress, getRenderInfo, downloadRender, } from './resources/renders.js';
6
- export { createTranscription, CreateTranscriptionPayload, type CreateTranscriptionResult, getTranscriptionInfo, getTranscriptionProgress, type TranscriptionInfoResult, } from './resources/transcriptions.js';
7
- export { createURLToken, type URLTokenResult, } from './resources/url-token.js';
8
- export { createUnprocessedFile, CreateUnprocessedFilePayload, type CreateUnprocessedFileResult, uploadUnprocessedReadableStream, type LookupUnprocessedFileByMd5Result, lookupUnprocessedFileByMd5, processIsobmffFile, type ProcessIsobmffFileResult, type UnprocessedFileUploadDetails, type UnprocessedFile, } from './resources/unprocessed-file.js';
1
+ export { createCaptionFile, CreateCaptionFilePayload, lookupCaptionFileByMd5, uploadCaptionFile, type CreateCaptionFileResult, type LookupCaptionFileByMd5Result, } from './resources/caption-file.js';
2
+ export { createImageFile, CreateImageFilePayload, getImageFileMetadata, ImageFileMimeTypes, lookupImageFileByMd5, uploadImageFile, type CreateImageFileResult, type GetImageFileMetadataResult, type LookupImageFileByMd5Result, } from './resources/image-file.js';
3
+ export { createISOBMFFFile, CreateISOBMFFFilePayload, getISOBMFFFileTranscription, lookupISOBMFFFileByMd5, transcribeISOBMFFFile, TranscribeISOBMFFFilePayload, uploadFragmentIndex, type CreateISOBMFFFileResult, type GetISOBMFFFileTranscriptionResult, type LookupISOBMFFFileByMd5Result, type TranscribeISOBMFFFileResult, } from './resources/isobmff-file.js';
4
+ export { AudioTrackPayload, createISOBMFFTrack, CreateISOBMFFTrackPayload, uploadISOBMFFTrack, VideoTrackPayload, type AudioStreamSchema, type CreateISOBMFFTrackResult, type VideoStreamSchema, } from './resources/isobmff-track.js';
9
5
  export { getIsobmffProcessInfo, getIsobmffProcessProgress, type IsobmffProcessInfoResult, } from './resources/process-isobmff.js';
6
+ export { createRender, CreateRenderPayload, downloadRender, getRenderInfo, getRenderProgress, lookupRenderByMd5, uploadRender, type CreateRenderResult, type LookupRenderByMd5Result, } from './resources/renders.js';
7
+ export { createTranscription, CreateTranscriptionPayload, getTranscriptionInfo, getTranscriptionProgress, type CreateTranscriptionResult, type TranscriptionInfoResult, } from './resources/transcriptions.js';
8
+ export { createUnprocessedFile, CreateUnprocessedFilePayload, lookupUnprocessedFileByMd5, processIsobmffFile, uploadUnprocessedReadableStream, type CreateUnprocessedFileResult, type LookupUnprocessedFileByMd5Result, type ProcessIsobmffFileResult, type UnprocessedFile, type UnprocessedFileUploadDetails, } from './resources/unprocessed-file.js';
9
+ export { createURLToken, type URLTokenResult, } from './resources/url-token.js';
10
10
  export { Client } from './client.js';
11
+ export type { CompletionIterator, ProgressIterator, } from './ProgressIterator.js';
11
12
  export type { IteratorWithPromise, UploadChunkEvent } from './uploadChunks.js';
12
- export type { ProgressIterator, CompletionIterator, } from './ProgressIterator.js';
13
- export type { StreamEventSource, ProgressEvent, CompletionEvent, StreamEventSourceEventMap, EventCallback, } from './StreamEventSource.js';
13
+ export type { CompletionEvent, EventCallback, ProgressEvent, StreamEventSource, StreamEventSourceEventMap, } from './StreamEventSource.js';
package/dist/index.js CHANGED
@@ -1,12 +1,12 @@
1
1
  import { CreateCaptionFilePayload, createCaptionFile, lookupCaptionFileByMd5, uploadCaptionFile } from "./resources/caption-file.js";
2
- import { CreateImageFilePayload, createImageFile, lookupImageFileByMd5, uploadImageFile } from "./resources/image-file.js";
2
+ import { CreateImageFilePayload, ImageFileMimeTypes, createImageFile, getImageFileMetadata, lookupImageFileByMd5, uploadImageFile } from "./resources/image-file.js";
3
3
  import { CreateISOBMFFFilePayload, TranscribeISOBMFFFilePayload, createISOBMFFFile, getISOBMFFFileTranscription, lookupISOBMFFFileByMd5, transcribeISOBMFFFile, uploadFragmentIndex } from "./resources/isobmff-file.js";
4
4
  import { AudioTrackPayload, CreateISOBMFFTrackPayload, VideoTrackPayload, createISOBMFFTrack, uploadISOBMFFTrack } from "./resources/isobmff-track.js";
5
+ import { getIsobmffProcessInfo, getIsobmffProcessProgress } from "./resources/process-isobmff.js";
5
6
  import { CreateRenderPayload, createRender, downloadRender, getRenderInfo, getRenderProgress, lookupRenderByMd5, uploadRender } from "./resources/renders.js";
6
7
  import { CreateTranscriptionPayload, createTranscription, getTranscriptionInfo, getTranscriptionProgress } from "./resources/transcriptions.js";
7
- import { createURLToken } from "./resources/url-token.js";
8
8
  import { CreateUnprocessedFilePayload, createUnprocessedFile, lookupUnprocessedFileByMd5, processIsobmffFile, uploadUnprocessedReadableStream } from "./resources/unprocessed-file.js";
9
- import { getIsobmffProcessInfo, getIsobmffProcessProgress } from "./resources/process-isobmff.js";
9
+ import { createURLToken } from "./resources/url-token.js";
10
10
  import { Client } from "./client.js";
11
11
  export {
12
12
  AudioTrackPayload,
@@ -18,6 +18,7 @@ export {
18
18
  CreateRenderPayload,
19
19
  CreateTranscriptionPayload,
20
20
  CreateUnprocessedFilePayload,
21
+ ImageFileMimeTypes,
21
22
  TranscribeISOBMFFFilePayload,
22
23
  VideoTrackPayload,
23
24
  createCaptionFile,
@@ -30,6 +31,7 @@ export {
30
31
  createUnprocessedFile,
31
32
  downloadRender,
32
33
  getISOBMFFFileTranscription,
34
+ getImageFileMetadata,
33
35
  getIsobmffProcessInfo,
34
36
  getIsobmffProcessProgress,
35
37
  getRenderInfo,
package/dist/node.js CHANGED
@@ -3,17 +3,17 @@ import { basename } from "node:path";
3
3
  import mime from "mime";
4
4
  import { md5FilePath } from "@editframe/assets";
5
5
  import { createImageFile, CreateImageFilePayload } from "./resources/image-file.js";
6
- import { lookupImageFileByMd5, uploadImageFile } from "./resources/image-file.js";
6
+ import { ImageFileMimeTypes, getImageFileMetadata, lookupImageFileByMd5, uploadImageFile } from "./resources/image-file.js";
7
7
  import { createUnprocessedFile, uploadUnprocessedReadableStream } from "./resources/unprocessed-file.js";
8
8
  import { CreateUnprocessedFilePayload, lookupUnprocessedFileByMd5, processIsobmffFile } from "./resources/unprocessed-file.js";
9
9
  import { createReadableStreamFromReadable } from "./utils/createReadableStreamFromReadable.js";
10
10
  import { CreateCaptionFilePayload, createCaptionFile, lookupCaptionFileByMd5, uploadCaptionFile } from "./resources/caption-file.js";
11
11
  import { CreateISOBMFFFilePayload, TranscribeISOBMFFFilePayload, createISOBMFFFile, getISOBMFFFileTranscription, lookupISOBMFFFileByMd5, transcribeISOBMFFFile, uploadFragmentIndex } from "./resources/isobmff-file.js";
12
12
  import { AudioTrackPayload, CreateISOBMFFTrackPayload, VideoTrackPayload, createISOBMFFTrack, uploadISOBMFFTrack } from "./resources/isobmff-track.js";
13
+ import { getIsobmffProcessInfo, getIsobmffProcessProgress } from "./resources/process-isobmff.js";
13
14
  import { CreateRenderPayload, createRender, downloadRender, getRenderInfo, getRenderProgress, lookupRenderByMd5, uploadRender } from "./resources/renders.js";
14
15
  import { CreateTranscriptionPayload, createTranscription, getTranscriptionInfo, getTranscriptionProgress } from "./resources/transcriptions.js";
15
16
  import { createURLToken } from "./resources/url-token.js";
16
- import { getIsobmffProcessInfo, getIsobmffProcessProgress } from "./resources/process-isobmff.js";
17
17
  import { Client } from "./client.js";
18
18
  const createImageFileFromPath = async (client, path) => {
19
19
  const fileInfo = await stat(path);
@@ -61,6 +61,7 @@ export {
61
61
  CreateRenderPayload,
62
62
  CreateTranscriptionPayload,
63
63
  CreateUnprocessedFilePayload,
64
+ ImageFileMimeTypes,
64
65
  TranscribeISOBMFFFilePayload,
65
66
  VideoTrackPayload,
66
67
  createCaptionFile,
@@ -76,6 +77,7 @@ export {
76
77
  createUnprocessedFileFromPath,
77
78
  downloadRender,
78
79
  getISOBMFFFileTranscription,
80
+ getImageFileMetadata,
79
81
  getIsobmffProcessInfo,
80
82
  getIsobmffProcessProgress,
81
83
  getRenderInfo,
@@ -1,22 +1,23 @@
1
1
  import { z } from 'zod';
2
2
  import { Client } from '../client.js';
3
- export declare const CreateImageFilePayload: z.ZodObject<{
3
+ export declare const ImageFileMimeTypes: z.ZodEnum<["image/jpeg", "image/png", "image/jpg", "image/webp"]>;
4
+ export declare const CreateImageFilePayload: z.ZodEffects<z.ZodObject<{
4
5
  /**
5
6
  * The md5 hash of the image file.
6
7
  */
7
- md5: z.ZodNullable<z.ZodString>;
8
+ md5: z.ZodOptional<z.ZodString>;
8
9
  /**
9
10
  * The height of the image file in pixels.
10
11
  */
11
- height: z.ZodNullable<z.ZodNumber>;
12
+ height: z.ZodOptional<z.ZodNumber>;
12
13
  /**
13
14
  * The width of the image file in pixels.
14
15
  */
15
- width: z.ZodNullable<z.ZodNumber>;
16
+ width: z.ZodOptional<z.ZodNumber>;
16
17
  /**
17
- * The mime type of the image file.
18
+ * The mime type of the image file. Optional if the filename has a known file extension.
18
19
  */
19
- mime_type: z.ZodEnum<["image/jpeg", "image/png", "image/jpg", "image/webp"]>;
20
+ mime_type: z.ZodOptional<z.ZodEnum<["image/jpeg", "image/png", "image/jpg", "image/webp"]>>;
20
21
  /**
21
22
  * The filename of the image file.
22
23
  */
@@ -26,19 +27,33 @@ export declare const CreateImageFilePayload: z.ZodObject<{
26
27
  */
27
28
  byte_size: z.ZodNumber;
28
29
  }, "strip", z.ZodTypeAny, {
29
- width: number | null;
30
- height: number | null;
31
30
  filename: string;
32
- md5: string | null;
33
- mime_type: "image/jpeg" | "image/png" | "image/jpg" | "image/webp";
34
31
  byte_size: number;
32
+ width?: number | undefined;
33
+ height?: number | undefined;
34
+ md5?: string | undefined;
35
+ mime_type?: "image/jpeg" | "image/png" | "image/jpg" | "image/webp" | undefined;
35
36
  }, {
36
- width: number | null;
37
- height: number | null;
38
37
  filename: string;
39
- md5: string | null;
40
- mime_type: "image/jpeg" | "image/png" | "image/jpg" | "image/webp";
41
38
  byte_size: number;
39
+ width?: number | undefined;
40
+ height?: number | undefined;
41
+ md5?: string | undefined;
42
+ mime_type?: "image/jpeg" | "image/png" | "image/jpg" | "image/webp" | undefined;
43
+ }>, {
44
+ filename: string;
45
+ byte_size: number;
46
+ width?: number | undefined;
47
+ height?: number | undefined;
48
+ md5?: string | undefined;
49
+ mime_type?: "image/jpeg" | "image/png" | "image/jpg" | "image/webp" | undefined;
50
+ }, {
51
+ filename: string;
52
+ byte_size: number;
53
+ width?: number | undefined;
54
+ height?: number | undefined;
55
+ md5?: string | undefined;
56
+ mime_type?: "image/jpeg" | "image/png" | "image/jpg" | "image/webp" | undefined;
42
57
  }>;
43
58
  export type CreateImageFilePayload = z.infer<typeof CreateImageFilePayload>;
44
59
  export interface CreateImageFileResult {
@@ -57,17 +72,40 @@ export interface CreateImageFileResult {
57
72
  /**
58
73
  * The md5 hash of the image file.
59
74
  */
60
- md5: string;
75
+ md5: string | null;
61
76
  }
62
77
  export interface LookupImageFileByMd5Result {
78
+ /**
79
+ * Whether the image file has been fully uploaded.
80
+ */
63
81
  complete: boolean | null;
82
+ /**
83
+ * The byte size of the image file.
84
+ */
64
85
  byte_size: number;
86
+ /**
87
+ * The id of the image file.
88
+ */
65
89
  id: string;
66
- md5: string;
90
+ /**
91
+ * md5 hash of the image file.
92
+ */
93
+ md5: string | null;
94
+ /**
95
+ * The height of the image file in pixels.
96
+ */
97
+ height: number | null;
98
+ /**
99
+ * The width of the image file in pixels.
100
+ */
101
+ width: number | null;
102
+ }
103
+ export interface GetImageFileMetadataResult extends LookupImageFileByMd5Result {
67
104
  }
68
105
  export declare const createImageFile: (client: Client, payload: CreateImageFilePayload) => Promise<CreateImageFileResult>;
69
106
  export declare const uploadImageFile: (client: Client, uploadDetails: {
70
107
  id: string;
71
108
  byte_size: number;
72
- }, fileStream: ReadableStream) => import('../uploadChunks.js').IteratorWithPromise<import('../uploadChunks.js').UploadChunkEvent>;
109
+ }, fileStream: ReadableStream, chunkSizeBytes?: number) => import('../uploadChunks.js').IteratorWithPromise<import('../uploadChunks.js').UploadChunkEvent>;
110
+ export declare const getImageFileMetadata: (client: Client, id: string) => Promise<GetImageFileMetadataResult | null>;
73
111
  export declare const lookupImageFileByMd5: (client: Client, md5: string) => Promise<LookupImageFileByMd5Result | null>;
@@ -1,25 +1,36 @@
1
1
  import debug from "debug";
2
+ import { types } from "mime-types";
2
3
  import { z } from "zod";
3
4
  import { uploadChunks } from "../uploadChunks.js";
4
5
  const log = debug("ef:api:image-file");
5
6
  const MAX_IMAGE_SIZE = 1024 * 1024 * 16;
7
+ const ImageFileMimeTypes = z.enum([
8
+ "image/jpeg",
9
+ "image/png",
10
+ "image/jpg",
11
+ "image/webp"
12
+ ]);
13
+ function getFileExtension(path) {
14
+ const match = path.match(/\.([^.]+)$/);
15
+ return match ? match[1] : null;
16
+ }
6
17
  const CreateImageFilePayload = z.object({
7
18
  /**
8
19
  * The md5 hash of the image file.
9
20
  */
10
- md5: z.string().nullable(),
21
+ md5: z.string().optional(),
11
22
  /**
12
23
  * The height of the image file in pixels.
13
24
  */
14
- height: z.number().int().nullable(),
25
+ height: z.number().int().optional(),
15
26
  /**
16
27
  * The width of the image file in pixels.
17
28
  */
18
- width: z.number().int().nullable(),
29
+ width: z.number().int().optional(),
19
30
  /**
20
- * The mime type of the image file.
31
+ * The mime type of the image file. Optional if the filename has a known file extension.
21
32
  */
22
- mime_type: z.enum(["image/jpeg", "image/png", "image/jpg", "image/webp"]),
33
+ mime_type: ImageFileMimeTypes.optional(),
23
34
  /**
24
35
  * The filename of the image file.
25
36
  */
@@ -28,6 +39,20 @@ const CreateImageFilePayload = z.object({
28
39
  * The byte size of the image file.
29
40
  */
30
41
  byte_size: z.number().int().max(MAX_IMAGE_SIZE)
42
+ }).superRefine((data, ctx) => {
43
+ const extension = getFileExtension(data.filename);
44
+ const mimeType = extension ? types[extension] : null;
45
+ const parsedMimeType = ImageFileMimeTypes.safeParse(mimeType).data;
46
+ if (parsedMimeType) {
47
+ data.mime_type = parsedMimeType;
48
+ }
49
+ if (!parsedMimeType && !data.mime_type) {
50
+ ctx.addIssue({
51
+ code: z.ZodIssueCode.custom,
52
+ message: "mime_type is required when filename extension doesn't match a known image type",
53
+ path: ["mime_type"]
54
+ });
55
+ }
31
56
  });
32
57
  const createImageFile = async (client, payload) => {
33
58
  log("Creating image file", payload);
@@ -44,15 +69,28 @@ const createImageFile = async (client, payload) => {
44
69
  `Failed to create file ${response.status} ${response.statusText}`
45
70
  );
46
71
  };
47
- const uploadImageFile = (client, uploadDetails, fileStream) => {
72
+ const uploadImageFile = (client, uploadDetails, fileStream, chunkSizeBytes) => {
48
73
  log("Uploading image file", uploadDetails.id);
49
74
  return uploadChunks(client, {
50
75
  url: `/api/v1/image_files/${uploadDetails.id}/upload`,
51
76
  fileSize: uploadDetails.byte_size,
52
77
  fileStream,
53
- maxSize: MAX_IMAGE_SIZE
78
+ maxSize: MAX_IMAGE_SIZE,
79
+ chunkSizeBytes
54
80
  });
55
81
  };
82
+ const getImageFileMetadata = async (client, id) => {
83
+ const response = await client.authenticatedFetch(
84
+ `/api/v1/image_files/${id}.json`,
85
+ {
86
+ method: "GET"
87
+ }
88
+ );
89
+ if (response.ok) {
90
+ return await response.json();
91
+ }
92
+ return null;
93
+ };
56
94
  const lookupImageFileByMd5 = async (client, md5) => {
57
95
  const response = await client.authenticatedFetch(
58
96
  `/api/v1/image_files/md5/${md5}`,
@@ -73,7 +111,9 @@ const lookupImageFileByMd5 = async (client, md5) => {
73
111
  };
74
112
  export {
75
113
  CreateImageFilePayload,
114
+ ImageFileMimeTypes,
76
115
  createImageFile,
116
+ getImageFileMetadata,
77
117
  lookupImageFileByMd5,
78
118
  uploadImageFile
79
119
  };