@remotion/studio-server 4.0.524 → 4.0.525

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 (43) hide show
  1. package/dist/codemods/add-effect.d.ts +1 -26
  2. package/dist/codemods/add-effect.js +6 -191
  3. package/dist/codemods/delete-effect.d.ts +1 -30
  4. package/dist/codemods/delete-effect.js +4 -126
  5. package/dist/codemods/duplicate-effect.d.ts +1 -26
  6. package/dist/codemods/duplicate-effect.js +4 -90
  7. package/dist/codemods/paste-effects.d.ts +9 -14
  8. package/dist/codemods/paste-effects.js +2 -170
  9. package/dist/codemods/reorder-effect.d.ts +1 -13
  10. package/dist/codemods/reorder-effect.js +2 -58
  11. package/dist/codemods/update-effect-props/update-effect-props.d.ts +2 -67
  12. package/dist/codemods/update-effect-props/update-effect-props.js +8 -312
  13. package/dist/codemods/update-keyframes/update-keyframes.js +2 -7
  14. package/dist/codemods/update-sequence-props/update-sequence-props.js +20 -58
  15. package/dist/helpers/resolve-composition-component.d.ts +2 -1
  16. package/dist/helpers/resolve-composition-component.js +13 -7
  17. package/dist/preview-server/api-routes.js +5 -0
  18. package/dist/preview-server/routes/add-keyframes.js +1 -0
  19. package/dist/preview-server/routes/apply-codemod.d.ts +19 -0
  20. package/dist/preview-server/routes/apply-codemod.js +17 -55
  21. package/dist/preview-server/routes/batch-update-keyframe-settings.js +1 -0
  22. package/dist/preview-server/routes/delete-keyframes.js +1 -0
  23. package/dist/preview-server/routes/duplicate-jsx-node.js +1 -0
  24. package/dist/preview-server/routes/insert-element.js +122 -19
  25. package/dist/preview-server/routes/insert-jsx-element.js +1 -0
  26. package/dist/preview-server/routes/install-remotion-skill.d.ts +4 -0
  27. package/dist/preview-server/routes/install-remotion-skill.js +108 -0
  28. package/dist/preview-server/routes/invalidate-bundle.d.ts +3 -0
  29. package/dist/preview-server/routes/invalidate-bundle.js +11 -0
  30. package/dist/preview-server/routes/move-keyframes.js +1 -0
  31. package/dist/preview-server/routes/save-multiple-effect-props.js +1 -0
  32. package/dist/preview-server/routes/save-sequence-props.js +1 -0
  33. package/dist/preview-server/undo-stack.d.ts +4 -2
  34. package/dist/preview-server/undo-stack.js +22 -4
  35. package/dist/preview-server/watch-ignore-next-change.d.ts +1 -0
  36. package/dist/preview-server/watch-ignore-next-change.js +20 -12
  37. package/package.json +8 -8
  38. package/dist/preview-server/routes/delete-effect-keyframe.d.ts +0 -3
  39. package/dist/preview-server/routes/delete-effect-keyframe.js +0 -89
  40. package/dist/preview-server/routes/delete-sequence-keyframe.d.ts +0 -3
  41. package/dist/preview-server/routes/delete-sequence-keyframe.js +0 -82
  42. package/dist/preview-server/routes/save-props-mutex.d.ts +0 -1
  43. package/dist/preview-server/routes/save-props-mutex.js +0 -11
@@ -3,72 +3,34 @@ Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.updateSequenceProps = exports.updateMultipleSequenceProps = exports.updateSequencePropsAst = void 0;
4
4
  const studio_codemods_1 = require("@remotion/studio-codemods");
5
5
  Object.defineProperty(exports, "updateSequencePropsAst", { enumerable: true, get: function () { return studio_codemods_1.updateSequencePropsAst; } });
