@remotion/studio-server 4.0.499 → 4.0.500

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.
@@ -19,6 +19,7 @@ const delete_static_file_1 = require("./routes/delete-static-file");
19
19
  const download_remote_asset_1 = require("./routes/download-remote-asset");
20
20
  const duplicate_effect_1 = require("./routes/duplicate-effect");
21
21
  const duplicate_jsx_node_1 = require("./routes/duplicate-jsx-node");
22
+ const find_in_file_1 = require("./routes/find-in-file");
22
23
  const insert_element_1 = require("./routes/insert-element");
23
24
  const insert_jsx_element_1 = require("./routes/insert-jsx-element");
24
25
  const install_dependency_1 = require("./routes/install-dependency");
@@ -36,6 +37,7 @@ const reorder_effect_1 = require("./routes/reorder-effect");
36
37
  const reorder_sequence_1 = require("./routes/reorder-sequence");
37
38
  const restart_studio_1 = require("./routes/restart-studio");
38
39
  const save_effect_props_1 = require("./routes/save-effect-props");
40
+ const save_multiple_effect_props_1 = require("./routes/save-multiple-effect-props");
39
41
  const save_sequence_props_1 = require("./routes/save-sequence-props");
40
42
  const split_jsx_sequence_1 = require("./routes/split-jsx-sequence");
41
43
  const subscribe_to_default_props_1 = require("./routes/subscribe-to-default-props");
