@remotion/studio-server 4.0.469 → 4.0.471

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 (68) hide show
  1. package/dist/codemods/add-effect.d.ts +15 -0
  2. package/dist/codemods/add-effect.js +231 -0
  3. package/dist/codemods/delete-effect.d.ts +18 -0
  4. package/dist/codemods/delete-effect.js +95 -21
  5. package/dist/codemods/delete-jsx-node.d.ts +10 -0
  6. package/dist/codemods/delete-jsx-node.js +38 -14
  7. package/dist/codemods/reorder-effect.d.ts +13 -0
  8. package/dist/codemods/reorder-effect.js +61 -0
  9. package/dist/codemods/update-keyframes/ensure-imports-and-frame-hook.d.ts +4 -0
  10. package/dist/codemods/update-keyframes/ensure-imports-and-frame-hook.js +152 -0
  11. package/dist/codemods/update-keyframes/update-keyframes.d.ts +12 -0
  12. package/dist/codemods/update-keyframes/update-keyframes.js +116 -31
  13. package/dist/codemods/update-sequence-props/update-sequence-props.d.ts +32 -10
  14. package/dist/codemods/update-sequence-props/update-sequence-props.js +39 -7
  15. package/dist/helpers/open-in-editor.d.ts +2 -2
  16. package/dist/helpers/open-in-editor.js +35 -2
  17. package/dist/helpers/resolve-composition-component.d.ts +15 -0
  18. package/dist/helpers/resolve-composition-component.js +269 -31
  19. package/dist/index.d.ts +2 -1
  20. package/dist/preview-server/api-routes.js +20 -0
  21. package/dist/preview-server/routes/add-effect-keyframe.d.ts +3 -0
  22. package/dist/preview-server/routes/add-effect-keyframe.js +91 -0
  23. package/dist/preview-server/routes/add-effect.d.ts +3 -0
  24. package/dist/preview-server/routes/add-effect.js +68 -0
  25. package/dist/preview-server/routes/add-sequence-keyframe.d.ts +3 -0
  26. package/dist/preview-server/routes/add-sequence-keyframe.js +87 -0
  27. package/dist/preview-server/routes/apply-codemod.js +1 -0
  28. package/dist/preview-server/routes/apply-visual-control-change.js +1 -0
  29. package/dist/preview-server/routes/can-update-sequence-props.d.ts +1 -0
  30. package/dist/preview-server/routes/can-update-sequence-props.js +48 -14
  31. package/dist/preview-server/routes/composition-component-info.d.ts +3 -0
  32. package/dist/preview-server/routes/composition-component-info.js +26 -0
  33. package/dist/preview-server/routes/delete-effect-keyframe.d.ts +3 -0
  34. package/dist/preview-server/routes/delete-effect-keyframe.js +89 -0
  35. package/dist/preview-server/routes/delete-effect.js +76 -37
  36. package/dist/preview-server/routes/delete-jsx-node.js +67 -36
  37. package/dist/preview-server/routes/delete-keyframes.d.ts +13 -0
  38. package/dist/preview-server/routes/delete-keyframes.js +263 -0
  39. package/dist/preview-server/routes/delete-sequence-keyframe.d.ts +3 -0
  40. package/dist/preview-server/routes/delete-sequence-keyframe.js +82 -0
  41. package/dist/preview-server/routes/duplicate-jsx-node.js +1 -0
  42. package/dist/preview-server/routes/insert-jsx-element.d.ts +3 -0
  43. package/dist/preview-server/routes/insert-jsx-element.js +79 -0
  44. package/dist/preview-server/routes/open-in-editor.d.ts +4 -0
  45. package/dist/preview-server/routes/open-in-editor.js +40 -0
  46. package/dist/preview-server/routes/register-client-render.d.ts +3 -0
  47. package/dist/preview-server/routes/register-client-render.js +11 -0
  48. package/dist/preview-server/routes/reorder-effect.d.ts +3 -0
  49. package/dist/preview-server/routes/reorder-effect.js +67 -0
  50. package/dist/preview-server/routes/save-effect-props.js +1 -0
  51. package/dist/preview-server/routes/save-sequence-props.js +158 -72
  52. package/dist/preview-server/routes/subscribe-to-sequence-props.js +2 -1
  53. package/dist/preview-server/routes/unregister-client-render.d.ts +4 -0
  54. package/dist/preview-server/routes/unregister-client-render.js +11 -0
  55. package/dist/preview-server/routes/update-default-props.js +1 -0
  56. package/dist/preview-server/sequence-props-watchers.d.ts +2 -1
  57. package/dist/preview-server/sequence-props-watchers.js +22 -2
  58. package/dist/preview-server/start-server.d.ts +1 -0
  59. package/dist/preview-server/start-server.js +1 -0
  60. package/dist/preview-server/undo-stack.d.ts +35 -4
  61. package/dist/preview-server/undo-stack.js +130 -42
  62. package/dist/preview-server/validate-same-origin.d.ts +2 -0
  63. package/dist/preview-server/validate-same-origin.js +13 -0
  64. package/dist/routes.d.ts +2 -1
  65. package/dist/routes.js +9 -136
  66. package/dist/start-studio.d.ts +2 -1
  67. package/dist/start-studio.js +2 -1
  68. package/package.json +6 -6
