@remotion/studio-server 4.0.529 → 4.0.531

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 (109) hide show
  1. package/dist/canvas-capture/generate-canvas-capture-composition.d.ts +14 -0
  2. package/dist/canvas-capture/generate-canvas-capture-composition.js +239 -0
  3. package/dist/codemods/add-composition-to-file.d.ts +7 -0
  4. package/dist/codemods/add-composition-to-file.js +63 -0
  5. package/dist/codemods/add-effect.d.ts +1 -0
  6. package/dist/codemods/add-effect.js +8 -0
  7. package/dist/codemods/apply-codemod-to-file.js +6 -1
  8. package/dist/codemods/apply-visual-control.d.ts +8 -0
  9. package/dist/codemods/apply-visual-control.js +89 -0
  10. package/dist/codemods/delete-effect.d.ts +1 -0
  11. package/dist/codemods/delete-effect.js +6 -0
  12. package/dist/codemods/delete-jsx-node.d.ts +22 -0
  13. package/dist/codemods/delete-jsx-node.js +17 -0
  14. package/dist/codemods/duplicate-composition.d.ts +2 -0
  15. package/dist/codemods/duplicate-composition.js +64 -0
  16. package/dist/codemods/duplicate-effect.d.ts +1 -0
  17. package/dist/codemods/duplicate-effect.js +6 -0
  18. package/dist/codemods/duplicate-jsx-node.d.ts +25 -0
  19. package/dist/codemods/duplicate-jsx-node.js +26 -0
  20. package/dist/codemods/format-file-content.d.ts +7 -0
  21. package/dist/codemods/format-file-content.js +80 -0
  22. package/dist/codemods/format-inline-content.d.ts +18 -0
  23. package/dist/codemods/format-inline-content.js +78 -0
  24. package/dist/codemods/insert-video-layers.d.ts +11 -0
  25. package/dist/codemods/insert-video-layers.js +5 -0
  26. package/dist/codemods/recast-mods.d.ts +13 -0
  27. package/dist/codemods/recast-mods.js +902 -0
  28. package/dist/codemods/reorder-effect.d.ts +1 -0
  29. package/dist/codemods/reorder-effect.js +5 -0
  30. package/dist/codemods/reorder-sequence.d.ts +1 -0
  31. package/dist/codemods/reorder-sequence.js +5 -0
  32. package/dist/codemods/simple-diff.d.ts +5 -0
  33. package/dist/codemods/simple-diff.js +39 -0
  34. package/dist/codemods/split-video-from-audio.d.ts +1 -0
  35. package/dist/codemods/split-video-from-audio.js +5 -0
  36. package/dist/codemods/update-default-props.d.ts +1 -0
  37. package/dist/codemods/update-default-props.js +6 -0
  38. package/dist/codemods/update-inline-caption-patches.d.ts +1 -0
  39. package/dist/codemods/update-inline-caption-patches.js +5 -0
  40. package/dist/codemods/update-keyframes/ensure-imports-and-frame-hook.d.ts +1 -0
  41. package/dist/codemods/update-keyframes/ensure-imports-and-frame-hook.js +7 -0
  42. package/dist/codemods/update-keyframes/update-keyframes.d.ts +3 -3
  43. package/dist/codemods/update-keyframes/update-keyframes.js +1 -1
  44. package/dist/codemods/update-sequence-props/update-sequence-props.js +1 -1
  45. package/dist/helpers/get-file-source.js +6 -4
  46. package/dist/helpers/get-local-package-override.d.ts +5 -0
  47. package/dist/helpers/get-local-package-override.js +39 -0
  48. package/dist/helpers/install-command.js +1 -0
  49. package/dist/helpers/resolve-composition-component.d.ts +2 -1
  50. package/dist/helpers/resolve-composition-component.js +66 -15
  51. package/dist/index.d.ts +5 -0
  52. package/dist/index.js +3 -0
  53. package/dist/open-directory-in-finder.js +11 -9
  54. package/dist/preview-server/api-routes.js +32 -12
  55. package/dist/preview-server/element-install-state.js +10 -2
  56. package/dist/preview-server/routes/add-composition.d.ts +3 -0
  57. package/dist/preview-server/routes/add-composition.js +97 -0
  58. package/dist/preview-server/routes/add-folder.d.ts +3 -0
  59. package/dist/preview-server/routes/add-folder.js +107 -0
  60. package/dist/preview-server/routes/add-keyframes.d.ts +2 -2
  61. package/dist/preview-server/routes/add-keyframes.js +49 -6
  62. package/dist/preview-server/routes/can-update-sequence-props.js +27 -5
  63. package/dist/preview-server/routes/delete-composition.d.ts +3 -0
  64. package/dist/preview-server/routes/delete-composition.js +104 -0
  65. package/dist/preview-server/routes/delete-jsx-node.d.ts +3 -0
  66. package/dist/preview-server/routes/delete-jsx-node.js +126 -0
  67. package/dist/preview-server/routes/delete-nodes.d.ts +3 -0
  68. package/dist/preview-server/routes/delete-nodes.js +142 -0
  69. package/dist/preview-server/routes/duplicate-composition.d.ts +3 -0
  70. package/dist/preview-server/routes/duplicate-composition.js +114 -0
  71. package/dist/preview-server/routes/duplicate-nodes.d.ts +3 -0
  72. package/dist/preview-server/routes/duplicate-nodes.js +123 -0
  73. package/dist/preview-server/routes/insert-basic-captions.js +2 -1
  74. package/dist/preview-server/routes/insert-composition-element.d.ts +3 -0
  75. package/dist/preview-server/routes/insert-composition-element.js +236 -0
  76. package/dist/preview-server/routes/insert-element.js +26 -19
  77. package/dist/preview-server/routes/insert-video-layers.d.ts +3 -0
  78. package/dist/preview-server/routes/insert-video-layers.js +68 -0
  79. package/dist/preview-server/routes/install-dependency.js +10 -1
  80. package/dist/preview-server/routes/move-composition.d.ts +3 -0
  81. package/dist/preview-server/routes/move-composition.js +148 -0
  82. package/dist/preview-server/routes/move-folder.d.ts +3 -0
  83. package/dist/preview-server/routes/move-folder.js +151 -0
  84. package/dist/preview-server/routes/precompose-jsx-nodes.d.ts +3 -0
  85. package/dist/preview-server/routes/precompose-jsx-nodes.js +209 -0
  86. package/dist/preview-server/routes/rename-composition.d.ts +3 -0
  87. package/dist/preview-server/routes/rename-composition.js +105 -0
  88. package/dist/preview-server/routes/rename-folder.d.ts +3 -0
  89. package/dist/preview-server/routes/rename-folder.js +111 -0
  90. package/dist/preview-server/routes/reorder-sequence.js +7 -2
  91. package/dist/preview-server/routes/replace-video-source.js +7 -2
  92. package/dist/preview-server/routes/save-sequence-props.js +6 -3
  93. package/dist/preview-server/routes/split-sequences.d.ts +3 -0
  94. package/dist/preview-server/routes/split-sequences.js +122 -0
  95. package/dist/preview-server/routes/split-video-from-audio.js +6 -1
  96. package/dist/preview-server/routes/unwrap-folder.d.ts +3 -0
  97. package/dist/preview-server/routes/unwrap-folder.js +107 -0
  98. package/dist/preview-server/routes/update-composition-metadata.d.ts +3 -0
  99. package/dist/preview-server/routes/update-composition-metadata.js +110 -0
  100. package/dist/preview-server/routes/update-public-license.d.ts +11 -0
  101. package/dist/preview-server/routes/update-public-license.js +97 -0
  102. package/dist/preview-server/routes/wrap-node.d.ts +3 -0
  103. package/dist/preview-server/routes/wrap-node.js +108 -0
  104. package/dist/preview-server/studio-protocol/handle-discovery.js +3 -10
  105. package/dist/preview-server/studio-protocol/handle-install.js +0 -3
  106. package/dist/preview-server/undo-stack.d.ts +1 -1
  107. package/dist/preview-server/undo-stack.js +6 -0
  108. package/dist/start-studio.js +1 -1
  109. package/package.json +8 -8
