@remotion/studio-server 4.0.496 → 4.0.497

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 (29) hide show
  1. package/dist/better-opn/index.d.ts +6 -0
  2. package/dist/better-opn/index.js +46 -18
  3. package/dist/codemods/update-sequence-props/update-sequence-props.js +47 -0
  4. package/dist/helpers/css-shorthand-properties.d.ts +27 -0
  5. package/dist/helpers/css-shorthand-properties.js +43 -0
  6. package/dist/helpers/package-manager-spawn-options.d.ts +2 -0
  7. package/dist/helpers/package-manager-spawn-options.js +7 -0
  8. package/dist/helpers/parse-background-shorthand.d.ts +11 -0
  9. package/dist/helpers/parse-background-shorthand.js +41 -0
  10. package/dist/helpers/parse-border-shorthand.d.ts +6 -0
  11. package/dist/helpers/parse-border-shorthand.js +135 -0
  12. package/dist/helpers/resolve-composition-component.d.ts +3 -1
  13. package/dist/helpers/resolve-composition-component.js +38 -9
  14. package/dist/index.d.ts +1 -0
  15. package/dist/index.js +2 -0
  16. package/dist/open-browser-shortcut.js +26 -16
  17. package/dist/preview-server/routes/can-update-sequence-props.js +54 -3
  18. package/dist/preview-server/routes/download-remote-asset.js +1 -0
  19. package/dist/preview-server/routes/insert-element.js +7 -1
  20. package/dist/preview-server/routes/insert-jsx-element.js +9 -1
  21. package/dist/preview-server/routes/install-dependency.js +5 -1
  22. package/dist/preview-server/routes/save-sequence-props.js +90 -22
  23. package/package.json +6 -6
  24. package/dist/preview-server/routes/delete-effect-keyframe.d.ts +0 -3
  25. package/dist/preview-server/routes/delete-effect-keyframe.js +0 -89
  26. package/dist/preview-server/routes/delete-sequence-keyframe.d.ts +0 -3
  27. package/dist/preview-server/routes/delete-sequence-keyframe.js +0 -82
  28. package/dist/preview-server/routes/save-props-mutex.d.ts +0 -1
  29. package/dist/preview-server/routes/save-props-mutex.js +0 -11
@@ -36,6 +36,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
36
36
  exports.registerOpenBrowserShortcut = void 0;
37
37
  const readline = __importStar(require("node:readline"));
38
38
  const renderer_1 = require("@remotion/renderer");
39
+ const better_opn_1 = require("./better-opn");
39
40
  const maybe_open_browser_1 = require("./maybe-open-browser");
40
41
  const live_events_1 = require("./preview-server/live-events");
