@editframe/api 0.16.7-beta.0 → 0.17.6-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.
@@ -1,7 +1,3 @@
1
1
  let CHUNK_SIZE_BYTES = 8 * 1024 * 1024;
2
- if ("process" in globalThis && process.env.CHUNK_SIZE_BYTES) {
3
- CHUNK_SIZE_BYTES = Number.parseInt(process.env.CHUNK_SIZE_BYTES, 10);
4
- }
5
- export {
6
- CHUNK_SIZE_BYTES
7
- };
2
+ if ("process" in globalThis && process.env.CHUNK_SIZE_BYTES) CHUNK_SIZE_BYTES = Number.parseInt(process.env.CHUNK_SIZE_BYTES, 10);
3
+ export { CHUNK_SIZE_BYTES };
@@ -1,117 +1,104 @@
1
1
  const promiseWithResolvers = () => {
2
- if (typeof Promise.withResolvers === "function") {
3
- return Promise.withResolvers();
4
- }
5
- let resolve;
6
- let reject;
7
- const promise = new Promise((res, rej) => {
8
- resolve = res;
9
- reject = rej;
10
- });
11
- return { promise, resolve, reject };
2
+ if (typeof Promise.withResolvers === "function") return Promise.withResolvers();
3
+ let resolve;
4
+ let reject;
5
+ const promise = new Promise((res, rej) => {
6
+ resolve = res;
7
+ reject = rej;
8
+ });
9
+ return {
10
+ promise,
11
+ resolve,
12
+ reject
13
+ };
12
14
  };
