@remotion/studio-server 4.0.464 → 4.0.465

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.
@@ -0,0 +1,6 @@
1
+ import type { RecastCodemod, SymbolicatedStackFrame } from '@remotion/studio-shared';
2
+ export declare const resolveFilePathFromSymbolicatedStack: (remotionRoot: string, stack: SymbolicatedStackFrame) => string;
3
+ export declare const applyCodemodToFile: ({ filePath, codeMod, }: {
4
+ filePath: string;
5
+ codeMod: RecastCodemod;
6
+ }) => Promise<string>;
@@ -0,0 +1,35 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.applyCodemodToFile = exports.resolveFilePathFromSymbolicatedStack = void 0;
7
+ const node_fs_1 = require("node:fs");
8
+ const node_path_1 = __importDefault(require("node:path"));
9
+ const can_update_default_props_1 = require("../preview-server/routes/can-update-default-props");
10
+ const duplicate_composition_1 = require("./duplicate-composition");
11
+ const resolveFilePathFromSymbolicatedStack = (remotionRoot, stack) => {
12
+ if (!stack.originalFileName) {
13
+ throw new Error('Could not determine the file where this composition is defined');
14
+ }
15
+ const absolutePath = node_path_1.default.resolve(remotionRoot, stack.originalFileName);
16
+ const fileRelativeToRoot = node_path_1.default.relative(remotionRoot, absolutePath);
17
+ if (fileRelativeToRoot.startsWith('..')) {
18
+ throw new Error('Cannot apply codemod to a file outside the project');
19
+ }
20
+ if (!(0, node_fs_1.existsSync)(absolutePath)) {
21
+ throw new Error(`File not found: ${stack.originalFileName}`);
22
+ }
23
+ return absolutePath;
24
+ };
25
+ exports.resolveFilePathFromSymbolicatedStack = resolveFilePathFromSymbolicatedStack;
26
+ const applyCodemodToFile = async ({ filePath, codeMod, }) => {
27
+ (0, can_update_default_props_1.checkIfTypeScriptFile)(filePath);
28
+ const input = (0, node_fs_1.readFileSync)(filePath, 'utf-8');
29
+ const { newContents } = (0, duplicate_composition_1.parseAndApplyCodemod)({
30
+ codeMod,
31
+ input,
32
+ });
33
+ return (0, duplicate_composition_1.formatOutput)(newContents);
34
+ };
35
+ exports.applyCodemodToFile = applyCodemodToFile;
@@ -0,0 +1,12 @@
1
+ import type { SequenceNodePath } from 'remotion';
2
+ export declare const deleteEffect: ({ input, sequenceNodePath, effectIndex, prettierConfigOverride, }: {
3
+ input: string;
4
+ sequenceNodePath: SequenceNodePath;
5
+ effectIndex: number;
6
+ prettierConfigOverride?: Record<string, unknown> | null | undefined;
7
+ }) => Promise<{
8
+ output: string;
9
+ formatted: boolean;
10
+ effectLabel: string;
11
+ logLine: number;
12
+ }>;
@@ -0,0 +1,54 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.deleteEffect = void 0;
4
+ const can_update_sequence_props_1 = require("../preview-server/routes/can-update-sequence-props");
5
+ const format_file_content_1 = require("./format-file-content");
6
+ const parse_ast_1 = require("./parse-ast");
7
+ const update_effect_props_1 = require("./update-effect-props/update-effect-props");
8
+ const getEffectsArray = (attr) => {
9
+ if (!attr.value || attr.value.type !== 'JSXExpressionContainer') {
10
+ throw new Error('Cannot delete effect: effects prop is not an array');
11
+ }
12
+ const expr = attr.value.expression;
13
+ if (expr.type !== 'ArrayExpression') {
14
+ throw new Error('Cannot delete effect: effects prop is not an array');
15
+ }
16
+ return expr;
17
+ };
18
+ const deleteEffect = async ({ input, sequenceNodePath, effectIndex, prettierConfigOverride, }) => {
19
+ var _a, _b;
20
+ var _c, _d, _e;
21
+ const ast = (0, parse_ast_1.parseAst)(input);
22
+ const jsx = (0, can_update_sequence_props_1.findJsxElementAtNodePath)(ast, sequenceNodePath);
23
+ if (!jsx) {
24
+ throw new Error('Could not find a JSX element at the specified location to delete effect');
25
+ }
26
+ const attr = (0, update_effect_props_1.findEffectsAttr)((_c = jsx.attributes) !== null && _c !== void 0 ? _c : []);
27
+ if (!attr) {
28
+ throw new Error('Could not find effects on the target JSX element');
29
+ }
30
+ const effectsArray = getEffectsArray(attr);
31
+ const found = (0, update_effect_props_1.findEffectCallExpression)({ attr, effectIndex });
32
+ if (found.kind === 'error') {
33
+ throw new Error(`Cannot delete effect: ${found.reason}`);
34
+ }
35
+ effectsArray.elements.splice(effectIndex, 1);
36
+ if (effectsArray.elements.length === 0) {
37
+ const attrIndex = jsx.attributes.indexOf(attr);
38
+ if (attrIndex !== -1) {
39
+ jsx.attributes.splice(attrIndex, 1);
40
+ }
41
+ }
42
+ const finalFile = (0, parse_ast_1.serializeAst)(ast);
43
+ const { output, formatted } = await (0, format_file_content_1.formatFileContent)({
44
+ input: finalFile,
45
+ prettierConfigOverride,
46
+ });
47
+ return {
48
+ output,
49
+ formatted,
50
+ effectLabel: `${found.callee}()`,
51
+ logLine: (_e = (_d = (_a = found.call.loc) === null || _a === void 0 ? void 0 : _a.start.line) !== null && _d !== void 0 ? _d : (_b = jsx.loc) === null || _b === void 0 ? void 0 : _b.start.line) !== null && _e !== void 0 ? _e : 1,
52
+ };
53
+ };
54
+ exports.deleteEffect = deleteEffect;
@@ -69,7 +69,7 @@ const parseAndApplyCodemod = ({ input, codeMod, }) => {
69
69
  codeMod,
70
70
  });
