@remotion/studio-server 4.0.427 → 4.0.429

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 (31) hide show
  1. package/README.md +3 -3
  2. package/dist/codemods/update-sequence-props.d.ts +8 -0
  3. package/dist/codemods/update-sequence-props.js +97 -0
  4. package/dist/helpers/open-in-editor-url-scheme.d.ts +6 -0
  5. package/dist/helpers/open-in-editor-url-scheme.js +50 -0
  6. package/dist/helpers/open-in-editor.js +16 -1
  7. package/dist/index.d.ts +2 -1
  8. package/dist/preview-server/api-routes.js +4 -0
  9. package/dist/preview-server/api-types.d.ts +1 -1
  10. package/dist/preview-server/dev-middleware/middleware.js +1 -1
  11. package/dist/preview-server/get-package-manager.js +1 -1
  12. package/dist/preview-server/hot-middleware/index.d.ts +1 -1
  13. package/dist/preview-server/hot-middleware/index.js +1 -1
  14. package/dist/preview-server/live-events.d.ts +1 -1
  15. package/dist/preview-server/public-folder.js +1 -1
  16. package/dist/preview-server/routes/apply-codemod.js +1 -1
  17. package/dist/preview-server/routes/can-update-sequence-props.d.ts +5 -0
  18. package/dist/preview-server/routes/can-update-sequence-props.js +150 -0
  19. package/dist/preview-server/routes/install-dependency.js +1 -1
  20. package/dist/preview-server/routes/save-sequence-props.d.ts +3 -0
  21. package/dist/preview-server/routes/save-sequence-props.js +37 -0
  22. package/dist/preview-server/serve-static.js +1 -1
  23. package/dist/preview-server/start-server.d.ts +1 -0
  24. package/dist/preview-server/start-server.js +2 -1
  25. package/dist/routes.d.ts +1 -1
  26. package/dist/routes.js +2 -2
  27. package/dist/start-studio.d.ts +2 -1
  28. package/dist/start-studio.js +3 -2
  29. package/package.json +8 -7
  30. package/dist/preview-server/__tests__/multiple-lockfiles.test.d.ts +0 -1
  31. package/dist/preview-server/__tests__/multiple-lockfiles.test.js +0 -37
package/README.md CHANGED
@@ -1,7 +1,7 @@
1
1
  # @remotion/studio-server
2
-
2
+
3
3
  Run a Remotion Studio with a server backend
4
-
4
+
5
5
  ## Usage
6
-
6
+
7
7
  This is an internal package and has no documentation.