@@ -0,0 +1,126 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.deleteJsxNodeHandler = void 0;
4
+ const node_fs_1 = require("node:fs");
5
+ const renderer_1 = require("@remotion/renderer");
6
+ const delete_jsx_node_1 = require("../../codemods/delete-jsx-node");
7
+ const file_watcher_1 = require("../../file-watcher");
8
+ const resolve_file_inside_project_1 = require("../../helpers/resolve-file-inside-project");
9
+ const format_log_file_location_1 = require("../format-log-file-location");
10
+ const hmr_timing_1 = require("../hmr-timing");
11
+ const sequence_node_path_mutation_1 = require("../sequence-node-path-mutation");
12
+ const undo_stack_1 = require("../undo-stack");
13
+ const source_file_write_queue_1 = require("./source-file-write-queue");
14
+ const getDeletedNodeDescription = (nodeLabels) => {
15
+ if (nodeLabels.length === 1) {
16
+ return nodeLabels[0];
17
+ }
18
+ return `${nodeLabels.length} JSX nodes`;
19
+ };
20
+ const deleteJsxNodeHandler = ({ input: { nodes }, remotionRoot, logLevel }) => {
21
+ return (0, source_file_write_queue_1.withSourceFileWriteQueue)(async () => {
22
+ var _a;
23
+ try {
24
+ (0, hmr_timing_1.logHmrTiming)({
25
+ detail: null,
26
+ logLevel,
27
+ stage: 'delete-jsx-node-request-start',
28
+ });
29
+ if (nodes.length === 0) {
30
+ throw new Error('No JSX nodes were specified for deletion');
31
+ }
32
+ renderer_1.RenderInternals.Log.trace({ indent: false, logLevel }, `[delete-jsx-node] Received request to delete ${nodes.length} JSX node${nodes.length === 1 ? '' : 's'}`);
33
+ const itemsByFileName = new Map();
34
+ for (const item of nodes) {
35
+ const fileItems = (_a = itemsByFileName.get(item.fileName)) !== null && _a !== void 0 ? _a : [];
36
+ fileItems.push(item);
37
+ itemsByFileName.set(item.fileName, fileItems);
38
+ }
39
+ const updates = await Promise.all([...itemsByFileName.entries()].map(async ([fileName, fileItems]) => {
40
+ const { absolutePath, fileRelativeToRoot } = (0, resolve_file_inside_project_1.resolveFileInsideProject)({
41
+ remotionRoot,
42
+ fileName,
43
+ action: 'modify',
44
+ });
45
+ const fileContents = (0, node_fs_1.readFileSync)(absolutePath, 'utf-8');
46
+ const { output, nodeLabels, logLines, nodePathRemappings } = await (0, delete_jsx_node_1.deleteJsxNodes)({
47
+ input: fileContents,
48
+ nodePaths: fileItems.map((item) => item.nodePath),
49
+ });
50
+ return {
51
+ absolutePath,
52
+ fileRelativeToRoot,
53
+ fileContents,
54
+ output,
55
+ nodeLabels,
56
+ nodePathRemappings,
57
+ logLine: Math.min(...logLines),
58
+ };
59
+ }));
60
+ (0, hmr_timing_1.logHmrTiming)({
61
+ detail: `files=${updates.length}`,
62
+ logLevel,
63
+ stage: 'delete-jsx-node-codemod-complete',
64
+ });
65
+ const nodePathMutation = (0, sequence_node_path_mutation_1.broadcastSequenceNodePathMutation)(updates.map((update) => ({
66
+ absolutePath: update.absolutePath,
67
+ remappings: update.nodePathRemappings,
68
+ })), null);
69
+ for (const update of updates) {
70
+ const deletedNodeDescription = getDeletedNodeDescription(update.nodeLabels);
71
+ (0, undo_stack_1.pushToUndoStack)({
72
+ filePath: update.absolutePath,
73
+ oldContents: update.fileContents,
74
+ newContents: null,
75
+ logLevel,
76
+ remotionRoot,
77
+ logLine: update.logLine,
78
+ description: {
79
+ undoMessage: `↩️ Deletion of ${deletedNodeDescription}`,
80
+ redoMessage: `↪️ Deletion of ${deletedNodeDescription}`,
81
+ },
82
+ entryType: 'delete-jsx-node',
83
+ suppressHmrOnFileRestore: false,
84
+ nodePathRemappings: update.nodePathRemappings,
85
+ });
86
+ (0, undo_stack_1.suppressUndoStackInvalidation)(update.absolutePath);
87
+ (0, hmr_timing_1.logHmrTiming)({
88
+ detail: `file=${update.fileRelativeToRoot}`,
89
+ logLevel,
90
+ stage: 'source-file-write-start',
91
+ });
92
+ (0, file_watcher_1.writeFileAndNotifyFileWatchers)({
93
+ file: update.absolutePath,
94
+ content: update.output,
95
+ originatorClientId: undefined,
96
+ metadata: { skipSequencePropsUpdate: true },
97
+ });
98
+ (0, hmr_timing_1.logHmrTiming)({
99
+ detail: `file=${update.fileRelativeToRoot}`,
100
+ logLevel,
101
+ stage: 'source-file-write-complete',
102
+ });
103
+ const locationLabel = (0, format_log_file_location_1.formatLogFileLocation)({
104
+ remotionRoot,
105
+ absolutePath: update.absolutePath,
106
+ line: update.logLine,
107
+ });
108
+ renderer_1.RenderInternals.Log.info({ indent: false, logLevel }, `${(0, source_file_write_queue_1.getCodemodTimingPrefix)(logLevel)}${renderer_1.RenderInternals.chalk.blueBright(`${locationLabel}`)} Deleted ${deletedNodeDescription}`);
109
+ renderer_1.RenderInternals.Log.verbose({ indent: false, logLevel }, `[delete-jsx-node] Wrote ${update.fileRelativeToRoot}`);
110
+ }
111
+ (0, undo_stack_1.printUndoHint)(logLevel);
112
+ return {
113
+ success: true,
114
+ nodePathMutation,
115
+ };
116
+ }
117
+ catch (err) {
118
+ return {
119
+ success: false,
120
+ reason: err.message,
121
+ stack: err.stack,
122
+ };
123
+ }
124
+ });
125
+ };
126
+ exports.deleteJsxNodeHandler = deleteJsxNodeHandler;
@@ -0,0 +1,3 @@
1
+ import type { DeleteNodesRequest, DeleteNodesResponse } from '@remotion/studio-shared';
2
+ import type { ApiHandler } from '../api-types';
3
+ export declare const deleteNodesHandler: ApiHandler<DeleteNodesRequest, DeleteNodesResponse>;
@@ -0,0 +1,142 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.deleteNodesHandler = void 0;
4
+ const node_fs_1 = require("node:fs");
5
+ const codemods_1 = require("@remotion/codemods");
6
+ const renderer_1 = require("@remotion/renderer");
7
+ const file_watcher_1 = require("../../file-watcher");
8
+ const resolve_file_inside_project_1 = require("../../helpers/resolve-file-inside-project");
9
+ const format_log_file_location_1 = require("../format-log-file-location");
10
+ const hmr_timing_1 = require("../hmr-timing");
11
+ const sequence_node_path_mutation_1 = require("../sequence-node-path-mutation");
12
+ const undo_stack_1 = require("../undo-stack");
13
+ const source_file_write_queue_1 = require("./source-file-write-queue");
14
+ const getDeletedNodeDescription = (nodeLabels) => {
15
+ if (nodeLabels.length === 1) {
16
+ return nodeLabels[0];
17
+ }
18
+ return `${nodeLabels.length} JSX nodes`;
19
+ };
20
+ const deleteNodesHandler = ({ input: { nodes }, remotionRoot, logLevel }) => {
21
+ return (0, source_file_write_queue_1.withSourceFileWriteQueue)(async () => {
22
+ var _a;
23
+ try {
24
+ (0, hmr_timing_1.logHmrTiming)({
25
+ detail: null,
26
+ logLevel,
27
+ stage: 'delete-nodes-request-start',
28
+ });
29
+ if (nodes.length === 0) {
30
+ throw new Error('No JSX nodes were specified for deletion');
31
+ }
32
+ renderer_1.RenderInternals.Log.trace({ indent: false, logLevel }, `[delete-nodes] Received request to delete ${nodes.length} JSX node${nodes.length === 1 ? '' : 's'}`);
33
+ const itemsByFileName = new Map();
34
+ for (const item of nodes) {
35
+ const fileItems = (_a = itemsByFileName.get(item.fileName)) !== null && _a !== void 0 ? _a : [];
36
+ fileItems.push(item);
37
+ itemsByFileName.set(item.fileName, fileItems);
38
+ }
39
+ const updates = await Promise.all([...itemsByFileName.entries()].map(async ([fileName, fileItems]) => {
40
+ var _a;
41
+ var _b;
42
+ const { absolutePath, fileRelativeToRoot } = (0, resolve_file_inside_project_1.resolveFileInsideProject)({
43
+ remotionRoot,
44
+ fileName,
45
+ action: 'modify',
46
+ });
47
+ const fileContents = (0, node_fs_1.readFileSync)(absolutePath, 'utf-8');
48
+ const result = await (0, codemods_1.deleteNodes)({
49
+ project: {
50
+ files: { [absolutePath]: fileContents },
51
+ rootDir: remotionRoot,
52
+ },
53
+ nodes: fileItems.map((item) => ({
54
+ filePath: absolutePath,
55
+ nodePath: item.nodePath,
56
+ })),
57
+ });
58
+ const output = (_b = (_a = result.changes[0]) === null || _a === void 0 ? void 0 : _a.nextContents) !== null && _b !== void 0 ? _b : fileContents;
59
+ const { nodeLabels, logLines } = result.editDetails[0];
60
+ const nodePathRemappings = result.nodePathRemappings.map(({ oldNodePath, newNodePath, oldJsxName, newJsxName }) => ({
61
+ oldNodePath,
62
+ newNodePath,
63
+ oldJsxName,
64
+ newJsxName,
65
+ }));
66
+ return {
67
+ absolutePath,
68
+ fileRelativeToRoot,
69
+ fileContents,
70
+ output,
71
+ nodeLabels,
72
+ nodePathRemappings,
73
+ logLine: Math.min(...logLines),
74
+ };
75
+ }));
76
+ (0, hmr_timing_1.logHmrTiming)({
77
+ detail: `files=${updates.length}`,
78
+ logLevel,
79
+ stage: 'delete-nodes-codemod-complete',
80
+ });
81
+ const nodePathMutation = (0, sequence_node_path_mutation_1.broadcastSequenceNodePathMutation)(updates.map((update) => ({
82
+ absolutePath: update.absolutePath,
83
+ remappings: update.nodePathRemappings,
84
+ })), null);
85
+ for (const update of updates) {
86
+ const deletedNodeDescription = getDeletedNodeDescription(update.nodeLabels);
87
+ (0, undo_stack_1.pushToUndoStack)({
88
+ filePath: update.absolutePath,
89
+ oldContents: update.fileContents,
90
+ newContents: null,
91
+ logLevel,
92
+ remotionRoot,
93
+ logLine: update.logLine,
94
+ description: {
95
+ undoMessage: `↩️ Deletion of ${deletedNodeDescription}`,
96
+ redoMessage: `↪️ Deletion of ${deletedNodeDescription}`,
97
+ },
98
+ entryType: 'delete-nodes',
99
+ suppressHmrOnFileRestore: false,
100
+ nodePathRemappings: update.nodePathRemappings,
101
+ });
102
+ (0, undo_stack_1.suppressUndoStackInvalidation)(update.absolutePath);
103
+ (0, hmr_timing_1.logHmrTiming)({
104
+ detail: `file=${update.fileRelativeToRoot}`,
105
+ logLevel,
106
+ stage: 'source-file-write-start',
107
+ });
108
+ (0, file_watcher_1.writeFileAndNotifyFileWatchers)({
109
+ file: update.absolutePath,
110
+ content: update.output,
111
+ originatorClientId: undefined,
112
+ metadata: { skipSequencePropsUpdate: true },
113
+ });
114
+ (0, hmr_timing_1.logHmrTiming)({
115
+ detail: `file=${update.fileRelativeToRoot}`,
116
+ logLevel,
117
+ stage: 'source-file-write-complete',
118
+ });
119
+ const locationLabel = (0, format_log_file_location_1.formatLogFileLocation)({
120
+ remotionRoot,
121
+ absolutePath: update.absolutePath,
122
+ line: update.logLine,
123
+ });
124
+ renderer_1.RenderInternals.Log.info({ indent: false, logLevel }, `${(0, source_file_write_queue_1.getCodemodTimingPrefix)(logLevel)}${renderer_1.RenderInternals.chalk.blueBright(`${locationLabel}`)} Deleted ${deletedNodeDescription}`);
125
+ renderer_1.RenderInternals.Log.verbose({ indent: false, logLevel }, `[delete-nodes] Wrote ${update.fileRelativeToRoot}`);
126
+ }
127
+ (0, undo_stack_1.printUndoHint)(logLevel);
128
+ return {
129
+ success: true,
130
+ nodePathMutation,
131
+ };
132
+ }
133
+ catch (err) {
134
+ return {
135
+ success: false,
136
+ reason: err.message,
137
+ stack: err.stack,
138
+ };
139
+ }
140
+ });
141
+ };
142
+ exports.deleteNodesHandler = deleteNodesHandler;
@@ -0,0 +1,3 @@
1
+ import type { CompositionEditResponse, DuplicateCompositionRequest } from '@remotion/studio-shared';
2
+ import type { ApiHandler } from '../api-types';
3
+ export declare const duplicateCompositionHandler: ApiHandler<DuplicateCompositionRequest, CompositionEditResponse>;
@@ -0,0 +1,114 @@
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.duplicateCompositionHandler = void 0;
7
+ const node_fs_1 = require("node:fs");
8
+ const node_path_1 = __importDefault(require("node:path"));
9
+ const codemods_1 = require("@remotion/codemods");
10
+ const renderer_1 = require("@remotion/renderer");
11
+ const file_watcher_1 = require("../../file-watcher");
12
+ const resolve_file_inside_project_1 = require("../../helpers/resolve-file-inside-project");
13
+ const format_log_file_location_1 = require("../format-log-file-location");
14
+ const project_info_1 = require("../project-info");
15
+ const undo_stack_1 = require("../undo-stack");
16
+ const can_update_default_props_1 = require("./can-update-default-props");
17
+ const source_file_write_queue_1 = require("./source-file-write-queue");
18
+ const duplicateCompositionHandler = ({ input: request, logLevel, remotionRoot, entryPoint }) => (0, source_file_write_queue_1.withSourceFileWriteQueue)(async () => {
19
+ var _a, _b;
20
+ var _c, _d, _e, _f, _g, _h;
21
+ try {
22
+ let filePath;
23
+ if ((_a = request.symbolicatedStack) === null || _a === void 0 ? void 0 : _a.originalFileName) {
24
+ filePath = (0, resolve_file_inside_project_1.resolveFileInsideProject)({
25
+ remotionRoot,
26
+ fileName: request.symbolicatedStack.originalFileName,
27
+ action: 'duplicate a composition in',
28
+ }).absolutePath;
29
+ }
30
+ else {
31
+ const { rootFile } = await (0, project_info_1.getProjectInfo)(remotionRoot, entryPoint);
32
+ if (rootFile === null) {
33
+ throw new Error('Cannot find the Remotion root file');
34
+ }
35
+ filePath = rootFile;
36
+ }
37
+ (0, can_update_default_props_1.checkIfTypeScriptFile)(filePath);
38
+ const result = (0, codemods_1.duplicateComposition)({
39
+ project: {
40
+ files: { [filePath]: (0, node_fs_1.readFileSync)(filePath, 'utf-8') },
41
+ rootDir: node_path_1.default.dirname(filePath),
42
+ },
43
+ compositionFile: filePath,
44
+ compositionId: request.idToDuplicate,
45
+ newId: request.newId,
46
+ tag: request.tag,
47
+ metadata: {
48
+ width: (_c = request.newWidth) !== null && _c !== void 0 ? _c : undefined,
49
+ height: (_d = request.newHeight) !== null && _d !== void 0 ? _d : undefined,
50
+ fps: request.tag === 'Still' ? undefined : ((_e = request.newFps) !== null && _e !== void 0 ? _e : undefined),
51
+ durationInFrames: request.tag === 'Still'
52
+ ? undefined
53
+ : ((_f = request.newDurationInFrames) !== null && _f !== void 0 ? _f : undefined),
54
+ },
55
+ });
56
+ for (const change of result.changes) {
57
+ const currentContents = (0, node_fs_1.existsSync)(change.filePath)
58
+ ? (0, node_fs_1.readFileSync)(change.filePath, 'utf-8')
59
+ : null;
60
+ if (currentContents !== change.previousContents) {
61
+ throw new Error(`Source changed before duplicating composition: ${change.filePath}`);
62
+ }
63
+ }
64
+ if (result.changes.length > 0) {
65
+ const logLine = (_g = (_b = request.symbolicatedStack) === null || _b === void 0 ? void 0 : _b.originalLineNumber) !== null && _g !== void 0 ? _g : 1;
66
+ (0, undo_stack_1.pushTransactionToUndoStack)({
67
+ snapshots: result.changes.map((change) => ({
68
+ filePath: change.filePath,
69
+ oldContents: change.previousContents,
70
+ newContents: change.nextContents,
71
+ logLine: change.filePath === filePath ? logLine : 1,
72
+ nodePathRemappings: null,
73
+ })),
74
+ logLevel,
75
+ remotionRoot,
76
+ description: {
77
+ undoMessage: `↩️ Duplication of composition "${request.idToDuplicate}" to "${request.newId}"`,
78
+ redoMessage: `↪️ Duplication of composition "${request.idToDuplicate}" to "${request.newId}"`,
79
+ },
80
+ entryType: 'duplicate-composition',
81
+ suppressHmrOnFileRestore: false,
82
+ undoRedoNavigation: request.undoRedoNavigation,
83
+ });
84
+ for (const change of result.changes) {
85
+ if (change.nextContents === null) {
86
+ throw new Error('Duplicating a composition cannot remove source files');
87
+ }
88
+ (0, undo_stack_1.suppressUndoStackInvalidation)(change.filePath);
89
+ (0, file_watcher_1.writeFileAndNotifyFileWatchers)({
90
+ file: change.filePath,
91
+ content: change.nextContents,
92
+ originatorClientId: undefined,
93
+ metadata: null,
94
+ });
95
+ }
96
+ const locationLabel = (0, format_log_file_location_1.formatLogFileLocation)({
97
+ remotionRoot,
98
+ absolutePath: filePath,
99
+ line: logLine,
100
+ });
101
+ renderer_1.RenderInternals.Log.info({ indent: false, logLevel }, `${(0, source_file_write_queue_1.getCodemodTimingPrefix)(logLevel)}${renderer_1.RenderInternals.chalk.blueBright(locationLabel)} Duplicated composition "${request.idToDuplicate}" to "${request.newId}"`);
102
+ (0, undo_stack_1.printUndoHint)(logLevel);
103
+ }
104
+ return { success: true, nodePathMutation: null };
105
+ }
106
+ catch (error) {
107
+ return {
108
+ success: false,
109
+ reason: error instanceof Error ? error.message : String(error),
110
+ stack: error instanceof Error ? ((_h = error.stack) !== null && _h !== void 0 ? _h : '') : '',
111
+ };
112
+ }
113
+ });
114
+ exports.duplicateCompositionHandler = duplicateCompositionHandler;
@@ -0,0 +1,3 @@
1
+ import type { DuplicateNodesRequest, DuplicateNodesResponse } from '@remotion/studio-shared';
2
+ import type { ApiHandler } from '../api-types';
3
+ export declare const duplicateNodesHandler: ApiHandler<DuplicateNodesRequest, DuplicateNodesResponse>;
@@ -0,0 +1,123 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.duplicateNodesHandler = void 0;
4
+ const node_fs_1 = require("node:fs");
5
+ const codemods_1 = require("@remotion/codemods");
6
+ const renderer_1 = require("@remotion/renderer");
7
+ const file_watcher_1 = require("../../file-watcher");
8
+ const resolve_file_inside_project_1 = require("../../helpers/resolve-file-inside-project");
9
+ const format_log_file_location_1 = require("../format-log-file-location");
10
+ const sequence_node_path_mutation_1 = require("../sequence-node-path-mutation");
11
+ const undo_stack_1 = require("../undo-stack");
12
+ const source_file_write_queue_1 = require("./source-file-write-queue");
13
+ const duplicateNodesHandler = ({ input: { nodes }, remotionRoot, logLevel }) => {
14
+ return (0, source_file_write_queue_1.withSourceFileWriteQueue)(async () => {
15
+ var _a;
16
+ try {
17
+ if (nodes.length === 0) {
18
+ throw new Error('No JSX nodes were specified for duplication');
19
+ }
20
+ renderer_1.RenderInternals.Log.trace({ indent: false, logLevel }, `[duplicate-nodes] Received request to duplicate ${nodes.length} JSX node${nodes.length === 1 ? '' : 's'}`);
21
+ const itemsByFileName = new Map();
22
+ for (const item of nodes) {
23
+ const fileItems = (_a = itemsByFileName.get(item.fileName)) !== null && _a !== void 0 ? _a : [];
24
+ fileItems.push(item);
25
+ itemsByFileName.set(item.fileName, fileItems);
26
+ }
27
+ const updates = await Promise.all([...itemsByFileName.entries()].map(async ([fileName, fileItems]) => {
28
+ var _a;
29
+ var _b;
30
+ const { absolutePath, fileRelativeToRoot } = (0, resolve_file_inside_project_1.resolveFileInsideProject)({
31
+ remotionRoot,
32
+ fileName,
33
+ action: 'modify',
34
+ });
35
+ const fileContents = (0, node_fs_1.readFileSync)(absolutePath, 'utf-8');
36
+ const result = await (0, codemods_1.duplicateNodes)({
37
+ project: {
38
+ files: { [absolutePath]: fileContents },
39
+ rootDir: remotionRoot,
40
+ },
41
+ nodes: fileItems.map((item) => ({
42
+ filePath: absolutePath,
43
+ nodePath: item.nodePath,
44
+ })),
45
+ });
46
+ const output = (_b = (_a = result.changes[0]) === null || _a === void 0 ? void 0 : _a.nextContents) !== null && _b !== void 0 ? _b : fileContents;
47
+ const { nodeLabels, logLines } = result.editDetails[0];
48
+ const nodePathRemappings = result.nodePathRemappings.map(({ oldNodePath, newNodePath, oldJsxName, newJsxName }) => ({
49
+ oldNodePath,
50
+ newNodePath,
51
+ oldJsxName,
52
+ newJsxName,
53
+ }));
54
+ return {
55
+ absolutePath,
56
+ fileRelativeToRoot,
57
+ fileContents,
58
+ logLine: Math.min(...logLines),
59
+ nodeLabels,
60
+ nodePathRemappings,
61
+ output,
62
+ };
63
+ }));
64
+ const nodePathMutation = (0, sequence_node_path_mutation_1.broadcastSequenceNodePathMutation)(updates.map((update) => ({
65
+ absolutePath: update.absolutePath,
66
+ remappings: update.nodePathRemappings,
67
+ })), null);
68
+ const duplicatedNodeDescription = nodes.length === 1
69
+ ? updates[0].nodeLabels[0]
70
+ : `${nodes.length} JSX nodes`;
71
+ (0, undo_stack_1.pushTransactionToUndoStack)({
72
+ snapshots: updates.map((update) => ({
73
+ filePath: update.absolutePath,
74
+ oldContents: update.fileContents,
75
+ newContents: null,
76
+ logLine: update.logLine,
77
+ nodePathRemappings: update.nodePathRemappings,
78
+ })),
79
+ logLevel,
80
+ remotionRoot,
81
+ description: {
82
+ undoMessage: `↩️ Duplication of ${duplicatedNodeDescription}`,
83
+ redoMessage: `↪️ Duplication of ${duplicatedNodeDescription}`,
84
+ },
85
+ entryType: 'duplicate-nodes',
86
+ suppressHmrOnFileRestore: false,
87
+ undoRedoNavigation: null,
88
+ });
89
+ for (const update of updates) {
90
+ (0, undo_stack_1.suppressUndoStackInvalidation)(update.absolutePath);
91
+ (0, file_watcher_1.writeFileAndNotifyFileWatchers)({
92
+ file: update.absolutePath,
93
+ content: update.output,
94
+ originatorClientId: undefined,
95
+ metadata: { skipSequencePropsUpdate: true },
96
+ });
97
+ const locationLabel = (0, format_log_file_location_1.formatLogFileLocation)({
98
+ remotionRoot,
99
+ absolutePath: update.absolutePath,
100
+ line: update.logLine,
101
+ });
102
+ const fileDescription = update.nodeLabels.length === 1
103
+ ? update.nodeLabels[0]
104
+ : `${update.nodeLabels.length} JSX nodes`;
105
+ renderer_1.RenderInternals.Log.info({ indent: false, logLevel }, `${(0, source_file_write_queue_1.getCodemodTimingPrefix)(logLevel)}${renderer_1.RenderInternals.chalk.blueBright(`${locationLabel}`)} Duplicated ${fileDescription}`);
106
+ renderer_1.RenderInternals.Log.verbose({ indent: false, logLevel }, `[duplicate-nodes] Wrote ${update.fileRelativeToRoot}`);
107
+ }
108
+ (0, undo_stack_1.printUndoHint)(logLevel);
109
+ return {
110
+ success: true,
111
+ nodePathMutation,
112
+ };
113
+ }
114
+ catch (err) {
115
+ return {
116
+ success: false,
117
+ reason: err.message,
118
+ stack: err.stack,
119
+ };
120
+ }
121
+ });
122
+ };
123
+ exports.duplicateNodesHandler = duplicateNodesHandler;
@@ -11,7 +11,7 @@ const sequence_node_path_mutation_1 = require("../sequence-node-path-mutation");
11
11
  const undo_stack_1 = require("../undo-stack");