13
- class BaseEventIterator {
14
- constructor(eventSource) {
15
- this.queue = [];
16
- this.index = 0;
17
- this.isComplete = false;
18
- this.resolversNext = promiseWithResolvers();
19
- this.eventSource = eventSource;
20
- }
21
- async whenComplete() {
22
- for await (const _ of this) {
23
- }
24
- return this.queue;
25
- }
26
- push(event) {
27
- this.queue.push(event);
28
- this.resolversNext.resolve();
29
- this.resolversNext = promiseWithResolvers();
30
- }
31
- get queueLength() {
32
- return this.queue.length - this.index;
33
- }
34
- async *[Symbol.asyncIterator]() {
35
- try {
36
- while (!this.isComplete || this.queueLength > 0) {
37
- if (this.queueLength === 0) {
38
- await this.resolversNext.promise;
39
- } else {
40
- const item = this.queue[this.index];
41
- if (!item) {
42
- throw new Error("Queue is corrupted");
43
- }
44
- this.index++;
45
- yield item;
46
- }
47
- }
48
- } finally {
49
- this.eventSource.close();
50
- }
51
- }
52
- }
53
- class ProgressIterator extends BaseEventIterator {
54
- constructor(eventSource) {
55
- super(eventSource);
56
- this.initializeListeners();
57
- }
58
- initializeListeners() {
59
- this.eventSource.on("progress", (event) => {
60
- this.push(event);
61
- });
62
- this.eventSource.on("complete", (event) => {
63
- this.isComplete = true;
64
- this.push(event);
65
- });
66
- this.eventSource.on("error", (error) => {
67
- this.eventSource.close();
68
- this.resolversNext.reject(error);
69
- });
70
- }
71
- }
72
- class CompletionIterator extends BaseEventIterator {
73
- constructor(eventSource) {
74
- super(eventSource);
75
- this.totalSize = 0;
76
- this.currentProgress = 0;
77
- this.initializeListeners();
78
- }
79
- initializeListeners() {
80
- this.eventSource.on("size", (event) => {
81
- this.totalSize = event.data.size;
82
- this.push({
83
- type: "progress",
84
- data: {
85
- progress: 0
86
- }
87
- });
88
- });
89
- this.eventSource.on("completion", (event) => {
90
- this.currentProgress += Number(event.data.count);
91
- this.push({
92
- type: "progress",
93
- data: {
94
- progress: this.currentProgress / this.totalSize
95
- }
96
- });
97
- if (this.currentProgress >= this.totalSize) {
98
- this.isComplete = true;
99
- }
100
- });
101
- this.eventSource.on("complete", (event) => {
102
- this.isComplete = true;
103
- this.push(event);
104
- });
105
- this.eventSource.on("error", (error) => {
106
- this.eventSource.close();
107
- this.resolversNext.reject(error);
108
- });
109
- }
110
- abort() {
111
- this.eventSource.abort();
112
- }
113
- }
114
- export {
115
- CompletionIterator,
116
- ProgressIterator
15
+ var BaseEventIterator = class {
16
+ constructor(eventSource) {
17
+ this.queue = [];
18
+ this.index = 0;
19
+ this.isComplete = false;
20
+ this.resolversNext = promiseWithResolvers();
21
+ this.eventSource = eventSource;
22
+ }
23
+ async whenComplete() {
24
+ for await (const _ of this);
25
+ return this.queue;
26
+ }
27
+ push(event) {
28
+ this.queue.push(event);
29
+ this.resolversNext.resolve();
30
+ this.resolversNext = promiseWithResolvers();
31
+ }
32
+ get queueLength() {
33
+ return this.queue.length - this.index;
34
+ }
35
+ async *[Symbol.asyncIterator]() {
36
+ try {
37
+ while (!this.isComplete || this.queueLength > 0) if (this.queueLength === 0) await this.resolversNext.promise;
38
+ else {
39
+ const item = this.queue[this.index];
40
+ if (!item) throw new Error("Queue is corrupted");
41
+ this.index++;
42
+ yield item;
43
+ }
44
+ } finally {
45
+ this.eventSource.close();
46
+ }
47
+ }
117
48
  };
49
+ var ProgressIterator = class extends BaseEventIterator {
50
+ constructor(eventSource) {
51
+ super(eventSource);
52
+ this.initializeListeners();
53
+ }
54
+ initializeListeners() {
55
+ this.eventSource.on("progress", (event) => {
56
+ this.push(event);
57
+ });
58
+ this.eventSource.on("complete", (event) => {
59
+ this.isComplete = true;
60
+ this.push(event);
61
+ });
62
+ this.eventSource.on("error", (error) => {
63
+ this.eventSource.close();
64
+ this.resolversNext.reject(error);
65
+ });
66
+ }
67
+ };
68
+ var CompletionIterator = class extends BaseEventIterator {
69
+ constructor(eventSource) {
70
+ super(eventSource);
71
+ this.totalSize = 0;
72
+ this.currentProgress = 0;
73
+ this.initializeListeners();
74
+ }
75
+ initializeListeners() {
76
+ this.eventSource.on("size", (event) => {
77
+ this.totalSize = event.data.size;
78
+ this.push({
79
+ type: "progress",
80
+ data: { progress: 0 }
81
+ });
82
+ });
83
+ this.eventSource.on("completion", (event) => {
84
+ this.currentProgress += Number(event.data.count);
85
+ this.push({
86
+ type: "progress",
87
+ data: { progress: this.currentProgress / this.totalSize }
88
+ });
89
+ if (this.currentProgress >= this.totalSize) this.isComplete = true;
90
+ });
91
+ this.eventSource.on("complete", (event) => {
92
+ this.isComplete = true;
93
+ this.push(event);
94
+ });
95
+ this.eventSource.on("error", (error) => {
96
+ this.eventSource.close();
97
+ this.resolversNext.reject(error);
98
+ });
99
+ }
100
+ abort() {
101
+ this.eventSource.abort();
102
+ }
103
+ };
104
+ export { CompletionIterator, ProgressIterator };
@@ -1,141 +1,119 @@
1
1
  import debug from "debug";
2
2
  import { createParser } from "eventsource-parser";
3
3
  const log = debug("ef:StreamEventSource");
4
- class StreamEventSource {
5
- constructor(stream, abortController) {
6
- this.activeReader = null;
7
- this.decoder = new TextDecoder();
8
- this.listeners = {};
9
- if (!stream) {
10
- console.error("StreamEventSource: Stream is null or undefined");
11
- throw new Error("Stream is required");
12
- }
13
- this.stream = stream;
14
- this.abortController = abortController;
15
- this.parser = createParser({
16
- onError: (err) => {
17
- console.error("StreamEventSource: Parser error:", err);
18
- this.emit("error", err);
19
- },
20
- onEvent: (event) => {
21
- if (event.event) {
22
- switch (event.event) {
23
- case "heartbeat":
24
- this.emit("heartbeat", {
25
- type: "heartbeat",
26
- data: JSON.parse(event.data)
27
- });
28
- break;
29
- case "size":
30
- this.emit("size", {
31
- type: "size",
32
- data: JSON.parse(event.data)
33
- });
34
- break;
35
- case "completion":
36
- this.emit("completion", {
37
- type: "completion",
38
- data: JSON.parse(event.data)
39
- });
40
- break;
41
- case "progress":
42
- this.emit("progress", {
43
- type: "progress",
44
- data: JSON.parse(event.data)
45
- });
46
- break;
47
- case "complete":
48
- this.emit("complete", {
49
- type: "complete",
50
- data: JSON.parse(event.data)
51
- });
52
- break;
53
- case "error":
54
- log("StreamEventSource: Error event", event.data);
55
- this.emit("error", new Error(event.data));
56
- break;
57
- default:
58
- this.emit(
59
- "error",
60
- new Error(`Unknown event: ${event.event} data: ${event.data}`)
61
- );
62
- }
63
- } else {
64
- this.emit("message", {
65
- id: event.id,
66
- data: event.data
67
- });
68
- }
69
- }
70
- });
71
- this.startReading().catch((error) => {
72
- console.error("StreamEventSource: Error in startReading:", error);
73
- this.emit("error", error);
74
- });
75
- this.abortController.signal.addEventListener("abort", () => {
76
- this.close();
77
- });
78
- }
79
- on(event, callback) {
80
- if (!this.listeners[event]) {
81
- this.listeners[event] = [];
82
- }
83
- this.listeners[event]?.push(callback);
84
- return this;
85
- }
86
- off(event, callback) {
87
- const listeners = this.listeners[event];
88
- if (listeners) {
89
- const index = listeners.indexOf(callback);
90
- if (index !== -1) {
91
- listeners.splice(index, 1);
92
- }
93
- }
94
- return this;
95
- }
96
- emit(event, data) {
97
- for (const callback of this.listeners[event] ?? []) {
98
- callback(data);
99
- }
100
- }
101
- whenClosed() {
102
- return new Promise((resolve) => {
103
- this.on("end", () => resolve());
104
- });
105
- }
106
- async startReading() {
107
- try {
108
- this.activeReader = this.stream.getReader();
109
- while (true) {
110
- const { done, value } = await this.activeReader.read();
111
- if (done) break;
112
- const chunk = this.decoder.decode(value);
113
- if (!value) {
114
- throw new Error("Chunk is null");
115
- }
116
- this.parser.feed(chunk);
117
- }
118
- this.activeReader = null;
119
- this.emit("end", []);
120
- } catch (error) {
121
- console.error("StreamEventSource: Error reading stream:", error);
122
- if (error instanceof Error) {
123
- this.emit("error", error);
124
- } else {
125
- this.emit("error", new Error(String(error)));
126
- }
127
- }
128
- }
129
- close() {
130
- if (this.activeReader) {
131
- this.activeReader = null;
132
- }
133
- this.parser.reset();
134
- }
135
- abort() {
136
- this.abortController.abort();
137
- }
138
- }
139
- export {
140
- StreamEventSource
4
+ var StreamEventSource = class {
5
+ constructor(stream, abortController) {
6
+ this.activeReader = null;
7
+ this.decoder = new TextDecoder();
8
+ this.listeners = {};
9
+ if (!stream) {
10
+ console.error("StreamEventSource: Stream is null or undefined");
11
+ throw new Error("Stream is required");
12
+ }
13
+ this.stream = stream;
14
+ this.abortController = abortController;
15
+ this.parser = createParser({
16
+ onError: (err) => {
17
+ console.error("StreamEventSource: Parser error:", err);
18
+ this.emit("error", err);
19
+ },
20
+ onEvent: (event) => {
21
+ if (event.event) switch (event.event) {
22
+ case "heartbeat":
23
+ this.emit("heartbeat", {
24
+ type: "heartbeat",
25
+ data: JSON.parse(event.data)
26
+ });
27
+ break;
28
+ case "size":
29
+ this.emit("size", {
30
+ type: "size",
31
+ data: JSON.parse(event.data)
32
+ });
33
+ break;
34
+ case "completion":
35
+ this.emit("completion", {
36
+ type: "completion",
37
+ data: JSON.parse(event.data)
38
+ });
39
+ break;
40
+ case "progress":
41
+ this.emit("progress", {
42
+ type: "progress",
43
+ data: JSON.parse(event.data)
44
+ });
45
+ break;
46
+ case "complete":
47
+ this.emit("complete", {
48
+ type: "complete",
49
+ data: JSON.parse(event.data)
50
+ });
51
+ break;
52
+ case "error":
53
+ log("StreamEventSource: Error event", event.data);
54
+ this.emit("error", new Error(event.data));
55
+ break;
56
+ default: this.emit("error", /* @__PURE__ */ new Error(`Unknown event: ${event.event} data: ${event.data}`));
57
+ }
58
+ else this.emit("message", {
59
+ id: event.id,
60
+ data: event.data
61
+ });
62
+ }
63
+ });
64
+ this.startReading().catch((error) => {
65
+ console.error("StreamEventSource: Error in startReading:", error);
66
+ this.emit("error", error);
67
+ });
68
+ this.abortController.signal.addEventListener("abort", () => {
69
+ this.close();
70
+ });
71
+ }
72
+ on(event, callback) {
73
+ if (!this.listeners[event]) this.listeners[event] = [];
74
+ this.listeners[event]?.push(callback);
75
+ return this;
76
+ }
77
+ off(event, callback) {
78
+ const listeners = this.listeners[event];
79
+ if (listeners) {
80
+ const index = listeners.indexOf(callback);
81
+ if (index !== -1) listeners.splice(index, 1);
82
+ }
83
+ return this;
84
+ }
85
+ emit(event, data) {
86
+ for (const callback of this.listeners[event] ?? []) callback(data);
87
+ }
88
+ whenClosed() {
89
+ return new Promise((resolve) => {
90
+ this.on("end", () => resolve());
91
+ });
92
+ }
93
+ async startReading() {
94
+ try {
95
+ this.activeReader = this.stream.getReader();
96
+ while (true) {
97
+ const { done, value } = await this.activeReader.read();
98
+ if (done) break;
99
+ const chunk = this.decoder.decode(value);
100
+ if (!value) throw new Error("Chunk is null");
101
+ this.parser.feed(chunk);
102
+ }
103
+ this.activeReader = null;
104
+ this.emit("end", []);
105
+ } catch (error) {
106
+ console.error("StreamEventSource: Error reading stream:", error);
107
+ if (error instanceof Error) this.emit("error", error);
108
+ else this.emit("error", new Error(String(error)));
109
+ }
110
+ }
111
+ close() {
112
+ if (this.activeReader) this.activeReader = null;
113
+ this.parser.reset();
114
+ }
115
+ abort() {
116
+ this.abortController.abort();
117
+ }
141
118
  };
119
+ export { StreamEventSource };
package/dist/client.js CHANGED
@@ -1,53 +1,42 @@
1
- import debug from "debug";
2
1
  import { StreamEventSource } from "./StreamEventSource.js";
2
+ import debug from "debug";
3
3
  const log = debug("ef:api:client");
4
- class Client {
5
- constructor(token, efHost = "https://editframe.dev") {
6
- this.authenticatedEventSource = async (path, init = {}) => {
7
- const abortController = new AbortController();
8
- const response = await this.authenticatedFetch(path, {
9
- ...init,
10
- signal: abortController.signal
11
- });
12
- if (response.body === null) {
13
- throw new Error("Could not create event source. Response body is null.");
14
- }
15
- return new StreamEventSource(response.body, abortController);
16
- };
17
- this.authenticatedFetch = async (path, init = {}) => {
18
- init.headers ||= {};
19
- const url = new URL(path, this.#efHost);
20
- log(
21
- "Authenticated fetch",
22
- { url: url.toString(), init },
23
- this.#token ? "(Token will be added as Bearer token)" : "(Using session cookie)"
24
- );
25
- if (this.#token) {
26
- Object.assign(init.headers, {
27
- Authorization: `Bearer ${this.#token}`
28
- });
29
- }
30
- Object.assign(init.headers, {
31
- "Content-Type": "application/json"
32
- });
33
- init.credentials = "include";
34
- const response = await fetch(url, init);
35
- log("Authenticated fetch response", response.status, response.statusText);
36
- return response;
37
- };
38
- log("Creating client with efHost", { efHost, tokenIsSet: !!token });
39
- this.#token = token;
40
- this.#efHost = efHost;
41
- if (token) {
42
- const { apiKey, apiSecret } = token.match(/^(?<apiSecret>ef_[^_]+)_(?<apiKey>.+)$/)?.groups ?? {};
43
- if (!apiKey || !apiSecret) {
44
- throw new Error("Invalid token format. Must look like: ef_{}_{}");
45
- }
46
- }
47
- }
48
- #token;
49
- #efHost;
50
- }
51
- export {
52
- Client
4
+ var Client = class {
5
+ #token;
6
+ #efHost;
7
+ constructor(token, efHost = "https://editframe.dev") {
8
+ this.authenticatedEventSource = async (path, init = {}) => {
9
+ const abortController = new AbortController();
10
+ const requestInit = { ...init };
11
+ requestInit.signal ??= abortController.signal;
12
+ const response = await this.authenticatedFetch(path, requestInit);
13
+ if (response.body === null) throw new Error("Could not create event source. Response body is null.");
14
+ return new StreamEventSource(response.body, abortController);
15
+ };
16
+ this.authenticatedFetch = async (path, init = {}) => {
17
+ init.headers ||= {};
18
+ const url = new URL(path, this.#efHost);
19
+ log("Authenticated fetch", {
20
+ url: url.toString(),
21
+ init
22
+ }, this.#token ? "(Token will be added as Bearer token)" : "(Using session cookie)");
23
+ if (this.#token) Object.assign(init.headers, { Authorization: `Bearer ${this.#token}` });
24
+ Object.assign(init.headers, { "Content-Type": "application/json" });
25
+ init.credentials = "include";
26
+ const response = await fetch(url, init);
27
+ log("Authenticated fetch response", response.status, response.statusText);
28
+ return response;
29
+ };
30
+ log("Creating client with efHost", {
31
+ efHost,
32
+ tokenIsSet: !!token
33
+ });
34
+ this.#token = token;
35
+ this.#efHost = efHost;
36
+ if (token) {
37
+ const { apiKey, apiSecret } = token.match(/^(?<apiSecret>ef_[^_]+)_(?<apiKey>.+)$/)?.groups ?? {};
38
+ if (!apiKey || !apiSecret) throw new Error("Invalid token format. Must look like: ef_{}_{}");
39
+ }
40
+ }
53
41
  };
42
+ export { Client };
package/dist/index.js CHANGED
@@ -1,56 +1,11 @@
1
- import { CreateCaptionFilePayload, createCaptionFile, lookupCaptionFileByMd5, uploadCaptionFile } from "./resources/caption-file.js";
2
1
  import { CreateImageFilePayload, ImageFileMimeTypes, createImageFile, getImageFileMetadata, lookupImageFileByMd5, uploadImageFile } from "./resources/image-file.js";
2
+ import { CreateUnprocessedFilePayload, createUnprocessedFile, lookupUnprocessedFileByMd5, processIsobmffFile, uploadUnprocessedReadableStream } from "./resources/unprocessed-file.js";
3
+ import { CreateCaptionFilePayload, createCaptionFile, lookupCaptionFileByMd5, uploadCaptionFile } from "./resources/caption-file.js";
3
4
  import { CreateISOBMFFFilePayload, TranscribeISOBMFFFilePayload, createISOBMFFFile, getISOBMFFFileTranscription, lookupISOBMFFFileByMd5, transcribeISOBMFFFile, uploadFragmentIndex } from "./resources/isobmff-file.js";
4
5
  import { AudioTrackPayload, CreateISOBMFFTrackPayload, VideoTrackPayload, createISOBMFFTrack, uploadISOBMFFTrack } from "./resources/isobmff-track.js";
5
6
  import { getIsobmffProcessInfo, getIsobmffProcessProgress } from "./resources/process-isobmff.js";
6
7
  import { CreateRenderPayload, OutputConfiguration, RenderOutputConfiguration, createRender, downloadRender, getRenderInfo, getRenderProgress, lookupRenderByMd5, uploadRender } from "./resources/renders.js";
7
8
  import { CreateTranscriptionPayload, createTranscription, getTranscriptionInfo, getTranscriptionProgress } from "./resources/transcriptions.js";
8
- import { CreateUnprocessedFilePayload, createUnprocessedFile, lookupUnprocessedFileByMd5, processIsobmffFile, uploadUnprocessedReadableStream } from "./resources/unprocessed-file.js";
9
9
  import { createURLToken } from "./resources/url-token.js";
10
10
  import { Client } from "./client.js";
11
- export {
12
- AudioTrackPayload,
13
- Client,
14
- CreateCaptionFilePayload,
15
- CreateISOBMFFFilePayload,
16
- CreateISOBMFFTrackPayload,
17
- CreateImageFilePayload,
18
- CreateRenderPayload,
19
- CreateTranscriptionPayload,
20
- CreateUnprocessedFilePayload,
21
- ImageFileMimeTypes,
22
- OutputConfiguration,
23
- RenderOutputConfiguration,
24
- TranscribeISOBMFFFilePayload,
25
- VideoTrackPayload,
26
- createCaptionFile,
27
- createISOBMFFFile,
28
- createISOBMFFTrack,
29
- createImageFile,
30
- createRender,
31
- createTranscription,
32
- createURLToken,
33
- createUnprocessedFile,
34
- downloadRender,
35
- getISOBMFFFileTranscription,
36
- getImageFileMetadata,
37
- getIsobmffProcessInfo,
38
- getIsobmffProcessProgress,
39
- getRenderInfo,
40
- getRenderProgress,
41
- getTranscriptionInfo,
42
- getTranscriptionProgress,
43
- lookupCaptionFileByMd5,
44
- lookupISOBMFFFileByMd5,
45
- lookupImageFileByMd5,
46
- lookupRenderByMd5,
47
- lookupUnprocessedFileByMd5,
48
- processIsobmffFile,
49
- transcribeISOBMFFFile,
50
- uploadCaptionFile,
51
- uploadFragmentIndex,
52
- uploadISOBMFFTrack,
53
- uploadImageFile,
54
- uploadRender,
55
- uploadUnprocessedReadableStream
56
- };
11
+ export { AudioTrackPayload, Client, CreateCaptionFilePayload, CreateISOBMFFFilePayload, CreateISOBMFFTrackPayload, CreateImageFilePayload, CreateRenderPayload, CreateTranscriptionPayload, CreateUnprocessedFilePayload, ImageFileMimeTypes, OutputConfiguration, RenderOutputConfiguration, TranscribeISOBMFFFilePayload, VideoTrackPayload, createCaptionFile, createISOBMFFFile, createISOBMFFTrack, createImageFile, createRender, createTranscription, createURLToken, createUnprocessedFile, downloadRender, getISOBMFFFileTranscription, getImageFileMetadata, getIsobmffProcessInfo, getIsobmffProcessProgress, getRenderInfo, getRenderProgress, getTranscriptionInfo, getTranscriptionProgress, lookupCaptionFileByMd5, lookupISOBMFFFileByMd5, lookupImageFileByMd5, lookupRenderByMd5, lookupUnprocessedFileByMd5, processIsobmffFile, transcribeISOBMFFFile, uploadCaptionFile, uploadFragmentIndex, uploadISOBMFFTrack, uploadImageFile, uploadRender, uploadUnprocessedReadableStream };