@remotion/studio-server 4.0.468 → 4.0.470
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/codemods/delete-effect.d.ts +18 -0
- package/dist/codemods/delete-effect.js +95 -21
- package/dist/codemods/delete-jsx-node.d.ts +10 -0
- package/dist/codemods/delete-jsx-node.js +38 -14
- package/dist/codemods/update-keyframes/ensure-imports-and-frame-hook.d.ts +4 -0
- package/dist/codemods/update-keyframes/ensure-imports-and-frame-hook.js +152 -0
- package/dist/codemods/update-keyframes/update-keyframes.d.ts +8 -0
- package/dist/codemods/update-keyframes/update-keyframes.js +98 -31
- package/dist/codemods/update-sequence-props/update-sequence-props.d.ts +32 -10
- package/dist/codemods/update-sequence-props/update-sequence-props.js +39 -7
- package/dist/index.d.ts +2 -1
- package/dist/preview-server/api-routes.js +16 -0
- package/dist/preview-server/routes/add-effect-keyframe.d.ts +3 -0
- package/dist/preview-server/routes/add-effect-keyframe.js +91 -0
- package/dist/preview-server/routes/add-sequence-keyframe.d.ts +3 -0
- package/dist/preview-server/routes/add-sequence-keyframe.js +84 -0
- package/dist/preview-server/routes/apply-codemod.js +1 -0
- package/dist/preview-server/routes/apply-visual-control-change.js +1 -0
- package/dist/preview-server/routes/can-update-sequence-props.d.ts +0 -9
- package/dist/preview-server/routes/can-update-sequence-props.js +192 -24
- package/dist/preview-server/routes/composition-component-info.d.ts +3 -0
- package/dist/preview-server/routes/composition-component-info.js +26 -0
- 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-effect.js +76 -37
- package/dist/preview-server/routes/delete-jsx-node.js +67 -36
- 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/duplicate-jsx-node.js +1 -0
- package/dist/preview-server/routes/open-in-editor.d.ts +4 -0
- package/dist/preview-server/routes/open-in-editor.js +40 -0
- package/dist/preview-server/routes/register-client-render.d.ts +3 -0
- package/dist/preview-server/routes/register-client-render.js +11 -0
- package/dist/preview-server/routes/save-effect-props.js +1 -0
- package/dist/preview-server/routes/save-sequence-props.js +161 -72
- package/dist/preview-server/routes/unregister-client-render.d.ts +4 -0
- package/dist/preview-server/routes/unregister-client-render.js +11 -0
- package/dist/preview-server/routes/update-default-props.js +1 -0
- package/dist/preview-server/start-server.d.ts +1 -0
- package/dist/preview-server/start-server.js +1 -0
- package/dist/preview-server/undo-stack.d.ts +26 -3
- package/dist/preview-server/undo-stack.js +130 -42
- package/dist/preview-server/validate-same-origin.d.ts +2 -0
- package/dist/preview-server/validate-same-origin.js +13 -0
- package/dist/routes.d.ts +2 -1
- package/dist/routes.js +9 -136
- package/dist/start-studio.d.ts +2 -1
- package/dist/start-studio.js +2 -1
- package/package.json +6 -6
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.pushToUndoStack = pushToUndoStack;
|
|
4
|
+
exports.pushTransactionToUndoStack = pushTransactionToUndoStack;
|
|
4
5
|
exports.printUndoHint = printUndoHint;
|
|
5
6
|
exports.pushToRedoStack = pushToRedoStack;
|
|
6
7
|
exports.suppressUndoStackInvalidation = suppressUndoStackInvalidation;
|
|
@@ -8,6 +9,7 @@ exports.popUndo = popUndo;
|
|
|
8
9
|
exports.popRedo = popRedo;
|
|
9
10
|
exports.getUndoStack = getUndoStack;
|
|
10
11
|
exports.getRedoStack = getRedoStack;
|
|
12
|
+
exports.clearUndoStackForTests = clearUndoStackForTests;
|
|
11
13
|
const node_fs_1 = require("node:fs");
|
|
12
14
|
const renderer_1 = require("@remotion/renderer");
|
|
13
15
|
const parse_ast_1 = require("../codemods/parse-ast");
|
|
@@ -35,23 +37,60 @@ function broadcastState() {
|
|
|
35
37
|
});
|
|
36
38
|
});
|
|
37
39
|
}
|
|
38
|
-
|
|
40
|
+
const entryTouchesFile = (entry, filePath) => {
|
|
41
|
+
return entry.snapshots.some((snapshot) => snapshot.filePath === filePath);
|
|
42
|
+
};
|
|
43
|
+
const getEntryFilePaths = (entry) => {
|
|
44
|
+
return entry.snapshots.map((snapshot) => snapshot.filePath);
|
|
45
|
+
};
|
|
46
|
+
const makeUndoEntry = ({ snapshots, description, entryType, suppressHmrOnFileRestore, }) => {
|
|
47
|
+
if (snapshots.length === 0) {
|
|
48
|
+
throw new Error('Cannot create an undo entry without snapshots');
|
|
49
|
+
}
|
|
50
|
+
return {
|
|
51
|
+
filePath: snapshots[0].filePath,
|
|
52
|
+
logLine: snapshots[0].logLine,
|
|
53
|
+
snapshots,
|
|
54
|
+
description,
|
|
55
|
+
entryType,
|
|
56
|
+
suppressHmrOnFileRestore,
|
|
57
|
+
};
|
|
58
|
+
};
|
|
59
|
+
function pushToUndoStack({ filePath, oldContents, newContents, logLevel, remotionRoot, logLine, description, entryType, suppressHmrOnFileRestore, }) {
|
|
60
|
+
pushTransactionToUndoStack({
|
|
61
|
+
snapshots: [
|
|
62
|
+
{
|
|
63
|
+
filePath,
|
|
64
|
+
oldContents,
|
|
65
|
+
newContents,
|
|
66
|
+
logLine,
|
|
67
|
+
},
|
|
68
|
+
],
|
|
69
|
+
logLevel,
|
|
70
|
+
remotionRoot,
|
|
71
|
+
description,
|
|
72
|
+
entryType,
|
|
73
|
+
suppressHmrOnFileRestore,
|
|
74
|
+
});
|
|
75
|
+
}
|
|
76
|
+
function pushTransactionToUndoStack({ snapshots, logLevel, remotionRoot, description, entryType, suppressHmrOnFileRestore, }) {
|
|
39
77
|
storedLogLevel = logLevel;
|
|
40
78
|
storedRemotionRoot = remotionRoot;
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
oldContents,
|
|
44
|
-
logLine,
|
|
79
|
+
const entry = makeUndoEntry({
|
|
80
|
+
snapshots,
|
|
45
81
|
description,
|
|
46
82
|
entryType,
|
|
47
83
|
suppressHmrOnFileRestore,
|
|
48
84
|
});
|
|
85
|
+
undoStack.push(entry);
|
|
49
86
|
if (undoStack.length > MAX_ENTRIES) {
|
|
50
87
|
undoStack.shift();
|
|
51
88
|
}
|
|
52
89
|
redoStack.length = 0;
|
|
53
|
-
renderer_1.RenderInternals.Log.verbose({ indent: false, logLevel }, renderer_1.RenderInternals.chalk.gray(`Undo stack: added entry for ${filePath} (${undoStack.length} items)`));
|
|
54
|
-
|
|
90
|
+
renderer_1.RenderInternals.Log.verbose({ indent: false, logLevel }, renderer_1.RenderInternals.chalk.gray(`Undo stack: added entry for ${entry.filePath} (${undoStack.length} items)`));
|
|
91
|
+
for (const filePath of getEntryFilePaths(entry)) {
|
|
92
|
+
ensureWatching(filePath);
|
|
93
|
+
}
|
|
55
94
|
broadcastState();
|
|
56
95
|
}
|
|
57
96
|
function printUndoHint(logLevel) {
|
|
@@ -61,20 +100,28 @@ function printUndoHint(logLevel) {
|
|
|
61
100
|
renderer_1.RenderInternals.Log.info({ indent: false, logLevel }, renderer_1.RenderInternals.chalk.gray(`Tip: ${shortcut} in Studio to undo`));
|
|
62
101
|
}
|
|
63
102
|
}
|
|
64
|
-
function pushToRedoStack({ filePath, oldContents, logLine, description, entryType, suppressHmrOnFileRestore, }) {
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
103
|
+
function pushToRedoStack({ filePath, oldContents, newContents, logLine, description, entryType, suppressHmrOnFileRestore, }) {
|
|
104
|
+
const entry = makeUndoEntry({
|
|
105
|
+
snapshots: [
|
|
106
|
+
{
|
|
107
|
+
filePath,
|
|
108
|
+
oldContents,
|
|
109
|
+
newContents,
|
|
110
|
+
logLine,
|
|
111
|
+
},
|
|
112
|
+
],
|
|
69
113
|
description,
|
|
70
114
|
entryType,
|
|
71
115
|
suppressHmrOnFileRestore,
|
|
72
116
|
});
|
|
117
|
+
redoStack.push(entry);
|
|
73
118
|
if (redoStack.length > MAX_ENTRIES) {
|
|
74
119
|
redoStack.shift();
|
|
75
120
|
}
|
|
76
|
-
renderer_1.RenderInternals.Log.verbose({ indent: false, logLevel: storedLogLevel }, renderer_1.RenderInternals.chalk.gray(`Redo stack: added entry for ${filePath} (${redoStack.length} items)`));
|
|
77
|
-
|
|
121
|
+
renderer_1.RenderInternals.Log.verbose({ indent: false, logLevel: storedLogLevel }, renderer_1.RenderInternals.chalk.gray(`Redo stack: added entry for ${entry.filePath} (${redoStack.length} items)`));
|
|
122
|
+
for (const watchedFilePath of getEntryFilePaths(entry)) {
|
|
123
|
+
ensureWatching(watchedFilePath);
|
|
124
|
+
}
|
|
78
125
|
broadcastState();
|
|
79
126
|
}
|
|
80
127
|
function suppressUndoStackInvalidation(filePath) {
|
|
@@ -109,7 +156,7 @@ function invalidateForFile(filePath) {
|
|
|
109
156
|
let changed = false;
|
|
110
157
|
let lastUndoIndex = -1;
|
|
111
158
|
for (let i = undoStack.length - 1; i >= 0; i--) {
|
|
112
|
-
if (undoStack[i]
|
|
159
|
+
if (entryTouchesFile(undoStack[i], filePath)) {
|
|
113
160
|
lastUndoIndex = i;
|
|
114
161
|
break;
|
|
115
162
|
}
|
|
@@ -122,7 +169,7 @@ function invalidateForFile(filePath) {
|
|
|
122
169
|
}
|
|
123
170
|
let lastRedoIndex = -1;
|
|
124
171
|
for (let i = redoStack.length - 1; i >= 0; i--) {
|
|
125
|
-
if (redoStack[i]
|
|
172
|
+
if (entryTouchesFile(redoStack[i], filePath)) {
|
|
126
173
|
lastRedoIndex = i;
|
|
127
174
|
break;
|
|
128
175
|
}
|
|
@@ -140,8 +187,8 @@ function invalidateForFile(filePath) {
|
|
|
140
187
|
}
|
|
141
188
|
function cleanupWatchers() {
|
|
142
189
|
const filesInStacks = new Set([
|
|
143
|
-
...undoStack.
|
|
144
|
-
...redoStack.
|
|
190
|
+
...undoStack.flatMap(getEntryFilePaths),
|
|
191
|
+
...redoStack.flatMap(getEntryFilePaths),
|
|
145
192
|
]);
|
|
146
193
|
for (const [filePath, watcher] of watchers) {
|
|
147
194
|
if (!filesInStacks.has(filePath)) {
|
|
@@ -182,26 +229,39 @@ function popUndo() {
|
|
|
182
229
|
if (!entry) {
|
|
183
230
|
return { success: false, reason: 'Nothing to undo' };
|
|
184
231
|
}
|
|
185
|
-
const
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
232
|
+
const redoSnapshots = entry.snapshots.map((snapshot) => {
|
|
233
|
+
var _a;
|
|
234
|
+
return {
|
|
235
|
+
...snapshot,
|
|
236
|
+
newContents: (_a = snapshot.newContents) !== null && _a !== void 0 ? _a : (0, node_fs_1.readFileSync)(snapshot.filePath, 'utf-8'),
|
|
237
|
+
};
|
|
238
|
+
});
|
|
239
|
+
redoStack.push(makeUndoEntry({
|
|
240
|
+
snapshots: redoSnapshots,
|
|
190
241
|
description: entry.description,
|
|
191
242
|
entryType: entry.entryType,
|
|
192
243
|
suppressHmrOnFileRestore: entry.suppressHmrOnFileRestore,
|
|
193
|
-
});
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
244
|
+
}));
|
|
245
|
+
if (redoStack.length > MAX_ENTRIES) {
|
|
246
|
+
redoStack.shift();
|
|
247
|
+
}
|
|
248
|
+
for (const snapshot of entry.snapshots) {
|
|
249
|
+
suppressUndoStackInvalidation(snapshot.filePath);
|
|
250
|
+
if (entry.suppressHmrOnFileRestore) {
|
|
251
|
+
(0, watch_ignore_next_change_1.suppressBundlerUpdateForFile)(snapshot.filePath);
|
|
252
|
+
}
|
|
253
|
+
(0, file_watcher_1.writeFileAndNotifyFileWatchers)(snapshot.filePath, snapshot.oldContents, undefined);
|
|
197
254
|
}
|
|
198
|
-
(0, file_watcher_1.writeFileAndNotifyFileWatchers)(entry.filePath, entry.oldContents, undefined);
|
|
199
255
|
renderer_1.RenderInternals.Log.verbose({ indent: false, logLevel: storedLogLevel }, renderer_1.RenderInternals.chalk.gray(`Undo: restored ${entry.filePath} (undo: ${undoStack.length}, redo: ${redoStack.length})`));
|
|
200
256
|
logFileAction(entry.description.undoMessage, entry.filePath, entry.logLine);
|
|
201
257
|
if (entry.entryType === 'visual-control') {
|
|
202
|
-
|
|
258
|
+
for (const snapshot of entry.snapshots) {
|
|
259
|
+
emitVisualControlChanges(snapshot.oldContents);
|
|
260
|
+
}
|
|
261
|
+
}
|
|
262
|
+
for (const filePath of getEntryFilePaths(entry)) {
|
|
263
|
+
ensureWatching(filePath);
|
|
203
264
|
}
|
|
204
|
-
ensureWatching(entry.filePath);
|
|
205
265
|
broadcastState();
|
|
206
266
|
return { success: true };
|
|
207
267
|
}
|
|
@@ -210,32 +270,60 @@ function popRedo() {
|
|
|
210
270
|
if (!entry) {
|
|
211
271
|
return { success: false, reason: 'Nothing to redo' };
|
|
212
272
|
}
|
|
213
|
-
const
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
273
|
+
const snapshotsWithNewContents = [];
|
|
274
|
+
for (const snapshot of entry.snapshots) {
|
|
275
|
+
if (snapshot.newContents === null) {
|
|
276
|
+
return { success: false, reason: 'Redo entry is incomplete' };
|
|
277
|
+
}
|
|
278
|
+
snapshotsWithNewContents.push({
|
|
279
|
+
...snapshot,
|
|
280
|
+
newContents: snapshot.newContents,
|
|
281
|
+
});
|
|
282
|
+
}
|
|
283
|
+
undoStack.push(makeUndoEntry({
|
|
284
|
+
snapshots: snapshotsWithNewContents,
|
|
218
285
|
description: entry.description,
|
|
219
286
|
entryType: entry.entryType,
|
|
220
287
|
suppressHmrOnFileRestore: entry.suppressHmrOnFileRestore,
|
|
221
|
-
});
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
288
|
+
}));
|
|
289
|
+
if (undoStack.length > MAX_ENTRIES) {
|
|
290
|
+
undoStack.shift();
|
|
291
|
+
}
|
|
292
|
+
for (const snapshot of snapshotsWithNewContents) {
|
|
293
|
+
suppressUndoStackInvalidation(snapshot.filePath);
|
|
294
|
+
if (entry.suppressHmrOnFileRestore) {
|
|
295
|
+
(0, watch_ignore_next_change_1.suppressBundlerUpdateForFile)(snapshot.filePath);
|
|
296
|
+
}
|
|
297
|
+
(0, file_watcher_1.writeFileAndNotifyFileWatchers)(snapshot.filePath, snapshot.newContents, undefined);
|
|
225
298
|
}
|
|
226
|
-
(0, file_watcher_1.writeFileAndNotifyFileWatchers)(entry.filePath, entry.oldContents, undefined);
|
|
227
299
|
renderer_1.RenderInternals.Log.verbose({ indent: false, logLevel: storedLogLevel }, renderer_1.RenderInternals.chalk.gray(`Redo: restored ${entry.filePath} (undo: ${undoStack.length}, redo: ${redoStack.length})`));
|
|
228
300
|
logFileAction(entry.description.redoMessage, entry.filePath, entry.logLine);
|
|
229
301
|
if (entry.entryType === 'visual-control') {
|
|
230
|
-
|
|
302
|
+
for (const snapshot of entry.snapshots) {
|
|
303
|
+
if (snapshot.newContents !== null) {
|
|
304
|
+
emitVisualControlChanges(snapshot.newContents);
|
|
305
|
+
}
|
|
306
|
+
}
|
|
307
|
+
}
|
|
308
|
+
for (const filePath of getEntryFilePaths(entry)) {
|
|
309
|
+
ensureWatching(filePath);
|
|
231
310
|
}
|
|
232
|
-
ensureWatching(entry.filePath);
|
|
233
311
|
broadcastState();
|
|
234
312
|
return { success: true };
|
|
235
313
|
}
|
|
314
|
+
/*
|
|
315
|
+
* Keep stack accessors typed as readonly arrays so callers can only inspect
|
|
316
|
+
* whether undo/redo is available and which file represents the top entry.
|
|
317
|
+
*/
|
|
236
318
|
function getUndoStack() {
|
|
237
319
|
return undoStack;
|
|
238
320
|
}
|
|
239
321
|
function getRedoStack() {
|
|
240
322
|
return redoStack;
|
|
241
323
|
}
|
|
324
|
+
function clearUndoStackForTests() {
|
|
325
|
+
undoStack.length = 0;
|
|
326
|
+
redoStack.length = 0;
|
|
327
|
+
suppressedWrites.clear();
|
|
328
|
+
cleanupWatchers();
|
|
329
|
+
}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.validateSameOrigin = void 0;
|
|
4
|
+
const validateSameOrigin = (req) => {
|
|
5
|
+
const { origin, host } = req.headers;
|
|
6
|
+
if (origin) {
|
|
7
|
+
const originUrl = new URL(origin);
|
|
8
|
+
if (originUrl.host !== host) {
|
|
9
|
+
throw new Error('Request from different origin not allowed');
|
|
10
|
+
}
|
|
11
|
+
}
|
|
12
|
+
};
|
|
13
|
+
exports.validateSameOrigin = validateSameOrigin;
|
package/dist/routes.d.ts
CHANGED
|
@@ -2,7 +2,7 @@ import type { IncomingMessage, ServerResponse } from 'node:http';
|
|
|
2
2
|
import type { GitSource, RenderDefaults, RenderJob } from '@remotion/studio-shared';
|
|
3
3
|
import type { QueueMethods } from './preview-server/api-types';
|
|
4
4
|
import type { LiveEventsServer } from './preview-server/live-events';
|
|
5
|
-
export declare const handleRoutes: ({ staticHash, staticHashPrefix, outputHash, outputHashPrefix, request, response, liveEventsServer, getCurrentInputProps, getEnvVariables, remotionRoot, entryPoint, publicDir, logLevel, getRenderQueue, getRenderDefaults, numberOfAudioTags, queueMethods: methods, gitSource, binariesDirectory, audioLatencyHint, enableCrossSiteIsolation, }: {
|
|
5
|
+
export declare const handleRoutes: ({ staticHash, staticHashPrefix, outputHash, outputHashPrefix, request, response, liveEventsServer, getCurrentInputProps, getEnvVariables, remotionRoot, entryPoint, publicDir, logLevel, getRenderQueue, getRenderDefaults, numberOfAudioTags, queueMethods: methods, gitSource, binariesDirectory, audioLatencyHint, previewSampleRate, enableCrossSiteIsolation, }: {
|
|
6
6
|
staticHash: string;
|
|
7
7
|
staticHashPrefix: string;
|
|
8
8
|
outputHash: string;
|
|
@@ -23,5 +23,6 @@ export declare const handleRoutes: ({ staticHash, staticHashPrefix, outputHash,
|
|
|
23
23
|
gitSource: GitSource | null;
|
|
24
24
|
binariesDirectory: string | null;
|
|
25
25
|
audioLatencyHint: AudioContextLatencyCategory | null;
|
|
26
|
+
previewSampleRate: number | null;
|
|
26
27
|
enableCrossSiteIsolation: boolean;
|
|
27
28
|
}) => Promise<void>;
|
package/dist/routes.js
CHANGED
|
@@ -44,18 +44,16 @@ const studio_shared_1 = require("@remotion/studio-shared");
|
|
|
44
44
|
const client_render_queue_1 = require("./client-render-queue");
|
|
45
45
|
const get_file_source_1 = require("./helpers/get-file-source");
|
|
46
46
|
const get_installed_installable_packages_1 = require("./helpers/get-installed-installable-packages");
|
|
47
|
-
const open_in_editor_1 = require("./helpers/open-in-editor");
|
|
48
|
-
const resolve_composition_component_1 = require("./helpers/resolve-composition-component");
|
|
49
47
|
const resolve_output_path_1 = require("./helpers/resolve-output-path");
|
|
50
48
|
const api_routes_1 = require("./preview-server/api-routes");
|
|
51
49
|
const get_package_manager_1 = require("./preview-server/get-package-manager");
|
|
52
50
|
const get_static_file_fallback_hint_1 = require("./preview-server/get-static-file-fallback-hint");
|
|
53
51
|
const handler_1 = require("./preview-server/handler");
|
|
54
|
-
const parse_body_1 = require("./preview-server/parse-body");
|
|
55
52
|
const public_folder_1 = require("./preview-server/public-folder");
|
|
53
|
+
const open_in_editor_1 = require("./preview-server/routes/open-in-editor");
|
|
56
54
|
const serve_static_1 = require("./preview-server/serve-static");
|
|
55
|
+
const validate_same_origin_1 = require("./preview-server/validate-same-origin");
|
|
57
56
|
const watch_ignore_next_change_1 = require("./preview-server/watch-ignore-next-change");
|
|
58
|
-
const editorGuess = (0, open_in_editor_1.guessEditor)();
|
|
59
57
|
const loggedStaticFileHints = new Set();
|
|
60
58
|
const static404 = (response) => {
|
|
61
59
|
response.writeHead(404);
|
|
@@ -80,7 +78,7 @@ const handleRemotionConfig = (response, remotionRoot) => {
|
|
|
80
78
|
response.end(JSON.stringify(body));
|
|
81
79
|
return Promise.resolve();
|
|
82
80
|
};
|
|
83
|
-
const handleFallback = async ({ remotionRoot, hash, response, request, getCurrentInputProps, getEnvVariables, publicDir, getRenderQueue, getRenderDefaults, numberOfAudioTags, audioLatencyHint, gitSource, logLevel, enableCrossSiteIsolation, }) => {
|
|
81
|
+
const handleFallback = async ({ remotionRoot, hash, response, request, getCurrentInputProps, getEnvVariables, publicDir, getRenderQueue, getRenderDefaults, numberOfAudioTags, audioLatencyHint, previewSampleRate, gitSource, logLevel, enableCrossSiteIsolation, }) => {
|
|
84
82
|
var _a;
|
|
85
83
|
const acceptsHtml = ((_a = request.headers.accept) !== null && _a !== void 0 ? _a : '').includes('text/html');
|
|
86
84
|
if (request.method === 'GET' && acceptsHtml) {
|
|
@@ -103,8 +101,7 @@ const handleFallback = async ({ remotionRoot, hash, response, request, getCurren
|
|
|
103
101
|
`Change \`"${pathname}"\` to \`staticFile("${pathname}")\` to fix the error.`,
|
|
104
102
|
].join('\n'));
|
|
105
103
|
}
|
|
106
|
-
const
|
|
107
|
-
const displayName = (0, open_in_editor_1.getDisplayNameForEditor)(edit ? edit.command : null);
|
|
104
|
+
const displayName = await (0, open_in_editor_1.getEditorName)();
|
|
108
105
|
response.setHeader('content-type', 'text/html');
|
|
109
106
|
if (enableCrossSiteIsolation) {
|
|
110
107
|
response.setHeader('Cross-Origin-Opener-Policy', 'same-origin');
|
|
@@ -145,6 +142,7 @@ const handleFallback = async ({ remotionRoot, hash, response, request, getCurren
|
|
|
145
142
|
logLevel,
|
|
146
143
|
mode: 'dev',
|
|
147
144
|
audioLatencyHint: audioLatencyHint !== null && audioLatencyHint !== void 0 ? audioLatencyHint : 'playback',
|
|
145
|
+
sampleRate: previewSampleRate,
|
|
148
146
|
}));
|
|
149
147
|
};
|
|
150
148
|
const handleFileSource = async ({ method, remotionRoot, search, response, }) => {
|
|
@@ -167,88 +165,9 @@ const handleFileSource = async ({ method, remotionRoot, search, response, }) =>
|
|
|
167
165
|
response.end();
|
|
168
166
|
return Promise.resolve();
|
|
169
167
|
};
|
|
170
|
-
const handleOpenInEditor = async (remotionRoot, req, res, logLevel) => {
|
|
171
|
-
if (req.method === 'OPTIONS') {
|
|
172
|
-
res.statusCode = 200;
|
|
173
|
-
res.end();
|
|
174
|
-
return;
|
|
175
|
-
}
|
|
176
|
-
try {
|
|
177
|
-
const body = (await (0, parse_body_1.parseRequestBody)(req));
|
|
178
|
-
if (!('stack' in body)) {
|
|
179
|
-
throw new TypeError('Need to pass stack');
|
|
180
|
-
}
|
|
181
|
-
const stack = body.stack;
|
|
182
|
-
const guess = await editorGuess;
|
|
183
|
-
const didOpen = await (0, open_in_editor_1.launchEditor)({
|
|
184
|
-
colNumber: stack.originalColumnNumber,
|
|
185
|
-
editor: guess[0],
|
|
186
|
-
fileName: node_path_1.default.resolve(remotionRoot, stack.originalFileName),
|
|
187
|
-
lineNumber: stack.originalLineNumber,
|
|
188
|
-
vsCodeNewWindow: false,
|
|
189
|
-
logLevel,
|
|
190
|
-
});
|
|
191
|
-
res.setHeader('content-type', 'application/json');
|
|
192
|
-
res.writeHead(200);
|
|
193
|
-
res.end(JSON.stringify({
|
|
194
|
-
success: didOpen,
|
|
195
|
-
}));
|
|
196
|
-
}
|
|
197
|
-
catch (_a) {
|
|
198
|
-
res.setHeader('content-type', 'application/json');
|
|
199
|
-
res.writeHead(200);
|
|
200
|
-
res.end(JSON.stringify({
|
|
201
|
-
success: false,
|
|
202
|
-
}));
|
|
203
|
-
}
|
|
204
|
-
};
|
|
205
|
-
const handleGetCompositionComponentInfo = async (remotionRoot, req, res) => {
|
|
206
|
-
if (req.method === 'OPTIONS') {
|
|
207
|
-
res.statusCode = 200;
|
|
208
|
-
res.end();
|
|
209
|
-
return;
|
|
210
|
-
}
|
|
211
|
-
res.setHeader('content-type', 'application/json');
|
|
212
|
-
try {
|
|
213
|
-
const body = (await (0, parse_body_1.parseRequestBody)(req));
|
|
214
|
-
if (typeof body.compositionFile !== 'string') {
|
|
215
|
-
throw new TypeError('Need to pass compositionFile');
|
|
216
|
-
}
|
|
217
|
-
if (typeof body.compositionId !== 'string') {
|
|
218
|
-
throw new TypeError('Need to pass compositionId');
|
|
219
|
-
}
|
|
220
|
-
const location = await (0, resolve_composition_component_1.resolveCompositionComponent)({
|
|
221
|
-
remotionRoot,
|
|
222
|
-
compositionFile: body.compositionFile,
|
|
223
|
-
compositionId: body.compositionId,
|
|
224
|
-
});
|
|
225
|
-
res.writeHead(200);
|
|
226
|
-
res.end(JSON.stringify({
|
|
227
|
-
success: true,
|
|
228
|
-
location,
|
|
229
|
-
canAddSequence: location.canAddSequence,
|
|
230
|
-
}));
|
|
231
|
-
}
|
|
232
|
-
catch (err) {
|
|
233
|
-
res.writeHead(200);
|
|
234
|
-
res.end(JSON.stringify({
|
|
235
|
-
success: false,
|
|
236
|
-
error: err.message,
|
|
237
|
-
}));
|
|
238
|
-
}
|
|
239
|
-
};
|
|
240
|
-
const validateSameOrigin = (req) => {
|
|
241
|
-
const { origin, host } = req.headers;
|
|
242
|
-
if (origin) {
|
|
243
|
-
const originUrl = new URL(origin);
|
|
244
|
-
if (originUrl.host !== host) {
|
|
245
|
-
throw new Error('Request from different origin not allowed');
|
|
246
|
-
}
|
|
247
|
-
}
|
|
248
|
-
};
|
|
249
168
|
const handleAddAsset = ({ req, res, search, publicDir, }) => {
|
|
250
169
|
try {
|
|
251
|
-
validateSameOrigin(req);
|
|
170
|
+
(0, validate_same_origin_1.validateSameOrigin)(req);
|
|
252
171
|
const query = new node_url_1.URLSearchParams(search);
|
|
253
172
|
const filePath = query.get('filePath');
|
|
254
173
|
if (typeof filePath !== 'string') {
|
|
@@ -274,7 +193,7 @@ const handleAddAsset = ({ req, res, search, publicDir, }) => {
|
|
|
274
193
|
};
|
|
275
194
|
const handleUploadOutput = ({ req, res, search, remotionRoot, }) => {
|
|
276
195
|
try {
|
|
277
|
-
validateSameOrigin(req);
|
|
196
|
+
(0, validate_same_origin_1.validateSameOrigin)(req);
|
|
278
197
|
const query = new node_url_1.URLSearchParams(search);
|
|
279
198
|
const filePath = query.get('filePath');
|
|
280
199
|
if (typeof filePath !== 'string') {
|
|
@@ -303,34 +222,6 @@ const handleUploadOutput = ({ req, res, search, remotionRoot, }) => {
|
|
|
303
222
|
}
|
|
304
223
|
return Promise.resolve();
|
|
305
224
|
};
|
|
306
|
-
const handleRegisterClientRender = async ({ req, res, remotionRoot, }) => {
|
|
307
|
-
try {
|
|
308
|
-
validateSameOrigin(req);
|
|
309
|
-
const body = (await (0, parse_body_1.parseRequestBody)(req));
|
|
310
|
-
(0, client_render_queue_1.addCompletedClientRender)({ render: body, remotionRoot });
|
|
311
|
-
res.setHeader('content-type', 'application/json');
|
|
312
|
-
res.writeHead(200);
|
|
313
|
-
res.end(JSON.stringify({ success: true }));
|
|
314
|
-
}
|
|
315
|
-
catch (err) {
|
|
316
|
-
res.statusCode = 500;
|
|
317
|
-
res.end(JSON.stringify({ error: err.message }));
|
|
318
|
-
}
|
|
319
|
-
};
|
|
320
|
-
const handleUnregisterClientRender = async ({ req, res, }) => {
|
|
321
|
-
try {
|
|
322
|
-
validateSameOrigin(req);
|
|
323
|
-
const body = (await (0, parse_body_1.parseRequestBody)(req));
|
|
324
|
-
(0, client_render_queue_1.removeCompletedClientRender)(body.id);
|
|
325
|
-
res.setHeader('content-type', 'application/json');
|
|
326
|
-
res.writeHead(200);
|
|
327
|
-
res.end(JSON.stringify({ success: true }));
|
|
328
|
-
}
|
|
329
|
-
catch (err) {
|
|
330
|
-
res.statusCode = 500;
|
|
331
|
-
res.end(JSON.stringify({ error: err.message }));
|
|
332
|
-
}
|
|
333
|
-
};
|
|
334
225
|
const handleFavicon = (_, response) => {
|
|
335
226
|
const filePath = node_path_1.default.join(__dirname, '..', 'web', 'favicon.png');
|
|
336
227
|
const stat = (0, node_fs_1.statSync)(filePath);
|
|
@@ -353,7 +244,7 @@ const handleBeep = (_, response) => {
|
|
|
353
244
|
readStream.pipe(response);
|
|
354
245
|
return Promise.resolve();
|
|
355
246
|
};
|
|
356
|
-
const handleRoutes = ({ staticHash, staticHashPrefix, outputHash, outputHashPrefix, request, response, liveEventsServer, getCurrentInputProps, getEnvVariables, remotionRoot, entryPoint, publicDir, logLevel, getRenderQueue, getRenderDefaults, numberOfAudioTags, queueMethods: methods, gitSource, binariesDirectory, audioLatencyHint, enableCrossSiteIsolation, }) => {
|
|
247
|
+
const handleRoutes = ({ staticHash, staticHashPrefix, outputHash, outputHashPrefix, request, response, liveEventsServer, getCurrentInputProps, getEnvVariables, remotionRoot, entryPoint, publicDir, logLevel, getRenderQueue, getRenderDefaults, numberOfAudioTags, queueMethods: methods, gitSource, binariesDirectory, audioLatencyHint, previewSampleRate, enableCrossSiteIsolation, }) => {
|
|
357
248
|
const url = new URL(request.url, 'http://localhost');
|
|
358
249
|
if (url.pathname === '/api/file-source') {
|
|
359
250
|
return handleFileSource({
|
|
@@ -363,12 +254,6 @@ const handleRoutes = ({ staticHash, staticHashPrefix, outputHash, outputHashPref
|
|
|
363
254
|
response,
|
|
364
255
|
});
|
|
365
256
|
}
|
|
366
|
-
if (url.pathname === '/api/open-in-editor') {
|
|
367
|
-
return handleOpenInEditor(remotionRoot, request, response, logLevel);
|
|
368
|
-
}
|
|
369
|
-
if (url.pathname === '/api/composition-component-info') {
|
|
370
|
-
return handleGetCompositionComponentInfo(remotionRoot, request, response);
|
|
371
|
-
}
|
|
372
257
|
if (url.pathname === `${staticHash}/api/add-asset`) {
|
|
373
258
|
return handleAddAsset({
|
|
374
259
|
req: request,
|
|
@@ -385,19 +270,6 @@ const handleRoutes = ({ staticHash, staticHashPrefix, outputHash, outputHashPref
|
|
|
385
270
|
remotionRoot,
|
|
386
271
|
});
|
|
387
272
|
}
|
|
388
|
-
if (url.pathname === '/api/register-client-render') {
|
|
389
|
-
return handleRegisterClientRender({
|
|
390
|
-
req: request,
|
|
391
|
-
res: response,
|
|
392
|
-
remotionRoot,
|
|
393
|
-
});
|
|
394
|
-
}
|
|
395
|
-
if (url.pathname === '/api/unregister-client-render') {
|
|
396
|
-
return handleUnregisterClientRender({
|
|
397
|
-
req: request,
|
|
398
|
-
res: response,
|
|
399
|
-
});
|
|
400
|
-
}
|
|
401
273
|
for (const [key, value] of Object.entries(api_routes_1.allApiRoutes)) {
|
|
402
274
|
if (url.pathname === key) {
|
|
403
275
|
return (0, handler_1.handleRequest)({
|
|
@@ -467,6 +339,7 @@ const handleRoutes = ({ staticHash, staticHashPrefix, outputHash, outputHashPref
|
|
|
467
339
|
gitSource,
|
|
468
340
|
logLevel,
|
|
469
341
|
audioLatencyHint,
|
|
342
|
+
previewSampleRate,
|
|
470
343
|
enableCrossSiteIsolation,
|
|
471
344
|
});
|
|
472
345
|
};
|
package/dist/start-studio.d.ts
CHANGED
|
@@ -6,7 +6,7 @@ export type StartStudioResult = {
|
|
|
6
6
|
} | {
|
|
7
7
|
type: 'already-running';
|
|
8
8
|
};
|
|
9
|
-
export declare const startStudio: ({ browserArgs, browserFlag, shouldOpenBrowser, fullEntryPath, logLevel, getCurrentInputProps, getEnvVariables, desiredPort, maxTimelineTracks, remotionRoot, keyboardShortcutsEnabled, experimentalClientSideRenderingEnabled, relativePublicDir, webpackOverride, poll, getRenderDefaults, getRenderQueue, numberOfAudioTags, queueMethods, previewEntry, gitSource, bufferStateDelayInMilliseconds, binariesDirectory, forceIPv4, audioLatencyHint, enableCrossSiteIsolation, askAIEnabled, forceNew, rspack, }: {
|
|
9
|
+
export declare const startStudio: ({ browserArgs, browserFlag, shouldOpenBrowser, fullEntryPath, logLevel, getCurrentInputProps, getEnvVariables, desiredPort, maxTimelineTracks, remotionRoot, keyboardShortcutsEnabled, experimentalClientSideRenderingEnabled, relativePublicDir, webpackOverride, poll, getRenderDefaults, getRenderQueue, numberOfAudioTags, queueMethods, previewEntry, gitSource, bufferStateDelayInMilliseconds, binariesDirectory, forceIPv4, audioLatencyHint, previewSampleRate, enableCrossSiteIsolation, askAIEnabled, forceNew, rspack, }: {
|
|
10
10
|
browserArgs: string;
|
|
11
11
|
browserFlag: string;
|
|
12
12
|
logLevel: "error" | "info" | "trace" | "verbose" | "warn";
|
|
@@ -27,6 +27,7 @@ export declare const startStudio: ({ browserArgs, browserFlag, shouldOpenBrowser
|
|
|
27
27
|
getRenderQueue: () => RenderJob[];
|
|
28
28
|
numberOfAudioTags: number;
|
|
29
29
|
audioLatencyHint: AudioContextLatencyCategory | null;
|
|
30
|
+
previewSampleRate: number | null;
|
|
30
31
|
enableCrossSiteIsolation: boolean;
|
|
31
32
|
queueMethods: QueueMethods;
|
|
32
33
|
previewEntry: string;
|
package/dist/start-studio.js
CHANGED
|
@@ -18,7 +18,7 @@ const public_folder_1 = require("./preview-server/public-folder");
|
|
|
18
18
|
const start_server_1 = require("./preview-server/start-server");
|
|
19
19
|
const server_ready_1 = require("./server-ready");
|
|
20
20
|
const watch_root_file_1 = require("./watch-root-file");
|
|
21
|
-
const startStudio = async ({ browserArgs, browserFlag, shouldOpenBrowser, fullEntryPath, logLevel, getCurrentInputProps, getEnvVariables, desiredPort, maxTimelineTracks, remotionRoot, keyboardShortcutsEnabled, experimentalClientSideRenderingEnabled, relativePublicDir, webpackOverride, poll, getRenderDefaults, getRenderQueue, numberOfAudioTags, queueMethods, previewEntry, gitSource, bufferStateDelayInMilliseconds, binariesDirectory, forceIPv4, audioLatencyHint, enableCrossSiteIsolation, askAIEnabled, forceNew, rspack, }) => {
|
|
21
|
+
const startStudio = async ({ browserArgs, browserFlag, shouldOpenBrowser, fullEntryPath, logLevel, getCurrentInputProps, getEnvVariables, desiredPort, maxTimelineTracks, remotionRoot, keyboardShortcutsEnabled, experimentalClientSideRenderingEnabled, relativePublicDir, webpackOverride, poll, getRenderDefaults, getRenderQueue, numberOfAudioTags, queueMethods, previewEntry, gitSource, bufferStateDelayInMilliseconds, binariesDirectory, forceIPv4, audioLatencyHint, previewSampleRate, enableCrossSiteIsolation, askAIEnabled, forceNew, rspack, }) => {
|
|
22
22
|
try {
|
|
23
23
|
if (typeof Bun === 'undefined') {
|
|
24
24
|
process.title = 'node (npx remotion studio)';
|
|
@@ -89,6 +89,7 @@ const startStudio = async ({ browserArgs, browserFlag, shouldOpenBrowser, fullEn
|
|
|
89
89
|
binariesDirectory,
|
|
90
90
|
forceIPv4,
|
|
91
91
|
audioLatencyHint,
|
|
92
|
+
previewSampleRate,
|
|
92
93
|
enableCrossSiteIsolation,
|
|
93
94
|
askAIEnabled,
|
|
94
95
|
forceNew,
|
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.470",
|
|
7
7
|
"description": "Run a Remotion Studio with a server backend",
|
|
8
8
|
"main": "dist",
|
|
9
9
|
"scripts": {
|
|
@@ -27,11 +27,11 @@
|
|
|
27
27
|
"@babel/parser": "7.24.1",
|
|
28
28
|
"semver": "7.5.3",
|
|
29
29
|
"prettier": "3.8.1",
|
|
30
|
-
"remotion": "4.0.
|
|
30
|
+
"remotion": "4.0.470",
|
|
31
31
|
"recast": "0.23.11",
|
|
32
|
-
"@remotion/bundler": "4.0.
|
|
33
|
-
"@remotion/renderer": "4.0.
|
|
34
|
-
"@remotion/studio-shared": "4.0.
|
|
32
|
+
"@remotion/bundler": "4.0.470",
|
|
33
|
+
"@remotion/renderer": "4.0.470",
|
|
34
|
+
"@remotion/studio-shared": "4.0.470",
|
|
35
35
|
"memfs": "3.4.3",
|
|
36
36
|
"open": "8.4.2"
|
|
37
37
|
},
|
|
@@ -39,7 +39,7 @@
|
|
|
39
39
|
"ast-types": "0.16.1",
|
|
40
40
|
"react": "19.2.3",
|
|
41
41
|
"@types/semver": "7.5.3",
|
|
42
|
-
"@remotion/eslint-config-internal": "4.0.
|
|
42
|
+
"@remotion/eslint-config-internal": "4.0.470",
|
|
43
43
|
"eslint": "9.19.0",
|
|
44
44
|
"@types/node": "20.12.14",
|
|
45
45
|
"@typescript/native-preview": "7.0.0-dev.20260217.1"
|