@remotion/studio-server 4.0.467 → 4.0.468

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.
@@ -1,22 +1,19 @@
1
1
  "use strict";
2
- var __importDefault = (this && this.__importDefault) || function (mod) {
3
- return (mod && mod.__esModule) ? mod : { "default": mod };
4
- };
5
2
  Object.defineProperty(exports, "__esModule", { value: true });
6
3
  exports.applyCodemodToFile = exports.resolveFilePathFromSymbolicatedStack = void 0;
7
4
  const node_fs_1 = require("node:fs");
8
- const node_path_1 = __importDefault(require("node:path"));
5
+ const resolve_file_inside_project_1 = require("../helpers/resolve-file-inside-project");
9
6
  const can_update_default_props_1 = require("../preview-server/routes/can-update-default-props");
10
7
  const duplicate_composition_1 = require("./duplicate-composition");
11
8
  const resolveFilePathFromSymbolicatedStack = (remotionRoot, stack) => {
12
9
  if (!stack.originalFileName) {
13
10
  throw new Error('Could not determine the file where this composition is defined');
14
11
  }
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
- }
12
+ const { absolutePath } = (0, resolve_file_inside_project_1.resolveFileInsideProject)({
13
+ remotionRoot,
14
+ fileName: stack.originalFileName,
15
+ action: 'apply codemod to',
16
+ });
20
17
  if (!(0, node_fs_1.existsSync)(absolutePath)) {
21
18
  throw new Error(`File not found: ${stack.originalFileName}`);
22
19
  }
