@hyperframes/studio-server 0.8.136 → 0.8.138
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/{chunk-YOBWV2CY.js → chunk-6RFZWPPN.js} +3 -3
- package/dist/{chunk-I3DRHG52.js → chunk-74JVVCWL.js} +2 -2
- package/dist/{chunk-7ON477WG.js → chunk-DG2VOIGR.js} +2 -2
- package/dist/{chunk-TTWLTYSQ.js → chunk-DTKK7TKL.js} +30 -6
- package/dist/chunk-DTKK7TKL.js.map +1 -0
- package/dist/{chunk-WK3ZL3SN.js → chunk-G7FEKQ32.js} +3 -3
- package/dist/{chunk-36F5I56K.js → chunk-K3H6HTVC.js} +2 -2
- package/dist/helpers/hfIdPersist.js +4 -2
- package/dist/helpers/mediaCodecMap.js +4 -2
- package/dist/helpers/mediaProxyPreview.js +6 -4
- package/dist/helpers/proxyTranscoder.js +5 -3
- package/dist/helpers/safePath.d.ts +7 -2
- package/dist/helpers/safePath.js +7 -1
- package/dist/history/index.js +4 -2
- package/dist/index.d.ts +3 -1
- package/dist/index.js +47 -25
- package/dist/index.js.map +1 -1
- package/package.json +3 -3
- package/dist/chunk-TTWLTYSQ.js.map +0 -1
- /package/dist/{chunk-YOBWV2CY.js.map → chunk-6RFZWPPN.js.map} +0 -0
- /package/dist/{chunk-I3DRHG52.js.map → chunk-74JVVCWL.js.map} +0 -0
- /package/dist/{chunk-7ON477WG.js.map → chunk-DG2VOIGR.js.map} +0 -0
- /package/dist/{chunk-WK3ZL3SN.js.map → chunk-G7FEKQ32.js.map} +0 -0
- /package/dist/{chunk-36F5I56K.js.map → chunk-K3H6HTVC.js.map} +0 -0
|
@@ -2,12 +2,12 @@ import {
|
|
|
2
2
|
PROXY_VARIANT_CONFIG,
|
|
3
3
|
probeFirstFrameColour,
|
|
4
4
|
probeMediaMetadata
|
|
5
|
-
} from "./chunk-
|
|
5
|
+
} from "./chunk-74JVVCWL.js";
|
|
6
6
|
import {
|
|
7
7
|
mkdirWithinProject,
|
|
8
8
|
realProjectRoot,
|
|
9
9
|
realpath
|
|
10
|
-
} from "./chunk-
|
|
10
|
+
} from "./chunk-DTKK7TKL.js";
|
|
11
11
|
|
|
12
12
|
// src/helpers/proxyTranscoder.ts
|
|
13
13
|
import { spawn } from "child_process";
|
|
@@ -481,4 +481,4 @@ export {
|
|
|
481
481
|
proxyActivityMark,
|
|
482
482
|
resolveProxy
|
|
483
483
|
};
|
|
484
|
-
//# sourceMappingURL=chunk-
|
|
484
|
+
//# sourceMappingURL=chunk-6RFZWPPN.js.map
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import {
|
|
2
2
|
realpath
|
|
3
|
-
} from "./chunk-
|
|
3
|
+
} from "./chunk-DTKK7TKL.js";
|
|
4
4
|
|
|
5
5
|
// src/helpers/mediaCodecMap.ts
|
|
6
6
|
import { existsSync, statSync } from "fs";
|
|
@@ -346,4 +346,4 @@ export {
|
|
|
346
346
|
probeAssetCodec,
|
|
347
347
|
scanProjectMediaCodecMap
|
|
348
348
|
};
|
|
349
|
-
//# sourceMappingURL=chunk-
|
|
349
|
+
//# sourceMappingURL=chunk-74JVVCWL.js.map
|
|
@@ -2,7 +2,7 @@ import {
|
|
|
2
2
|
isInHiddenOrVendorDir,
|
|
3
3
|
mkdirWithinProject,
|
|
4
4
|
walkDir
|
|
5
|
-
} from "./chunk-
|
|
5
|
+
} from "./chunk-DTKK7TKL.js";
|
|
6
6
|
|
|
7
7
|
// src/helpers/hfIdPersist.ts
|
|
8
8
|
import { ensureHfIds } from "@hyperframes/parsers/hf-ids";
|
|
@@ -95,4 +95,4 @@ export {
|
|
|
95
95
|
stampProjectHfIds,
|
|
96
96
|
stampFileHfIds
|
|
97
97
|
};
|
|
98
|
-
//# sourceMappingURL=chunk-
|
|
98
|
+
//# sourceMappingURL=chunk-DG2VOIGR.js.map
|
|
@@ -1,16 +1,26 @@
|
|
|
1
|
+
import {
|
|
2
|
+
STUDIO_MANUAL_EDITS_PATH
|
|
3
|
+
} from "./chunk-6XMC64FJ.js";
|
|
4
|
+
import {
|
|
5
|
+
STUDIO_MOTION_PATH
|
|
6
|
+
} from "./chunk-4ETS2LXI.js";
|
|
7
|
+
|
|
1
8
|
// src/helpers/safePath.ts
|
|
2
9
|
import { basename, dirname, isAbsolute, join, relative, sep } from "path";
|
|
3
10
|
import { readdirSync } from "fs";
|
|
4
|
-
import { realpath, resolveWithinProject } from "@hyperframes/core/safe-path";
|
|
11
|
+
import { realpath, resolveWithinProject as resolveInProject } from "@hyperframes/core/safe-path";
|
|
5
12
|
import {
|
|
6
13
|
folderGone,
|
|
7
14
|
isProjectRootMissing,
|
|
8
15
|
isSafePath,
|
|
9
16
|
mkdirWithinProject,
|
|
10
17
|
realpath as realpath2,
|
|
11
|
-
realProjectRoot
|
|
12
|
-
resolveWithinProject as resolveWithinProject2
|
|
18
|
+
realProjectRoot
|
|
13
19
|
} from "@hyperframes/core/safe-path";
|
|
20
|
+
function resolveWithinProject(base, relativePath) {
|
|
21
|
+
const resolved = resolveInProject(base, relativePath);
|
|
22
|
+
return resolved && !isPrivateProjectFile(base, resolved) ? resolved : null;
|
|
23
|
+
}
|
|
14
24
|
function realFilePath(filePath) {
|
|
15
25
|
try {
|
|
16
26
|
return realpath(filePath);
|
|
@@ -19,6 +29,18 @@ function realFilePath(filePath) {
|
|
|
19
29
|
return dir === filePath ? filePath : join(realFilePath(dir), basename(filePath));
|
|
20
30
|
}
|
|
21
31
|
}
|
|
32
|
+
var STUDIO_FILES = /* @__PURE__ */ new Set([STUDIO_MOTION_PATH, STUDIO_MANUAL_EDITS_PATH]);
|
|
33
|
+
var STUDIO_FOLDERS = [".hyperframes/prepared-assets", ".hyperframes/requests"];
|
|
34
|
+
function isPrivateProjectPath(relPath) {
|
|
35
|
+
const path = relPath.toLowerCase();
|
|
36
|
+
return (path === ".hyperframes" || path.startsWith(".hyperframes/")) && !STUDIO_FILES.has(path) && !STUDIO_FOLDERS.some((folder) => path === folder || path.startsWith(`${folder}/`));
|
|
37
|
+
}
|
|
38
|
+
function isPrivateProjectFile(projectDir, filePath) {
|
|
39
|
+
const rel = (from, to) => relative(from, to).split(sep).join("/");
|
|
40
|
+
return [rel(projectDir, filePath), rel(realFilePath(projectDir), realFilePath(filePath))].some(
|
|
41
|
+
isPrivateProjectPath
|
|
42
|
+
);
|
|
43
|
+
}
|
|
22
44
|
function pinWithinProject(base, relativePath) {
|
|
23
45
|
const checked = resolveWithinProject(base, relativePath);
|
|
24
46
|
if (!checked) return null;
|
|
@@ -64,7 +86,10 @@ function walkDir(dir, prefix = "") {
|
|
|
64
86
|
}
|
|
65
87
|
|
|
66
88
|
export {
|
|
89
|
+
resolveWithinProject,
|
|
67
90
|
realFilePath,
|
|
91
|
+
isPrivateProjectPath,
|
|
92
|
+
isPrivateProjectFile,
|
|
68
93
|
pinWithinProject,
|
|
69
94
|
isInHiddenOrVendorDir,
|
|
70
95
|
walkDir,
|
|
@@ -73,7 +98,6 @@ export {
|
|
|
73
98
|
isSafePath,
|
|
74
99
|
mkdirWithinProject,
|
|
75
100
|
realpath2 as realpath,
|
|
76
|
-
realProjectRoot
|
|
77
|
-
resolveWithinProject2 as resolveWithinProject
|
|
101
|
+
realProjectRoot
|
|
78
102
|
};
|
|
79
|
-
//# sourceMappingURL=chunk-
|
|
103
|
+
//# sourceMappingURL=chunk-DTKK7TKL.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/helpers/safePath.ts"],"sourcesContent":["import { basename, dirname, isAbsolute, join, relative, sep } from \"node:path\";\nimport { readdirSync, type Dirent } from \"node:fs\";\nimport { realpath, resolveWithinProject as resolveInProject } from \"@hyperframes/core/safe-path\";\nimport { STUDIO_MANUAL_EDITS_PATH } from \"./manualEditsRenderScript.js\";\nimport { STUDIO_MOTION_PATH } from \"./studioMotionRenderScript.js\";\n\n// `isSafePath` lives at the package root so non-studio-api layers (compiler,\n// CLI, engine) can share it without a backwards dependency on studio-api.\n// Re-exported here for back-compat with existing `../helpers/safePath.js` imports.\nexport {\n folderGone,\n isProjectRootMissing,\n isSafePath,\n mkdirWithinProject,\n realpath,\n realProjectRoot,\n} from \"@hyperframes/core/safe-path\";\n\n/** Core's `resolveWithinProject`, closed to the desktop app's private files for every route a request path reaches. */\nexport function resolveWithinProject(base: string, relativePath: string): string | null {\n const resolved = resolveInProject(base, relativePath);\n return resolved && !isPrivateProjectFile(base, resolved) ? resolved : null;\n}\n\n/** The real path; for a path not there (yet, or any more), the nearest existing folder's real path plus the rest. */\nexport function realFilePath(filePath: string): string {\n try {\n return realpath(filePath);\n } catch {\n const dir = dirname(filePath);\n return dir === filePath ? filePath : join(realFilePath(dir), basename(filePath));\n }\n}\n\n// `.hyperframes/` holds the desktop app's and the CLI's own records (a hand-off, chat history, read marks): no route\n// reaches any of it, the folder itself included, but Studio's own files and the app's request pictures.\nconst STUDIO_FILES = new Set([STUDIO_MOTION_PATH, STUDIO_MANUAL_EDITS_PATH]);\nconst STUDIO_FOLDERS = [\".hyperframes/prepared-assets\", \".hyperframes/requests\"];\n\n/** For a project-relative path with `/` separators. */\nexport function isPrivateProjectPath(relPath: string): boolean {\n const path = relPath.toLowerCase();\n return (\n (path === \".hyperframes\" || path.startsWith(\".hyperframes/\")) &&\n !STUDIO_FILES.has(path) &&\n !STUDIO_FOLDERS.some((folder) => path === folder || path.startsWith(`${folder}/`))\n );\n}\n\nexport function isPrivateProjectFile(projectDir: string, filePath: string): boolean {\n const rel = (from: string, to: string) => relative(from, to).split(sep).join(\"/\");\n return [rel(projectDir, filePath), rel(realFilePath(projectDir), realFilePath(filePath))].some(\n isPrivateProjectPath,\n );\n}\n\n/**\n * `resolveWithinProject` with every link inside the project resolved now, so a write to the result lands on the\n * file checked here even if a link on the way is retargeted before the write.\n */\nexport function pinWithinProject(base: string, relativePath: string): string | null {\n const checked = resolveWithinProject(base, relativePath);\n if (!checked) return null;\n const inside = relative(realFilePath(base), realFilePath(checked));\n const escapes = inside === \"..\" || inside.startsWith(`..${sep}`) || isAbsolute(inside);\n return escapes ? null : join(base, inside);\n}\n\nconst IGNORE_DIRS = new Set([\n \".thumbnails\",\n \".transcode-cache\",\n \".waveform-cache\",\n \"node_modules\",\n \".git\",\n]);\n\nfunction shouldIgnoreDir(rel: string): boolean {\n return rel === \".hyperframes/backup\";\n}\n\n/**\n * True when any directory segment of a relative path is a dot-directory or\n * node_modules. Projects that vendor tooling assets under dot-directories\n * (.hyperframes/, .cache/, …) ship example/preset HTML that must not surface\n * as project compositions or studio lint targets (#1384). The file tree is\n * deliberately not filtered — this only gates discovery.\n */\nexport function isInHiddenOrVendorDir(relPath: string): boolean {\n const segments = relPath.split(\"/\");\n return segments.slice(0, -1).some((seg) => seg.startsWith(\".\") || seg === \"node_modules\");\n}\n\nconst UNREADABLE_DIR_CODES = new Set([\"EACCES\", \"EPERM\", \"ENOENT\", \"ENOTDIR\"]);\n\n/** Recursively walk a directory and return relative file paths. A subfolder that is unreadable\n * or removed mid-walk is skipped; any other failure, or an unreadable `dir` itself, throws. */\nexport function walkDir(dir: string, prefix = \"\"): string[] {\n let entries: Dirent[];\n try {\n entries = readdirSync(dir, { withFileTypes: true });\n } catch (err) {\n const code = (err as NodeJS.ErrnoException).code;\n if (!prefix || !code || !UNREADABLE_DIR_CODES.has(code)) throw err;\n return [];\n }\n const files: string[] = [];\n for (const entry of entries) {\n const rel = prefix ? `${prefix}/${entry.name}` : entry.name;\n if (IGNORE_DIRS.has(entry.name) || shouldIgnoreDir(rel)) continue;\n if (entry.isDirectory()) {\n files.push(...walkDir(join(dir, entry.name), rel));\n } else {\n files.push(rel);\n }\n }\n return files;\n}\n"],"mappings":"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","names":["realpath"]}
|
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
import {
|
|
2
2
|
PROXY_PARAMS_VERSION,
|
|
3
3
|
resolveProxy
|
|
4
|
-
} from "./chunk-
|
|
4
|
+
} from "./chunk-6RFZWPPN.js";
|
|
5
5
|
import {
|
|
6
6
|
createMediaCodecProbeCache,
|
|
7
7
|
proxyVariantFor,
|
|
8
8
|
recordProxyPrewarm,
|
|
9
9
|
scanProjectMediaCodecMap,
|
|
10
10
|
shouldPrewarmProxy
|
|
11
|
-
} from "./chunk-
|
|
11
|
+
} from "./chunk-74JVVCWL.js";
|
|
12
12
|
|
|
13
13
|
// src/helpers/mediaProxyPreview.ts
|
|
14
14
|
import { resolve } from "path";
|
|
@@ -63,4 +63,4 @@ export {
|
|
|
63
63
|
injectMediaCodecMapIntoHtml,
|
|
64
64
|
injectMediaCodecMap
|
|
65
65
|
};
|
|
66
|
-
//# sourceMappingURL=chunk-
|
|
66
|
+
//# sourceMappingURL=chunk-G7FEKQ32.js.map
|
|
@@ -2,7 +2,7 @@ import {
|
|
|
2
2
|
isSafePath,
|
|
3
3
|
mkdirWithinProject,
|
|
4
4
|
realFilePath
|
|
5
|
-
} from "./chunk-
|
|
5
|
+
} from "./chunk-DTKK7TKL.js";
|
|
6
6
|
|
|
7
7
|
// src/history/projectHistory.ts
|
|
8
8
|
import { randomUUID as randomUUID6 } from "crypto";
|
|
@@ -1750,4 +1750,4 @@ export {
|
|
|
1750
1750
|
openProjectHistory,
|
|
1751
1751
|
historyCache
|
|
1752
1752
|
};
|
|
1753
|
-
//# sourceMappingURL=chunk-
|
|
1753
|
+
//# sourceMappingURL=chunk-K3H6HTVC.js.map
|
|
@@ -2,8 +2,10 @@ import {
|
|
|
2
2
|
isCompositionSource,
|
|
3
3
|
stampFileHfIds,
|
|
4
4
|
stampProjectHfIds
|
|
5
|
-
} from "../chunk-
|
|
6
|
-
import "../chunk-
|
|
5
|
+
} from "../chunk-DG2VOIGR.js";
|
|
6
|
+
import "../chunk-DTKK7TKL.js";
|
|
7
|
+
import "../chunk-6XMC64FJ.js";
|
|
8
|
+
import "../chunk-4ETS2LXI.js";
|
|
7
9
|
export {
|
|
8
10
|
isCompositionSource,
|
|
9
11
|
stampFileHfIds,
|
|
@@ -13,8 +13,10 @@ import {
|
|
|
13
13
|
resolveProxyVariantRequest,
|
|
14
14
|
scanProjectMediaCodecMap,
|
|
15
15
|
shouldPrewarmProxy
|
|
16
|
-
} from "../chunk-
|
|
17
|
-
import "../chunk-
|
|
16
|
+
} from "../chunk-74JVVCWL.js";
|
|
17
|
+
import "../chunk-DTKK7TKL.js";
|
|
18
|
+
import "../chunk-6XMC64FJ.js";
|
|
19
|
+
import "../chunk-4ETS2LXI.js";
|
|
18
20
|
export {
|
|
19
21
|
BROWSER_HOSTILE_CODECS,
|
|
20
22
|
PROXY_VARIANT_CONFIG,
|
|
@@ -4,10 +4,12 @@ import {
|
|
|
4
4
|
isAutoProxyEnabled,
|
|
5
5
|
proxyEtagSalt,
|
|
6
6
|
resolvePreviewMediaCodecProbeCache
|
|
7
|
-
} from "../chunk-
|
|
8
|
-
import "../chunk-
|
|
9
|
-
import "../chunk-
|
|
10
|
-
import "../chunk-
|
|
7
|
+
} from "../chunk-G7FEKQ32.js";
|
|
8
|
+
import "../chunk-6RFZWPPN.js";
|
|
9
|
+
import "../chunk-74JVVCWL.js";
|
|
10
|
+
import "../chunk-DTKK7TKL.js";
|
|
11
|
+
import "../chunk-6XMC64FJ.js";
|
|
12
|
+
import "../chunk-4ETS2LXI.js";
|
|
11
13
|
export {
|
|
12
14
|
injectMediaCodecMap,
|
|
13
15
|
injectMediaCodecMapIntoHtml,
|
|
@@ -14,9 +14,11 @@ import {
|
|
|
14
14
|
proxyActivityMark,
|
|
15
15
|
resolveProxy,
|
|
16
16
|
waitForProxy
|
|
17
|
-
} from "../chunk-
|
|
18
|
-
import "../chunk-
|
|
19
|
-
import "../chunk-
|
|
17
|
+
} from "../chunk-6RFZWPPN.js";
|
|
18
|
+
import "../chunk-74JVVCWL.js";
|
|
19
|
+
import "../chunk-DTKK7TKL.js";
|
|
20
|
+
import "../chunk-6XMC64FJ.js";
|
|
21
|
+
import "../chunk-4ETS2LXI.js";
|
|
20
22
|
export {
|
|
21
23
|
CACHE_DIR_NAME,
|
|
22
24
|
DEFAULT_PROXY_WAIT_TIMEOUT_MS,
|
|
@@ -1,7 +1,12 @@
|
|
|
1
|
-
export { folderGone, isProjectRootMissing, isSafePath, mkdirWithinProject, realProjectRoot, realpath
|
|
1
|
+
export { folderGone, isProjectRootMissing, isSafePath, mkdirWithinProject, realProjectRoot, realpath } from '@hyperframes/core/safe-path';
|
|
2
2
|
|
|
3
|
+
/** Core's `resolveWithinProject`, closed to the desktop app's private files for every route a request path reaches. */
|
|
4
|
+
declare function resolveWithinProject(base: string, relativePath: string): string | null;
|
|
3
5
|
/** The real path; for a path not there (yet, or any more), the nearest existing folder's real path plus the rest. */
|
|
4
6
|
declare function realFilePath(filePath: string): string;
|
|
7
|
+
/** For a project-relative path with `/` separators. */
|
|
8
|
+
declare function isPrivateProjectPath(relPath: string): boolean;
|
|
9
|
+
declare function isPrivateProjectFile(projectDir: string, filePath: string): boolean;
|
|
5
10
|
/**
|
|
6
11
|
* `resolveWithinProject` with every link inside the project resolved now, so a write to the result lands on the
|
|
7
12
|
* file checked here even if a link on the way is retargeted before the write.
|
|
@@ -19,4 +24,4 @@ declare function isInHiddenOrVendorDir(relPath: string): boolean;
|
|
|
19
24
|
* or removed mid-walk is skipped; any other failure, or an unreadable `dir` itself, throws. */
|
|
20
25
|
declare function walkDir(dir: string, prefix?: string): string[];
|
|
21
26
|
|
|
22
|
-
export { isInHiddenOrVendorDir, pinWithinProject, realFilePath, walkDir };
|
|
27
|
+
export { isInHiddenOrVendorDir, isPrivateProjectFile, isPrivateProjectPath, pinWithinProject, realFilePath, resolveWithinProject, walkDir };
|
package/dist/helpers/safePath.js
CHANGED
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
import {
|
|
2
2
|
folderGone,
|
|
3
3
|
isInHiddenOrVendorDir,
|
|
4
|
+
isPrivateProjectFile,
|
|
5
|
+
isPrivateProjectPath,
|
|
4
6
|
isProjectRootMissing,
|
|
5
7
|
isSafePath,
|
|
6
8
|
mkdirWithinProject,
|
|
@@ -10,10 +12,14 @@ import {
|
|
|
10
12
|
realpath,
|
|
11
13
|
resolveWithinProject,
|
|
12
14
|
walkDir
|
|
13
|
-
} from "../chunk-
|
|
15
|
+
} from "../chunk-DTKK7TKL.js";
|
|
16
|
+
import "../chunk-6XMC64FJ.js";
|
|
17
|
+
import "../chunk-4ETS2LXI.js";
|
|
14
18
|
export {
|
|
15
19
|
folderGone,
|
|
16
20
|
isInHiddenOrVendorDir,
|
|
21
|
+
isPrivateProjectFile,
|
|
22
|
+
isPrivateProjectPath,
|
|
17
23
|
isProjectRootMissing,
|
|
18
24
|
isSafePath,
|
|
19
25
|
mkdirWithinProject,
|
package/dist/history/index.js
CHANGED
|
@@ -10,8 +10,10 @@ import {
|
|
|
10
10
|
listProjectHistories,
|
|
11
11
|
openProjectHistory,
|
|
12
12
|
pruneGoneProjectHistories
|
|
13
|
-
} from "../chunk-
|
|
14
|
-
import "../chunk-
|
|
13
|
+
} from "../chunk-K3H6HTVC.js";
|
|
14
|
+
import "../chunk-DTKK7TKL.js";
|
|
15
|
+
import "../chunk-6XMC64FJ.js";
|
|
16
|
+
import "../chunk-4ETS2LXI.js";
|
|
15
17
|
export {
|
|
16
18
|
DEFAULT_HISTORY_ROOT,
|
|
17
19
|
START as HISTORY_START,
|
package/dist/index.d.ts
CHANGED
|
@@ -25,6 +25,8 @@ import './helpers/mediaCodecMap.js';
|
|
|
25
25
|
*/
|
|
26
26
|
declare function createStudioApi(adapter: StudioApiAdapter): Hono;
|
|
27
27
|
|
|
28
|
+
declare const MAX_UPLOAD_BYTES: number;
|
|
29
|
+
|
|
28
30
|
/**
|
|
29
31
|
* Whether a write at `changedPath` can change `createProjectSignature(projectDir)`.
|
|
30
32
|
*
|
|
@@ -226,4 +228,4 @@ type BackgroundRemovalRender = (options: {
|
|
|
226
228
|
}>;
|
|
227
229
|
declare function createBackgroundRemovalJob(opts: BackgroundRemovalJobOptions, render: BackgroundRemovalRender): MediaProcessingJobState;
|
|
228
230
|
|
|
229
|
-
export { type AppliedFileMutation, type BackgroundRemovalRender, DELETED_VERSION, type DuplicateElementResult, type FileMutationInput, type FileWriteReceipt, MIME_TYPES, MediaProcessingJobState, PREVIEW_BUNDLE_OPTIONS, SourceMutationTarget, StudioApiAdapter, type ThumbnailOutputDimensions, affectsPreview, affectsProjectSignature, applyFileMutations, buildSubCompositionHtml, cleanupProxyCache, compositionsAffectedBy, consumeFileWriteReceipt, createBackgroundRemovalJob, createPreviewDocumentStore, createProjectSignature, createStudioApi, duplicateElementInHtml, fileContentVersion, getMimeType, identifyFileWrite, requestSubPath, settledFileTag, thumbnailDeviceScaleFactor };
|
|
231
|
+
export { type AppliedFileMutation, type BackgroundRemovalRender, DELETED_VERSION, type DuplicateElementResult, type FileMutationInput, type FileWriteReceipt, MAX_UPLOAD_BYTES, MIME_TYPES, MediaProcessingJobState, PREVIEW_BUNDLE_OPTIONS, SourceMutationTarget, StudioApiAdapter, type ThumbnailOutputDimensions, affectsPreview, affectsProjectSignature, applyFileMutations, buildSubCompositionHtml, cleanupProxyCache, compositionsAffectedBy, consumeFileWriteReceipt, createBackgroundRemovalJob, createPreviewDocumentStore, createProjectSignature, createStudioApi, duplicateElementInHtml, fileContentVersion, getMimeType, identifyFileWrite, requestSubPath, settledFileTag, thumbnailDeviceScaleFactor };
|
package/dist/index.js
CHANGED
|
@@ -21,7 +21,7 @@ import {
|
|
|
21
21
|
import {
|
|
22
22
|
isCompositionSource,
|
|
23
23
|
stampProjectHfIds
|
|
24
|
-
} from "./chunk-
|
|
24
|
+
} from "./chunk-DG2VOIGR.js";
|
|
25
25
|
import {
|
|
26
26
|
DEFAULT_HISTORY_ROOT,
|
|
27
27
|
DELETED_VERSION,
|
|
@@ -47,7 +47,7 @@ import {
|
|
|
47
47
|
resolveProjectAndSignature,
|
|
48
48
|
resolveProjectSignature,
|
|
49
49
|
settledFileTag
|
|
50
|
-
} from "./chunk-
|
|
50
|
+
} from "./chunk-K3H6HTVC.js";
|
|
51
51
|
import {
|
|
52
52
|
clearElementScreenshotIsolation,
|
|
53
53
|
getElementScreenshotClip
|
|
@@ -64,7 +64,7 @@ import {
|
|
|
64
64
|
isAutoProxyEnabled,
|
|
65
65
|
proxyEtagSalt,
|
|
66
66
|
resolvePreviewMediaCodecProbeCache
|
|
67
|
-
} from "./chunk-
|
|
67
|
+
} from "./chunk-G7FEKQ32.js";
|
|
68
68
|
import {
|
|
69
69
|
CACHE_DIR_NAME,
|
|
70
70
|
PROXY_PENDING_RETRY_AFTER_SECONDS,
|
|
@@ -75,7 +75,7 @@ import {
|
|
|
75
75
|
proxyActivityMark,
|
|
76
76
|
resolveProxy,
|
|
77
77
|
waitForProxy
|
|
78
|
-
} from "./chunk-
|
|
78
|
+
} from "./chunk-6RFZWPPN.js";
|
|
79
79
|
import {
|
|
80
80
|
PROXY_VARIANT_CONFIG,
|
|
81
81
|
decideMediaProxyEligibility,
|
|
@@ -84,10 +84,12 @@ import {
|
|
|
84
84
|
probeMediaMetadata,
|
|
85
85
|
recordProxyRequest,
|
|
86
86
|
resolveProxyVariantRequest
|
|
87
|
-
} from "./chunk-
|
|
87
|
+
} from "./chunk-74JVVCWL.js";
|
|
88
88
|
import {
|
|
89
89
|
folderGone,
|
|
90
90
|
isInHiddenOrVendorDir,
|
|
91
|
+
isPrivateProjectFile,
|
|
92
|
+
isPrivateProjectPath,
|
|
91
93
|
isProjectRootMissing,
|
|
92
94
|
isSafePath,
|
|
93
95
|
mkdirWithinProject,
|
|
@@ -96,7 +98,7 @@ import {
|
|
|
96
98
|
realpath,
|
|
97
99
|
resolveWithinProject,
|
|
98
100
|
walkDir
|
|
99
|
-
} from "./chunk-
|
|
101
|
+
} from "./chunk-DTKK7TKL.js";
|
|
100
102
|
import {
|
|
101
103
|
STUDIO_MANUAL_EDITS_PATH,
|
|
102
104
|
createStudioManualEditsRenderBodyScript,
|
|
@@ -149,7 +151,7 @@ function registerProjectRoutes(api, adapter) {
|
|
|
149
151
|
api.get("/projects/:id", async (c) => {
|
|
150
152
|
const project = await adapter.resolveProject(c.req.param("id"));
|
|
151
153
|
if (!project) return c.json({ error: "not found" }, 404);
|
|
152
|
-
const files = walkDir(project.dir);
|
|
154
|
+
const files = walkDir(project.dir).filter((file) => !isPrivateProjectPath(file));
|
|
153
155
|
const compositions = await filterCompositionFiles(project.dir, files);
|
|
154
156
|
return c.json({ id: project.id, dir: project.dir, title: project.title, files, compositions });
|
|
155
157
|
});
|
|
@@ -1572,7 +1574,7 @@ function updateReferences(projectDir, oldPath, newPath, isDirectory) {
|
|
|
1572
1574
|
const rewrite = referenceRewriter(oldPath, newPath, isDirectory, projectPaths(projectDir));
|
|
1573
1575
|
let updatedCount = 0;
|
|
1574
1576
|
for (const file of textFiles) {
|
|
1575
|
-
if (!isSafePath(projectDir, file)) continue;
|
|
1577
|
+
if (!isSafePath(projectDir, file) || isPrivateProjectFile(projectDir, file)) continue;
|
|
1576
1578
|
const content = readableText(file);
|
|
1577
1579
|
if (content === null) continue;
|
|
1578
1580
|
const updated = rewrite(content);
|
|
@@ -2681,8 +2683,8 @@ async function foldAtomicCutFile(c, file, absPath, before, writer) {
|
|
|
2681
2683
|
skippedSelectors: [...skippedSelectors]
|
|
2682
2684
|
};
|
|
2683
2685
|
}
|
|
2686
|
+
var MAX_UPLOAD_BYTES = 500 * 1024 * 1024;
|
|
2684
2687
|
async function processUploadedFiles(formData, targetDir, projectDir) {
|
|
2685
|
-
const MAX_UPLOAD_BYTES = 500 * 1024 * 1024;
|
|
2686
2688
|
const uploaded = [];
|
|
2687
2689
|
const skipped = [];
|
|
2688
2690
|
const invalid = [];
|
|
@@ -2716,7 +2718,7 @@ async function processUploadedFiles(formData, targetDir, projectDir) {
|
|
|
2716
2718
|
finalName = `${base} (${n})${ext}`;
|
|
2717
2719
|
finalPath = resolve2(targetDir, finalName);
|
|
2718
2720
|
}
|
|
2719
|
-
if (!isSafePath(projectDir, finalPath)) continue;
|
|
2721
|
+
if (!isSafePath(projectDir, finalPath) || isPrivateProjectFile(projectDir, finalPath)) continue;
|
|
2720
2722
|
const buffer = Buffer.from(await value.arrayBuffer());
|
|
2721
2723
|
const validation = validateUploadedMediaBuffer(finalName, buffer);
|
|
2722
2724
|
if (!validation.ok) {
|
|
@@ -3495,7 +3497,6 @@ function registerFileRoutes(api, adapter) {
|
|
|
3495
3497
|
}
|
|
3496
3498
|
return c.json({ ok: true, path: copyPath }, 201);
|
|
3497
3499
|
});
|
|
3498
|
-
const MAX_UPLOAD_BYTES = 500 * 1024 * 1024;
|
|
3499
3500
|
api.post(
|
|
3500
3501
|
"/projects/:id/upload",
|
|
3501
3502
|
bodyLimit({
|
|
@@ -3610,7 +3611,10 @@ import {
|
|
|
3610
3611
|
insertRuntimeTag,
|
|
3611
3612
|
stripEmbeddedRuntimeScripts as stripEmbeddedRuntimeScripts2
|
|
3612
3613
|
} from "@hyperframes/core/compiler";
|
|
3613
|
-
import {
|
|
3614
|
+
import {
|
|
3615
|
+
STUDIO_PREVIEW_MARK_META,
|
|
3616
|
+
STUDIO_PREVIEW_ERRORS
|
|
3617
|
+
} from "@hyperframes/core/studio-preview-mark";
|
|
3614
3618
|
import { gsapCdnDist as gsapCdnDist2, motionPathPluginUrl } from "@hyperframes/core/gsap-cdn";
|
|
3615
3619
|
import { findStartTags as findStartTags2, injectTagsAtHeadStart } from "@hyperframes/core/compiler/html-document";
|
|
3616
3620
|
import { isWithinProjectRoot } from "@hyperframes/parsers/asset-resolution";
|
|
@@ -3905,15 +3909,17 @@ var GSAP_CDN_FALLBACK_SCRIPT = `<script ${GSAP_FALLBACK_ATTR}>
|
|
|
3905
3909
|
if(loaded[file])return loaded[file];
|
|
3906
3910
|
return loaded[file]=new Promise(function(ok,fail){
|
|
3907
3911
|
var s=document.createElement("script");
|
|
3908
|
-
s.src=cdnBase+file;s.onload=ok;s.onerror=fail;
|
|
3912
|
+
s.src=cdnBase+file;s.hfGsapFallback=true;s.onload=ok;s.onerror=fail;
|
|
3909
3913
|
document.head.appendChild(s);
|
|
3910
3914
|
});
|
|
3911
3915
|
}
|
|
3912
3916
|
document.addEventListener("error",function(e){
|
|
3913
3917
|
var t=e.target;
|
|
3914
|
-
if(!t||t.tagName!=="SCRIPT"||!t.src)return;
|
|
3918
|
+
if(!t||t.tagName!=="SCRIPT"||!t.src||t.hfGsapFallback)return;
|
|
3915
3919
|
var m=t.src.match(/gsap[^/]*\\/dist\\/(.+\\.js)/);
|
|
3916
|
-
if(m)loadFallback(m[1])
|
|
3920
|
+
if(m)loadFallback(m[1]).catch(function(){
|
|
3921
|
+
reportError(new Error("GSAP could not load from "+t.src+" or "+cdnBase+m[1]+", so this preview's animations will not play."));
|
|
3922
|
+
});
|
|
3917
3923
|
},true);
|
|
3918
3924
|
})();
|
|
3919
3925
|
</script>`;
|
|
@@ -3945,8 +3951,13 @@ function previewVariablesFromRequest(rawVariables) {
|
|
|
3945
3951
|
return { raw: rawVariables, values: parse2.values };
|
|
3946
3952
|
}
|
|
3947
3953
|
var PREVIEW_CAPTURE_PARAM = "hf-capture";
|
|
3954
|
+
var EARLY_ERRORS_SCRIPT = `<script>(function(){var seen=window.${STUDIO_PREVIEW_ERRORS}=[];
|
|
3955
|
+
addEventListener("error",function(e){seen.push(e.message||String(e))});})();</script>`;
|
|
3948
3956
|
function injectStudioPreviewAugmentations(html, adapter, projectDir, activeCompositionPath, capture) {
|
|
3949
|
-
const marked = capture ? html : injectTagsAtHeadStart(
|
|
3957
|
+
const marked = capture ? html : injectTagsAtHeadStart(
|
|
3958
|
+
lazyPreviewImages(html),
|
|
3959
|
+
`<meta name="${STUDIO_PREVIEW_MARK_META}">${EARLY_ERRORS_SCRIPT}`
|
|
3960
|
+
);
|
|
3950
3961
|
return injectStudioMotionScript(
|
|
3951
3962
|
injectMotionPathPluginIfNeeded(
|
|
3952
3963
|
injectGsapCdnFallback(
|
|
@@ -4167,7 +4178,7 @@ ${etag}`;
|
|
|
4167
4178
|
const subPath = requestSubPath(c.req.url, "projects/:id/preview");
|
|
4168
4179
|
const candidate = resolve4(project.dir, subPath);
|
|
4169
4180
|
const file = isWithinProjectRoot(project.dir, candidate) ? candidate : null;
|
|
4170
|
-
if (!file) {
|
|
4181
|
+
if (!file || isPrivateProjectFile(project.dir, file)) {
|
|
4171
4182
|
return c.text("not found", 404);
|
|
4172
4183
|
}
|
|
4173
4184
|
recordPreviewRead(project.dir, file);
|
|
@@ -4321,7 +4332,7 @@ function registerLintRoutes(api, adapter) {
|
|
|
4321
4332
|
|
|
4322
4333
|
// src/routes/render.ts
|
|
4323
4334
|
import { streamSSE } from "hono/streaming";
|
|
4324
|
-
import { existsSync as existsSync6, readFileSync as readFileSync8, unlinkSync as unlinkSync3, readdirSync as readdirSync3, statSync as statSync5 } from "fs";
|
|
4335
|
+
import { existsSync as existsSync6, lstatSync as lstatSync3, readFileSync as readFileSync8, unlinkSync as unlinkSync3, readdirSync as readdirSync3, statSync as statSync5 } from "fs";
|
|
4325
4336
|
import { join as join10 } from "path";
|
|
4326
4337
|
import { VALID_CANVAS_RESOLUTIONS } from "@hyperframes/parsers";
|
|
4327
4338
|
import { formatRenderOutputTimestamp, parseFps } from "@hyperframes/core";
|
|
@@ -4449,6 +4460,13 @@ function registerRenderRoutes(api, adapter) {
|
|
|
4449
4460
|
".mov": "video/quicktime"
|
|
4450
4461
|
};
|
|
4451
4462
|
const RENDER_EXTENSIONS = Object.keys(RENDER_MIME);
|
|
4463
|
+
const isPlainFile = (path) => {
|
|
4464
|
+
try {
|
|
4465
|
+
return lstatSync3(path).isFile();
|
|
4466
|
+
} catch {
|
|
4467
|
+
return false;
|
|
4468
|
+
}
|
|
4469
|
+
};
|
|
4452
4470
|
function renderContentType(filePath) {
|
|
4453
4471
|
const ext = RENDER_EXTENSIONS.find((e) => filePath.endsWith(e));
|
|
4454
4472
|
return (ext && RENDER_MIME[ext]) ?? "video/mp4";
|
|
@@ -4456,7 +4474,7 @@ function registerRenderRoutes(api, adapter) {
|
|
|
4456
4474
|
api.get("/render/:jobId/view", (c) => {
|
|
4457
4475
|
const { jobId } = c.req.param();
|
|
4458
4476
|
const job = renderJobs.get(jobId);
|
|
4459
|
-
if (!job?.outputPath || !
|
|
4477
|
+
if (!job?.outputPath || !isPlainFile(job.outputPath)) {
|
|
4460
4478
|
return c.json({ error: "not found" }, 404);
|
|
4461
4479
|
}
|
|
4462
4480
|
const contentType = renderContentType(job.outputPath);
|
|
@@ -4474,7 +4492,7 @@ function registerRenderRoutes(api, adapter) {
|
|
|
4474
4492
|
api.get("/render/:jobId/download", (c) => {
|
|
4475
4493
|
const { jobId } = c.req.param();
|
|
4476
4494
|
const job = renderJobs.get(jobId);
|
|
4477
|
-
if (!job?.outputPath || !
|
|
4495
|
+
if (!job?.outputPath || !isPlainFile(job.outputPath)) {
|
|
4478
4496
|
return c.json({ error: "not found" }, 404);
|
|
4479
4497
|
}
|
|
4480
4498
|
const contentType = renderContentType(job.outputPath);
|
|
@@ -4509,7 +4527,7 @@ function registerRenderRoutes(api, adapter) {
|
|
|
4509
4527
|
if (!filename) return c.json({ error: "missing filename" }, 400);
|
|
4510
4528
|
const rendersDir = adapter.rendersDir(project);
|
|
4511
4529
|
const fp = resolveWithinProject(rendersDir, filename);
|
|
4512
|
-
if (!fp) return c.json({ error: "forbidden" }, 403);
|
|
4530
|
+
if (!fp || isPrivateProjectFile(project.dir, fp)) return c.json({ error: "forbidden" }, 403);
|
|
4513
4531
|
if (!existsSync6(fp)) return c.json({ error: "not found" }, 404);
|
|
4514
4532
|
const contentType = renderContentType(fp);
|
|
4515
4533
|
const content = readFileSync8(fp);
|
|
@@ -4527,8 +4545,10 @@ function registerRenderRoutes(api, adapter) {
|
|
|
4527
4545
|
if (!project) return c.json({ error: "not found" }, 404);
|
|
4528
4546
|
const rendersDir = adapter.rendersDir(project);
|
|
4529
4547
|
if (!existsSync6(rendersDir)) return c.json({ renders: [] });
|
|
4530
|
-
const files = readdirSync3(rendersDir).filter((f) => f.endsWith(".mp4") || f.endsWith(".webm") || f.endsWith(".mov")).
|
|
4531
|
-
const fp =
|
|
4548
|
+
const files = readdirSync3(rendersDir).filter((f) => f.endsWith(".mp4") || f.endsWith(".webm") || f.endsWith(".mov")).flatMap((f) => {
|
|
4549
|
+
const fp = resolveWithinProject(rendersDir, f);
|
|
4550
|
+
return fp && !isPrivateProjectFile(project.dir, fp) ? [{ f, fp }] : [];
|
|
4551
|
+
}).map(({ f, fp }) => {
|
|
4532
4552
|
const stat2 = statSync5(fp);
|
|
4533
4553
|
const rid = f.replace(/\.(mp4|webm|mov)$/, "");
|
|
4534
4554
|
const metaPath = join10(rendersDir, `${rid}.meta.json`);
|
|
@@ -4547,6 +4567,7 @@ function registerRenderRoutes(api, adapter) {
|
|
|
4547
4567
|
return {
|
|
4548
4568
|
id: rid,
|
|
4549
4569
|
filename: f,
|
|
4570
|
+
path: fp,
|
|
4550
4571
|
size: stat2.size,
|
|
4551
4572
|
createdAt: stat2.mtimeMs,
|
|
4552
4573
|
status,
|
|
@@ -4560,12 +4581,12 @@ function registerRenderRoutes(api, adapter) {
|
|
|
4560
4581
|
id: file.id,
|
|
4561
4582
|
status: file.status,
|
|
4562
4583
|
progress: 100,
|
|
4563
|
-
outputPath:
|
|
4584
|
+
outputPath: file.path,
|
|
4564
4585
|
createdAt: file.createdAt
|
|
4565
4586
|
});
|
|
4566
4587
|
}
|
|
4567
4588
|
}
|
|
4568
|
-
return c.json({ renders: files });
|
|
4589
|
+
return c.json({ renders: files.map(({ path: _path, ...render }) => render) });
|
|
4569
4590
|
});
|
|
4570
4591
|
}
|
|
4571
4592
|
|
|
@@ -6432,6 +6453,7 @@ export {
|
|
|
6432
6453
|
HistoryBusyError,
|
|
6433
6454
|
HistoryClosedError,
|
|
6434
6455
|
HistoryIdError,
|
|
6456
|
+
MAX_UPLOAD_BYTES,
|
|
6435
6457
|
MAX_WINDOW_IDLE_MS,
|
|
6436
6458
|
MIME_TYPES,
|
|
6437
6459
|
PREVIEW_BUNDLE_OPTIONS,
|