@editframe/api 0.15.0-beta.18 → 0.15.0-beta.19
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.
- package/dist/index.d.ts +1 -1
- package/dist/index.js +2 -1
- package/dist/node.js +2 -1
- package/dist/resources/image-file.d.ts +52 -15
- package/dist/resources/image-file.js +41 -7
- package/dist/resources/renders.d.ts +1 -0
- package/dist/uploadChunks.js +1 -0
- package/package.json +6 -4
- package/src/resources/image-file.test.ts +23 -0
- package/src/resources/image-file.ts +95 -26
- package/src/resources/renders.ts +1 -0
- package/types.json +1 -1
package/dist/index.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
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';
|
|
2
|
+
export { createImageFile, CreateImageFilePayload, type CreateImageFileResult, uploadImageFile, type LookupImageFileByMd5Result, lookupImageFileByMd5, type GetImageFileMetadataResult, getImageFileMetadata, } from './resources/image-file.js';
|
|
3
3
|
export { createISOBMFFFile, CreateISOBMFFFilePayload, type CreateISOBMFFFileResult, uploadFragmentIndex, type LookupISOBMFFFileByMd5Result, lookupISOBMFFFileByMd5, type GetISOBMFFFileTranscriptionResult, getISOBMFFFileTranscription, type TranscribeISOBMFFFileResult, transcribeISOBMFFFile, TranscribeISOBMFFFilePayload, } from './resources/isobmff-file.js';
|
|
4
4
|
export { createISOBMFFTrack, CreateISOBMFFTrackPayload, type CreateISOBMFFTrackResult, uploadISOBMFFTrack, AudioTrackPayload, type AudioStreamSchema, VideoTrackPayload, type VideoStreamSchema, } from './resources/isobmff-track.js';
|
|
5
5
|
export { createRender, CreateRenderPayload, type CreateRenderResult, uploadRender, type LookupRenderByMd5Result, lookupRenderByMd5, getRenderProgress, getRenderInfo, downloadRender, } from './resources/renders.js';
|
package/dist/index.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
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, 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
5
|
import { CreateRenderPayload, createRender, downloadRender, getRenderInfo, getRenderProgress, lookupRenderByMd5, uploadRender } from "./resources/renders.js";
|
|
@@ -30,6 +30,7 @@ export {
|
|
|
30
30
|
createUnprocessedFile,
|
|
31
31
|
downloadRender,
|
|
32
32
|
getISOBMFFFileTranscription,
|
|
33
|
+
getImageFileMetadata,
|
|
33
34
|
getIsobmffProcessInfo,
|
|
34
35
|
getIsobmffProcessProgress,
|
|
35
36
|
getRenderInfo,
|
package/dist/node.js
CHANGED
|
@@ -3,7 +3,7 @@ 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 { 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";
|
|
@@ -76,6 +76,7 @@ export {
|
|
|
76
76
|
createUnprocessedFileFromPath,
|
|
77
77
|
downloadRender,
|
|
78
78
|
getISOBMFFFileTranscription,
|
|
79
|
+
getImageFileMetadata,
|
|
79
80
|
getIsobmffProcessInfo,
|
|
80
81
|
getIsobmffProcessProgress,
|
|
81
82
|
getRenderInfo,
|
|
@@ -1,22 +1,22 @@
|
|
|
1
1
|
import { z } from 'zod';
|
|
2
2
|
import { Client } from '../client.js';
|
|
3
|
-
export declare const CreateImageFilePayload: z.ZodObject<{
|
|
3
|
+
export declare const CreateImageFilePayload: z.ZodEffects<z.ZodObject<{
|
|
4
4
|
/**
|
|
5
5
|
* The md5 hash of the image file.
|
|
6
6
|
*/
|
|
7
|
-
md5: z.
|
|
7
|
+
md5: z.ZodOptional<z.ZodString>;
|
|
8
8
|
/**
|
|
9
9
|
* The height of the image file in pixels.
|
|
10
10
|
*/
|
|
11
|
-
height: z.
|
|
11
|
+
height: z.ZodOptional<z.ZodNumber>;
|
|
12
12
|
/**
|
|
13
13
|
* The width of the image file in pixels.
|
|
14
14
|
*/
|
|
15
|
-
width: z.
|
|
15
|
+
width: z.ZodOptional<z.ZodNumber>;
|
|
16
16
|
/**
|
|
17
|
-
* The mime type of the image file.
|
|
17
|
+
* The mime type of the image file. Optional if the filename has a known file extension.
|
|
18
18
|
*/
|
|
19
|
-
mime_type: z.ZodEnum<["image/jpeg", "image/png", "image/jpg", "image/webp"]
|
|
19
|
+
mime_type: z.ZodOptional<z.ZodEnum<["image/jpeg", "image/png", "image/jpg", "image/webp"]>>;
|
|
20
20
|
/**
|
|
21
21
|
* The filename of the image file.
|
|
22
22
|
*/
|
|
@@ -26,19 +26,33 @@ export declare const CreateImageFilePayload: z.ZodObject<{
|
|
|
26
26
|
*/
|
|
27
27
|
byte_size: z.ZodNumber;
|
|
28
28
|
}, "strip", z.ZodTypeAny, {
|
|
29
|
-
width: number | null;
|
|
30
|
-
height: number | null;
|
|
31
29
|
filename: string;
|
|
32
|
-
md5: string | null;
|
|
33
|
-
mime_type: "image/jpeg" | "image/png" | "image/jpg" | "image/webp";
|
|
34
30
|
byte_size: number;
|
|
31
|
+
width?: number | undefined;
|
|
32
|
+
height?: number | undefined;
|
|
33
|
+
md5?: string | undefined;
|
|
34
|
+
mime_type?: "image/jpeg" | "image/png" | "image/jpg" | "image/webp" | undefined;
|
|
35
35
|
}, {
|
|
36
|
-
width: number | null;
|
|
37
|
-
height: number | null;
|
|
38
36
|
filename: string;
|
|
39
|
-
md5: string | null;
|
|
40
|
-
mime_type: "image/jpeg" | "image/png" | "image/jpg" | "image/webp";
|
|
41
37
|
byte_size: number;
|
|
38
|
+
width?: number | undefined;
|
|
39
|
+
height?: number | undefined;
|
|
40
|
+
md5?: string | undefined;
|
|
41
|
+
mime_type?: "image/jpeg" | "image/png" | "image/jpg" | "image/webp" | undefined;
|
|
42
|
+
}>, {
|
|
43
|
+
filename: string;
|
|
44
|
+
byte_size: number;
|
|
45
|
+
width?: number | undefined;
|
|
46
|
+
height?: number | undefined;
|
|
47
|
+
md5?: string | undefined;
|
|
48
|
+
mime_type?: "image/jpeg" | "image/png" | "image/jpg" | "image/webp" | undefined;
|
|
49
|
+
}, {
|
|
50
|
+
filename: string;
|
|
51
|
+
byte_size: number;
|
|
52
|
+
width?: number | undefined;
|
|
53
|
+
height?: number | undefined;
|
|
54
|
+
md5?: string | undefined;
|
|
55
|
+
mime_type?: "image/jpeg" | "image/png" | "image/jpg" | "image/webp" | undefined;
|
|
42
56
|
}>;
|
|
43
57
|
export type CreateImageFilePayload = z.infer<typeof CreateImageFilePayload>;
|
|
44
58
|
export interface CreateImageFileResult {
|
|
@@ -60,14 +74,37 @@ export interface CreateImageFileResult {
|
|
|
60
74
|
md5: string | null;
|
|
61
75
|
}
|
|
62
76
|
export interface LookupImageFileByMd5Result {
|
|
77
|
+
/**
|
|
78
|
+
* Whether the image file has been fully uploaded.
|
|
79
|
+
*/
|
|
63
80
|
complete: boolean | null;
|
|
81
|
+
/**
|
|
82
|
+
* The byte size of the image file.
|
|
83
|
+
*/
|
|
64
84
|
byte_size: number;
|
|
85
|
+
/**
|
|
86
|
+
* The id of the image file.
|
|
87
|
+
*/
|
|
65
88
|
id: string;
|
|
89
|
+
/**
|
|
90
|
+
* md5 hash of the image file.
|
|
91
|
+
*/
|
|
66
92
|
md5: string | null;
|
|
93
|
+
/**
|
|
94
|
+
* The height of the image file in pixels.
|
|
95
|
+
*/
|
|
96
|
+
height: number | null;
|
|
97
|
+
/**
|
|
98
|
+
* The width of the image file in pixels.
|
|
99
|
+
*/
|
|
100
|
+
width: number | null;
|
|
101
|
+
}
|
|
102
|
+
export interface GetImageFileMetadataResult extends LookupImageFileByMd5Result {
|
|
67
103
|
}
|
|
68
104
|
export declare const createImageFile: (client: Client, payload: CreateImageFilePayload) => Promise<CreateImageFileResult>;
|
|
69
105
|
export declare const uploadImageFile: (client: Client, uploadDetails: {
|
|
70
106
|
id: string;
|
|
71
107
|
byte_size: number;
|
|
72
|
-
}, fileStream: ReadableStream) => import('../uploadChunks.js').IteratorWithPromise<import('../uploadChunks.js').UploadChunkEvent>;
|
|
108
|
+
}, fileStream: ReadableStream, chunkSizeBytes?: number) => import('../uploadChunks.js').IteratorWithPromise<import('../uploadChunks.js').UploadChunkEvent>;
|
|
109
|
+
export declare const getImageFileMetadata: (client: Client, id: string) => Promise<GetImageFileMetadataResult | null>;
|
|
73
110
|
export declare const lookupImageFileByMd5: (client: Client, md5: string) => Promise<LookupImageFileByMd5Result | null>;
|
|
@@ -1,25 +1,32 @@
|
|
|
1
1
|
import debug from "debug";
|
|
2
|
+
import mime 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 acceptedTypes = z.enum([
|
|
8
|
+
"image/jpeg",
|
|
9
|
+
"image/png",
|
|
10
|
+
"image/jpg",
|
|
11
|
+
"image/webp"
|
|
12
|
+
]);
|
|
6
13
|
const CreateImageFilePayload = z.object({
|
|
7
14
|
/**
|
|
8
15
|
* The md5 hash of the image file.
|
|
9
16
|
*/
|
|
10
|
-
md5: z.string().
|
|
17
|
+
md5: z.string().optional(),
|
|
11
18
|
/**
|
|
12
19
|
* The height of the image file in pixels.
|
|
13
20
|
*/
|
|
14
|
-
height: z.number().int().
|
|
21
|
+
height: z.number().int().optional(),
|
|
15
22
|
/**
|
|
16
23
|
* The width of the image file in pixels.
|
|
17
24
|
*/
|
|
18
|
-
width: z.number().int().
|
|
25
|
+
width: z.number().int().optional(),
|
|
19
26
|
/**
|
|
20
|
-
* The mime type of the image file.
|
|
27
|
+
* The mime type of the image file. Optional if the filename has a known file extension.
|
|
21
28
|
*/
|
|
22
|
-
mime_type:
|
|
29
|
+
mime_type: acceptedTypes.optional(),
|
|
23
30
|
/**
|
|
24
31
|
* The filename of the image file.
|
|
25
32
|
*/
|
|
@@ -28,6 +35,19 @@ const CreateImageFilePayload = z.object({
|
|
|
28
35
|
* The byte size of the image file.
|
|
29
36
|
*/
|
|
30
37
|
byte_size: z.number().int().max(MAX_IMAGE_SIZE)
|
|
38
|
+
}).superRefine((data, ctx) => {
|
|
39
|
+
const mimeType = mime.lookup(data.filename);
|
|
40
|
+
const parsedMimeType = acceptedTypes.safeParse(mimeType).data;
|
|
41
|
+
if (parsedMimeType) {
|
|
42
|
+
data.mime_type = parsedMimeType;
|
|
43
|
+
}
|
|
44
|
+
if (!parsedMimeType && !data.mime_type) {
|
|
45
|
+
ctx.addIssue({
|
|
46
|
+
code: z.ZodIssueCode.custom,
|
|
47
|
+
message: "mime_type is required when filename extension doesn't match a known image type",
|
|
48
|
+
path: ["mime_type"]
|
|
49
|
+
});
|
|
50
|
+
}
|
|
31
51
|
});
|
|
32
52
|
const createImageFile = async (client, payload) => {
|
|
33
53
|
log("Creating image file", payload);
|
|
@@ -44,15 +64,28 @@ const createImageFile = async (client, payload) => {
|
|
|
44
64
|
`Failed to create file ${response.status} ${response.statusText}`
|
|
45
65
|
);
|
|
46
66
|
};
|
|
47
|
-
const uploadImageFile = (client, uploadDetails, fileStream) => {
|
|
67
|
+
const uploadImageFile = (client, uploadDetails, fileStream, chunkSizeBytes) => {
|
|
48
68
|
log("Uploading image file", uploadDetails.id);
|
|
49
69
|
return uploadChunks(client, {
|
|
50
70
|
url: `/api/v1/image_files/${uploadDetails.id}/upload`,
|
|
51
71
|
fileSize: uploadDetails.byte_size,
|
|
52
72
|
fileStream,
|
|
53
|
-
maxSize: MAX_IMAGE_SIZE
|
|
73
|
+
maxSize: MAX_IMAGE_SIZE,
|
|
74
|
+
chunkSizeBytes
|
|
54
75
|
});
|
|
55
76
|
};
|
|
77
|
+
const getImageFileMetadata = async (client, id) => {
|
|
78
|
+
const response = await client.authenticatedFetch(
|
|
79
|
+
`/api/v1/image_files/${id}.json`,
|
|
80
|
+
{
|
|
81
|
+
method: "GET"
|
|
82
|
+
}
|
|
83
|
+
);
|
|
84
|
+
if (response.ok) {
|
|
85
|
+
return await response.json();
|
|
86
|
+
}
|
|
87
|
+
return null;
|
|
88
|
+
};
|
|
56
89
|
const lookupImageFileByMd5 = async (client, md5) => {
|
|
57
90
|
const response = await client.authenticatedFetch(
|
|
58
91
|
`/api/v1/image_files/md5/${md5}`,
|
|
@@ -74,6 +107,7 @@ const lookupImageFileByMd5 = async (client, md5) => {
|
|
|
74
107
|
export {
|
|
75
108
|
CreateImageFilePayload,
|
|
76
109
|
createImageFile,
|
|
110
|
+
getImageFileMetadata,
|
|
77
111
|
lookupImageFileByMd5,
|
|
78
112
|
uploadImageFile
|
|
79
113
|
};
|
|
@@ -53,6 +53,7 @@ export interface LookupRenderByMd5Result {
|
|
|
53
53
|
id: string;
|
|
54
54
|
md5: string | null;
|
|
55
55
|
status: "complete" | "created" | "failed" | "pending" | "rendering" | string;
|
|
56
|
+
metadata: Record<string, string>;
|
|
56
57
|
}
|
|
57
58
|
export declare const createRender: (client: Client, payload: CreateRenderPayload) => Promise<CreateRenderResult>;
|
|
58
59
|
export declare const uploadRender: (client: Client, renderId: string, fileStream: ReadableStream) => Promise<any>;
|
package/dist/uploadChunks.js
CHANGED
|
@@ -49,6 +49,7 @@ function uploadChunks(client, {
|
|
|
49
49
|
}
|
|
50
50
|
log("Checking upload status", url);
|
|
51
51
|
const uploadStatus = await client.authenticatedFetch(url);
|
|
52
|
+
console.log("UPLOAD STATUS", url, uploadStatus);
|
|
52
53
|
yield { type: "progress", progress: 0 };
|
|
53
54
|
if (uploadStatus.status === 200) {
|
|
54
55
|
log("Chunk already uploaded");
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@editframe/api",
|
|
3
|
-
"version": "0.15.0-beta.
|
|
3
|
+
"version": "0.15.0-beta.19",
|
|
4
4
|
"description": "API functions for EditFrame",
|
|
5
5
|
"exports": {
|
|
6
6
|
".": {
|
|
@@ -38,23 +38,25 @@
|
|
|
38
38
|
"license": "UNLICENSED",
|
|
39
39
|
"devDependencies": {
|
|
40
40
|
"@types/jsonwebtoken": "^9.0.6",
|
|
41
|
+
"@types/mime-types": "^2.1.4",
|
|
41
42
|
"@types/node": "^20.14.13",
|
|
42
43
|
"typedoc": "^0.26.5",
|
|
43
44
|
"typescript": "^5.5.4",
|
|
44
45
|
"vite-plugin-dts": "^4.0.3"
|
|
45
46
|
},
|
|
46
47
|
"dependencies": {
|
|
47
|
-
"@editframe/assets": "0.15.0-beta.
|
|
48
|
+
"@editframe/assets": "0.15.0-beta.19",
|
|
48
49
|
"@vitejs/plugin-react": "^4.3.4",
|
|
49
|
-
"vite-tsconfig-paths": "^4.3.2",
|
|
50
|
-
"vite": "^5.4.11",
|
|
51
50
|
"debug": "^4.3.5",
|
|
52
51
|
"eventsource-parser": "^3.0.0",
|
|
53
52
|
"jsonwebtoken": "^9.0.2",
|
|
54
53
|
"mime": "^4.0.4",
|
|
54
|
+
"mime-types": "^2.1.35",
|
|
55
55
|
"node-fetch": "^3.3.2",
|
|
56
56
|
"tar": "^7.4.3",
|
|
57
|
+
"vite": "^5.4.11",
|
|
57
58
|
"vite-plugin-singlefile": "^2.1.0",
|
|
59
|
+
"vite-tsconfig-paths": "^4.3.2",
|
|
58
60
|
"zod": "^3.23.8"
|
|
59
61
|
}
|
|
60
62
|
}
|
|
@@ -6,6 +6,7 @@ import { ZodError } from "zod";
|
|
|
6
6
|
import { Client } from "../client.js";
|
|
7
7
|
import { webReadableFromBuffers } from "../readableFromBuffers.js";
|
|
8
8
|
import {
|
|
9
|
+
CreateImageFilePayload,
|
|
9
10
|
createImageFile,
|
|
10
11
|
lookupImageFileByMd5,
|
|
11
12
|
uploadImageFile,
|
|
@@ -19,6 +20,28 @@ const UploadMustContinue = (id = "test-file") =>
|
|
|
19
20
|
HttpResponse.json({}, { status: 202 }),
|
|
20
21
|
);
|
|
21
22
|
|
|
23
|
+
describe("CreateImageFilePayload", () => {
|
|
24
|
+
test("parses mime type from filename", () => {
|
|
25
|
+
const payload = CreateImageFilePayload.parse({
|
|
26
|
+
byte_size: 100,
|
|
27
|
+
filename: "test.jpg",
|
|
28
|
+
});
|
|
29
|
+
|
|
30
|
+
expect(payload.mime_type).toBe("image/jpeg");
|
|
31
|
+
});
|
|
32
|
+
|
|
33
|
+
test("rejects unsupported mime types", () => {
|
|
34
|
+
const payload = CreateImageFilePayload.safeParse({
|
|
35
|
+
byte_size: 100,
|
|
36
|
+
filename: "test.txt",
|
|
37
|
+
});
|
|
38
|
+
|
|
39
|
+
expect(
|
|
40
|
+
payload.error?.issues.some((issue) => issue.path.includes("mime_type")),
|
|
41
|
+
).toBe(true);
|
|
42
|
+
});
|
|
43
|
+
});
|
|
44
|
+
|
|
22
45
|
describe("ImageFile", () => {
|
|
23
46
|
beforeAll(() => server.listen());
|
|
24
47
|
afterEach(() => server.resetHandlers());
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import debug from "debug";
|
|
2
|
+
import mime from "mime-types";
|
|
2
3
|
import { z } from "zod";
|
|
3
4
|
|
|
4
5
|
import type { Client } from "../client.js";
|
|
@@ -8,32 +9,57 @@ const log = debug("ef:api:image-file");
|
|
|
8
9
|
|
|
9
10
|
const MAX_IMAGE_SIZE = 1024 * 1024 * 16; // 16MB
|
|
10
11
|
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
12
|
+
const acceptedTypes = z.enum([
|
|
13
|
+
"image/jpeg",
|
|
14
|
+
"image/png",
|
|
15
|
+
"image/jpg",
|
|
16
|
+
"image/webp",
|
|
17
|
+
]);
|
|
18
|
+
|
|
19
|
+
export const CreateImageFilePayload = z
|
|
20
|
+
.object({
|
|
21
|
+
/**
|
|
22
|
+
* The md5 hash of the image file.
|
|
23
|
+
*/
|
|
24
|
+
md5: z.string().optional(),
|
|
25
|
+
/**
|
|
26
|
+
* The height of the image file in pixels.
|
|
27
|
+
*/
|
|
28
|
+
height: z.number().int().optional(),
|
|
29
|
+
/**
|
|
30
|
+
* The width of the image file in pixels.
|
|
31
|
+
*/
|
|
32
|
+
width: z.number().int().optional(),
|
|
33
|
+
/**
|
|
34
|
+
* The mime type of the image file. Optional if the filename has a known file extension.
|
|
35
|
+
*/
|
|
36
|
+
mime_type: acceptedTypes.optional(),
|
|
37
|
+
/**
|
|
38
|
+
* The filename of the image file.
|
|
39
|
+
*/
|
|
40
|
+
filename: z.string(),
|
|
41
|
+
/**
|
|
42
|
+
* The byte size of the image file.
|
|
43
|
+
*/
|
|
44
|
+
byte_size: z.number().int().max(MAX_IMAGE_SIZE),
|
|
45
|
+
})
|
|
46
|
+
.superRefine((data, ctx) => {
|
|
47
|
+
const mimeType = mime.lookup(data.filename);
|
|
48
|
+
const parsedMimeType = acceptedTypes.safeParse(mimeType).data;
|
|
49
|
+
|
|
50
|
+
if (parsedMimeType) {
|
|
51
|
+
data.mime_type = parsedMimeType;
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
if (!parsedMimeType && !data.mime_type) {
|
|
55
|
+
ctx.addIssue({
|
|
56
|
+
code: z.ZodIssueCode.custom,
|
|
57
|
+
message:
|
|
58
|
+
"mime_type is required when filename extension doesn't match a known image type",
|
|
59
|
+
path: ["mime_type"],
|
|
60
|
+
});
|
|
61
|
+
}
|
|
62
|
+
});
|
|
37
63
|
|
|
38
64
|
export type CreateImageFilePayload = z.infer<typeof CreateImageFilePayload>;
|
|
39
65
|
|
|
@@ -57,12 +83,35 @@ export interface CreateImageFileResult {
|
|
|
57
83
|
}
|
|
58
84
|
|
|
59
85
|
export interface LookupImageFileByMd5Result {
|
|
86
|
+
/**
|
|
87
|
+
* Whether the image file has been fully uploaded.
|
|
88
|
+
*/
|
|
60
89
|
complete: boolean | null;
|
|
90
|
+
/**
|
|
91
|
+
* The byte size of the image file.
|
|
92
|
+
*/
|
|
61
93
|
byte_size: number;
|
|
94
|
+
/**
|
|
95
|
+
* The id of the image file.
|
|
96
|
+
*/
|
|
62
97
|
id: string;
|
|
98
|
+
/**
|
|
99
|
+
* md5 hash of the image file.
|
|
100
|
+
*/
|
|
63
101
|
md5: string | null;
|
|
102
|
+
/**
|
|
103
|
+
* The height of the image file in pixels.
|
|
104
|
+
*/
|
|
105
|
+
height: number | null;
|
|
106
|
+
/**
|
|
107
|
+
* The width of the image file in pixels.
|
|
108
|
+
*/
|
|
109
|
+
width: number | null;
|
|
64
110
|
}
|
|
65
111
|
|
|
112
|
+
export interface GetImageFileMetadataResult
|
|
113
|
+
extends LookupImageFileByMd5Result {}
|
|
114
|
+
|
|
66
115
|
export const createImageFile = async (
|
|
67
116
|
client: Client,
|
|
68
117
|
payload: CreateImageFilePayload,
|
|
@@ -92,6 +141,7 @@ export const uploadImageFile = (
|
|
|
92
141
|
byte_size: number;
|
|
93
142
|
},
|
|
94
143
|
fileStream: ReadableStream,
|
|
144
|
+
chunkSizeBytes?: number,
|
|
95
145
|
) => {
|
|
96
146
|
log("Uploading image file", uploadDetails.id);
|
|
97
147
|
|
|
@@ -100,9 +150,28 @@ export const uploadImageFile = (
|
|
|
100
150
|
fileSize: uploadDetails.byte_size,
|
|
101
151
|
fileStream,
|
|
102
152
|
maxSize: MAX_IMAGE_SIZE,
|
|
153
|
+
chunkSizeBytes,
|
|
103
154
|
});
|
|
104
155
|
};
|
|
105
156
|
|
|
157
|
+
export const getImageFileMetadata = async (
|
|
158
|
+
client: Client,
|
|
159
|
+
id: string,
|
|
160
|
+
): Promise<GetImageFileMetadataResult | null> => {
|
|
161
|
+
const response = await client.authenticatedFetch(
|
|
162
|
+
`/api/v1/image_files/${id}.json`,
|
|
163
|
+
{
|
|
164
|
+
method: "GET",
|
|
165
|
+
},
|
|
166
|
+
);
|
|
167
|
+
|
|
168
|
+
if (response.ok) {
|
|
169
|
+
return (await response.json()) as LookupImageFileByMd5Result;
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
return null;
|
|
173
|
+
};
|
|
174
|
+
|
|
106
175
|
export const lookupImageFileByMd5 = async (
|
|
107
176
|
client: Client,
|
|
108
177
|
md5: string,
|
package/src/resources/renders.ts
CHANGED