@@ -0,0 +1,61 @@
1
+ import type { SequenceNodePath } from 'remotion';
2
+ export type KeyframeOperation = {
3
+ type: 'add';
4
+ frame: number;
5
+ value: unknown;
6
+ } | {
7
+ type: 'remove';
8
+ frame: number;
9
+ };
10
+ export type SequenceKeyframeUpdate = {
11
+ key: string;
12
+ operation: KeyframeOperation;
13
+ };
14
+ export type EffectKeyframeUpdate = {
15
+ key: string;
16
+ operation: KeyframeOperation;
17
+ };
18
+ export declare const updateSequenceKeyframesAst: ({ input, nodePath, updates, }: {
19
+ input: string;
20
+ nodePath: SequenceNodePath;
21
+ updates: SequenceKeyframeUpdate[];
22
+ }) => {
23
+ serialized: string;
24
+ oldValueStrings: string[];
25
+ logLine: number;
26
+ };
27
+ export declare const updateSequenceKeyframes: ({ input, nodePath, updates, prettierConfigOverride, }: {
28
+ input: string;
29
+ nodePath: SequenceNodePath;
30
+ updates: SequenceKeyframeUpdate[];
31
+ prettierConfigOverride?: Record<string, unknown> | null | undefined;
32
+ }) => Promise<{
33
+ output: string;
34
+ formatted: boolean;
35
+ oldValueStrings: string[];
36
+ logLine: number;
37
+ }>;
38
+ export declare const updateEffectKeyframesAst: ({ input, sequenceNodePath, effectIndex, updates, }: {
39
+ input: string;
40
+ sequenceNodePath: SequenceNodePath;
41
+ effectIndex: number;
42
+ updates: EffectKeyframeUpdate[];
43
+ }) => {
44
+ serialized: string;
45
+ oldValueStrings: string[];
46
+ logLine: number;
47
+ effectCallee: string;
48
+ };
49
+ export declare const updateEffectKeyframes: ({ input, sequenceNodePath, effectIndex, updates, prettierConfigOverride, }: {
50
+ input: string;
51
+ sequenceNodePath: SequenceNodePath;
52
+ effectIndex: number;
53
+ updates: EffectKeyframeUpdate[];
54
+ prettierConfigOverride?: Record<string, unknown> | null | undefined;
55
+ }) => Promise<{
56
+ output: string;
57
+ formatted: boolean;
58
+ oldValueStrings: string[];
59
+ logLine: number;
60
+ effectCallee: string;
61
+ }>;
@@ -0,0 +1,401 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || (function () {
19
+ var ownKeys = function(o) {
20
+ ownKeys = Object.getOwnPropertyNames || function (o) {
21
+ var ar = [];
22
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
23
+ return ar;
24
+ };
25
+ return ownKeys(o);
26
+ };
27
+ return function (mod) {
28
+ if (mod && mod.__esModule) return mod;
29
+ var result = {};
30
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
31
+ __setModuleDefault(result, mod);
32
+ return result;
33
+ };
34
+ })();
35
+ Object.defineProperty(exports, "__esModule", { value: true });
36
+ exports.updateEffectKeyframes = exports.updateEffectKeyframesAst = exports.updateSequenceKeyframes = exports.updateSequenceKeyframesAst = void 0;
37
+ const recast = __importStar(require("recast"));
38
+ const can_update_sequence_props_1 = require("../../preview-server/routes/can-update-sequence-props");
39
+ const format_file_content_1 = require("../format-file-content");
40
+ const parse_ast_1 = require("../parse-ast");
41
+ const update_effect_props_1 = require("../update-effect-props/update-effect-props");
42
+ const update_nested_prop_1 = require("../update-nested-prop");
43
+ const b = recast.types.builders;
44
+ const getSupportedCallArgument = (arg) => {
45
+ if (arg === undefined ||
46
+ arg.type === 'ArgumentPlaceholder' ||
47
+ arg.type === 'JSXNamespacedName') {
48
+ return null;
49
+ }
50
+ return arg;
51
+ };
52
+ const getNumericValue = (node) => {
53
+ if (node.type === 'NumericLiteral') {
54
+ return node.value;
55
+ }
56
+ if (node.type === 'UnaryExpression' &&
57
+ (node.operator === '-' || node.operator === '+') &&
58
+ node.argument.type === 'NumericLiteral') {
59
+ return node.operator === '-' ? -node.argument.value : node.argument.value;
60
+ }
61
+ if (node.type === 'TSAsExpression') {
62
+ return getNumericValue(node.expression);
63
+ }
64
+ return null;
65
+ };
66
+ const getInterpolationExpression = (node) => {
67
+ if (node.type === 'TSAsExpression') {
68
+ return getInterpolationExpression(node.expression);
69
+ }
70
+ if (node.type !== 'CallExpression' ||
71
+ node.callee.type !== 'Identifier' ||
72
+ (node.callee.name !== 'interpolate' &&
73
+ node.callee.name !== 'interpolateColors')) {
74
+ return null;
75
+ }
76
+ const frameArg = getSupportedCallArgument(node.arguments[0]);
77
+ const inputArg = node.arguments[1];
78
+ const outputArg = node.arguments[2];
79
+ if (!frameArg ||
80
+ !inputArg ||
81
+ !outputArg ||
82
+ inputArg.type !== 'ArrayExpression' ||
83
+ outputArg.type !== 'ArrayExpression' ||
84
+ inputArg.elements.length !== outputArg.elements.length) {
85
+ return null;
86
+ }
87
+ const keyframes = [];
88
+ for (let i = 0; i < inputArg.elements.length; i++) {
89
+ const inputElement = inputArg.elements[i];
90
+ const outputElement = outputArg.elements[i];
91
+ if (!inputElement ||
92
+ !outputElement ||
93
+ inputElement.type === 'SpreadElement' ||
94
+ outputElement.type === 'SpreadElement') {
95
+ return null;
96
+ }
97
+ const frame = getNumericValue(inputElement);
98
+ if (frame === null || !(0, can_update_sequence_props_1.isStaticValue)(outputElement)) {
99
+ return null;
100
+ }
101
+ keyframes.push({
102
+ frame,
103
+ output: outputElement,
104
+ value: (0, can_update_sequence_props_1.extractStaticValue)(outputElement),
105
+ });
106
+ }
107
+ if (keyframes.length === 0) {
108
+ return null;
109
+ }
110
+ const extraArgs = [];
111
+ for (const arg of node.arguments.slice(3)) {
112
+ const supportedArg = getSupportedCallArgument(arg);
113
+ if (!supportedArg) {
114
+ return null;
115
+ }
116
+ extraArgs.push(supportedArg);
117
+ }
118
+ return {
119
+ callee: node.callee,
120
+ input: frameArg,
121
+ extraArgs,
122
+ keyframes,
123
+ };
124
+ };
125
+ const getInterpolationCalleeForValues = ({ staticValue, newValue, }) => {
126
+ return b.identifier(typeof staticValue === 'string' && typeof newValue === 'string'
127
+ ? 'interpolateColors'
128
+ : 'interpolate');
129
+ };
130
+ const createFrameExpression = (frame) => {
131
+ return (0, update_nested_prop_1.parseValueExpression)(frame);
132
+ };
133
+ const createInterpolateExpression = ({ callee, input, extraArgs, keyframes, }) => {
134
+ const sortedKeyframes = [...keyframes].sort((first, second) => first.frame - second.frame);
135
+ return b.callExpression(callee, [
136
+ input,
137
+ b.arrayExpression(sortedKeyframes.map((keyframe) => createFrameExpression(keyframe.frame))),
138
+ b.arrayExpression(sortedKeyframes.map((keyframe) => keyframe.output)),
139
+ ...extraArgs,
140
+ ]);
141
+ };
142
+ const addKeyframe = ({ expression, frame, value, }) => {
143
+ const existing = getInterpolationExpression(expression);
144
+ const newOutput = (0, update_nested_prop_1.parseValueExpression)(value);
145
+ if (existing) {
146
+ const existingIndex = existing.keyframes.findIndex((keyframe) => keyframe.frame === frame);
147
+ const nextKeyframes = existingIndex === -1
148
+ ? [...existing.keyframes, { frame, output: newOutput, value }]
149
+ : existing.keyframes.map((keyframe, index) => index === existingIndex
150
+ ? { frame, output: newOutput, value }
151
+ : keyframe);
152
+ return createInterpolateExpression({
153
+ callee: existing.callee,
154
+ input: existing.input,
155
+ extraArgs: existing.extraArgs,
156
+ keyframes: nextKeyframes,
157
+ });
158
+ }
159
+ if (!(0, can_update_sequence_props_1.isStaticValue)(expression)) {
160
+ throw new Error('Cannot add keyframe to computed expression');
161
+ }
162
+ if (frame === 0) {
163
+ throw new Error('Cannot add keyframe to static expression at frame 0 because interpolate requires two distinct frames');
164
+ }
165
+ const staticValue = (0, can_update_sequence_props_1.extractStaticValue)(expression);
166
+ const staticOutput = (0, update_nested_prop_1.parseValueExpression)(staticValue);
167
+ return createInterpolateExpression({
168
+ callee: getInterpolationCalleeForValues({
169
+ staticValue,
170
+ newValue: value,
171
+ }),
172
+ input: b.identifier('frame'),
173
+ extraArgs: [],
174
+ keyframes: [
175
+ { frame: 0, output: staticOutput, value: staticValue },
176
+ { frame, output: newOutput, value },
177
+ ],
178
+ });
179
+ };
180
+ const removeKeyframe = ({ expression, frame, }) => {
181
+ const existing = getInterpolationExpression(expression);
182
+ if (!existing) {
183
+ throw new Error('Cannot remove keyframe from non-interpolated expression');
184
+ }
185
+ const keyframeIndex = existing.keyframes.findIndex((keyframe) => keyframe.frame === frame);
186
+ if (keyframeIndex === -1) {
187
+ throw new Error(`Cannot remove keyframe at frame ${frame}: not found`);
188
+ }
189
+ const nextKeyframes = existing.keyframes.filter((_keyframe, index) => index !== keyframeIndex);
190
+ if (nextKeyframes.length === 1) {
191
+ return (0, update_nested_prop_1.parseValueExpression)(nextKeyframes[0].value);
192
+ }
193
+ return createInterpolateExpression({
194
+ callee: existing.callee,
195
+ input: existing.input,
196
+ extraArgs: existing.extraArgs,
197
+ keyframes: nextKeyframes,
198
+ });
199
+ };
200
+ const applyKeyframeOperation = ({ expression, operation, }) => {
201
+ if (operation.type === 'add') {
202
+ return addKeyframe({
203
+ expression,
204
+ frame: operation.frame,
205
+ value: operation.value,
206
+ });
207
+ }
208
+ return removeKeyframe({ expression, frame: operation.frame });
209
+ };
210
+ const getExpressionFromJsxAttribute = (attr) => {
211
+ if (!attr.value) {
212
+ return b.booleanLiteral(true);
213
+ }
214
+ if (attr.value.type === 'StringLiteral') {
215
+ return attr.value;
216
+ }
217
+ if (attr.value.type !== 'JSXExpressionContainer') {
218
+ return null;
219
+ }
220
+ const { expression } = attr.value;
221
+ if (expression.type === 'JSXEmptyExpression') {
222
+ return null;
223
+ }
224
+ return expression;
225
+ };
226
+ const findJsxAttribute = (attributes, name) => {
227
+ const attrIndex = attributes.findIndex((candidate) => {
228
+ if (candidate.type === 'JSXSpreadAttribute') {
229
+ return false;
230
+ }
231
+ if (candidate.name.type === 'JSXNamespacedName') {
232
+ return false;
233
+ }
234
+ return candidate.name.name === name;
235
+ });
236
+ const foundAttr = attrIndex === -1 ? undefined : attributes[attrIndex];
237
+ return {
238
+ attrIndex,
239
+ attr: foundAttr && foundAttr.type === 'JSXAttribute'
240
+ ? foundAttr
241
+ : undefined,
242
+ };
243
+ };
244
+ const findObjectProperty = (objExpr, propertyName) => {
245
+ const propIndex = objExpr.properties.findIndex((prop) => prop.type === 'ObjectProperty' &&
246
+ ((prop.key.type === 'Identifier' && prop.key.name === propertyName) ||
247
+ (prop.key.type === 'StringLiteral' && prop.key.value === propertyName)));
248
+ return {
249
+ propIndex,
250
+ prop: propIndex === -1
251
+ ? undefined
252
+ : objExpr.properties[propIndex],
253
+ };
254
+ };
255
+ const getObjectExpression = (attr) => {
256
+ if (!attr.value || attr.value.type !== 'JSXExpressionContainer') {
257
+ return null;
258
+ }
259
+ if (attr.value.expression.type !== 'ObjectExpression') {
260
+ return null;
261
+ }
262
+ return attr.value.expression;
263
+ };
264
+ const getSequenceWritableProp = ({ attributes, key, }) => {
265
+ const dotIndex = key.indexOf('.');
266
+ if (dotIndex === -1) {
267
+ const { attr: topLevelAttr } = findJsxAttribute(attributes, key);
268
+ if (!topLevelAttr) {
269
+ throw new Error(`Cannot update keyframes: "${key}" is not set`);
270
+ }
271
+ const expression = getExpressionFromJsxAttribute(topLevelAttr);
272
+ if (!expression) {
273
+ throw new Error(`Cannot update keyframes: "${key}" is computed`);
274
+ }
275
+ return {
276
+ expression,
277
+ setExpression: (nextExpression) => {
278
+ topLevelAttr.value = b.jsxExpressionContainer(nextExpression);
279
+ },
280
+ };
281
+ }
282
+ const parentKey = key.slice(0, dotIndex);
283
+ const childKey = key.slice(dotIndex + 1);
284
+ const { attr: parentAttr } = findJsxAttribute(attributes, parentKey);
285
+ if (!parentAttr) {
286
+ throw new Error(`Cannot update keyframes: "${parentKey}" is not set`);
287
+ }
288
+ const objExpr = getObjectExpression(parentAttr);
289
+ if (!objExpr) {
290
+ throw new Error(`Cannot update keyframes: "${parentKey}" is computed`);
291
+ }
292
+ const { prop } = findObjectProperty(objExpr, childKey);
293
+ if (!prop) {
294
+ throw new Error(`Cannot update keyframes: "${key}" is not set`);
295
+ }
296
+ return {
297
+ expression: prop.value,
298
+ setExpression: (nextExpression) => {
299
+ prop.value = nextExpression;
300
+ },
301
+ };
302
+ };
303
+ const updateSequenceKeyframesAst = ({ input, nodePath, updates, }) => {
304
+ var _a;
305
+ var _b;
306
+ const ast = (0, parse_ast_1.parseAst)(input);
307
+ const node = (0, can_update_sequence_props_1.findJsxElementAtNodePath)(ast, nodePath);
308
+ if (!node) {
309
+ throw new Error('Could not find a JSX element at the specified location to update keyframes');
310
+ }
311
+ if (!node.attributes) {
312
+ node.attributes = [];
313
+ }
314
+ const oldValueStrings = [];
315
+ for (const update of updates) {
316
+ const prop = getSequenceWritableProp({
317
+ attributes: node.attributes,
318
+ key: update.key,
319
+ });
320
+ oldValueStrings.push(recast.print(prop.expression).code);
321
+ prop.setExpression(applyKeyframeOperation({
322
+ expression: prop.expression,
323
+ operation: update.operation,
324
+ }));
325
+ }
326
+ return {
327
+ serialized: (0, parse_ast_1.serializeAst)(ast),
328
+ oldValueStrings,
329
+ logLine: (_b = (_a = node.loc) === null || _a === void 0 ? void 0 : _a.start.line) !== null && _b !== void 0 ? _b : 1,
330
+ };
331
+ };
332
+ exports.updateSequenceKeyframesAst = updateSequenceKeyframesAst;
333
+ const updateSequenceKeyframes = async ({ input, nodePath, updates, prettierConfigOverride, }) => {
334
+ const { serialized, oldValueStrings, logLine } = (0, exports.updateSequenceKeyframesAst)({
335
+ input,
336
+ nodePath,
337
+ updates,
338
+ });
339
+ const { output, formatted } = await (0, format_file_content_1.formatFileContent)({
340
+ input: serialized,
341
+ prettierConfigOverride,
342
+ });
343
+ return { output, formatted, oldValueStrings, logLine };
344
+ };
345
+ exports.updateSequenceKeyframes = updateSequenceKeyframes;
346
+ const updateEffectKeyframesAst = ({ input, sequenceNodePath, effectIndex, updates, }) => {
347
+ var _a, _b;
348
+ var _c, _d, _e;
349
+ const ast = (0, parse_ast_1.parseAst)(input);
350
+ const jsx = (0, can_update_sequence_props_1.findJsxElementAtNodePath)(ast, sequenceNodePath);
351
+ if (!jsx) {
352
+ throw new Error('Could not find a JSX element at the specified location to update effect keyframes');
353
+ }
354
+ const attr = (0, update_effect_props_1.findEffectsAttr)((_c = jsx.attributes) !== null && _c !== void 0 ? _c : []);
355
+ if (!attr) {
356
+ throw new Error('Could not find effects on the target JSX element');
357
+ }
358
+ const found = (0, update_effect_props_1.findEffectCallExpression)({ attr, effectIndex });
359
+ if (found.kind === 'error') {
360
+ throw new Error(`Cannot update effect keyframe: ${found.reason}`);
361
+ }
362
+ const { call, callee: effectCallee } = found;
363
+ if (call.arguments.length === 0 ||
364
+ call.arguments[0].type !== 'ObjectExpression') {
365
+ throw new Error('Cannot update effect keyframe: computed');
366
+ }
367
+ const objExpr = call.arguments[0];
368
+ const oldValueStrings = [];
369
+ for (const update of updates) {
370
+ const { prop } = findObjectProperty(objExpr, update.key);
371
+ if (!prop) {
372
+ throw new Error(`Cannot update keyframes: "${update.key}" is not set`);
373
+ }
374
+ oldValueStrings.push(recast.print(prop.value).code);
375
+ prop.value = applyKeyframeOperation({
376
+ expression: prop.value,
377
+ operation: update.operation,
378
+ });
379
+ }
380
+ return {
381
+ serialized: (0, parse_ast_1.serializeAst)(ast),
382
+ oldValueStrings,
383
+ logLine: (_e = (_d = (_a = 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,
384
+ effectCallee,
385
+ };
386
+ };
387
+ exports.updateEffectKeyframesAst = updateEffectKeyframesAst;
388
+ const updateEffectKeyframes = async ({ input, sequenceNodePath, effectIndex, updates, prettierConfigOverride, }) => {
389
+ const { serialized, oldValueStrings, logLine, effectCallee } = (0, exports.updateEffectKeyframesAst)({
390
+ input,
391
+ sequenceNodePath,
392
+ effectIndex,
393
+ updates,
394
+ });
395
+ const { output, formatted } = await (0, format_file_content_1.formatFileContent)({
396
+ input: serialized,
397
+ prettierConfigOverride,
398
+ });
399
+ return { output, formatted, oldValueStrings, logLine, effectCallee };
400
+ };
401
+ exports.updateEffectKeyframes = updateEffectKeyframes;
@@ -0,0 +1,8 @@
1
+ export declare const resolveFileInsideProject: ({ remotionRoot, fileName, action, }: {
2
+ remotionRoot: string;
3
+ fileName: string;
4
+ action: string;
5
+ }) => {
6
+ absolutePath: string;
7
+ fileRelativeToRoot: string;
8
+ };
@@ -0,0 +1,25 @@
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.resolveFileInsideProject = void 0;
7
+ const node_path_1 = __importDefault(require("node:path"));
8
+ const formatOutsideProjectError = ({ action, fileName, absolutePath, remotionRoot, }) => `Cannot ${action} a file outside the project: "${fileName}" resolves to "${absolutePath}", but the project root is "${remotionRoot}".`;
9
+ const resolveFileInsideProject = ({ remotionRoot, fileName, action, }) => {
10
+ const resolvedRemotionRoot = node_path_1.default.resolve(remotionRoot);
11
+ const absolutePath = node_path_1.default.resolve(resolvedRemotionRoot, fileName);
12
+ const fileRelativeToRoot = node_path_1.default.relative(resolvedRemotionRoot, absolutePath);
13
+ if (fileRelativeToRoot === '..' ||
14
+ fileRelativeToRoot.startsWith(`..${node_path_1.default.sep}`) ||
15
+ node_path_1.default.isAbsolute(fileRelativeToRoot)) {
16
+ throw new Error(formatOutsideProjectError({
17
+ action,
18
+ fileName,
19
+ absolutePath,
20
+ remotionRoot: resolvedRemotionRoot,
21
+ }));
22
+ }
23
+ return { absolutePath, fileRelativeToRoot };
24
+ };
25
+ exports.resolveFileInsideProject = resolveFileInsideProject;
@@ -32,18 +32,15 @@ var __importStar = (this && this.__importStar) || (function () {
32
32
  return result;
33
33
  };
34
34
  })();
35
- var __importDefault = (this && this.__importDefault) || function (mod) {
36
- return (mod && mod.__esModule) ? mod : { "default": mod };
37
- };
38
35
  Object.defineProperty(exports, "__esModule", { value: true });
39
36
  exports.applyVisualControlHandler = void 0;
40
37
  const node_fs_1 = require("node:fs");
41
- const node_path_1 = __importDefault(require("node:path"));
42
38
  const renderer_1 = require("@remotion/renderer");
43
39
  const recast = __importStar(require("recast"));
44
40
  const parse_ast_1 = require("../../codemods/parse-ast");
45
41
  const recast_mods_1 = require("../../codemods/recast-mods");
46
42
  const file_watcher_1 = require("../../file-watcher");
43
+ const resolve_file_inside_project_1 = require("../../helpers/resolve-file-inside-project");
47
44
  const format_log_file_location_1 = require("../format-log-file-location");
48
45
  const live_events_1 = require("../live-events");
49
46
  const undo_stack_1 = require("../undo-stack");
@@ -71,11 +68,11 @@ const getVisualControlChangeLine = (file, changeId) => {
71
68
  };
72
69
  const applyVisualControlHandler = async ({ input: { fileName, changes }, remotionRoot, logLevel }) => {
73
70
  renderer_1.RenderInternals.Log.trace({ indent: false, logLevel }, `[apply-visual-control] Received request for ${fileName} with ${changes.length} changes`);
74
- const absolutePath = node_path_1.default.resolve(remotionRoot, fileName);
75
- const fileRelativeToRoot = node_path_1.default.relative(remotionRoot, absolutePath);
76
- if (fileRelativeToRoot.startsWith('..')) {
77
- throw new Error('Cannot apply visual control change to a file outside the project');
78
- }
71
+ const { absolutePath } = (0, resolve_file_inside_project_1.resolveFileInsideProject)({
72
+ remotionRoot,
73
+ fileName,
74
+ action: 'apply visual control change to',
75
+ });
79
76
  const fileContents = (0, node_fs_1.readFileSync)(absolutePath, 'utf-8');
80
77
  const ast = (0, parse_ast_1.parseAst)(fileContents);
81
78
  const logLine = changes.length > 0 ? getVisualControlChangeLine(ast, changes[0].id) : 1;
@@ -1,13 +1,10 @@
1
1
  "use strict";
2
- var __importDefault = (this && this.__importDefault) || function (mod) {
3
- return (mod && mod.__esModule) ? mod : { "default": mod };
4
- };
5
2
  Object.defineProperty(exports, "__esModule", { value: true });
6
3
  exports.computeEffectPropsStatusesFromFile = exports.computeEffectPropsStatusesFromContent = exports.computeEffectPropStatus = void 0;
7
4
  const node_fs_1 = require("node:fs");
8
- const node_path_1 = __importDefault(require("node:path"));
9
5
  const parse_ast_1 = require("../../codemods/parse-ast");
10
6
  const update_effect_props_1 = require("../../codemods/update-effect-props/update-effect-props");
7
+ const resolve_file_inside_project_1 = require("../../helpers/resolve-file-inside-project");
11
8
  const can_update_sequence_props_1 = require("./can-update-sequence-props");
12
9
  const findEffectsAttr = (jsx) => {
13
10
  for (const attr of jsx.attributes) {
@@ -129,11 +126,11 @@ const computeEffectPropsStatusesFromContent = ({ fileContents, sequenceNodePath,
129
126
  };
130
127
  exports.computeEffectPropsStatusesFromContent = computeEffectPropsStatusesFromContent;
131
128
  const computeEffectPropsStatusesFromFile = ({ fileName, sequenceNodePath, effects, keysFor, remotionRoot, }) => {
132
- const absolutePath = node_path_1.default.resolve(remotionRoot, fileName);
133
- const fileRelativeToRoot = node_path_1.default.relative(remotionRoot, absolutePath);
134
- if (fileRelativeToRoot.startsWith('..')) {
135
- throw new Error('Cannot read a file outside the project');
136
- }
129
+ const { absolutePath } = (0, resolve_file_inside_project_1.resolveFileInsideProject)({
130
+ remotionRoot,
131
+ fileName,
132
+ action: 'read',
133
+ });
137
134
  const fileContents = (0, node_fs_1.readFileSync)(absolutePath, 'utf-8');
138
135
  return (0, exports.computeEffectPropsStatusesFromContent)({
139
136
  fileContents,
@@ -32,17 +32,14 @@ var __importStar = (this && this.__importStar) || (function () {
32
32
  return result;
33
33
  };
34
34
  })();
35
- var __importDefault = (this && this.__importDefault) || function (mod) {
36
- return (mod && mod.__esModule) ? mod : { "default": mod };
37
- };
38
35
  Object.defineProperty(exports, "__esModule", { value: true });
39
36
  exports.computeSequencePropsStatusFromFilenameByLine = exports.computeSequencePropsStatus = exports.computeSequencePropsStatusFromContent = exports.computeSequencePropsOnlyStatus = exports.lineColumnToNodePath = exports.findJsxElementAtNodePath = exports.getComputedStatus = exports.extractStaticValue = exports.isStaticValue = void 0;
40
37
  const node_fs_1 = require("node:fs");
41
- const node_path_1 = __importDefault(require("node:path"));
42
38
  const renderer_1 = require("@remotion/renderer");
43
39
  const recast = __importStar(require("recast"));
44
40
  const parse_ast_1 = require("../../codemods/parse-ast");
45
41
  const get_ast_node_path_1 = require("../../helpers/get-ast-node-path");
42
+ const resolve_file_inside_project_1 = require("../../helpers/resolve-file-inside-project");
46
43
  const jsx_element_not_found_at_location_error_1 = require("../jsx-element-not-found-at-location-error");
47
44
  const can_update_effect_props_1 = require("./can-update-effect-props");
48
45
  const isStaticValue = (node) => {
@@ -131,16 +128,17 @@ const getNumericValue = (node) => {
131
128
  }
132
129
  return null;
133
130
  };
134
- const getInterpolateKeyframes = (node) => {
131
+ const getInterpolationKeyframes = (node) => {
135
132
  if (node.type === 'TSAsExpression') {
136
- return getInterpolateKeyframes(node.expression);
133
+ return getInterpolationKeyframes(node.expression);
137
134
  }
138
135
  if (node.type !== 'CallExpression') {
139
136
  return undefined;
140
137
  }
141
138
  const callExpression = node;
142
139
  if (callExpression.callee.type !== 'Identifier' ||
143
- callExpression.callee.name !== 'interpolate') {
140
+ (callExpression.callee.name !== 'interpolate' &&
141
+ callExpression.callee.name !== 'interpolateColors')) {
144
142
  return undefined;
145
143
  }
146
144
  const inputArg = callExpression.arguments[1];
@@ -176,7 +174,7 @@ const getInterpolateKeyframes = (node) => {
176
174
  return keyframes.length > 0 ? keyframes : undefined;
177
175
  };
178
176
  const getComputedStatus = (node) => {
179
- const keyframes = getInterpolateKeyframes(node);
177
+ const keyframes = getInterpolationKeyframes(node);
180
178
  if (!keyframes) {
181
179
  return { canUpdate: false, reason: 'computed' };
182
180
  }
@@ -348,11 +346,11 @@ const computeSequenceOnlyPropsRecord = ({ jsxElement, keys, }) => {
348
346
  return filteredProps;
349
347
  };
350
348
  const computeSequencePropsOnlyStatus = ({ fileName, nodePath, keys, remotionRoot, }) => {
351
- const absolutePath = node_path_1.default.resolve(remotionRoot, fileName);
352
- const fileRelativeToRoot = node_path_1.default.relative(remotionRoot, absolutePath);
353
- if (fileRelativeToRoot.startsWith('..')) {
354
- throw new Error('Cannot read a file outside the project');
355
- }
349
+ const { absolutePath } = (0, resolve_file_inside_project_1.resolveFileInsideProject)({
350
+ remotionRoot,
351
+ fileName,
352
+ action: 'read',
353
+ });
356
354
  const fileContents = (0, node_fs_1.readFileSync)(absolutePath, 'utf-8');
357
355
  const ast = (0, parse_ast_1.parseAst)(fileContents);
358
356
  const jsxElement = (0, exports.findJsxElementAtNodePath)(ast, nodePath);
@@ -381,11 +379,11 @@ const computeSequencePropsStatusFromContent = ({ fileContents, nodePath, keys, e
381
379
  };
382
380
  exports.computeSequencePropsStatusFromContent = computeSequencePropsStatusFromContent;
383
381
  const computeSequencePropsStatus = ({ fileName, nodePath, keys, effects, remotionRoot, }) => {
384
- const absolutePath = node_path_1.default.resolve(remotionRoot, fileName);
385
- const fileRelativeToRoot = node_path_1.default.relative(remotionRoot, absolutePath);
386
- if (fileRelativeToRoot.startsWith('..')) {
387
- throw new Error('Cannot read a file outside the project');
388
- }
382
+ const { absolutePath } = (0, resolve_file_inside_project_1.resolveFileInsideProject)({
383
+ remotionRoot,
384
+ fileName,
385
+ action: 'read',
386
+ });
389
387
  const fileContents = (0, node_fs_1.readFileSync)(absolutePath, 'utf-8');
390
388
  return (0, exports.computeSequencePropsStatusFromContent)({
391
389
  fileContents,
@@ -397,11 +395,11 @@ const computeSequencePropsStatus = ({ fileName, nodePath, keys, effects, remotio
397
395
  exports.computeSequencePropsStatus = computeSequencePropsStatus;
398
396
  const computeSequencePropsStatusFromFilenameByLine = ({ fileName, line, keys, effects, remotionRoot, logLevel, }) => {
399
397
  try {
400
- const absolutePath = node_path_1.default.resolve(remotionRoot, fileName);
401
- const fileRelativeToRoot = node_path_1.default.relative(remotionRoot, absolutePath);
402
- if (fileRelativeToRoot.startsWith('..')) {
403
- throw new Error('Cannot read a file outside the project');
404
- }
398
+ const { absolutePath } = (0, resolve_file_inside_project_1.resolveFileInsideProject)({
399
+ remotionRoot,
400
+ fileName,
401
+ action: 'read',
402
+ });
405
403
  const fileContents = (0, node_fs_1.readFileSync)(absolutePath, 'utf-8');
406
404
  const ast = (0, parse_ast_1.parseAst)(fileContents);
407
405
  const resolvedNodePath = (0, exports.lineColumnToNodePath)(ast, line);
@@ -1,14 +1,11 @@
1
1
  "use strict";
2
- var __importDefault = (this && this.__importDefault) || function (mod) {
3
- return (mod && mod.__esModule) ? mod : { "default": mod };
4
- };
5
2
  Object.defineProperty(exports, "__esModule", { value: true });
6
3
  exports.deleteEffectHandler = void 0;
7
4
  const node_fs_1 = require("node:fs");
8
- const node_path_1 = __importDefault(require("node:path"));
9
5
  const renderer_1 = require("@remotion/renderer");
10
6
  const delete_effect_1 = require("../../codemods/delete-effect");
11
7
  const file_watcher_1 = require("../../file-watcher");
8
+ const resolve_file_inside_project_1 = require("../../helpers/resolve-file-inside-project");
12
9
  const format_log_file_location_1 = require("../format-log-file-location");
13
10
  const undo_stack_1 = require("../undo-stack");
14
11
  const formatting_1 = require("./log-updates/formatting");
@@ -16,11 +13,11 @@ const log_update_1 = require("./log-updates/log-update");
16
13
  const deleteEffectHandler = async ({ input: { fileName, sequenceNodePath, effectIndex }, remotionRoot, logLevel, }) => {
17
14
  try {
18
15
  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
- }
16
+ const { absolutePath, fileRelativeToRoot } = (0, resolve_file_inside_project_1.resolveFileInsideProject)({
17
+ remotionRoot,
18
+ fileName,
19
+ action: 'modify',
20
+ });
24
21
  const fileContents = (0, node_fs_1.readFileSync)(absolutePath, 'utf-8');
25
22
  const { output, formatted, effectLabel, logLine } = await (0, delete_effect_1.deleteEffect)({
26
23
  input: fileContents,
@@ -1,25 +1,22 @@
1
1
  "use strict";
2
- var __importDefault = (this && this.__importDefault) || function (mod) {
3
- return (mod && mod.__esModule) ? mod : { "default": mod };
4
- };
5
2
  Object.defineProperty(exports, "__esModule", { value: true });
6
3
  exports.deleteJsxNodeHandler = void 0;
7
4
  const node_fs_1 = require("node:fs");
8
- const node_path_1 = __importDefault(require("node:path"));
9
5
  const renderer_1 = require("@remotion/renderer");
10
6
  const delete_jsx_node_1 = require("../../codemods/delete-jsx-node");
11
7
  const file_watcher_1 = require("../../file-watcher");
8
+ const resolve_file_inside_project_1 = require("../../helpers/resolve-file-inside-project");
12
9
  const format_log_file_location_1 = require("../format-log-file-location");
13
10
  const undo_stack_1 = require("../undo-stack");
14
11
  const log_update_1 = require("./log-updates/log-update");
15
12
  const deleteJsxNodeHandler = async ({ input: { fileName, nodePath }, remotionRoot, logLevel }) => {
16
13
  try {
17
14
  renderer_1.RenderInternals.Log.trace({ indent: false, logLevel }, `[delete-jsx-node] Received request for fileName="${fileName}"`);
18
- const absolutePath = node_path_1.default.resolve(remotionRoot, fileName);
19
- const fileRelativeToRoot = node_path_1.default.relative(remotionRoot, absolutePath);
20
- if (fileRelativeToRoot.startsWith('..')) {
21
- throw new Error('Cannot modify a file outside the project');
22
- }
15
+ const { absolutePath, fileRelativeToRoot } = (0, resolve_file_inside_project_1.resolveFileInsideProject)({
16
+ remotionRoot,
17
+ fileName,
18
+ action: 'modify',
19
+ });
23
20
  const fileContents = (0, node_fs_1.readFileSync)(absolutePath, 'utf-8');
24
21
  const { output, formatted, nodeLabel, logLine } = await (0, delete_jsx_node_1.deleteJsxNode)({
25
22
  input: fileContents,
@@ -1,25 +1,22 @@
1
1
  "use strict";
2
- var __importDefault = (this && this.__importDefault) || function (mod) {
3
- return (mod && mod.__esModule) ? mod : { "default": mod };
4
- };
5
2
  Object.defineProperty(exports, "__esModule", { value: true });
6
3
  exports.duplicateJsxNodeHandler = void 0;
7
4
  const node_fs_1 = require("node:fs");
8
- const node_path_1 = __importDefault(require("node:path"));
9
5
  const renderer_1 = require("@remotion/renderer");
10
6
  const duplicate_jsx_node_1 = require("../../codemods/duplicate-jsx-node");
11
7
  const file_watcher_1 = require("../../file-watcher");
8
+ const resolve_file_inside_project_1 = require("../../helpers/resolve-file-inside-project");
12
9
  const format_log_file_location_1 = require("../format-log-file-location");
13
10
  const undo_stack_1 = require("../undo-stack");
14
11
  const log_update_1 = require("./log-updates/log-update");
15
12
  const duplicateJsxNodeHandler = async ({ input: { fileName, nodePath }, remotionRoot, logLevel }) => {
16
13
  try {
17
14
  renderer_1.RenderInternals.Log.trace({ indent: false, logLevel }, `[duplicate-jsx-node] Received request for fileName="${fileName}"`);
18
- const absolutePath = node_path_1.default.resolve(remotionRoot, fileName);
19
- const fileRelativeToRoot = node_path_1.default.relative(remotionRoot, absolutePath);
20
- if (fileRelativeToRoot.startsWith('..')) {
21
- throw new Error('Cannot modify a file outside the project');
22
- }
15
+ const { absolutePath, fileRelativeToRoot } = (0, resolve_file_inside_project_1.resolveFileInsideProject)({
16
+ remotionRoot,
17
+ fileName,
18
+ action: 'modify',
19
+ });
23
20
  const fileContents = (0, node_fs_1.readFileSync)(absolutePath, 'utf-8');
24
21
  const { output, formatted, nodeLabel, logLine } = await (0, duplicate_jsx_node_1.duplicateJsxNode)({
25
22
  input: fileContents,
@@ -1,16 +1,13 @@
1
1
  "use strict";
2
- var __importDefault = (this && this.__importDefault) || function (mod) {
3
- return (mod && mod.__esModule) ? mod : { "default": mod };
4
- };
5
2
  Object.defineProperty(exports, "__esModule", { value: true });
6
3
  exports.saveEffectPropsHandler = void 0;
7
4
  const node_fs_1 = require("node:fs");
8
- const node_path_1 = __importDefault(require("node:path"));
9
5
  const renderer_1 = require("@remotion/renderer");
10
6
  const studio_shared_1 = require("@remotion/studio-shared");
11
7
  const parse_ast_1 = require("../../codemods/parse-ast");
12
8
  const update_effect_props_1 = require("../../codemods/update-effect-props/update-effect-props");
13
9
  const file_watcher_1 = require("../../file-watcher");
10
+ const resolve_file_inside_project_1 = require("../../helpers/resolve-file-inside-project");
14
11
  const undo_stack_1 = require("../undo-stack");
15
12
  const watch_ignore_next_change_1 = require("../watch-ignore-next-change");
16
13
  const can_update_effect_props_1 = require("./can-update-effect-props");
@@ -21,11 +18,11 @@ const log_update_1 = require("./log-updates/log-update");
21
18
  const save_props_mutex_1 = require("./save-props-mutex");
22
19
  const saveEffectPropsHandler = ({ input: { fileName, sequenceNodePath, effectIndex, key, value, defaultValue, schema, clientId, }, remotionRoot, logLevel, }) => (0, save_props_mutex_1.withSavePropsLock)(async () => {
23
20
  renderer_1.RenderInternals.Log.trace({ indent: false, logLevel }, `[save-effect-props] Received request for fileName="${fileName}" effectIndex=${effectIndex} key="${key}"`);
24
- const absolutePath = node_path_1.default.resolve(remotionRoot, fileName);
25
- const fileRelativeToRoot = node_path_1.default.relative(remotionRoot, absolutePath);
26
- if (fileRelativeToRoot.startsWith('..')) {
27
- throw new Error('Cannot modify a file outside the project');
28
- }
21
+ const { absolutePath, fileRelativeToRoot } = (0, resolve_file_inside_project_1.resolveFileInsideProject)({
22
+ remotionRoot,
23
+ fileName,
24
+ action: 'modify',
25
+ });
29
26
  const fileContents = (0, node_fs_1.readFileSync)(absolutePath, 'utf-8');
30
27
  const parsedDefault = defaultValue !== null ? JSON.parse(defaultValue) : null;
31
28
  const { output, oldValueString, formatted, logLine, effectCallee, removedProps, } = await (0, update_effect_props_1.updateEffectProps)({
@@ -1,16 +1,13 @@
1
1
  "use strict";
2
- var __importDefault = (this && this.__importDefault) || function (mod) {
3
- return (mod && mod.__esModule) ? mod : { "default": mod };
4
- };
5
2
  Object.defineProperty(exports, "__esModule", { value: true });
6
3
  exports.saveSequencePropsHandler = void 0;
7
4
  const node_fs_1 = require("node:fs");
8
- const node_path_1 = __importDefault(require("node:path"));
9
5
  const renderer_1 = require("@remotion/renderer");
10
6
  const studio_shared_1 = require("@remotion/studio-shared");
11
7
  const no_react_1 = require("remotion/no-react");
12
8
  const update_sequence_props_1 = require("../../codemods/update-sequence-props/update-sequence-props");
13
9
  const file_watcher_1 = require("../../file-watcher");
10
+ const resolve_file_inside_project_1 = require("../../helpers/resolve-file-inside-project");
14
11
  const undo_stack_1 = require("../undo-stack");
15
12
  const watch_ignore_next_change_1 = require("../watch-ignore-next-change");
16
13
  const can_update_sequence_props_1 = require("./can-update-sequence-props");
@@ -19,11 +16,11 @@ const log_update_1 = require("./log-updates/log-update");
19
16
  const save_props_mutex_1 = require("./save-props-mutex");
20
17
  const saveSequencePropsHandler = ({ input: { fileName, nodePath, key, value, defaultValue, schema, clientId }, remotionRoot, logLevel, }) => (0, save_props_mutex_1.withSavePropsLock)(async () => {
21
18
  renderer_1.RenderInternals.Log.trace({ indent: false, logLevel }, `[save-sequence-props] Received request for fileName="${fileName}" key="${key}"`);
22
- const absolutePath = node_path_1.default.resolve(remotionRoot, fileName);
23
- const fileRelativeToRoot = node_path_1.default.relative(remotionRoot, absolutePath);
24
- if (fileRelativeToRoot.startsWith('..')) {
25
- throw new Error('Cannot modify a file outside the project');
26
- }
19
+ const { absolutePath, fileRelativeToRoot } = (0, resolve_file_inside_project_1.resolveFileInsideProject)({
20
+ remotionRoot,
21
+ fileName,
22
+ action: 'modify',
23
+ });
27
24
  const fileContents = (0, node_fs_1.readFileSync)(absolutePath, 'utf-8');
28
25
  const { output, oldValueStrings, formatted, logLine, removedProps } = await (0, update_sequence_props_1.updateSequenceProps)({
29
26
  input: fileContents,
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.467",
6
+ "version": "4.0.468",
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.467",
30
+ "remotion": "4.0.468",
31
31
  "recast": "0.23.11",
32
- "@remotion/bundler": "4.0.467",
33
- "@remotion/renderer": "4.0.467",
34
- "@remotion/studio-shared": "4.0.467",
32
+ "@remotion/bundler": "4.0.468",
33
+ "@remotion/renderer": "4.0.468",
34
+ "@remotion/studio-shared": "4.0.468",
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.467",
42
+ "@remotion/eslint-config-internal": "4.0.468",
43
43
  "eslint": "9.19.0",
44
44
  "@types/node": "20.12.14",
45
45
  "@typescript/native-preview": "7.0.0-dev.20260217.1"