@remotion/studio-server 4.0.506 → 4.0.508

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 (101) hide show
  1. package/dist/codemods/delete-jsx-node.d.ts +4 -0
  2. package/dist/codemods/delete-jsx-node.js +8 -0
  3. package/dist/codemods/duplicate-jsx-node.d.ts +2 -0
  4. package/dist/codemods/duplicate-jsx-node.js +8 -0
  5. package/dist/codemods/effect-param-expression.js +2 -0
  6. package/dist/codemods/get-node-path-remappings.d.ts +13 -0
  7. package/dist/codemods/get-node-path-remappings.js +87 -0
  8. package/dist/codemods/reorder-sequence.d.ts +2 -1
  9. package/dist/codemods/reorder-sequence.js +8 -0
  10. package/dist/codemods/split-jsx-sequence.d.ts +2 -0
  11. package/dist/codemods/split-jsx-sequence.js +8 -0
  12. package/dist/codemods/update-keyframes/update-keyframes.js +2 -0
  13. package/dist/file-watcher.d.ts +11 -1
  14. package/dist/file-watcher.js +16 -5
  15. package/dist/helpers/coding-agent-registry.d.ts +34 -0
  16. package/dist/helpers/coding-agent-registry.js +442 -21
  17. package/dist/helpers/editor-registry.d.ts +1 -0
  18. package/dist/helpers/editor-registry.js +31 -3
  19. package/dist/helpers/finder-artwork.d.ts +1 -0
  20. package/dist/helpers/finder-artwork.js +4 -0
  21. package/dist/helpers/open-in-editor.js +5 -5
  22. package/dist/helpers/parse-keyframe-easing-expression.js +3 -0
  23. package/dist/helpers/resolve-composition-component.d.ts +2 -1
  24. package/dist/helpers/resolve-composition-component.js +60 -68
  25. package/dist/helpers/resolve-editor.d.ts +2 -0
  26. package/dist/helpers/resolve-editor.js +4 -1
  27. package/dist/helpers/terminal-artwork.d.ts +6 -0
  28. package/dist/helpers/terminal-artwork.js +14 -0
  29. package/dist/helpers/terminal-registry.d.ts +36 -0
  30. package/dist/helpers/terminal-registry.js +401 -0
  31. package/dist/index.d.ts +7 -2
  32. package/dist/preview-server/api-routes.js +7 -4
  33. package/dist/preview-server/handler.d.ts +1 -1
  34. package/dist/preview-server/live-events.d.ts +1 -0
  35. package/dist/preview-server/live-events.js +3 -1
  36. package/dist/preview-server/routes/add-effect-keyframe.js +7 -1
  37. package/dist/preview-server/routes/add-effect.js +7 -1
  38. package/dist/preview-server/routes/add-keyframes.js +10 -2
  39. package/dist/preview-server/routes/add-render.js +2 -0
  40. package/dist/preview-server/routes/add-sequence-keyframe.js +7 -1
  41. package/dist/preview-server/routes/app-icon.d.ts +6 -0
  42. package/dist/preview-server/routes/app-icon.js +66 -0
  43. package/dist/preview-server/routes/apply-codemod.js +15 -2
  44. package/dist/preview-server/routes/apply-visual-control-change.js +7 -1
  45. package/dist/preview-server/routes/batch-update-keyframe-settings.js +10 -2
  46. package/dist/preview-server/routes/can-update-sequence-props.d.ts +1 -0
  47. package/dist/preview-server/routes/can-update-sequence-props.js +33 -9
  48. package/dist/preview-server/routes/copy-render-output-to-asset.d.ts +3 -0
  49. package/dist/preview-server/routes/copy-render-output-to-asset.js +58 -0
  50. package/dist/preview-server/routes/default-coding-agent.d.ts +2 -6
  51. package/dist/preview-server/routes/default-coding-agent.js +19 -88
  52. package/dist/preview-server/routes/default-editor.d.ts +1 -6
  53. package/dist/preview-server/routes/default-editor.js +13 -113
  54. package/dist/preview-server/routes/delete-effect.js +7 -1
  55. package/dist/preview-server/routes/delete-jsx-node.js +16 -2
  56. package/dist/preview-server/routes/delete-keyframes.js +10 -2
  57. package/dist/preview-server/routes/duplicate-effect.js +7 -1
  58. package/dist/preview-server/routes/duplicate-jsx-node.js +17 -5
  59. package/dist/preview-server/routes/insert-element.js +23 -3
  60. package/dist/preview-server/routes/insert-jsx-element.js +17 -2
  61. package/dist/preview-server/routes/move-keyframes.js +10 -2
  62. package/dist/preview-server/routes/open-in-editor.js +1 -1
  63. package/dist/preview-server/routes/open-in-terminal.d.ts +3 -0
  64. package/dist/preview-server/routes/open-in-terminal.js +17 -0
  65. package/dist/preview-server/routes/paste-effects.js +7 -1
  66. package/dist/preview-server/routes/reorder-effect.js +7 -1
  67. package/dist/preview-server/routes/reorder-sequence.js +17 -2
  68. package/dist/preview-server/routes/save-effect-props.js +7 -1
  69. package/dist/preview-server/routes/save-multiple-effect-props.js +10 -2
  70. package/dist/preview-server/routes/save-sequence-props.js +10 -2
  71. package/dist/preview-server/routes/split-jsx-sequence.js +17 -6
  72. package/dist/preview-server/routes/update-config.d.ts +7 -0
  73. package/dist/preview-server/routes/update-config.js +193 -0
  74. package/dist/preview-server/routes/update-default-props.js +7 -1
  75. package/dist/preview-server/routes/update-effect-keyframe-settings.js +7 -1
  76. package/dist/preview-server/routes/update-sequence-keyframe-settings.js +7 -1
  77. package/dist/preview-server/sequence-node-path-mutation.d.ts +7 -0
  78. package/dist/preview-server/sequence-node-path-mutation.js +21 -0
  79. package/dist/preview-server/sequence-props-watchers.js +15 -6
  80. package/dist/preview-server/start-server.d.ts +1 -1
  81. package/dist/preview-server/studio-protocol/handle-discovery.js +3 -4
  82. package/dist/preview-server/studio-protocol/handle-install.js +1 -1
  83. package/dist/preview-server/studio-protocol/handle-license-key.js +2 -2
  84. package/dist/preview-server/studio-protocol/origin-policy.d.ts +2 -5
  85. package/dist/preview-server/studio-protocol/origin-policy.js +6 -30
  86. package/dist/preview-server/undo-stack.d.ts +7 -13
  87. package/dist/preview-server/undo-stack.js +58 -5
  88. package/dist/routes.d.ts +1 -1
  89. package/dist/routes.js +8 -1
  90. package/dist/start-studio.d.ts +1 -1
  91. package/package.json +8 -8
  92. package/web/coding-agent-icons/claude-code.png +0 -0
  93. package/web/coding-agent-icons/codex.png +0 -0
  94. package/web/coding-agent-icons/copilot.png +0 -0
  95. package/web/coding-agent-icons/cursor.png +0 -0
  96. package/dist/preview-server/routes/delete-effect-keyframe.d.ts +0 -3
  97. package/dist/preview-server/routes/delete-effect-keyframe.js +0 -89
  98. package/dist/preview-server/routes/delete-sequence-keyframe.d.ts +0 -3
  99. package/dist/preview-server/routes/delete-sequence-keyframe.js +0 -82
  100. package/dist/preview-server/routes/save-props-mutex.d.ts +0 -1
  101. package/dist/preview-server/routes/save-props-mutex.js +0 -11