71
71
  if (changesMade.length === 0) {
72
- throw new Error('Unable to calculate the changes needed for this file. Edit the root file manually.');
72
+ throw new Error('Unable to calculate the changes needed for this file. Edit the file manually.');
73
73
  }
74
74
  const output = (0, parse_ast_1.serializeAst)(newAst);
75
75
  return { changesMade, newContents: output };
@@ -60,11 +60,65 @@ const mapReturnStatement = (statement, transformation, changesMade) => {
60
60
  if (!statement.argument) {
61
61
  return statement;
62
62
  }
63
+ const replacement = transformLoneJsxElement(statement.argument, transformation, changesMade);
64
+ if (replacement !== null) {
65
+ return { ...statement, argument: replacement };
66
+ }
63
67
  return {
64
68
  ...statement,
65
69
  argument: mapAll(statement.argument, transformation, changesMade),
66
70
  };
67
71
  };
72
+ const nullLiteral = () => ({ type: 'NullLiteral' });
73
+ // When a node was originally parenthesized (e.g. the `<JSX/>` inside
74
+ // `return (<JSX/>)`), Babel records `extra.parenthesized` on it. If we move
75
+ // such a node into a JSXFragment without clearing that hint, recast prints
76
+ // stray `(` / `)` characters around it as JSX text. Clear the hint so the
77
+ // node prints cleanly in its new context.
78
+ const stripParenthesizedExtra = (node) => {
79
+ if (!node.extra) {
80
+ return node;
81
+ }
82
+ const { parenthesized: _p, parenStart: _ps, ...rest } = node.extra;
83
+ return { ...node, extra: rest };
84
+ };
85
+ const wrapInJsxFragment = (children) => ({
86
+ type: 'JSXFragment',
87
+ openingFragment: { type: 'JSXOpeningFragment' },
88
+ closingFragment: { type: 'JSXClosingFragment' },
89
+ children: children.map(stripParenthesizedExtra),
90
+ });
91
+ // When a <Composition> JSX element appears in a position where it cannot
92
+ // simply be removed from a parent's children list (e.g. as the sole return
93
+ // value of a wrapper component or as the concise body of an arrow function),
94
+ // we still want delete/rename/duplicate codemods to work. This helper detects
95
+ // that case and produces a structurally-valid replacement expression.
96
+ const transformLoneJsxElement = (expression, transformation, changesMade) => {
97
+ if (expression.type !== 'JSXElement') {
98
+ return null;
99
+ }
100
+ const compId = getCompositionIdFromJSXElement(expression);
101
+ if (compId === null) {
102
+ return null;
103
+ }
104
+ const isMatch = (transformation.type === 'delete-composition' &&
105
+ compId === transformation.idToDelete) ||
106
+ (transformation.type === 'rename-composition' &&
107
+ compId === transformation.idToRename) ||
108
+ (transformation.type === 'duplicate-composition' &&
109
+ compId === transformation.idToDuplicate);
110
+ if (!isMatch) {
111
+ return null;
112
+ }
113
+ const transformed = mapJsxChild(expression, transformation, changesMade);
114
+ if (transformed.length === 0) {
115
+ return nullLiteral();
116
+ }
117
+ if (transformed.length === 1) {
118
+ return transformed[0];
119
+ }
120
+ return wrapInJsxFragment(transformed);
121
+ };
68
122
  const mapJsxElementOrFragment = (jsxFragment, transformation, changesMade) => {
69
123
  return {
70
124
  ...jsxFragment,
@@ -129,6 +183,16 @@ const mapRecognizedType = (expression, transformation, changesMade) => {
129
183
  }
130
184
  if (expression.type === 'ArrowFunctionExpression' ||
131
185
  expression.type === 'FunctionExpression') {
186
+ if (expression.type === 'ArrowFunctionExpression' &&
187
+ expression.body.type === 'JSXElement') {
188
+ const replacement = transformLoneJsxElement(expression.body, transformation, changesMade);
189
+ if (replacement !== null) {
190
+ return {
191
+ ...expression,
192
+ body: replacement,
193
+ };
194
+ }
195
+ }
132
196
  return {
133
197
  ...expression,
134
198
  body: mapAll(expression.body, transformation, changesMade),
@@ -12,6 +12,7 @@ export type UpdateEffectPropsResult = {
12
12
  logLine: number;
13
13
  effectCallee: string;
14
14
  };
15
+ export declare const findEffectsAttr: (attrs: readonly unknown[]) => JSXAttribute | null;
15
16
  export type EffectArrayElement = {
16
17
  kind: 'call';
17
18
  callee: 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.updateEffectProps = exports.updateEffectPropsAst = exports.findEffectCallExpression = exports.enumerateEffectArrayElements = void 0;
36
+ exports.updateEffectProps = exports.updateEffectPropsAst = exports.findEffectCallExpression = exports.enumerateEffectArrayElements = exports.findEffectsAttr = void 0;
37
37
  const studio_shared_1 = require("@remotion/studio-shared");
38
38
  const recast = __importStar(require("recast"));
39
39
  const can_update_sequence_props_1 = require("../../preview-server/routes/can-update-sequence-props");
@@ -50,19 +50,19 @@ const parseValueExpression = (value) => {
50
50
  }
51
51
  return stmt.expression.right;
52
52
  };
53
- const findExperimentalEffectsAttr = (attrs) => {
53
+ const findEffectsAttr = (attrs) => {
54
54
  for (const attr of attrs) {
55
55
  if (attr.type !== 'JSXAttribute') {
56
56
  continue;
57
57
  }
58
58
  const a = attr;
59
- if (a.name.type === 'JSXIdentifier' &&
60
- a.name.name === '_experimentalEffects') {
59
+ if (a.name.type === 'JSXIdentifier' && a.name.name === 'effects') {
61
60
  return a;
62
61
  }
63
62
  }
64
63
  return null;
65
64
  };
65
+ exports.findEffectsAttr = findEffectsAttr;
66
66
  const getCalleeName = (call) => {
67
67
  const { callee } = call;
68
68
  if (callee.type === 'Identifier') {
@@ -140,9 +140,9 @@ const updateEffectPropsAst = ({ input, sequenceNodePath, effectIndex, update, })
140
140
  if (!jsx) {
141
141
  throw new Error('Could not find a JSX element at the specified location to update effects');
142
142
  }
143
- const attr = findExperimentalEffectsAttr((_e = jsx.attributes) !== null && _e !== void 0 ? _e : []);
143
+ const attr = (0, exports.findEffectsAttr)((_e = jsx.attributes) !== null && _e !== void 0 ? _e : []);
144
144
  if (!attr) {
145
- throw new Error('Could not find _experimentalEffects on the target JSX element');
145
+ throw new Error('Could not find effects on the target JSX element');
146
146
  }
147
147
  const found = (0, exports.findEffectCallExpression)({
148
148
  attr,
package/dist/index.d.ts CHANGED
@@ -80,6 +80,10 @@ export declare const StudioServerInternals: {
80
80
  newContents: string;
81
81
  changesMade: import("./codemods/recast-mods").Change[];
82
82
  };
83
+ applyCodemodToFile: ({ filePath, codeMod, }: {
84
+ filePath: string;
85
+ codeMod: import("@remotion/studio-shared").RecastCodemod;
86
+ }) => Promise<string>;
83
87
  formatOutput: (tsContent: string) => Promise<string>;
84
88
  updateDefaultProps: ({ input, compositionId, newDefaultProps, enumPaths, }: {
85
89
  input: string;
package/dist/index.js CHANGED
@@ -6,6 +6,7 @@ const studio_shared_2 = require("@remotion/studio-shared");
6
6
  Object.defineProperty(exports, "getDefaultOutLocation", { enumerable: true, get: function () { return studio_shared_2.getDefaultOutLocation; } });
7
7
  const ansi_diff_1 = require("./ansi-diff");
8
8
  const client_render_queue_1 = require("./client-render-queue");
9
+ const apply_codemod_to_file_1 = require("./codemods/apply-codemod-to-file");
9
10
  const duplicate_composition_1 = require("./codemods/duplicate-composition");
10
11
  const update_default_props_1 = require("./codemods/update-default-props");
11
12
  const file_watcher_1 = require("./file-watcher");
@@ -33,6 +34,7 @@ exports.StudioServerInternals = {
33
34
  AnsiDiff: ansi_diff_1.AnsiDiff,
34
35
  formatBytes: studio_shared_1.formatBytes,
35
36
  parseAndApplyCodemod: duplicate_composition_1.parseAndApplyCodemod,
37
+ applyCodemodToFile: apply_codemod_to_file_1.applyCodemodToFile,
36
38
  formatOutput: duplicate_composition_1.formatOutput,
37
39
  updateDefaultProps: update_default_props_1.updateDefaultProps,
38
40
  getInstalledDependencies: get_installed_dependencies_1.getInstalledDependencies,
@@ -5,6 +5,7 @@ const add_render_1 = require("./routes/add-render");
5
5
  const apply_codemod_1 = require("./routes/apply-codemod");
6
6
  const apply_visual_control_change_1 = require("./routes/apply-visual-control-change");
7
7
  const cancel_render_1 = require("./routes/cancel-render");
8
+ const delete_effect_1 = require("./routes/delete-effect");
8
9
  const delete_jsx_node_1 = require("./routes/delete-jsx-node");
9
10
  const delete_static_file_1 = require("./routes/delete-static-file");
10
11
  const duplicate_jsx_node_1 = require("./routes/duplicate-jsx-node");
@@ -41,6 +42,7 @@ exports.allApiRoutes = {
41
42
  '/api/unsubscribe-from-sequence-props': unsubscribe_from_sequence_props_1.unsubscribeFromSequenceProps,
42
43
  '/api/save-sequence-props': save_sequence_props_1.saveSequencePropsHandler,
43
44
  '/api/save-effect-props': save_effect_props_1.saveEffectPropsHandler,
45
+ '/api/delete-effect': delete_effect_1.deleteEffectHandler,
44
46
  '/api/delete-jsx-node': delete_jsx_node_1.deleteJsxNodeHandler,
45
47
  '/api/duplicate-jsx-node': duplicate_jsx_node_1.duplicateJsxNodeHandler,
46
48
  '/api/update-available': update_available_1.handleUpdate,
@@ -7,7 +7,7 @@ exports.setupOutputFileSystem = setupOutputFileSystem;
7
7
  const memfs_1 = __importDefault(require("memfs"));
8
8
  function setupOutputFileSystem(context) {
9
9
  const outputFileSystem = memfs_1.default.createFsFromVolume(new memfs_1.default.Volume());
10
- // @ts-expect-error output file sytem
11
- context.compiler.outputFileSystem = outputFileSystem;
10
+ context.compiler.outputFileSystem =
11
+ outputFileSystem;
12
12
  context.outputFileSystem = outputFileSystem;
13
13
  }
@@ -1,35 +1,89 @@
1
1
  "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
2
5
  Object.defineProperty(exports, "__esModule", { value: true });
3
6
  exports.applyCodemodHandler = void 0;
4
7
  const node_fs_1 = require("node:fs");
8
+ const node_path_1 = __importDefault(require("node:path"));
5
9
  const renderer_1 = require("@remotion/renderer");
6
- const duplicate_composition_1 = require("../../codemods/duplicate-composition");
10
+ const apply_codemod_to_file_1 = require("../../codemods/apply-codemod-to-file");
7
11
  const simple_diff_1 = require("../../codemods/simple-diff");
8
12
  const file_watcher_1 = require("../../file-watcher");
9
13
  const project_info_1 = require("../project-info");
14
+ const undo_stack_1 = require("../undo-stack");
10
15
  const can_update_default_props_1 = require("./can-update-default-props");
11
- const applyCodemodHandler = async ({ input: { codemod, dryRun }, logLevel, remotionRoot, entryPoint }) => {
16
+ const getCodemodUndoDescription = (codemod) => {
17
+ if (codemod.type === 'delete-composition') {
18
+ return {
19
+ undoMessage: `↩️ Deletion of composition "${codemod.idToDelete}"`,
20
+ redoMessage: `↪️ Deletion of composition "${codemod.idToDelete}"`,
21
+ entryType: codemod.type,
22
+ };
23
+ }
24
+ if (codemod.type === 'rename-composition') {
25
+ const label = `composition "${codemod.idToRename}" to "${codemod.newId}"`;
26
+ return {
27
+ undoMessage: `↩️ Rename of ${label}`,
28
+ redoMessage: `↪️ Rename of ${label}`,
29
+ entryType: codemod.type,
30
+ };
31
+ }
32
+ if (codemod.type === 'duplicate-composition') {
33
+ const label = `composition "${codemod.idToDuplicate}" to "${codemod.newId}"`;
34
+ return {
35
+ undoMessage: `↩️ Duplication of ${label}`,
36
+ redoMessage: `↪️ Duplication of ${label}`,
37
+ entryType: codemod.type,
38
+ };
39
+ }
40
+ return {
41
+ undoMessage: '↩️ Visual control change',
42
+ redoMessage: '↪️ Visual control change',
43
+ entryType: 'visual-control',
44
+ };
45
+ };
46
+ const applyCodemodHandler = async ({ input: { codemod, dryRun, symbolicatedStack }, logLevel, remotionRoot, entryPoint, }) => {
47
+ var _a;
12
48
  try {
13
49
  const time = Date.now();
14
- const projectInfo = await (0, project_info_1.getProjectInfo)(remotionRoot, entryPoint);
15
- if (!projectInfo.rootFile) {
16
- throw new Error('Cannot find root file in project');
50
+ const filePath = symbolicatedStack
51
+ ? (0, apply_codemod_to_file_1.resolveFilePathFromSymbolicatedStack)(remotionRoot, symbolicatedStack)
52
+ : (await (0, project_info_1.getProjectInfo)(remotionRoot, entryPoint)).rootFile;
53
+ if (!filePath) {
54
+ throw new Error('Cannot find file for composition in project');
17
55
  }
18
- (0, can_update_default_props_1.checkIfTypeScriptFile)(projectInfo.rootFile);
19
- const input = (0, node_fs_1.readFileSync)(projectInfo.rootFile, 'utf-8');
20
- const { newContents } = (0, duplicate_composition_1.parseAndApplyCodemod)({
56
+ (0, can_update_default_props_1.checkIfTypeScriptFile)(filePath);
57
+ const input = (0, node_fs_1.readFileSync)(filePath, 'utf-8');
58
+ const formatted = await (0, apply_codemod_to_file_1.applyCodemodToFile)({
59
+ filePath,
21
60
  codeMod: codemod,
22
- input,
23
61
  });
24
- const formatted = await (0, duplicate_composition_1.formatOutput)(newContents);
25
62
  const diff = (0, simple_diff_1.simpleDiff)({
26
63
  oldLines: input.split('\n'),
27
64
  newLines: formatted.split('\n'),
28
65
  });
29
66
  if (!dryRun) {
30
- (0, file_watcher_1.writeFileAndNotifyFileWatchers)(projectInfo.rootFile, formatted, undefined);
67
+ const { entryType, undoMessage, redoMessage } = getCodemodUndoDescription(codemod);
68
+ (0, undo_stack_1.pushToUndoStack)({
69
+ filePath,
70
+ oldContents: input,
71
+ logLevel,
72
+ remotionRoot,
73
+ logLine: (_a = symbolicatedStack === null || symbolicatedStack === void 0 ? void 0 : symbolicatedStack.originalLineNumber) !== null && _a !== void 0 ? _a : 1,
74
+ description: {
75
+ undoMessage,
76
+ redoMessage,
77
+ },
78
+ entryType,
79
+ suppressHmrOnFileRestore: false,
80
+ });
81
+ (0, undo_stack_1.suppressUndoStackInvalidation)(filePath);
82
+ (0, file_watcher_1.writeFileAndNotifyFileWatchers)(filePath, formatted, undefined);
31
83
  const end = Date.now() - time;
32
- renderer_1.RenderInternals.Log.info({ indent: false, logLevel }, renderer_1.RenderInternals.chalk.blue(`Edited root file in ${end}ms`));
84
+ const relativePath = node_path_1.default.relative(remotionRoot, filePath);
85
+ renderer_1.RenderInternals.Log.info({ indent: false, logLevel }, renderer_1.RenderInternals.chalk.blue(`Edited ${relativePath} in ${end}ms`));
86
+ (0, undo_stack_1.printUndoHint)(logLevel);
33
87
  }
34
88
  return {
35
89
  success: true,
@@ -9,13 +9,12 @@ const node_path_1 = __importDefault(require("node:path"));
9
9
  const parse_ast_1 = require("../../codemods/parse-ast");
10
10
  const update_effect_props_1 = require("../../codemods/update-effect-props/update-effect-props");
11
11
  const can_update_sequence_props_1 = require("./can-update-sequence-props");
12
- const findExperimentalEffectsAttr = (jsx) => {
12
+ const findEffectsAttr = (jsx) => {
13
13
  for (const attr of jsx.attributes) {
14
14
  if (attr.type !== 'JSXAttribute') {
15
15
  continue;
16
16
  }
17
- if (attr.name.type === 'JSXIdentifier' &&
18
- attr.name.name === '_experimentalEffects') {
17
+ if (attr.name.type === 'JSXIdentifier' && attr.name.name === 'effects') {
19
18
  return attr;
20
19
  }
21
20
  }
@@ -55,7 +54,7 @@ const getPropsFromObjectExpression = ({ objExpr, keys, }) => {
55
54
  return out;
56
55
  };
57
56
  const computeEffectPropStatus = ({ jsx, effectIndex, keys, }) => {
58
- const attr = findExperimentalEffectsAttr(jsx);
57
+ const attr = findEffectsAttr(jsx);
59
58
  const elements = getEffectsArrayElements(attr);
60
59
  if (!elements) {
61
60
  return {
@@ -0,0 +1,3 @@
1
+ import type { DeleteEffectRequest, DeleteEffectResponse } from '@remotion/studio-shared';
2
+ import type { ApiHandler } from '../api-types';
3
+ export declare const deleteEffectHandler: ApiHandler<DeleteEffectRequest, DeleteEffectResponse>;
@@ -0,0 +1,68 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.deleteEffectHandler = void 0;
7
+ const node_fs_1 = require("node:fs");
8
+ const node_path_1 = __importDefault(require("node:path"));
9
+ const renderer_1 = require("@remotion/renderer");
10
+ const delete_effect_1 = require("../../codemods/delete-effect");
11
+ const file_watcher_1 = require("../../file-watcher");
12
+ const format_log_file_location_1 = require("../format-log-file-location");
13
+ const undo_stack_1 = require("../undo-stack");
14
+ const formatting_1 = require("./log-updates/formatting");
15
+ const log_update_1 = require("./log-updates/log-update");
16
+ const deleteEffectHandler = async ({ input: { fileName, sequenceNodePath, effectIndex }, remotionRoot, logLevel, }) => {
17
+ try {
18
+ renderer_1.RenderInternals.Log.trace({ indent: false, logLevel }, `[delete-effect] Received request for fileName="${fileName}" effectIndex=${effectIndex}`);
19
+ const absolutePath = node_path_1.default.resolve(remotionRoot, fileName);
20
+ const fileRelativeToRoot = node_path_1.default.relative(remotionRoot, absolutePath);
21
+ if (fileRelativeToRoot.startsWith('..')) {
22
+ throw new Error('Cannot modify a file outside the project');
23
+ }
24
+ const fileContents = (0, node_fs_1.readFileSync)(absolutePath, 'utf-8');
25
+ const { output, formatted, effectLabel, logLine } = await (0, delete_effect_1.deleteEffect)({
26
+ input: fileContents,
27
+ sequenceNodePath: sequenceNodePath.nodePath,
28
+ effectIndex,
29
+ });
30
+ (0, undo_stack_1.pushToUndoStack)({
31
+ filePath: absolutePath,
32
+ oldContents: fileContents,
33
+ logLevel,
34
+ remotionRoot,
35
+ logLine,
36
+ description: {
37
+ undoMessage: `↩️ Deletion of ${effectLabel}`,
38
+ redoMessage: `↪️ Deletion of ${effectLabel}`,
39
+ },
40
+ entryType: 'delete-effect',
41
+ suppressHmrOnFileRestore: false,
42
+ });
43
+ (0, undo_stack_1.suppressUndoStackInvalidation)(absolutePath);
44
+ (0, file_watcher_1.writeFileAndNotifyFileWatchers)(absolutePath, output, undefined);
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}`)} ${(0, formatting_1.strikeThroughOrRemovedPrefix)(effectLabel)}`);
51
+ if (!formatted) {
52
+ (0, log_update_1.warnAboutPrettierOnce)(logLevel);
53
+ }
54
+ renderer_1.RenderInternals.Log.verbose({ indent: false, logLevel }, `[delete-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.deleteEffectHandler = deleteEffectHandler;
@@ -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' | 'delete-jsx-node' | 'duplicate-jsx-node';
6
+ type UndoEntryType = 'visual-control' | 'default-props' | 'sequence-props' | 'effect-props' | 'delete-effect' | 'delete-jsx-node' | 'duplicate-jsx-node' | 'delete-composition' | 'rename-composition' | 'duplicate-composition';
7
7
  type UndoEntry = {
8
8
  filePath: string;
9
9
  oldContents: string;
@@ -20,10 +20,18 @@ type UndoEntry = {
20
20
  entryType: 'sequence-props';
21
21
  } | {
22
22
  entryType: 'effect-props';
23
+ } | {
24
+ entryType: 'delete-effect';
23
25
  } | {
24
26
  entryType: 'delete-jsx-node';
25
27
  } | {
26
28
  entryType: 'duplicate-jsx-node';
29
+ } | {
30
+ entryType: 'delete-composition';
31
+ } | {
32
+ entryType: 'rename-composition';
33
+ } | {
34
+ entryType: 'duplicate-composition';
27
35
  });
28
36
  export declare function pushToUndoStack({ filePath, oldContents, logLevel, remotionRoot, logLine, description, entryType, suppressHmrOnFileRestore }: {
29
37
  filePath: string;
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.464",
6
+ "version": "4.0.465",
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.464",
30
+ "remotion": "4.0.465",
31
31
  "recast": "0.23.11",
32
- "@remotion/bundler": "4.0.464",
33
- "@remotion/renderer": "4.0.464",
34
- "@remotion/studio-shared": "4.0.464",
32
+ "@remotion/bundler": "4.0.465",
33
+ "@remotion/renderer": "4.0.465",
34
+ "@remotion/studio-shared": "4.0.465",
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.464",
42
+ "@remotion/eslint-config-internal": "4.0.465",
43
43
  "eslint": "9.19.0",
44
44
  "@types/node": "20.12.14",
45
45
  "@typescript/native-preview": "7.0.0-dev.20260217.1"