comfyui-mcp 0.7.0 → 0.8.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.
- package/CHANGELOG.md +52 -0
- package/README.md +12 -0
- package/ROADMAP.md +15 -0
- package/dist/services/download-auth.d.ts +7 -0
- package/dist/services/download-auth.d.ts.map +1 -1
- package/dist/services/download-auth.js +26 -1
- package/dist/services/download-auth.js.map +1 -1
- package/dist/services/download-cache.d.ts +3 -1
- package/dist/services/download-cache.d.ts.map +1 -1
- package/dist/services/download-cache.js +45 -9
- package/dist/services/download-cache.js.map +1 -1
- package/dist/services/image-convert.d.ts +29 -0
- package/dist/services/image-convert.d.ts.map +1 -0
- package/dist/services/image-convert.js +218 -0
- package/dist/services/image-convert.js.map +1 -0
- package/dist/services/manifest.d.ts +63 -0
- package/dist/services/manifest.d.ts.map +1 -0
- package/dist/services/manifest.js +333 -0
- package/dist/services/manifest.js.map +1 -0
- package/dist/services/model-resolver.d.ts.map +1 -1
- package/dist/services/model-resolver.js +7 -1
- package/dist/services/model-resolver.js.map +1 -1
- package/dist/services/node-authoring.d.ts +5 -0
- package/dist/services/node-authoring.d.ts.map +1 -1
- package/dist/services/node-authoring.js +56 -0
- package/dist/services/node-authoring.js.map +1 -1
- package/dist/services/node-verify.d.ts +35 -0
- package/dist/services/node-verify.d.ts.map +1 -0
- package/dist/services/node-verify.js +138 -0
- package/dist/services/node-verify.js.map +1 -0
- package/dist/services/skill-cache.d.ts +26 -0
- package/dist/services/skill-cache.d.ts.map +1 -0
- package/dist/services/skill-cache.js +172 -0
- package/dist/services/skill-cache.js.map +1 -0
- package/dist/services/storage/azure-blob.d.ts +8 -0
- package/dist/services/storage/azure-blob.d.ts.map +1 -0
- package/dist/services/storage/azure-blob.js +146 -0
- package/dist/services/storage/azure-blob.js.map +1 -0
- package/dist/services/storage/hf.d.ts +7 -0
- package/dist/services/storage/hf.d.ts.map +1 -0
- package/dist/services/storage/hf.js +80 -0
- package/dist/services/storage/hf.js.map +1 -0
- package/dist/services/storage/http.d.ts +6 -0
- package/dist/services/storage/http.d.ts.map +1 -0
- package/dist/services/storage/http.js +41 -0
- package/dist/services/storage/http.js.map +1 -0
- package/dist/services/storage/index.d.ts +28 -0
- package/dist/services/storage/index.d.ts.map +1 -0
- package/dist/services/storage/index.js +42 -0
- package/dist/services/storage/index.js.map +1 -0
- package/dist/services/storage/s3.d.ts +12 -0
- package/dist/services/storage/s3.d.ts.map +1 -0
- package/dist/services/storage/s3.js +84 -0
- package/dist/services/storage/s3.js.map +1 -0
- package/dist/services/storage/types.d.ts +22 -0
- package/dist/services/storage/types.d.ts.map +1 -0
- package/dist/services/storage/types.js +2 -0
- package/dist/services/storage/types.js.map +1 -0
- package/dist/services/storage/utils.d.ts +6 -0
- package/dist/services/storage/utils.d.ts.map +1 -0
- package/dist/services/storage/utils.js +39 -0
- package/dist/services/storage/utils.js.map +1 -0
- package/dist/services/storage-upload.d.ts +18 -0
- package/dist/services/storage-upload.d.ts.map +1 -0
- package/dist/services/storage-upload.js +121 -0
- package/dist/services/storage-upload.js.map +1 -0
- package/dist/tools/image-convert.d.ts +3 -0
- package/dist/tools/image-convert.d.ts.map +1 -0
- package/dist/tools/image-convert.js +58 -0
- package/dist/tools/image-convert.js.map +1 -0
- package/dist/tools/index.d.ts.map +1 -1
- package/dist/tools/index.js +8 -0
- package/dist/tools/index.js.map +1 -1
- package/dist/tools/manifest.d.ts +3 -0
- package/dist/tools/manifest.d.ts.map +1 -0
- package/dist/tools/manifest.js +25 -0
- package/dist/tools/manifest.js.map +1 -0
- package/dist/tools/model-management.d.ts.map +1 -1
- package/dist/tools/model-management.js +9 -1
- package/dist/tools/model-management.js.map +1 -1
- package/dist/tools/node-authoring.d.ts.map +1 -1
- package/dist/tools/node-authoring.js +8 -2
- package/dist/tools/node-authoring.js.map +1 -1
- package/dist/tools/node-verify.d.ts +3 -0
- package/dist/tools/node-verify.d.ts.map +1 -0
- package/dist/tools/node-verify.js +42 -0
- package/dist/tools/node-verify.js.map +1 -0
- package/dist/tools/skill-generator.d.ts.map +1 -1
- package/dist/tools/skill-generator.js +16 -3
- package/dist/tools/skill-generator.js.map +1 -1
- package/dist/tools/storage-upload.d.ts +3 -0
- package/dist/tools/storage-upload.d.ts.map +1 -0
- package/dist/tools/storage-upload.js +57 -0
- package/dist/tools/storage-upload.js.map +1 -0
- package/package.json +5 -1
- package/scripts/gen-tool-docs.ts +6 -5
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
import { execFile } from "node:child_process";
|
|
2
|
+
import { mkdtemp, rm, writeFile } from "node:fs/promises";
|
|
3
|
+
import { tmpdir } from "node:os";
|
|
4
|
+
import { basename, join } from "node:path";
|
|
5
|
+
import { promisify } from "node:util";
|
|
6
|
+
import { ModelError, ValidationError } from "../../utils/errors.js";
|
|
7
|
+
import { withPrefix } from "./utils.js";
|
|
8
|
+
const execFileAsync = promisify(execFile);
|
|
9
|
+
const ASCII_CONTROL_RE = /[\x00-\x1F\x7F]/;
|
|
10
|
+
async function findHfCli() {
|
|
11
|
+
for (const command of ["hf", "huggingface-cli"]) {
|
|
12
|
+
try {
|
|
13
|
+
await execFileAsync(command, ["--version"]);
|
|
14
|
+
return command;
|
|
15
|
+
}
|
|
16
|
+
catch {
|
|
17
|
+
// Try the next known CLI name.
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
throw new ValidationError("hf upload requires the hf CLI. Install and authenticate `hf` or `huggingface-cli` first.");
|
|
21
|
+
}
|
|
22
|
+
function validateRepo(repo) {
|
|
23
|
+
if (!/^[A-Za-z0-9][A-Za-z0-9._-]*\/[A-Za-z0-9][A-Za-z0-9._-]*$/.test(repo)) {
|
|
24
|
+
throw new ValidationError("hf.repo must be in owner/name format.");
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
function validateRemotePath(path) {
|
|
28
|
+
if (ASCII_CONTROL_RE.test(path)) {
|
|
29
|
+
throw new ValidationError("hf remote path cannot contain ASCII control characters.");
|
|
30
|
+
}
|
|
31
|
+
for (const segment of path.split("/")) {
|
|
32
|
+
if (segment === "..") {
|
|
33
|
+
throw new ValidationError("hf remote path cannot contain '..' segments.");
|
|
34
|
+
}
|
|
35
|
+
if (segment.startsWith("-")) {
|
|
36
|
+
throw new ValidationError("hf remote path segments cannot start with '-'.");
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
export async function uploadHfFile(source, destination) {
|
|
41
|
+
validateRepo(destination.repo);
|
|
42
|
+
const repoType = destination.repo_type ?? "model";
|
|
43
|
+
const remotePath = withPrefix(destination.path, source.filename);
|
|
44
|
+
validateRemotePath(remotePath);
|
|
45
|
+
const command = await findHfCli();
|
|
46
|
+
let tempDir;
|
|
47
|
+
let localPath = source.path;
|
|
48
|
+
try {
|
|
49
|
+
if (!localPath) {
|
|
50
|
+
tempDir = await mkdtemp(join(tmpdir(), "comfyui-mcp-hf-upload-"));
|
|
51
|
+
localPath = join(tempDir, basename(source.filename));
|
|
52
|
+
await writeFile(localPath, source.data ?? Buffer.alloc(0));
|
|
53
|
+
}
|
|
54
|
+
const args = ["upload"];
|
|
55
|
+
if (repoType !== "model")
|
|
56
|
+
args.push("--repo-type", repoType);
|
|
57
|
+
args.push("--", destination.repo, localPath, remotePath);
|
|
58
|
+
await execFileAsync(command, args);
|
|
59
|
+
const prefix = repoType === "dataset" ? "datasets/" : repoType === "space" ? "spaces/" : "";
|
|
60
|
+
return {
|
|
61
|
+
provider: "hf",
|
|
62
|
+
url: `https://huggingface.co/${prefix}${destination.repo}/blob/main/${remotePath}`,
|
|
63
|
+
};
|
|
64
|
+
}
|
|
65
|
+
catch (err) {
|
|
66
|
+
if (err instanceof ValidationError)
|
|
67
|
+
throw err;
|
|
68
|
+
throw new ModelError("hf upload failed", {
|
|
69
|
+
name: err instanceof Error ? err.name : undefined,
|
|
70
|
+
code: typeof err?.code === "string"
|
|
71
|
+
? err.code
|
|
72
|
+
: undefined,
|
|
73
|
+
});
|
|
74
|
+
}
|
|
75
|
+
finally {
|
|
76
|
+
if (tempDir)
|
|
77
|
+
await rm(tempDir, { recursive: true, force: true }).catch(() => undefined);
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
//# sourceMappingURL=hf.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"hf.js","sourceRoot":"","sources":["../../../src/services/storage/hf.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import type { StorageUploadResult, StorageUploadSource } from "./types.js";
|
|
2
|
+
export declare function isHttpUrl(url: string): boolean;
|
|
3
|
+
export declare function uploadHttpFile(source: StorageUploadSource, destination: {
|
|
4
|
+
url: string;
|
|
5
|
+
}): Promise<StorageUploadResult>;
|
|
6
|
+
//# sourceMappingURL=http.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"http.d.ts","sourceRoot":"","sources":["../../../src/services/storage/http.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,mBAAmB,EAAE,mBAAmB,EAAE,MAAM,YAAY,CAAC;AAE3E,wBAAgB,SAAS,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAE9C;AAUD,wBAAsB,cAAc,CAClC,MAAM,EAAE,mBAAmB,EAC3B,WAAW,EAAE;IAAE,GAAG,EAAE,MAAM,CAAA;CAAE,GAC3B,OAAO,CAAC,mBAAmB,CAAC,CAyB9B"}
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
import { createReadStream } from "node:fs";
|
|
2
|
+
import { ModelError } from "../../utils/errors.js";
|
|
3
|
+
import { redactUrlForLogs } from "../download-auth.js";
|
|
4
|
+
export function isHttpUrl(url) {
|
|
5
|
+
return url.startsWith("http://") || url.startsWith("https://");
|
|
6
|
+
}
|
|
7
|
+
function redactedRedirectLocation(location, baseUrl) {
|
|
8
|
+
try {
|
|
9
|
+
return redactUrlForLogs(new URL(location, baseUrl).toString());
|
|
10
|
+
}
|
|
11
|
+
catch {
|
|
12
|
+
return "[INVALID_REDIRECT_LOCATION]";
|
|
13
|
+
}
|
|
14
|
+
}
|
|
15
|
+
export async function uploadHttpFile(source, destination) {
|
|
16
|
+
const init = {
|
|
17
|
+
method: "PUT",
|
|
18
|
+
redirect: "manual",
|
|
19
|
+
headers: source.contentType ? { "Content-Type": source.contentType } : undefined,
|
|
20
|
+
body: (source.path ? createReadStream(source.path) : source.data),
|
|
21
|
+
};
|
|
22
|
+
if (source.path)
|
|
23
|
+
init.duplex = "half";
|
|
24
|
+
const response = await fetch(destination.url, init);
|
|
25
|
+
if (response.status >= 300 && response.status < 400) {
|
|
26
|
+
const location = response.headers.get("location");
|
|
27
|
+
throw new ModelError(`HTTP upload redirect rejected: ${response.status} ${response.statusText}`, {
|
|
28
|
+
url: redactUrlForLogs(destination.url),
|
|
29
|
+
status: response.status,
|
|
30
|
+
location: location ? redactedRedirectLocation(location, destination.url) : undefined,
|
|
31
|
+
});
|
|
32
|
+
}
|
|
33
|
+
if (!response.ok) {
|
|
34
|
+
throw new ModelError(`HTTP upload failed: ${response.status} ${response.statusText}`, {
|
|
35
|
+
url: redactUrlForLogs(destination.url),
|
|
36
|
+
status: response.status,
|
|
37
|
+
});
|
|
38
|
+
}
|
|
39
|
+
return { provider: "http", url: redactUrlForLogs(destination.url) };
|
|
40
|
+
}
|
|
41
|
+
//# sourceMappingURL=http.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"http.js","sourceRoot":"","sources":["../../../src/services/storage/http.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,gBAAgB,EAAE,MAAM,SAAS,CAAC;AAC3C,OAAO,EAAE,UAAU,EAAE,MAAM,uBAAuB,CAAC;AACnD,OAAO,EAAE,gBAAgB,EAAE,MAAM,qBAAqB,CAAC;AAGvD,MAAM,UAAU,SAAS,CAAC,GAAW;IACnC,OAAO,GAAG,CAAC,UAAU,CAAC,SAAS,CAAC,IAAI,GAAG,CAAC,UAAU,CAAC,UAAU,CAAC,CAAC;AACjE,CAAC;AAED,SAAS,wBAAwB,CAAC,QAAgB,EAAE,OAAe;IACjE,IAAI,CAAC;QACH,OAAO,gBAAgB,CAAC,IAAI,GAAG,CAAC,QAAQ,EAAE,OAAO,CAAC,CAAC,QAAQ,EAAE,CAAC,CAAC;IACjE,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,6BAA6B,CAAC;IACvC,CAAC;AACH,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,cAAc,CAClC,MAA2B,EAC3B,WAA4B;IAE5B,MAAM,IAAI,GAAsC;QAC9C,MAAM,EAAE,KAAK;QACb,QAAQ,EAAE,QAAQ;QAClB,OAAO,EAAE,MAAM,CAAC,WAAW,CAAC,CAAC,CAAC,EAAE,cAAc,EAAE,MAAM,CAAC,WAAW,EAAE,CAAC,CAAC,CAAC,SAAS;QAChF,IAAI,EAAE,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC,gBAAgB,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,IAAI,CAAmC;KACpG,CAAC;IACF,IAAI,MAAM,CAAC,IAAI;QAAE,IAAI,CAAC,MAAM,GAAG,MAAM,CAAC;IAEtC,MAAM,QAAQ,GAAG,MAAM,KAAK,CAAC,WAAW,CAAC,GAAG,EAAE,IAAI,CAAC,CAAC;IACpD,IAAI,QAAQ,CAAC,MAAM,IAAI,GAAG,IAAI,QAAQ,CAAC,MAAM,GAAG,GAAG,EAAE,CAAC;QACpD,MAAM,QAAQ,GAAG,QAAQ,CAAC,OAAO,CAAC,GAAG,CAAC,UAAU,CAAC,CAAC;QAClD,MAAM,IAAI,UAAU,CAAC,kCAAkC,QAAQ,CAAC,MAAM,IAAI,QAAQ,CAAC,UAAU,EAAE,EAAE;YAC/F,GAAG,EAAE,gBAAgB,CAAC,WAAW,CAAC,GAAG,CAAC;YACtC,MAAM,EAAE,QAAQ,CAAC,MAAM;YACvB,QAAQ,EAAE,QAAQ,CAAC,CAAC,CAAC,wBAAwB,CAAC,QAAQ,EAAE,WAAW,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,SAAS;SACrF,CAAC,CAAC;IACL,CAAC;IACD,IAAI,CAAC,QAAQ,CAAC,EAAE,EAAE,CAAC;QACjB,MAAM,IAAI,UAAU,CAAC,uBAAuB,QAAQ,CAAC,MAAM,IAAI,QAAQ,CAAC,UAAU,EAAE,EAAE;YACpF,GAAG,EAAE,gBAAgB,CAAC,WAAW,CAAC,GAAG,CAAC;YACtC,MAAM,EAAE,QAAQ,CAAC,MAAM;SACxB,CAAC,CAAC;IACL,CAAC;IACD,OAAO,EAAE,QAAQ,EAAE,MAAM,EAAE,GAAG,EAAE,gBAAgB,CAAC,WAAW,CAAC,GAAG,CAAC,EAAE,CAAC;AACtE,CAAC"}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import type { CloudStorageAuth, StorageUploadResult, StorageUploadSource } from "./types.js";
|
|
2
|
+
export type UploadDestination = {
|
|
3
|
+
s3: {
|
|
4
|
+
bucket: string;
|
|
5
|
+
prefix?: string;
|
|
6
|
+
async?: boolean;
|
|
7
|
+
};
|
|
8
|
+
} | {
|
|
9
|
+
azure: {
|
|
10
|
+
container: string;
|
|
11
|
+
blob_prefix?: string;
|
|
12
|
+
};
|
|
13
|
+
} | {
|
|
14
|
+
http: {
|
|
15
|
+
url: string;
|
|
16
|
+
};
|
|
17
|
+
} | {
|
|
18
|
+
hf: {
|
|
19
|
+
repo: string;
|
|
20
|
+
repo_type?: "model" | "dataset" | "space";
|
|
21
|
+
path?: string;
|
|
22
|
+
};
|
|
23
|
+
};
|
|
24
|
+
export declare function supportsCloudDownload(url: string): boolean;
|
|
25
|
+
export declare function downloadCloudUrlToFile(url: string, targetPath: string, auth?: CloudStorageAuth): Promise<void>;
|
|
26
|
+
export declare function uploadToStorage(source: StorageUploadSource, destination: UploadDestination, auth?: CloudStorageAuth): Promise<StorageUploadResult>;
|
|
27
|
+
export type { CloudStorageAuth, S3Auth, StorageUploadResult, StorageUploadSource, } from "./types.js";
|
|
28
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/services/storage/index.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EACV,gBAAgB,EAChB,mBAAmB,EACnB,mBAAmB,EACpB,MAAM,YAAY,CAAC;AAEpB,MAAM,MAAM,iBAAiB,GACzB;IAAE,EAAE,EAAE;QAAE,MAAM,EAAE,MAAM,CAAC;QAAC,MAAM,CAAC,EAAE,MAAM,CAAC;QAAC,KAAK,CAAC,EAAE,OAAO,CAAA;KAAE,CAAA;CAAE,GAC5D;IAAE,KAAK,EAAE;QAAE,SAAS,EAAE,MAAM,CAAC;QAAC,WAAW,CAAC,EAAE,MAAM,CAAA;KAAE,CAAA;CAAE,GACtD;IAAE,IAAI,EAAE;QAAE,GAAG,EAAE,MAAM,CAAA;KAAE,CAAA;CAAE,GACzB;IAAE,EAAE,EAAE;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,SAAS,CAAC,EAAE,OAAO,GAAG,SAAS,GAAG,OAAO,CAAC;QAAC,IAAI,CAAC,EAAE,MAAM,CAAA;KAAE,CAAA;CAAE,CAAC;AAEvF,wBAAgB,qBAAqB,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAE1D;AAED,wBAAsB,sBAAsB,CAC1C,GAAG,EAAE,MAAM,EACX,UAAU,EAAE,MAAM,EAClB,IAAI,GAAE,gBAAqB,GAC1B,OAAO,CAAC,IAAI,CAAC,CAYf;AAED,wBAAsB,eAAe,CACnC,MAAM,EAAE,mBAAmB,EAC3B,WAAW,EAAE,iBAAiB,EAC9B,IAAI,GAAE,gBAAqB,GAC1B,OAAO,CAAC,mBAAmB,CAAC,CAuB9B;AAED,YAAY,EACV,gBAAgB,EAChB,MAAM,EACN,mBAAmB,EACnB,mBAAmB,GACpB,MAAM,YAAY,CAAC"}
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
import { ValidationError } from "../../utils/errors.js";
|
|
2
|
+
import { isAzureBlobUrl, downloadAzureBlobToFile, uploadAzureBlobFile } from "./azure-blob.js";
|
|
3
|
+
import { uploadHfFile } from "./hf.js";
|
|
4
|
+
import { isHttpUrl, uploadHttpFile } from "./http.js";
|
|
5
|
+
import { downloadS3ToFile, isS3Url, uploadS3File } from "./s3.js";
|
|
6
|
+
export function supportsCloudDownload(url) {
|
|
7
|
+
return isS3Url(url) || isAzureBlobUrl(url);
|
|
8
|
+
}
|
|
9
|
+
export async function downloadCloudUrlToFile(url, targetPath, auth = {}) {
|
|
10
|
+
if (isS3Url(url)) {
|
|
11
|
+
await downloadS3ToFile(url, targetPath, auth.s3);
|
|
12
|
+
return;
|
|
13
|
+
}
|
|
14
|
+
if (isAzureBlobUrl(url)) {
|
|
15
|
+
await downloadAzureBlobToFile(url, targetPath);
|
|
16
|
+
return;
|
|
17
|
+
}
|
|
18
|
+
throw new ValidationError("Unsupported cloud storage download URL. Expected s3://bucket/key or an Azure Blob URL.");
|
|
19
|
+
}
|
|
20
|
+
export async function uploadToStorage(source, destination, auth = {}) {
|
|
21
|
+
const keys = Object.keys(destination);
|
|
22
|
+
if (keys.length !== 1) {
|
|
23
|
+
throw new ValidationError("Provide exactly one upload destination: s3, azure, http, or hf.");
|
|
24
|
+
}
|
|
25
|
+
if ("s3" in destination) {
|
|
26
|
+
return uploadS3File(source, destination.s3, auth.s3);
|
|
27
|
+
}
|
|
28
|
+
if ("azure" in destination) {
|
|
29
|
+
return uploadAzureBlobFile(source, destination.azure);
|
|
30
|
+
}
|
|
31
|
+
if ("http" in destination) {
|
|
32
|
+
if (!isHttpUrl(destination.http.url)) {
|
|
33
|
+
throw new ValidationError("http.url must start with http:// or https://.");
|
|
34
|
+
}
|
|
35
|
+
return uploadHttpFile(source, destination.http);
|
|
36
|
+
}
|
|
37
|
+
if ("hf" in destination) {
|
|
38
|
+
return uploadHfFile(source, destination.hf);
|
|
39
|
+
}
|
|
40
|
+
throw new ValidationError("Unsupported upload destination. Expected s3, azure, http, or hf.");
|
|
41
|
+
}
|
|
42
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/services/storage/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,eAAe,EAAE,MAAM,uBAAuB,CAAC;AACxD,OAAO,EAAE,cAAc,EAAE,uBAAuB,EAAE,mBAAmB,EAAE,MAAM,iBAAiB,CAAC;AAC/F,OAAO,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AACvC,OAAO,EAAE,SAAS,EAAE,cAAc,EAAE,MAAM,WAAW,CAAC;AACtD,OAAO,EAAE,gBAAgB,EAAE,OAAO,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AAalE,MAAM,UAAU,qBAAqB,CAAC,GAAW;IAC/C,OAAO,OAAO,CAAC,GAAG,CAAC,IAAI,cAAc,CAAC,GAAG,CAAC,CAAC;AAC7C,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,sBAAsB,CAC1C,GAAW,EACX,UAAkB,EAClB,OAAyB,EAAE;IAE3B,IAAI,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC;QACjB,MAAM,gBAAgB,CAAC,GAAG,EAAE,UAAU,EAAE,IAAI,CAAC,EAAE,CAAC,CAAC;QACjD,OAAO;IACT,CAAC;IACD,IAAI,cAAc,CAAC,GAAG,CAAC,EAAE,CAAC;QACxB,MAAM,uBAAuB,CAAC,GAAG,EAAE,UAAU,CAAC,CAAC;QAC/C,OAAO;IACT,CAAC;IACD,MAAM,IAAI,eAAe,CACvB,wFAAwF,CACzF,CAAC;AACJ,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,eAAe,CACnC,MAA2B,EAC3B,WAA8B,EAC9B,OAAyB,EAAE;IAE3B,MAAM,IAAI,GAAG,MAAM,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC;IACtC,IAAI,IAAI,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QACtB,MAAM,IAAI,eAAe,CAAC,iEAAiE,CAAC,CAAC;IAC/F,CAAC;IAED,IAAI,IAAI,IAAI,WAAW,EAAE,CAAC;QACxB,OAAO,YAAY,CAAC,MAAM,EAAE,WAAW,CAAC,EAAE,EAAE,IAAI,CAAC,EAAE,CAAC,CAAC;IACvD,CAAC;IACD,IAAI,OAAO,IAAI,WAAW,EAAE,CAAC;QAC3B,OAAO,mBAAmB,CAAC,MAAM,EAAE,WAAW,CAAC,KAAK,CAAC,CAAC;IACxD,CAAC;IACD,IAAI,MAAM,IAAI,WAAW,EAAE,CAAC;QAC1B,IAAI,CAAC,SAAS,CAAC,WAAW,CAAC,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC;YACrC,MAAM,IAAI,eAAe,CAAC,+CAA+C,CAAC,CAAC;QAC7E,CAAC;QACD,OAAO,cAAc,CAAC,MAAM,EAAE,WAAW,CAAC,IAAI,CAAC,CAAC;IAClD,CAAC;IACD,IAAI,IAAI,IAAI,WAAW,EAAE,CAAC;QACxB,OAAO,YAAY,CAAC,MAAM,EAAE,WAAW,CAAC,EAAE,CAAC,CAAC;IAC9C,CAAC;IAED,MAAM,IAAI,eAAe,CAAC,kEAAkE,CAAC,CAAC;AAChG,CAAC"}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import type { S3Auth, StorageUploadResult, StorageUploadSource } from "./types.js";
|
|
2
|
+
export declare function isS3Url(url: string): boolean;
|
|
3
|
+
export declare function parseS3Url(url: string): {
|
|
4
|
+
bucket: string;
|
|
5
|
+
key: string;
|
|
6
|
+
};
|
|
7
|
+
export declare function downloadS3ToFile(url: string, targetPath: string, auth?: S3Auth): Promise<void>;
|
|
8
|
+
export declare function uploadS3File(source: StorageUploadSource, destination: {
|
|
9
|
+
bucket: string;
|
|
10
|
+
prefix?: string;
|
|
11
|
+
}, auth?: S3Auth): Promise<StorageUploadResult>;
|
|
12
|
+
//# sourceMappingURL=s3.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"s3.d.ts","sourceRoot":"","sources":["../../../src/services/storage/s3.ts"],"names":[],"mappings":"AAWA,OAAO,KAAK,EAAE,MAAM,EAAE,mBAAmB,EAAE,mBAAmB,EAAE,MAAM,YAAY,CAAC;AAGnF,wBAAgB,OAAO,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAE5C;AAED,wBAAgB,UAAU,CAAC,GAAG,EAAE,MAAM,GAAG;IAAE,MAAM,EAAE,MAAM,CAAC;IAAC,GAAG,EAAE,MAAM,CAAA;CAAE,CAWvE;AAqBD,wBAAsB,gBAAgB,CACpC,GAAG,EAAE,MAAM,EACX,UAAU,EAAE,MAAM,EAClB,IAAI,CAAC,EAAE,MAAM,GACZ,OAAO,CAAC,IAAI,CAAC,CAkBf;AAED,wBAAsB,YAAY,CAChC,MAAM,EAAE,mBAAmB,EAC3B,WAAW,EAAE;IAAE,MAAM,EAAE,MAAM,CAAC;IAAC,MAAM,CAAC,EAAE,MAAM,CAAA;CAAE,EAChD,IAAI,CAAC,EAAE,MAAM,GACZ,OAAO,CAAC,mBAAmB,CAAC,CAqB9B"}
|
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
import { createReadStream } from "node:fs";
|
|
2
|
+
import { createWriteStream } from "node:fs";
|
|
3
|
+
import { pipeline } from "node:stream/promises";
|
|
4
|
+
import { GetObjectCommand, PutObjectCommand, S3Client, } from "@aws-sdk/client-s3";
|
|
5
|
+
import { ModelError, ValidationError } from "../../utils/errors.js";
|
|
6
|
+
import { redactUrlForLogs } from "../download-auth.js";
|
|
7
|
+
import { bodyToReadable, safeErrorDetails, withPrefix } from "./utils.js";
|
|
8
|
+
export function isS3Url(url) {
|
|
9
|
+
return url.startsWith("s3://");
|
|
10
|
+
}
|
|
11
|
+
export function parseS3Url(url) {
|
|
12
|
+
let parsed;
|
|
13
|
+
try {
|
|
14
|
+
parsed = new URL(url);
|
|
15
|
+
}
|
|
16
|
+
catch {
|
|
17
|
+
throw new ValidationError("Invalid S3 URL. Expected s3://bucket/key.");
|
|
18
|
+
}
|
|
19
|
+
if (parsed.protocol !== "s3:" || !parsed.hostname || parsed.pathname.length <= 1) {
|
|
20
|
+
throw new ValidationError("Invalid S3 URL. Expected s3://bucket/key.");
|
|
21
|
+
}
|
|
22
|
+
return { bucket: parsed.hostname, key: decodeURIComponent(parsed.pathname.slice(1)) };
|
|
23
|
+
}
|
|
24
|
+
function makeS3Client(auth) {
|
|
25
|
+
const endpoint = auth?.endpoint ?? process.env.AWS_S3_ENDPOINT;
|
|
26
|
+
const region = auth?.region ?? process.env.AWS_REGION ?? (endpoint ? "auto" : undefined);
|
|
27
|
+
const config = {
|
|
28
|
+
region,
|
|
29
|
+
endpoint,
|
|
30
|
+
forcePathStyle: Boolean(endpoint),
|
|
31
|
+
};
|
|
32
|
+
const accessKeyId = auth?.access_key_id ?? process.env.AWS_ACCESS_KEY_ID;
|
|
33
|
+
const secretAccessKey = auth?.secret_access_key ?? process.env.AWS_SECRET_ACCESS_KEY;
|
|
34
|
+
const sessionToken = auth?.session_token ?? process.env.AWS_SESSION_TOKEN;
|
|
35
|
+
if (accessKeyId && secretAccessKey) {
|
|
36
|
+
config.credentials = { accessKeyId, secretAccessKey, sessionToken };
|
|
37
|
+
}
|
|
38
|
+
return new S3Client(config);
|
|
39
|
+
}
|
|
40
|
+
export async function downloadS3ToFile(url, targetPath, auth) {
|
|
41
|
+
const { bucket, key } = parseS3Url(url);
|
|
42
|
+
const client = makeS3Client(auth);
|
|
43
|
+
try {
|
|
44
|
+
const response = await client.send(new GetObjectCommand({ Bucket: bucket, Key: key }));
|
|
45
|
+
if (!response.Body) {
|
|
46
|
+
throw new ModelError("S3 download response has no body", { url: redactUrlForLogs(url) });
|
|
47
|
+
}
|
|
48
|
+
await pipeline(bodyToReadable(response.Body), createWriteStream(targetPath));
|
|
49
|
+
}
|
|
50
|
+
catch (err) {
|
|
51
|
+
if (err instanceof ModelError || err instanceof ValidationError)
|
|
52
|
+
throw err;
|
|
53
|
+
throw new ModelError("S3 download failed", {
|
|
54
|
+
url: redactUrlForLogs(url),
|
|
55
|
+
...safeErrorDetails(err),
|
|
56
|
+
});
|
|
57
|
+
}
|
|
58
|
+
finally {
|
|
59
|
+
client.destroy();
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
export async function uploadS3File(source, destination, auth) {
|
|
63
|
+
const key = withPrefix(destination.prefix, source.filename);
|
|
64
|
+
const client = makeS3Client(auth);
|
|
65
|
+
try {
|
|
66
|
+
await client.send(new PutObjectCommand({
|
|
67
|
+
Bucket: destination.bucket,
|
|
68
|
+
Key: key,
|
|
69
|
+
Body: source.path ? createReadStream(source.path) : source.data,
|
|
70
|
+
ContentType: source.contentType,
|
|
71
|
+
}));
|
|
72
|
+
return { provider: "s3", url: `s3://${destination.bucket}/${key}` };
|
|
73
|
+
}
|
|
74
|
+
catch (err) {
|
|
75
|
+
throw new ModelError("S3 upload failed", {
|
|
76
|
+
url: `s3://${destination.bucket}/${key}`,
|
|
77
|
+
...safeErrorDetails(err),
|
|
78
|
+
});
|
|
79
|
+
}
|
|
80
|
+
finally {
|
|
81
|
+
client.destroy();
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
//# sourceMappingURL=s3.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"s3.js","sourceRoot":"","sources":["../../../src/services/storage/s3.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,gBAAgB,EAAE,MAAM,SAAS,CAAC;AAC3C,OAAO,EAAE,iBAAiB,EAAE,MAAM,SAAS,CAAC;AAC5C,OAAO,EAAE,QAAQ,EAAE,MAAM,sBAAsB,CAAC;AAChD,OAAO,EACL,gBAAgB,EAChB,gBAAgB,EAChB,QAAQ,GAET,MAAM,oBAAoB,CAAC;AAC5B,OAAO,EAAE,UAAU,EAAE,eAAe,EAAE,MAAM,uBAAuB,CAAC;AACpE,OAAO,EAAE,gBAAgB,EAAE,MAAM,qBAAqB,CAAC;AAEvD,OAAO,EAAE,cAAc,EAAE,gBAAgB,EAAE,UAAU,EAAE,MAAM,YAAY,CAAC;AAE1E,MAAM,UAAU,OAAO,CAAC,GAAW;IACjC,OAAO,GAAG,CAAC,UAAU,CAAC,OAAO,CAAC,CAAC;AACjC,CAAC;AAED,MAAM,UAAU,UAAU,CAAC,GAAW;IACpC,IAAI,MAAW,CAAC;IAChB,IAAI,CAAC;QACH,MAAM,GAAG,IAAI,GAAG,CAAC,GAAG,CAAC,CAAC;IACxB,CAAC;IAAC,MAAM,CAAC;QACP,MAAM,IAAI,eAAe,CAAC,2CAA2C,CAAC,CAAC;IACzE,CAAC;IACD,IAAI,MAAM,CAAC,QAAQ,KAAK,KAAK,IAAI,CAAC,MAAM,CAAC,QAAQ,IAAI,MAAM,CAAC,QAAQ,CAAC,MAAM,IAAI,CAAC,EAAE,CAAC;QACjF,MAAM,IAAI,eAAe,CAAC,2CAA2C,CAAC,CAAC;IACzE,CAAC;IACD,OAAO,EAAE,MAAM,EAAE,MAAM,CAAC,QAAQ,EAAE,GAAG,EAAE,kBAAkB,CAAC,MAAM,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC;AACxF,CAAC;AAED,SAAS,YAAY,CAAC,IAAa;IACjC,MAAM,QAAQ,GAAG,IAAI,EAAE,QAAQ,IAAI,OAAO,CAAC,GAAG,CAAC,eAAe,CAAC;IAC/D,MAAM,MAAM,GAAG,IAAI,EAAE,MAAM,IAAI,OAAO,CAAC,GAAG,CAAC,UAAU,IAAI,CAAC,QAAQ,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC;IACzF,MAAM,MAAM,GAAmB;QAC7B,MAAM;QACN,QAAQ;QACR,cAAc,EAAE,OAAO,CAAC,QAAQ,CAAC;KAClC,CAAC;IAEF,MAAM,WAAW,GAAG,IAAI,EAAE,aAAa,IAAI,OAAO,CAAC,GAAG,CAAC,iBAAiB,CAAC;IACzE,MAAM,eAAe,GAAG,IAAI,EAAE,iBAAiB,IAAI,OAAO,CAAC,GAAG,CAAC,qBAAqB,CAAC;IACrF,MAAM,YAAY,GAAG,IAAI,EAAE,aAAa,IAAI,OAAO,CAAC,GAAG,CAAC,iBAAiB,CAAC;IAC1E,IAAI,WAAW,IAAI,eAAe,EAAE,CAAC;QACnC,MAAM,CAAC,WAAW,GAAG,EAAE,WAAW,EAAE,eAAe,EAAE,YAAY,EAAE,CAAC;IACtE,CAAC;IAED,OAAO,IAAI,QAAQ,CAAC,MAAM,CAAC,CAAC;AAC9B,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,gBAAgB,CACpC,GAAW,EACX,UAAkB,EAClB,IAAa;IAEb,MAAM,EAAE,MAAM,EAAE,GAAG,EAAE,GAAG,UAAU,CAAC,GAAG,CAAC,CAAC;IACxC,MAAM,MAAM,GAAG,YAAY,CAAC,IAAI,CAAC,CAAC;IAClC,IAAI,CAAC;QACH,MAAM,QAAQ,GAAG,MAAM,MAAM,CAAC,IAAI,CAAC,IAAI,gBAAgB,CAAC,EAAE,MAAM,EAAE,MAAM,EAAE,GAAG,EAAE,GAAG,EAAE,CAAC,CAAC,CAAC;QACvF,IAAI,CAAC,QAAQ,CAAC,IAAI,EAAE,CAAC;YACnB,MAAM,IAAI,UAAU,CAAC,kCAAkC,EAAE,EAAE,GAAG,EAAE,gBAAgB,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;QAC3F,CAAC;QACD,MAAM,QAAQ,CAAC,cAAc,CAAC,QAAQ,CAAC,IAAI,CAAC,EAAE,iBAAiB,CAAC,UAAU,CAAC,CAAC,CAAC;IAC/E,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,IAAI,GAAG,YAAY,UAAU,IAAI,GAAG,YAAY,eAAe;YAAE,MAAM,GAAG,CAAC;QAC3E,MAAM,IAAI,UAAU,CAAC,oBAAoB,EAAE;YACzC,GAAG,EAAE,gBAAgB,CAAC,GAAG,CAAC;YAC1B,GAAG,gBAAgB,CAAC,GAAG,CAAC;SACzB,CAAC,CAAC;IACL,CAAC;YAAS,CAAC;QACT,MAAM,CAAC,OAAO,EAAE,CAAC;IACnB,CAAC;AACH,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,YAAY,CAChC,MAA2B,EAC3B,WAAgD,EAChD,IAAa;IAEb,MAAM,GAAG,GAAG,UAAU,CAAC,WAAW,CAAC,MAAM,EAAE,MAAM,CAAC,QAAQ,CAAC,CAAC;IAC5D,MAAM,MAAM,GAAG,YAAY,CAAC,IAAI,CAAC,CAAC;IAClC,IAAI,CAAC;QACH,MAAM,MAAM,CAAC,IAAI,CACf,IAAI,gBAAgB,CAAC;YACnB,MAAM,EAAE,WAAW,CAAC,MAAM;YAC1B,GAAG,EAAE,GAAG;YACR,IAAI,EAAE,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC,gBAAgB,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,IAAI;YAC/D,WAAW,EAAE,MAAM,CAAC,WAAW;SAChC,CAAC,CACH,CAAC;QACF,OAAO,EAAE,QAAQ,EAAE,IAAI,EAAE,GAAG,EAAE,QAAQ,WAAW,CAAC,MAAM,IAAI,GAAG,EAAE,EAAE,CAAC;IACtE,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,MAAM,IAAI,UAAU,CAAC,kBAAkB,EAAE;YACvC,GAAG,EAAE,QAAQ,WAAW,CAAC,MAAM,IAAI,GAAG,EAAE;YACxC,GAAG,gBAAgB,CAAC,GAAG,CAAC;SACzB,CAAC,CAAC;IACL,CAAC;YAAS,CAAC;QACT,MAAM,CAAC,OAAO,EAAE,CAAC;IACnB,CAAC;AACH,CAAC"}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
export interface S3Auth {
|
|
2
|
+
type: "s3";
|
|
3
|
+
access_key_id: string;
|
|
4
|
+
secret_access_key: string;
|
|
5
|
+
session_token?: string;
|
|
6
|
+
region?: string;
|
|
7
|
+
endpoint?: string;
|
|
8
|
+
}
|
|
9
|
+
export interface CloudStorageAuth {
|
|
10
|
+
s3?: S3Auth;
|
|
11
|
+
}
|
|
12
|
+
export interface StorageUploadSource {
|
|
13
|
+
path?: string;
|
|
14
|
+
data?: Buffer;
|
|
15
|
+
filename: string;
|
|
16
|
+
contentType?: string;
|
|
17
|
+
}
|
|
18
|
+
export interface StorageUploadResult {
|
|
19
|
+
provider: "s3" | "azure" | "http" | "hf";
|
|
20
|
+
url: string;
|
|
21
|
+
}
|
|
22
|
+
//# sourceMappingURL=types.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../src/services/storage/types.ts"],"names":[],"mappings":"AAAA,MAAM,WAAW,MAAM;IACrB,IAAI,EAAE,IAAI,CAAC;IACX,aAAa,EAAE,MAAM,CAAC;IACtB,iBAAiB,EAAE,MAAM,CAAC;IAC1B,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB;AAED,MAAM,WAAW,gBAAgB;IAC/B,EAAE,CAAC,EAAE,MAAM,CAAC;CACb;AAED,MAAM,WAAW,mBAAmB;IAClC,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,QAAQ,EAAE,MAAM,CAAC;IACjB,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB;AAED,MAAM,WAAW,mBAAmB;IAClC,QAAQ,EAAE,IAAI,GAAG,OAAO,GAAG,MAAM,GAAG,IAAI,CAAC;IACzC,GAAG,EAAE,MAAM,CAAC;CACb"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.js","sourceRoot":"","sources":["../../../src/services/storage/types.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import { Readable } from "node:stream";
|
|
2
|
+
export declare function safeErrorDetails(err: unknown): Record<string, unknown>;
|
|
3
|
+
export declare function bodyToReadable(body: unknown): Readable;
|
|
4
|
+
export declare function normalizePrefix(prefix: string | undefined): string;
|
|
5
|
+
export declare function withPrefix(prefix: string | undefined, filename: string): string;
|
|
6
|
+
//# sourceMappingURL=utils.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"utils.d.ts","sourceRoot":"","sources":["../../../src/services/storage/utils.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,aAAa,CAAC;AAGvC,wBAAgB,gBAAgB,CAAC,GAAG,EAAE,OAAO,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAatE;AAED,wBAAgB,cAAc,CAAC,IAAI,EAAE,OAAO,GAAG,QAAQ,CAUtD;AAED,wBAAgB,eAAe,CAAC,MAAM,EAAE,MAAM,GAAG,SAAS,GAAG,MAAM,CAGlE;AAED,wBAAgB,UAAU,CAAC,MAAM,EAAE,MAAM,GAAG,SAAS,EAAE,QAAQ,EAAE,MAAM,GAAG,MAAM,CAG/E"}
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import { Readable } from "node:stream";
|
|
2
|
+
export function safeErrorDetails(err) {
|
|
3
|
+
if (!err || typeof err !== "object")
|
|
4
|
+
return {};
|
|
5
|
+
const record = err;
|
|
6
|
+
const metadata = record.$metadata;
|
|
7
|
+
return {
|
|
8
|
+
name: typeof record.name === "string" ? record.name : undefined,
|
|
9
|
+
code: typeof record.Code === "string"
|
|
10
|
+
? record.Code
|
|
11
|
+
: typeof record.code === "string"
|
|
12
|
+
? record.code
|
|
13
|
+
: undefined,
|
|
14
|
+
status: metadata?.httpStatusCode,
|
|
15
|
+
};
|
|
16
|
+
}
|
|
17
|
+
export function bodyToReadable(body) {
|
|
18
|
+
if (body instanceof Readable)
|
|
19
|
+
return body;
|
|
20
|
+
if (body instanceof Uint8Array)
|
|
21
|
+
return Readable.from(body);
|
|
22
|
+
if (body && typeof body.transformToByteArray === "function") {
|
|
23
|
+
return Readable.from((async function* () {
|
|
24
|
+
yield await body
|
|
25
|
+
.transformToByteArray();
|
|
26
|
+
})());
|
|
27
|
+
}
|
|
28
|
+
return Readable.fromWeb(body);
|
|
29
|
+
}
|
|
30
|
+
export function normalizePrefix(prefix) {
|
|
31
|
+
if (!prefix)
|
|
32
|
+
return "";
|
|
33
|
+
return prefix.replace(/^\/+/, "").replace(/\/+$/, "");
|
|
34
|
+
}
|
|
35
|
+
export function withPrefix(prefix, filename) {
|
|
36
|
+
const clean = normalizePrefix(prefix);
|
|
37
|
+
return clean ? `${clean}/${filename}` : filename;
|
|
38
|
+
}
|
|
39
|
+
//# sourceMappingURL=utils.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"utils.js","sourceRoot":"","sources":["../../../src/services/storage/utils.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,aAAa,CAAC;AAGvC,MAAM,UAAU,gBAAgB,CAAC,GAAY;IAC3C,IAAI,CAAC,GAAG,IAAI,OAAO,GAAG,KAAK,QAAQ;QAAE,OAAO,EAAE,CAAC;IAC/C,MAAM,MAAM,GAAG,GAA8B,CAAC;IAC9C,MAAM,QAAQ,GAAG,MAAM,CAAC,SAAgD,CAAC;IACzE,OAAO;QACL,IAAI,EAAE,OAAO,MAAM,CAAC,IAAI,KAAK,QAAQ,CAAC,CAAC,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC,SAAS;QAC/D,IAAI,EAAE,OAAO,MAAM,CAAC,IAAI,KAAK,QAAQ;YACnC,CAAC,CAAC,MAAM,CAAC,IAAI;YACb,CAAC,CAAC,OAAO,MAAM,CAAC,IAAI,KAAK,QAAQ;gBAC/B,CAAC,CAAC,MAAM,CAAC,IAAI;gBACb,CAAC,CAAC,SAAS;QACf,MAAM,EAAE,QAAQ,EAAE,cAAc;KACjC,CAAC;AACJ,CAAC;AAED,MAAM,UAAU,cAAc,CAAC,IAAa;IAC1C,IAAI,IAAI,YAAY,QAAQ;QAAE,OAAO,IAAI,CAAC;IAC1C,IAAI,IAAI,YAAY,UAAU;QAAE,OAAO,QAAQ,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IAC3D,IAAI,IAAI,IAAI,OAAQ,IAA2C,CAAC,oBAAoB,KAAK,UAAU,EAAE,CAAC;QACpG,OAAO,QAAQ,CAAC,IAAI,CAAC,CAAC,KAAK,SAAS,CAAC;YACnC,MAAM,MAAO,IAA4D;iBACtE,oBAAoB,EAAE,CAAC;QAC5B,CAAC,CAAC,EAAE,CAAC,CAAC;IACR,CAAC;IACD,OAAO,QAAQ,CAAC,OAAO,CAAC,IAAyB,CAAC,CAAC;AACrD,CAAC;AAED,MAAM,UAAU,eAAe,CAAC,MAA0B;IACxD,IAAI,CAAC,MAAM;QAAE,OAAO,EAAE,CAAC;IACvB,OAAO,MAAM,CAAC,OAAO,CAAC,MAAM,EAAE,EAAE,CAAC,CAAC,OAAO,CAAC,MAAM,EAAE,EAAE,CAAC,CAAC;AACxD,CAAC;AAED,MAAM,UAAU,UAAU,CAAC,MAA0B,EAAE,QAAgB;IACrE,MAAM,KAAK,GAAG,eAAe,CAAC,MAAM,CAAC,CAAC;IACtC,OAAO,KAAK,CAAC,CAAC,CAAC,GAAG,KAAK,IAAI,QAAQ,EAAE,CAAC,CAAC,CAAC,QAAQ,CAAC;AACnD,CAAC"}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { type UploadDestination, type StorageUploadResult } from "./storage/index.js";
|
|
2
|
+
export interface UploadOutputOptions {
|
|
3
|
+
asset_id?: string;
|
|
4
|
+
path?: string;
|
|
5
|
+
destination: UploadDestination;
|
|
6
|
+
}
|
|
7
|
+
export interface UploadOutputResult {
|
|
8
|
+
source: {
|
|
9
|
+
filename: string;
|
|
10
|
+
path?: string;
|
|
11
|
+
asset_id?: string;
|
|
12
|
+
mime_type?: string;
|
|
13
|
+
bytes?: number;
|
|
14
|
+
};
|
|
15
|
+
uploads: StorageUploadResult[];
|
|
16
|
+
}
|
|
17
|
+
export declare function uploadOutput(opts: UploadOutputOptions): Promise<UploadOutputResult>;
|
|
18
|
+
//# sourceMappingURL=storage-upload.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"storage-upload.d.ts","sourceRoot":"","sources":["../../src/services/storage-upload.ts"],"names":[],"mappings":"AAKA,OAAO,EAEL,KAAK,iBAAiB,EACtB,KAAK,mBAAmB,EAEzB,MAAM,oBAAoB,CAAC;AAK5B,MAAM,WAAW,mBAAmB;IAClC,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,WAAW,EAAE,iBAAiB,CAAC;CAChC;AAED,MAAM,WAAW,kBAAkB;IACjC,MAAM,EAAE;QACN,QAAQ,EAAE,MAAM,CAAC;QACjB,IAAI,CAAC,EAAE,MAAM,CAAC;QACd,QAAQ,CAAC,EAAE,MAAM,CAAC;QAClB,SAAS,CAAC,EAAE,MAAM,CAAC;QACnB,KAAK,CAAC,EAAE,MAAM,CAAC;KAChB,CAAC;IACF,OAAO,EAAE,mBAAmB,EAAE,CAAC;CAChC;AAwGD,wBAAsB,YAAY,CAAC,IAAI,EAAE,mBAAmB,GAAG,OAAO,CAAC,kBAAkB,CAAC,CAyBzF"}
|
|
@@ -0,0 +1,121 @@
|
|
|
1
|
+
import { realpath, stat } from "node:fs/promises";
|
|
2
|
+
import { basename, extname, isAbsolute, relative, resolve, sep } from "node:path";
|
|
3
|
+
import { config } from "../config.js";
|
|
4
|
+
import { AssetRegistry } from "./asset-registry.js";
|
|
5
|
+
import { getOutputImage } from "./image-management.js";
|
|
6
|
+
import { uploadToStorage, } from "./storage/index.js";
|
|
7
|
+
import { ValidationError } from "../utils/errors.js";
|
|
8
|
+
import { logger } from "../utils/logger.js";
|
|
9
|
+
import { redactUrlForLogs } from "./download-auth.js";
|
|
10
|
+
const MIME_BY_EXTENSION = {
|
|
11
|
+
".png": "image/png",
|
|
12
|
+
".jpg": "image/jpeg",
|
|
13
|
+
".jpeg": "image/jpeg",
|
|
14
|
+
".webp": "image/webp",
|
|
15
|
+
".gif": "image/gif",
|
|
16
|
+
".bmp": "image/bmp",
|
|
17
|
+
".tiff": "image/tiff",
|
|
18
|
+
".tif": "image/tiff",
|
|
19
|
+
".mp4": "video/mp4",
|
|
20
|
+
".mov": "video/quicktime",
|
|
21
|
+
".webm": "video/webm",
|
|
22
|
+
".wav": "audio/wav",
|
|
23
|
+
".mp3": "audio/mpeg",
|
|
24
|
+
".flac": "audio/flac",
|
|
25
|
+
};
|
|
26
|
+
function getOutputDir() {
|
|
27
|
+
if (!config.comfyuiPath) {
|
|
28
|
+
throw new ValidationError("COMFYUI_PATH is not configured. Set the COMFYUI_PATH environment variable.");
|
|
29
|
+
}
|
|
30
|
+
return resolve(config.comfyuiPath, "output");
|
|
31
|
+
}
|
|
32
|
+
function isInsideOrEqual(root, candidate) {
|
|
33
|
+
const rel = relative(root, candidate);
|
|
34
|
+
return rel === "" || (!rel.startsWith("..") && !isAbsolute(rel));
|
|
35
|
+
}
|
|
36
|
+
function assertInsideOutput(root, candidate, label) {
|
|
37
|
+
if (!isInsideOrEqual(root, candidate) || candidate === root) {
|
|
38
|
+
throw new ValidationError(`${label} must stay within the ComfyUI output directory.`);
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
function resolveOutputPath(path) {
|
|
42
|
+
if (path.trim().length === 0) {
|
|
43
|
+
throw new ValidationError("path must be a non-empty path.");
|
|
44
|
+
}
|
|
45
|
+
const outputDir = getOutputDir();
|
|
46
|
+
const resolved = isAbsolute(path) ? resolve(path) : resolve(outputDir, path);
|
|
47
|
+
if (resolved === outputDir || !resolved.startsWith(outputDir + sep)) {
|
|
48
|
+
throw new ValidationError("path must stay within the ComfyUI output directory.");
|
|
49
|
+
}
|
|
50
|
+
return resolved;
|
|
51
|
+
}
|
|
52
|
+
function inferMimeType(filename) {
|
|
53
|
+
return MIME_BY_EXTENSION[extname(filename).toLowerCase()] ?? "application/octet-stream";
|
|
54
|
+
}
|
|
55
|
+
async function sourceFromPath(path) {
|
|
56
|
+
const lexicalPath = resolveOutputPath(path);
|
|
57
|
+
const root = await realpath(getOutputDir());
|
|
58
|
+
const sourcePath = await realpath(lexicalPath).catch(() => undefined);
|
|
59
|
+
if (!sourcePath) {
|
|
60
|
+
throw new ValidationError(`Upload source not found: ${lexicalPath}`);
|
|
61
|
+
}
|
|
62
|
+
assertInsideOutput(root, sourcePath, "path");
|
|
63
|
+
const info = await stat(sourcePath).catch(() => undefined);
|
|
64
|
+
if (!info?.isFile()) {
|
|
65
|
+
throw new ValidationError(`Upload source not found: ${sourcePath}`);
|
|
66
|
+
}
|
|
67
|
+
const filename = basename(sourcePath);
|
|
68
|
+
return {
|
|
69
|
+
path: sourcePath,
|
|
70
|
+
filename,
|
|
71
|
+
contentType: inferMimeType(filename),
|
|
72
|
+
bytes: info.size,
|
|
73
|
+
};
|
|
74
|
+
}
|
|
75
|
+
async function sourceFromAsset(assetId) {
|
|
76
|
+
const record = AssetRegistry.get(assetId);
|
|
77
|
+
if (!record) {
|
|
78
|
+
throw new ValidationError(`No asset found for id "${assetId}". It may have expired or never been registered.`);
|
|
79
|
+
}
|
|
80
|
+
const validType = record.type === "output" || record.type === "input" || record.type === "temp";
|
|
81
|
+
const fetchType = validType
|
|
82
|
+
? record.type
|
|
83
|
+
: "output";
|
|
84
|
+
const image = await getOutputImage(record.filename, fetchType, record.subfolder);
|
|
85
|
+
const data = Buffer.from(image.base64, "base64");
|
|
86
|
+
return {
|
|
87
|
+
data,
|
|
88
|
+
filename: image.filename,
|
|
89
|
+
contentType: image.mimeType,
|
|
90
|
+
bytes: data.length,
|
|
91
|
+
};
|
|
92
|
+
}
|
|
93
|
+
function redactDestinationForLogs(destination) {
|
|
94
|
+
if ("http" in destination)
|
|
95
|
+
return { http: { url: redactUrlForLogs(destination.http.url) } };
|
|
96
|
+
return destination;
|
|
97
|
+
}
|
|
98
|
+
export async function uploadOutput(opts) {
|
|
99
|
+
if (Boolean(opts.asset_id) === Boolean(opts.path)) {
|
|
100
|
+
throw new ValidationError("Provide exactly one upload source: asset_id or path.");
|
|
101
|
+
}
|
|
102
|
+
const source = opts.asset_id
|
|
103
|
+
? await sourceFromAsset(opts.asset_id)
|
|
104
|
+
: await sourceFromPath(opts.path);
|
|
105
|
+
logger.info("Uploading ComfyUI output to cloud storage", {
|
|
106
|
+
source: source.path ?? `asset:${opts.asset_id}`,
|
|
107
|
+
destination: redactDestinationForLogs(opts.destination),
|
|
108
|
+
});
|
|
109
|
+
const upload = await uploadToStorage(source, opts.destination);
|
|
110
|
+
return {
|
|
111
|
+
source: {
|
|
112
|
+
filename: source.filename,
|
|
113
|
+
path: source.path,
|
|
114
|
+
asset_id: opts.asset_id,
|
|
115
|
+
mime_type: source.contentType,
|
|
116
|
+
bytes: source.bytes,
|
|
117
|
+
},
|
|
118
|
+
uploads: [upload],
|
|
119
|
+
};
|
|
120
|
+
}
|
|
121
|
+
//# sourceMappingURL=storage-upload.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"storage-upload.js","sourceRoot":"","sources":["../../src/services/storage-upload.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"image-convert.d.ts","sourceRoot":"","sources":["../../src/tools/image-convert.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AA4CzE,wBAAgB,yBAAyB,CAAC,MAAM,EAAE,SAAS,GAAG,IAAI,CAoBjE"}
|