41
42
  const registerOpenBrowserShortcut = ({ browserArgs, browserFlag, url, logLevel, }) => {
@@ -64,30 +65,39 @@ const registerOpenBrowserShortcut = ({ browserArgs, browserFlag, url, logLevel,
64
65
  process.stdin.pause();
65
66
  }
66
67
  };
67
- const openStudio = () => {
68
+ const openStudio = async () => {
68
69
  if (isOpeningBrowser) {
69
70
  return;
70
71
  }
71
72
  isOpeningBrowser = true;
72
73
  (0, live_events_1.clearPrintPortMessageTimeout)();
73
- (0, maybe_open_browser_1.maybeOpenBrowser)({
74
- browserArgs,
75
- browserFlag,
76
- shouldOpenBrowser: true,
77
- url,
78
- logLevel,
79
- })
80
- .then((result) => {
74
+ try {
75
+ const didFocus = await (0, better_opn_1.focusBrowserTabByOrigin)({
76
+ url,
77
+ browserArgs,
78
+ browserFlag,
79
+ });
80
+ if (didFocus) {
81
+ renderer_1.RenderInternals.Log.info({ indent: false, logLevel }, renderer_1.RenderInternals.chalk.blue(`Opened ${url} in browser`));
82
+ return;
83
+ }
84
+ const result = await (0, maybe_open_browser_1.maybeOpenBrowser)({
85
+ browserArgs,
86
+ browserFlag,
87
+ shouldOpenBrowser: true,
88
+ url,
89
+ logLevel,
90
+ });
81
91
  if (result.didOpenBrowser) {
82
- renderer_1.RenderInternals.Log.info({ indent: false, logLevel }, `Opened ${url} in browser`);
92
+ renderer_1.RenderInternals.Log.info({ indent: false, logLevel }, renderer_1.RenderInternals.chalk.blue(`Opened ${url} in browser`));
83
93
  }
84
- })
85
- .catch((err) => {
94
+ }
95
+ catch (err) {
86
96
  renderer_1.RenderInternals.Log.error({ indent: false, logLevel }, 'Could not open browser:', err);
87
- })
88
- .finally(() => {
97
+ }
98
+ finally {
89
99
  isOpeningBrowser = false;
90
- });
100
+ }
91
101
  };
92
102
  function onKeypress(_str, key) {
93
103
  if ((key === null || key === void 0 ? void 0 : key.ctrl) && key.name === 'c') {
@@ -98,7 +108,7 @@ const registerOpenBrowserShortcut = ({ browserArgs, browserFlag, url, logLevel,
98
108
  if ((key === null || key === void 0 ? void 0 : key.meta) || (key === null || key === void 0 ? void 0 : key.ctrl) || (key === null || key === void 0 ? void 0 : key.name) !== 's') {
99
109
  return;
100
110
  }
101
- openStudio();
111
+ openStudio().catch(() => undefined);
102
112
  }
103
113
  readline.emitKeypressEvents(process.stdin);
104
114
  process.stdin.setRawMode(true);
@@ -40,6 +40,7 @@ const studio_shared_1 = require("@remotion/studio-shared");
40
40
  const recast = __importStar(require("recast"));
41
41
  const no_react_1 = require("remotion/no-react");
42
42
  const parse_ast_1 = require("../../codemods/parse-ast");
43
+ const css_shorthand_properties_1 = require("../../helpers/css-shorthand-properties");
43
44
  const get_ast_node_path_1 = require("../../helpers/get-ast-node-path");
44
45
  const import_agnostic_node_path_1 = require("../../helpers/import-agnostic-node-path");
45
46
  const parse_keyframe_easing_expression_1 = require("../../helpers/parse-keyframe-easing-expression");
@@ -669,6 +670,15 @@ const validateStyleValue = (childKey, value) => {
669
670
  }
670
671
  return true;
671
672
  };
673
+ const getObjectPropertyName = (property) => {
674
+ if (property.key.type === 'Identifier') {
675
+ return property.key.name;
676
+ }
677
+ if (property.key.type === 'StringLiteral') {
678
+ return property.key.value;
679
+ }
680
+ return null;
681
+ };
672
682
  const getNestedPropStatus = ({ jsxElement, ast, parentKey, childKey, videoConfigValues, allowSpecialValues, }) => {
673
683
  const attr = jsxElement.attributes.find((a) => a.type !== 'JSXSpreadAttribute' &&
674
684
  a.name.type !== 'JSXNamespacedName' &&
@@ -687,9 +697,50 @@ const getNestedPropStatus = ({ jsxElement, ast, parentKey, childKey, videoConfig
687
697
  return computedStatus();
688
698
  }
689
699
  const objExpr = expression;
690
- const prop = objExpr.properties.find((p) => p.type === 'ObjectProperty' &&
691
- ((p.key.type === 'Identifier' && p.key.name === childKey) ||
692
- (p.key.type === 'StringLiteral' && p.key.value === childKey)));
700
+ const cssShorthand = (0, css_shorthand_properties_1.getCssShorthandForLonghand)({
701
+ parentKey,
702
+ longhand: childKey,
703
+ });
704
+ if (cssShorthand &&
705
+ objExpr.properties.some((property) => {
706
+ if (property.type !== 'ObjectProperty') {
707
+ return false;
708
+ }
709
+ const propertyName = getObjectPropertyName(property);
710
+ return (propertyName !== null &&
711
+ cssShorthand.isUnsupportedProperty(propertyName));
712
+ })) {
713
+ return computedStatus();
714
+ }
715
+ let prop;
716
+ for (let index = objExpr.properties.length - 1; index >= 0; index--) {
717
+ const candidate = objExpr.properties[index];
718
+ if (candidate.type === 'SpreadElement') {
719
+ return computedStatus();
720
+ }
721
+ if (candidate.type === 'ObjectProperty' &&
722
+ (getObjectPropertyName(candidate) === childKey ||
723
+ getObjectPropertyName(candidate) === (cssShorthand === null || cssShorthand === void 0 ? void 0 : cssShorthand.shorthand))) {
724
+ prop = candidate;
725
+ break;
726
+ }
727
+ }
728
+ if (prop &&
729
+ cssShorthand &&
730
+ getObjectPropertyName(prop) === cssShorthand.shorthand) {
731
+ const shorthandValue = prop.value;
732
+ if (!(0, exports.isStaticValue)(shorthandValue, { allowSpecialValues: false })) {
733
+ return computedStatus();
734
+ }
735
+ const staticShorthandValue = (0, exports.extractStaticValue)(shorthandValue, {
736
+ allowSpecialValues: false,
737
+ });
738
+ if (typeof staticShorthandValue !== 'string') {
739
+ return computedStatus();
740
+ }
741
+ const parsed = cssShorthand.parse(staticShorthandValue);
742
+ return parsed ? staticStatus(parsed[childKey], null) : computedStatus();
743
+ }
693
744
  if (!prop) {
694
745
  // Property not set in the object, can be added
695
746
  return staticStatus(undefined, null);
@@ -263,6 +263,7 @@ const downloadRemoteAssetHandler = async ({ input, publicDir, request }) => {
263
263
  src: assetPath,
264
264
  srcType: 'static',
265
265
  dimensions: fileType.dimensions,
266
+ durationInFrames: null,
266
267
  position: null,
267
268
  };
268
269
  return {
@@ -69,10 +69,14 @@ const validateElement = (element) => {
69
69
  }
70
70
  validateDimensions(element.dimensions);
71
71
  };
72
- const insertElementHandler = ({ input: { compositionFile, compositionId, element, position }, remotionRoot, logLevel, }) => (0, source_file_write_queue_1.withSourceFileWriteQueue)(async () => {
72
+ const insertElementHandler = ({ input: { compositionFile, compositionId, element, from, position }, remotionRoot, logLevel, }) => (0, source_file_write_queue_1.withSourceFileWriteQueue)(async () => {
73
73
  try {
74
74
  validateElement(element);
75
75
  validatePosition(position);
76
+ if (from !== null &&
77
+ (!Number.isInteger(from) || !Number.isFinite(from) || from < 0)) {
78
+ throw new Error('from must be a non-negative integer');
79
+ }
76
80
  const componentName = (0, studio_shared_1.getElementComponentNameFromSourceCode)(element.sourceCode);
77
81
  if (componentName === null) {
78
82
  throw new Error('Element source must export exactly one named component');
@@ -118,9 +122,11 @@ const insertElementHandler = ({ input: { compositionFile, compositionId, element
118
122
  props: [],
119
123
  position: null,
120
124
  },
125
+ from: null,
121
126
  prettierConfigOverride: null,
122
127
  wrapInSequence: {
123
128
  dimensions: element.dimensions,
129
+ from,
124
130
  name: element.displayName,
125
131
  position,
126
132
  },
@@ -72,6 +72,9 @@ const validateElement = (element, remotionRoot) => {
72
72
  validateDimension('width', element.dimensions.width);
73
73
  validateDimension('height', element.dimensions.height);
74
74
  }
75
+ if (element.durationInFrames !== null) {
76
+ validateDimension('durationInFrames', element.durationInFrames);
77
+ }
75
78
  return;
76
79
  }
77
80
  if (element.type === 'component') {
@@ -145,9 +148,13 @@ const getElementLabel = (element) => {
145
148
  }
146
149
  throw new Error('Unsupported element type');
147
150
  };
148
- const insertJsxElementHandler = ({ input: { compositionFile, compositionId, element }, remotionRoot, logLevel, }) => (0, source_file_write_queue_1.withSourceFileWriteQueue)(async () => {
151
+ const insertJsxElementHandler = ({ input: { compositionFile, compositionId, element, from }, remotionRoot, logLevel, }) => (0, source_file_write_queue_1.withSourceFileWriteQueue)(async () => {
149
152
  try {
150
153
  validateElement(element, remotionRoot);
154
+ if (from !== null &&
155
+ (!Number.isInteger(from) || !Number.isFinite(from) || from < 0)) {
156
+ throw new Error('from must be a non-negative integer');
157
+ }
151
158
  const elementLabel = getElementLabel(element);
152
159
  renderer_1.RenderInternals.Log.trace({ indent: false, logLevel }, `[insert-jsx-element] Received request for compositionFile="${compositionFile}" compositionId="${compositionId}" element="${element.type}"`);
153
160
  const { fileName, source, oldContents, output, formatted, logLine } = await (0, resolve_composition_component_1.insertJsxElementIntoComposition)({
@@ -155,6 +162,7 @@ const insertJsxElementHandler = ({ input: { compositionFile, compositionId, elem
155
162
  compositionFile,
156
163
  compositionId,
157
164
  element,
165
+ from,
158
166
  prettierConfigOverride: null,
159
167
  });
160
168
  (0, undo_stack_1.pushToUndoStack)({
@@ -6,6 +6,7 @@ const renderer_1 = require("@remotion/renderer");
6
6
  const studio_shared_1 = require("@remotion/studio-shared");
7
7
  const version_1 = require("remotion/version");
8
8
  const install_command_1 = require("../../helpers/install-command");
9
+ const package_manager_spawn_options_1 = require("../../helpers/package-manager-spawn-options");
9
10
  const get_package_manager_1 = require("../get-package-manager");
10
11
  const getExtraPackageVersion = (packageName) => {
11
12
  const pkg = studio_shared_1.extraPackages.find((p) => p.name === packageName);
@@ -52,7 +53,10 @@ const handleInstallPackage = async ({ logLevel, remotionRoot, input: { packageNa
52
53
  const time = Date.now();
53
54
  try {
54
55
  await new Promise((resolve, reject) => {
55
- const cmd = (0, node_child_process_1.spawn)(manager.manager, command, {});
56
+ const cmd = (0, node_child_process_1.spawn)(manager.manager, command, (0, package_manager_spawn_options_1.getPackageManagerSpawnOptions)());
57
+ cmd.on('error', (err) => {
58
+ reject(err);
59
+ });
56
60
  cmd.stdout.on('data', (d) => {
57
61
  const splitted = d.toString().trim().split('\n');
58
62
  splitted.forEach((line) => {
@@ -59,14 +59,20 @@ const shouldSuppressHmrForSequencePropEdits = (edits) => {
59
59
  (edit.sourceEdit === null || edit.sourceEdit === undefined));
60
60
  };
61
61
  exports.shouldSuppressHmrForSequencePropEdits = shouldSuppressHmrForSequencePropEdits;
62
- const saveSequencePropsHandler = ({ input: { edits, movedKeyframes = { sequenceKeyframes: [], effectKeyframes: [] }, clientId, undoLabel, redoLabel, }, remotionRoot, logLevel, }) => (0, source_file_write_queue_1.withSourceFileWriteQueue)(async () => {
63
- var _a, _b, _c;
64
- const totalKeyframeMoves = movedKeyframes.sequenceKeyframes.length +
65
- movedKeyframes.effectKeyframes.length;
66
- if (edits.length === 0 && totalKeyframeMoves === 0) {
62
+ const saveSequencePropsHandler = ({ input: { edits, addedKeyframes, movedKeyframes, clientId, undoLabel, redoLabel, }, remotionRoot, logLevel, }) => (0, source_file_write_queue_1.withSourceFileWriteQueue)(async () => {
63
+ var _a, _b, _c, _d;
64
+ const keyframesToAdd = addedKeyframes === null ? [] : addedKeyframes;
65
+ const keyframesToMove = movedKeyframes === null
66
+ ? { sequenceKeyframes: [], effectKeyframes: [] }
67
+ : movedKeyframes;
68
+ const totalKeyframeMoves = keyframesToMove.sequenceKeyframes.length +
69
+ keyframesToMove.effectKeyframes.length;
70
+ if (edits.length === 0 &&
71
+ keyframesToAdd.length === 0 &&
72
+ totalKeyframeMoves === 0) {
67
73
  throw new Error('No sequence prop edits to save');
68
74
  }
69
- renderer_1.RenderInternals.Log.trace({ indent: false, logLevel }, `[save-sequence-props] Received request with ${edits.length} edit(s) and ${totalKeyframeMoves} moved keyframe(s)`);
75
+ renderer_1.RenderInternals.Log.trace({ indent: false, logLevel }, `[save-sequence-props] Received request with ${edits.length} edit(s), ${keyframesToAdd.length} added keyframe(s), and ${totalKeyframeMoves} moved keyframe(s)`);
70
76
  const editGroups = new Map();
71
77
  for (const [index, edit] of edits.entries()) {
72
78
  const parsedValue = parseSequencePropEditValue(edit.value);
@@ -79,7 +85,8 @@ const saveSequencePropsHandler = ({ input: { edits, movedKeyframes = { sequenceK
79
85
  const group = (_a = editGroups.get(absolutePath)) !== null && _a !== void 0 ? _a : {
80
86
  fileRelativeToRoot,
81
87
  edits: [],
82
- sequenceKeyframes: [],
88
+ addedKeyframes: [],
89
+ movedSequenceKeyframes: [],
83
90
  effectKeyframes: [],
84
91
  };
85
92
  group.edits.push({
@@ -98,7 +105,7 @@ const saveSequencePropsHandler = ({ input: { edits, movedKeyframes = { sequenceK
98
105
  });
99
106
  editGroups.set(absolutePath, group);
100
107
  }
101
- for (const [index, keyframe,] of movedKeyframes.sequenceKeyframes.entries()) {
108
+ for (const keyframe of keyframesToAdd) {
102
109
  const { absolutePath, fileRelativeToRoot } = (0, resolve_file_inside_project_1.resolveFileInsideProject)({
103
110
  remotionRoot,
104
111
  fileName: keyframe.fileName,
@@ -107,13 +114,14 @@ const saveSequencePropsHandler = ({ input: { edits, movedKeyframes = { sequenceK
107
114
  const group = (_b = editGroups.get(absolutePath)) !== null && _b !== void 0 ? _b : {
108
115
  fileRelativeToRoot,
109
116
  edits: [],
110
- sequenceKeyframes: [],
117
+ addedKeyframes: [],
118
+ movedSequenceKeyframes: [],
111
119
  effectKeyframes: [],
112
120
  };
113
- group.sequenceKeyframes.push({ ...keyframe, index });
121
+ group.addedKeyframes.push(keyframe);
114
122
  editGroups.set(absolutePath, group);
115
123
  }
116
- for (const [index, keyframe] of movedKeyframes.effectKeyframes.entries()) {
124
+ for (const [index, keyframe,] of keyframesToMove.sequenceKeyframes.entries()) {
117
125
  const { absolutePath, fileRelativeToRoot } = (0, resolve_file_inside_project_1.resolveFileInsideProject)({
118
126
  remotionRoot,
119
127
  fileName: keyframe.fileName,
@@ -122,7 +130,24 @@ const saveSequencePropsHandler = ({ input: { edits, movedKeyframes = { sequenceK
122
130
  const group = (_c = editGroups.get(absolutePath)) !== null && _c !== void 0 ? _c : {
123
131
  fileRelativeToRoot,
124
132
  edits: [],
125
- sequenceKeyframes: [],
133
+ addedKeyframes: [],
134
+ movedSequenceKeyframes: [],
135
+ effectKeyframes: [],
136
+ };
137
+ group.movedSequenceKeyframes.push({ ...keyframe, index });
138
+ editGroups.set(absolutePath, group);
139
+ }
140
+ for (const [index, keyframe] of keyframesToMove.effectKeyframes.entries()) {
141
+ const { absolutePath, fileRelativeToRoot } = (0, resolve_file_inside_project_1.resolveFileInsideProject)({
142
+ remotionRoot,
143
+ fileName: keyframe.fileName,
144
+ action: 'modify',
145
+ });
146
+ const group = (_d = editGroups.get(absolutePath)) !== null && _d !== void 0 ? _d : {
147
+ fileRelativeToRoot,
148
+ edits: [],
149
+ addedKeyframes: [],
150
+ movedSequenceKeyframes: [],
126
151
  effectKeyframes: [],
127
152
  };
128
153
  group.effectKeyframes.push({ ...keyframe, index });
@@ -158,7 +183,40 @@ const saveSequencePropsHandler = ({ input: { edits, movedKeyframes = { sequenceK
158
183
  });
159
184
  }
160
185
  }
161
- for (const keyframeGroup of groupBy(group.sequenceKeyframes, (keyframe) => JSON.stringify(keyframe.nodePath.nodePath))) {
186
+ for (const keyframeGroup of groupBy(group.addedKeyframes, (keyframe) => JSON.stringify(keyframe.nodePath.nodePath))) {
187
+ const [firstSequenceKeyframe] = keyframeGroup;
188
+ if (!firstSequenceKeyframe) {
189
+ continue;
190
+ }
191
+ const updates = keyframeGroup.map((keyframe) => ({
192
+ key: keyframe.key,
193
+ operation: {
194
+ type: 'add',
195
+ frame: keyframe.frame,
196
+ value: JSON.parse(keyframe.value),
197
+ },
198
+ }));
199
+ const result = await (0, update_keyframes_1.updateSequenceKeyframes)({
200
+ input: output,
201
+ nodePath: firstSequenceKeyframe.nodePath.nodePath,
202
+ schema: firstSequenceKeyframe.schema,
203
+ videoConfigValues: firstSequenceKeyframe.nodePath.videoConfigValues,
204
+ updates,
205
+ });
206
+ output = result.output;
207
+ firstLogLine = Math.min(firstLogLine, result.logLine);
208
+ for (const [updateIndex, update] of updates.entries()) {
209
+ sequenceKeyframeLogs.push({
210
+ fileRelativeToRoot: group.fileRelativeToRoot,
211
+ line: result.logLine,
212
+ key: update.key,
213
+ oldValueString: result.oldValueStrings[updateIndex],
214
+ newValueString: result.newValueStrings[updateIndex],
215
+ formatted: result.formatted,
216
+ });
217
+ }
218
+ }
219
+ for (const keyframeGroup of groupBy(group.movedSequenceKeyframes, (keyframe) => JSON.stringify(keyframe.nodePath.nodePath))) {
162
220
  const [firstSequenceKeyframe] = keyframeGroup;
163
221
  if (!firstSequenceKeyframe) {
164
222
  continue;
@@ -318,10 +376,16 @@ const saveSequencePropsHandler = ({ input: { edits, movedKeyframes = { sequenceK
318
376
  });
319
377
  }
320
378
  (0, undo_stack_1.printUndoHint)(logLevel);
321
- const results = edits.map((edit) => {
379
+ const statusTargets = [
380
+ ...new Map([...edits, ...keyframesToAdd].map((target) => [
381
+ JSON.stringify(target.nodePath),
382
+ target,
383
+ ])).values(),
384
+ ];
385
+ const results = statusTargets.map((target) => {
322
386
  const { absolutePath } = (0, resolve_file_inside_project_1.resolveFileInsideProject)({
323
387
  remotionRoot,
324
- fileName: edit.fileName,
388
+ fileName: target.fileName,
325
389
  action: 'modify',
326
390
  });
327
391
  const output = outputByPath.get(absolutePath);
@@ -330,22 +394,26 @@ const saveSequencePropsHandler = ({ input: { edits, movedKeyframes = { sequenceK
330
394
  }
331
395
  const newStatus = (0, can_update_sequence_props_1.computeSequencePropsStatusFromContent)({
332
396
  fileContents: output,
333
- keys: (0, studio_shared_1.getAllSchemaKeys)(edit.schema),
334
- assetKeys: (0, studio_shared_1.getAssetSchemaKeys)(edit.schema),
335
- nodePath: edit.nodePath.nodePath,
397
+ keys: (0, studio_shared_1.getAllSchemaKeys)(target.schema),
398
+ assetKeys: (0, studio_shared_1.getAssetSchemaKeys)(target.schema),
399
+ nodePath: target.nodePath.nodePath,
336
400
  componentIdentity: null,
337
401
  effects: [],
338
- videoConfigValues: edit.nodePath.videoConfigValues,
402
+ videoConfigValues: target.nodePath.videoConfigValues,
339
403
  });
340
404
  return {
341
- fileName: edit.fileName,
342
- nodePath: edit.nodePath,
405
+ fileName: target.fileName,
406
+ nodePath: target.nodePath,
343
407
  props: newStatus.props,
344
408
  };
345
409
  });
410
+ const firstResult = results[0];
411
+ if (!firstResult) {
412
+ throw new Error('Could not compute sequence prop edit status');
413
+ }
346
414
  return {
347
415
  canUpdate: true,
348
- props: results[0].props,
416
+ props: firstResult.props,
349
417
  results,
350
418
  };
351
419
  });
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.496",
6
+ "version": "4.0.497",
7
7
  "description": "Run a Remotion Studio with a server backend",
8
8
  "main": "dist",
9
9
  "scripts": {
@@ -30,11 +30,11 @@
30
30
  "kiwi-schema": "0.5.0",
31
31
  "semver": "7.5.3",
32
32
  "prettier": "3.8.1",
33
- "remotion": "4.0.496",
33
+ "remotion": "4.0.497",
34
34
  "recast": "0.23.11",
35
- "@remotion/bundler": "4.0.496",
36
- "@remotion/renderer": "4.0.496",
37
- "@remotion/studio-shared": "4.0.496",
35
+ "@remotion/bundler": "4.0.497",
36
+ "@remotion/renderer": "4.0.497",
37
+ "@remotion/studio-shared": "4.0.497",
38
38
  "memfs": "3.4.3",
39
39
  "open": "8.4.2"
40
40
  },
@@ -42,7 +42,7 @@
42
42
  "ast-types": "0.16.1",
43
43
  "react": "19.2.3",
44
44
  "@types/semver": "7.5.3",
45
- "@remotion/eslint-config-internal": "4.0.496",
45
+ "@remotion/eslint-config-internal": "4.0.497",
46
46
  "eslint": "9.19.0",
47
47
  "@types/node": "20.12.14",
48
48
  "@typescript/native-preview": "7.0.0-dev.20260217.1"
@@ -1,3 +0,0 @@
1
- import type { DeleteEffectKeyframeRequest, DeleteEffectKeyframeResponse } from '@remotion/studio-shared';
2
- import type { ApiHandler } from '../api-types';
3
- export declare const deleteEffectKeyframeHandler: ApiHandler<DeleteEffectKeyframeRequest, DeleteEffectKeyframeResponse>;
@@ -1,89 +0,0 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.deleteEffectKeyframeHandler = void 0;
4
- const node_fs_1 = require("node:fs");
5
- const renderer_1 = require("@remotion/renderer");
6
- const studio_shared_1 = require("@remotion/studio-shared");
7
- const parse_ast_1 = require("../../codemods/parse-ast");
8
- const update_keyframes_1 = require("../../codemods/update-keyframes/update-keyframes");
9
- const file_watcher_1 = require("../../file-watcher");
10
- const resolve_file_inside_project_1 = require("../../helpers/resolve-file-inside-project");
11
- const undo_stack_1 = require("../undo-stack");
12
- const watch_ignore_next_change_1 = require("../watch-ignore-next-change");
13
- const can_update_effect_props_1 = require("./can-update-effect-props");
14
- const can_update_sequence_props_1 = require("./can-update-sequence-props");
15
- const log_effect_update_1 = require("./log-updates/log-effect-update");
16
- const save_props_mutex_1 = require("./save-props-mutex");
17
- const deleteEffectKeyframeHandler = ({ input: { fileName, sequenceNodePath, effectIndex, key, frame, schema, clientId, }, remotionRoot, logLevel, }) => (0, save_props_mutex_1.withSavePropsLock)(async () => {
18
- renderer_1.RenderInternals.Log.trace({ indent: false, logLevel }, `[delete-effect-keyframe] Received request for fileName="${fileName}" effectIndex=${effectIndex} key="${key}" frame=${frame}`);
19
- const { absolutePath, fileRelativeToRoot } = (0, resolve_file_inside_project_1.resolveFileInsideProject)({
20
- remotionRoot,
21
- fileName,
22
- action: 'modify',
23
- });
24
- const fileContents = (0, node_fs_1.readFileSync)(absolutePath, 'utf-8');
25
- const { output, oldValueStrings, newValueStrings, formatted, logLine, effectCallee, } = await (0, update_keyframes_1.updateEffectKeyframes)({
26
- input: fileContents,
27
- sequenceNodePath: sequenceNodePath.nodePath,
28
- effectIndex,
29
- updates: [
30
- {
31
- key,
32
- operation: {
33
- type: 'remove',
34
- frame,
35
- },
36
- },
37
- ],
38
- });
39
- const oldValueString = oldValueStrings[0];
40
- const newValueString = newValueStrings[0];
41
- const undoPropChange = `${key} keyframe restored at frame ${frame}`;
42
- const redoPropChange = `${key} keyframe deleted at frame ${frame}`;
43
- (0, undo_stack_1.pushToUndoStack)({
44
- filePath: absolutePath,
45
- oldContents: fileContents,
46
- newContents: null,
47
- logLevel,
48
- remotionRoot,
49
- logLine,
50
- description: {
51
- undoMessage: `↩️ ${undoPropChange}`,
52
- redoMessage: `↪️ ${redoPropChange}`,
53
- },
54
- entryType: 'effect-props',
55
- suppressHmrOnFileRestore: true,
56
- });
57
- (0, undo_stack_1.suppressUndoStackInvalidation)(absolutePath);
58
- (0, watch_ignore_next_change_1.suppressBundlerUpdateForFile)(absolutePath);
59
- (0, file_watcher_1.writeFileAndNotifyFileWatchers)(absolutePath, output, clientId);
60
- (0, log_effect_update_1.logEffectUpdate)({
61
- fileRelativeToRoot,
62
- line: logLine,
63
- effectName: effectCallee,
64
- propKey: key,
65
- oldValueString,
66
- newValueString,
67
- defaultValueString: null,
68
- formatted,
69
- logLevel,
70
- removedProps: [],
71
- addedProps: [],
72
- });
73
- (0, undo_stack_1.printUndoHint)(logLevel);
74
- const ast = (0, parse_ast_1.parseAst)((0, node_fs_1.readFileSync)(absolutePath, 'utf-8'));
75
- const jsx = (0, can_update_sequence_props_1.findJsxElementAtNodePath)(ast, sequenceNodePath.nodePath);
76
- if (!jsx) {
77
- return {
78
- canUpdate: false,
79
- effectIndex,
80
- reason: 'not-found',
81
- };
82
- }
83
- return (0, can_update_effect_props_1.computeEffectPropStatus)({
84
- jsx,
85
- effectIndex,
86
- keys: (0, studio_shared_1.getAllSchemaKeys)(schema),
87
- });
88
- });
89
- exports.deleteEffectKeyframeHandler = deleteEffectKeyframeHandler;
@@ -1,3 +0,0 @@
1
- import type { DeleteSequenceKeyframeRequest, DeleteSequenceKeyframeResponse } from '@remotion/studio-shared';
2
- import type { ApiHandler } from '../api-types';
3
- export declare const deleteSequenceKeyframeHandler: ApiHandler<DeleteSequenceKeyframeRequest, DeleteSequenceKeyframeResponse>;
@@ -1,82 +0,0 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.deleteSequenceKeyframeHandler = void 0;
4
- const node_fs_1 = require("node:fs");
5
- const renderer_1 = require("@remotion/renderer");
6
- const studio_shared_1 = require("@remotion/studio-shared");
7
- const update_keyframes_1 = require("../../codemods/update-keyframes/update-keyframes");
8
- const file_watcher_1 = require("../../file-watcher");
9
- const resolve_file_inside_project_1 = require("../../helpers/resolve-file-inside-project");
10
- const undo_stack_1 = require("../undo-stack");
11
- const watch_ignore_next_change_1 = require("../watch-ignore-next-change");
12
- const can_update_sequence_props_1 = require("./can-update-sequence-props");
13
- const log_update_1 = require("./log-updates/log-update");
14
- const save_props_mutex_1 = require("./save-props-mutex");
15
- const deleteSequenceKeyframeHandler = ({ input: { fileName, nodePath, key, frame, schema, clientId }, remotionRoot, logLevel, }) => (0, save_props_mutex_1.withSavePropsLock)(async () => {
16
- renderer_1.RenderInternals.Log.trace({ indent: false, logLevel }, `[delete-sequence-keyframe] Received request for fileName="${fileName}" key="${key}" frame=${frame}`);
17
- const { absolutePath, fileRelativeToRoot } = (0, resolve_file_inside_project_1.resolveFileInsideProject)({
18
- remotionRoot,
19
- fileName,
20
- action: 'modify',
21
- });
22
- const fileContents = (0, node_fs_1.readFileSync)(absolutePath, 'utf-8');
23
- const { output, oldValueStrings, newValueStrings, formatted, logLine } = await (0, update_keyframes_1.updateSequenceKeyframes)({
24
- input: fileContents,
25
- nodePath: nodePath.nodePath,
26
- updates: [
27
- {
28
- key,
29
- operation: {
30
- type: 'remove',
31
- frame,
32
- },
33
- },
34
- ],
35
- });
36
- const oldValueString = oldValueStrings[0];
37
- const newValueString = newValueStrings[0];
38
- const undoPropChange = `${key} keyframe restored at frame ${frame}`;
39
- const redoPropChange = `${key} keyframe deleted at frame ${frame}`;
40
- (0, undo_stack_1.pushToUndoStack)({
41
- filePath: absolutePath,
42
- oldContents: fileContents,
43
- newContents: null,
44
- logLevel,
45
- remotionRoot,
46
- logLine,
47
- description: {
48
- undoMessage: `↩️ ${undoPropChange}`,
49
- redoMessage: `↪️ ${redoPropChange}`,
50
- },
51
- entryType: 'sequence-props',
52
- suppressHmrOnFileRestore: true,
53
- });
54
- (0, undo_stack_1.suppressUndoStackInvalidation)(absolutePath);
55
- (0, watch_ignore_next_change_1.suppressBundlerUpdateForFile)(absolutePath);
56
- (0, file_watcher_1.writeFileAndNotifyFileWatchers)(absolutePath, output, clientId);
57
- (0, log_update_1.logUpdate)({
58
- fileRelativeToRoot,
59
- line: logLine,
60
- key,
61
- oldValueString,
62
- newValueString,
63
- defaultValueString: null,
64
- formatted,
65
- logLevel,
66
- removedProps: [],
67
- addedProps: [],
68
- });
69
- (0, undo_stack_1.printUndoHint)(logLevel);
70
- const status = (0, can_update_sequence_props_1.computeSequencePropsStatusFromContent)({
71
- fileContents: output,
72
- keys: (0, studio_shared_1.getAllSchemaKeys)(schema),
73
- nodePath: nodePath.nodePath,
74
- effects: [],
75
- });
76
- return {
77
- canUpdate: true,
78
- props: status.props,
79
- results: [{ fileName, nodePath, props: status.props }],
80
- };
81
- });
82
- exports.deleteSequenceKeyframeHandler = deleteSequenceKeyframeHandler;
@@ -1 +0,0 @@
1
- export declare const withSavePropsLock: <T>(fn: () => Promise<T>) => Promise<T>;
@@ -1,11 +0,0 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.withSavePropsLock = void 0;
4
- let chain = Promise.resolve();
5
- const withSavePropsLock = (fn) => {
6
- const run = () => fn();
7
- const next = chain.then(run, run);
8
- chain = next.then(() => undefined, () => undefined);
9
- return next;
10
- };
11
- exports.withSavePropsLock = withSavePropsLock;