@remotion/studio-server 4.0.464 → 4.0.466

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,
@@ -0,0 +1,11 @@
1
+ export type ResolvedCompositionComponent = {
2
+ source: string;
3
+ line: number;
4
+ column: number;
5
+ canAddSequence: boolean;
6
+ };
7
+ export declare const resolveCompositionComponent: ({ remotionRoot, compositionFile, compositionId, }: {
8
+ remotionRoot: string;
9
+ compositionFile: string;
10
+ compositionId: string;
11
+ }) => Promise<ResolvedCompositionComponent>;