@@ -0,0 +1,68 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.addEffectHandler = void 0;
4
+ const node_fs_1 = require("node:fs");
5
+ const renderer_1 = require("@remotion/renderer");
6
+ const add_effect_1 = require("../../codemods/add-effect");
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 formatting_1 = require("./log-updates/formatting");
12
+ const log_update_1 = require("./log-updates/log-update");
13
+ const addEffectHandler = async ({ input: { fileName, sequenceNodePath, effectName, effectImportPath, effectConfig, clientId, }, remotionRoot, logLevel, }) => {
14
+ try {
15
+ renderer_1.RenderInternals.Log.trace({ indent: false, logLevel }, `[add-effect] Received request for fileName="${fileName}" effect="${effectName}"`);
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, effectLabel, nodeLabel, logLine } = await (0, add_effect_1.addEffect)({
23
+ input: fileContents,
24
+ sequenceNodePath: sequenceNodePath.nodePath,
25
+ effectName,
26
+ effectImportPath,
27
+ effectConfig,
28
+ });
29
+ (0, undo_stack_1.pushToUndoStack)({
30
+ filePath: absolutePath,
31
+ oldContents: fileContents,
32
+ newContents: null,
33
+ logLevel,
34
+ remotionRoot,
35
+ logLine,
36
+ description: {
37
+ undoMessage: `↩️ Addition of ${effectLabel} to ${nodeLabel}`,
38
+ redoMessage: `↪️ Addition of ${effectLabel} to ${nodeLabel}`,
39
+ },
40
+ entryType: 'add-effect',
41
+ suppressHmrOnFileRestore: false,
42
+ });
43
+ (0, undo_stack_1.suppressUndoStackInvalidation)(absolutePath);
44
+ (0, file_watcher_1.writeFileAndNotifyFileWatchers)(absolutePath, output, clientId);
45
+ const locationLabel = (0, format_log_file_location_1.formatLogFileLocation)({
46
+ remotionRoot,
47
+ absolutePath,
48
+ line: logLine,
49
+ });
50
+ renderer_1.RenderInternals.Log.info({ indent: false, logLevel }, `${renderer_1.RenderInternals.chalk.blueBright(`${locationLabel}`)} Added ${(0, formatting_1.attrName)(effectLabel)} to ${nodeLabel}`);
51
+ if (!formatted) {
52
+ (0, log_update_1.warnAboutPrettierOnce)(logLevel);
53
+ }
54
+ renderer_1.RenderInternals.Log.verbose({ indent: false, logLevel }, `[add-effect] Wrote ${fileRelativeToRoot}${formatted ? ' (formatted)' : ''}`);
55
+ (0, undo_stack_1.printUndoHint)(logLevel);
56
+ return {
57
+ success: true,
58
+ };
59
+ }
60
+ catch (err) {
61
+ return {
62
+ success: false,
63
+ reason: err.message,
64
+ stack: err.stack,
65
+ };
66
+ }
67
+ };
68
+ exports.addEffectHandler = addEffectHandler;
@@ -0,0 +1,3 @@
1
+ import type { AddSequenceKeyframeRequest, AddSequenceKeyframeResponse } from '@remotion/studio-shared';
2
+ import type { ApiHandler } from '../api-types';
3
+ export declare const addSequenceKeyframeHandler: ApiHandler<AddSequenceKeyframeRequest, AddSequenceKeyframeResponse>;
@@ -0,0 +1,87 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.addSequenceKeyframeHandler = 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 addSequenceKeyframeHandler = ({ input: { fileName, nodePath, key, frame, value, schema, clientId }, remotionRoot, logLevel, }) => (0, save_props_mutex_1.withSavePropsLock)(async () => {
16
+ renderer_1.RenderInternals.Log.trace({ indent: false, logLevel }, `[add-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 parsedValue = JSON.parse(value);
24
+ const { output, oldValueStrings, newValueStrings, formatted, logLine, updatedNodePath, } = await (0, update_keyframes_1.updateSequenceKeyframes)({
25
+ input: fileContents,
26
+ nodePath: nodePath.nodePath,
27
+ updates: [
28
+ {
29
+ key,
30
+ operation: {
31
+ type: 'add',
32
+ frame,
33
+ value: parsedValue,
34
+ },
35
+ },
36
+ ],
37
+ });
38
+ const oldValueString = oldValueStrings[0];
39
+ const newValueString = newValueStrings[0];
40
+ const undoPropChange = `${key} keyframe removed at frame ${frame}`;
41
+ const redoPropChange = `${key} keyframe added at frame ${frame}`;
42
+ (0, undo_stack_1.pushToUndoStack)({
43
+ filePath: absolutePath,
44
+ oldContents: fileContents,
45
+ newContents: null,
46
+ logLevel,
47
+ remotionRoot,
48
+ logLine,
49
+ description: {
50
+ undoMessage: `↩️ ${undoPropChange}`,
51
+ redoMessage: `↪️ ${redoPropChange}`,
52
+ },
53
+ entryType: 'sequence-props',
54
+ suppressHmrOnFileRestore: true,
55
+ });
56
+ (0, undo_stack_1.suppressUndoStackInvalidation)(absolutePath);
57
+ (0, watch_ignore_next_change_1.suppressBundlerUpdateForFile)(absolutePath);
58
+ (0, file_watcher_1.writeFileAndNotifyFileWatchers)(absolutePath, output, clientId);
59
+ (0, log_update_1.logUpdate)({
60
+ fileRelativeToRoot,
61
+ line: logLine,
62
+ key,
63
+ oldValueString,
64
+ newValueString,
65
+ defaultValueString: null,
66
+ formatted,
67
+ logLevel,
68
+ removedProps: [],
69
+ addedProps: [],
70
+ });
71
+ (0, undo_stack_1.printUndoHint)(logLevel);
72
+ const status = (0, can_update_sequence_props_1.computeSequencePropsStatusFromContent)({
73
+ fileContents: output,
74
+ keys: (0, studio_shared_1.getAllSchemaKeys)(schema),
75
+ nodePath: updatedNodePath,
76
+ effects: [],
77
+ });
78
+ const updatedSubscriptionKey = { ...nodePath, nodePath: updatedNodePath };
79
+ return {
80
+ canUpdate: true,
81
+ props: status.props,
82
+ results: [
83
+ { fileName, nodePath: updatedSubscriptionKey, props: status.props },
84
+ ],
85
+ };
86
+ });
87
+ exports.addSequenceKeyframeHandler = addSequenceKeyframeHandler;
@@ -68,6 +68,7 @@ const applyCodemodHandler = async ({ input: { codemod, dryRun, symbolicatedStack
68
68
  (0, undo_stack_1.pushToUndoStack)({
69
69
  filePath,
70
70
  oldContents: input,
71
+ newContents: null,
71
72
  logLevel,
72
73
  remotionRoot,
73
74
  logLine: (_a = symbolicatedStack === null || symbolicatedStack === void 0 ? void 0 : symbolicatedStack.originalLineNumber) !== null && _a !== void 0 ? _a : 1,
@@ -111,6 +111,7 @@ const applyVisualControlHandler = async ({ input: { fileName, changes }, remotio
111
111
  (0, undo_stack_1.pushToUndoStack)({
112
112
  filePath: absolutePath,
113
113
  oldContents: fileContents,
114
+ newContents: null,
114
115
  logLevel,
115
116
  remotionRoot,
116
117
  logLine,
@@ -5,6 +5,7 @@ export declare const isStaticValue: (node: Expression) => boolean;
5
5
  export declare const extractStaticValue: (node: Expression) => unknown;
6
6
  export declare const getComputedStatus: (node: Expression) => CanUpdateSequencePropStatus;
7
7
  export declare const findJsxElementAtNodePath: (ast: File, nodePath: SequenceNodePath) => JSXOpeningElement | null;
8
+ export declare const findNodePathForJsxElement: (ast: File, target: JSXOpeningElement) => SequenceNodePath | null;
8
9
  export declare const lineColumnToNodePath: (ast: File, targetLine: number) => SequenceNodePath | null;
9
10
  export declare const computeSequencePropsStatusFromContent: ({ fileContents, nodePath, keys, effects, }: {
10
11
  fileContents: string;
@@ -33,7 +33,7 @@ var __importStar = (this && this.__importStar) || (function () {
33
33
  };
34
34
  })();
35
35
  Object.defineProperty(exports, "__esModule", { value: true });
36
- exports.computeSequencePropsStatusFromFilenameByLine = exports.computeSequencePropsStatus = exports.computeSequencePropsStatusFromContent = exports.lineColumnToNodePath = exports.findJsxElementAtNodePath = exports.getComputedStatus = exports.extractStaticValue = exports.isStaticValue = void 0;
36
+ exports.computeSequencePropsStatusFromFilenameByLine = exports.computeSequencePropsStatus = exports.computeSequencePropsStatusFromContent = exports.lineColumnToNodePath = exports.findNodePathForJsxElement = exports.findJsxElementAtNodePath = exports.getComputedStatus = exports.extractStaticValue = exports.isStaticValue = void 0;
37
37
  const node_fs_1 = require("node:fs");
38
38
  const renderer_1 = require("@remotion/renderer");
39
39
  const recast = __importStar(require("recast"));
@@ -211,12 +211,9 @@ const getKeyframeEasingArray = ({ easingNode, segments, }) => {
211
211
  }
212
212
  return new Array(segments).fill(easing);
213
213
  };
214
- const getInterpolationMetadata = (callExpression, keyframeCount) => {
214
+ const getInterpolationMetadata = (interpolationFunction, callExpression, keyframeCount) => {
215
215
  const segments = Math.max(0, keyframeCount - 1);
216
- if (callExpression.callee.type !== 'Identifier') {
217
- return null;
218
- }
219
- const defaultClamping = callExpression.callee.name === 'interpolateColors'
216
+ const defaultClamping = interpolationFunction === 'interpolateColors'
220
217
  ? {
221
218
  left: 'clamp',
222
219
  right: 'clamp',
@@ -228,13 +225,8 @@ const getInterpolationMetadata = (callExpression, keyframeCount) => {
228
225
  const defaults = {
229
226
  easing: new Array(segments).fill('linear'),
230
227
  clamping: defaultClamping,
228
+ posterize: undefined,
231
229
  };
232
- if (callExpression.callee.name === 'interpolateColors') {
233
- return defaults;
234
- }
235
- if (callExpression.callee.name !== 'interpolate') {
236
- return null;
237
- }
238
230
  const optionsArg = callExpression.arguments[3];
239
231
  if (!optionsArg) {
240
232
  return defaults;
@@ -244,6 +236,7 @@ const getInterpolationMetadata = (callExpression, keyframeCount) => {
244
236
  }
245
237
  let { easing } = defaults;
246
238
  let { clamping } = defaults;
239
+ let posterize;
247
240
  for (const property of optionsArg.properties) {
248
241
  if (property.type !== 'ObjectProperty' || property.computed) {
249
242
  return null;
@@ -258,6 +251,9 @@ const getInterpolationMetadata = (callExpression, keyframeCount) => {
258
251
  }
259
252
  const value = property.value;
260
253
  if (key === 'easing') {
254
+ if (interpolationFunction === 'interpolateColors') {
255
+ return null;
256
+ }
261
257
  const parsedEasing = getKeyframeEasingArray({
262
258
  easingNode: value,
263
259
  segments,
@@ -269,6 +265,9 @@ const getInterpolationMetadata = (callExpression, keyframeCount) => {
269
265
  continue;
270
266
  }
271
267
  if (key === 'extrapolateLeft' || key === 'extrapolateRight') {
268
+ if (interpolationFunction === 'interpolateColors') {
269
+ return null;
270
+ }
272
271
  const extrapolateType = getExtrapolateType(value);
273
272
  if (!extrapolateType) {
274
273
  return null;
@@ -277,9 +276,25 @@ const getInterpolationMetadata = (callExpression, keyframeCount) => {
277
276
  key === 'extrapolateLeft'
278
277
  ? { ...clamping, left: extrapolateType }
279
278
  : { ...clamping, right: extrapolateType };
279
+ continue;
280
+ }
281
+ if (key === 'posterize') {
282
+ const parsedPosterize = getNumericValue(value);
283
+ if (parsedPosterize === null ||
284
+ !Number.isFinite(parsedPosterize) ||
285
+ parsedPosterize <= 0) {
286
+ return null;
287
+ }
288
+ posterize = parsedPosterize;
289
+ continue;
280
290
  }
291
+ return null;
281
292
  }
282
- return { easing, clamping };
293
+ return {
294
+ easing,
295
+ clamping,
296
+ posterize,
297
+ };
283
298
  };
284
299
  const getInterpolationKeyframes = (node) => {
285
300
  if (node.type === 'TSAsExpression') {
@@ -294,6 +309,7 @@ const getInterpolationKeyframes = (node) => {
294
309
  callExpression.callee.name !== 'interpolateColors')) {
295
310
  return undefined;
296
311
  }
312
+ const interpolationFunction = callExpression.callee.name;
297
313
  const inputArg = callExpression.arguments[1];
298
314
  const outputArg = callExpression.arguments[2];
299
315
  if (!inputArg ||
@@ -327,14 +343,16 @@ const getInterpolationKeyframes = (node) => {
327
343
  if (keyframes.length === 0) {
328
344
  return undefined;
329
345
  }
330
- const metadata = getInterpolationMetadata(callExpression, keyframes.length);
346
+ const metadata = getInterpolationMetadata(interpolationFunction, callExpression, keyframes.length);
331
347
  if (!metadata) {
332
348
  return undefined;
333
349
  }
334
350
  return {
351
+ interpolationFunction,
335
352
  keyframes,
336
353
  easing: metadata.easing,
337
354
  clamping: metadata.clamping,
355
+ posterize: metadata.posterize,
338
356
  };
339
357
  };
340
358
  const getComputedStatus = (node) => {
@@ -345,9 +363,11 @@ const getComputedStatus = (node) => {
345
363
  return {
346
364
  canUpdate: false,
347
365
  reason: 'keyframed',
366
+ interpolationFunction: interpolation.interpolationFunction,
348
367
  keyframes: interpolation.keyframes,
349
368
  easing: interpolation.easing,
350
369
  clamping: interpolation.clamping,
370
+ posterize: interpolation.posterize,
351
371
  };
352
372
  };
353
373
  exports.getComputedStatus = getComputedStatus;
@@ -423,6 +443,20 @@ const findJsxElementAtNodePath = (ast, nodePath) => {
423
443
  return null;
424
444
  };
425
445
  exports.findJsxElementAtNodePath = findJsxElementAtNodePath;
446
+ const findNodePathForJsxElement = (ast, target) => {
447
+ let foundPath = null;
448
+ recast.types.visit(ast, {
449
+ visitJSXOpeningElement(p) {
450
+ if (p.node === target) {
451
+ foundPath = getNodePathForRecastPath(p);
452
+ return false;
453
+ }
454
+ return this.traverse(p);
455
+ },
456
+ });
457
+ return foundPath;
458
+ };
459
+ exports.findNodePathForJsxElement = findNodePathForJsxElement;
426
460
  const lineColumnToNodePath = (ast, targetLine) => {
427
461
  let foundPath = null;
428
462
  recast.types.visit(ast, {
@@ -0,0 +1,3 @@
1
+ import type { CompositionComponentInfoRequest, CompositionComponentInfoResponse } from '@remotion/studio-shared';
2
+ import type { ApiHandler } from '../api-types';
3
+ export declare const compositionComponentInfoHandler: ApiHandler<CompositionComponentInfoRequest, CompositionComponentInfoResponse>;
@@ -0,0 +1,26 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.compositionComponentInfoHandler = void 0;
4
+ const resolve_composition_component_1 = require("../../helpers/resolve-composition-component");
5
+ const compositionComponentInfoHandler = async ({ input: { compositionFile, compositionId }, remotionRoot }) => {
6
+ if (typeof compositionFile !== 'string') {
7
+ throw new TypeError('Need to pass compositionFile');
8
+ }
9
+ if (typeof compositionId !== 'string') {
10
+ throw new TypeError('Need to pass compositionId');
11
+ }
12
+ const location = await (0, resolve_composition_component_1.resolveCompositionComponent)({
13
+ remotionRoot,
14
+ compositionFile,
15
+ compositionId,
16
+ });
17
+ return {
18
+ location: {
19
+ source: location.source,
20
+ line: location.line,
21
+ column: location.column,
22
+ },
23
+ canAddSequence: location.canAddSequence,
24
+ };
25
+ };
26
+ exports.compositionComponentInfoHandler = compositionComponentInfoHandler;
@@ -0,0 +1,3 @@
1
+ import type { DeleteEffectKeyframeRequest, DeleteEffectKeyframeResponse } from '@remotion/studio-shared';
2
+ import type { ApiHandler } from '../api-types';
3
+ export declare const deleteEffectKeyframeHandler: ApiHandler<DeleteEffectKeyframeRequest, DeleteEffectKeyframeResponse>;
@@ -0,0 +1,89 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.deleteEffectKeyframeHandler = void 0;
4
+ const node_fs_1 = require("node:fs");
5
+ const renderer_1 = require("@remotion/renderer");
6
+ const studio_shared_1 = require("@remotion/studio-shared");
7
+ const parse_ast_1 = require("../../codemods/parse-ast");
8
+ const update_keyframes_1 = require("../../codemods/update-keyframes/update-keyframes");
9
+ const file_watcher_1 = require("../../file-watcher");
10
+ const resolve_file_inside_project_1 = require("../../helpers/resolve-file-inside-project");
11
+ const undo_stack_1 = require("../undo-stack");
12
+ const watch_ignore_next_change_1 = require("../watch-ignore-next-change");
13
+ const can_update_effect_props_1 = require("./can-update-effect-props");
14
+ const can_update_sequence_props_1 = require("./can-update-sequence-props");
15
+ const log_effect_update_1 = require("./log-updates/log-effect-update");
16
+ const save_props_mutex_1 = require("./save-props-mutex");
17
+ const deleteEffectKeyframeHandler = ({ input: { fileName, sequenceNodePath, effectIndex, key, frame, schema, clientId, }, remotionRoot, logLevel, }) => (0, save_props_mutex_1.withSavePropsLock)(async () => {
18
+ renderer_1.RenderInternals.Log.trace({ indent: false, logLevel }, `[delete-effect-keyframe] Received request for fileName="${fileName}" effectIndex=${effectIndex} key="${key}" frame=${frame}`);
19
+ const { absolutePath, fileRelativeToRoot } = (0, resolve_file_inside_project_1.resolveFileInsideProject)({
20
+ remotionRoot,
21
+ fileName,
22
+ action: 'modify',
23
+ });
24
+ const fileContents = (0, node_fs_1.readFileSync)(absolutePath, 'utf-8');
25
+ const { output, oldValueStrings, newValueStrings, formatted, logLine, effectCallee, } = await (0, update_keyframes_1.updateEffectKeyframes)({
26
+ input: fileContents,
27
+ sequenceNodePath: sequenceNodePath.nodePath,
28
+ effectIndex,
29
+ updates: [
30
+ {
31
+ key,
32
+ operation: {
33
+ type: 'remove',
34
+ frame,
35
+ },
36
+ },
37
+ ],
38
+ });
39
+ const oldValueString = oldValueStrings[0];
40
+ const newValueString = newValueStrings[0];
41
+ const undoPropChange = `${key} keyframe restored at frame ${frame}`;
42
+ const redoPropChange = `${key} keyframe deleted at frame ${frame}`;
43
+ (0, undo_stack_1.pushToUndoStack)({
44
+ filePath: absolutePath,
45
+ oldContents: fileContents,
46
+ newContents: null,
47
+ logLevel,
48
+ remotionRoot,
49
+ logLine,
50
+ description: {
51
+ undoMessage: `↩️ ${undoPropChange}`,
52
+ redoMessage: `↪️ ${redoPropChange}`,
53
+ },
54
+ entryType: 'effect-props',
55
+ suppressHmrOnFileRestore: true,
56
+ });
57
+ (0, undo_stack_1.suppressUndoStackInvalidation)(absolutePath);
58
+ (0, watch_ignore_next_change_1.suppressBundlerUpdateForFile)(absolutePath);
59
+ (0, file_watcher_1.writeFileAndNotifyFileWatchers)(absolutePath, output, clientId);
60
+ (0, log_effect_update_1.logEffectUpdate)({
61
+ fileRelativeToRoot,
62
+ line: logLine,
63
+ effectName: effectCallee,
64
+ propKey: key,
65
+ oldValueString,
66
+ newValueString,
67
+ defaultValueString: null,
68
+ formatted,
69
+ logLevel,
70
+ removedProps: [],
71
+ addedProps: [],
72
+ });
73
+ (0, undo_stack_1.printUndoHint)(logLevel);
74
+ const ast = (0, parse_ast_1.parseAst)((0, node_fs_1.readFileSync)(absolutePath, 'utf-8'));
75
+ const jsx = (0, can_update_sequence_props_1.findJsxElementAtNodePath)(ast, sequenceNodePath.nodePath);
76
+ if (!jsx) {
77
+ return {
78
+ canUpdate: false,
79
+ effectIndex,
80
+ reason: 'not-found',
81
+ };
82
+ }
83
+ return (0, can_update_effect_props_1.computeEffectPropStatus)({
84
+ jsx,
85
+ effectIndex,
86
+ keys: (0, studio_shared_1.getAllSchemaKeys)(schema),
87
+ });
88
+ });
89
+ exports.deleteEffectKeyframeHandler = deleteEffectKeyframeHandler;
@@ -10,45 +10,84 @@ const format_log_file_location_1 = require("../format-log-file-location");
10
10
  const undo_stack_1 = require("../undo-stack");
11
11
  const formatting_1 = require("./log-updates/formatting");
12
12
  const log_update_1 = require("./log-updates/log-update");
13
- const deleteEffectHandler = async ({ input: { fileName, sequenceNodePath, effectIndex }, remotionRoot, logLevel, }) => {
13
+ const getDeletedEffectDescription = (effectLabels) => {
14
+ if (effectLabels.length === 1) {
15
+ return effectLabels[0];
16
+ }
17
+ return `${effectLabels.length} effects`;
18
+ };
19
+ const deleteEffectHandler = async ({ input: effects, remotionRoot, logLevel }) => {
20
+ var _a;
14
21
  try {
15
- renderer_1.RenderInternals.Log.trace({ indent: false, logLevel }, `[delete-effect] Received request for fileName="${fileName}" effectIndex=${effectIndex}`);
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, effectLabel, logLine } = await (0, delete_effect_1.deleteEffect)({
23
- input: fileContents,
24
- sequenceNodePath: sequenceNodePath.nodePath,
25
- effectIndex,
26
- });
27
- (0, undo_stack_1.pushToUndoStack)({
28
- filePath: absolutePath,
29
- oldContents: fileContents,
30
- logLevel,
31
- remotionRoot,
32
- logLine,
33
- description: {
34
- undoMessage: `↩️ Deletion of ${effectLabel}`,
35
- redoMessage: `↪️ Deletion of ${effectLabel}`,
36
- },
37
- entryType: 'delete-effect',
38
- suppressHmrOnFileRestore: false,
39
- });
40
- (0, undo_stack_1.suppressUndoStackInvalidation)(absolutePath);
41
- (0, file_watcher_1.writeFileAndNotifyFileWatchers)(absolutePath, output, undefined);
42
- const locationLabel = (0, format_log_file_location_1.formatLogFileLocation)({
43
- remotionRoot,
44
- absolutePath,
45
- line: logLine,
46
- });
47
- renderer_1.RenderInternals.Log.info({ indent: false, logLevel }, `${renderer_1.RenderInternals.chalk.blueBright(`${locationLabel}`)} ${(0, formatting_1.strikeThroughOrRemovedPrefix)(effectLabel)}`);
48
- if (!formatted) {
49
- (0, log_update_1.warnAboutPrettierOnce)(logLevel);
22
+ if (effects.length === 0) {
23
+ throw new Error('No effects were specified for deletion');
24
+ }
25
+ renderer_1.RenderInternals.Log.trace({ indent: false, logLevel }, `[delete-effect] Received request to delete ${effects.length} effect target${effects.length === 1 ? '' : 's'}`);
26
+ const itemsByFileName = new Map();
27
+ for (const item of effects) {
28
+ const fileItems = (_a = itemsByFileName.get(item.fileName)) !== null && _a !== void 0 ? _a : [];
29
+ fileItems.push(item);
30
+ itemsByFileName.set(item.fileName, fileItems);
31
+ }
32
+ const updates = await Promise.all([...itemsByFileName.entries()].map(async ([fileName, fileItems]) => {
33
+ const { absolutePath, fileRelativeToRoot } = (0, resolve_file_inside_project_1.resolveFileInsideProject)({
34
+ remotionRoot,
35
+ fileName,
36
+ action: 'modify',
37
+ });
38
+ const fileContents = (0, node_fs_1.readFileSync)(absolutePath, 'utf-8');
39
+ const { output, formatted, effectLabels, logLines } = await (0, delete_effect_1.deleteEffects)({
40
+ input: fileContents,
41
+ effects: fileItems.map((item) => item.type === 'single-effect'
42
+ ? {
43
+ type: 'single-effect',
44
+ sequenceNodePath: item.sequenceNodePath.nodePath,
45
+ effectIndex: item.effectIndex,
46
+ }
47
+ : {
48
+ type: 'all-effects',
49
+ sequenceNodePath: item.sequenceNodePath.nodePath,
50
+ }),
51
+ });
52
+ return {
53
+ absolutePath,
54
+ fileRelativeToRoot,
55
+ fileContents,
56
+ output,
57
+ formatted,
58
+ effectLabels,
59
+ logLine: Math.min(...logLines),
60
+ };
61
+ }));
62
+ for (const update of updates) {
63
+ const deletedEffectDescription = getDeletedEffectDescription(update.effectLabels);
64
+ (0, undo_stack_1.pushToUndoStack)({
65
+ filePath: update.absolutePath,
66
+ oldContents: update.fileContents,
67
+ newContents: null,
68
+ logLevel,
69
+ remotionRoot,
70
+ logLine: update.logLine,
71
+ description: {
72
+ undoMessage: `↩️ Deletion of ${deletedEffectDescription}`,
73
+ redoMessage: `↪️ Deletion of ${deletedEffectDescription}`,
74
+ },
75
+ entryType: 'delete-effect',
76
+ suppressHmrOnFileRestore: false,
77
+ });
78
+ (0, undo_stack_1.suppressUndoStackInvalidation)(update.absolutePath);
79
+ (0, file_watcher_1.writeFileAndNotifyFileWatchers)(update.absolutePath, update.output, undefined);
80
+ const locationLabel = (0, format_log_file_location_1.formatLogFileLocation)({
81
+ remotionRoot,
82
+ absolutePath: update.absolutePath,
83
+ line: update.logLine,
84
+ });
85
+ renderer_1.RenderInternals.Log.info({ indent: false, logLevel }, `${renderer_1.RenderInternals.chalk.blueBright(`${locationLabel}`)} ${(0, formatting_1.strikeThroughOrRemovedPrefix)(deletedEffectDescription)}`);
86
+ if (!update.formatted) {
87
+ (0, log_update_1.warnAboutPrettierOnce)(logLevel);
88
+ }
89
+ renderer_1.RenderInternals.Log.verbose({ indent: false, logLevel }, `[delete-effect] Wrote ${update.fileRelativeToRoot}${update.formatted ? ' (formatted)' : ''}`);
50
90
  }
51
- renderer_1.RenderInternals.Log.verbose({ indent: false, logLevel }, `[delete-effect] Wrote ${fileRelativeToRoot}${formatted ? ' (formatted)' : ''}`);
52
91
  (0, undo_stack_1.printUndoHint)(logLevel);
53
92
  return {
54
93
  success: true,