12
12
  const source_file_write_queue_1 = require("./source-file-write-queue");
13
13
  const { basicCaptionsElementSource, getBasicCaptionsElementFile, insertBasicCaptions, } = codemods_1.CodemodsInternals;
14
- const insertBasicCaptionsHandler = ({ input: { fileName, nodePath, captions, durationInFrames }, remotionRoot, logLevel, }) => (0, source_file_write_queue_1.withSourceFileWriteQueue)(() => {
14
+ const insertBasicCaptionsHandler = ({ input: { fileName, nodePath, captions, durationInFrames, premountFor }, remotionRoot, logLevel, }) => (0, source_file_write_queue_1.withSourceFileWriteQueue)(() => {
15
15
  var _a;
16
16
  try {
17
17
  const { absolutePath } = (0, resolve_file_inside_project_1.resolveFileInsideProject)({
@@ -49,6 +49,7 @@ const insertBasicCaptionsHandler = ({ input: { fileName, nodePath, captions, dur
49
49
  nodePath,
50
50
  captions,
51
51
  durationInFrames,
52
+ premountFor,
52
53
  importPath: elementFile.importPath,
53
54
  });
54
55
  const nodePathMutation = (0, sequence_node_path_mutation_1.broadcastSequenceNodePathMutation)([{ absolutePath, remappings: nodePathRemappings }], null);
@@ -0,0 +1,3 @@
1
+ import { type InsertCompositionElementRequest, type InsertCompositionElementResponse } from '@remotion/studio-shared';
2
+ import type { ApiHandler } from '../api-types';
3
+ export declare const insertCompositionElementHandler: ApiHandler<InsertCompositionElementRequest, InsertCompositionElementResponse>;