@@ -61,6 +63,7 @@ exports.allApiRoutes = {
61
63
  '/api/subscribe-to-file-existence': subscribe_to_file_existence_1.subscribeToFileExistence,
62
64
  '/api/remove-render': remove_render_1.handleRemoveRender,
63
65
  '/api/open-in-editor': open_in_editor_1.openInEditorHandler,
66
+ '/api/find-in-file': find_in_file_1.findInFileHandler,
64
67
  '/api/open-in-file-explorer': open_in_file_explorer_1.handleOpenInFileExplorer,
65
68
  '/api/register-client-render': register_client_render_1.registerClientRenderHandler,
66
69
  '/api/unregister-client-render': unregister_client_render_1.unregisterClientRenderHandler,
@@ -73,6 +76,7 @@ exports.allApiRoutes = {
73
76
  '/api/unsubscribe-from-sequence-props': unsubscribe_from_sequence_props_1.unsubscribeFromSequenceProps,
74
77
  '/api/save-sequence-props': save_sequence_props_1.saveSequencePropsHandler,
75
78
  '/api/save-effect-props': save_effect_props_1.saveEffectPropsHandler,
79
+ '/api/save-multiple-effect-props': save_multiple_effect_props_1.saveMultipleEffectPropsHandler,
76
80
  '/api/add-effect': add_effect_1.addEffectHandler,
77
81
  '/api/reorder-effect': reorder_effect_1.reorderEffectHandler,
78
82
  '/api/duplicate-effect': duplicate_effect_1.duplicateEffectHandler,
@@ -0,0 +1,12 @@
1
+ import type { FindInFileRequest, FindInFileResponse } from '@remotion/studio-shared';
2
+ import type { ApiHandler } from '../api-types';
3
+ export declare const findSearchPosition: ({ contents, lineNumber, columnNumber, search, }: {
4
+ contents: string;
5
+ lineNumber: number;
6
+ columnNumber: number;
7
+ search: string;
8
+ }) => {
9
+ lineNumber: number;
10
+ columnNumber: number;
11
+ };
12
+ export declare const findInFileHandler: ApiHandler<FindInFileRequest, FindInFileResponse>;
@@ -0,0 +1,35 @@
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.findInFileHandler = exports.findSearchPosition = void 0;
7
+ const node_fs_1 = __importDefault(require("node:fs"));
8
+ const node_path_1 = __importDefault(require("node:path"));
9
+ const findSearchPosition = ({ contents, lineNumber, columnNumber, search, }) => {
10
+ const lines = contents.split(/\r?\n/);
11
+ const startLineIndex = Math.max(0, lineNumber - 1);
12
+ for (let lineIndex = startLineIndex; lineIndex < lines.length; lineIndex++) {
13
+ const startColumnIndex = lineIndex === startLineIndex ? Math.max(0, columnNumber - 1) : 0;
14
+ const foundColumnIndex = lines[lineIndex].indexOf(search, startColumnIndex);
15
+ if (foundColumnIndex !== -1) {
16
+ return {
17
+ lineNumber: lineIndex + 1,
18
+ columnNumber: foundColumnIndex + 1,
19
+ };
20
+ }
21
+ }
22
+ return { lineNumber, columnNumber };
23
+ };
24
+ exports.findSearchPosition = findSearchPosition;
25
+ const findInFileHandler = async ({ input, remotionRoot }) => {
26
+ const { fileName, lineNumber, columnNumber, search } = input;
27
+ const contents = await node_fs_1.default.promises.readFile(node_path_1.default.resolve(remotionRoot, fileName), 'utf-8');
28
+ return (0, exports.findSearchPosition)({
29
+ contents,
30
+ lineNumber,
31
+ columnNumber,
32
+ search,
33
+ });
34
+ };
35
+ exports.findInFileHandler = findInFileHandler;
@@ -0,0 +1,3 @@
1
+ import type { SaveMultipleEffectPropsRequest, SaveMultipleEffectPropsResponse } from '@remotion/studio-shared';
2
+ import type { ApiHandler } from '../api-types';
3
+ export declare const saveMultipleEffectPropsHandler: ApiHandler<SaveMultipleEffectPropsRequest, SaveMultipleEffectPropsResponse>;
@@ -0,0 +1,171 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.saveMultipleEffectPropsHandler = void 0;
4
+ const node_fs_1 = require("node:fs");
5
+ const renderer_1 = require("@remotion/renderer");
6
+ const studio_shared_1 = require("@remotion/studio-shared");
7
+ const parse_ast_1 = require("../../codemods/parse-ast");
8
+ const update_effect_props_1 = require("../../codemods/update-effect-props/update-effect-props");
9
+ const file_watcher_1 = require("../../file-watcher");
10
+ const resolve_file_inside_project_1 = require("../../helpers/resolve-file-inside-project");
11
+ const video_config_values_1 = require("../../helpers/video-config-values");
12
+ const undo_stack_1 = require("../undo-stack");
13
+ const watch_ignore_next_change_1 = require("../watch-ignore-next-change");
14
+ const can_update_effect_props_1 = require("./can-update-effect-props");
15
+ const can_update_sequence_props_1 = require("./can-update-sequence-props");
16
+ const log_effect_update_1 = require("./log-updates/log-effect-update");
17
+ const source_file_write_queue_1 = require("./source-file-write-queue");
18
+ const resolveEdit = ({ edit, index, }) => {
19
+ const defaultValue = edit.defaultValue === null ? null : JSON.parse(edit.defaultValue);
20
+ const update = edit.type === 'value'
21
+ ? {
22
+ key: edit.key,
23
+ value: JSON.parse(edit.value),
24
+ defaultValue,
25
+ }
26
+ : {
27
+ key: edit.key,
28
+ effectParam: edit.effectParam,
29
+ defaultValue,
30
+ };
31
+ return {
32
+ index,
33
+ edit,
34
+ update,
35
+ defaultValueString: defaultValue === null ? null : JSON.stringify(defaultValue),
36
+ };
37
+ };
38
+ const saveMultipleEffectPropsHandler = ({ input: { edits, clientId, undoLabel, redoLabel }, remotionRoot, logLevel, }) => (0, source_file_write_queue_1.withSourceFileWriteQueue)(async () => {
39
+ var _a;
40
+ if (edits.length === 0) {
41
+ throw new Error('No effect prop edits to save');
42
+ }
43
+ renderer_1.RenderInternals.Log.trace({ indent: false, logLevel }, `[save-multiple-effect-props] Received request with ${edits.length} edit(s)`);
44
+ const editGroups = new Map();
45
+ for (const [index, edit] of edits.entries()) {
46
+ const { absolutePath, fileRelativeToRoot } = (0, resolve_file_inside_project_1.resolveFileInsideProject)({
47
+ remotionRoot,
48
+ fileName: edit.fileName,
49
+ action: 'modify',
50
+ });
51
+ const group = (_a = editGroups.get(absolutePath)) !== null && _a !== void 0 ? _a : {
52
+ fileRelativeToRoot,
53
+ edits: [],
54
+ };
55
+ group.edits.push(resolveEdit({ edit, index }));
56
+ editGroups.set(absolutePath, group);
57
+ }
58
+ const snapshots = [];
59
+ const outputByPath = new Map();
60
+ const resultByIndex = new Map();
61
+ for (const [absolutePath, group] of editGroups) {
62
+ const fileContents = (0, node_fs_1.readFileSync)(absolutePath, 'utf-8');
63
+ let output = fileContents;
64
+ let firstLogLine = Number.POSITIVE_INFINITY;
65
+ for (const edit of group.edits) {
66
+ const result = await (0, update_effect_props_1.updateEffectProps)({
67
+ input: output,
68
+ sequenceNodePath: edit.edit.sequenceNodePath.nodePath,
69
+ effectIndex: edit.edit.effectIndex,
70
+ update: edit.update,
71
+ schema: edit.edit.schema,
72
+ });
73
+ output = result.output;
74
+ firstLogLine = Math.min(firstLogLine, result.logLine);
75
+ resultByIndex.set(edit.index, {
76
+ ...result,
77
+ edit,
78
+ fileRelativeToRoot: group.fileRelativeToRoot,
79
+ });
80
+ }
81
+ outputByPath.set(absolutePath, output);
82
+ snapshots.push({
83
+ filePath: absolutePath,
84
+ oldContents: fileContents,
85
+ newContents: output,
86
+ logLine: Number.isFinite(firstLogLine) ? firstLogLine : 1,
87
+ });
88
+ }
89
+ (0, undo_stack_1.pushTransactionToUndoStack)({
90
+ snapshots,
91
+ logLevel,
92
+ remotionRoot,
93
+ description: {
94
+ undoMessage: `↩️ ${undoLabel}`,
95
+ redoMessage: `↪️ ${redoLabel}`,
96
+ },
97
+ entryType: 'effect-props',
98
+ suppressHmrOnFileRestore: true,
99
+ });
100
+ for (const [absolutePath, output] of outputByPath) {
101
+ (0, undo_stack_1.suppressUndoStackInvalidation)(absolutePath);
102
+ (0, watch_ignore_next_change_1.suppressBundlerUpdateForFile)(absolutePath);
103
+ (0, file_watcher_1.writeFileAndNotifyFileWatchers)(absolutePath, output, clientId);
104
+ }
105
+ for (const index of edits.keys()) {
106
+ const result = resultByIndex.get(index);
107
+ if (!result) {
108
+ throw new Error('Could not compute effect prop edit result');
109
+ }
110
+ (0, log_effect_update_1.logEffectUpdate)({
111
+ fileRelativeToRoot: result.fileRelativeToRoot,
112
+ line: result.logLine,
113
+ effectName: result.effectCallee,
114
+ propKey: result.edit.edit.key,
115
+ oldValueString: result.oldValueString,
116
+ newValueString: result.newValueString,
117
+ defaultValueString: result.edit.defaultValueString,
118
+ formatted: result.formatted,
119
+ logLevel,
120
+ removedProps: result.removedProps,
121
+ addedProps: [],
122
+ });
123
+ }
124
+ (0, undo_stack_1.printUndoHint)(logLevel);
125
+ const statusTargets = [
126
+ ...new Map(edits.map((edit) => [
127
+ JSON.stringify([
128
+ edit.fileName,
129
+ edit.sequenceNodePath.nodePath,
130
+ edit.effectIndex,
131
+ ]),
132
+ edit,
133
+ ])).values(),
134
+ ];
135
+ const results = statusTargets.map((edit) => {
136
+ const { absolutePath } = (0, resolve_file_inside_project_1.resolveFileInsideProject)({
137
+ remotionRoot,
138
+ fileName: edit.fileName,
139
+ action: 'modify',
140
+ });
141
+ const output = outputByPath.get(absolutePath);
142
+ if (!output) {
143
+ throw new Error('Could not compute effect prop edit status');
144
+ }
145
+ const ast = (0, parse_ast_1.parseAst)(output);
146
+ const jsx = (0, can_update_sequence_props_1.findJsxElementAtNodePath)(ast, edit.sequenceNodePath.nodePath);
147
+ const status = jsx
148
+ ? (0, can_update_effect_props_1.computeEffectPropStatus)({
149
+ ast,
150
+ jsx,
151
+ effectIndex: edit.effectIndex,
152
+ keys: (0, studio_shared_1.getAllSchemaKeys)(edit.schema),
153
+ videoConfigValues: (0, video_config_values_1.getVideoConfigIdentifierValues)({
154
+ ast,
155
+ videoConfigValues: edit.sequenceNodePath.videoConfigValues,
156
+ }),
157
+ })
158
+ : {
159
+ canUpdate: false,
160
+ effectIndex: edit.effectIndex,
161
+ reason: 'not-found',
162
+ };
163
+ return {
164
+ fileName: edit.fileName,
165
+ sequenceNodePath: edit.sequenceNodePath,
166
+ status,
167
+ };
168
+ });
169
+ return { results };
170
+ });
171
+ exports.saveMultipleEffectPropsHandler = saveMultipleEffectPropsHandler;
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.499",
6
+ "version": "4.0.500",
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/drag-and-drop": "4.0.499",
26
+ "@remotion/drag-and-drop": "4.0.500",
27
27
  "@babel/types": "7.24.0",
28
28
  "@babel/parser": "7.24.1",
29
29
  "@svgr/core": "8.1.0",
@@ -31,11 +31,11 @@
31
31
  "kiwi-schema": "0.5.0",
32
32
  "semver": "7.5.3",
33
33
  "prettier": "3.8.1",
34
- "remotion": "4.0.499",
34
+ "remotion": "4.0.500",
35
35
  "recast": "0.23.11",
36
- "@remotion/bundler": "4.0.499",
37
- "@remotion/renderer": "4.0.499",
38
- "@remotion/studio-shared": "4.0.499",
36
+ "@remotion/bundler": "4.0.500",
37
+ "@remotion/renderer": "4.0.500",
38
+ "@remotion/studio-shared": "4.0.500",
39
39
  "memfs": "3.4.3",
40
40
  "open": "8.4.2"
41
41
  },
@@ -43,7 +43,7 @@
43
43
  "ast-types": "0.16.1",
44
44
  "react": "19.2.3",
45
45
  "@types/semver": "7.5.3",
46
- "@remotion/eslint-config-internal": "4.0.499",
46
+ "@remotion/eslint-config-internal": "4.0.500",
47
47
  "eslint": "9.19.0",
48
48
  "@types/node": "20.12.14",
49
49
  "@typescript/native-preview": "7.0.0-dev.20260217.1"