@@ -7,6 +7,7 @@ const split_jsx_sequence_1 = require("../../codemods/split-jsx-sequence");
7
7
  const file_watcher_1 = require("../../file-watcher");
8
8
  const resolve_file_inside_project_1 = require("../../helpers/resolve-file-inside-project");
9
9
  const format_log_file_location_1 = require("../format-log-file-location");
10
+ const sequence_node_path_mutation_1 = require("../sequence-node-path-mutation");
10
11
  const undo_stack_1 = require("../undo-stack");
11
12
  const log_update_1 = require("./log-updates/log-update");
12
13
  const source_file_write_queue_1 = require("./source-file-write-queue");
@@ -19,11 +20,14 @@ const splitJsxSequenceHandler = ({ input: { fileName, nodePath, splitFrame }, re
19
20
  action: 'modify',
20
21
  });
21
22
  const fileContents = (0, node_fs_1.readFileSync)(absolutePath, 'utf-8');
22
- const { output, formatted, nodeLabel, logLine } = await (0, split_jsx_sequence_1.splitJsxSequence)({
23
- input: fileContents,
24
- nodePath,
25
- splitFrame,
26
- });
23
+ const { output, formatted, nodeLabel, logLine, nodePathRemappings } = await (0, split_jsx_sequence_1.splitJsxSequence)({ input: fileContents, nodePath, splitFrame });
24
+ const nodePathMutation = (0, sequence_node_path_mutation_1.broadcastSequenceNodePathMutation)([
25
+ {
26
+ absolutePath,
27
+ remappings: nodePathRemappings,
28
+ restoredNodePaths: [],
29
+ },
30
+ ]);
27
31
  (0, undo_stack_1.pushToUndoStack)({
28
32
  filePath: absolutePath,
29
33
  oldContents: fileContents,
@@ -37,9 +41,15 @@ const splitJsxSequenceHandler = ({ input: { fileName, nodePath, splitFrame }, re
37
41
  },
38
42
  entryType: 'split-jsx-sequence',
39
43
  suppressHmrOnFileRestore: false,
44
+ nodePathRemappings,
40
45
  });
41
46
  (0, undo_stack_1.suppressUndoStackInvalidation)(absolutePath);
42
- (0, file_watcher_1.writeFileAndNotifyFileWatchers)(absolutePath, output, undefined);
47
+ (0, file_watcher_1.writeFileAndNotifyFileWatchers)({
48
+ file: absolutePath,
49
+ content: output,
50
+ originatorClientId: undefined,
51
+ metadata: { skipSequencePropsUpdate: true },
52
+ });
43
53
  const locationLabel = (0, format_log_file_location_1.formatLogFileLocation)({
44
54
  remotionRoot,
45
55
  absolutePath,
@@ -53,6 +63,7 @@ const splitJsxSequenceHandler = ({ input: { fileName, nodePath, splitFrame }, re
53
63
  (0, undo_stack_1.printUndoHint)(logLevel);
54
64
  return {
55
65
  success: true,
66
+ nodePathMutation,
56
67
  };
57
68
  }
58
69
  catch (err) {
@@ -0,0 +1,7 @@
1
+ import { type ConfigUpdate, type UpdateConfigRequest, type UpdateConfigResponse } from '@remotion/studio-shared';
2
+ import type { ApiHandler } from '../api-types';
3
+ export declare const updateConfigFile: ({ configContents, updates, }: {
4
+ readonly configContents: string;
5
+ readonly updates: ConfigUpdate[];
6
+ }) => string;
7
+ export declare const updateConfigHandler: ApiHandler<UpdateConfigRequest, UpdateConfigResponse>;
@@ -0,0 +1,193 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || (function () {
19
+ var ownKeys = function(o) {
20
+ ownKeys = Object.getOwnPropertyNames || function (o) {
21
+ var ar = [];
22
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
23
+ return ar;
24
+ };
25
+ return ownKeys(o);
26
+ };
27
+ return function (mod) {
28
+ if (mod && mod.__esModule) return mod;
29
+ var result = {};
30
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
31
+ __setModuleDefault(result, mod);
32
+ return result;
33
+ };
34
+ })();
35
+ Object.defineProperty(exports, "__esModule", { value: true });
36
+ exports.updateConfigHandler = exports.updateConfigFile = void 0;
37
+ const node_fs_1 = require("node:fs");
38
+ const renderer_1 = require("@remotion/renderer");
39
+ const studio_shared_1 = require("@remotion/studio-shared");
40
+ const recast = __importStar(require("recast"));
41
+ const parse_ast_1 = require("../../codemods/parse-ast");
42
+ const file_watcher_1 = require("../../file-watcher");
43
+ const editor_registry_1 = require("../../helpers/editor-registry");
44
+ const validSetterName = /^set[A-Z][A-Za-z0-9]*$/;
45
+ const isConfigValue = (value) => {
46
+ if (value === null ||
47
+ typeof value === 'string' ||
48
+ typeof value === 'boolean') {
49
+ return true;
50
+ }
51
+ if (typeof value === 'number') {
52
+ return Number.isFinite(value);
53
+ }
54
+ if (Array.isArray(value)) {
55
+ return value.every(isConfigValue);
56
+ }
57
+ if (typeof value === 'object') {
58
+ if (Object.getPrototypeOf(value) !== Object.prototype &&
59
+ Object.getPrototypeOf(value) !== null) {
60
+ return false;
61
+ }
62
+ return Object.values(value).every(isConfigValue);
63
+ }
64
+ return false;
65
+ };
66
+ const validateUpdates = (updates) => {
67
+ if (!Array.isArray(updates) || updates.length === 0) {
68
+ return 'At least one config update is required.';
69
+ }
70
+ const setters = new Set();
71
+ for (const update of updates) {
72
+ if (typeof update !== 'object' || update === null) {
73
+ return 'Each config update must be an object.';
74
+ }
75
+ const { setter, type } = update;
76
+ if (typeof setter !== 'string' ||
77
+ !validSetterName.test(setter) ||
78
+ !(setter in studio_shared_1.configMethodLifecycles)) {
79
+ return `Invalid config setter: ${JSON.stringify(setter)}.`;
80
+ }
81
+ if (setters.has(setter)) {
82
+ return `The config setter ${setter} was specified more than once.`;
83
+ }
84
+ setters.add(setter);
85
+ if (type === 'delete') {
86
+ continue;
87
+ }
88
+ if (type !== 'set' ||
89
+ !('value' in update) ||
90
+ !isConfigValue(update.value)) {
91
+ return `Invalid value for Config.${setter}().`;
92
+ }
93
+ }
94
+ return null;
95
+ };
96
+ const updateConfigFile = ({ configContents, updates, }) => {
97
+ const setters = new Set(updates.map(({ setter }) => setter));
98
+ const ast = (0, parse_ast_1.parseAst)(configContents);
99
+ recast.types.visit(ast.program, {
100
+ visitExpressionStatement(path) {
101
+ const { expression } = path.node;
102
+ if (expression.type === 'CallExpression' &&
103
+ expression.callee.type === 'MemberExpression' &&
104
+ !expression.callee.computed &&
105
+ expression.callee.object.type === 'Identifier' &&
106
+ expression.callee.object.name === 'Config' &&
107
+ expression.callee.property.type === 'Identifier' &&
108
+ setters.has(expression.callee.property.name)) {
109
+ path.prune();
110
+ return false;
111
+ }
112
+ this.traverse(path);
113
+ },
114
+ });
115
+ let updatedConfig = recast.print(ast, { lineTerminator: '\n' }).code;
116
+ for (const update of updates) {
117
+ if (update.type === 'delete') {
118
+ continue;
119
+ }
120
+ const serializedValue = JSON.stringify(update.value)
121
+ .replaceAll('\u2028', '\\u2028')
122
+ .replaceAll('\u2029', '\\u2029');
123
+ const statement = (0, parse_ast_1.parseAst)(`Config.${update.setter}(${serializedValue});`)
124
+ .program.body[0];
125
+ const separator = updatedConfig.endsWith('\n') ? '' : '\n';
126
+ updatedConfig += `${separator}${recast.prettyPrint(statement, {
127
+ lineTerminator: '\n',
128
+ quote: 'single',
129
+ useTabs: true,
130
+ }).code}\n`;
131
+ }
132
+ return updatedConfig;
133
+ };
134
+ exports.updateConfigFile = updateConfigFile;
135
+ const updateConfigHandler = async ({ input, configFile }) => {
136
+ if (configFile === null || configFile === undefined) {
137
+ return {
138
+ success: false,
139
+ reason: 'No Remotion config file was loaded.',
140
+ };
141
+ }
142
+ const validationError = validateUpdates(input.updates);
143
+ if (validationError !== null) {
144
+ return { success: false, reason: validationError };
145
+ }
146
+ for (const update of input.updates) {
147
+ if (update.type === 'delete') {
148
+ continue;
149
+ }
150
+ if (update.setter === 'setDefaultCodingAgent' &&
151
+ (typeof update.value !== 'string' ||
152
+ !renderer_1.defaultCodingAgentIds.includes(update.value))) {
153
+ return {
154
+ success: false,
155
+ reason: `Unknown coding agent: ${JSON.stringify(update.value)}`,
156
+ };
157
+ }
158
+ if (update.setter === 'setDefaultEditor') {
159
+ if (typeof update.value !== 'string' ||
160
+ !renderer_1.defaultEditorIds.includes(update.value)) {
161
+ return {
162
+ success: false,
163
+ reason: `Unknown editor: ${JSON.stringify(update.value)}`,
164
+ };
165
+ }
166
+ const installedEditors = await (0, editor_registry_1.getAvailableEditors)();
167
+ if (!installedEditors.some(({ id }) => id === update.value)) {
168
+ return {
169
+ success: false,
170
+ reason: 'The selected editor is not installed.',
171
+ };
172
+ }
173
+ }
174
+ if (update.setter === 'setPublicLicenseKey' &&
175
+ (typeof update.value !== 'string' ||
176
+ (update.value !== 'free-license' &&
177
+ !update.value.startsWith('rm_pub_')))) {
178
+ return {
179
+ success: false,
180
+ reason: 'The public license key must start with "rm_pub_" or be "free-license".',
181
+ };
182
+ }
183
+ }
184
+ const configContents = (0, node_fs_1.readFileSync)(configFile, 'utf8');
185
+ (0, file_watcher_1.writeFileAndNotifyFileWatchers)({
186
+ file: configFile,
187
+ content: (0, exports.updateConfigFile)({ configContents, updates: input.updates }),
188
+ originatorClientId: input.clientId,
189
+ metadata: null,
190
+ });
191
+ return { success: true };
192
+ };
193
+ exports.updateConfigHandler = updateConfigHandler;
@@ -45,10 +45,16 @@ const updateDefaultPropsHandler = ({ input: { compositionId, defaultProps, enumP
45
45
  },
46
46
  entryType: 'default-props',
47
47
  suppressHmrOnFileRestore: true,
48
+ nodePathRemappings: null,
48
49
  });
49
50
  (0, undo_stack_1.suppressUndoStackInvalidation)(projectInfo.rootFile);
50
51
  (0, watch_ignore_next_change_1.suppressBundlerUpdateForFile)(projectInfo.rootFile);
51
- (0, file_watcher_1.writeFileAndNotifyFileWatchers)(projectInfo.rootFile, output, undefined);
52
+ (0, file_watcher_1.writeFileAndNotifyFileWatchers)({
53
+ file: projectInfo.rootFile,
54
+ content: output,
55
+ originatorClientId: undefined,
56
+ metadata: null,
57
+ });
52
58
  const locationLabel = (0, format_log_file_location_1.formatLogFileLocation)({
53
59
  remotionRoot,
54
60
  absolutePath: projectInfo.rootFile,
@@ -62,10 +62,16 @@ const updateEffectKeyframeSettingsHandler = ({ input: { fileName, sequenceNodePa
62
62
  },
63
63
  entryType: 'effect-props',
64
64
  suppressHmrOnFileRestore: true,
65
+ nodePathRemappings: null,
65
66
  });
66
67
  (0, undo_stack_1.suppressUndoStackInvalidation)(absolutePath);
67
68
  (0, watch_ignore_next_change_1.suppressBundlerUpdateForFile)(absolutePath);
68
- (0, file_watcher_1.writeFileAndNotifyFileWatchers)(absolutePath, output, clientId);
69
+ (0, file_watcher_1.writeFileAndNotifyFileWatchers)({
70
+ file: absolutePath,
71
+ content: output,
72
+ originatorClientId: clientId,
73
+ metadata: null,
74
+ });
69
75
  (0, log_effect_update_1.logEffectUpdate)({
70
76
  fileRelativeToRoot,
71
77
  line: logLine,
@@ -58,10 +58,16 @@ const updateSequenceKeyframeSettingsHandler = ({ input: { fileName, nodePath, ke
58
58
  },
59
59
  entryType: 'sequence-props',
60
60
  suppressHmrOnFileRestore: true,
61
+ nodePathRemappings: null,
61
62
  });
62
63
  (0, undo_stack_1.suppressUndoStackInvalidation)(absolutePath);
63
64
  (0, watch_ignore_next_change_1.suppressBundlerUpdateForFile)(absolutePath);
64
- (0, file_watcher_1.writeFileAndNotifyFileWatchers)(absolutePath, output, clientId);
65
+ (0, file_watcher_1.writeFileAndNotifyFileWatchers)({
66
+ file: absolutePath,
67
+ content: output,
68
+ originatorClientId: clientId,
69
+ metadata: null,
70
+ });
65
71
  (0, log_update_1.logUpdate)({
66
72
  fileRelativeToRoot,
67
73
  line: logLine,
@@ -0,0 +1,7 @@
1
+ import type { SequenceNodePathMutation, SequenceNodePathRemapping } from '@remotion/studio-shared';
2
+ import type { SequenceNodePath } from 'remotion';
3
+ export declare const broadcastSequenceNodePathMutation: (files: {
4
+ absolutePath: string;
5
+ remappings: SequenceNodePathRemapping[];
6
+ restoredNodePaths: SequenceNodePath[];
7
+ }[]) => SequenceNodePathMutation;
@@ -0,0 +1,21 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.broadcastSequenceNodePathMutation = void 0;
4
+ const node_crypto_1 = require("node:crypto");
5
+ const live_events_1 = require("./live-events");
6
+ const mutationSessionId = (0, node_crypto_1.randomUUID)();
7
+ let mutationCounter = 0;
8
+ const broadcastSequenceNodePathMutation = (files) => {
9
+ var _a;
10
+ mutationCounter++;
11
+ const mutation = {
12
+ mutationId: `${mutationSessionId}:${mutationCounter}`,
13
+ files,
14
+ };
15
+ (_a = (0, live_events_1.getLiveEventsListener)()) === null || _a === void 0 ? void 0 : _a.sendEventToClient({
16
+ type: 'sequence-node-paths-remapped',
17
+ mutation,
18
+ });
19
+ return mutation;
20
+ };
21
+ exports.broadcastSequenceNodePathMutation = broadcastSequenceNodePathMutation;
@@ -122,11 +122,16 @@ const subscribeToSequencePropsWatchers = ({ fileName, line, column, nodePath: pr
122
122
  (0, node_path_cache_1.setCachedNodePath)(fileName, line, column, initialResult.nodePath.nodePath);
123
123
  const { nodePath } = initialResult;
124
124
  const watcherKey = getWatcherKey(nodePath, assetKeys);
125
- // If a watcher already exists for this key, just bump the ref count
126
- if ((_a = sequencePropsWatchers[clientId]) === null || _a === void 0 ? void 0 : _a[watcherKey]) {
127
- sequencePropsWatchers[clientId][watcherKey].refCount++;
125
+ const existingWatcher = (_a = sequencePropsWatchers[clientId]) === null || _a === void 0 ? void 0 : _a[watcherKey];
126
+ if (existingWatcher) {
127
+ existingWatcher.refCount++;
128
128
  return initialResult;
129
129
  }
130
+ const watcherInfo = {
131
+ unwatch: () => undefined,
132
+ refCount: 1,
133
+ currentNodePath: nodePath,
134
+ };
130
135
  const { unwatch } = (0, file_watcher_1.installFileWatcher)({
131
136
  file: absolutePath,
132
137
  existenceOnly: false,
@@ -137,10 +142,13 @@ const subscribeToSequencePropsWatchers = ({ fileName, line, column, nodePath: pr
137
142
  if (event.originatorClientId === clientId) {
138
143
  return;
139
144
  }
145
+ if (event.type === 'changed' && event.skipSequencePropsUpdate) {
146
+ return;
147
+ }
140
148
  try {
141
149
  const result = (0, can_update_sequence_props_1.computeSequencePropsStatusFromContent)({
142
150
  fileContents: event.content,
143
- nodePath: nodePath.nodePath,
151
+ nodePath: watcherInfo.currentNodePath.nodePath,
144
152
  componentIdentity,
145
153
  keys,
146
154
  assetKeys,
@@ -158,7 +166,7 @@ const subscribeToSequencePropsWatchers = ({ fileName, line, column, nodePath: pr
158
166
  listener.sendEventToClientId(clientId, {
159
167
  type: 'sequence-props-updated',
160
168
  fileName,
161
- nodePath,
169
+ nodePath: watcherInfo.currentNodePath,
162
170
  result,
163
171
  });
164
172
  });
@@ -180,10 +188,11 @@ const subscribeToSequencePropsWatchers = ({ fileName, line, column, nodePath: pr
180
188
  }
181
189
  },
182
190
  });
191
+ watcherInfo.unwatch = unwatch;
183
192
  if (!sequencePropsWatchers[clientId]) {
184
193
  sequencePropsWatchers[clientId] = {};
185
194
  }
186
- sequencePropsWatchers[clientId][watcherKey] = { unwatch, refCount: 1 };
195
+ sequencePropsWatchers[clientId][watcherKey] = watcherInfo;
187
196
  return initialResult;
188
197
  };
189
198
  exports.subscribeToSequencePropsWatchers = subscribeToSequencePropsWatchers;
@@ -42,7 +42,7 @@ export declare const startServer: (options: {
42
42
  forceNew: boolean;
43
43
  rspack: boolean;
44
44
  getStudioRuntimeConfig: () => StudioRuntimeConfig;
45
- getDefaultCodingAgent: () => "claude-code" | "codex" | "cursor" | "github-copilot" | null;
45
+ getDefaultCodingAgent: () => "claude-code" | "codex" | "copilot" | "cursor" | null;
46
46
  getDefaultEditor: () => DefaultEditor | null;
47
47
  configFile: string | null;
48
48
  }) => Promise<StartServerResult>;
@@ -43,7 +43,7 @@ const getProject = ({ gitSource, remotionRoot, }) => (0, studio_shared_1.getProj
43
43
  resolvedRemotionRoot: remotionRoot,
44
44
  });
45
45
  const handleStudioProtocolDiscovery = ({ gitSource, liveEventsServer, remotionRoot, request, response, }) => {
46
- (0, origin_policy_1.setStudioProtocolCorsHeaders)({ licenseKey: false, request, response });
46
+ (0, origin_policy_1.setStudioProtocolCorsHeaders)({ request, response });
47
47
  const requestOrigin = (0, origin_policy_1.getAllowedStudioProtocolOrigin)(request.headers.origin);
48
48
  if (requestOrigin === null) {
49
49
  (0, protocol_response_1.writeStudioProtocolError)({
@@ -77,12 +77,11 @@ const handleStudioProtocolDiscovery = ({ gitSource, liveEventsServer, remotionRo
77
77
  purpose: 'install-element',
78
78
  target: installTarget,
79
79
  });
80
- const licenseKeyOrigin = (0, origin_policy_1.getAllowedLicenseKeyOrigin)(request.headers.origin);
81
- const issuedLicenseKeyTarget = target === null || licenseKeyOrigin === null
80
+ const issuedLicenseKeyTarget = target === null
82
81
  ? null
83
82
  : (0, element_install_state_1.issueStudioProtocolTarget)({
84
83
  now,
85
- origin: licenseKeyOrigin,
84
+ origin: requestOrigin,
86
85
  purpose: 'set-license-key',
87
86
  target,
88
87
  });
@@ -45,7 +45,7 @@ const deliverElementInstall = ({ element, focusStudioTab, liveEventsServer, orig
45
45
  return delivered;
46
46
  };
47
47
  const handleStudioProtocolInstall = async ({ focusStudioTab, liveEventsServer, request, response, }) => {
48
- (0, origin_policy_1.setStudioProtocolCorsHeaders)({ licenseKey: false, request, response });
48
+ (0, origin_policy_1.setStudioProtocolCorsHeaders)({ request, response });
49
49
  const requestOrigin = (0, origin_policy_1.getAllowedStudioProtocolOrigin)(request.headers.origin);
50
50
  if (requestOrigin === null) {
51
51
  (0, protocol_response_1.writeStudioProtocolError)({
@@ -16,8 +16,8 @@ const studioProtocolLicenseKeyRequestSchema = zod_1.z.object({
16
16
  });
17
17
  const MAX_STUDIO_PROTOCOL_LICENSE_KEY_BODY_SIZE = 4096;
18
18
  const handleStudioProtocolLicenseKey = async ({ configFile, focusStudioTab, liveEventsServer, request, response, }) => {
19
- (0, origin_policy_1.setStudioProtocolCorsHeaders)({ licenseKey: true, request, response });
20
- const requestOrigin = (0, origin_policy_1.getAllowedLicenseKeyOrigin)(request.headers.origin);
19
+ (0, origin_policy_1.setStudioProtocolCorsHeaders)({ request, response });
20
+ const requestOrigin = (0, origin_policy_1.getAllowedStudioProtocolOrigin)(request.headers.origin);
21
21
  if (requestOrigin === null) {
22
22
  (0, protocol_response_1.writeStudioProtocolError)({
23
23
  code: 'unsupported-origin',
@@ -1,13 +1,10 @@
1
1
  import type { IncomingMessage, ServerResponse } from 'node:http';
2
2
  export declare const getAllowedStudioProtocolOrigin: (origin: string | undefined) => string | null;
3
- export declare const getAllowedLicenseKeyOrigin: (origin: string | undefined) => string | null;
4
- export declare const setStudioProtocolCorsHeaders: ({ licenseKey, request, response, }: {
5
- readonly licenseKey: boolean;
3
+ export declare const setStudioProtocolCorsHeaders: ({ request, response, }: {
6
4
  readonly request: IncomingMessage;
7
5
  readonly response: ServerResponse<IncomingMessage>;
8
6
  }) => void;
9
- export declare const handleStudioProtocolOptions: ({ licenseKey, request, response, }: {
10
- readonly licenseKey: boolean;
7
+ export declare const handleStudioProtocolOptions: ({ request, response, }: {
11
8
  readonly request: IncomingMessage;
12
9
  readonly response: ServerResponse<IncomingMessage>;
13
10
  }) => Promise<void>;
@@ -1,6 +1,6 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.handleStudioProtocolOptions = exports.setStudioProtocolCorsHeaders = exports.getAllowedLicenseKeyOrigin = exports.getAllowedStudioProtocolOrigin = void 0;
3
+ exports.handleStudioProtocolOptions = exports.setStudioProtocolCorsHeaders = exports.getAllowedStudioProtocolOrigin = void 0;
4
4
  const isLoopbackHttp = (url) => url.protocol === 'http:' &&
5
5
  (url.hostname === 'localhost' || url.hostname === '127.0.0.1');
6
6
  const getAllowedStudioProtocolOrigin = (origin) => {
@@ -19,30 +19,8 @@ const getAllowedStudioProtocolOrigin = (origin) => {
19
19
  }
20
20
  };
21
21
  exports.getAllowedStudioProtocolOrigin = getAllowedStudioProtocolOrigin;
22
- const getAllowedLicenseKeyOrigin = (origin) => {
23
- if (!origin) {
24
- return null;
25
- }
26
- try {
27
- const url = new URL(origin);
28
- if (isLoopbackHttp(url)) {
29
- return url.origin;
30
- }
31
- if (url.origin === 'https://remotion.pro' ||
32
- url.origin === 'https://www.remotion.pro') {
33
- return url.origin;
34
- }
35
- return null;
36
- }
37
- catch (_a) {
38
- return null;
39
- }
40
- };
41
- exports.getAllowedLicenseKeyOrigin = getAllowedLicenseKeyOrigin;
42
- const setStudioProtocolCorsHeaders = ({ licenseKey, request, response, }) => {
43
- const origin = licenseKey
44
- ? (0, exports.getAllowedLicenseKeyOrigin)(request.headers.origin)
45
- : (0, exports.getAllowedStudioProtocolOrigin)(request.headers.origin);
22
+ const setStudioProtocolCorsHeaders = ({ request, response, }) => {
23
+ const origin = (0, exports.getAllowedStudioProtocolOrigin)(request.headers.origin);
46
24
  if (origin === null) {
47
25
  return;
48
26
  }
@@ -54,11 +32,9 @@ const setStudioProtocolCorsHeaders = ({ licenseKey, request, response, }) => {
54
32
  response.setHeader('Access-Control-Allow-Private-Network', 'true');
55
33
  };
56
34
  exports.setStudioProtocolCorsHeaders = setStudioProtocolCorsHeaders;
57
- const handleStudioProtocolOptions = ({ licenseKey, request, response, }) => {
58
- (0, exports.setStudioProtocolCorsHeaders)({ licenseKey, request, response });
59
- const origin = licenseKey
60
- ? (0, exports.getAllowedLicenseKeyOrigin)(request.headers.origin)
61
- : (0, exports.getAllowedStudioProtocolOrigin)(request.headers.origin);
35
+ const handleStudioProtocolOptions = ({ request, response, }) => {
36
+ (0, exports.setStudioProtocolCorsHeaders)({ request, response });
37
+ const origin = (0, exports.getAllowedStudioProtocolOrigin)(request.headers.origin);
62
38
  response.writeHead(origin === null ? 403 : 204);
63
39
  response.end();
64
40
  return Promise.resolve();
@@ -1,4 +1,5 @@
1
1
  import type { LogLevel } from '@remotion/renderer';
2
+ import type { RedoResponse, SequenceNodePathRemapping, UndoResponse } from '@remotion/studio-shared';
2
3
  export interface UndoEntryDescription {
3
4
  undoMessage: string;
4
5
  redoMessage: string;
@@ -10,6 +11,7 @@ type UndoEntrySnapshot = {
10
11
  newContents: string | null;
11
12
  /** 1-based source line for terminal/IDE file links (e.g. path:line). */
12
13
  logLine: number;
14
+ nodePathRemappings: SequenceNodePathRemapping[] | null;
13
15
  };
14
16
  type UndoEntry = {
15
17
  filePath: string;
@@ -70,7 +72,7 @@ type UndoEntry = {
70
72
  } | {
71
73
  entryType: 'rename-folder';
72
74
  });
73
- export declare function pushToUndoStack({ filePath, oldContents, newContents, logLevel, remotionRoot, logLine, description, entryType, suppressHmrOnFileRestore }: {
75
+ export declare function pushToUndoStack({ filePath, oldContents, newContents, logLevel, remotionRoot, logLine, description, entryType, suppressHmrOnFileRestore, nodePathRemappings }: {
74
76
  filePath: string;
75
77
  oldContents: string;
76
78
  newContents: string | null;
@@ -80,6 +82,7 @@ export declare function pushToUndoStack({ filePath, oldContents, newContents, lo
80
82
  description: UndoEntryDescription;
81
83
  entryType: UndoEntryType;
82
84
  suppressHmrOnFileRestore: boolean;
85
+ nodePathRemappings: SequenceNodePathRemapping[] | null;
83
86
  }): void;
84
87
  export declare function pushTransactionToUndoStack({ snapshots, logLevel, remotionRoot, description, entryType, suppressHmrOnFileRestore }: {
85
88
  snapshots: Array<{
@@ -87,6 +90,7 @@ export declare function pushTransactionToUndoStack({ snapshots, logLevel, remoti
87
90
  oldContents: string | null;
88
91
  newContents: string | null;
89
92
  logLine: number;
93
+ nodePathRemappings: SequenceNodePathRemapping[] | null;
90
94
  }>;
91
95
  logLevel: LogLevel;
92
96
  remotionRoot: string;
@@ -105,18 +109,8 @@ export declare function pushToRedoStack({ filePath, oldContents, newContents, lo
105
109
  suppressHmrOnFileRestore: boolean;
106
110
  }): void;
107
111
  export declare function suppressUndoStackInvalidation(filePath: string): void;
108
- export declare function popUndo(): {
109
- success: true;
110
- } | {
111
- success: false;
112
- reason: string;
113
- };
114
- export declare function popRedo(): {
115
- success: true;
116
- } | {
117
- success: false;
118
- reason: string;
119
- };
112
+ export declare function popUndo(): UndoResponse;
113
+ export declare function popRedo(): RedoResponse;
120
114
  export declare function getUndoStack(): readonly UndoEntry[];
121
115
  export declare function getRedoStack(): readonly UndoEntry[];
122
116
  export declare function clearUndoStackForTests(): void;