@remotion/studio-server 4.0.471 → 4.0.473

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 (53) hide show
  1. package/dist/codemods/add-effect.d.ts +11 -0
  2. package/dist/codemods/add-effect.js +14 -52
  3. package/dist/codemods/effect-param-expression.d.ts +15 -0
  4. package/dist/codemods/effect-param-expression.js +131 -0
  5. package/dist/codemods/format-file-content.js +1 -1
  6. package/dist/codemods/parse-ast.js +4 -1
  7. package/dist/codemods/paste-effects.d.ts +15 -0
  8. package/dist/codemods/paste-effects.js +147 -0
  9. package/dist/codemods/recast-mods.js +178 -31
  10. package/dist/codemods/reorder-sequence.d.ts +14 -0
  11. package/dist/codemods/reorder-sequence.js +109 -0
  12. package/dist/codemods/update-effect-props/update-effect-props.d.ts +7 -0
  13. package/dist/codemods/update-effect-props/update-effect-props.js +64 -16
  14. package/dist/codemods/update-keyframes/ensure-imports-and-frame-hook.d.ts +1 -1
  15. package/dist/codemods/update-keyframes/ensure-imports-and-frame-hook.js +7 -55
  16. package/dist/codemods/update-keyframes/update-keyframes.d.ts +24 -6
  17. package/dist/codemods/update-keyframes/update-keyframes.js +279 -16
  18. package/dist/helpers/get-ast-node-path.js +6 -1
  19. package/dist/helpers/import-agnostic-node-path.d.ts +10 -0
  20. package/dist/helpers/import-agnostic-node-path.js +154 -0
  21. package/dist/helpers/imports.d.ts +16 -0
  22. package/dist/helpers/imports.js +145 -0
  23. package/dist/helpers/resolve-composition-component.js +133 -51
  24. package/dist/preview-server/api-routes.js +16 -0
  25. package/dist/preview-server/routes/add-effect-keyframe.js +2 -0
  26. package/dist/preview-server/routes/add-sequence-keyframe.js +1 -0
  27. package/dist/preview-server/routes/apply-codemod.js +18 -0
  28. package/dist/preview-server/routes/can-update-effect-props.d.ts +3 -2
  29. package/dist/preview-server/routes/can-update-effect-props.js +78 -8
  30. package/dist/preview-server/routes/can-update-sequence-props.d.ts +1 -1
  31. package/dist/preview-server/routes/can-update-sequence-props.js +82 -43
  32. package/dist/preview-server/routes/delete-keyframes.js +1 -0
  33. package/dist/preview-server/routes/download-remote-asset.d.ts +7 -0
  34. package/dist/preview-server/routes/download-remote-asset.js +267 -0
  35. package/dist/preview-server/routes/insert-jsx-element.js +26 -0
  36. package/dist/preview-server/routes/log-studio-error.d.ts +3 -0
  37. package/dist/preview-server/routes/log-studio-error.js +58 -0
  38. package/dist/preview-server/routes/move-keyframes.d.ts +7 -0
  39. package/dist/preview-server/routes/move-keyframes.js +242 -0
  40. package/dist/preview-server/routes/paste-effects.d.ts +3 -0
  41. package/dist/preview-server/routes/paste-effects.js +78 -0
  42. package/dist/preview-server/routes/rename-static-file.d.ts +3 -0
  43. package/dist/preview-server/routes/rename-static-file.js +53 -0
  44. package/dist/preview-server/routes/reorder-sequence.d.ts +3 -0
  45. package/dist/preview-server/routes/reorder-sequence.js +67 -0
  46. package/dist/preview-server/routes/save-effect-props.js +25 -9
  47. package/dist/preview-server/routes/save-sequence-props.js +2 -34
  48. package/dist/preview-server/routes/update-effect-keyframe-settings.d.ts +3 -0
  49. package/dist/preview-server/routes/update-effect-keyframe-settings.js +90 -0
  50. package/dist/preview-server/routes/update-sequence-keyframe-settings.d.ts +3 -0
  51. package/dist/preview-server/routes/update-sequence-keyframe-settings.js +85 -0
  52. package/dist/preview-server/undo-stack.d.ts +9 -1
  53. package/package.json +6 -6
