@hyperframes/studio-server 0.8.137 → 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.js +45 -23
- 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.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);
|
|
@@ -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) {
|
|
@@ -3609,7 +3611,10 @@ import {
|
|
|
3609
3611
|
insertRuntimeTag,
|
|
3610
3612
|
stripEmbeddedRuntimeScripts as stripEmbeddedRuntimeScripts2
|
|
3611
3613
|
} from "@hyperframes/core/compiler";
|
|
3612
|
-
import {
|
|
3614
|
+
import {
|
|
3615
|
+
STUDIO_PREVIEW_MARK_META,
|
|
3616
|
+
STUDIO_PREVIEW_ERRORS
|
|
3617
|
+
} from "@hyperframes/core/studio-preview-mark";
|
|
3613
3618
|
import { gsapCdnDist as gsapCdnDist2, motionPathPluginUrl } from "@hyperframes/core/gsap-cdn";
|
|
3614
3619
|
import { findStartTags as findStartTags2, injectTagsAtHeadStart } from "@hyperframes/core/compiler/html-document";
|
|
3615
3620
|
import { isWithinProjectRoot } from "@hyperframes/parsers/asset-resolution";
|
|
@@ -3904,15 +3909,17 @@ var GSAP_CDN_FALLBACK_SCRIPT = `<script ${GSAP_FALLBACK_ATTR}>
|
|
|
3904
3909
|
if(loaded[file])return loaded[file];
|
|
3905
3910
|
return loaded[file]=new Promise(function(ok,fail){
|
|
3906
3911
|
var s=document.createElement("script");
|
|
3907
|
-
s.src=cdnBase+file;s.onload=ok;s.onerror=fail;
|
|
3912
|
+
s.src=cdnBase+file;s.hfGsapFallback=true;s.onload=ok;s.onerror=fail;
|
|
3908
3913
|
document.head.appendChild(s);
|
|
3909
3914
|
});
|
|
3910
3915
|
}
|
|
3911
3916
|
document.addEventListener("error",function(e){
|
|
3912
3917
|
var t=e.target;
|
|
3913
|
-
if(!t||t.tagName!=="SCRIPT"||!t.src)return;
|
|
3918
|
+
if(!t||t.tagName!=="SCRIPT"||!t.src||t.hfGsapFallback)return;
|
|
3914
3919
|
var m=t.src.match(/gsap[^/]*\\/dist\\/(.+\\.js)/);
|
|
3915
|
-
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
|
+
});
|
|
3916
3923
|
},true);
|
|
3917
3924
|
})();
|
|
3918
3925
|
</script>`;
|
|
@@ -3944,8 +3951,13 @@ function previewVariablesFromRequest(rawVariables) {
|
|
|
3944
3951
|
return { raw: rawVariables, values: parse2.values };
|
|
3945
3952
|
}
|
|
3946
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>`;
|
|
3947
3956
|
function injectStudioPreviewAugmentations(html, adapter, projectDir, activeCompositionPath, capture) {
|
|
3948
|
-
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
|
+
);
|
|
3949
3961
|
return injectStudioMotionScript(
|
|
3950
3962
|
injectMotionPathPluginIfNeeded(
|
|
3951
3963
|
injectGsapCdnFallback(
|
|
@@ -4166,7 +4178,7 @@ ${etag}`;
|
|
|
4166
4178
|
const subPath = requestSubPath(c.req.url, "projects/:id/preview");
|
|
4167
4179
|
const candidate = resolve4(project.dir, subPath);
|
|
4168
4180
|
const file = isWithinProjectRoot(project.dir, candidate) ? candidate : null;
|
|
4169
|
-
if (!file) {
|
|
4181
|
+
if (!file || isPrivateProjectFile(project.dir, file)) {
|
|
4170
4182
|
return c.text("not found", 404);
|
|
4171
4183
|
}
|
|
4172
4184
|
recordPreviewRead(project.dir, file);
|
|
@@ -4320,7 +4332,7 @@ function registerLintRoutes(api, adapter) {
|
|
|
4320
4332
|
|
|
4321
4333
|
// src/routes/render.ts
|
|
4322
4334
|
import { streamSSE } from "hono/streaming";
|
|
4323
|
-
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";
|
|
4324
4336
|
import { join as join10 } from "path";
|
|
4325
4337
|
import { VALID_CANVAS_RESOLUTIONS } from "@hyperframes/parsers";
|
|
4326
4338
|
import { formatRenderOutputTimestamp, parseFps } from "@hyperframes/core";
|
|
@@ -4448,6 +4460,13 @@ function registerRenderRoutes(api, adapter) {
|
|
|
4448
4460
|
".mov": "video/quicktime"
|
|
4449
4461
|
};
|
|
4450
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
|
+
};
|
|
4451
4470
|
function renderContentType(filePath) {
|
|
4452
4471
|
const ext = RENDER_EXTENSIONS.find((e) => filePath.endsWith(e));
|
|
4453
4472
|
return (ext && RENDER_MIME[ext]) ?? "video/mp4";
|
|
@@ -4455,7 +4474,7 @@ function registerRenderRoutes(api, adapter) {
|
|
|
4455
4474
|
api.get("/render/:jobId/view", (c) => {
|
|
4456
4475
|
const { jobId } = c.req.param();
|
|
4457
4476
|
const job = renderJobs.get(jobId);
|
|
4458
|
-
if (!job?.outputPath || !
|
|
4477
|
+
if (!job?.outputPath || !isPlainFile(job.outputPath)) {
|
|
4459
4478
|
return c.json({ error: "not found" }, 404);
|
|
4460
4479
|
}
|
|
4461
4480
|
const contentType = renderContentType(job.outputPath);
|
|
@@ -4473,7 +4492,7 @@ function registerRenderRoutes(api, adapter) {
|
|
|
4473
4492
|
api.get("/render/:jobId/download", (c) => {
|
|
4474
4493
|
const { jobId } = c.req.param();
|
|
4475
4494
|
const job = renderJobs.get(jobId);
|
|
4476
|
-
if (!job?.outputPath || !
|
|
4495
|
+
if (!job?.outputPath || !isPlainFile(job.outputPath)) {
|
|
4477
4496
|
return c.json({ error: "not found" }, 404);
|
|
4478
4497
|
}
|
|
4479
4498
|
const contentType = renderContentType(job.outputPath);
|
|
@@ -4508,7 +4527,7 @@ function registerRenderRoutes(api, adapter) {
|
|
|
4508
4527
|
if (!filename) return c.json({ error: "missing filename" }, 400);
|
|
4509
4528
|
const rendersDir = adapter.rendersDir(project);
|
|
4510
4529
|
const fp = resolveWithinProject(rendersDir, filename);
|
|
4511
|
-
if (!fp) return c.json({ error: "forbidden" }, 403);
|
|
4530
|
+
if (!fp || isPrivateProjectFile(project.dir, fp)) return c.json({ error: "forbidden" }, 403);
|
|
4512
4531
|
if (!existsSync6(fp)) return c.json({ error: "not found" }, 404);
|
|
4513
4532
|
const contentType = renderContentType(fp);
|
|
4514
4533
|
const content = readFileSync8(fp);
|
|
@@ -4526,8 +4545,10 @@ function registerRenderRoutes(api, adapter) {
|
|
|
4526
4545
|
if (!project) return c.json({ error: "not found" }, 404);
|
|
4527
4546
|
const rendersDir = adapter.rendersDir(project);
|
|
4528
4547
|
if (!existsSync6(rendersDir)) return c.json({ renders: [] });
|
|
4529
|
-
const files = readdirSync3(rendersDir).filter((f) => f.endsWith(".mp4") || f.endsWith(".webm") || f.endsWith(".mov")).
|
|
4530
|
-
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 }) => {
|
|
4531
4552
|
const stat2 = statSync5(fp);
|
|
4532
4553
|
const rid = f.replace(/\.(mp4|webm|mov)$/, "");
|
|
4533
4554
|
const metaPath = join10(rendersDir, `${rid}.meta.json`);
|
|
@@ -4546,6 +4567,7 @@ function registerRenderRoutes(api, adapter) {
|
|
|
4546
4567
|
return {
|
|
4547
4568
|
id: rid,
|
|
4548
4569
|
filename: f,
|
|
4570
|
+
path: fp,
|
|
4549
4571
|
size: stat2.size,
|
|
4550
4572
|
createdAt: stat2.mtimeMs,
|
|
4551
4573
|
status,
|
|
@@ -4559,12 +4581,12 @@ function registerRenderRoutes(api, adapter) {
|
|
|
4559
4581
|
id: file.id,
|
|
4560
4582
|
status: file.status,
|
|
4561
4583
|
progress: 100,
|
|
4562
|
-
outputPath:
|
|
4584
|
+
outputPath: file.path,
|
|
4563
4585
|
createdAt: file.createdAt
|
|
4564
4586
|
});
|
|
4565
4587
|
}
|
|
4566
4588
|
}
|
|
4567
|
-
return c.json({ renders: files });
|
|
4589
|
+
return c.json({ renders: files.map(({ path: _path, ...render }) => render) });
|
|
4568
4590
|
});
|
|
4569
4591
|
}
|
|
4570
4592
|
|