@remotion/studio-server 4.0.484 → 4.0.486

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.
Files changed (41) hide show
  1. package/dist/codemods/duplicate-composition.js +8 -0
  2. package/dist/codemods/recast-mods.js +246 -5
  3. package/dist/codemods/split-jsx-sequence.d.ts +14 -0
  4. package/dist/codemods/split-jsx-sequence.js +345 -0
  5. package/dist/codemods/update-sequence-props/update-sequence-props.d.ts +3 -1
  6. package/dist/codemods/update-sequence-props/update-sequence-props.js +406 -9
  7. package/dist/helpers/import-agnostic-node-path.js +30 -4
  8. package/dist/helpers/resolve-composition-component.d.ts +1 -0
  9. package/dist/helpers/resolve-composition-component.js +206 -9
  10. package/dist/preview-server/api-routes.js +2 -0
  11. package/dist/preview-server/routes/add-effect-keyframe.js +2 -2
  12. package/dist/preview-server/routes/add-effect.js +56 -53
  13. package/dist/preview-server/routes/add-keyframes.js +2 -2
  14. package/dist/preview-server/routes/add-sequence-keyframe.js +2 -2
  15. package/dist/preview-server/routes/apply-codemod.js +123 -101
  16. package/dist/preview-server/routes/apply-visual-control-change.js +83 -80
  17. package/dist/preview-server/routes/can-update-sequence-props.d.ts +13 -1
  18. package/dist/preview-server/routes/can-update-sequence-props.js +101 -7
  19. package/dist/preview-server/routes/delete-effect.js +83 -80
  20. package/dist/preview-server/routes/delete-jsx-node.js +74 -71
  21. package/dist/preview-server/routes/delete-keyframes.js +2 -2
  22. package/dist/preview-server/routes/duplicate-effect.js +77 -74
  23. package/dist/preview-server/routes/duplicate-jsx-node.js +53 -50
  24. package/dist/preview-server/routes/insert-element.js +2 -2
  25. package/dist/preview-server/routes/insert-jsx-element.js +53 -4
  26. package/dist/preview-server/routes/move-keyframes.js +2 -2
  27. package/dist/preview-server/routes/paste-effects.js +59 -56
  28. package/dist/preview-server/routes/reorder-effect.js +55 -52
  29. package/dist/preview-server/routes/reorder-sequence.js +55 -52
  30. package/dist/preview-server/routes/save-effect-props.js +2 -2
  31. package/dist/preview-server/routes/save-sequence-props.d.ts +3 -1
  32. package/dist/preview-server/routes/save-sequence-props.js +208 -24
  33. package/dist/preview-server/routes/source-file-write-queue.d.ts +1 -0
  34. package/dist/preview-server/routes/source-file-write-queue.js +11 -0
  35. package/dist/preview-server/routes/split-jsx-sequence.d.ts +3 -0
  36. package/dist/preview-server/routes/split-jsx-sequence.js +66 -0
  37. package/dist/preview-server/routes/update-default-props.js +58 -55
  38. package/dist/preview-server/routes/update-effect-keyframe-settings.js +2 -2
  39. package/dist/preview-server/routes/update-sequence-keyframe-settings.js +2 -2
  40. package/dist/preview-server/undo-stack.d.ts +7 -1
  41. package/package.json +6 -6
@@ -4,15 +4,41 @@ exports.saveSequencePropsHandler = exports.shouldSuppressHmrForSequencePropEdits
4
4
  const node_fs_1 = require("node:fs");
5
5
  const renderer_1 = require("@remotion/renderer");
6
6
  const studio_shared_1 = require("@remotion/studio-shared");
7
+ const update_keyframes_1 = require("../../codemods/update-keyframes/update-keyframes");
7
8
  const update_sequence_props_1 = require("../../codemods/update-sequence-props/update-sequence-props");
8
9
  const file_watcher_1 = require("../../file-watcher");
9
10
  const resolve_file_inside_project_1 = require("../../helpers/resolve-file-inside-project");
10
11
  const undo_stack_1 = require("../undo-stack");
11
12
  const watch_ignore_next_change_1 = require("../watch-ignore-next-change");
12
13
  const can_update_sequence_props_1 = require("./can-update-sequence-props");
14
+ const log_effect_update_1 = require("./log-updates/log-effect-update");
13
15
  const log_update_1 = require("./log-updates/log-update");