@@ -35,6 +35,7 @@ var __importStar = (this && this.__importStar) || (function () {
35
35
  Object.defineProperty(exports, "__esModule", { value: true });
36
36
  exports.ensureUseCurrentFrameHook = exports.ensureRemotionImports = exports.findEnclosingFunctionPath = void 0;
37
37
  const recast = __importStar(require("recast"));
38
+ const imports_1 = require("../../helpers/imports");
38
39
  const b = recast.types.builders;
39
40
  const n = recast.types.namedTypes;
40
41
  const isFunctionNode = (value) => {
@@ -53,60 +54,11 @@ const findEnclosingFunctionPath = (path) => {
53
54
  return null;
54
55
  };
55
56
  exports.findEnclosingFunctionPath = findEnclosingFunctionPath;
56
- const findRemotionImport = (ast) => {
57
- for (const stmt of ast.program.body) {
58
- if (stmt.type === 'ImportDeclaration' &&
59
- stmt.source.type === 'StringLiteral' &&
60
- stmt.source.value === 'remotion') {
61
- return stmt;
62
- }
63
- }
64
- return null;
65
- };
66
- const insertImportDeclaration = (ast, importDecl) => {
67
- const { body } = ast.program;
68
- let lastImportIndex = -1;
69
- for (let i = 0; i < body.length; i++) {
70
- if (body[i].type === 'ImportDeclaration') {
71
- lastImportIndex = i;
72
- }
73
- }
74
- body.splice(lastImportIndex + 1, 0, importDecl);
75
- };
76
57
  const ensureRemotionImports = (ast, names) => {
77
- var _a, _b;
78
- if (names.size === 0) {
79
- return;
80
- }
81
- let remotionImport = findRemotionImport(ast);
82
- if (!remotionImport) {
83
- remotionImport = b.importDeclaration([], b.stringLiteral('remotion'));
84
- insertImportDeclaration(ast, remotionImport);
85
- }
86
- const existingNames = new Set();
87
- for (const specifier of (_a = remotionImport.specifiers) !== null && _a !== void 0 ? _a : []) {
88
- if (specifier.type !== 'ImportSpecifier') {
89
- continue;
90
- }
91
- const { imported } = specifier;
92
- if (imported.type === 'Identifier') {
93
- existingNames.add(imported.name);
94
- }
95
- else if (imported.type === 'StringLiteral') {
96
- existingNames.add(imported.value);
97
- }
98
- }
99
- for (const name of names) {
100
- if (existingNames.has(name)) {
101
- continue;
102
- }
103
- remotionImport.specifiers = (_b = remotionImport.specifiers) !== null && _b !== void 0 ? _b : [];
104
- remotionImport.specifiers.push(b.importSpecifier(b.identifier(name)));
105
- existingNames.add(name);
106
- }
58
+ (0, imports_1.ensureNamedImports)({ ast, importedNames: names, sourcePath: 'remotion' });
107
59
  };
108
60
  exports.ensureRemotionImports = ensureRemotionImports;
109
- const componentBodyHasFrameDeclaration = (body) => {
61
+ const componentBodyHasFrameDeclaration = ({ body, hookName, }) => {
110
62
  if (!n.BlockStatement.check(body)) {
111
63
  return false;
112
64
  }
@@ -123,14 +75,14 @@ const componentBodyHasFrameDeclaration = (body) => {
123
75
  decl.init &&
124
76
  decl.init.type === 'CallExpression' &&
125
77
  decl.init.callee.type === 'Identifier' &&
126
- decl.init.callee.name === 'useCurrentFrame') {
78
+ decl.init.callee.name === hookName) {
127
79
  return true;
128
80
  }
129
81
  }
130
82
  }
131
83
  return false;
132
84
  };
133
- const ensureUseCurrentFrameHook = (functionPath) => {
85
+ const ensureUseCurrentFrameHook = (functionPath, hookName = 'useCurrentFrame') => {
134
86
  const fn = functionPath.value;
135
87
  if (!n.BlockStatement.check(fn.body)) {
136
88
  // Arrow function with expression body: wrap the expression in a block so
@@ -140,12 +92,12 @@ const ensureUseCurrentFrameHook = (functionPath) => {
140
92
  b.returnStatement(expression),
141
93
  ]);
142
94
  }
143
- if (componentBodyHasFrameDeclaration(fn.body)) {
95
+ if (componentBodyHasFrameDeclaration({ body: fn.body, hookName })) {
144
96
  return;
145
97
  }
146
98
  const block = fn.body;
147
99
  const frameDecl = b.variableDeclaration('const', [
148
- b.variableDeclarator(b.identifier('frame'), b.callExpression(b.identifier('useCurrentFrame'), [])),
100
+ b.variableDeclarator(b.identifier('frame'), b.callExpression(b.identifier(hookName), [])),
149
101
  ]);
150
102
  block.body.unshift(frameDecl);
151
103
  };
@@ -1,4 +1,5 @@
1
- import type { SequenceNodePath } from 'remotion';
1
+ import { type KeyframeInterpolationFunction } from '@remotion/studio-shared';
2
+ import type { ExtrapolateType, SequenceNodePath, SequenceSchema } from 'remotion';
2
3
  export type KeyframeOperation = {
3
4
  type: 'add';
4
5
  frame: number;
@@ -6,6 +7,19 @@ export type KeyframeOperation = {
6
7
  } | {
7
8
  type: 'remove';
8
9
  frame: number;
10
+ } | {
11
+ type: 'settings';
12
+ clamping: {
13
+ left: ExtrapolateType;
14
+ right: ExtrapolateType;
15
+ } | undefined;
16
+ posterize: number | undefined;
17
+ } | {
18
+ type: 'move';
19
+ moves: {
20
+ fromFrame: number;
21
+ toFrame: number;
22
+ }[];
9
23
  };
10
24
  export type SequenceKeyframeUpdate = {
11
25
  key: string;
@@ -16,13 +30,14 @@ export type EffectKeyframeUpdate = {
16
30
  operation: KeyframeOperation;
17
31
  };
18
32
  export type IntroducedKeyframeIdentifiers = {
19
- calleeName: 'interpolate' | 'interpolateColors' | null;
33
+ calleeName: KeyframeInterpolationFunction | null;
20
34
  needsFrameHook: boolean;
21
35
  };
22
- export declare const updateSequenceKeyframesAst: ({ input, nodePath, updates, }: {
36
+ export declare const updateSequenceKeyframesAst: ({ input, nodePath, updates, schema, }: {
23
37
  input: string;
24
38
  nodePath: SequenceNodePath;
25
39
  updates: SequenceKeyframeUpdate[];
40
+ schema?: SequenceSchema | undefined;
26
41
  }) => {
27
42
  serialized: string;
28
43
  oldValueStrings: string[];
@@ -30,10 +45,11 @@ export declare const updateSequenceKeyframesAst: ({ input, nodePath, updates, }:
30
45
  logLine: number;
31
46
  updatedNodePath: SequenceNodePath;
32
47
  };
33
- export declare const updateSequenceKeyframes: ({ input, nodePath, updates, prettierConfigOverride, }: {
48
+ export declare const updateSequenceKeyframes: ({ input, nodePath, updates, schema, prettierConfigOverride, }: {
34
49
  input: string;
35
50
  nodePath: SequenceNodePath;
36
51
  updates: SequenceKeyframeUpdate[];
52
+ schema?: SequenceSchema | undefined;
37
53
  prettierConfigOverride?: Record<string, unknown> | null | undefined;
38
54
  }) => Promise<{
39
55
  output: string;
@@ -43,11 +59,12 @@ export declare const updateSequenceKeyframes: ({ input, nodePath, updates, prett
43
59
  logLine: number;
44
60
  updatedNodePath: SequenceNodePath;
45
61
  }>;
46
- export declare const updateEffectKeyframesAst: ({ input, sequenceNodePath, effectIndex, updates, }: {
62
+ export declare const updateEffectKeyframesAst: ({ input, sequenceNodePath, effectIndex, updates, schema, }: {
47
63
  input: string;
48
64
  sequenceNodePath: SequenceNodePath;
49
65
  effectIndex: number;
50
66
  updates: EffectKeyframeUpdate[];
67
+ schema?: SequenceSchema | undefined;
51
68
  }) => {
52
69
  serialized: string;
53
70
  oldValueStrings: string[];
@@ -56,11 +73,12 @@ export declare const updateEffectKeyframesAst: ({ input, sequenceNodePath, effec
56
73
  effectCallee: string;
57
74
  updatedSequenceNodePath: SequenceNodePath;
58
75
  };
59
- export declare const updateEffectKeyframes: ({ input, sequenceNodePath, effectIndex, updates, prettierConfigOverride, }: {
76
+ export declare const updateEffectKeyframes: ({ input, sequenceNodePath, effectIndex, updates, schema, prettierConfigOverride, }: {
60
77
  input: string;
61
78
  sequenceNodePath: SequenceNodePath;
62
79
  effectIndex: number;
63
80
  updates: EffectKeyframeUpdate[];
81
+ schema?: SequenceSchema | undefined;
64
82
  prettierConfigOverride?: Record<string, unknown> | null | undefined;
65
83
  }) => Promise<{
66
84
  output: string;
@@ -34,6 +34,7 @@ var __importStar = (this && this.__importStar) || (function () {
34
34
  })();
35
35
  Object.defineProperty(exports, "__esModule", { value: true });
36
36
  exports.updateEffectKeyframes = exports.updateEffectKeyframesAst = exports.updateSequenceKeyframes = exports.updateSequenceKeyframesAst = void 0;
37
+ const studio_shared_1 = require("@remotion/studio-shared");
37
38
  const recast = __importStar(require("recast"));
38
39
  const get_ast_node_path_1 = require("../../helpers/get-ast-node-path");
39
40
  const can_update_sequence_props_1 = require("../../preview-server/routes/can-update-sequence-props");
@@ -71,8 +72,7 @@ const getInterpolationExpression = (node) => {
71
72
  }
72
73
  if (node.type !== 'CallExpression' ||
73
74
  node.callee.type !== 'Identifier' ||
74
- (node.callee.name !== 'interpolate' &&
75
- node.callee.name !== 'interpolateColors')) {
75
+ !(0, studio_shared_1.isKeyframeInterpolationFunction)(node.callee.name)) {
76
76
  return null;
77
77
  }
78
78
  const frameArg = getSupportedCallArgument(node.arguments[0]);
@@ -124,14 +124,109 @@ const getInterpolationExpression = (node) => {
124
124
  keyframes,
125
125
  };
126
126
  };
127
- const getInterpolationCalleeForValues = ({ staticValue, newValue, }) => {
128
- return b.identifier(typeof staticValue === 'string' && typeof newValue === 'string'
129
- ? 'interpolateColors'
130
- : 'interpolate');
127
+ const getInterpolationCalleeForValues = ({ schema, key, staticValue, newValue, }) => {
128
+ return b.identifier((0, studio_shared_1.getKeyframeInterpolationFunction)({
129
+ schema,
130
+ key,
131
+ staticValue,
132
+ newValue,
133
+ }));
131
134
  };
132
135
  const createFrameExpression = (frame) => {
133
136
  return (0, update_nested_prop_1.parseValueExpression)(frame);
134
137
  };
138
+ const createClampOptionsExpression = () => {
139
+ return b.objectExpression([
140
+ b.objectProperty(b.identifier('extrapolateLeft'), b.stringLiteral('clamp')),
141
+ b.objectProperty(b.identifier('extrapolateRight'), b.stringLiteral('clamp')),
142
+ ]);
143
+ };
144
+ const createEmptyOptionsExpression = () => b.objectExpression([]);
145
+ const findObjectOptionProperty = (options, propertyName) => {
146
+ const propIndex = options.properties.findIndex((prop) => prop.type === 'ObjectProperty' &&
147
+ !prop.computed &&
148
+ ((prop.key.type === 'Identifier' && prop.key.name === propertyName) ||
149
+ (prop.key.type === 'StringLiteral' && prop.key.value === propertyName)));
150
+ return {
151
+ propIndex,
152
+ prop: propIndex === -1
153
+ ? undefined
154
+ : options.properties[propIndex],
155
+ };
156
+ };
157
+ const setOptionsProperty = ({ options, propertyName, value, }) => {
158
+ const { propIndex, prop } = findObjectOptionProperty(options, propertyName);
159
+ if (value === null) {
160
+ if (propIndex !== -1) {
161
+ options.properties.splice(propIndex, 1);
162
+ }
163
+ return;
164
+ }
165
+ if (prop) {
166
+ prop.value = value;
167
+ return;
168
+ }
169
+ options.properties.push(b.objectProperty(b.identifier(propertyName), value));
170
+ };
171
+ const validatePosterize = (posterize) => {
172
+ if (posterize === undefined) {
173
+ return;
174
+ }
175
+ if (!Number.isFinite(posterize) || posterize <= 0) {
176
+ throw new Error('Cannot update keyframe settings: posterize must be > 0');
177
+ }
178
+ };
179
+ const updateKeyframeSettings = ({ expression, clamping, posterize, }) => {
180
+ validatePosterize(posterize);
181
+ const existing = getInterpolationExpression(expression);
182
+ if (!existing) {
183
+ throw new Error('Cannot update keyframe settings on non-keyframed value');
184
+ }
185
+ const calleeName = existing.callee.type === 'Identifier' ? existing.callee.name : null;
186
+ const isColorInterpolation = calleeName === 'interpolateColors';
187
+ const extraArgs = [...existing.extraArgs];
188
+ const existingOptions = extraArgs[0];
189
+ if (existingOptions && existingOptions.type !== 'ObjectExpression') {
190
+ throw new Error('Cannot update keyframe settings: options must be inline');
191
+ }
192
+ const options = (existingOptions === null || existingOptions === void 0 ? void 0 : existingOptions.type) === 'ObjectExpression'
193
+ ? existingOptions
194
+ : createEmptyOptionsExpression();
195
+ if (isColorInterpolation) {
196
+ setOptionsProperty({ options, propertyName: 'extrapolateLeft', value: null });
197
+ setOptionsProperty({
198
+ options,
199
+ propertyName: 'extrapolateRight',
200
+ value: null,
201
+ });
202
+ }
203
+ else if (clamping) {
204
+ setOptionsProperty({
205
+ options,
206
+ propertyName: 'extrapolateLeft',
207
+ value: b.stringLiteral(clamping.left),
208
+ });
209
+ setOptionsProperty({
210
+ options,
211
+ propertyName: 'extrapolateRight',
212
+ value: b.stringLiteral(clamping.right),
213
+ });
214
+ }
215
+ setOptionsProperty({
216
+ options,
217
+ propertyName: 'posterize',
218
+ value: posterize === undefined ? null : b.numericLiteral(posterize),
219
+ });
220
+ const nextExtraArgs = options.properties.length === 0
221
+ ? extraArgs.slice(1)
222
+ : [options, ...extraArgs.slice(1)];
223
+ return createInterpolateExpression({
224
+ callee: existing.callee,
225
+ input: existing.input,
226
+ extraArgs: nextExtraArgs,
227
+ keyframes: existing.keyframes,
228
+ });
229
+ };
135
230
  const createInterpolateExpression = ({ callee, input, extraArgs, keyframes, }) => {
136
231
  const sortedKeyframes = [...keyframes].sort((first, second) => first.frame - second.frame);
137
232
  return b.callExpression(callee, [
@@ -145,10 +240,21 @@ const noIntroducedIdentifiers = {
145
240
  calleeName: null,
146
241
  needsFrameHook: false,
147
242
  };
148
- const addKeyframe = ({ expression, frame, value, }) => {
243
+ const addKeyframe = ({ expression, key, frame, value, schema, }) => {
244
+ if (!(0, studio_shared_1.isSchemaFieldKeyframable)({ schema, key })) {
245
+ throw new Error(`Cannot add keyframe: "${key}" is not keyframable`);
246
+ }
149
247
  const existing = getInterpolationExpression(expression);
150
248
  const newOutput = (0, update_nested_prop_1.parseValueExpression)(value);
151
249
  if (existing) {
250
+ const existingCalleeName = existing.callee.type === 'Identifier'
251
+ ? existing.callee.name
252
+ : 'interpolate';
253
+ const schemaCalleeName = (0, studio_shared_1.getKeyframeInterpolationFunctionForSchemaField)({
254
+ schema,
255
+ key,
256
+ });
257
+ const nextCalleeName = schemaCalleeName !== null && schemaCalleeName !== void 0 ? schemaCalleeName : existingCalleeName;
152
258
  const existingIndex = existing.keyframes.findIndex((keyframe) => keyframe.frame === frame);
153
259
  const nextKeyframes = existingIndex === -1
154
260
  ? [...existing.keyframes, { frame, output: newOutput, value }]
@@ -157,12 +263,17 @@ const addKeyframe = ({ expression, frame, value, }) => {
157
263
  : keyframe);
158
264
  return {
159
265
  expression: createInterpolateExpression({
160
- callee: existing.callee,
266
+ callee: b.identifier(nextCalleeName),
161
267
  input: existing.input,
162
268
  extraArgs: existing.extraArgs,
163
269
  keyframes: nextKeyframes,
164
270
  }),
165
- introduced: noIntroducedIdentifiers,
271
+ introduced: {
272
+ calleeName: schemaCalleeName && schemaCalleeName !== existingCalleeName
273
+ ? schemaCalleeName
274
+ : null,
275
+ needsFrameHook: false,
276
+ },
166
277
  };
167
278
  }
168
279
  if (!(0, can_update_sequence_props_1.isStaticValue)(expression)) {
@@ -171,14 +282,19 @@ const addKeyframe = ({ expression, frame, value, }) => {
171
282
  const staticValue = (0, can_update_sequence_props_1.extractStaticValue)(expression);
172
283
  const keyframes = [{ frame, output: newOutput, value }];
173
284
  const callee = getInterpolationCalleeForValues({
285
+ schema,
286
+ key,
174
287
  staticValue,
175
288
  newValue: value,
176
289
  });
290
+ const extraArgs = callee.type === 'Identifier' && callee.name === 'interpolateColors'
291
+ ? []
292
+ : [createClampOptionsExpression()];
177
293
  return {
178
294
  expression: createInterpolateExpression({
179
295
  callee,
180
296
  input: b.identifier('frame'),
181
- extraArgs: [],
297
+ extraArgs,
182
298
  keyframes,
183
299
  }),
184
300
  introduced: {
@@ -209,14 +325,82 @@ const removeKeyframe = ({ expression, frame, }) => {
209
325
  keyframes: nextKeyframes,
210
326
  });
211
327
  };
212
- const applyKeyframeOperation = ({ expression, operation, }) => {
328
+ const moveKeyframes = ({ expression, moves, }) => {
329
+ var _a;
330
+ const existing = getInterpolationExpression(expression);
331
+ if (!existing) {
332
+ throw new Error('Cannot move keyframe in non-interpolated expression');
333
+ }
334
+ const moveMap = new Map();
335
+ for (const move of moves) {
336
+ if (move.fromFrame === move.toFrame) {
337
+ continue;
338
+ }
339
+ if (moveMap.has(move.fromFrame)) {
340
+ throw new Error(`Cannot move keyframe at frame ${move.fromFrame} twice`);
341
+ }
342
+ moveMap.set(move.fromFrame, move.toFrame);
343
+ }
344
+ if (moveMap.size === 0) {
345
+ return expression;
346
+ }
347
+ const frames = new Set(existing.keyframes.map((keyframe) => keyframe.frame));
348
+ for (const fromFrame of moveMap.keys()) {
349
+ if (!frames.has(fromFrame)) {
350
+ throw new Error(`Cannot move keyframe at frame ${fromFrame}: not found`);
351
+ }
352
+ }
353
+ const movedFromFrames = new Set(moveMap.keys());
354
+ const nextFrames = new Set();
355
+ for (const keyframe of existing.keyframes) {
356
+ const nextFrame = (_a = moveMap.get(keyframe.frame)) !== null && _a !== void 0 ? _a : keyframe.frame;
357
+ if (nextFrames.has(nextFrame)) {
358
+ throw new Error(`Cannot move keyframe to frame ${nextFrame}: frame already exists`);
359
+ }
360
+ if (!movedFromFrames.has(keyframe.frame) && moveMap.has(nextFrame)) {
361
+ throw new Error(`Cannot move keyframe to frame ${nextFrame}: frame already exists`);
362
+ }
363
+ nextFrames.add(nextFrame);
364
+ }
365
+ return createInterpolateExpression({
366
+ callee: existing.callee,
367
+ input: existing.input,
368
+ extraArgs: existing.extraArgs,
369
+ keyframes: existing.keyframes.map((keyframe) => {
370
+ var _a;
371
+ return ({
372
+ ...keyframe,
373
+ frame: (_a = moveMap.get(keyframe.frame)) !== null && _a !== void 0 ? _a : keyframe.frame,
374
+ });
375
+ }),
376
+ });
377
+ };
378
+ const applyKeyframeOperation = ({ expression, key, operation, schema, }) => {
213
379
  if (operation.type === 'add') {
214
380
  return addKeyframe({
215
381
  expression,
382
+ key,
216
383
  frame: operation.frame,
217
384
  value: operation.value,
385
+ schema,
218
386
  });
219
387
  }
388
+ if (operation.type === 'settings') {
389
+ return {
390
+ expression: updateKeyframeSettings({
391
+ expression,
392
+ clamping: operation.clamping,
393
+ posterize: operation.posterize,
394
+ }),
395
+ introduced: noIntroducedIdentifiers,
396
+ };
397
+ }
398
+ if (operation.type === 'move') {
399
+ return {
400
+ expression: moveKeyframes({ expression, moves: operation.moves }),
401
+ introduced: noIntroducedIdentifiers,
402
+ };
403
+ }
220
404
  return {
221
405
  expression: removeKeyframe({ expression, frame: operation.frame }),
222
406
  introduced: noIntroducedIdentifiers,
@@ -267,6 +451,30 @@ const findObjectProperty = (objExpr, propertyName) => {
267
451
  : objExpr.properties[propIndex],
268
452
  };
269
453
  };
454
+ const findFieldInSchema = (schema, key) => {
455
+ if (key in schema) {
456
+ return schema[key];
457
+ }
458
+ for (const field of Object.values(schema)) {
459
+ if (field.type !== 'enum') {
460
+ continue;
461
+ }
462
+ for (const variant of Object.values(field.variants)) {
463
+ const found = findFieldInSchema(variant, key);
464
+ if (found) {
465
+ return found;
466
+ }
467
+ }
468
+ }
469
+ return undefined;
470
+ };
471
+ const getInitialValueForMissingProp = ({ schema, key, newValue, }) => {
472
+ const field = schema ? findFieldInSchema(schema, key) : undefined;
473
+ if (field && field.type !== 'hidden' && field.default !== undefined) {
474
+ return field.default;
475
+ }
476
+ return newValue;
477
+ };
270
478
  const getObjectExpression = (attr) => {
271
479
  if (!attr.value || attr.value.type !== 'JSXExpressionContainer') {
272
480
  return null;
@@ -276,11 +484,31 @@ const getObjectExpression = (attr) => {
276
484
  }
277
485
  return attr.value.expression;
278
486
  };
279
- const getSequenceWritableProp = ({ attributes, key, }) => {
487
+ const createJsxExpressionAttribute = (key, expression) => {
488
+ return b.jsxAttribute(b.jsxIdentifier(key), b.jsxExpressionContainer(expression));
489
+ };
490
+ const createObjectProperty = (key, value) => b.objectProperty(b.identifier(key), value);
491
+ const createObjectExpressionAttribute = ({ parentKey, childKey, expression, }) => {
492
+ return createJsxExpressionAttribute(parentKey, b.objectExpression([
493
+ createObjectProperty(childKey, expression),
494
+ ]));
495
+ };
496
+ const createMissingPropExpression = (missingPropInitialValue) => {
497
+ return (0, update_nested_prop_1.parseValueExpression)(missingPropInitialValue.value);
498
+ };
499
+ const getSequenceWritableProp = ({ attributes, key, missingPropInitialValue, }) => {
280
500
  const dotIndex = key.indexOf('.');
281
501
  if (dotIndex === -1) {
282
502
  const { attr: topLevelAttr } = findJsxAttribute(attributes, key);
283
503
  if (!topLevelAttr) {
504
+ if (missingPropInitialValue) {
505
+ return {
506
+ expression: createMissingPropExpression(missingPropInitialValue),
507
+ setExpression: (nextExpression) => {
508
+ attributes.push(createJsxExpressionAttribute(key, nextExpression));
509
+ },
510
+ };
511
+ }
284
512
  throw new Error(`Cannot update keyframes: "${key}" is not set`);
285
513
  }
286
514
  const expression = getExpressionFromJsxAttribute(topLevelAttr);
@@ -298,6 +526,18 @@ const getSequenceWritableProp = ({ attributes, key, }) => {
298
526
  const childKey = key.slice(dotIndex + 1);
299
527
  const { attr: parentAttr } = findJsxAttribute(attributes, parentKey);
300
528
  if (!parentAttr) {
529
+ if (missingPropInitialValue) {
530
+ return {
531
+ expression: createMissingPropExpression(missingPropInitialValue),
532
+ setExpression: (nextExpression) => {
533
+ attributes.push(createObjectExpressionAttribute({
534
+ parentKey,
535
+ childKey,
536
+ expression: nextExpression,
537
+ }));
538
+ },
539
+ };
540
+ }
301
541
  throw new Error(`Cannot update keyframes: "${parentKey}" is not set`);
302
542
  }
303
543
  const objExpr = getObjectExpression(parentAttr);
@@ -306,6 +546,14 @@ const getSequenceWritableProp = ({ attributes, key, }) => {
306
546
  }
307
547
  const { prop } = findObjectProperty(objExpr, childKey);
308
548
  if (!prop) {
549
+ if (missingPropInitialValue) {
550
+ return {
551
+ expression: createMissingPropExpression(missingPropInitialValue),
552
+ setExpression: (nextExpression) => {
553
+ objExpr.properties.push(createObjectProperty(childKey, nextExpression));
554
+ },
555
+ };
556
+ }
309
557
  throw new Error(`Cannot update keyframes: "${key}" is not set`);
310
558
  }
311
559
  return {
@@ -315,7 +563,7 @@ const getSequenceWritableProp = ({ attributes, key, }) => {
315
563
  },
316
564
  };
317
565
  };
318
- const updateSequenceKeyframesAst = ({ input, nodePath, updates, }) => {
566
+ const updateSequenceKeyframesAst = ({ input, nodePath, updates, schema, }) => {
319
567
  var _a;
320
568
  var _b;
321
569
  const ast = (0, parse_ast_1.parseAst)(input);
@@ -335,11 +583,22 @@ const updateSequenceKeyframesAst = ({ input, nodePath, updates, }) => {
335
583
  const prop = getSequenceWritableProp({
336
584
  attributes: node.attributes,
337
585
  key: update.key,
586
+ missingPropInitialValue: update.operation.type === 'add'
587
+ ? {
588
+ value: getInitialValueForMissingProp({
589
+ schema: schema !== null && schema !== void 0 ? schema : null,
590
+ key: update.key,
591
+ newValue: update.operation.value,
592
+ }),
593
+ }
594
+ : null,
338
595
  });
339
596
  oldValueStrings.push(recast.print(prop.expression).code);
340
597
  const { expression: nextExpression, introduced } = applyKeyframeOperation({
341
598
  expression: prop.expression,
599
+ key: update.key,
342
600
  operation: update.operation,
601
+ schema: schema !== null && schema !== void 0 ? schema : null,
343
602
  });
344
603
  newValueStrings.push(recast.print(nextExpression).code);
345
604
  prop.setExpression(nextExpression);
@@ -371,11 +630,12 @@ const updateSequenceKeyframesAst = ({ input, nodePath, updates, }) => {
371
630
  };
372
631
  };
373
632
  exports.updateSequenceKeyframesAst = updateSequenceKeyframesAst;
374
- const updateSequenceKeyframes = async ({ input, nodePath, updates, prettierConfigOverride, }) => {
633
+ const updateSequenceKeyframes = async ({ input, nodePath, updates, schema, prettierConfigOverride, }) => {
375
634
  const { serialized, oldValueStrings, newValueStrings, logLine, updatedNodePath, } = (0, exports.updateSequenceKeyframesAst)({
376
635
  input,
377
636
  nodePath,
378
637
  updates,
638
+ schema,
379
639
  });
380
640
  const { output, formatted } = await (0, format_file_content_1.formatFileContent)({
381
641
  input: serialized,
@@ -391,7 +651,7 @@ const updateSequenceKeyframes = async ({ input, nodePath, updates, prettierConfi
391
651
  };
392
652
  };
393
653
  exports.updateSequenceKeyframes = updateSequenceKeyframes;
394
- const updateEffectKeyframesAst = ({ input, sequenceNodePath, effectIndex, updates, }) => {
654
+ const updateEffectKeyframesAst = ({ input, sequenceNodePath, effectIndex, updates, schema, }) => {
395
655
  var _a, _b;
396
656
  var _c, _d, _e;
397
657
  const ast = (0, parse_ast_1.parseAst)(input);
@@ -426,7 +686,9 @@ const updateEffectKeyframesAst = ({ input, sequenceNodePath, effectIndex, update
426
686
  oldValueStrings.push(recast.print(prop.value).code);
427
687
  const { expression: nextExpression, introduced } = applyKeyframeOperation({
428
688
  expression: prop.value,
689
+ key: update.key,
429
690
  operation: update.operation,
691
+ schema: schema !== null && schema !== void 0 ? schema : null,
430
692
  });
431
693
  newValueStrings.push(recast.print(nextExpression).code);
432
694
  prop.value = nextExpression;
@@ -459,12 +721,13 @@ const updateEffectKeyframesAst = ({ input, sequenceNodePath, effectIndex, update
459
721
  };
460
722
  };
461
723
  exports.updateEffectKeyframesAst = updateEffectKeyframesAst;
462
- const updateEffectKeyframes = async ({ input, sequenceNodePath, effectIndex, updates, prettierConfigOverride, }) => {
724
+ const updateEffectKeyframes = async ({ input, sequenceNodePath, effectIndex, updates, schema, prettierConfigOverride, }) => {
463
725
  const { serialized, oldValueStrings, newValueStrings, logLine, effectCallee, updatedSequenceNodePath, } = (0, exports.updateEffectKeyframesAst)({
464
726
  input,
465
727
  sequenceNodePath,
466
728
  effectIndex,
467
729
  updates,
730
+ schema,
468
731
  });
469
732
  const { output, formatted } = await (0, format_file_content_1.formatFileContent)({
470
733
  input: serialized,
@@ -35,9 +35,14 @@ var __importStar = (this && this.__importStar) || (function () {
35
35
  Object.defineProperty(exports, "__esModule", { value: true });
36
36
  exports.getAstNodePath = void 0;
37
37
  const recast = __importStar(require("recast"));
38
+ const import_agnostic_node_path_1 = require("./import-agnostic-node-path");
38
39
  const getAstNodePath = (ast, nodePath) => {
40
+ const resolvedNodePath = (0, import_agnostic_node_path_1.fromImportAgnosticNodePath)({ ast, nodePath });
41
+ if (!resolvedNodePath) {
42
+ return null;
43
+ }
39
44
  let current = new recast.types.NodePath(ast);
40
- for (const segment of nodePath) {
45
+ for (const segment of resolvedNodePath) {
41
46
  current = current.get(segment);
42
47
  if (current.value === null || current.value === undefined) {
43
48
  return null;
@@ -0,0 +1,10 @@
1
+ import type { File } from '@babel/types';
2
+ import type { SequenceNodePath } from 'remotion';
3
+ export declare const toImportAgnosticNodePath: ({ ast, nodePath, }: {
4
+ ast: File;
5
+ nodePath: SequenceNodePath;
6
+ }) => SequenceNodePath;
7
+ export declare const fromImportAgnosticNodePath: ({ ast, nodePath, }: {
8
+ ast: File;
9
+ nodePath: SequenceNodePath;
10
+ }) => SequenceNodePath | null;