@remotion/studio-server 4.0.514 → 4.0.515
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/helpers/open-file-for-writing-without-symlinks.d.ts +4 -0
- package/dist/helpers/open-file-for-writing-without-symlinks.js +52 -0
- package/dist/helpers/video-config-values.js +25 -6
- package/dist/preview-server/routes/delete-effect-keyframe.d.ts +3 -0
- package/dist/preview-server/routes/delete-effect-keyframe.js +89 -0
- package/dist/preview-server/routes/delete-sequence-keyframe.d.ts +3 -0
- package/dist/preview-server/routes/delete-sequence-keyframe.js +82 -0
- package/dist/preview-server/routes/install-dependency.js +8 -2
- package/dist/preview-server/routes/save-props-mutex.d.ts +1 -0
- package/dist/preview-server/routes/save-props-mutex.js +11 -0
- package/dist/routes.js +36 -5
- package/package.json +8 -8
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.openFileForWritingWithoutSymlinks = void 0;
|
|
7
|
+
const node_fs_1 = __importDefault(require("node:fs"));
|
|
8
|
+
const node_path_1 = __importDefault(require("node:path"));
|
|
9
|
+
const assertNoSymlinks = ({ rootDirectory, absolutePath, }) => {
|
|
10
|
+
const relativePath = node_path_1.default.relative(rootDirectory, absolutePath);
|
|
11
|
+
if (relativePath === '..' ||
|
|
12
|
+
relativePath.startsWith(`..${node_path_1.default.sep}`) ||
|
|
13
|
+
node_path_1.default.isAbsolute(relativePath)) {
|
|
14
|
+
throw new Error(`Not allowed to write to ${relativePath}`);
|
|
15
|
+
}
|
|
16
|
+
let pathToCheck = rootDirectory;
|
|
17
|
+
for (const segment of relativePath.split(node_path_1.default.sep)) {
|
|
18
|
+
pathToCheck = node_path_1.default.join(pathToCheck, segment);
|
|
19
|
+
try {
|
|
20
|
+
if (node_fs_1.default.lstatSync(pathToCheck).isSymbolicLink()) {
|
|
21
|
+
throw new Error(`Not allowed to write through symbolic link ${pathToCheck}`);
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
catch (error) {
|
|
25
|
+
if (error.code === 'ENOENT') {
|
|
26
|
+
break;
|
|
27
|
+
}
|
|
28
|
+
throw error;
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
};
|
|
32
|
+
const openFileForWritingWithoutSymlinks = ({ rootDirectory, absolutePath, }) => {
|
|
33
|
+
const resolvedRootDirectory = node_path_1.default.resolve(rootDirectory);
|
|
34
|
+
const resolvedAbsolutePath = node_path_1.default.resolve(absolutePath);
|
|
35
|
+
assertNoSymlinks({
|
|
36
|
+
rootDirectory: resolvedRootDirectory,
|
|
37
|
+
absolutePath: resolvedAbsolutePath,
|
|
38
|
+
});
|
|
39
|
+
node_fs_1.default.mkdirSync(node_path_1.default.dirname(resolvedAbsolutePath), { recursive: true });
|
|
40
|
+
assertNoSymlinks({
|
|
41
|
+
rootDirectory: resolvedRootDirectory,
|
|
42
|
+
absolutePath: resolvedAbsolutePath,
|
|
43
|
+
});
|
|
44
|
+
const flags = process.platform === 'win32'
|
|
45
|
+
? 'w'
|
|
46
|
+
: node_fs_1.default.constants.O_CREAT |
|
|
47
|
+
node_fs_1.default.constants.O_WRONLY |
|
|
48
|
+
node_fs_1.default.constants.O_TRUNC |
|
|
49
|
+
node_fs_1.default.constants.O_NOFOLLOW;
|
|
50
|
+
return node_fs_1.default.openSync(resolvedAbsolutePath, flags);
|
|
51
|
+
};
|
|
52
|
+
exports.openFileForWritingWithoutSymlinks = openFileForWritingWithoutSymlinks;
|
|
@@ -36,15 +36,21 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
36
36
|
exports.getVideoConfigIdentifierValues = void 0;
|
|
37
37
|
const recast = __importStar(require("recast"));
|
|
38
38
|
const getVideoConfigIdentifierValues = ({ ast, videoConfigValues, }) => {
|
|
39
|
-
if (videoConfigValues === null) {
|
|
40
|
-
return {};
|
|
41
|
-
}
|
|
42
39
|
const candidates = new Map();
|
|
43
40
|
const otherDeclarations = new Set();
|
|
41
|
+
const addCandidate = (identifier, value) => {
|
|
42
|
+
if (candidates.has(identifier) || otherDeclarations.has(identifier)) {
|
|
43
|
+
candidates.delete(identifier);
|
|
44
|
+
otherDeclarations.add(identifier);
|
|
45
|
+
return;
|
|
46
|
+
}
|
|
47
|
+
candidates.set(identifier, value);
|
|
48
|
+
};
|
|
44
49
|
recast.types.visit(ast, {
|
|
45
50
|
visitVariableDeclarator(path) {
|
|
46
51
|
const { id, init } = path.node;
|
|
47
|
-
const isVideoConfigDeclaration =
|
|
52
|
+
const isVideoConfigDeclaration = videoConfigValues !== null &&
|
|
53
|
+
id.type === 'ObjectPattern' &&
|
|
48
54
|
(init === null || init === void 0 ? void 0 : init.type) === 'CallExpression' &&
|
|
49
55
|
init.callee.type === 'Identifier' &&
|
|
50
56
|
init.callee.name === 'useVideoConfig' &&
|
|
@@ -66,12 +72,25 @@ const getVideoConfigIdentifierValues = ({ ast, videoConfigValues, }) => {
|
|
|
66
72
|
}
|
|
67
73
|
const value = videoConfigValues[configKey];
|
|
68
74
|
if (Number.isFinite(value)) {
|
|
69
|
-
|
|
75
|
+
addCandidate(property.value.name, value);
|
|
70
76
|
}
|
|
71
77
|
}
|
|
72
78
|
}
|
|
73
79
|
else if (id.type === 'Identifier') {
|
|
74
|
-
|
|
80
|
+
const declaration = path.parentPath.node;
|
|
81
|
+
const numericConstant = declaration.type === 'VariableDeclaration' &&
|
|
82
|
+
declaration.kind === 'const' &&
|
|
83
|
+
(init === null || init === void 0 ? void 0 : init.type) === 'NumericLiteral' &&
|
|
84
|
+
Number.isFinite(init.value)
|
|
85
|
+
? init.value
|
|
86
|
+
: null;
|
|
87
|
+
if (numericConstant !== null) {
|
|
88
|
+
addCandidate(id.name, numericConstant);
|
|
89
|
+
}
|
|
90
|
+
else {
|
|
91
|
+
candidates.delete(id.name);
|
|
92
|
+
otherDeclarations.add(id.name);
|
|
93
|
+
}
|
|
75
94
|
}
|
|
76
95
|
this.traverse(path);
|
|
77
96
|
},
|
|
@@ -0,0 +1,3 @@
|
|
|
1
|
+
import type { DeleteEffectKeyframeRequest, DeleteEffectKeyframeResponse } from '@remotion/studio-shared';
|
|
2
|
+
import type { ApiHandler } from '../api-types';
|
|
3
|
+
export declare const deleteEffectKeyframeHandler: ApiHandler<DeleteEffectKeyframeRequest, DeleteEffectKeyframeResponse>;
|
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.deleteEffectKeyframeHandler = void 0;
|
|
4
|
+
const node_fs_1 = require("node:fs");
|
|
5
|
+
const renderer_1 = require("@remotion/renderer");
|
|
6
|
+
const studio_shared_1 = require("@remotion/studio-shared");
|
|
7
|
+
const parse_ast_1 = require("../../codemods/parse-ast");
|
|
8
|
+
const update_keyframes_1 = require("../../codemods/update-keyframes/update-keyframes");
|
|
9
|
+
const file_watcher_1 = require("../../file-watcher");
|
|
10
|
+
const resolve_file_inside_project_1 = require("../../helpers/resolve-file-inside-project");
|
|
11
|
+
const undo_stack_1 = require("../undo-stack");
|
|
12
|
+
const watch_ignore_next_change_1 = require("../watch-ignore-next-change");
|
|
13
|
+
const can_update_effect_props_1 = require("./can-update-effect-props");
|
|
14
|
+
const can_update_sequence_props_1 = require("./can-update-sequence-props");
|
|
15
|
+
const log_effect_update_1 = require("./log-updates/log-effect-update");
|
|
16
|
+
const save_props_mutex_1 = require("./save-props-mutex");
|
|
17
|
+
const deleteEffectKeyframeHandler = ({ input: { fileName, sequenceNodePath, effectIndex, key, frame, schema, clientId, }, remotionRoot, logLevel, }) => (0, save_props_mutex_1.withSavePropsLock)(async () => {
|
|
18
|
+
renderer_1.RenderInternals.Log.trace({ indent: false, logLevel }, `[delete-effect-keyframe] Received request for fileName="${fileName}" effectIndex=${effectIndex} key="${key}" frame=${frame}`);
|
|
19
|
+
const { absolutePath, fileRelativeToRoot } = (0, resolve_file_inside_project_1.resolveFileInsideProject)({
|
|
20
|
+
remotionRoot,
|
|
21
|
+
fileName,
|
|
22
|
+
action: 'modify',
|
|
23
|
+
});
|
|
24
|
+
const fileContents = (0, node_fs_1.readFileSync)(absolutePath, 'utf-8');
|
|
25
|
+
const { output, oldValueStrings, newValueStrings, formatted, logLine, effectCallee, } = await (0, update_keyframes_1.updateEffectKeyframes)({
|
|
26
|
+
input: fileContents,
|
|
27
|
+
sequenceNodePath: sequenceNodePath.nodePath,
|
|
28
|
+
effectIndex,
|
|
29
|
+
updates: [
|
|
30
|
+
{
|
|
31
|
+
key,
|
|
32
|
+
operation: {
|
|
33
|
+
type: 'remove',
|
|
34
|
+
frame,
|
|
35
|
+
},
|
|
36
|
+
},
|
|
37
|
+
],
|
|
38
|
+
});
|
|
39
|
+
const oldValueString = oldValueStrings[0];
|
|
40
|
+
const newValueString = newValueStrings[0];
|
|
41
|
+
const undoPropChange = `${key} keyframe restored at frame ${frame}`;
|
|
42
|
+
const redoPropChange = `${key} keyframe deleted at frame ${frame}`;
|
|
43
|
+
(0, undo_stack_1.pushToUndoStack)({
|
|
44
|
+
filePath: absolutePath,
|
|
45
|
+
oldContents: fileContents,
|
|
46
|
+
newContents: null,
|
|
47
|
+
logLevel,
|
|
48
|
+
remotionRoot,
|
|
49
|
+
logLine,
|
|
50
|
+
description: {
|
|
51
|
+
undoMessage: `↩️ ${undoPropChange}`,
|
|
52
|
+
redoMessage: `↪️ ${redoPropChange}`,
|
|
53
|
+
},
|
|
54
|
+
entryType: 'effect-props',
|
|
55
|
+
suppressHmrOnFileRestore: true,
|
|
56
|
+
});
|
|
57
|
+
(0, undo_stack_1.suppressUndoStackInvalidation)(absolutePath);
|
|
58
|
+
(0, watch_ignore_next_change_1.suppressBundlerUpdateForFile)(absolutePath);
|
|
59
|
+
(0, file_watcher_1.writeFileAndNotifyFileWatchers)(absolutePath, output, clientId);
|
|
60
|
+
(0, log_effect_update_1.logEffectUpdate)({
|
|
61
|
+
fileRelativeToRoot,
|
|
62
|
+
line: logLine,
|
|
63
|
+
effectName: effectCallee,
|
|
64
|
+
propKey: key,
|
|
65
|
+
oldValueString,
|
|
66
|
+
newValueString,
|
|
67
|
+
defaultValueString: null,
|
|
68
|
+
formatted,
|
|
69
|
+
logLevel,
|
|
70
|
+
removedProps: [],
|
|
71
|
+
addedProps: [],
|
|
72
|
+
});
|
|
73
|
+
(0, undo_stack_1.printUndoHint)(logLevel);
|
|
74
|
+
const ast = (0, parse_ast_1.parseAst)((0, node_fs_1.readFileSync)(absolutePath, 'utf-8'));
|
|
75
|
+
const jsx = (0, can_update_sequence_props_1.findJsxElementAtNodePath)(ast, sequenceNodePath.nodePath);
|
|
76
|
+
if (!jsx) {
|
|
77
|
+
return {
|
|
78
|
+
canUpdate: false,
|
|
79
|
+
effectIndex,
|
|
80
|
+
reason: 'not-found',
|
|
81
|
+
};
|
|
82
|
+
}
|
|
83
|
+
return (0, can_update_effect_props_1.computeEffectPropStatus)({
|
|
84
|
+
jsx,
|
|
85
|
+
effectIndex,
|
|
86
|
+
keys: (0, studio_shared_1.getAllSchemaKeys)(schema),
|
|
87
|
+
});
|
|
88
|
+
});
|
|
89
|
+
exports.deleteEffectKeyframeHandler = deleteEffectKeyframeHandler;
|
|
@@ -0,0 +1,3 @@
|
|
|
1
|
+
import type { DeleteSequenceKeyframeRequest, DeleteSequenceKeyframeResponse } from '@remotion/studio-shared';
|
|
2
|
+
import type { ApiHandler } from '../api-types';
|
|
3
|
+
export declare const deleteSequenceKeyframeHandler: ApiHandler<DeleteSequenceKeyframeRequest, DeleteSequenceKeyframeResponse>;
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.deleteSequenceKeyframeHandler = void 0;
|
|
4
|
+
const node_fs_1 = require("node:fs");
|
|
5
|
+
const renderer_1 = require("@remotion/renderer");
|
|
6
|
+
const studio_shared_1 = require("@remotion/studio-shared");
|
|
7
|
+
const update_keyframes_1 = require("../../codemods/update-keyframes/update-keyframes");
|
|
8
|
+
const file_watcher_1 = require("../../file-watcher");
|
|
9
|
+
const resolve_file_inside_project_1 = require("../../helpers/resolve-file-inside-project");
|
|
10
|
+
const undo_stack_1 = require("../undo-stack");
|
|
11
|
+
const watch_ignore_next_change_1 = require("../watch-ignore-next-change");
|
|
12
|
+
const can_update_sequence_props_1 = require("./can-update-sequence-props");
|
|
13
|
+
const log_update_1 = require("./log-updates/log-update");
|
|
14
|
+
const save_props_mutex_1 = require("./save-props-mutex");
|
|
15
|
+
const deleteSequenceKeyframeHandler = ({ input: { fileName, nodePath, key, frame, schema, clientId }, remotionRoot, logLevel, }) => (0, save_props_mutex_1.withSavePropsLock)(async () => {
|
|
16
|
+
renderer_1.RenderInternals.Log.trace({ indent: false, logLevel }, `[delete-sequence-keyframe] Received request for fileName="${fileName}" key="${key}" frame=${frame}`);
|
|
17
|
+
const { absolutePath, fileRelativeToRoot } = (0, resolve_file_inside_project_1.resolveFileInsideProject)({
|
|
18
|
+
remotionRoot,
|
|
19
|
+
fileName,
|
|
20
|
+
action: 'modify',
|
|
21
|
+
});
|
|
22
|
+
const fileContents = (0, node_fs_1.readFileSync)(absolutePath, 'utf-8');
|
|
23
|
+
const { output, oldValueStrings, newValueStrings, formatted, logLine } = await (0, update_keyframes_1.updateSequenceKeyframes)({
|
|
24
|
+
input: fileContents,
|
|
25
|
+
nodePath: nodePath.nodePath,
|
|
26
|
+
updates: [
|
|
27
|
+
{
|
|
28
|
+
key,
|
|
29
|
+
operation: {
|
|
30
|
+
type: 'remove',
|
|
31
|
+
frame,
|
|
32
|
+
},
|
|
33
|
+
},
|
|
34
|
+
],
|
|
35
|
+
});
|
|
36
|
+
const oldValueString = oldValueStrings[0];
|
|
37
|
+
const newValueString = newValueStrings[0];
|
|
38
|
+
const undoPropChange = `${key} keyframe restored at frame ${frame}`;
|
|
39
|
+
const redoPropChange = `${key} keyframe deleted at frame ${frame}`;
|
|
40
|
+
(0, undo_stack_1.pushToUndoStack)({
|
|
41
|
+
filePath: absolutePath,
|
|
42
|
+
oldContents: fileContents,
|
|
43
|
+
newContents: null,
|
|
44
|
+
logLevel,
|
|
45
|
+
remotionRoot,
|
|
46
|
+
logLine,
|
|
47
|
+
description: {
|
|
48
|
+
undoMessage: `↩️ ${undoPropChange}`,
|
|
49
|
+
redoMessage: `↪️ ${redoPropChange}`,
|
|
50
|
+
},
|
|
51
|
+
entryType: 'sequence-props',
|
|
52
|
+
suppressHmrOnFileRestore: true,
|
|
53
|
+
});
|
|
54
|
+
(0, undo_stack_1.suppressUndoStackInvalidation)(absolutePath);
|
|
55
|
+
(0, watch_ignore_next_change_1.suppressBundlerUpdateForFile)(absolutePath);
|
|
56
|
+
(0, file_watcher_1.writeFileAndNotifyFileWatchers)(absolutePath, output, clientId);
|
|
57
|
+
(0, log_update_1.logUpdate)({
|
|
58
|
+
fileRelativeToRoot,
|
|
59
|
+
line: logLine,
|
|
60
|
+
key,
|
|
61
|
+
oldValueString,
|
|
62
|
+
newValueString,
|
|
63
|
+
defaultValueString: null,
|
|
64
|
+
formatted,
|
|
65
|
+
logLevel,
|
|
66
|
+
removedProps: [],
|
|
67
|
+
addedProps: [],
|
|
68
|
+
});
|
|
69
|
+
(0, undo_stack_1.printUndoHint)(logLevel);
|
|
70
|
+
const status = (0, can_update_sequence_props_1.computeSequencePropsStatusFromContent)({
|
|
71
|
+
fileContents: output,
|
|
72
|
+
keys: (0, studio_shared_1.getAllSchemaKeys)(schema),
|
|
73
|
+
nodePath: nodePath.nodePath,
|
|
74
|
+
effects: [],
|
|
75
|
+
});
|
|
76
|
+
return {
|
|
77
|
+
canUpdate: true,
|
|
78
|
+
props: status.props,
|
|
79
|
+
results: [{ fileName, nodePath, props: status.props }],
|
|
80
|
+
};
|
|
81
|
+
});
|
|
82
|
+
exports.deleteSequenceKeyframeHandler = deleteSequenceKeyframeHandler;
|
|
@@ -46,13 +46,19 @@ const handleInstallPackage = async ({ logLevel, remotionRoot, input: { dependenc
|
|
|
46
46
|
manager: manager.manager,
|
|
47
47
|
packages: packagesWithVersions,
|
|
48
48
|
version: '',
|
|
49
|
-
additionalArgs: [],
|
|
49
|
+
additionalArgs: manager.manager === 'yarn' ? [] : ['--ignore-scripts'],
|
|
50
50
|
});
|
|
51
51
|
renderer_1.RenderInternals.Log.info({ indent: false, logLevel }, renderer_1.RenderInternals.chalk.gray(`╭─ ${manager.manager} ${command.join(' ')}`));
|
|
52
52
|
const time = Date.now();
|
|
53
53
|
try {
|
|
54
54
|
await new Promise((resolve, reject) => {
|
|
55
|
-
const cmd = (0, node_child_process_1.spawn)(manager.manager, command,
|
|
55
|
+
const cmd = (0, node_child_process_1.spawn)(manager.manager, command, {
|
|
56
|
+
...(0, package_manager_spawn_options_1.getPackageManagerSpawnOptions)(),
|
|
57
|
+
env: {
|
|
58
|
+
...process.env,
|
|
59
|
+
YARN_ENABLE_SCRIPTS: 'false',
|
|
60
|
+
},
|
|
61
|
+
});
|
|
56
62
|
cmd.on('error', reject);
|
|
57
63
|
cmd.stdout.on('data', (d) => d
|
|
58
64
|
.toString()
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare const withSavePropsLock: <T>(fn: () => Promise<T>) => Promise<T>;
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.withSavePropsLock = void 0;
|
|
4
|
+
let chain = Promise.resolve();
|
|
5
|
+
const withSavePropsLock = (fn) => {
|
|
6
|
+
const run = () => fn();
|
|
7
|
+
const next = chain.then(run, run);
|
|
8
|
+
chain = next.then(() => undefined, () => undefined);
|
|
9
|
+
return next;
|
|
10
|
+
};
|
|
11
|
+
exports.withSavePropsLock = withSavePropsLock;
|
package/dist/routes.js
CHANGED
|
@@ -34,7 +34,6 @@ var __importStar = (this && this.__importStar) || (function () {
|
|
|
34
34
|
})();
|
|
35
35
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
36
36
|
exports.handleRoutes = void 0;
|
|
37
|
-
const fs_1 = __importStar(require("fs"));
|
|
38
37
|
const node_fs_1 = require("node:fs");
|
|
39
38
|
const node_path_1 = __importStar(require("node:path"));
|
|
40
39
|
const node_url_1 = require("node:url");
|
|
@@ -45,6 +44,7 @@ const better_opn_1 = require("./better-opn");
|
|
|
45
44
|
const client_render_queue_1 = require("./client-render-queue");
|
|
46
45
|
const get_file_source_1 = require("./helpers/get-file-source");
|
|
47
46
|
const get_installed_installable_packages_1 = require("./helpers/get-installed-installable-packages");
|
|
47
|
+
const open_file_for_writing_without_symlinks_1 = require("./helpers/open-file-for-writing-without-symlinks");
|
|
48
48
|
const resolve_output_path_1 = require("./helpers/resolve-output-path");
|
|
49
49
|
const api_routes_1 = require("./preview-server/api-routes");
|
|
50
50
|
const get_package_manager_1 = require("./preview-server/get-package-manager");
|
|
@@ -61,6 +61,21 @@ const origin_policy_1 = require("./preview-server/studio-protocol/origin-policy"
|
|
|
61
61
|
const validate_same_origin_1 = require("./preview-server/validate-same-origin");
|
|
62
62
|
const watch_ignore_next_change_1 = require("./preview-server/watch-ignore-next-change");
|
|
63
63
|
const loggedStaticFileHints = new Set();
|
|
64
|
+
const clientRenderOutputExtensions = new Set([
|
|
65
|
+
'aac',
|
|
66
|
+
'flac',
|
|
67
|
+
'jpeg',
|
|
68
|
+
'jpg',
|
|
69
|
+
'mkv',
|
|
70
|
+
'mov',
|
|
71
|
+
'mp3',
|
|
72
|
+
'mp4',
|
|
73
|
+
'ogg',
|
|
74
|
+
'png',
|
|
75
|
+
'wav',
|
|
76
|
+
'webm',
|
|
77
|
+
'webp',
|
|
78
|
+
]);
|
|
64
79
|
const static404 = (response) => {
|
|
65
80
|
response.writeHead(404);
|
|
66
81
|
response.end('The static/ prefix has been changed, this URL is no longer valid.');
|
|
@@ -188,8 +203,14 @@ const handleAddAsset = ({ req, res, search, publicDir, }) => {
|
|
|
188
203
|
if (relativeToPublicDir.startsWith('..')) {
|
|
189
204
|
throw new Error(`Not allowed to write to ${relativeToPublicDir}`);
|
|
190
205
|
}
|
|
191
|
-
|
|
192
|
-
|
|
206
|
+
const fileDescriptor = (0, open_file_for_writing_without_symlinks_1.openFileForWritingWithoutSymlinks)({
|
|
207
|
+
rootDirectory: publicDir,
|
|
208
|
+
absolutePath,
|
|
209
|
+
});
|
|
210
|
+
const writeStream = (0, node_fs_1.createWriteStream)(absolutePath, {
|
|
211
|
+
fd: fileDescriptor,
|
|
212
|
+
autoClose: true,
|
|
213
|
+
});
|
|
193
214
|
writeStream.on('close', () => {
|
|
194
215
|
res.end(JSON.stringify({ success: true }));
|
|
195
216
|
});
|
|
@@ -210,8 +231,18 @@ const handleUploadOutput = ({ req, res, search, remotionRoot, }) => {
|
|
|
210
231
|
throw new Error('No `filePath` provided');
|
|
211
232
|
}
|
|
212
233
|
const absolutePath = (0, resolve_output_path_1.resolveOutputPath)(remotionRoot, filePath);
|
|
213
|
-
|
|
214
|
-
|
|
234
|
+
const extension = node_path_1.default.extname(absolutePath).slice(1).toLowerCase();
|
|
235
|
+
if (!clientRenderOutputExtensions.has(extension)) {
|
|
236
|
+
throw new Error(`Not allowed to upload a .${extension || 'unknown'} file`);
|
|
237
|
+
}
|
|
238
|
+
const fileDescriptor = (0, open_file_for_writing_without_symlinks_1.openFileForWritingWithoutSymlinks)({
|
|
239
|
+
rootDirectory: remotionRoot,
|
|
240
|
+
absolutePath,
|
|
241
|
+
});
|
|
242
|
+
const writeStream = (0, node_fs_1.createWriteStream)(absolutePath, {
|
|
243
|
+
fd: fileDescriptor,
|
|
244
|
+
autoClose: true,
|
|
245
|
+
});
|
|
215
246
|
writeStream.on('close', () => {
|
|
216
247
|
res.end(JSON.stringify({ success: true }));
|
|
217
248
|
});
|
package/package.json
CHANGED
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
"url": "https://github.com/remotion-dev/remotion/tree/main/packages/studio-server"
|
|
4
4
|
},
|
|
5
5
|
"name": "@remotion/studio-server",
|
|
6
|
-
"version": "4.0.
|
|
6
|
+
"version": "4.0.515",
|
|
7
7
|
"description": "Run a Remotion Studio with a server backend",
|
|
8
8
|
"main": "dist",
|
|
9
9
|
"scripts": {
|
|
@@ -23,7 +23,7 @@
|
|
|
23
23
|
"access": "public"
|
|
24
24
|
},
|
|
25
25
|
"dependencies": {
|
|
26
|
-
"@remotion/studio-protocol": "4.0.
|
|
26
|
+
"@remotion/studio-protocol": "4.0.515",
|
|
27
27
|
"@babel/types": "7.24.0",
|
|
28
28
|
"@babel/parser": "7.24.1",
|
|
29
29
|
"@svgr/core": "8.1.0",
|
|
@@ -32,12 +32,12 @@
|
|
|
32
32
|
"semver": "7.5.3",
|
|
33
33
|
"zod": "4.4.3",
|
|
34
34
|
"prettier": "3.8.1",
|
|
35
|
-
"remotion": "4.0.
|
|
35
|
+
"remotion": "4.0.515",
|
|
36
36
|
"recast": "0.23.11",
|
|
37
|
-
"@remotion/bundler": "4.0.
|
|
38
|
-
"@remotion/renderer": "4.0.
|
|
39
|
-
"@remotion/studio-codemods": "4.0.
|
|
40
|
-
"@remotion/studio-shared": "4.0.
|
|
37
|
+
"@remotion/bundler": "4.0.515",
|
|
38
|
+
"@remotion/renderer": "4.0.515",
|
|
39
|
+
"@remotion/studio-codemods": "4.0.515",
|
|
40
|
+
"@remotion/studio-shared": "4.0.515",
|
|
41
41
|
"memfs": "3.4.3",
|
|
42
42
|
"open": "8.4.2"
|
|
43
43
|
},
|
|
@@ -45,7 +45,7 @@
|
|
|
45
45
|
"ast-types": "0.16.1",
|
|
46
46
|
"react": "19.2.3",
|
|
47
47
|
"@types/semver": "7.5.3",
|
|
48
|
-
"@remotion/eslint-config-internal": "4.0.
|
|
48
|
+
"@remotion/eslint-config-internal": "4.0.515",
|
|
49
49
|
"eslint": "9.19.0",
|
|
50
50
|
"@types/node": "20.12.14",
|
|
51
51
|
"@typescript/native-preview": "7.0.0-dev.20260217.1"
|