@@ -0,0 +1,8 @@
1
+ import { type EnumPath } from '@remotion/studio-shared';
2
+ export declare const updateSequenceProps: ({ input, targetLine, key, value, enumPaths, }: {
3
+ input: string;
4
+ targetLine: number;
5
+ key: string;
6
+ value: unknown;
7
+ enumPaths: EnumPath[];
8
+ }) => Promise<string>;
@@ -0,0 +1,97 @@
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.updateSequenceProps = void 0;
37
+ const studio_shared_1 = require("@remotion/studio-shared");
38
+ const recast = __importStar(require("recast"));
39
+ const parse_ast_1 = require("./parse-ast");
40
+ const updateSequenceProps = async ({ input, targetLine, key, value, enumPaths, }) => {
41
+ const ast = (0, parse_ast_1.parseAst)(input);
42
+ let found = false;
43
+ recast.types.visit(ast, {
44
+ visitJSXOpeningElement(path) {
45
+ var _a;
46
+ const { node } = path;
47
+ if (!node.loc || node.loc.start.line !== targetLine) {
48
+ return this.traverse(path);
49
+ }
50
+ const attr = (_a = node.attributes) === null || _a === void 0 ? void 0 : _a.find((a) => {
51
+ if (a.type === 'JSXSpreadAttribute') {
52
+ return false;
53
+ }
54
+ if (a.name.type === 'JSXNamespacedName') {
55
+ return false;
56
+ }
57
+ return a.name.name === key;
58
+ });
59
+ if (!attr || attr.type === 'JSXSpreadAttribute') {
60
+ throw new Error(`Could not find attribute "${key}" on the JSX element at line ${targetLine}`);
61
+ }
62
+ const parsed = (0, parse_ast_1.parseAst)(`a = ${(0, studio_shared_1.stringifyDefaultProps)({ props: value, enumPaths })}`)
63
+ .program.body[0].expression.right;
64
+ attr.value = recast.types.builders.jsxExpressionContainer(parsed);
65
+ found = true;
66
+ return this.traverse(path);
67
+ },
68
+ });
69
+ if (!found) {
70
+ throw new Error('Could not find a JSX element at the specified line to update');
71
+ }
72
+ let prettier = null;
73
+ try {
74
+ prettier = await Promise.resolve().then(() => __importStar(require('prettier')));
75
+ }
76
+ catch (_a) {
77
+ throw new Error('Prettier cannot be found in the current project.');
78
+ }
79
+ const { format, resolveConfig, resolveConfigFile } = prettier;
80
+ const configFilePath = await resolveConfigFile();
81
+ if (!configFilePath) {
82
+ throw new Error('The Prettier config file was not found');
83
+ }
84
+ const prettierConfig = await resolveConfig(configFilePath);
85
+ if (!prettierConfig) {
86
+ throw new Error('The Prettier config file was not found. For this feature, the "prettier" package must be installed and a .prettierrc file must exist.');
87
+ }
88
+ const finalFile = (0, parse_ast_1.serializeAst)(ast);
89
+ const prettified = await format(finalFile, {
90
+ ...prettierConfig,
91
+ filepath: 'test.tsx',
92
+ plugins: [],
93
+ endOfLine: 'auto',
94
+ });
95
+ return prettified;
96
+ };
97
+ exports.updateSequenceProps = updateSequenceProps;
@@ -0,0 +1,6 @@
1
+ export declare const openInEditorViaUrlScheme: ({ editor, fileName, lineNumber, colNumber, }: {
2
+ editor: string;
3
+ fileName: string;
4
+ lineNumber: number;
5
+ colNumber: number;
6
+ }) => Promise<boolean> | null;
@@ -0,0 +1,50 @@
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.openInEditorViaUrlScheme = void 0;
7
+ const node_child_process_1 = __importDefault(require("node:child_process"));
8
+ const getVsCodeUrlScheme = (editor) => {
9
+ switch (editor) {
10
+ case 'code':
11
+ case 'Code.exe':
12
+ return 'vscode';
13
+ case 'code-insiders':
14
+ case 'Code - Insiders.exe':
15
+ return 'vscode-insiders';
16
+ case 'vscodium':
17
+ case 'VSCodium.exe':
18
+ return 'vscodium';
19
+ case 'cursor':
20
+ case 'Cursor.exe':
21
+ return 'cursor';
22
+ case 'windsurf':
23
+ case 'Windsurf.exe':
24
+ return 'windsurf';
25
+ default:
26
+ return null;
27
+ }
28
+ };
29
+ // On macOS, use URL protocol handler for VS Code derivatives.
30
+ // This is faster than spawning the CLI which boots a Node.js process.
31
+ const openInEditorViaUrlScheme = ({ editor, fileName, lineNumber, colNumber, }) => {
32
+ if (process.platform !== 'darwin') {
33
+ return null;
34
+ }
35
+ const urlScheme = getVsCodeUrlScheme(editor);
36
+ if (!urlScheme) {
37
+ return null;
38
+ }
39
+ const filePath = fileName.startsWith('/') ? fileName.substring(1) : fileName;
40
+ const encodedPath = filePath.split('/').map(encodeURIComponent).join('/');
41
+ const url = `${urlScheme}://file/${encodedPath}:${lineNumber}:${colNumber}`;
42
+ return new Promise((resolve) => {
43
+ const proc = node_child_process_1.default.spawn('open', [url], {
44
+ stdio: 'ignore',
45
+ });
46
+ proc.on('error', () => resolve(false));
47
+ proc.on('close', (code) => resolve(code === 0));
48
+ });
49
+ };
50
+ exports.openInEditorViaUrlScheme = openInEditorViaUrlScheme;
@@ -40,12 +40,13 @@ Object.defineProperty(exports, "__esModule", { value: true });
40
40
  exports.getDisplayNameForEditor = void 0;
41
41
  exports.guessEditor = guessEditor;
42
42
  exports.launchEditor = launchEditor;
43
- const renderer_1 = require("@remotion/renderer");
44
43
  const node_child_process_1 = __importStar(require("node:child_process"));
45
44
  const node_fs_1 = __importDefault(require("node:fs"));
46
45
  const node_os_1 = __importDefault(require("node:os"));
47
46
  const node_path_1 = __importDefault(require("node:path"));
48
47
  const node_util_1 = __importDefault(require("node:util"));
48
+ const renderer_1 = require("@remotion/renderer");
49
+ const open_in_editor_url_scheme_1 = require("./open-in-editor-url-scheme");
49
50
  const { Log } = renderer_1.RenderInternals;
50
51
  const execProm = node_util_1.default.promisify(node_child_process_1.exec);