14
- const save_props_mutex_1 = require("./save-props-mutex");
16
+ const source_file_write_queue_1 = require("./source-file-write-queue");
17
+ const parseSequencePropEditValue = (value) => {
18
+ if (value.type === 'undefined') {
19
+ return undefined;
20
+ }
21
+ return JSON.parse(value.serialized);
22
+ };
23
+ const stringifySequencePropEditValue = (value) => {
24
+ if (value === undefined) {
25
+ return 'undefined';
26
+ }
27
+ return JSON.stringify(value);
28
+ };
29
+ const groupBy = (items, getKey) => {
30
+ var _a;
31
+ const groups = new Map();
32
+ for (const item of items) {
33
+ const key = getKey(item);
34
+ const group = (_a = groups.get(key)) !== null && _a !== void 0 ? _a : [];
35
+ group.push(item);
36
+ groups.set(key, group);
37
+ }
38
+ return [...groups.values()];
39
+ };
15
40
  const convertSequencePropEditToCodemodChange = (edit) => {
41
+ var _a;
16
42
  return {
17
43
  nodePath: edit.nodePath.nodePath,
18
44
  updates: [
@@ -20,6 +46,7 @@ const convertSequencePropEditToCodemodChange = (edit) => {
20
46
  key: edit.key,
21
47
  value: edit.value,
22
48
  defaultValue: edit.defaultValue,
49
+ googleFont: ((_a = edit.sourceEdit) === null || _a === void 0 ? void 0 : _a.type) === 'google-font' ? edit.sourceEdit.font : null,
23
50
  },
24
51
  ],
25
52
  schema: edit.schema,
@@ -27,18 +54,21 @@ const convertSequencePropEditToCodemodChange = (edit) => {
27
54
  };
28
55
  exports.convertSequencePropEditToCodemodChange = convertSequencePropEditToCodemodChange;
29
56
  const shouldSuppressHmrForSequencePropEdits = (edits) => {
30
- return edits.every((edit) => edit.key !== 'showInTimeline');
57
+ return edits.every((edit) => edit.key !== 'showInTimeline' &&
58
+ (edit.sourceEdit === null || edit.sourceEdit === undefined));
31
59
  };
32
60
  exports.shouldSuppressHmrForSequencePropEdits = shouldSuppressHmrForSequencePropEdits;
33
- const saveSequencePropsHandler = ({ input: { edits, clientId, undoLabel, redoLabel }, remotionRoot, logLevel, }) => (0, save_props_mutex_1.withSavePropsLock)(async () => {
34
- var _a;
35
- if (edits.length === 0) {
61
+ const saveSequencePropsHandler = ({ input: { edits, movedKeyframes = { sequenceKeyframes: [], effectKeyframes: [] }, clientId, undoLabel, redoLabel, }, remotionRoot, logLevel, }) => (0, source_file_write_queue_1.withSourceFileWriteQueue)(async () => {
62
+ var _a, _b, _c;
63
+ const totalKeyframeMoves = movedKeyframes.sequenceKeyframes.length +
64
+ movedKeyframes.effectKeyframes.length;
65
+ if (edits.length === 0 && totalKeyframeMoves === 0) {
36
66
  throw new Error('No sequence prop edits to save');
37
67
  }
38
- renderer_1.RenderInternals.Log.trace({ indent: false, logLevel }, `[save-sequence-props] Received request with ${edits.length} edit(s)`);
68
+ renderer_1.RenderInternals.Log.trace({ indent: false, logLevel }, `[save-sequence-props] Received request with ${edits.length} edit(s) and ${totalKeyframeMoves} moved keyframe(s)`);
39
69
  const editGroups = new Map();
40
70
  for (const [index, edit] of edits.entries()) {
41
- const parsedValue = JSON.parse(edit.value);
71
+ const parsedValue = parseSequencePropEditValue(edit.value);
42
72
  const parsedDefaultValue = edit.defaultValue !== null ? JSON.parse(edit.defaultValue) : null;
43
73
  const { absolutePath, fileRelativeToRoot } = (0, resolve_file_inside_project_1.resolveFileInsideProject)({
44
74
  remotionRoot,
@@ -48,6 +78,8 @@ const saveSequencePropsHandler = ({ input: { edits, clientId, undoLabel, redoLab
48
78
  const group = (_a = editGroups.get(absolutePath)) !== null && _a !== void 0 ? _a : {
49
79
  fileRelativeToRoot,
50
80
  edits: [],
81
+ sequenceKeyframes: [],
82
+ effectKeyframes: [],
51
83
  };
52
84
  group.edits.push({
53
85
  index,
@@ -55,42 +87,165 @@ const saveSequencePropsHandler = ({ input: { edits, clientId, undoLabel, redoLab
55
87
  nodePath: edit.nodePath,
56
88
  key: edit.key,
57
89
  value: parsedValue,
58
- valueString: JSON.stringify(parsedValue),
90
+ valueString: stringifySequencePropEditValue(parsedValue),
59
91
  defaultValue: parsedDefaultValue,
60
92
  defaultValueString: parsedDefaultValue !== null
61
93
  ? JSON.stringify(parsedDefaultValue)
62
94
  : null,
63
95
  schema: edit.schema,
96
+ sourceEdit: edit.sourceEdit,
64
97
  });
65
98
  editGroups.set(absolutePath, group);
66
99
  }
100
+ for (const [index, keyframe,] of movedKeyframes.sequenceKeyframes.entries()) {
101
+ const { absolutePath, fileRelativeToRoot } = (0, resolve_file_inside_project_1.resolveFileInsideProject)({
102
+ remotionRoot,
103
+ fileName: keyframe.fileName,
104
+ action: 'modify',
105
+ });
106
+ const group = (_b = editGroups.get(absolutePath)) !== null && _b !== void 0 ? _b : {
107
+ fileRelativeToRoot,
108
+ edits: [],
109
+ sequenceKeyframes: [],
110
+ effectKeyframes: [],
111
+ };
112
+ group.sequenceKeyframes.push({ ...keyframe, index });
113
+ editGroups.set(absolutePath, group);
114
+ }
115
+ for (const [index, keyframe] of movedKeyframes.effectKeyframes.entries()) {
116
+ const { absolutePath, fileRelativeToRoot } = (0, resolve_file_inside_project_1.resolveFileInsideProject)({
117
+ remotionRoot,
118
+ fileName: keyframe.fileName,
119
+ action: 'modify',
120
+ });
121
+ const group = (_c = editGroups.get(absolutePath)) !== null && _c !== void 0 ? _c : {
122
+ fileRelativeToRoot,
123
+ edits: [],
124
+ sequenceKeyframes: [],
125
+ effectKeyframes: [],
126
+ };
127
+ group.effectKeyframes.push({ ...keyframe, index });
128
+ editGroups.set(absolutePath, group);
129
+ }
67
130
  const snapshots = [];
68
131
  const outputByPath = new Map();
69
132
  const resultByIndex = new Map();
133
+ const sequenceKeyframeLogs = [];
134
+ const effectKeyframeLogs = [];
70
135
  for (const [absolutePath, group] of editGroups) {
71
136
  const fileContents = (0, node_fs_1.readFileSync)(absolutePath, 'utf-8');
72
- const { output, formatted, results: updateResults, } = await (0, update_sequence_props_1.updateMultipleSequenceProps)({
73
- input: fileContents,
74
- changes: group.edits.map(exports.convertSequencePropEditToCodemodChange),
75
- prettierConfigOverride: null,
76
- });
77
- const [{ logLine: firstLogLine }] = updateResults;
137
+ let output = fileContents;
138
+ let firstLogLine = Number.POSITIVE_INFINITY;
139
+ if (group.edits.length > 0) {
140
+ const { output: sequencePropsOutput, formatted, results: updateResults, } = await (0, update_sequence_props_1.updateMultipleSequenceProps)({
141
+ input: output,
142
+ changes: group.edits.map(exports.convertSequencePropEditToCodemodChange),
143
+ prettierConfigOverride: null,
144
+ });
145
+ output = sequencePropsOutput;
146
+ const firstUpdate = updateResults[0];
147
+ if (firstUpdate) {
148
+ firstLogLine = Math.min(firstLogLine, firstUpdate.logLine);
149
+ }
150
+ for (const [resultIndex, result] of updateResults.entries()) {
151
+ const edit = group.edits[resultIndex];
152
+ resultByIndex.set(edit.index, {
153
+ oldValueString: result.oldValueStrings[0],
154
+ logLine: result.logLine,
155
+ removedProps: result.removedProps,
156
+ formatted,
157
+ });
158
+ }
159
+ }
160
+ for (const keyframeGroup of groupBy(group.sequenceKeyframes, (keyframe) => JSON.stringify(keyframe.nodePath.nodePath))) {
161
+ const [firstSequenceKeyframe] = keyframeGroup;
162
+ if (!firstSequenceKeyframe) {
163
+ continue;
164
+ }
165
+ const updates = groupBy(keyframeGroup, (keyframe) => keyframe.key).map((keyframes) => {
166
+ const [firstMove] = keyframes;
167
+ if (!firstMove) {
168
+ throw new Error('Expected keyframe');
169
+ }
170
+ return {
171
+ key: firstMove.key,
172
+ operation: {
173
+ type: 'move',
174
+ moves: keyframes.map((keyframe) => ({
175
+ fromFrame: keyframe.fromFrame,
176
+ toFrame: keyframe.toFrame,
177
+ })),
178
+ },
179
+ };
180
+ });
181
+ const result = await (0, update_keyframes_1.updateSequenceKeyframes)({
182
+ input: output,
183
+ nodePath: firstSequenceKeyframe.nodePath.nodePath,
184
+ schema: firstSequenceKeyframe.schema,
185
+ updates,
186
+ });
187
+ output = result.output;
188
+ firstLogLine = Math.min(firstLogLine, result.logLine);
189
+ for (const [updateIndex, update] of updates.entries()) {
190
+ sequenceKeyframeLogs.push({
191
+ fileRelativeToRoot: group.fileRelativeToRoot,
192
+ line: result.logLine,
193
+ key: update.key,
194
+ oldValueString: result.oldValueStrings[updateIndex],
195
+ newValueString: result.newValueStrings[updateIndex],
196
+ formatted: result.formatted,
197
+ });
198
+ }
199
+ }
200
+ for (const keyframeGroup of groupBy(group.effectKeyframes, (keyframe) => `${JSON.stringify(keyframe.sequenceNodePath.nodePath)}:${keyframe.effectIndex}`)) {
201
+ const [firstEffectKeyframe] = keyframeGroup;
202
+ if (!firstEffectKeyframe) {
203
+ continue;
204
+ }
205
+ const updates = groupBy(keyframeGroup, (keyframe) => keyframe.key).map((keyframes) => {
206
+ const [firstMove] = keyframes;
207
+ if (!firstMove) {
208
+ throw new Error('Expected keyframe');
209
+ }
210
+ return {
211
+ key: firstMove.key,
212
+ operation: {
213
+ type: 'move',
214
+ moves: keyframes.map((keyframe) => ({
215
+ fromFrame: keyframe.fromFrame,
216
+ toFrame: keyframe.toFrame,
217
+ })),
218
+ },
219
+ };
220
+ });
221
+ const result = await (0, update_keyframes_1.updateEffectKeyframes)({
222
+ input: output,
223
+ sequenceNodePath: firstEffectKeyframe.sequenceNodePath.nodePath,
224
+ effectIndex: firstEffectKeyframe.effectIndex,
225
+ schema: firstEffectKeyframe.schema,
226
+ updates,
227
+ });
228
+ output = result.output;
229
+ firstLogLine = Math.min(firstLogLine, result.logLine);
230
+ for (const [updateIndex, update] of updates.entries()) {
231
+ effectKeyframeLogs.push({
232
+ fileRelativeToRoot: group.fileRelativeToRoot,
233
+ line: result.logLine,
234
+ effectName: result.effectCallee,
235
+ propKey: update.key,
236
+ oldValueString: result.oldValueStrings[updateIndex],
237
+ newValueString: result.newValueStrings[updateIndex],
238
+ formatted: result.formatted,
239
+ });
240
+ }
241
+ }
78
242
  outputByPath.set(absolutePath, output);
79
243
  snapshots.push({
80
244
  filePath: absolutePath,
81
245
  oldContents: fileContents,
82
246
  newContents: output,
83
- logLine: firstLogLine,
247
+ logLine: Number.isFinite(firstLogLine) ? firstLogLine : 1,
84
248
  });
85
- for (const [resultIndex, result] of updateResults.entries()) {
86
- const edit = group.edits[resultIndex];
87
- resultByIndex.set(edit.index, {
88
- oldValueString: result.oldValueStrings[0],
89
- logLine: result.logLine,
90
- removedProps: result.removedProps,
91
- formatted,
92
- });
93
- }
94
249
  }
95
250
  const undoMessage = `↩️ ${undoLabel}`;
96
251
  const redoMessage = `↪️ ${redoLabel}`;
@@ -130,6 +285,35 @@ const saveSequencePropsHandler = ({ input: { edits, clientId, undoLabel, redoLab
130
285
  });
131
286
  }
132
287
  }
288
+ for (const log of sequenceKeyframeLogs) {
289
+ (0, log_update_1.logUpdate)({
290
+ fileRelativeToRoot: log.fileRelativeToRoot,
291
+ line: log.line,
292
+ key: log.key,
293
+ oldValueString: log.oldValueString,
294
+ newValueString: log.newValueString,
295
+ defaultValueString: null,
296
+ formatted: log.formatted,
297
+ logLevel,
298
+ removedProps: [],
299
+ addedProps: [],
300
+ });
301
+ }
302
+ for (const log of effectKeyframeLogs) {
303
+ (0, log_effect_update_1.logEffectUpdate)({
304
+ fileRelativeToRoot: log.fileRelativeToRoot,
305
+ line: log.line,
306
+ effectName: log.effectName,
307
+ propKey: log.propKey,
308
+ oldValueString: log.oldValueString,
309
+ newValueString: log.newValueString,
310
+ defaultValueString: null,
311
+ formatted: log.formatted,
312
+ logLevel,
313
+ removedProps: [],
314
+ addedProps: [],
315
+ });
316
+ }
133
317
  (0, undo_stack_1.printUndoHint)(logLevel);
134
318
  const results = edits.map((edit) => {
135
319
  const { absolutePath } = (0, resolve_file_inside_project_1.resolveFileInsideProject)({
@@ -0,0 +1 @@
1
+ export declare const withSourceFileWriteQueue: <T>(fn: () => Promise<T>) => Promise<T>;
@@ -0,0 +1,11 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.withSourceFileWriteQueue = void 0;
4
+ let chain = Promise.resolve();
5
+ const withSourceFileWriteQueue = (fn) => {
6
+ const run = () => fn();
7
+ const next = chain.then(run, run);
8
+ chain = next.then(() => undefined, () => undefined);
9
+ return next;
10
+ };
11
+ exports.withSourceFileWriteQueue = withSourceFileWriteQueue;
@@ -0,0 +1,3 @@
1
+ import type { SplitJsxSequenceRequest, SplitJsxSequenceResponse } from '@remotion/studio-shared';
2
+ import type { ApiHandler } from '../api-types';
3
+ export declare const splitJsxSequenceHandler: ApiHandler<SplitJsxSequenceRequest, SplitJsxSequenceResponse>;
@@ -0,0 +1,66 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.splitJsxSequenceHandler = void 0;
4
+ const node_fs_1 = require("node:fs");
5
+ const renderer_1 = require("@remotion/renderer");
6
+ const split_jsx_sequence_1 = require("../../codemods/split-jsx-sequence");
7
+ const file_watcher_1 = require("../../file-watcher");
8
+ const resolve_file_inside_project_1 = require("../../helpers/resolve-file-inside-project");
9
+ const format_log_file_location_1 = require("../format-log-file-location");
10
+ const undo_stack_1 = require("../undo-stack");
11
+ const log_update_1 = require("./log-updates/log-update");
12
+ const source_file_write_queue_1 = require("./source-file-write-queue");
13
+ const splitJsxSequenceHandler = ({ input: { fileName, nodePath, splitFrame }, remotionRoot, logLevel }) => (0, source_file_write_queue_1.withSourceFileWriteQueue)(async () => {
14
+ try {
15
+ renderer_1.RenderInternals.Log.trace({ indent: false, logLevel }, `[split-jsx-sequence] Received request for fileName="${fileName}" at frame ${splitFrame}`);
16
+ const { absolutePath, fileRelativeToRoot } = (0, resolve_file_inside_project_1.resolveFileInsideProject)({
17
+ remotionRoot,
18
+ fileName,
19
+ action: 'modify',
20
+ });
21
+ const fileContents = (0, node_fs_1.readFileSync)(absolutePath, 'utf-8');
22
+ const { output, formatted, nodeLabel, logLine } = await (0, split_jsx_sequence_1.splitJsxSequence)({
23
+ input: fileContents,
24
+ nodePath,
25
+ splitFrame,
26
+ });
27
+ (0, undo_stack_1.pushToUndoStack)({
28
+ filePath: absolutePath,
29
+ oldContents: fileContents,
30
+ newContents: null,
31
+ logLevel,
32
+ remotionRoot,
33
+ logLine,
34
+ description: {
35
+ undoMessage: `↩️ Split of ${nodeLabel}`,
36
+ redoMessage: `↪️ Split of ${nodeLabel}`,
37
+ },
38
+ entryType: 'split-jsx-sequence',
39
+ suppressHmrOnFileRestore: false,
40
+ });
41
+ (0, undo_stack_1.suppressUndoStackInvalidation)(absolutePath);
42
+ (0, file_watcher_1.writeFileAndNotifyFileWatchers)(absolutePath, output, undefined);
43
+ const locationLabel = (0, format_log_file_location_1.formatLogFileLocation)({
44
+ remotionRoot,
45
+ absolutePath,
46
+ line: logLine,
47
+ });
48
+ renderer_1.RenderInternals.Log.info({ indent: false, logLevel }, `${renderer_1.RenderInternals.chalk.blueBright(`${locationLabel}`)} Split ${nodeLabel}`);
49
+ if (!formatted) {
50
+ (0, log_update_1.warnAboutPrettierOnce)(logLevel);
51
+ }
52
+ renderer_1.RenderInternals.Log.verbose({ indent: false, logLevel }, `[split-jsx-sequence] Wrote ${fileRelativeToRoot}${formatted ? ' (formatted)' : ''}`);
53
+ (0, undo_stack_1.printUndoHint)(logLevel);
54
+ return {
55
+ success: true,
56
+ };
57
+ }
58
+ catch (err) {
59
+ return {
60
+ success: false,
61
+ reason: err.message,
62
+ stack: err.stack,
63
+ };
64
+ }
65
+ });
66
+ exports.splitJsxSequenceHandler = splitJsxSequenceHandler;
@@ -11,62 +11,65 @@ const undo_stack_1 = require("../undo-stack");
11
11
  const watch_ignore_next_change_1 = require("../watch-ignore-next-change");
12
12
  const can_update_default_props_1 = require("./can-update-default-props");
13
13
  const log_update_1 = require("./log-updates/log-update");
14
- const updateDefaultPropsHandler = async ({ input: { compositionId, defaultProps, enumPaths }, remotionRoot, entryPoint, logLevel, }) => {
15
- try {
16
- renderer_1.RenderInternals.Log.trace({ indent: false, logLevel }, `[update-default-props] Received request for compositionId="${compositionId}"`);
17
- const projectInfo = await (0, project_info_1.getProjectInfo)(remotionRoot, entryPoint);
18
- if (!projectInfo.rootFile) {
19
- throw new Error('Cannot find root file in project');
14
+ const source_file_write_queue_1 = require("./source-file-write-queue");
15
+ const updateDefaultPropsHandler = ({ input: { compositionId, defaultProps, enumPaths }, remotionRoot, entryPoint, logLevel, }) => {
16
+ return (0, source_file_write_queue_1.withSourceFileWriteQueue)(async () => {
17
+ try {
18
+ renderer_1.RenderInternals.Log.trace({ indent: false, logLevel }, `[update-default-props] Received request for compositionId="${compositionId}"`);
19
+ const projectInfo = await (0, project_info_1.getProjectInfo)(remotionRoot, entryPoint);
20
+ if (!projectInfo.rootFile) {
21
+ throw new Error('Cannot find root file in project');
22
+ }
23
+ (0, can_update_default_props_1.checkIfTypeScriptFile)(projectInfo.rootFile);
24
+ const fileContents = (0, node_fs_1.readFileSync)(projectInfo.rootFile, 'utf-8');
25
+ const logLine = (0, update_default_props_1.getCompositionDefaultPropsLine)({
26
+ input: fileContents,
27
+ compositionId,
28
+ });
29
+ const { output, formatted } = await (0, update_default_props_1.updateDefaultProps)({
30
+ compositionId,
31
+ input: fileContents,
32
+ newDefaultProps: JSON.parse(defaultProps),
33
+ enumPaths,
34
+ });
35
+ (0, undo_stack_1.pushToUndoStack)({
36
+ filePath: projectInfo.rootFile,
37
+ oldContents: fileContents,
38
+ newContents: null,
39
+ logLevel,
40
+ remotionRoot,
41
+ logLine,
42
+ description: {
43
+ undoMessage: `↩️ default props update for "${compositionId}"`,
44
+ redoMessage: `↪️ default props update for "${compositionId}"`,
45
+ },
46
+ entryType: 'default-props',
47
+ suppressHmrOnFileRestore: true,
48
+ });
49
+ (0, undo_stack_1.suppressUndoStackInvalidation)(projectInfo.rootFile);
50
+ (0, watch_ignore_next_change_1.suppressBundlerUpdateForFile)(projectInfo.rootFile);
51
+ (0, file_watcher_1.writeFileAndNotifyFileWatchers)(projectInfo.rootFile, output, undefined);
52
+ const locationLabel = (0, format_log_file_location_1.formatLogFileLocation)({
53
+ remotionRoot,
54
+ absolutePath: projectInfo.rootFile,
55
+ line: logLine,
56
+ });
57
+ renderer_1.RenderInternals.Log.info({ indent: false, logLevel }, `${renderer_1.RenderInternals.chalk.blueBright(`${locationLabel}`)} Updated default props for "${compositionId}"`);
58
+ if (!formatted) {
59
+ (0, log_update_1.warnAboutPrettierOnce)(logLevel);
60
+ }
61
+ (0, undo_stack_1.printUndoHint)(logLevel);
62
+ return {
63
+ success: true,
64
+ };
20
65
  }
21
- (0, can_update_default_props_1.checkIfTypeScriptFile)(projectInfo.rootFile);
22
- const fileContents = (0, node_fs_1.readFileSync)(projectInfo.rootFile, 'utf-8');
23
- const logLine = (0, update_default_props_1.getCompositionDefaultPropsLine)({
24
- input: fileContents,
25
- compositionId,
26
- });
27
- const { output, formatted } = await (0, update_default_props_1.updateDefaultProps)({
28
- compositionId,
29
- input: fileContents,
30
- newDefaultProps: JSON.parse(defaultProps),
31
- enumPaths,
32
- });
33
- (0, undo_stack_1.pushToUndoStack)({
34
- filePath: projectInfo.rootFile,
35
- oldContents: fileContents,
36
- newContents: null,
37
- logLevel,
38
- remotionRoot,
39
- logLine,
40
- description: {
41
- undoMessage: `↩️ default props update for "${compositionId}"`,
42
- redoMessage: `↪️ default props update for "${compositionId}"`,
43
- },
44
- entryType: 'default-props',
45
- suppressHmrOnFileRestore: true,
46
- });
47
- (0, undo_stack_1.suppressUndoStackInvalidation)(projectInfo.rootFile);
48
- (0, watch_ignore_next_change_1.suppressBundlerUpdateForFile)(projectInfo.rootFile);
49
- (0, file_watcher_1.writeFileAndNotifyFileWatchers)(projectInfo.rootFile, output, undefined);
50
- const locationLabel = (0, format_log_file_location_1.formatLogFileLocation)({
51
- remotionRoot,
52
- absolutePath: projectInfo.rootFile,
53
- line: logLine,
54
- });
55
- renderer_1.RenderInternals.Log.info({ indent: false, logLevel }, `${renderer_1.RenderInternals.chalk.blueBright(`${locationLabel}`)} Updated default props for "${compositionId}"`);
56
- if (!formatted) {
57
- (0, log_update_1.warnAboutPrettierOnce)(logLevel);
66
+ catch (err) {
67
+ return {
68
+ success: false,
69
+ reason: err.message,
70
+ stack: err.stack,
71
+ };
58
72
  }
59
- (0, undo_stack_1.printUndoHint)(logLevel);
60
- return {
61
- success: true,
62
- };
63
- }
64
- catch (err) {
65
- return {
66
- success: false,
67
- reason: err.message,
68
- stack: err.stack,
69
- };
70
- }
73
+ });
71
74
  };
72
75
  exports.updateDefaultPropsHandler = updateDefaultPropsHandler;
@@ -13,8 +13,8 @@ const watch_ignore_next_change_1 = require("../watch-ignore-next-change");
13
13
  const can_update_effect_props_1 = require("./can-update-effect-props");
14
14
  const can_update_sequence_props_1 = require("./can-update-sequence-props");
15
15
  const log_effect_update_1 = require("./log-updates/log-effect-update");
16
- const save_props_mutex_1 = require("./save-props-mutex");
17
- const updateEffectKeyframeSettingsHandler = ({ input: { fileName, sequenceNodePath, effectIndex, key, settings, schema, clientId, }, remotionRoot, logLevel, }) => (0, save_props_mutex_1.withSavePropsLock)(async () => {
16
+ const source_file_write_queue_1 = require("./source-file-write-queue");
17
+ const updateEffectKeyframeSettingsHandler = ({ input: { fileName, sequenceNodePath, effectIndex, key, settings, schema, clientId, }, remotionRoot, logLevel, }) => (0, source_file_write_queue_1.withSourceFileWriteQueue)(async () => {
18
18
  renderer_1.RenderInternals.Log.trace({ indent: false, logLevel }, `[update-effect-keyframe-settings] Received request for fileName="${fileName}" effectIndex=${effectIndex} key="${key}"`);
19
19
  const { absolutePath, fileRelativeToRoot } = (0, resolve_file_inside_project_1.resolveFileInsideProject)({
20
20
  remotionRoot,
@@ -11,8 +11,8 @@ const undo_stack_1 = require("../undo-stack");
11
11
  const watch_ignore_next_change_1 = require("../watch-ignore-next-change");
12
12
  const can_update_sequence_props_1 = require("./can-update-sequence-props");
13
13
  const log_update_1 = require("./log-updates/log-update");
14
- const save_props_mutex_1 = require("./save-props-mutex");
15
- const updateSequenceKeyframeSettingsHandler = ({ input: { fileName, nodePath, key, settings, schema, clientId }, remotionRoot, logLevel, }) => (0, save_props_mutex_1.withSavePropsLock)(async () => {
14
+ const source_file_write_queue_1 = require("./source-file-write-queue");
15
+ const updateSequenceKeyframeSettingsHandler = ({ input: { fileName, nodePath, key, settings, schema, clientId }, remotionRoot, logLevel, }) => (0, source_file_write_queue_1.withSourceFileWriteQueue)(async () => {
16
16
  renderer_1.RenderInternals.Log.trace({ indent: false, logLevel }, `[update-sequence-keyframe-settings] Received request for fileName="${fileName}" key="${key}"`);
17
17
  const { absolutePath, fileRelativeToRoot } = (0, resolve_file_inside_project_1.resolveFileInsideProject)({
18
18
  remotionRoot,
@@ -3,7 +3,7 @@ export interface UndoEntryDescription {
3
3
  undoMessage: string;
4
4
  redoMessage: string;
5
5
  }
6
- type UndoEntryType = 'visual-control' | 'default-props' | 'sequence-props' | 'effect-props' | 'keyframe-add' | 'keyframe-delete' | 'add-effect' | 'delete-effect' | 'duplicate-effect' | 'paste-effects' | 'reorder-effect' | 'reorder-sequence' | 'delete-jsx-node' | 'duplicate-jsx-node' | 'insert-jsx-element' | 'delete-composition' | 'rename-composition' | 'new-composition' | 'duplicate-composition' | 'delete-folder' | 'rename-folder';
6
+ type UndoEntryType = 'visual-control' | 'default-props' | 'sequence-props' | 'effect-props' | 'keyframe-add' | 'keyframe-delete' | 'add-effect' | 'delete-effect' | 'duplicate-effect' | 'paste-effects' | 'reorder-effect' | 'reorder-sequence' | 'delete-jsx-node' | 'duplicate-jsx-node' | 'split-jsx-sequence' | 'insert-jsx-element' | 'delete-composition' | 'rename-composition' | 'new-composition' | 'duplicate-composition' | 'move-composition-to-folder' | 'new-folder' | 'delete-folder' | 'rename-folder';
7
7
  type UndoEntrySnapshot = {
8
8
  filePath: string;
9
9
  oldContents: string | null;
@@ -47,6 +47,8 @@ type UndoEntry = {
47
47
  entryType: 'delete-jsx-node';
48
48
  } | {
49
49
  entryType: 'duplicate-jsx-node';
50
+ } | {
51
+ entryType: 'split-jsx-sequence';
50
52
  } | {
51
53
  entryType: 'insert-jsx-element';
52
54
  } | {
@@ -57,6 +59,10 @@ type UndoEntry = {
57
59
  entryType: 'new-composition';
58
60
  } | {
59
61
  entryType: 'duplicate-composition';
62
+ } | {
63
+ entryType: 'move-composition-to-folder';
64
+ } | {
65
+ entryType: 'new-folder';
60
66
  } | {
61
67
  entryType: 'delete-folder';
62
68
  } | {
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.484",
6
+ "version": "4.0.486",
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.484",
30
+ "remotion": "4.0.486",
31
31
  "recast": "0.23.11",
32
- "@remotion/bundler": "4.0.484",
33
- "@remotion/renderer": "4.0.484",
34
- "@remotion/studio-shared": "4.0.484",
32
+ "@remotion/bundler": "4.0.486",
33
+ "@remotion/renderer": "4.0.486",
34
+ "@remotion/studio-shared": "4.0.486",
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.484",
42
+ "@remotion/eslint-config-internal": "4.0.486",
43
43
  "eslint": "9.19.0",
44
44
  "@types/node": "20.12.14",
45
45
  "@typescript/native-preview": "7.0.0-dev.20260217.1"