6
- const format_file_content_1 = require("../format-file-content");
7
- const format_inline_content_1 = require("../format-inline-content");
8
- const updateMultipleSequenceProps = async ({ input, changes, prettierConfigOverride, ast: providedAst, }) => {
9
- const { output: unformattedOutput, results, ast, openingElementRanges, } = (0, studio_codemods_1.updateMultipleSequenceProps)({
10
- input,
11
- changes,
12
- ast: providedAst,
13
- });
14
- if (unformattedOutput === input) {
15
- return { output: input, formatted: true, results, ast };
16
- }
17
- if ((openingElementRanges === null || openingElementRanges === void 0 ? void 0 : openingElementRanges.length) === 1) {
18
- const [range] = openingElementRanges;
19
- const openingElement = unformattedOutput.slice(range.start, range.end);
20
- const formattableOpeningElement = range.selfClosing
21
- ? openingElement
22
- : openingElement.slice(0, -1) + ' />';
23
- const lineStart = unformattedOutput.lastIndexOf('\n', range.start) + 1;
24
- const linePrefix = unformattedOutput.slice(lineStart, range.start);
25
- const { formatted: formattedOpeningElement, didFormat } = await (0, format_inline_content_1.formatInlineContent)({
26
- inlineContent: formattableOpeningElement,
27
- linePrefix,
28
- endOfLine: 'lf',
6
+ const updateMultipleSequenceProps = ({ input, changes, prettierConfigOverride, ast: providedAst, }) => {
7
+ return Promise.resolve().then(() => {
8
+ const { output, results, ast } = (0, studio_codemods_1.updateMultipleSequenceProps)({
9
+ input,
10
+ changes,
11
+ ast: providedAst,
29
12
  prettierConfigOverride,
30
13
  });
31
- let finalOpeningElement = formattedOpeningElement;
32
- if (!range.selfClosing) {
33
- const slashIndex = finalOpeningElement.lastIndexOf('/>');
34
- if (slashIndex !== finalOpeningElement.length - 2) {
35
- throw new Error('Could not format JSX opening element');
36
- }
37
- const lastLineStart = finalOpeningElement.lastIndexOf('\n') + 1;
38
- const beforeSlash = finalOpeningElement.slice(lastLineStart, slashIndex);
39
- finalOpeningElement =
40
- beforeSlash.trim().length === 0
41
- ? finalOpeningElement.slice(0, slashIndex) + '>'
42
- : finalOpeningElement.slice(0, slashIndex).trimEnd() + '>';
43
- }
44
- return {
45
- output: unformattedOutput.slice(0, range.start) +
46
- finalOpeningElement +
47
- unformattedOutput.slice(range.end),
48
- formatted: didFormat,
49
- results,
50
- ast,
51
- };
52
- }
53
- const { output, formatted } = await (0, format_file_content_1.formatFileContent)({
54
- input: unformattedOutput,
55
- prettierConfigOverride,
14
+ return { output, formatted: true, results, ast };
56
15
  });
57
- return { output, formatted, results, ast };
58
16
  };
59
17
  exports.updateMultipleSequenceProps = updateMultipleSequenceProps;
60
18
  const updateSequenceProps = async ({ input, nodePath, updates, schema, prettierConfigOverride, videoConfigValues, }) => {
61
- const { serialized, oldValueStrings, logLine, removedProps } = (0, studio_codemods_1.updateSequencePropsAst)({
19
+ const { output, results } = await (0, exports.updateMultipleSequenceProps)({
62
20
  input,
63
- nodePath,
64
- updates,
65
- schema,
66
- videoConfigValues,
67
- });
68
- const { output, formatted } = await (0, format_file_content_1.formatFileContent)({
69
- input: serialized,
21
+ changes: [{ nodePath, updates, schema, videoConfigValues }],
70
22
  prettierConfigOverride,
71
23
  });
72
- return { output, oldValueStrings, formatted, logLine, removedProps };
24
+ const result = results[0];
25
+ if (!result) {
26
+ throw new Error('Expected sequence prop update result');
27
+ }
28
+ return {
29
+ output,
30
+ oldValueStrings: result.oldValueStrings,
31
+ formatted: true,
32
+ logLine: result.logLine,
33
+ removedProps: result.removedProps,
34
+ };
73
35
  };
74
36
  exports.updateSequenceProps = updateSequenceProps;
@@ -12,7 +12,7 @@ export declare const resolveCompositionComponent: ({ remotionRoot, compositionFi
12
12
  compositionFile: string;
13
13
  compositionId: string;
14
14
  }) => Promise<ResolvedCompositionComponent>;
15
- export declare const insertJsxElementIntoComposition: ({ remotionRoot, compositionFile, compositionId, element, from, prettierConfigOverride, wrapInSequence, }: {
15
+ export declare const insertJsxElementIntoComposition: ({ remotionRoot, compositionFile, compositionId, element, from, prettierConfigOverride, wrapInSequence, sourceFileOverrides, }: {
16
16
  remotionRoot: string;
17
17
  compositionFile: string;
18
18
  compositionId: string;
@@ -29,6 +29,7 @@ export declare const insertJsxElementIntoComposition: ({ remotionRoot, compositi
29
29
  name: string | null;
30
30
  position: InsertableCompositionElementPosition | null;
31
31
  } | null | undefined;
32
+ sourceFileOverrides: ReadonlyMap<string, string> | null;
32
33
  }) => Promise<{
33
34
  fileName: string;
34
35
  source: string;
@@ -8,14 +8,20 @@ const node_fs_1 = __importDefault(require("node:fs"));
8
8
  const node_path_1 = __importDefault(require("node:path"));
9
9
  const studio_codemods_1 = require("@remotion/studio-codemods");
10
10
  const svg_to_jsx_1 = require("./svg-to-jsx");
11
- const makeCodemodEnvironment = (remotionRoot) => ({
11
+ const makeCodemodEnvironment = (remotionRoot, sourceFileOverrides) => ({
12
12
  dirname: node_path_1.default.dirname,
13
13
  extname: node_path_1.default.extname,
14
- fileExists: (fileName) => node_fs_1.default.existsSync(fileName) && node_fs_1.default.statSync(fileName).isFile(),
14
+ fileExists: (fileName) => (sourceFileOverrides === null || sourceFileOverrides === void 0 ? void 0 : sourceFileOverrides.has(node_path_1.default.resolve(fileName))) === true ||
15
+ (node_fs_1.default.existsSync(fileName) && node_fs_1.default.statSync(fileName).isFile()),
15
16
  isAbsolute: node_path_1.default.isAbsolute,
16
17
  join: node_path_1.default.join,
17
18
  pathSeparator: node_path_1.default.sep,
18
- readFile: (fileName) => node_fs_1.default.promises.readFile(fileName, 'utf-8'),
19
+ readFile: (fileName) => {
20
+ const override = sourceFileOverrides === null || sourceFileOverrides === void 0 ? void 0 : sourceFileOverrides.get(node_path_1.default.resolve(fileName));
21
+ return override === undefined
22
+ ? node_fs_1.default.promises.readFile(fileName, 'utf-8')
23
+ : Promise.resolve(override);
24
+ },
19
25
  relative: node_path_1.default.relative,
20
26
  resolve: node_path_1.default.resolve,
21
27
  rootDir: remotionRoot,
@@ -24,22 +30,22 @@ const makeCodemodEnvironment = (remotionRoot) => ({
24
30
  const resolveCompositionComponentWithFile = ({ remotionRoot, compositionFile, compositionId, }) => (0, studio_codemods_1.resolveCompositionComponentWithFile)({
25
31
  compositionFile,
26
32
  compositionId,
27
- environment: makeCodemodEnvironment(remotionRoot),
33
+ environment: makeCodemodEnvironment(remotionRoot, null),
28
34
  });
29
35
  exports.resolveCompositionComponentWithFile = resolveCompositionComponentWithFile;
30
36
  const resolveCompositionComponent = ({ remotionRoot, compositionFile, compositionId, }) => (0, studio_codemods_1.resolveCompositionComponent)({
31
37
  compositionFile,
32
38
  compositionId,
33
- environment: makeCodemodEnvironment(remotionRoot),
39
+ environment: makeCodemodEnvironment(remotionRoot, null),
34
40
  });
35
41
  exports.resolveCompositionComponent = resolveCompositionComponent;
36
- const insertJsxElementIntoComposition = ({ remotionRoot, compositionFile, compositionId, element, from, prettierConfigOverride, wrapInSequence = null, }) => {
42
+ const insertJsxElementIntoComposition = ({ remotionRoot, compositionFile, compositionId, element, from, prettierConfigOverride, wrapInSequence = null, sourceFileOverrides, }) => {
37
43
  var _a;
38
44
  return (0, studio_codemods_1.insertJsxElementIntoComposition)({
39
45
  compositionFile,
40
46
  compositionId,
41
47
  element,
42
- environment: makeCodemodEnvironment(remotionRoot),
48
+ environment: makeCodemodEnvironment(remotionRoot, sourceFileOverrides),
43
49
  from,
44
50
  prettierConfigOverride,
45
51
  wrapInSequence: wrapInSequence === null
@@ -25,6 +25,8 @@ const duplicate_jsx_node_1 = require("./routes/duplicate-jsx-node");
25
25
  const find_in_file_1 = require("./routes/find-in-file");
26
26
  const insert_element_1 = require("./routes/insert-element");
27
27
  const insert_jsx_element_1 = require("./routes/insert-jsx-element");
28
+ const install_remotion_skill_1 = require("./routes/install-remotion-skill");
29
+ const invalidate_bundle_1 = require("./routes/invalidate-bundle");
28
30
  const log_studio_error_1 = require("./routes/log-studio-error");
29
31
  const move_keyframes_1 = require("./routes/move-keyframes");
30
32
  const open_in_editor_1 = require("./routes/open-in-editor");
@@ -64,6 +66,7 @@ const update_element_install_target_1 = require("./routes/update-element-install
64
66
  const update_sequence_keyframe_settings_1 = require("./routes/update-sequence-keyframe-settings");
65
67
  const upgrade_remotion_1 = require("./routes/upgrade-remotion");
66
68
  exports.allApiRoutes = {
69
+ '/api/invalidate-bundle': invalidate_bundle_1.invalidateBundleHandler,
67
70
  '/api/composition-component-info': composition_component_info_1.compositionComponentInfoHandler,
68
71
  '/api/copy-render-output-to-asset': copy_render_output_to_asset_1.copyRenderOutputToAssetHandler,
69
72
  '/api/convert-figma-clipboard-to-svg': convert_figma_clipboard_to_svg_1.convertFigmaClipboardToSvgHandler,
@@ -111,6 +114,8 @@ exports.allApiRoutes = {
111
114
  '/api/update-available': update_available_1.handleUpdate,
112
115
  '/api/release-notes': release_notes_1.getReleaseNotesHandler,
113
116
  '/api/remotion-skills-info': remotion_skills_info_1.remotionSkillsInfoHandler,
117
+ '/api/install-remotion-skill': install_remotion_skill_1.installRemotionSkillHandler,
118
+ '/api/remove-remotion-skill': install_remotion_skill_1.removeRemotionSkillHandler,
114
119
  '/api/project-info': project_info_1.projectInfoHandler,
115
120
  '/api/delete-static-file': delete_static_file_1.deleteStaticFileHandler,
116
121
  '/api/rename-static-file': rename_static_file_1.renameStaticFileHandler,
@@ -179,6 +179,7 @@ const addKeyframes = async ({ sequenceKeyframes, effectKeyframes, clientId, remo
179
179
  ? 'sequence-props'
180
180
  : 'effect-props',
181
181
  suppressHmrOnFileRestore: true,
182
+ undoRedoNavigation: null,
182
183
  });
183
184
  for (const snapshot of snapshots) {
184
185
  (0, undo_stack_1.suppressUndoStackInvalidation)(snapshot.filePath);
@@ -1,4 +1,23 @@
1
1
  import type { ApplyCodemodRequest, ApplyCodemodResponse } from '@remotion/studio-shared';
2
2
  import type { ApiHandler } from '../api-types';
3
+ export declare const formatNewCompositionFile: (codemod: {
4
+ type: "new-composition";
5
+ newId: string;
6
+ componentName: string;
7
+ componentImportPath: string;
8
+ folderName: string | null;
9
+ parentName: string | null;
10
+ newHeight: number;
11
+ newWidth: number;
12
+ newFps: number;
13
+ newDurationInFrames: number;
14
+ canvasCapture: {
15
+ readonly videoFileName: string;
16
+ readonly videoHeight: number;
17
+ readonly videoWidth: number;
18
+ readonly keyframeFps: number;
19
+ readonly data: import("@remotion/studio-shared").CanvasCaptureData;
20
+ } | null;
21
+ }) => string;
3
22
  export declare const getCodemodLogMessage: (codemod: import("@remotion/studio-shared").RecastCodemod) => string;
4
23
  export declare const applyCodemodHandler: ApiHandler<ApplyCodemodRequest, ApplyCodemodResponse>;
@@ -3,12 +3,11 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
3
3
  return (mod && mod.__esModule) ? mod : { "default": mod };
4
4
  };
5
5
  Object.defineProperty(exports, "__esModule", { value: true });
6
- exports.applyCodemodHandler = exports.getCodemodLogMessage = void 0;
6
+ exports.applyCodemodHandler = exports.getCodemodLogMessage = exports.formatNewCompositionFile = void 0;
7
7
  const node_fs_1 = require("node:fs");
8
8
  const node_path_1 = __importDefault(require("node:path"));
9
9
  const renderer_1 = require("@remotion/renderer");
10
10
  const studio_codemods_1 = require("@remotion/studio-codemods");
11
- const generate_canvas_capture_composition_1 = require("../../canvas-capture/generate-canvas-capture-composition");
12
11
  const apply_codemod_to_file_1 = require("../../codemods/apply-codemod-to-file");
13
12
  const file_watcher_1 = require("../../file-watcher");
14
13
  const format_log_file_location_1 = require("../format-log-file-location");
@@ -16,29 +15,8 @@ const project_info_1 = require("../project-info");
16
15
  const undo_stack_1 = require("../undo-stack");
17
16
  const can_update_default_props_1 = require("./can-update-default-props");
18
17
  const source_file_write_queue_1 = require("./source-file-write-queue");
19
- const formatNewCompositionFile = (codemod) => {
20
- if (codemod.canvasCapture !== null) {
21
- return (0, generate_canvas_capture_composition_1.generateCanvasCaptureComposition)({
22
- componentName: codemod.componentName,
23
- compositionId: codemod.newId,
24
- data: codemod.canvasCapture.data,
25
- durationInFrames: codemod.newDurationInFrames,
26
- fps: codemod.newFps,
27
- height: codemod.newHeight,
28
- keyframeFps: codemod.canvasCapture.keyframeFps,
29
- videoFileName: codemod.canvasCapture.videoFileName,
30
- videoHeight: codemod.canvasCapture.videoHeight,
31
- videoWidth: codemod.canvasCapture.videoWidth,
32
- width: codemod.newWidth,
33
- });
34
- }
35
- return `import React from 'react';
36
-
37
- export const ${codemod.componentName}: React.FC = () => {
38
- return null;
39
- };
40
- `;
41
- };
18
+ const formatNewCompositionFile = (codemod) => (0, studio_codemods_1.makeNewCompositionComponentSource)(codemod);
19
+ exports.formatNewCompositionFile = formatNewCompositionFile;
42
20
  const getFolderPath = (parentName, folderName) => {
43
21
  return parentName ? `${parentName}/${folderName}` : folderName;
44
22
  };
@@ -184,7 +162,7 @@ const getCodemodUndoDescription = (codemod) => {
184
162
  entryType: 'visual-control',
185
163
  };
186
164
  };
187
- const applyCodemodHandler = ({ input: { codemod, dryRun, symbolicatedStack }, logLevel, remotionRoot, entryPoint, }) => {
165
+ const applyCodemodHandler = ({ input: { codemod, dryRun, symbolicatedStack, undoRedoNavigation }, logLevel, remotionRoot, entryPoint, }) => {
188
166
  return (0, source_file_write_queue_1.withSourceFileWriteQueue)(async () => {
189
167
  var _a;
190
168
  try {
@@ -231,7 +209,7 @@ const applyCodemodHandler = ({ input: { codemod, dryRun, symbolicatedStack }, lo
231
209
  if (componentFilePath === null) {
232
210
  throw new Error('Could not determine the new component file path');
233
211
  }
234
- componentFileContents = await formatNewCompositionFile(codemod);
212
+ componentFileContents = await (0, exports.formatNewCompositionFile)(codemod);
235
213
  snapshots.push({
236
214
  filePath: componentFilePath,
237
215
  oldContents: null,
@@ -239,35 +217,19 @@ const applyCodemodHandler = ({ input: { codemod, dryRun, symbolicatedStack }, lo
239
217
  logLine: 1,
240
218
  nodePathRemappings: null,
241
219
  });
242
- (0, undo_stack_1.pushTransactionToUndoStack)({
243
- snapshots,
244
- logLevel,
245
- remotionRoot,
246
- description: {
247
- undoMessage,
248
- redoMessage,
249
- },
250
- entryType,
251
- suppressHmrOnFileRestore: false,
252
- });
253
- }
254
- else {
255
- (0, undo_stack_1.pushToUndoStack)({
256
- filePath,
257
- oldContents: input,
258
- newContents: null,
259
- logLevel,
260
- remotionRoot,
261
- logLine,
262
- description: {
263
- undoMessage,
264
- redoMessage,
265
- },
266
- entryType,
267
- suppressHmrOnFileRestore: false,
268
- nodePathRemappings: null,
269
- });
270
220
  }
221
+ (0, undo_stack_1.pushTransactionToUndoStack)({
222
+ snapshots,
223
+ logLevel,
224
+ remotionRoot,
225
+ description: {
226
+ undoMessage,
227
+ redoMessage,
228
+ },
229
+ entryType,
230
+ suppressHmrOnFileRestore: false,
231
+ undoRedoNavigation,
232
+ });
271
233
  (0, undo_stack_1.suppressUndoStackInvalidation)(filePath);
272
234
  if (componentFilePath) {
273
235
  (0, undo_stack_1.suppressUndoStackInvalidation)(componentFilePath);
@@ -151,6 +151,7 @@ const batchUpdateKeyframeSettings = async ({ sequenceKeyframes, effectKeyframes,
151
151
  },
152
152
  entryType: sequenceKeyframes.length > 0 ? 'sequence-props' : 'effect-props',
153
153
  suppressHmrOnFileRestore: true,
154
+ undoRedoNavigation: null,
154
155
  });
155
156
  for (const snapshot of snapshots) {
156
157
  (0, undo_stack_1.suppressUndoStackInvalidation)(snapshot.filePath);
@@ -186,6 +186,7 @@ const deleteKeyframes = async ({ sequenceKeyframes, effectKeyframes, clientId, r
186
186
  ? 'sequence-props'
187
187
  : 'effect-props',
188
188
  suppressHmrOnFileRestore: true,
189
+ undoRedoNavigation: null,
189
190
  });
190
191
  for (const snapshot of snapshots) {
191
192
  (0, undo_stack_1.suppressUndoStackInvalidation)(snapshot.filePath);
@@ -70,6 +70,7 @@ const duplicateJsxNodeHandler = ({ input: { nodes }, remotionRoot, logLevel }) =
70
70
  },
71
71
  entryType: 'duplicate-jsx-node',
72
72
  suppressHmrOnFileRestore: false,
73
+ undoRedoNavigation: null,
73
74
  });
74
75
  for (const update of updates) {
75
76
  (0, undo_stack_1.suppressUndoStackInvalidation)(update.absolutePath);
@@ -1,12 +1,21 @@
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.insertElementHandler = void 0;
7
+ const node_fs_1 = require("node:fs");
8
+ const node_path_1 = __importDefault(require("node:path"));
4
9
  const renderer_1 = require("@remotion/renderer");
10
+ const apply_codemod_to_file_1 = require("../../codemods/apply-codemod-to-file");
5
11
  const file_watcher_1 = require("../../file-watcher");
6
12
  const resolve_composition_component_1 = require("../../helpers/resolve-composition-component");
7
13
  const format_log_file_location_1 = require("../format-log-file-location");
14
+ const project_info_1 = require("../project-info");
8
15
  const sequence_node_path_mutation_1 = require("../sequence-node-path-mutation");
9
16
  const undo_stack_1 = require("../undo-stack");
17
+ const apply_codemod_1 = require("./apply-codemod");
18
+ const can_update_default_props_1 = require("./can-update-default-props");
10
19
  const element_install_plan_1 = require("./element-install-plan");
11
20
  const source_file_write_queue_1 = require("./source-file-write-queue");
12
21
  const hasExpectedFileState = ({ expected, actual, }) => {
@@ -21,9 +30,9 @@ const hasExpectedFileState = ({ expected, actual, }) => {
21
30
  }
22
31
  return actual.sourceHash === expected.sourceHash;
23
32
  };
24
- const insertElementHandler = ({ input: { compositionFile, compositionId, element, installationName, expectedFileState, from, position, overwriteExisting, }, entryPoint, remotionRoot, logLevel, }) => (0, source_file_write_queue_1.withSourceFileWriteQueue)(async () => {
25
- var _a;
26
- var _b;
33
+ const insertElementHandler = ({ input: { compositionFile, compositionId, element, installationName, expectedFileState, from, position, overwriteExisting, undoRedoNavigation, newComposition, }, entryPoint, remotionRoot, logLevel, }) => (0, source_file_write_queue_1.withSourceFileWriteQueue)(async () => {
34
+ var _a, _b, _c;
35
+ var _d, _e, _f;
27
36
  try {
28
37
  (0, element_install_plan_1.validateElementInstallPosition)(position);
29
38
  if (from !== null &&
@@ -50,13 +59,57 @@ const insertElementHandler = ({ input: { compositionFile, compositionId, element
50
59
  throw new Error('Component-owned Element initial style must be an object');
51
60
  }
52
61
  renderer_1.RenderInternals.Log.trace({ indent: false, logLevel }, `[insert-element] Received request for compositionFile="${compositionFile}" compositionId="${compositionId}" element="${element.slug}"`);
53
- const plan = await (0, element_install_plan_1.getElementInstallPlan)({
54
- installationName,
55
- destination: {
62
+ let compositionCreation = null;
63
+ let sourceFileOverrides = null;
64
+ if (newComposition !== null) {
65
+ if (newComposition.codemod.newId !== compositionId) {
66
+ throw new Error('New composition ID does not match installation target');
67
+ }
68
+ const registrationFilePath = newComposition.symbolicatedStack
69
+ ? (0, apply_codemod_to_file_1.resolveFilePathFromSymbolicatedStack)(remotionRoot, newComposition.symbolicatedStack)
70
+ : (await (0, project_info_1.getProjectInfo)(remotionRoot, entryPoint)).rootFile;
71
+ if (registrationFilePath === null) {
72
+ throw new Error('Cannot find file for composition in project');
73
+ }
74
+ (0, can_update_default_props_1.checkIfTypeScriptFile)(registrationFilePath);
75
+ if (node_path_1.default.resolve(remotionRoot, compositionFile) !== registrationFilePath) {
76
+ throw new Error('New composition source does not match installation target');
77
+ }
78
+ const componentFilePath = node_path_1.default.join(node_path_1.default.dirname(registrationFilePath), `${newComposition.codemod.componentName}.tsx`);
79
+ if ((0, node_fs_1.existsSync)(componentFilePath)) {
80
+ throw new Error(`Cannot create ${node_path_1.default.relative(remotionRoot, componentFilePath)} because it already exists`);
81
+ }
82
+ const registrationFileOldContents = (0, node_fs_1.readFileSync)(registrationFilePath, 'utf-8');
83
+ const registrationFileNewContents = await (0, apply_codemod_to_file_1.applyCodemodToFile)({
84
+ filePath: registrationFilePath,
85
+ codeMod: newComposition.codemod,
86
+ });
87
+ const componentFileContents = await (0, apply_codemod_1.formatNewCompositionFile)(newComposition.codemod);
88
+ compositionCreation = {
89
+ componentFileContents,
90
+ componentFilePath,
91
+ registrationFileNewContents,
92
+ registrationFileOldContents,
93
+ registrationFilePath,
94
+ };
95
+ sourceFileOverrides = new Map([
96
+ [registrationFilePath, registrationFileNewContents],
97
+ [componentFilePath, componentFileContents],
98
+ ]);
99
+ }
100
+ const installDestination = newComposition === null
101
+ ? {
56
102
  type: 'current-composition',
57
103
  compositionFile,
58
104
  compositionId,
59
- },
105
+ }
106
+ : {
107
+ type: 'new-composition',
108
+ compositionFile,
109
+ };
110
+ const plan = await (0, element_install_plan_1.getElementInstallPlan)({
111
+ installationName,
112
+ destination: installDestination,
60
113
  element,
61
114
  entryPoint,
62
115
  remotionRoot,
@@ -93,8 +146,13 @@ const insertElementHandler = ({ input: { compositionFile, compositionId, element
93
146
  },
94
147
  };
95
148
  }
149
+ if (compositionCreation !== null &&
150
+ plan.elementFileName ===
151
+ node_path_1.default.join(node_path_1.default.dirname(plan.safePaths.compositionFileName), node_path_1.default.basename(compositionCreation.componentFilePath))) {
152
+ throw new Error('Element source file conflicts with the new composition file');
153
+ }
96
154
  const shouldWriteElementFile = !plan.elementFileExists || elementSourcesDiffer;
97
- const inserted = await (0, resolve_composition_component_1.insertJsxElementIntoComposition)({
155
+ const insertionInput = {
98
156
  remotionRoot,
99
157
  compositionFile,
100
158
  compositionId,
@@ -104,7 +162,7 @@ const insertElementHandler = ({ input: { compositionFile, compositionId, element
104
162
  importName: plan.componentName,
105
163
  importPath: plan.importPath,
106
164
  props: [
107
- ...Object.entries((_b = element.initialProps) !== null && _b !== void 0 ? _b : {}).map(([name, value]) => ({ name, value })),
165
+ ...Object.entries((_d = element.initialProps) !== null && _d !== void 0 ? _d : {}).map(([name, value]) => ({ name, value })),
108
166
  ...(componentOwnsSequence && element.durationInFrames !== null
109
167
  ? [
110
168
  {
@@ -130,14 +188,18 @@ const insertElementHandler = ({ input: { compositionFile, compositionId, element
130
188
  name: element.displayName,
131
189
  position,
132
190
  },
191
+ };
192
+ const inserted = await (0, resolve_composition_component_1.insertJsxElementIntoComposition)({
193
+ ...insertionInput,
194
+ sourceFileOverrides,
133
195
  });
196
+ if (compositionCreation !== null &&
197
+ inserted.fileName !== compositionCreation.componentFilePath) {
198
+ throw new Error('New composition component does not match installation target');
199
+ }
134
200
  const finalPlan = await (0, element_install_plan_1.getElementInstallPlan)({
135
201
  installationName,
136
- destination: {
137
- type: 'current-composition',
138
- compositionFile,
139
- compositionId,
140
- },
202
+ destination: installDestination,
141
203
  element,
142
204
  entryPoint,
143
205
  remotionRoot,
@@ -152,6 +214,12 @@ const insertElementHandler = ({ input: { compositionFile, compositionId, element
152
214
  })) {
153
215
  throw new Error('Element source changed during installation');
154
216
  }
217
+ if (compositionCreation !== null &&
218
+ ((0, node_fs_1.readFileSync)(compositionCreation.registrationFilePath, 'utf-8') !==
219
+ compositionCreation.registrationFileOldContents ||
220
+ (0, node_fs_1.existsSync)(compositionCreation.componentFilePath))) {
221
+ throw new Error('Composition source changed during Element installation');
222
+ }
155
223
  const nodePathMutation = (0, sequence_node_path_mutation_1.broadcastSequenceNodePathMutation)([
156
224
  {
157
225
  absolutePath: inserted.fileName,
@@ -160,6 +228,17 @@ const insertElementHandler = ({ input: { compositionFile, compositionId, element
160
228
  ], null);
161
229
  (0, undo_stack_1.pushTransactionToUndoStack)({
162
230
  snapshots: [
231
+ ...(compositionCreation === null
232
+ ? []
233
+ : [
234
+ {
235
+ filePath: compositionCreation.registrationFilePath,
236
+ oldContents: compositionCreation.registrationFileOldContents,
237
+ newContents: compositionCreation.registrationFileNewContents,
238
+ logLine: (_e = (_b = newComposition === null || newComposition === void 0 ? void 0 : newComposition.symbolicatedStack) === null || _b === void 0 ? void 0 : _b.originalLineNumber) !== null && _e !== void 0 ? _e : 1,
239
+ nodePathRemappings: null,
240
+ },
241
+ ]),
163
242
  ...(shouldWriteElementFile
164
243
  ? [
165
244
  {
@@ -173,7 +252,7 @@ const insertElementHandler = ({ input: { compositionFile, compositionId, element
173
252
  : []),
174
253
  {
175
254
  filePath: inserted.fileName,
176
- oldContents: inserted.oldContents,
255
+ oldContents: compositionCreation === null ? inserted.oldContents : null,
177
256
  newContents: inserted.output,
178
257
  logLine: inserted.logLine,
179
258
  nodePathRemappings: inserted.nodePathRemappings,
@@ -181,17 +260,34 @@ const insertElementHandler = ({ input: { compositionFile, compositionId, element
181
260
  ],
182
261
  logLevel,
183
262
  remotionRoot,
184
- description: {
185
- undoMessage: `↩️ Added ${element.displayName}`,
186
- redoMessage: `↪️ Added ${element.displayName}`,
187
- },
263
+ description: newComposition === null
264
+ ? {
265
+ undoMessage: `↩️ Added ${element.displayName}`,
266
+ redoMessage: `↪️ Added ${element.displayName}`,
267
+ }
268
+ : {
269
+ undoMessage: `↩️ Installation of ${element.displayName} into composition "${compositionId}"`,
270
+ redoMessage: `↪️ Installation of ${element.displayName} into composition "${compositionId}"`,
271
+ },
188
272
  entryType: 'insert-jsx-element',
189
273
  suppressHmrOnFileRestore: false,
274
+ undoRedoNavigation,
190
275
  });
276
+ if (compositionCreation !== null) {
277
+ (0, undo_stack_1.suppressUndoStackInvalidation)(compositionCreation.registrationFilePath);
278
+ }
191
279
  if (shouldWriteElementFile) {
192
280
  (0, undo_stack_1.suppressUndoStackInvalidation)(plan.elementFileName);
193
281
  }
194
282
  (0, undo_stack_1.suppressUndoStackInvalidation)(inserted.fileName);
283
+ if (compositionCreation !== null) {
284
+ (0, file_watcher_1.writeFileAndNotifyFileWatchers)({
285
+ file: compositionCreation.registrationFilePath,
286
+ content: compositionCreation.registrationFileNewContents,
287
+ originatorClientId: undefined,
288
+ metadata: null,
289
+ });
290
+ }
195
291
  if (shouldWriteElementFile) {
196
292
  (0, file_watcher_1.writeFileAndNotifyFileWatchers)({
197
293
  file: plan.elementFileName,
@@ -206,6 +302,13 @@ const insertElementHandler = ({ input: { compositionFile, compositionId, element
206
302
  originatorClientId: undefined,
207
303
  metadata: { skipSequencePropsUpdate: true },
208
304
  });
305
+ if (newComposition !== null && compositionCreation !== null) {
306
+ renderer_1.RenderInternals.Log.info({ indent: false, logLevel }, `${(0, source_file_write_queue_1.getCodemodTimingPrefix)(logLevel)}${renderer_1.RenderInternals.chalk.blueBright((0, format_log_file_location_1.formatLogFileLocation)({
307
+ remotionRoot,
308
+ absolutePath: compositionCreation.registrationFilePath,
309
+ line: (_f = (_c = newComposition.symbolicatedStack) === null || _c === void 0 ? void 0 : _c.originalLineNumber) !== null && _f !== void 0 ? _f : 1,
310
+ }))} Created composition "${compositionId}"`);
311
+ }
209
312
  const compositionLocationLabel = (0, format_log_file_location_1.formatLogFileLocation)({
210
313
  remotionRoot,
211
314
  absolutePath: inserted.fileName,
@@ -165,6 +165,7 @@ const insertJsxElementHandler = ({ input: { compositionFile, compositionId, elem
165
165
  element,
166
166
  from,
167
167
  prettierConfigOverride: null,
168
+ sourceFileOverrides: null,
168
169
  });
169
170
  const nodePathMutation = (0, sequence_node_path_mutation_1.broadcastSequenceNodePathMutation)([
170
171
  {
@@ -0,0 +1,4 @@
1
+ import type { GetRemotionSkillsInfoResponse, InstallRemotionSkillRequest, RemoveRemotionSkillRequest } from '@remotion/studio-shared';
2
+ import type { ApiHandler } from '../api-types';
3
+ export declare const installRemotionSkillHandler: ApiHandler<InstallRemotionSkillRequest, GetRemotionSkillsInfoResponse>;
4
+ export declare const removeRemotionSkillHandler: ApiHandler<RemoveRemotionSkillRequest, GetRemotionSkillsInfoResponse>;