51
52
  const isVsCodeDerivative = (editor) => {
@@ -483,6 +484,20 @@ async function launchEditor({ colNumber, editor, fileName, lineNumber, vsCodeNew
483
484
  return false;
484
485
  }
485
486
  const shouldOpenVsCodeNewWindow = isVsCodeDerivative(editor.command) && vsCodeNewWindow;
487
+ if (!shouldOpenVsCodeNewWindow) {
488
+ const result = (0, open_in_editor_url_scheme_1.openInEditorViaUrlScheme)({
489
+ editor: editor.command,
490
+ fileName,
491
+ lineNumber,
492
+ colNumber,
493
+ });
494
+ if (result) {
495
+ const opened = await result;
496
+ if (opened) {
497
+ return true;
498
+ }
499
+ }
500
+ }
486
501
  const args = shouldOpenVsCodeNewWindow
487
502
  ? ['--new-window', fileName]
488
503
  : lineNumber
package/dist/index.d.ts CHANGED
@@ -2,7 +2,7 @@ export { ApiRoutes, CopyStillToClipboardRequest, getDefaultOutLocation, OpenInFi
2
2
  export type { AggregateRenderProgress, BundlingState, CopyingState, DownloadProgress, HotMiddlewareOptions, JobProgressCallback, ModuleMap, PackageManager, ProjectInfo, RenderingProgressInput, RenderJob, RenderJobWithCleanup, RequiredChromiumOptions, StitchingProgressInput, UiOpenGlOptions, } from '@remotion/studio-shared';
3
3
  import { AnsiDiff } from './ansi-diff';
4
4
  export declare const StudioServerInternals: {
5
- startStudio: ({ browserArgs, browserFlag, shouldOpenBrowser, fullEntryPath, logLevel, getCurrentInputProps, getEnvVariables, desiredPort, maxTimelineTracks, remotionRoot, keyboardShortcutsEnabled, experimentalClientSideRenderingEnabled, relativePublicDir, webpackOverride, poll, getRenderDefaults, getRenderQueue, numberOfAudioTags, queueMethods, previewEntry, gitSource, bufferStateDelayInMilliseconds, binariesDirectory, forceIPv4, audioLatencyHint, enableCrossSiteIsolation, askAIEnabled, forceNew, rspack, }: {
5
+ startStudio: ({ browserArgs, browserFlag, shouldOpenBrowser, fullEntryPath, logLevel, getCurrentInputProps, getEnvVariables, desiredPort, maxTimelineTracks, remotionRoot, keyboardShortcutsEnabled, experimentalClientSideRenderingEnabled, experimentalVisualModeEnabled, relativePublicDir, webpackOverride, poll, getRenderDefaults, getRenderQueue, numberOfAudioTags, queueMethods, previewEntry, gitSource, bufferStateDelayInMilliseconds, binariesDirectory, forceIPv4, audioLatencyHint, enableCrossSiteIsolation, askAIEnabled, forceNew, rspack, }: {
6
6
  browserArgs: string;
7
7
  browserFlag: string;
8
8
  logLevel: "error" | "info" | "trace" | "verbose" | "warn";
@@ -16,6 +16,7 @@ export declare const StudioServerInternals: {
16
16
  remotionRoot: string;
17
17
  keyboardShortcutsEnabled: boolean;
18
18
  experimentalClientSideRenderingEnabled: boolean;
19
+ experimentalVisualModeEnabled: boolean;
19
20
  relativePublicDir: string | null;
20
21
  webpackOverride: import("@remotion/bundler").WebpackOverrideFn;
21
22
  poll: number | null;
@@ -5,6 +5,7 @@ const add_render_1 = require("./routes/add-render");
5
5
  const apply_codemod_1 = require("./routes/apply-codemod");
6
6
  const apply_visual_control_change_1 = require("./routes/apply-visual-control-change");
7
7
  const can_update_default_props_1 = require("./routes/can-update-default-props");
8
+ const can_update_sequence_props_1 = require("./routes/can-update-sequence-props");
8
9
  const cancel_render_1 = require("./routes/cancel-render");
9
10
  const delete_static_file_1 = require("./routes/delete-static-file");
10
11
  const install_dependency_1 = require("./routes/install-dependency");
@@ -12,6 +13,7 @@ const open_in_file_explorer_1 = require("./routes/open-in-file-explorer");
12
13
  const project_info_1 = require("./routes/project-info");
13
14
  const remove_render_1 = require("./routes/remove-render");
14
15
  const restart_studio_1 = require("./routes/restart-studio");
16
+ const save_sequence_props_1 = require("./routes/save-sequence-props");
15
17
  const subscribe_to_file_existence_1 = require("./routes/subscribe-to-file-existence");
16
18
  const unsubscribe_from_file_existence_1 = require("./routes/unsubscribe-from-file-existence");
17
19
  const update_available_1 = require("./routes/update-available");
@@ -27,6 +29,8 @@ exports.allApiRoutes = {
27
29
  '/api/apply-visual-control-change': apply_visual_control_change_1.applyVisualControlHandler,
28
30
  '/api/apply-codemod': apply_codemod_1.applyCodemodHandler,
29
31
  '/api/can-update-default-props': can_update_default_props_1.canUpdateDefaultPropsHandler,
32
+ '/api/can-update-sequence-props': can_update_sequence_props_1.canUpdateSequencePropsHandler,
33
+ '/api/save-sequence-props': save_sequence_props_1.saveSequencePropsHandler,
30
34
  '/api/update-available': update_available_1.handleUpdate,
31
35
  '/api/project-info': project_info_1.projectInfoHandler,
32
36
  '/api/delete-static-file': delete_static_file_1.deleteStaticFileHandler,
@@ -1,6 +1,6 @@
1
+ import type { IncomingMessage, ServerResponse } from 'node:http';
1
2
  import type { LogLevel } from '@remotion/renderer';
2
3
  import type { RenderJobWithCleanup } from '@remotion/studio-shared';
3
- import type { IncomingMessage, ServerResponse } from 'node:http';
4
4
  export type QueueMethods = {
5
5
  removeJob: (jobId: string) => void;
6
6
  cancelJob: (jobId: string) => void;
@@ -5,10 +5,10 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
5
5
  Object.defineProperty(exports, "__esModule", { value: true });
6
6
  exports.getValueContentRangeHeader = getValueContentRangeHeader;
7
7
  exports.middleware = middleware;
8
- const renderer_1 = require("@remotion/renderer");
9
8
  const node_path_1 = __importDefault(require("node:path"));
10
9
  const node_querystring_1 = __importDefault(require("node:querystring"));
11
10
  const node_url_1 = require("node:url");
11
+ const renderer_1 = require("@remotion/renderer");
12
12
  const compatible_api_1 = require("./compatible-api");
13
13
  const get_paths_1 = require("./get-paths");
14
14
  const range_parser_1 = require("./range-parser");
@@ -4,9 +4,9 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
4
4
  };
5
5
  Object.defineProperty(exports, "__esModule", { value: true });
6
6
  exports.getPackageManager = exports.lockFilePaths = void 0;
7
- const renderer_1 = require("@remotion/renderer");
8
7
  const node_fs_1 = __importDefault(require("node:fs"));
9
8
  const node_path_1 = __importDefault(require("node:path"));
9
+ const renderer_1 = require("@remotion/renderer");
10
10
  exports.lockFilePaths = [
11
11
  {
12
12
  path: 'package-lock.json',
@@ -3,8 +3,8 @@
3
3
  * https://github.com/webpack-contrib/webpack-hot-middleware#readme
4
4
  * and rewritten in TypeScript. This file is MIT licensed
5
5
  */
6
- import type { webpack } from '@remotion/bundler';
7
6
  import type { IncomingMessage, ServerResponse } from 'node:http';
7
+ import type { webpack } from '@remotion/bundler';
8
8
  declare global {
9
9
  const __webpack_hash__: unknown;
10
10
  interface HotNotifierInfo {
@@ -6,9 +6,9 @@
6
6
  */
7
7
  Object.defineProperty(exports, "__esModule", { value: true });
8
8
  exports.webpackHotMiddleware = void 0;
9
+ const node_url_1 = require("node:url");
9
10
  const renderer_1 = require("@remotion/renderer");
10
11
  const studio_shared_1 = require("@remotion/studio-shared");
11
- const node_url_1 = require("node:url");
12
12
  const pathMatch = function (url, path) {
13
13
  try {
14
14
  return (0, node_url_1.parse)(url).pathname === path;
@@ -1,5 +1,5 @@
1
- import type { EventSourceEvent } from '@remotion/studio-shared';
2
1
  import type { IncomingMessage, ServerResponse } from 'node:http';
2
+ import type { EventSourceEvent } from '@remotion/studio-shared';
3
3
  export type LiveEventsServer = {
4
4
  sendEventToClient: (event: EventSourceEvent) => void;
5
5
  router: (request: IncomingMessage, response: ServerResponse) => Promise<void>;
@@ -4,9 +4,9 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
4
4
  };
5
5
  Object.defineProperty(exports, "__esModule", { value: true });
6
6
  exports.getFiles = exports.fetchFolder = exports.initPublicFolderWatch = void 0;
7
- const bundler_1 = require("@remotion/bundler");
8
7
  const node_fs_1 = require("node:fs");
9
8
  const node_path_1 = __importDefault(require("node:path"));
9
+ const bundler_1 = require("@remotion/bundler");
10
10
  const env_supports_fs_recursive_1 = require("./env-supports-fs-recursive");
11
11
  let files = [];
12
12
  const initPublicFolderWatch = ({ publicDir, onUpdate, staticHash, }) => {
@@ -1,8 +1,8 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.applyCodemodHandler = void 0;
4
- const renderer_1 = require("@remotion/renderer");
5
4
  const node_fs_1 = require("node:fs");
5
+ const renderer_1 = require("@remotion/renderer");
6
6
  const duplicate_composition_1 = require("../../codemods/duplicate-composition");
7
7
  const simple_diff_1 = require("../../codemods/simple-diff");
8
8
  const project_info_1 = require("../project-info");
@@ -0,0 +1,5 @@
1
+ import type { Expression } from '@babel/types';
2
+ import type { CanUpdateSequencePropsRequest, CanUpdateSequencePropsResponse } from '@remotion/studio-shared';
3
+ import type { ApiHandler } from '../api-types';
4
+ export declare const isStaticValue: (node: Expression) => boolean;
5
+ export declare const canUpdateSequencePropsHandler: ApiHandler<CanUpdateSequencePropsRequest, CanUpdateSequencePropsResponse>;
@@ -0,0 +1,150 @@
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
+ var __importDefault = (this && this.__importDefault) || function (mod) {
36
+ return (mod && mod.__esModule) ? mod : { "default": mod };
37
+ };
38
+ Object.defineProperty(exports, "__esModule", { value: true });
39
+ exports.canUpdateSequencePropsHandler = exports.isStaticValue = void 0;
40
+ const node_fs_1 = require("node:fs");
41
+ const node_path_1 = __importDefault(require("node:path"));
42
+ const recast = __importStar(require("recast"));
43
+ const parse_ast_1 = require("../../codemods/parse-ast");
44
+ const isStaticValue = (node) => {
45
+ switch (node.type) {
46
+ case 'NumericLiteral':
47
+ case 'StringLiteral':
48
+ case 'BooleanLiteral':
49
+ case 'NullLiteral':
50
+ return true;
51
+ case 'UnaryExpression':
52
+ return ((node.operator === '-' ||
53
+ node.operator === '+') &&
54
+ node.argument.type === 'NumericLiteral');
55
+ case 'ArrayExpression':
56
+ return node.elements.every((el) => el !== null && el.type !== 'SpreadElement' && (0, exports.isStaticValue)(el));
57
+ case 'ObjectExpression':
58
+ return node.properties.every((prop) => prop.type === 'ObjectProperty' &&
59
+ (0, exports.isStaticValue)(prop.value));
60
+ default:
61
+ return false;
62
+ }
63
+ };
64
+ exports.isStaticValue = isStaticValue;
65
+ const getPropsStatus = (jsxElement) => {
66
+ const props = {};
67
+ for (const attr of jsxElement.attributes) {
68
+ if (attr.type === 'JSXSpreadAttribute') {
69
+ continue;
70
+ }
71
+ if (attr.name.type === 'JSXNamespacedName') {
72
+ continue;
73
+ }
74
+ const { name } = attr.name;
75
+ if (typeof name !== 'string') {
76
+ continue;
77
+ }
78
+ const { value } = attr;
79
+ if (!value) {
80
+ props[name] = { canUpdate: true };
81
+ continue;
82
+ }
83
+ if (value.type === 'StringLiteral') {
84
+ props[name] = { canUpdate: true };
85
+ continue;
86
+ }
87
+ if (value.type === 'JSXExpressionContainer') {
88
+ const { expression } = value;
89
+ if (expression.type === 'JSXEmptyExpression' ||
90
+ !(0, exports.isStaticValue)(expression)) {
91
+ props[name] = { canUpdate: false, reason: 'computed' };
92
+ continue;
93
+ }
94
+ props[name] = { canUpdate: true };
95
+ continue;
96
+ }
97
+ props[name] = { canUpdate: false, reason: 'computed' };
98
+ }
99
+ return props;
100
+ };
101
+ const findJsxElementAtLine = (ast, targetLine) => {
102
+ let found = null;
103
+ recast.types.visit(ast, {
104
+ visitJSXOpeningElement(nodePath) {
105
+ const { node } = nodePath;
106
+ if (node.loc && node.loc.start.line === targetLine) {
107
+ found = node;
108
+ return false;
109
+ }
110
+ return this.traverse(nodePath);
111
+ },
112
+ });
113
+ return found;
114
+ };
115
+ const canUpdateSequencePropsHandler = ({ input: { fileName, line, column: _column, keys }, remotionRoot }) => {
116
+ try {
117
+ const absolutePath = node_path_1.default.resolve(remotionRoot, fileName);
118
+ const fileRelativeToRoot = node_path_1.default.relative(remotionRoot, absolutePath);
119
+ if (fileRelativeToRoot.startsWith('..')) {
120
+ throw new Error('Cannot read a file outside the project');
121
+ }
122
+ const fileContents = (0, node_fs_1.readFileSync)(absolutePath, 'utf-8');
123
+ const ast = (0, parse_ast_1.parseAst)(fileContents);
124
+ const jsxElement = findJsxElementAtLine(ast, line);
125
+ if (!jsxElement) {
126
+ throw new Error('Could not find a JSX element at the specified location');
127
+ }
128
+ const allProps = getPropsStatus(jsxElement);
129
+ const filteredProps = {};
130
+ for (const key of keys) {
131
+ if (key in allProps) {
132
+ filteredProps[key] = allProps[key];
133
+ }
134
+ else {
135
+ filteredProps[key] = { canUpdate: false, reason: 'computed' };
136
+ }
137
+ }
138
+ return Promise.resolve({
139
+ canUpdate: true,
140
+ props: filteredProps,
141
+ });
142
+ }
143
+ catch (err) {
144
+ return Promise.resolve({
145
+ canUpdate: false,
146
+ reason: err.message,
147
+ });
148
+ }
149
+ };
150
+ exports.canUpdateSequencePropsHandler = canUpdateSequencePropsHandler;
@@ -1,9 +1,9 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.handleInstallPackage = void 0;
4
+ const node_child_process_1 = require("node:child_process");
4
5
  const renderer_1 = require("@remotion/renderer");
5
6
  const studio_shared_1 = require("@remotion/studio-shared");
6
- const node_child_process_1 = require("node:child_process");
7
7
  const version_1 = require("remotion/version");
8
8
  const install_command_1 = require("../../helpers/install-command");
9
9
  const get_package_manager_1 = require("../get-package-manager");
@@ -0,0 +1,3 @@
1
+ import type { SaveSequencePropsRequest, SaveSequencePropsResponse } from '@remotion/studio-shared';
2
+ import type { ApiHandler } from '../api-types';
3
+ export declare const saveSequencePropsHandler: ApiHandler<SaveSequencePropsRequest, SaveSequencePropsResponse>;
@@ -0,0 +1,37 @@
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.saveSequencePropsHandler = void 0;
7
+ const node_fs_1 = require("node:fs");
8
+ const node_path_1 = __importDefault(require("node:path"));
9
+ const update_sequence_props_1 = require("../../codemods/update-sequence-props");
10
+ const saveSequencePropsHandler = async ({ input: { fileName, line, column: _column, key, value, enumPaths }, remotionRoot, }) => {
11
+ try {
12
+ const absolutePath = node_path_1.default.resolve(remotionRoot, fileName);
13
+ const fileRelativeToRoot = node_path_1.default.relative(remotionRoot, absolutePath);
14
+ if (fileRelativeToRoot.startsWith('..')) {
15
+ throw new Error('Cannot modify a file outside the project');
16
+ }
17
+ const fileContents = (0, node_fs_1.readFileSync)(absolutePath, 'utf-8');
18
+ const updated = await (0, update_sequence_props_1.updateSequenceProps)({
19
+ input: fileContents,
20
+ targetLine: line,
21
+ key,
22
+ value: JSON.parse(value),
23
+ enumPaths,
24
+ });
25
+ (0, node_fs_1.writeFileSync)(absolutePath, updated);
26
+ return {
27
+ success: true,
28
+ };
29
+ }
30
+ catch (err) {
31
+ return {
32
+ success: false,
33
+ reason: err.message,
34
+ };
35
+ }
36
+ };
37
+ exports.saveSequencePropsHandler = saveSequencePropsHandler;
@@ -8,8 +8,8 @@
8
8
  */
9
9
  Object.defineProperty(exports, "__esModule", { value: true });
10
10
  exports.serveStatic = void 0;
11
- const renderer_1 = require("@remotion/renderer");
12
11
  const node_fs_1 = require("node:fs");
12
+ const renderer_1 = require("@remotion/renderer");
13
13
  const middleware_1 = require("./dev-middleware/middleware");
14
14
  const range_parser_1 = require("./dev-middleware/range-parser");
15
15
  const serveStatic = async function ({ root, path, req, res, allowOutsidePublicFolder, }) {
@@ -23,6 +23,7 @@ export declare const startServer: (options: {
23
23
  remotionRoot: string;
24
24
  keyboardShortcutsEnabled: boolean;
25
25
  experimentalClientSideRenderingEnabled: boolean;
26
+ experimentalVisualModeEnabled: boolean;
26
27
  publicDir: string;
27
28
  poll: number | null;
28
29
  staticHash: string;
@@ -4,9 +4,9 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
4
4
  };
5
5
  Object.defineProperty(exports, "__esModule", { value: true });
6
6
  exports.startServer = void 0;
7
+ const node_http_1 = __importDefault(require("node:http"));
7
8
  const bundler_1 = require("@remotion/bundler");
8
9
  const renderer_1 = require("@remotion/renderer");
9
- const node_http_1 = __importDefault(require("node:http"));
10
10
  const detect_remotion_server_1 = require("../detect-remotion-server");
11
11
  const routes_1 = require("../routes");
12
12
  const dev_middleware_1 = require("./dev-middleware");
@@ -36,6 +36,7 @@ const startServer = async (options) => {
36
36
  remotionRoot: options.remotionRoot,
37
37
  keyboardShortcutsEnabled: options.keyboardShortcutsEnabled,
38
38
  experimentalClientSideRenderingEnabled: options.experimentalClientSideRenderingEnabled,
39
+ experimentalVisualModeEnabled: options.experimentalVisualModeEnabled,
39
40
  poll: options.poll,
40
41
  bufferStateDelayInMilliseconds: options.bufferStateDelayInMilliseconds,
41
42
  askAIEnabled: options.askAIEnabled,
package/dist/routes.d.ts CHANGED
@@ -1,5 +1,5 @@
1
- import type { GitSource, RenderDefaults, RenderJob } from '@remotion/studio-shared';
2
1
  import type { IncomingMessage, ServerResponse } from 'node:http';
2
+ import type { GitSource, RenderDefaults, RenderJob } from '@remotion/studio-shared';
3
3
  import type { QueueMethods } from './preview-server/api-types';
4
4
  import type { LiveEventsServer } from './preview-server/live-events';
5
5
  export declare const handleRoutes: ({ staticHash, staticHashPrefix, outputHash, outputHashPrefix, request, response, liveEventsServer, getCurrentInputProps, getEnvVariables, remotionRoot, entryPoint, publicDir, logLevel, getRenderQueue, getRenderDefaults, numberOfAudioTags, queueMethods: methods, gitSource, binariesDirectory, audioLatencyHint, enableCrossSiteIsolation, }: {
package/dist/routes.js CHANGED
@@ -34,12 +34,12 @@ var __importStar = (this && this.__importStar) || (function () {
34
34
  })();
35
35
  Object.defineProperty(exports, "__esModule", { value: true });
36
36
  exports.handleRoutes = void 0;
37
- const bundler_1 = require("@remotion/bundler");
38
- const studio_shared_1 = require("@remotion/studio-shared");
39
37
  const fs_1 = __importStar(require("fs"));
40
38
  const node_fs_1 = require("node:fs");
41
39
  const node_path_1 = __importStar(require("node:path"));
42
40
  const node_url_1 = require("node:url");
41
+ const bundler_1 = require("@remotion/bundler");
42
+ const studio_shared_1 = require("@remotion/studio-shared");
43
43
  const client_render_queue_1 = require("./client-render-queue");
44
44
  const get_file_source_1 = require("./helpers/get-file-source");
45
45
  const get_installed_installable_packages_1 = require("./helpers/get-installed-installable-packages");
@@ -6,7 +6,7 @@ export type StartStudioResult = {
6
6
  } | {
7
7
  type: 'already-running';
8
8
  };
9
- export declare const startStudio: ({ browserArgs, browserFlag, shouldOpenBrowser, fullEntryPath, logLevel, getCurrentInputProps, getEnvVariables, desiredPort, maxTimelineTracks, remotionRoot, keyboardShortcutsEnabled, experimentalClientSideRenderingEnabled, relativePublicDir, webpackOverride, poll, getRenderDefaults, getRenderQueue, numberOfAudioTags, queueMethods, previewEntry, gitSource, bufferStateDelayInMilliseconds, binariesDirectory, forceIPv4, audioLatencyHint, enableCrossSiteIsolation, askAIEnabled, forceNew, rspack, }: {
9
+ export declare const startStudio: ({ browserArgs, browserFlag, shouldOpenBrowser, fullEntryPath, logLevel, getCurrentInputProps, getEnvVariables, desiredPort, maxTimelineTracks, remotionRoot, keyboardShortcutsEnabled, experimentalClientSideRenderingEnabled, experimentalVisualModeEnabled, relativePublicDir, webpackOverride, poll, getRenderDefaults, getRenderQueue, numberOfAudioTags, queueMethods, previewEntry, gitSource, bufferStateDelayInMilliseconds, binariesDirectory, forceIPv4, audioLatencyHint, enableCrossSiteIsolation, askAIEnabled, forceNew, rspack, }: {
10
10
  browserArgs: string;
11
11
  browserFlag: string;
12
12
  logLevel: "error" | "info" | "trace" | "verbose" | "warn";
@@ -20,6 +20,7 @@ export declare const startStudio: ({ browserArgs, browserFlag, shouldOpenBrowser
20
20
  remotionRoot: string;
21
21
  keyboardShortcutsEnabled: boolean;
22
22
  experimentalClientSideRenderingEnabled: boolean;
23
+ experimentalVisualModeEnabled: boolean;
23
24
  relativePublicDir: string | null;
24
25
  webpackOverride: WebpackOverrideFn;
25
26
  poll: number | null;
@@ -4,10 +4,10 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
4
4
  };
5
5
  Object.defineProperty(exports, "__esModule", { value: true });
6
6
  exports.startStudio = void 0;
7
- const renderer_1 = require("@remotion/renderer");
8
7
  const node_crypto_1 = __importDefault(require("node:crypto"));
9
8
  const node_fs_1 = require("node:fs");
10
9
  const node_path_1 = __importDefault(require("node:path"));
10
+ const renderer_1 = require("@remotion/renderer");
11
11
  const get_network_address_1 = require("./get-network-address");
12
12
  const maybe_open_browser_1 = require("./maybe-open-browser");
13
13
  const close_and_restart_1 = require("./preview-server/close-and-restart");
@@ -17,7 +17,7 @@ const public_folder_1 = require("./preview-server/public-folder");
17
17
  const start_server_1 = require("./preview-server/start-server");
18
18
  const server_ready_1 = require("./server-ready");
19
19
  const watch_root_file_1 = require("./watch-root-file");
20
- const startStudio = async ({ browserArgs, browserFlag, shouldOpenBrowser, fullEntryPath, logLevel, getCurrentInputProps, getEnvVariables, desiredPort, maxTimelineTracks, remotionRoot, keyboardShortcutsEnabled, experimentalClientSideRenderingEnabled, relativePublicDir, webpackOverride, poll, getRenderDefaults, getRenderQueue, numberOfAudioTags, queueMethods, previewEntry, gitSource, bufferStateDelayInMilliseconds, binariesDirectory, forceIPv4, audioLatencyHint, enableCrossSiteIsolation, askAIEnabled, forceNew, rspack, }) => {
20
+ const startStudio = async ({ browserArgs, browserFlag, shouldOpenBrowser, fullEntryPath, logLevel, getCurrentInputProps, getEnvVariables, desiredPort, maxTimelineTracks, remotionRoot, keyboardShortcutsEnabled, experimentalClientSideRenderingEnabled, experimentalVisualModeEnabled, relativePublicDir, webpackOverride, poll, getRenderDefaults, getRenderQueue, numberOfAudioTags, queueMethods, previewEntry, gitSource, bufferStateDelayInMilliseconds, binariesDirectory, forceIPv4, audioLatencyHint, enableCrossSiteIsolation, askAIEnabled, forceNew, rspack, }) => {
21
21
  try {
22
22
  if (typeof Bun === 'undefined') {
23
23
  process.title = 'node (npx remotion studio)';
@@ -69,6 +69,7 @@ const startStudio = async ({ browserArgs, browserFlag, shouldOpenBrowser, fullEn
69
69
  remotionRoot,
70
70
  keyboardShortcutsEnabled,
71
71
  experimentalClientSideRenderingEnabled,
72
+ experimentalVisualModeEnabled,
72
73
  publicDir,
73
74
  webpackOverride,
74
75
  poll,
package/package.json CHANGED
@@ -3,14 +3,14 @@
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.427",
6
+ "version": "4.0.429",
7
7
  "description": "Run a Remotion Studio with a server backend",
8
8
  "main": "dist",
9
9
  "sideEffects": false,
10
10
  "scripts": {
11
11
  "lint": "eslint src",
12
12
  "test": "bun test src",
13
- "formatting": "prettier src --check",
13
+ "formatting": "oxfmt src --check",
14
14
  "make": "tsgo -d"
15
15
  },
16
16
  "author": "Jonny Burger <jonny@remotion.dev>",
@@ -25,11 +25,12 @@
25
25
  "dependencies": {
26
26
  "@babel/parser": "7.24.1",
27
27
  "semver": "7.5.3",
28
- "remotion": "4.0.427",
28
+ "prettier": "3.8.1",
29
+ "remotion": "4.0.429",
29
30
  "recast": "0.23.11",
30
- "@remotion/bundler": "4.0.427",
31
- "@remotion/renderer": "4.0.427",
32
- "@remotion/studio-shared": "4.0.427",
31
+ "@remotion/bundler": "4.0.429",
32
+ "@remotion/renderer": "4.0.429",
33
+ "@remotion/studio-shared": "4.0.429",
33
34
  "memfs": "3.4.3",
34
35
  "source-map": "0.7.3",
35
36
  "open": "^8.4.2"
@@ -39,7 +40,7 @@
39
40
  "react": "19.2.3",
40
41
  "@babel/types": "7.24.0",
41
42
  "@types/semver": "^7.3.4",
42
- "@remotion/eslint-config-internal": "4.0.427",
43
+ "@remotion/eslint-config-internal": "4.0.429",
43
44
  "eslint": "9.19.0",
44
45
  "@types/node": "20.12.14",
45
46
  "@typescript/native-preview": "7.0.0-dev.20260217.1"
@@ -1,37 +0,0 @@
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
- const bun_test_1 = require("bun:test");
7
- const node_fs_1 = __importDefault(require("node:fs"));
8
- const node_os_1 = __importDefault(require("node:os"));
9
- const node_path_1 = __importDefault(require("node:path"));
10
- const get_package_manager_1 = require("../get-package-manager");
11
- (0, bun_test_1.describe)('getPackageManager multiple lockfiles', () => {
12
- let tempDir;
13
- (0, bun_test_1.beforeEach)(() => {
14
- tempDir = node_fs_1.default.mkdtempSync(node_path_1.default.join(node_os_1.default.tmpdir(), 'remotion-test-'));
15
- });
16
- (0, bun_test_1.afterEach)(() => {
17
- node_fs_1.default.rmSync(tempDir, { recursive: true, force: true });
18
- });
19
- (0, bun_test_1.test)('should not throw error when multiple lockfiles are detected', () => {
20
- node_fs_1.default.writeFileSync(node_path_1.default.join(tempDir, 'package-lock.json'), '{}');
21
- node_fs_1.default.writeFileSync(node_path_1.default.join(tempDir, 'bun.lock'), '');
22
- // Should not throw
23
- const manager = (0, get_package_manager_1.getPackageManager)(tempDir, undefined, 0);
24
- // Should return one of them (usually the first one in the list, which is npm)
25
- (0, bun_test_1.expect)(manager).not.toBe('unknown');
26
- if (typeof manager !== 'string') {
27
- (0, bun_test_1.expect)(['npm', 'bun']).toContain(manager.manager);
28
- }
29
- });
30
- (0, bun_test_1.test)('should return npm if only package-lock.json exists', () => {
31
- node_fs_1.default.writeFileSync(node_path_1.default.join(tempDir, 'package-lock.json'), '{}');
32
- const manager = (0, get_package_manager_1.getPackageManager)(tempDir, undefined, 0);
33
- if (typeof manager !== 'string') {
34
- (0, bun_test_1.expect)(manager.manager).toBe('npm');
35
- }
36
- });
37
- });