@remotion/studio-server 4.0.536 → 4.0.537

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.
@@ -71,6 +71,7 @@ const unsubscribe_from_default_props_1 = require("./routes/unsubscribe-from-defa
71
71
  const unsubscribe_from_file_existence_1 = require("./routes/unsubscribe-from-file-existence");
72
72
  const unsubscribe_from_sequence_props_1 = require("./routes/unsubscribe-from-sequence-props");
73
73
  const unwrap_folder_1 = require("./routes/unwrap-folder");
74
+ const unwrap_node_1 = require("./routes/unwrap-node");
74
75
  const update_available_1 = require("./routes/update-available");
75
76
  const update_composition_metadata_1 = require("./routes/update-composition-metadata");
76
77
  const update_default_props_1 = require("./routes/update-default-props");
@@ -133,6 +134,7 @@ exports.allApiRoutes = {
133
134
  '/api/paste-effects': paste_effects_1.pasteEffectsHandler,
134
135
  '/api/delete-nodes': delete_nodes_1.deleteNodesHandler,
135
136
  '/api/duplicate-nodes': duplicate_nodes_1.duplicateNodesHandler,
137
+ '/api/unwrap-node': unwrap_node_1.unwrapNodeHandler,
136
138
  '/api/wrap-node': wrap_node_1.wrapNodeHandler,
137
139
  '/api/precompose-jsx-nodes': precompose_jsx_nodes_1.precomposeJsxNodesHandler,
138
140
  '/api/split-sequences': split_sequences_1.splitSequencesHandler,
@@ -1,7 +1,8 @@
1
- import type { CanUpdateDefaultPropsResponse } from '@remotion/studio-shared';
2
- export declare const subscribeToDefaultPropsWatchers: ({ compositionId, clientId, remotionRoot, entryPoint, }: {
1
+ import type { CanUpdateDefaultPropsResponse, SymbolicatedStackFrame } from '@remotion/studio-shared';
2
+ export declare const subscribeToDefaultPropsWatchers: ({ compositionId, clientId, symbolicatedStack, remotionRoot, entryPoint, }: {
3
3
  compositionId: string;
4
4
  clientId: string;
5
+ symbolicatedStack: SymbolicatedStackFrame | null;
5
6
  remotionRoot: string;
6
7
  entryPoint: string;
7
8
  }) => Promise<CanUpdateDefaultPropsResponse>;
@@ -4,104 +4,75 @@ exports.unsubscribeClientDefaultPropsWatchers = exports.unsubscribeFromDefaultPr
4
4
  const file_watcher_1 = require("../file-watcher");
5
5
  const live_events_1 = require("./live-events");
6
6
  const can_update_default_props_1 = require("./routes/can-update-default-props");
7
- // Global file watcher — at most one for the root file
8
- let globalWatcher = null;
9
- // Per-compositionId set of subscribed clientIds
10
- const subscriptions = {};
11
- // Cached config for recomputation on file change
12
- let watcherConfig = null;
13
- const ensureGlobalWatcher = (rootFile) => {
14
- if (globalWatcher) {
15
- globalWatcher.refCount++;
7
+ // Each client watches its own resolved registration file or root-file fallback.
8
+ const watchers = {};
9
+ const removeClient = (compositionId, clientId) => {
10
+ const compositionWatchers = watchers[compositionId];
11
+ if (!compositionWatchers) {
16
12
  return;
17
13
  }
18
- const { unwatch } = (0, file_watcher_1.installFileWatcher)({
19
- file: rootFile,
20
- existenceOnly: false,
21
- onChange: (event) => {
22
- if (event.type === 'deleted') {
23
- return;
24
- }
25
- if (!watcherConfig) {
26
- return;
27
- }
28
- const compositionIds = Object.keys(subscriptions);
29
- for (const compositionId of compositionIds) {
30
- if (subscriptions[compositionId].size === 0) {
31
- continue;
14
+ for (const [file, watcher] of compositionWatchers) {
15
+ watcher.clientIds.delete(clientId);
16
+ if (watcher.clientIds.size === 0) {
17
+ watcher.unwatch();
18
+ compositionWatchers.delete(file);
19
+ }
20
+ }
21
+ if (compositionWatchers.size === 0) {
22
+ delete watchers[compositionId];
23
+ }
24
+ };
25
+ const subscribeToDefaultPropsWatchers = async ({ compositionId, clientId, symbolicatedStack, remotionRoot, entryPoint, }) => {
26
+ var _a;
27
+ const { result, compositionFile } = await (0, can_update_default_props_1.computeCanUpdateDefaultProps)({
28
+ compositionId,
29
+ symbolicatedStack,
30
+ remotionRoot,
31
+ entryPoint,
32
+ });
33
+ // Remove from any previous subscription for this client+composition
34
+ removeClient(compositionId, clientId);
35
+ if (!compositionFile) {
36
+ return result;
37
+ }
38
+ (_a = watchers[compositionId]) !== null && _a !== void 0 ? _a : (watchers[compositionId] = new Map());
39
+ const compositionWatchers = watchers[compositionId];
40
+ if (!compositionWatchers.has(compositionFile)) {
41
+ const clientIds = new Set();
42
+ const { unwatch } = (0, file_watcher_1.installFileWatcher)({
43
+ file: compositionFile,
44
+ existenceOnly: false,
45
+ onChange: (event) => {
46
+ if (event.type === 'deleted') {
47
+ return;
32
48
  }
33
- const clientIds = [...subscriptions[compositionId]];
34
49
  const newResult = (0, can_update_default_props_1.computeCanUpdateDefaultPropsFromContent)(event.content, compositionId);
50
+ const subscribedClientIds = [...clientIds];
35
51
  (0, live_events_1.waitForLiveEventsListener)().then((listener) => {
36
52
  const updateEvent = {
37
53
  type: 'default-props-updatable-changed',
38
54
  compositionId,
39
55
  result: newResult,
40
56
  };
41
- for (const cId of clientIds) {
57
+ for (const cId of subscribedClientIds) {
42
58
  listener.sendEventToClientId(cId, updateEvent);
43
59
  }
44
60
  });
45
- }
46
- },
47
- });
48
- globalWatcher = { unwatch, rootFile, refCount: 1 };
49
- };
50
- const releaseGlobalWatcher = () => {
51
- if (!globalWatcher) {
52
- return;
53
- }
54
- globalWatcher.refCount--;
55
- if (globalWatcher.refCount <= 0) {
56
- globalWatcher.unwatch();
57
- globalWatcher = null;
58
- watcherConfig = null;
59
- }
60
- };
61
- const subscribeToDefaultPropsWatchers = async ({ compositionId, clientId, remotionRoot, entryPoint, }) => {
62
- var _a;
63
- const { result, rootFile } = await (0, can_update_default_props_1.computeCanUpdateDefaultProps)({
64
- compositionId,
65
- remotionRoot,
66
- entryPoint,
67
- });
68
- // Remove from any previous subscription for this client+composition
69
- if ((_a = subscriptions[compositionId]) === null || _a === void 0 ? void 0 : _a.has(clientId)) {
70
- subscriptions[compositionId].delete(clientId);
71
- releaseGlobalWatcher();
72
- }
73
- if (rootFile) {
74
- watcherConfig = { remotionRoot, entryPoint };
75
- if (!subscriptions[compositionId]) {
76
- subscriptions[compositionId] = new Set();
77
- }
78
- subscriptions[compositionId].add(clientId);
79
- ensureGlobalWatcher(rootFile);
61
+ },
62
+ });
63
+ compositionWatchers.set(compositionFile, { unwatch, clientIds });
80
64
  }
65
+ compositionWatchers.get(compositionFile).clientIds.add(clientId);
81
66
  return result;
82
67
  };
83
68
  exports.subscribeToDefaultPropsWatchers = subscribeToDefaultPropsWatchers;
84
69
  const unsubscribeFromDefaultPropsWatchers = ({ compositionId, clientId, }) => {
85
- var _a;
86
- if (!((_a = subscriptions[compositionId]) === null || _a === void 0 ? void 0 : _a.has(clientId))) {
87
- return;
88
- }
89
- subscriptions[compositionId].delete(clientId);
90
- if (subscriptions[compositionId].size === 0) {
91
- delete subscriptions[compositionId];
92
- }
93
- releaseGlobalWatcher();
70
+ removeClient(compositionId, clientId);
94
71
  };
95
72
  exports.unsubscribeFromDefaultPropsWatchers = unsubscribeFromDefaultPropsWatchers;
96
73
  const unsubscribeClientDefaultPropsWatchers = (clientId) => {
97
- for (const compositionId of Object.keys(subscriptions)) {
98
- if (subscriptions[compositionId].has(clientId)) {
99
- subscriptions[compositionId].delete(clientId);
100
- if (subscriptions[compositionId].size === 0) {
101
- delete subscriptions[compositionId];
102
- }
103
- releaseGlobalWatcher();
104
- }
74
+ for (const compositionId of Object.keys(watchers)) {
75
+ removeClient(compositionId, clientId);
105
76
  }
106
77
  };
107
78
  exports.unsubscribeClientDefaultPropsWatchers = unsubscribeClientDefaultPropsWatchers;
@@ -1,11 +1,17 @@
1
- import type { CanUpdateDefaultPropsResponse } from '@remotion/studio-shared';
1
+ import type { CanUpdateDefaultPropsResponse, SymbolicatedStackFrame } from '@remotion/studio-shared';
2
2
  export declare const computeCanUpdateDefaultPropsFromContent: (content: string, compositionId: string) => CanUpdateDefaultPropsResponse;
3
3
  export declare const checkIfTypeScriptFile: (file: string) => void;
4
- export declare const computeCanUpdateDefaultProps: ({ compositionId, remotionRoot, entryPoint, }: {
4
+ export declare const getDefaultPropsFile: ({ symbolicatedStack, remotionRoot, entryPoint, }: {
5
+ symbolicatedStack: SymbolicatedStackFrame | null;
6
+ remotionRoot: string;
7
+ entryPoint: string;
8
+ }) => Promise<string>;
9
+ export declare const computeCanUpdateDefaultProps: ({ compositionId, symbolicatedStack, remotionRoot, entryPoint, }: {
5
10
  compositionId: string;
11
+ symbolicatedStack: SymbolicatedStackFrame | null;
6
12
  remotionRoot: string;
7
13
  entryPoint: string;
8
14
  }) => Promise<{
9
15
  result: CanUpdateDefaultPropsResponse;
10
- rootFile: string | null;
16
+ compositionFile: string | null;
11
17
  }>;
@@ -1,8 +1,9 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.computeCanUpdateDefaultProps = exports.checkIfTypeScriptFile = exports.computeCanUpdateDefaultPropsFromContent = void 0;
3
+ exports.computeCanUpdateDefaultProps = exports.getDefaultPropsFile = exports.checkIfTypeScriptFile = exports.computeCanUpdateDefaultPropsFromContent = void 0;
4
4
  const node_fs_1 = require("node:fs");
5
5
  const codemods_1 = require("@remotion/codemods");
6
+ const resolve_file_inside_project_1 = require("../../helpers/resolve-file-inside-project");
6
7
  const project_info_1 = require("../project-info");
7
8
  ({ computeCanUpdateDefaultPropsFromContent: exports.computeCanUpdateDefaultPropsFromContent } = codemods_1.CodemodsInternals);
8
9
  const checkIfTypeScriptFile = (file) => {
@@ -14,18 +15,50 @@ const checkIfTypeScriptFile = (file) => {
14
15
  }
15
16
  };
16
17
  exports.checkIfTypeScriptFile = checkIfTypeScriptFile;
17
- const computeCanUpdateDefaultProps = async ({ compositionId, remotionRoot, entryPoint, }) => {
18
+ // Compositions can be registered in files imported by the root file. The
19
+ // client sends the location of the registration, otherwise use the root file.
20
+ const getDefaultPropsFile = async ({ symbolicatedStack, remotionRoot, entryPoint, }) => {
21
+ if (symbolicatedStack === null || symbolicatedStack === void 0 ? void 0 : symbolicatedStack.originalFileName) {
22
+ return (0, resolve_file_inside_project_1.resolveFileInsideProject)({
23
+ remotionRoot,
24
+ fileName: symbolicatedStack.originalFileName,
25
+ action: 'update default props in',
26
+ }).absolutePath;
27
+ }
28
+ const { rootFile } = await (0, project_info_1.getProjectInfo)(remotionRoot, entryPoint);
29
+ if (!rootFile) {
30
+ throw new Error('Cannot find root file in project');
31
+ }
32
+ return rootFile;
33
+ };
34
+ exports.getDefaultPropsFile = getDefaultPropsFile;
35
+ const computeCanUpdateDefaultProps = async ({ compositionId, symbolicatedStack, remotionRoot, entryPoint, }) => {
18
36
  try {
19
- const projectInfo = await (0, project_info_1.getProjectInfo)(remotionRoot, entryPoint);
20
- if (!projectInfo.rootFile) {
21
- throw new Error('Cannot find root file in project');
22
- }
23
- (0, exports.checkIfTypeScriptFile)(projectInfo.rootFile);
24
- const input = (0, node_fs_1.readFileSync)(projectInfo.rootFile, 'utf-8');
37
+ const compositionFile = await (0, exports.getDefaultPropsFile)({
38
+ symbolicatedStack,
39
+ remotionRoot,
40
+ entryPoint,
41
+ });
42
+ (0, exports.checkIfTypeScriptFile)(compositionFile);
43
+ const input = (0, node_fs_1.readFileSync)(compositionFile, 'utf-8');
25
44
  const result = (0, exports.computeCanUpdateDefaultPropsFromContent)(input, compositionId);
45
+ if (!result.canUpdate &&
46
+ !(symbolicatedStack === null || symbolicatedStack === void 0 ? void 0 : symbolicatedStack.originalFileName) &&
47
+ codemods_1.CodemodsInternals.getCompositionFile({
48
+ compositionId,
49
+ project: { files: { [compositionFile]: input }, rootDir: remotionRoot },
50
+ }) === null) {
51
+ return {
52
+ result: {
53
+ canUpdate: false,
54
+ reason: `Could not determine which file registers this composition, checked the root file: ${result.reason}`,
55
+ },
56
+ compositionFile,
57
+ };
58
+ }
26
59
  return {
27
60
  result,
28
- rootFile: projectInfo.rootFile,
61
+ compositionFile,
29
62
  };
30
63
  }
31
64
  catch (err) {
@@ -34,7 +67,7 @@ const computeCanUpdateDefaultProps = async ({ compositionId, remotionRoot, entry
34
67
  canUpdate: false,
35
68
  reason: err.message,
36
69
  },
37
- rootFile: null,
70
+ compositionFile: null,
38
71
  };
39
72
  }
40
73
  };
@@ -2,10 +2,11 @@
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.subscribeToDefaultProps = void 0;
4
4
  const default_props_watchers_1 = require("../default-props-watchers");
5
- const subscribeToDefaultProps = ({ input: { compositionId, clientId }, remotionRoot, entryPoint }) => {
5
+ const subscribeToDefaultProps = ({ input: { compositionId, clientId, symbolicatedStack }, remotionRoot, entryPoint, }) => {
6
6
  return (0, default_props_watchers_1.subscribeToDefaultPropsWatchers)({
7
7
  compositionId,
8
8
  clientId,
9
+ symbolicatedStack,
9
10
  remotionRoot,
10
11
  entryPoint,
11
12
  });
@@ -1,3 +1,3 @@
1
- import type { UnsubscribeFromSequencePropsRequest } from '@remotion/studio-shared';
1
+ import type { UnsubscribeFromSequencePropsBatchRequest } from '@remotion/studio-shared';
2
2
  import type { ApiHandler } from '../api-types';
3
- export declare const unsubscribeFromSequenceProps: ApiHandler<UnsubscribeFromSequencePropsRequest, undefined>;
3
+ export declare const unsubscribeFromSequenceProps: ApiHandler<UnsubscribeFromSequencePropsBatchRequest, undefined>;
@@ -2,16 +2,18 @@
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.unsubscribeFromSequenceProps = void 0;
4
4
  const sequence_props_watchers_1 = require("../sequence-props-watchers");
5
- const unsubscribeFromSequenceProps = ({ input: { fileName, nodePath, clientId, sequenceKeys, assetKeys = [], effectKeys, }, remotionRoot, }) => {
6
- (0, sequence_props_watchers_1.unsubscribeFromSequencePropsWatchers)({
7
- fileName,
8
- nodePath: nodePath.nodePath,
9
- remotionRoot,
10
- clientId,
11
- sequenceKeys,
12
- assetKeys,
13
- effectKeys,
14
- });
5
+ const unsubscribeFromSequenceProps = ({ input, remotionRoot }) => {
6
+ for (const { fileName, nodePath, clientId, sequenceKeys, assetKeys = [], effectKeys, } of input.requests) {
7
+ (0, sequence_props_watchers_1.unsubscribeFromSequencePropsWatchers)({
8
+ fileName,
9
+ nodePath: nodePath.nodePath,
10
+ remotionRoot,
11
+ clientId,
12
+ sequenceKeys,
13
+ assetKeys,
14
+ effectKeys,
15
+ });
16
+ }
15
17
  return Promise.resolve(undefined);
16
18
  };
17
19
  exports.unsubscribeFromSequenceProps = unsubscribeFromSequenceProps;
@@ -0,0 +1,3 @@
1
+ import type { UnwrapNodeRequest, UnwrapNodeResponse } from '@remotion/studio-shared';
2
+ import type { ApiHandler } from '../api-types';
3
+ export declare const unwrapNodeHandler: ApiHandler<UnwrapNodeRequest, UnwrapNodeResponse>;
@@ -0,0 +1,98 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.unwrapNodeHandler = 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 unwrapNodeHandler = ({ input: { fileName, compositionId, nodePath, dryRun }, remotionRoot, logLevel, }) => {
14
+ return (0, source_file_write_queue_1.withSourceFileWriteQueue)(() => {
15
+ var _a;
16
+ try {
17
+ const { absolutePath, fileRelativeToRoot } = (0, resolve_file_inside_project_1.resolveFileInsideProject)({
18
+ remotionRoot,
19
+ fileName,
20
+ action: 'modify',
21
+ });
22
+ const fileContents = (0, node_fs_1.readFileSync)(absolutePath, 'utf-8');
23
+ const canUnwrap = (0, codemods_1.canUnwrapNode)({ input: fileContents, nodePath });
24
+ if (dryRun) {
25
+ return Promise.resolve({
26
+ success: true,
27
+ canUnwrap,
28
+ nodePathMutation: null,
29
+ });
30
+ }
31
+ const result = (0, codemods_1.unwrapNode)({
32
+ project: { files: { [absolutePath]: fileContents }, rootDir: remotionRoot },
33
+ node: { filePath: absolutePath, nodePath },
34
+ });
35
+ const change = result.changes.find(({ filePath }) => filePath === absolutePath);
36
+ if ((change === null || change === void 0 ? void 0 : change.previousContents) !== fileContents ||
37
+ change.nextContents === null) {
38
+ throw new Error('Could not unwrap JSX node');
39
+ }
40
+ const output = change.nextContents;
41
+ const remappings = result.nodePathRemappings.map(({ oldNodePath, newNodePath, oldJsxName, newJsxName }) => ({
42
+ oldNodePath,
43
+ newNodePath,
44
+ oldJsxName,
45
+ newJsxName,
46
+ }));
47
+ const { childNodePath } = result;
48
+ const nodePathMutation = (0, sequence_node_path_mutation_1.broadcastSequenceNodePathMutation)([{ absolutePath, remappings }], childNodePath !== null
49
+ ? { compositionId, absolutePath, nodePath: childNodePath }
50
+ : null);
51
+ const line = result.logLine;
52
+ (0, undo_stack_1.pushTransactionToUndoStack)({
53
+ snapshots: [
54
+ {
55
+ filePath: absolutePath,
56
+ oldContents: fileContents,
57
+ newContents: null,
58
+ logLine: line,
59
+ nodePathRemappings: remappings,
60
+ },
61
+ ],
62
+ logLevel,
63
+ remotionRoot,
64
+ description: {
65
+ undoMessage: '↩️ Unwrapping JSX',
66
+ redoMessage: '↪️ Unwrapping JSX',
67
+ },
68
+ entryType: 'unwrap-node',
69
+ suppressHmrOnFileRestore: false,
70
+ undoRedoNavigation: null,
71
+ });
72
+ (0, undo_stack_1.suppressUndoStackInvalidation)(absolutePath);
73
+ (0, file_watcher_1.writeFileAndNotifyFileWatchers)({
74
+ file: absolutePath,
75
+ content: output,
76
+ originatorClientId: undefined,
77
+ metadata: { skipSequencePropsUpdate: true },
78
+ });
79
+ const locationLabel = (0, format_log_file_location_1.formatLogFileLocation)({
80
+ remotionRoot,
81
+ absolutePath,
82
+ line,
83
+ });
84
+ renderer_1.RenderInternals.Log.info({ indent: false, logLevel }, `${(0, source_file_write_queue_1.getCodemodTimingPrefix)(logLevel)}${renderer_1.RenderInternals.chalk.blueBright(locationLabel)} Unwrapped JSX`);
85
+ renderer_1.RenderInternals.Log.verbose({ indent: false, logLevel }, `[unwrap-node] Wrote ${fileRelativeToRoot}`);
86
+ (0, undo_stack_1.printUndoHint)(logLevel);
87
+ return Promise.resolve({ success: true, canUnwrap, nodePathMutation });
88
+ }
89
+ catch (err) {
90
+ return Promise.resolve({
91
+ success: false,
92
+ reason: err.message,
93
+ stack: (_a = err.stack) !== null && _a !== void 0 ? _a : '',
94
+ });
95
+ }
96
+ });
97
+ };
98
+ exports.unwrapNodeHandler = unwrapNodeHandler;
@@ -6,29 +6,29 @@ const codemods_1 = require("@remotion/codemods");
6
6
  const renderer_1 = require("@remotion/renderer");
7
7
  const file_watcher_1 = require("../../file-watcher");
8
8
  const format_log_file_location_1 = require("../format-log-file-location");
9
- const project_info_1 = require("../project-info");
10
9
  const undo_stack_1 = require("../undo-stack");
11
10
  const watch_ignore_next_change_1 = require("../watch-ignore-next-change");
12
11
  const can_update_default_props_1 = require("./can-update-default-props");
13
12
  const source_file_write_queue_1 = require("./source-file-write-queue");
14
- const updateDefaultPropsHandler = ({ input: { compositionId, defaultProps, enumPaths }, remotionRoot, entryPoint, logLevel, }) => {
13
+ const updateDefaultPropsHandler = ({ input: { compositionId, defaultProps, enumPaths, symbolicatedStack }, remotionRoot, entryPoint, logLevel, }) => {
15
14
  return (0, source_file_write_queue_1.withSourceFileWriteQueue)(async () => {
16
15
  var _a;
17
16
  var _b;
18
17
  try {
19
18
  renderer_1.RenderInternals.Log.trace({ indent: false, logLevel }, `[update-default-props] Received request for compositionId="${compositionId}"`);
20
- const projectInfo = await (0, project_info_1.getProjectInfo)(remotionRoot, entryPoint);
21
- if (!projectInfo.rootFile) {
22
- throw new Error('Cannot find root file in project');
23
- }
24
- (0, can_update_default_props_1.checkIfTypeScriptFile)(projectInfo.rootFile);
25
- const fileContents = (0, node_fs_1.readFileSync)(projectInfo.rootFile, 'utf-8');
19
+ const compositionFile = await (0, can_update_default_props_1.getDefaultPropsFile)({
20
+ symbolicatedStack,
21
+ remotionRoot,
22
+ entryPoint,
23
+ });
24
+ (0, can_update_default_props_1.checkIfTypeScriptFile)(compositionFile);
25
+ const fileContents = (0, node_fs_1.readFileSync)(compositionFile, 'utf-8');
26
26
  const result = (0, codemods_1.setCompositionDefaultProps)({
27
27
  project: {
28
- files: { [projectInfo.rootFile]: fileContents },
28
+ files: { [compositionFile]: fileContents },
29
29
  rootDir: remotionRoot,
30
30
  },
31
- compositionFile: projectInfo.rootFile,
31
+ compositionFile,
32
32
  compositionId,
33
33
  defaultProps: JSON.parse(defaultProps),
34
34
  enumPaths,
@@ -36,7 +36,7 @@ const updateDefaultPropsHandler = ({ input: { compositionId, defaultProps, enumP
36
36
  const { logLine } = result;
37
37
  const output = (_b = (_a = result.changes[0]) === null || _a === void 0 ? void 0 : _a.nextContents) !== null && _b !== void 0 ? _b : fileContents;
38
38
  (0, undo_stack_1.pushToUndoStack)({
39
- filePath: projectInfo.rootFile,
39
+ filePath: compositionFile,
40
40
  oldContents: fileContents,
41
41
  newContents: null,
42
42
  logLevel,
@@ -50,17 +50,17 @@ const updateDefaultPropsHandler = ({ input: { compositionId, defaultProps, enumP
50
50
  suppressHmrOnFileRestore: true,
51
51
  nodePathRemappings: null,
52
52
  });
53
- (0, undo_stack_1.suppressUndoStackInvalidation)(projectInfo.rootFile);
54
- (0, watch_ignore_next_change_1.suppressBundlerUpdateForFile)(projectInfo.rootFile);
53
+ (0, undo_stack_1.suppressUndoStackInvalidation)(compositionFile);
54
+ (0, watch_ignore_next_change_1.suppressBundlerUpdateForFile)(compositionFile);
55
55
  (0, file_watcher_1.writeFileAndNotifyFileWatchers)({
56
- file: projectInfo.rootFile,
56
+ file: compositionFile,
57
57
  content: output,
58
58
  originatorClientId: undefined,
59
59
  metadata: null,
60
60
  });
61
61
  const locationLabel = (0, format_log_file_location_1.formatLogFileLocation)({
62
62
  remotionRoot,
63
- absolutePath: projectInfo.rootFile,
63
+ absolutePath: compositionFile,
64
64
  line: logLine,
65
65
  });
66
66
  renderer_1.RenderInternals.Log.info({ indent: false, logLevel }, `${(0, source_file_write_queue_1.getCodemodTimingPrefix)(logLevel)}${renderer_1.RenderInternals.chalk.blueBright(`${locationLabel}`)} Updated default props for "${compositionId}"`);
@@ -144,8 +144,13 @@ const subscribeToSequencePropsWatchers = ({ fileName, line, column, nodePath: pr
144
144
  return initialResult;
145
145
  }
146
146
  const absolutePath = node_path_1.default.resolve(remotionRoot, fileName);
147
- // Cache the resolved nodePath for future lookups with stale source maps
148
- (0, node_path_cache_1.setCachedNodePath)(fileName, line, column, initialResult.nodePath.nodePath);
147
+ // A preferred path may have been remapped while these coordinates still
148
+ // come from the previous bundle. Caching that pair can make a later mount
149
+ // at the same location inherit a different sibling's props after Refresh.
150
+ // Only a location-based subscription can establish a location cache entry.
151
+ if (preferredNodePath === null) {
152
+ (0, node_path_cache_1.setCachedNodePath)(fileName, line, column, initialResult.nodePath.nodePath);
153
+ }
149
154
  const { nodePath } = initialResult;
150
155
  const watcherKey = getWatcherKey(nodePath, assetKeys);
151
156
  const existingWatcher = (_a = sequencePropsWatchers[clientId]) === null || _a === void 0 ? void 0 : _a[watcherKey];
@@ -4,7 +4,7 @@ export interface UndoEntryDescription {
4
4
  undoMessage: string;
5
5
  redoMessage: string;
6
6
  }
7
- type UndoEntryType = 'visual-control' | 'default-props' | 'sequence-props' | 'effect-props' | 'keyframe-add' | 'keyframe-delete' | 'add-effect' | 'delete-effect' | 'duplicate-effect' | 'paste-effects' | 'reorder-effect' | 'reorder-sequence' | 'delete-nodes' | 'duplicate-nodes' | 'wrap-node' | 'precompose-jsx-nodes' | 'split-sequences' | 'split-video-from-audio' | 'insert-basic-captions' | 'replace-video-source' | 'insert-composition-element' | 'delete-composition' | 'rename-composition' | 'update-composition-metadata' | 'new-composition' | 'duplicate-composition' | 'move-composition-or-folder' | 'new-folder' | 'delete-folder' | 'rename-folder';
7
+ type UndoEntryType = 'visual-control' | 'default-props' | 'sequence-props' | 'effect-props' | 'keyframe-add' | 'keyframe-delete' | 'add-effect' | 'delete-effect' | 'duplicate-effect' | 'paste-effects' | 'reorder-effect' | 'reorder-sequence' | 'delete-nodes' | 'duplicate-nodes' | 'wrap-node' | 'unwrap-node' | 'precompose-jsx-nodes' | 'split-sequences' | 'split-video-from-audio' | 'insert-basic-captions' | 'replace-video-source' | 'insert-composition-element' | 'delete-composition' | 'rename-composition' | 'update-composition-metadata' | 'new-composition' | 'duplicate-composition' | 'move-composition-or-folder' | 'new-folder' | 'delete-folder' | 'rename-folder';
8
8
  type UndoEntrySnapshot = {
9
9
  filePath: string;
10
10
  oldContents: string | null;
package/package.json CHANGED
@@ -3,7 +3,7 @@
3
3
  "url": "https://github.com/remotion-dev/remotion/tree/main/packages/studio-server"
4
4
  },
5
5
  "name": "@remotion/studio-server",
6
- "version": "4.0.536",
6
+ "version": "4.0.537",
7
7
  "description": "Run a Remotion Studio with a server backend",
8
8
  "main": "dist",
9
9
  "scripts": {
@@ -23,7 +23,7 @@
23
23
  "access": "public"
24
24
  },
25
25
  "dependencies": {
26
- "@remotion/studio-protocol": "4.0.536",
26
+ "@remotion/studio-protocol": "4.0.537",
27
27
  "@babel/types": "7.24.0",
28
28
  "@babel/parser": "7.24.1",
29
29
  "@svgr/core": "8.1.0",
@@ -31,12 +31,12 @@
31
31
  "kiwi-schema": "0.5.0",
32
32
  "semver": "7.5.3",
33
33
  "zod": "4.5.4",
34
- "remotion": "4.0.536",
34
+ "remotion": "4.0.537",
35
35
  "recast": "0.23.21",
36
- "@remotion/bundler": "4.0.536",
37
- "@remotion/renderer": "4.0.536",
38
- "@remotion/codemods": "4.0.536",
39
- "@remotion/studio-shared": "4.0.536",
36
+ "@remotion/bundler": "4.0.537",
37
+ "@remotion/renderer": "4.0.537",
38
+ "@remotion/codemods": "4.0.537",
39
+ "@remotion/studio-shared": "4.0.537",
40
40
  "memfs": "3.4.3",
41
41
  "open": "8.4.2"
42
42
  },
@@ -44,7 +44,7 @@
44
44
  "ast-types": "0.16.1",
45
45
  "react": "19.2.3",
46
46
  "@types/semver": "7.5.3",
47
- "@remotion/eslint-config-internal": "4.0.536",
47
+ "@remotion/eslint-config-internal": "4.0.537",
48
48
  "eslint": "9.19.0",
49
49
  "prettier": "3.8.1",
50
50
  "@types/node": "20.12.14",