@remotion/studio-server 4.0.469 → 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 +94 -24
- 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.js +33 -13
- 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 +158 -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
|
@@ -14,87 +14,173 @@ const can_update_sequence_props_1 = require("./can-update-sequence-props");
|
|
|
14
14
|
const format_prop_change_1 = require("./log-updates/format-prop-change");
|
|
15
15
|
const log_update_1 = require("./log-updates/log-update");
|
|
16
16
|
const save_props_mutex_1 = require("./save-props-mutex");
|
|
17
|
-
const saveSequencePropsHandler = ({ input: {
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
const
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
const
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
17
|
+
const saveSequencePropsHandler = ({ input: { edits, clientId, undoLabel, redoLabel }, remotionRoot, logLevel, }) => (0, save_props_mutex_1.withSavePropsLock)(async () => {
|
|
18
|
+
var _a;
|
|
19
|
+
if (edits.length === 0) {
|
|
20
|
+
throw new Error('No sequence prop edits to save');
|
|
21
|
+
}
|
|
22
|
+
renderer_1.RenderInternals.Log.trace({ indent: false, logLevel }, `[save-sequence-props] Received request with ${edits.length} edit(s)`);
|
|
23
|
+
const editGroups = new Map();
|
|
24
|
+
for (const [index, edit] of edits.entries()) {
|
|
25
|
+
const parsedValue = JSON.parse(edit.value);
|
|
26
|
+
const parsedDefaultValue = edit.defaultValue !== null ? JSON.parse(edit.defaultValue) : null;
|
|
27
|
+
const { absolutePath, fileRelativeToRoot } = (0, resolve_file_inside_project_1.resolveFileInsideProject)({
|
|
28
|
+
remotionRoot,
|
|
29
|
+
fileName: edit.fileName,
|
|
30
|
+
action: 'modify',
|
|
31
|
+
});
|
|
32
|
+
const group = (_a = editGroups.get(absolutePath)) !== null && _a !== void 0 ? _a : {
|
|
33
|
+
fileRelativeToRoot,
|
|
34
|
+
edits: [],
|
|
35
|
+
};
|
|
36
|
+
group.edits.push({
|
|
37
|
+
index,
|
|
38
|
+
fileName: edit.fileName,
|
|
39
|
+
nodePath: edit.nodePath,
|
|
40
|
+
key: edit.key,
|
|
41
|
+
value: parsedValue,
|
|
42
|
+
valueString: JSON.stringify(parsedValue),
|
|
43
|
+
defaultValue: parsedDefaultValue,
|
|
44
|
+
defaultValueString: parsedDefaultValue !== null
|
|
45
|
+
? JSON.stringify(parsedDefaultValue)
|
|
46
|
+
: null,
|
|
47
|
+
schema: edit.schema,
|
|
48
|
+
});
|
|
49
|
+
editGroups.set(absolutePath, group);
|
|
50
|
+
}
|
|
51
|
+
const snapshots = [];
|
|
52
|
+
const outputByPath = new Map();
|
|
53
|
+
const resultByIndex = new Map();
|
|
54
|
+
for (const [absolutePath, group] of editGroups) {
|
|
55
|
+
const fileContents = (0, node_fs_1.readFileSync)(absolutePath, 'utf-8');
|
|
56
|
+
const { output, formatted, results: updateResults, } = await (0, update_sequence_props_1.updateMultipleSequenceProps)({
|
|
57
|
+
input: fileContents,
|
|
58
|
+
changes: group.edits.map((edit) => {
|
|
59
|
+
return {
|
|
60
|
+
nodePath: edit.nodePath.nodePath,
|
|
61
|
+
updates: [
|
|
62
|
+
{
|
|
63
|
+
key: edit.key,
|
|
64
|
+
value: edit.value,
|
|
65
|
+
defaultValue: edit.defaultValue,
|
|
66
|
+
},
|
|
67
|
+
],
|
|
68
|
+
schema: no_react_1.NoReactInternals.sequenceSchema,
|
|
69
|
+
};
|
|
70
|
+
}),
|
|
71
|
+
prettierConfigOverride: null,
|
|
72
|
+
});
|
|
73
|
+
const [{ logLine: firstLogLine }] = updateResults;
|
|
74
|
+
outputByPath.set(absolutePath, output);
|
|
75
|
+
snapshots.push({
|
|
76
|
+
filePath: absolutePath,
|
|
77
|
+
oldContents: fileContents,
|
|
78
|
+
newContents: output,
|
|
79
|
+
logLine: firstLogLine,
|
|
80
|
+
});
|
|
81
|
+
for (const [resultIndex, result] of updateResults.entries()) {
|
|
82
|
+
const edit = group.edits[resultIndex];
|
|
83
|
+
resultByIndex.set(edit.index, {
|
|
84
|
+
oldValueString: result.oldValueStrings[0],
|
|
85
|
+
logLine: result.logLine,
|
|
86
|
+
removedProps: result.removedProps,
|
|
87
|
+
formatted,
|
|
88
|
+
});
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
const [firstEdit] = edits;
|
|
92
|
+
const firstResult = resultByIndex.get(0);
|
|
93
|
+
if (!firstResult) {
|
|
94
|
+
throw new Error('Could not compute sequence prop edit result');
|
|
95
|
+
}
|
|
96
|
+
const undoMessage = undoLabel !== null
|
|
97
|
+
? `↩️ ${undoLabel}`
|
|
98
|
+
: edits.length === 1
|
|
99
|
+
? `↩️ ${(0, format_prop_change_1.formatPropChange)({
|
|
100
|
+
key: firstEdit.key,
|
|
101
|
+
oldValueString: (0, log_update_1.normalizeQuotes)(JSON.stringify(JSON.parse(firstEdit.value))),
|
|
102
|
+
newValueString: (0, log_update_1.normalizeQuotes)(firstResult.oldValueString),
|
|
103
|
+
defaultValueString: firstEdit.defaultValue !== null
|
|
104
|
+
? (0, log_update_1.normalizeQuotes)(JSON.stringify(JSON.parse(firstEdit.defaultValue)))
|
|
105
|
+
: null,
|
|
106
|
+
removedProps: [],
|
|
107
|
+
addedProps: firstResult.removedProps,
|
|
108
|
+
})}`
|
|
109
|
+
: '↩️ Update selected sequence props';
|
|
110
|
+
const redoMessage = redoLabel !== null
|
|
111
|
+
? `↪️ ${redoLabel}`
|
|
112
|
+
: edits.length === 1
|
|
113
|
+
? `↪️ ${(0, format_prop_change_1.formatPropChange)({
|
|
114
|
+
key: firstEdit.key,
|
|
115
|
+
oldValueString: (0, log_update_1.normalizeQuotes)(firstResult.oldValueString),
|
|
116
|
+
newValueString: (0, log_update_1.normalizeQuotes)(JSON.stringify(JSON.parse(firstEdit.value))),
|
|
117
|
+
defaultValueString: firstEdit.defaultValue !== null
|
|
118
|
+
? (0, log_update_1.normalizeQuotes)(JSON.stringify(JSON.parse(firstEdit.defaultValue)))
|
|
119
|
+
: null,
|
|
120
|
+
removedProps: firstResult.removedProps,
|
|
121
|
+
addedProps: [],
|
|
122
|
+
})}`
|
|
123
|
+
: '↪️ Update selected sequence props';
|
|
124
|
+
(0, undo_stack_1.pushTransactionToUndoStack)({
|
|
125
|
+
snapshots,
|
|
63
126
|
logLevel,
|
|
64
127
|
remotionRoot,
|
|
65
|
-
|
|
66
|
-
description: {
|
|
67
|
-
undoMessage: `↩️ ${undoPropChange}`,
|
|
68
|
-
redoMessage: `↪️ ${redoPropChange}`,
|
|
69
|
-
},
|
|
128
|
+
description: { undoMessage, redoMessage },
|
|
70
129
|
entryType: 'sequence-props',
|
|
71
130
|
suppressHmrOnFileRestore: true,
|
|
72
131
|
});
|
|
73
|
-
(
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
132
|
+
for (const [absolutePath, output] of outputByPath) {
|
|
133
|
+
(0, undo_stack_1.suppressUndoStackInvalidation)(absolutePath);
|
|
134
|
+
(0, watch_ignore_next_change_1.suppressBundlerUpdateForFile)(absolutePath);
|
|
135
|
+
(0, file_watcher_1.writeFileAndNotifyFileWatchers)(absolutePath, output, clientId);
|
|
136
|
+
}
|
|
137
|
+
for (const { edits: groupEdits, fileRelativeToRoot } of editGroups.values()) {
|
|
138
|
+
for (const edit of groupEdits) {
|
|
139
|
+
const result = resultByIndex.get(edit.index);
|
|
140
|
+
if (!result) {
|
|
141
|
+
throw new Error('Could not compute sequence prop edit result');
|
|
142
|
+
}
|
|
143
|
+
(0, log_update_1.logUpdate)({
|
|
144
|
+
fileRelativeToRoot,
|
|
145
|
+
line: result.logLine,
|
|
146
|
+
key: edit.key,
|
|
147
|
+
oldValueString: result.oldValueString,
|
|
148
|
+
newValueString: edit.valueString,
|
|
149
|
+
defaultValueString: edit.defaultValueString,
|
|
150
|
+
formatted: result.formatted,
|
|
151
|
+
logLevel,
|
|
152
|
+
removedProps: result.removedProps,
|
|
153
|
+
addedProps: [],
|
|
154
|
+
});
|
|
155
|
+
}
|
|
156
|
+
}
|
|
88
157
|
(0, undo_stack_1.printUndoHint)(logLevel);
|
|
89
|
-
const
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
158
|
+
const results = edits.map((edit) => {
|
|
159
|
+
const { absolutePath } = (0, resolve_file_inside_project_1.resolveFileInsideProject)({
|
|
160
|
+
remotionRoot,
|
|
161
|
+
fileName: edit.fileName,
|
|
162
|
+
action: 'modify',
|
|
163
|
+
});
|
|
164
|
+
const output = outputByPath.get(absolutePath);
|
|
165
|
+
if (!output) {
|
|
166
|
+
throw new Error('Could not compute sequence prop edit status');
|
|
167
|
+
}
|
|
168
|
+
const newStatus = (0, can_update_sequence_props_1.computeSequencePropsStatusFromContent)({
|
|
169
|
+
fileContents: output,
|
|
170
|
+
keys: (0, studio_shared_1.getAllSchemaKeys)(edit.schema),
|
|
171
|
+
nodePath: edit.nodePath.nodePath,
|
|
172
|
+
effects: [],
|
|
173
|
+
});
|
|
174
|
+
return {
|
|
175
|
+
fileName: edit.fileName,
|
|
176
|
+
nodePath: edit.nodePath,
|
|
177
|
+
props: newStatus.props,
|
|
178
|
+
};
|
|
94
179
|
});
|
|
95
180
|
return {
|
|
96
181
|
canUpdate: true,
|
|
97
|
-
props:
|
|
182
|
+
props: results[0].props,
|
|
183
|
+
results,
|
|
98
184
|
};
|
|
99
185
|
});
|
|
100
186
|
exports.saveSequencePropsHandler = saveSequencePropsHandler;
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.unregisterClientRenderHandler = void 0;
|
|
4
|
+
const client_render_queue_1 = require("../../client-render-queue");
|
|
5
|
+
const validate_same_origin_1 = require("../validate-same-origin");
|
|
6
|
+
const unregisterClientRenderHandler = ({ input: { id }, request, }) => {
|
|
7
|
+
(0, validate_same_origin_1.validateSameOrigin)(request);
|
|
8
|
+
(0, client_render_queue_1.removeCompletedClientRender)(id);
|
|
9
|
+
return Promise.resolve();
|
|
10
|
+
};
|
|
11
|
+
exports.unregisterClientRenderHandler = unregisterClientRenderHandler;
|
|
@@ -38,6 +38,7 @@ export declare const startServer: (options: {
|
|
|
38
38
|
binariesDirectory: string | null;
|
|
39
39
|
forceIPv4: boolean;
|
|
40
40
|
audioLatencyHint: AudioContextLatencyCategory | null;
|
|
41
|
+
previewSampleRate: number | null;
|
|
41
42
|
enableCrossSiteIsolation: boolean;
|
|
42
43
|
askAIEnabled: boolean;
|
|
43
44
|
forceNew: boolean;
|
|
@@ -102,6 +102,7 @@ const startServer = async (options) => {
|
|
|
102
102
|
gitSource: options.gitSource,
|
|
103
103
|
binariesDirectory: options.binariesDirectory,
|
|
104
104
|
audioLatencyHint: options.audioLatencyHint,
|
|
105
|
+
previewSampleRate: options.previewSampleRate,
|
|
105
106
|
enableCrossSiteIsolation: options.enableCrossSiteIsolation,
|
|
106
107
|
});
|
|
107
108
|
})
|
|
@@ -4,11 +4,18 @@ export interface UndoEntryDescription {
|
|
|
4
4
|
redoMessage: string;
|
|
5
5
|
}
|
|
6
6
|
type UndoEntryType = 'visual-control' | 'default-props' | 'sequence-props' | 'effect-props' | 'delete-effect' | 'delete-jsx-node' | 'duplicate-jsx-node' | 'delete-composition' | 'rename-composition' | 'duplicate-composition';
|
|
7
|
-
type
|
|
7
|
+
type UndoEntrySnapshot = {
|
|
8
8
|
filePath: string;
|
|
9
9
|
oldContents: string;
|
|
10
|
+
newContents: string | null;
|
|
11
|
+
/** 1-based source line for terminal/IDE file links (e.g. path:line). */
|
|
12
|
+
logLine: number;
|
|
13
|
+
};
|
|
14
|
+
type UndoEntry = {
|
|
15
|
+
filePath: string;
|
|
10
16
|
/** 1-based source line for terminal/IDE file links (e.g. path:line). */
|
|
11
17
|
logLine: number;
|
|
18
|
+
snapshots: UndoEntrySnapshot[];
|
|
12
19
|
description: UndoEntryDescription;
|
|
13
20
|
/** When true, undo/redo file restores call `suppressBundlerUpdateForFile` (skip HMR refresh). */
|
|
14
21
|
suppressHmrOnFileRestore: boolean;
|
|
@@ -33,9 +40,10 @@ type UndoEntry = {
|
|
|
33
40
|
} | {
|
|
34
41
|
entryType: 'duplicate-composition';
|
|
35
42
|
});
|
|
36
|
-
export declare function pushToUndoStack({ filePath, oldContents, logLevel, remotionRoot, logLine, description, entryType, suppressHmrOnFileRestore }: {
|
|
43
|
+
export declare function pushToUndoStack({ filePath, oldContents, newContents, logLevel, remotionRoot, logLine, description, entryType, suppressHmrOnFileRestore }: {
|
|
37
44
|
filePath: string;
|
|
38
45
|
oldContents: string;
|
|
46
|
+
newContents: string | null;
|
|
39
47
|
logLevel: LogLevel;
|
|
40
48
|
remotionRoot: string;
|
|
41
49
|
logLine: number;
|
|
@@ -43,10 +51,24 @@ export declare function pushToUndoStack({ filePath, oldContents, logLevel, remot
|
|
|
43
51
|
entryType: UndoEntryType;
|
|
44
52
|
suppressHmrOnFileRestore: boolean;
|
|
45
53
|
}): void;
|
|
54
|
+
export declare function pushTransactionToUndoStack({ snapshots, logLevel, remotionRoot, description, entryType, suppressHmrOnFileRestore }: {
|
|
55
|
+
snapshots: Array<{
|
|
56
|
+
filePath: string;
|
|
57
|
+
oldContents: string;
|
|
58
|
+
newContents: string | null;
|
|
59
|
+
logLine: number;
|
|
60
|
+
}>;
|
|
61
|
+
logLevel: LogLevel;
|
|
62
|
+
remotionRoot: string;
|
|
63
|
+
description: UndoEntryDescription;
|
|
64
|
+
entryType: UndoEntryType;
|
|
65
|
+
suppressHmrOnFileRestore: boolean;
|
|
66
|
+
}): void;
|
|
46
67
|
export declare function printUndoHint(logLevel: LogLevel): void;
|
|
47
|
-
export declare function pushToRedoStack({ filePath, oldContents, logLine, description, entryType, suppressHmrOnFileRestore }: {
|
|
68
|
+
export declare function pushToRedoStack({ filePath, oldContents, newContents, logLine, description, entryType, suppressHmrOnFileRestore }: {
|
|
48
69
|
filePath: string;
|
|
49
70
|
oldContents: string;
|
|
71
|
+
newContents: string | null;
|
|
50
72
|
logLine: number;
|
|
51
73
|
description: UndoEntryDescription;
|
|
52
74
|
entryType: UndoEntryType;
|
|
@@ -67,4 +89,5 @@ export declare function popRedo(): {
|
|
|
67
89
|
};
|
|
68
90
|
export declare function getUndoStack(): readonly UndoEntry[];
|
|
69
91
|
export declare function getRedoStack(): readonly UndoEntry[];
|
|
92
|
+
export declare function clearUndoStackForTests(): void;
|
|
70
93
|
export {};
|
|
@@ -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>;
|