@remotion/studio-server 4.0.519 → 4.0.521

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 (26) hide show
  1. package/dist/codemods/split-jsx-sequence.d.ts +0 -1
  2. package/dist/codemods/split-jsx-sequence.js +0 -5
  3. package/dist/helpers/install-command.js +1 -0
  4. package/dist/helpers/resolve-composition-component.d.ts +0 -1
  5. package/dist/helpers/resolve-composition-component.js +0 -2
  6. package/dist/preview-server/api-routes.js +4 -0
  7. package/dist/preview-server/close-and-restart.d.ts +4 -1
  8. package/dist/preview-server/close-and-restart.js +6 -5
  9. package/dist/preview-server/get-package-manager.js +6 -0
  10. package/dist/preview-server/routes/apply-codemod.js +16 -0
  11. package/dist/preview-server/routes/element-install-plan.d.ts +1 -9
  12. package/dist/preview-server/routes/insert-element.js +5 -8
  13. package/dist/preview-server/routes/insert-jsx-element.js +2 -6
  14. package/dist/preview-server/routes/restart-studio.js +2 -2
  15. package/dist/preview-server/routes/shutdown-studio.d.ts +2 -0
  16. package/dist/preview-server/routes/shutdown-studio.js +10 -0
  17. package/dist/preview-server/routes/split-jsx-sequence.js +2 -6
  18. package/dist/preview-server/routes/upgrade-remotion.d.ts +3 -0
  19. package/dist/preview-server/routes/upgrade-remotion.js +54 -0
  20. package/dist/preview-server/studio-protocol/handle-element-library.js +6 -14
  21. package/dist/preview-server/studio-protocol/handle-install.js +16 -25
  22. package/dist/preview-server/studio-protocol/handle-license-key.js +5 -13
  23. package/dist/preview-server/undo-stack.d.ts +1 -1
  24. package/dist/start-studio.d.ts +2 -0
  25. package/dist/start-studio.js +8 -2
  26. package/package.json +9 -9
@@ -7,7 +7,6 @@ export declare const splitJsxSequence: ({ input, nodePath, sequenceKeys, splitFr
7
7
  prettierConfigOverride?: Record<string, unknown> | null | undefined;
8
8
  }) => Promise<{
9
9
  output: string;
10
- formatted: boolean;
11
10
  nodeLabel: string;
12
11
  logLine: number;
13
12
  nodePathRemappings: import("@remotion/studio-shared").SequenceNodePathRemapping[];
@@ -2,16 +2,11 @@
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.splitJsxSequence = void 0;
4
4
  const studio_codemods_1 = require("@remotion/studio-codemods");
5
- const format_file_content_1 = require("./format-file-content");
6
5
  const splitJsxSequence = ({ input, nodePath, sequenceKeys, splitFrame, prettierConfigOverride, }) => (0, studio_codemods_1.splitJsxSequence)({
7
6
  input,
8
7
  nodePath,
9
8
  sequenceKeys,
10
9
  splitFrame,
11
- formatFile: ({ contents, prettierConfigOverride: override }) => (0, format_file_content_1.formatFileContent)({
12
- input: contents,
13
- prettierConfigOverride: override,
14
- }),
15
10
  prettierConfigOverride,
16
11
  });
17
12
  exports.splitJsxSequence = splitJsxSequence;
@@ -15,6 +15,7 @@ const getInstallCommand = ({ manager, packages, version, additionalArgs, }) => {
15
15
  pnpm: ['i', ...additionalArgs, ...pkgList],
16
16
  yarn: ['add', '--exact', ...additionalArgs, ...pkgList],
17
17
  bun: ['i', ...additionalArgs, ...pkgList],
18
+ nub: ['add', ...additionalArgs, ...pkgList],
18
19
  };
19
20
  return commands[manager];
20
21
  };
@@ -34,7 +34,6 @@ export declare const insertJsxElementIntoComposition: ({ remotionRoot, compositi
34
34
  source: string;
35
35
  oldContents: string;
36
36
  output: string;
37
- formatted: boolean;
38
37
  logLine: number;
39
38
  nodePathRemappings: SequenceNodePathRemapping[];
40
39
  insertedNodePath: SequenceNodePath | null;
@@ -7,13 +7,11 @@ exports.insertJsxElementIntoComposition = exports.resolveCompositionComponent =
7
7
  const node_fs_1 = __importDefault(require("node:fs"));
8
8
  const node_path_1 = __importDefault(require("node:path"));
9
9
  const studio_codemods_1 = require("@remotion/studio-codemods");
10
- const format_file_content_1 = require("../codemods/format-file-content");
11
10
  const svg_to_jsx_1 = require("./svg-to-jsx");
12
11
  const makeCodemodEnvironment = (remotionRoot) => ({
13
12
  dirname: node_path_1.default.dirname,
14
13
  extname: node_path_1.default.extname,
15
14
  fileExists: (fileName) => node_fs_1.default.existsSync(fileName) && node_fs_1.default.statSync(fileName).isFile(),
16
- formatFile: ({ contents, prettierConfigOverride }) => (0, format_file_content_1.formatFileContent)({ input: contents, prettierConfigOverride }),
17
15
  isAbsolute: node_path_1.default.isAbsolute,
18
16
  join: node_path_1.default.join,
19
17
  pathSeparator: node_path_1.default.sep,
@@ -47,6 +47,7 @@ const restart_studio_1 = require("./routes/restart-studio");
47
47
  const save_effect_props_1 = require("./routes/save-effect-props");
48
48
  const save_multiple_effect_props_1 = require("./routes/save-multiple-effect-props");
49
49
  const save_sequence_props_1 = require("./routes/save-sequence-props");
50
+ const shutdown_studio_1 = require("./routes/shutdown-studio");
50
51
  const split_jsx_sequence_1 = require("./routes/split-jsx-sequence");
51
52
  const split_video_from_audio_1 = require("./routes/split-video-from-audio");
52
53
  const subscribe_to_default_props_1 = require("./routes/subscribe-to-default-props");
@@ -62,6 +63,7 @@ const update_default_props_1 = require("./routes/update-default-props");
62
63
  const update_effect_keyframe_settings_1 = require("./routes/update-effect-keyframe-settings");
63
64
  const update_element_install_target_1 = require("./routes/update-element-install-target");
64
65
  const update_sequence_keyframe_settings_1 = require("./routes/update-sequence-keyframe-settings");
66
+ const upgrade_remotion_1 = require("./routes/upgrade-remotion");
65
67
  exports.allApiRoutes = {
66
68
  '/api/composition-component-info': composition_component_info_1.compositionComponentInfoHandler,
67
69
  '/api/copy-render-output-to-asset': copy_render_output_to_asset_1.copyRenderOutputToAssetHandler,
@@ -113,6 +115,8 @@ exports.allApiRoutes = {
113
115
  '/api/project-info': project_info_1.projectInfoHandler,
114
116
  '/api/delete-static-file': delete_static_file_1.deleteStaticFileHandler,
115
117
  '/api/rename-static-file': rename_static_file_1.renameStaticFileHandler,
118
+ '/api/upgrade-remotion': upgrade_remotion_1.handleUpgradeRemotion,
119
+ '/api/shutdown-studio': shutdown_studio_1.handleShutdownStudio,
116
120
  '/api/restart-studio': restart_studio_1.handleRestartStudio,
117
121
  '/api/default-coding-agent-info': default_coding_agent_1.getDefaultCodingAgentInfoHandler,
118
122
  '/api/default-editor-info': default_editor_1.getDefaultEditorInfoHandler,
@@ -1,2 +1,5 @@
1
- export declare const noOpUntilRestart: () => Promise<void>;
1
+ type StudioAction = 'restart' | 'shutdown';
2
+ export declare const noOpUntilRestart: () => Promise<StudioAction>;
2
3
  export declare const signalRestart: () => void;
4
+ export declare const signalShutdown: () => void;
5
+ export {};
@@ -1,6 +1,6 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.signalRestart = exports.noOpUntilRestart = void 0;
3
+ exports.signalShutdown = exports.signalRestart = exports.noOpUntilRestart = void 0;
4
4
  const resolveFunctions = [];
5
5
  const noOpUntilRestart = () => {
6
6
  return new Promise((resolve) => {
@@ -9,9 +9,10 @@ const noOpUntilRestart = () => {
9
9
  };
10
10
  exports.noOpUntilRestart = noOpUntilRestart;
11
11
  const signalRestart = () => {
12
- resolveFunctions.forEach((f) => {
13
- f();
14
- });
15
- resolveFunctions.length = 0;
12
+ resolveFunctions.splice(0).forEach((resolve) => resolve('restart'));
16
13
  };
17
14
  exports.signalRestart = signalRestart;
15
+ const signalShutdown = () => {
16
+ resolveFunctions.splice(0).forEach((resolve) => resolve('shutdown'));
17
+ };
18
+ exports.signalShutdown = signalShutdown;
@@ -26,6 +26,12 @@ exports.lockFilePaths = [
26
26
  installCommand: 'pnpm i',
27
27
  startCommand: 'pnpm exec remotion studio',
28
28
  },
29
+ {
30
+ path: 'nub.lock',
31
+ manager: 'nub',
32
+ installCommand: 'nub add',
33
+ startCommand: 'nubx remotion studio',
34
+ },
29
35
  {
30
36
  path: 'bun.lock',
31
37
  manager: 'bun',
@@ -68,6 +68,12 @@ const getCodemodLogMessage = (codemod) => {
68
68
  : 'to root';
69
69
  return `Moved composition "${codemod.idToMove}" ${destination}`;
70
70
  }
71
+ if (codemod.type === 'move-composition-or-folder') {
72
+ const source = codemod.source.type === 'composition'
73
+ ? `composition "${codemod.source.compositionId}"`
74
+ : `folder "${getFolderPath(codemod.source.parentName, codemod.source.folderName)}"`;
75
+ return `Moved ${source}`;
76
+ }
71
77
  if (codemod.type === 'rename-folder') {
72
78
  const oldName = getFolderPath(codemod.parentName, codemod.folderName);
73
79
  const newName = getFolderPath(codemod.parentName, codemod.newName);
@@ -130,6 +136,16 @@ const getCodemodUndoDescription = (codemod) => {
130
136
  entryType: codemod.type,
131
137
  };
132
138
  }
139
+ if (codemod.type === 'move-composition-or-folder') {
140
+ const label = codemod.source.type === 'composition'
141
+ ? `composition "${codemod.source.compositionId}"`
142
+ : `folder "${getFolderPath(codemod.source.parentName, codemod.source.folderName)}"`;
143
+ return {
144
+ undoMessage: `↩️ Move of ${label}`,
145
+ redoMessage: `↪️ Move of ${label}`,
146
+ entryType: codemod.type,
147
+ };
148
+ }
133
149
  if (codemod.type === 'new-composition') {
134
150
  return {
135
151
  undoMessage: `↩️ Creation of composition "${codemod.newId}"`,
@@ -2,15 +2,7 @@ import type { ElementInstallExpectedFileState, PrepareElementInstallRequest } fr
2
2
  export declare const normalizeElementSourceForComparison: (source: string) => string;
3
3
  export declare const getElementSourceHash: (source: string) => string;
4
4
  export declare const validateElementInstallPosition: (position: import("@remotion/studio-shared").InsertableCompositionElementPosition | null) => void;
5
- export declare const validateElementForInstallation: (element: {
6
- dependencies: import("@remotion/studio-protocol").ElementDependency[];
7
- durationInFrames?: number | undefined;
8
- installationMode?: import("@remotion/studio-protocol").ElementInstallationMode | undefined;
9
- slug: string;
10
- displayName: string;
11
- sourceCode: string;
12
- dimensions: import("@remotion/studio-protocol").ComponentDimensions | null;
13
- }) => void;
5
+ export declare const validateElementForInstallation: (element: import("@remotion/studio-shared").InstallableElement) => void;
14
6
  export declare const makeRelativeElementImportPath: ({ fromFile, toFile, }: {
15
7
  fromFile: string;
16
8
  toFile: string;
@@ -8,7 +8,6 @@ const format_log_file_location_1 = require("../format-log-file-location");
8
8
  const sequence_node_path_mutation_1 = require("../sequence-node-path-mutation");
9
9
  const undo_stack_1 = require("../undo-stack");
10
10
  const element_install_plan_1 = require("./element-install-plan");
11
- const log_update_1 = require("./log-updates/log-update");
12
11
  const source_file_write_queue_1 = require("./source-file-write-queue");
13
12
  const hasExpectedFileState = ({ expected, actual, }) => {
14
13
  if (expected.exists !== actual.exists) {
@@ -23,14 +22,15 @@ const hasExpectedFileState = ({ expected, actual, }) => {
23
22
  return actual.sourceHash === expected.sourceHash;
24
23
  };
25
24
  const insertElementHandler = ({ input: { compositionFile, compositionId, element, expectedFileState, from, position, overwriteExisting, }, entryPoint, remotionRoot, logLevel, }) => (0, source_file_write_queue_1.withSourceFileWriteQueue)(async () => {
26
- var _a, _b;
27
25
  try {
28
26
  (0, element_install_plan_1.validateElementInstallPosition)(position);
29
27
  if (from !== null &&
30
28
  (!Number.isInteger(from) || !Number.isFinite(from) || from < 0)) {
31
29
  throw new Error('from must be a non-negative integer');
32
30
  }
33
- const installationMode = (_a = element.installationMode) !== null && _a !== void 0 ? _a : 'wrapped';
31
+ const installationMode = element.installationMode === null
32
+ ? 'wrapped'
33
+ : element.installationMode;
34
34
  const componentOwnsSequence = installationMode === 'component-owned-sequence';
35
35
  renderer_1.RenderInternals.Log.trace({ indent: false, logLevel }, `[insert-element] Received request for compositionFile="${compositionFile}" compositionId="${compositionId}" element="${element.slug}"`);
36
36
  const plan = await (0, element_install_plan_1.getElementInstallPlan)({
@@ -90,7 +90,7 @@ const insertElementHandler = ({ input: { compositionFile, compositionId, element
90
90
  importPath: plan.importPath,
91
91
  props: componentOwnsSequence
92
92
  ? [
93
- ...(element.durationInFrames === undefined
93
+ ...(element.durationInFrames === null
94
94
  ? []
95
95
  : [
96
96
  {
@@ -109,7 +109,7 @@ const insertElementHandler = ({ input: { compositionFile, compositionId, element
109
109
  ? null
110
110
  : {
111
111
  dimensions: element.dimensions,
112
- durationInFrames: (_b = element.durationInFrames) !== null && _b !== void 0 ? _b : null,
112
+ durationInFrames: element.durationInFrames,
113
113
  from,
114
114
  name: element.displayName,
115
115
  position,
@@ -206,9 +206,6 @@ const insertElementHandler = ({ input: { compositionFile, compositionId, element
206
206
  : 'Created Element source';
207
207
  renderer_1.RenderInternals.Log.info({ indent: false, logLevel }, `${(0, source_file_write_queue_1.getCodemodTimingPrefix)(logLevel)}${renderer_1.RenderInternals.chalk.blueBright(elementLocationLabel)} ${elementFileAction}`);
208
208
  renderer_1.RenderInternals.Log.info({ indent: false, logLevel }, `${(0, source_file_write_queue_1.getCodemodTimingPrefix)(logLevel)}${renderer_1.RenderInternals.chalk.blueBright(compositionLocationLabel)} Added <${plan.componentName}>`);
209
- if (!inserted.formatted) {
210
- (0, log_update_1.warnAboutPrettierOnce)(logLevel);
211
- }
212
209
  (0, undo_stack_1.printUndoHint)(logLevel);
213
210
  return { success: true, nodePathMutation };
214
211
  }
@@ -13,7 +13,6 @@ const resolve_composition_component_1 = require("../../helpers/resolve-compositi
13
13
  const format_log_file_location_1 = require("../format-log-file-location");
14
14
  const sequence_node_path_mutation_1 = require("../sequence-node-path-mutation");
15
15
  const undo_stack_1 = require("../undo-stack");
16
- const log_update_1 = require("./log-updates/log-update");
17
16
  const source_file_write_queue_1 = require("./source-file-write-queue");
18
17
  const validateDimension = (name, value) => {
19
18
  if (!Number.isFinite(value) || value < 1) {
@@ -159,7 +158,7 @@ const insertJsxElementHandler = ({ input: { compositionFile, compositionId, elem
159
158
  }
160
159
  const elementLabel = getElementLabel(element);
161
160
  renderer_1.RenderInternals.Log.trace({ indent: false, logLevel }, `[insert-jsx-element] Received request for compositionFile="${compositionFile}" compositionId="${compositionId}" element="${element.type}"`);
162
- const { fileName, source, oldContents, output, formatted, insertedNodePath, logLine, nodePathRemappings, } = await (0, resolve_composition_component_1.insertJsxElementIntoComposition)({
161
+ const { fileName, source, oldContents, output, insertedNodePath, logLine, nodePathRemappings, } = await (0, resolve_composition_component_1.insertJsxElementIntoComposition)({
163
162
  remotionRoot,
164
163
  compositionFile,
165
164
  compositionId,
@@ -204,10 +203,7 @@ const insertJsxElementHandler = ({ input: { compositionFile, compositionId, elem
204
203
  line: logLine,
205
204
  });
206
205
  renderer_1.RenderInternals.Log.info({ indent: false, logLevel }, `${(0, source_file_write_queue_1.getCodemodTimingPrefix)(logLevel)}${renderer_1.RenderInternals.chalk.blueBright(`${locationLabel}`)} Added ${elementLabel}`);
207
- if (!formatted) {
208
- (0, log_update_1.warnAboutPrettierOnce)(logLevel);
209
- }
210
- renderer_1.RenderInternals.Log.verbose({ indent: false, logLevel }, `[insert-jsx-element] Wrote ${source}${formatted ? ' (formatted)' : ''}`);
206
+ renderer_1.RenderInternals.Log.verbose({ indent: false, logLevel }, `[insert-jsx-element] Wrote ${source}`);
211
207
  (0, undo_stack_1.printUndoHint)(logLevel);
212
208
  return {
213
209
  success: true,
@@ -2,8 +2,8 @@
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.handleRestartStudio = void 0;
4
4
  const close_and_restart_1 = require("../close-and-restart");
5
- const handleRestartStudio = () => {
6
- (0, close_and_restart_1.signalRestart)();
5
+ const handleRestartStudio = ({ response }) => {
6
+ response.once('finish', close_and_restart_1.signalRestart);
7
7
  return Promise.resolve({});
8
8
  };
9
9
  exports.handleRestartStudio = handleRestartStudio;
@@ -0,0 +1,2 @@
1
+ import type { ApiHandler } from '../api-types';
2
+ export declare const handleShutdownStudio: ApiHandler<{}, {}>;
@@ -0,0 +1,10 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.handleShutdownStudio = void 0;
4
+ const close_and_restart_1 = require("../close-and-restart");
5
+ const handleShutdownStudio = ({ response }) => {
6
+ // Flush the acknowledgement before closing the HTTP and live-event connections.
7
+ response.once('finish', close_and_restart_1.signalShutdown);
8
+ return Promise.resolve({});
9
+ };
10
+ exports.handleShutdownStudio = handleShutdownStudio;
@@ -9,7 +9,6 @@ const resolve_file_inside_project_1 = require("../../helpers/resolve-file-inside
9
9
  const format_log_file_location_1 = require("../format-log-file-location");
10
10
  const sequence_node_path_mutation_1 = require("../sequence-node-path-mutation");
11
11
  const undo_stack_1 = require("../undo-stack");
12
- const log_update_1 = require("./log-updates/log-update");
13
12
  const source_file_write_queue_1 = require("./source-file-write-queue");
14
13
  const splitJsxSequenceHandler = ({ input: { fileName, nodePath, sequenceKeys, splitFrame }, remotionRoot, logLevel, }) => (0, source_file_write_queue_1.withSourceFileWriteQueue)(async () => {
15
14
  try {
@@ -20,7 +19,7 @@ const splitJsxSequenceHandler = ({ input: { fileName, nodePath, sequenceKeys, sp
20
19
  action: 'modify',
21
20
  });
22
21
  const fileContents = (0, node_fs_1.readFileSync)(absolutePath, 'utf-8');
23
- const { output, formatted, nodeLabel, logLine, nodePathRemappings } = await (0, split_jsx_sequence_1.splitJsxSequence)({
22
+ const { output, nodeLabel, logLine, nodePathRemappings } = await (0, split_jsx_sequence_1.splitJsxSequence)({
24
23
  input: fileContents,
25
24
  nodePath,
26
25
  sequenceKeys,
@@ -60,10 +59,7 @@ const splitJsxSequenceHandler = ({ input: { fileName, nodePath, sequenceKeys, sp
60
59
  line: logLine,
61
60
  });
62
61
  renderer_1.RenderInternals.Log.info({ indent: false, logLevel }, `${(0, source_file_write_queue_1.getCodemodTimingPrefix)(logLevel)}${renderer_1.RenderInternals.chalk.blueBright(`${locationLabel}`)} Split ${nodeLabel}`);
63
- if (!formatted) {
64
- (0, log_update_1.warnAboutPrettierOnce)(logLevel);
65
- }
66
- renderer_1.RenderInternals.Log.verbose({ indent: false, logLevel }, `[split-jsx-sequence] Wrote ${fileRelativeToRoot}${formatted ? ' (formatted)' : ''}`);
62
+ renderer_1.RenderInternals.Log.verbose({ indent: false, logLevel }, `[split-jsx-sequence] Wrote ${fileRelativeToRoot}`);
67
63
  (0, undo_stack_1.printUndoHint)(logLevel);
68
64
  return {
69
65
  success: true,
@@ -0,0 +1,3 @@
1
+ import type { ApiRoutes } from '@remotion/studio-shared';
2
+ import type { ApiHandler } from '../api-types';
3
+ export declare const handleUpgradeRemotion: ApiHandler<ApiRoutes['/api/upgrade-remotion']['Request'], ApiRoutes['/api/upgrade-remotion']['Response']>;
@@ -0,0 +1,54 @@
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.handleUpgradeRemotion = void 0;
7
+ const node_child_process_1 = require("node:child_process");
8
+ const node_path_1 = __importDefault(require("node:path"));
9
+ const renderer_1 = require("@remotion/renderer");
10
+ let upgrading = false;
11
+ const handleUpgradeRemotion = async ({ remotionRoot, logLevel, input: { version } }) => {
12
+ if (typeof version !== 'string' || !/^\d+\.\d+\.\d+$/.test(version)) {
13
+ throw new Error('Invalid Remotion version.');
14
+ }
15
+ if (upgrading) {
16
+ throw new Error('A Remotion upgrade is already in progress.');
17
+ }
18
+ upgrading = true;
19
+ try {
20
+ const cliPackage = require.resolve('@remotion/cli/package.json', {
21
+ paths: [remotionRoot],
22
+ });
23
+ const cli = node_path_1.default.join(node_path_1.default.dirname(cliPackage), 'remotion-cli.js');
24
+ await new Promise((resolve, reject) => {
25
+ const child = (0, node_child_process_1.spawn)(process.execPath, [cli, 'upgrade', `--version=${version}`], {
26
+ cwd: remotionRoot,
27
+ stdio: ['ignore', 'pipe', 'pipe'],
28
+ env: { ...process.env, CI: '1' },
29
+ });
30
+ let output = '';
31
+ const onOutput = (chunk) => {
32
+ const message = chunk.toString();
33
+ output = (output + message).slice(-8000);
34
+ renderer_1.RenderInternals.Log.info({ indent: false, logLevel }, message.trimEnd());
35
+ };
36
+ child.stdout.on('data', onOutput);
37
+ child.stderr.on('data', onOutput);
38
+ child.on('error', reject);
39
+ child.on('close', (code, signal) => {
40
+ if (code === 0) {
41
+ resolve();
42
+ }
43
+ else {
44
+ reject(new Error(`Remotion upgrade failed (exit code ${code}, signal ${signal}).\n${output}`));
45
+ }
46
+ });
47
+ });
48
+ return {};
49
+ }
50
+ finally {
51
+ upgrading = false;
52
+ }
53
+ };
54
+ exports.handleUpgradeRemotion = handleUpgradeRemotion;
@@ -1,19 +1,11 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.handleStudioProtocolElementLibrary = void 0;
4
- const zod_1 = require("zod");
4
+ const studio_protocol_1 = require("@remotion/studio-protocol");
5
5
  const element_install_state_1 = require("../element-install-state");
6
6
  const parse_body_1 = require("../parse-body");
7
7
  const origin_policy_1 = require("./origin-policy");
8
8
  const protocol_response_1 = require("./protocol-response");
9
- const studioProtocolElementLibraryRequestSchema = zod_1.z.object({
10
- operation: zod_1.z.literal('add-element-library'),
11
- protocol: zod_1.z.literal('remotion-studio-protocol'),
12
- protocolVersion: zod_1.z.literal(1),
13
- targetId: zod_1.z.string().min(1),
14
- url: zod_1.z.string(),
15
- displayName: zod_1.z.string().nullable(),
16
- });
17
9
  const MAX_STUDIO_PROTOCOL_ELEMENT_LIBRARY_BODY_SIZE = 16 * 1024;
18
10
  const handleStudioProtocolElementLibrary = async ({ configFile, focusStudioTab, liveEventsServer, request, response, }) => {
19
11
  var _a;
@@ -62,8 +54,8 @@ const handleStudioProtocolElementLibrary = async ({ configFile, focusStudioTab,
62
54
  });
63
55
  return;
64
56
  }
65
- const parsedRequest = studioProtocolElementLibraryRequestSchema.safeParse(body);
66
- if (!parsedRequest.success) {
57
+ const parsedRequest = studio_protocol_1.StudioProtocolInternals.parseStudioProtocolAddElementLibraryRequest(body);
58
+ if (parsedRequest === null) {
67
59
  (0, protocol_response_1.writeStudioProtocolError)({
68
60
  code: 'unsupported-protocol',
69
61
  message: 'Invalid Remotion Studio Protocol request.',
@@ -74,7 +66,7 @@ const handleStudioProtocolElementLibrary = async ({ configFile, focusStudioTab,
74
66
  }
75
67
  let normalizedUrl;
76
68
  try {
77
- const parsedUrl = new URL(parsedRequest.data.url);
69
+ const parsedUrl = new URL(parsedRequest.url);
78
70
  if (parsedUrl.protocol !== 'http:' && parsedUrl.protocol !== 'https:') {
79
71
  throw new Error('Unsupported protocol');
80
72
  }
@@ -89,7 +81,7 @@ const handleStudioProtocolElementLibrary = async ({ configFile, focusStudioTab,
89
81
  });
90
82
  return;
91
83
  }
92
- const displayName = (_b = (_a = parsedRequest.data.displayName) === null || _a === void 0 ? void 0 : _a.trim()) !== null && _b !== void 0 ? _b : null;
84
+ const displayName = (_b = (_a = parsedRequest.displayName) === null || _a === void 0 ? void 0 : _a.trim()) !== null && _b !== void 0 ? _b : null;
93
85
  if (displayName === '') {
94
86
  (0, protocol_response_1.writeStudioProtocolError)({
95
87
  code: 'invalid-display-name',
@@ -103,7 +95,7 @@ const handleStudioProtocolElementLibrary = async ({ configFile, focusStudioTab,
103
95
  now: Date.now(),
104
96
  origin: requestOrigin,
105
97
  purpose: 'add-element-library',
106
- targetId: parsedRequest.data.targetId,
98
+ targetId: parsedRequest.targetId,
107
99
  });
108
100
  if (target === null) {
109
101
  (0, protocol_response_1.writeStudioProtocolError)({
@@ -2,22 +2,15 @@
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.handleStudioProtocolInstall = void 0;
4
4
  const studio_protocol_1 = require("@remotion/studio-protocol");
5
- const zod_1 = require("zod");
6
5
  const element_install_state_1 = require("../element-install-state");
7
6
  const parse_body_1 = require("../parse-body");
8
7
  const origin_policy_1 = require("./origin-policy");
9
8
  const protocol_response_1 = require("./protocol-response");
10
- const studioProtocolInstallRequestSchema = zod_1.z.object({
11
- operation: zod_1.z.literal('install-element'),
12
- protocol: zod_1.z.literal('remotion-studio-protocol'),
13
- protocolVersion: zod_1.z.literal(1),
14
- targetId: zod_1.z.string(),
15
- payload: zod_1.z.unknown(),
16
- });
17
9
  // A valid payload may contain 250,000 JSON characters. Allow room for its
18
10
  // UTF-8 representation and the protocol envelope while keeping memory bounded.
19
11
  const MAX_STUDIO_PROTOCOL_INSTALL_BODY_SIZE = 1000000;
20
12
  const deliverElementInstall = ({ element, focusStudioTab, liveEventsServer, origin, target, }) => {
13
+ var _a, _b;
21
14
  if (target.compositionFile === null || target.compositionId === null) {
22
15
  return false;
23
16
  }
@@ -27,7 +20,11 @@ const deliverElementInstall = ({ element, focusStudioTab, liveEventsServer, orig
27
20
  createdAt: Date.now(),
28
21
  compositionFile: target.compositionFile,
29
22
  compositionId: target.compositionId,
30
- element,
23
+ element: {
24
+ ...element,
25
+ durationInFrames: (_a = element.durationInFrames) !== null && _a !== void 0 ? _a : null,
26
+ installationMode: (_b = element.installationMode) !== null && _b !== void 0 ? _b : null,
27
+ },
31
28
  from: null,
32
29
  position: null,
33
30
  source: {
@@ -89,21 +86,15 @@ const handleStudioProtocolInstall = async ({ focusStudioTab, liveEventsServer, r
89
86
  });
90
87
  return;
91
88
  }
92
- const parsedRequest = studioProtocolInstallRequestSchema.safeParse(body);
93
- if (!parsedRequest.success) {
94
- (0, protocol_response_1.writeStudioProtocolError)({
95
- code: 'unsupported-protocol',
96
- message: 'Invalid Remotion Studio Protocol request.',
97
- response,
98
- status: 400,
99
- });
100
- return;
101
- }
102
- const payload = studio_protocol_1.StudioProtocolInternals.parseStudioElementPayload(parsedRequest.data.payload);
103
- if (payload === null) {
89
+ const parsedRequest = studio_protocol_1.StudioProtocolInternals.parseStudioProtocolInstallRequest(body);
90
+ if (parsedRequest.status !== 'valid') {
104
91
  (0, protocol_response_1.writeStudioProtocolError)({
105
- code: 'invalid-payload',
106
- message: 'Invalid Element payload.',
92
+ code: parsedRequest.status === 'invalid-payload'
93
+ ? 'invalid-payload'
94
+ : 'unsupported-protocol',
95
+ message: parsedRequest.status === 'invalid-payload'
96
+ ? 'Invalid Element payload.'
97
+ : 'Invalid Remotion Studio Protocol request.',
107
98
  response,
108
99
  status: 400,
109
100
  });
@@ -113,7 +104,7 @@ const handleStudioProtocolInstall = async ({ focusStudioTab, liveEventsServer, r
113
104
  now: Date.now(),
114
105
  origin: requestOrigin,
115
106
  purpose: 'install-element',
116
- targetId: parsedRequest.data.targetId,
107
+ targetId: parsedRequest.request.targetId,
117
108
  });
118
109
  if (target === null) {
119
110
  (0, protocol_response_1.writeStudioProtocolError)({
@@ -125,7 +116,7 @@ const handleStudioProtocolInstall = async ({ focusStudioTab, liveEventsServer, r
125
116
  return;
126
117
  }
127
118
  if (!deliverElementInstall({
128
- element: payload.element,
119
+ element: parsedRequest.request.payload.element,
129
120
  focusStudioTab,
130
121
  liveEventsServer,
131
122
  origin: requestOrigin,
@@ -2,18 +2,10 @@
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.handleStudioProtocolLicenseKey = void 0;
4
4
  const studio_protocol_1 = require("@remotion/studio-protocol");
5
- const zod_1 = require("zod");
6
5
  const element_install_state_1 = require("../element-install-state");
7
6
  const parse_body_1 = require("../parse-body");
8
7
  const origin_policy_1 = require("./origin-policy");
9
8
  const protocol_response_1 = require("./protocol-response");
10
- const studioProtocolLicenseKeyRequestSchema = zod_1.z.object({
11
- operation: zod_1.z.literal('set-license-key'),
12
- protocol: zod_1.z.literal('remotion-studio-protocol'),
13
- protocolVersion: zod_1.z.literal(1),
14
- targetId: zod_1.z.string().min(1),
15
- licenseKey: zod_1.z.string(),
16
- });
17
9
  const MAX_STUDIO_PROTOCOL_LICENSE_KEY_BODY_SIZE = 4096;
18
10
  const handleStudioProtocolLicenseKey = async ({ configFile, focusStudioTab, liveEventsServer, request, response, }) => {
19
11
  (0, origin_policy_1.setStudioProtocolCorsHeaders)({ request, response });
@@ -60,8 +52,8 @@ const handleStudioProtocolLicenseKey = async ({ configFile, focusStudioTab, live
60
52
  });
61
53
  return;
62
54
  }
63
- const parsedRequest = studioProtocolLicenseKeyRequestSchema.safeParse(body);
64
- if (!parsedRequest.success) {
55
+ const parsedRequest = studio_protocol_1.StudioProtocolInternals.parseStudioProtocolSetLicenseKeyRequest(body);
56
+ if (parsedRequest === null) {
65
57
  (0, protocol_response_1.writeStudioProtocolError)({
66
58
  code: 'unsupported-protocol',
67
59
  message: 'Invalid Remotion Studio Protocol request.',
@@ -70,7 +62,7 @@ const handleStudioProtocolLicenseKey = async ({ configFile, focusStudioTab, live
70
62
  });
71
63
  return;
72
64
  }
73
- if (!studio_protocol_1.StudioProtocolInternals.isValidPublicLicenseKey(parsedRequest.data.licenseKey)) {
65
+ if (!studio_protocol_1.StudioProtocolInternals.isValidPublicLicenseKey(parsedRequest.licenseKey)) {
74
66
  (0, protocol_response_1.writeStudioProtocolError)({
75
67
  code: 'invalid-license-key',
76
68
  message: 'The license key is not a valid public Remotion license key.',
@@ -83,7 +75,7 @@ const handleStudioProtocolLicenseKey = async ({ configFile, focusStudioTab, live
83
75
  now: Date.now(),
84
76
  origin: requestOrigin,
85
77
  purpose: 'set-license-key',
86
- targetId: parsedRequest.data.targetId,
78
+ targetId: parsedRequest.targetId,
87
79
  });
88
80
  if (target === null) {
89
81
  (0, protocol_response_1.writeStudioProtocolError)({
@@ -105,7 +97,7 @@ const handleStudioProtocolLicenseKey = async ({ configFile, focusStudioTab, live
105
97
  }
106
98
  const delivered = liveEventsServer.sendEventToClientId(target.clientId, {
107
99
  type: 'license-key-install-request',
108
- licenseKey: parsedRequest.data.licenseKey,
100
+ licenseKey: parsedRequest.licenseKey,
109
101
  });
110
102
  if (!delivered) {
111
103
  (0, protocol_response_1.writeStudioProtocolError)({
@@ -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-jsx-node' | 'duplicate-jsx-node' | 'split-jsx-sequence' | 'split-video-from-audio' | 'insert-jsx-element' | 'delete-composition' | 'rename-composition' | 'update-composition-metadata' | 'new-composition' | 'duplicate-composition' | 'move-composition-to-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-jsx-node' | 'duplicate-jsx-node' | 'split-jsx-sequence' | 'split-video-from-audio' | 'insert-jsx-element' | 'delete-composition' | 'rename-composition' | 'update-composition-metadata' | 'new-composition' | 'duplicate-composition' | 'move-composition-to-folder' | 'move-composition-or-folder' | 'new-folder' | 'delete-folder' | 'rename-folder';
8
8
  type UndoEntrySnapshot = {
9
9
  filePath: string;
10
10
  oldContents: string | null;
@@ -6,6 +6,8 @@ export type StartStudioResult = {
6
6
  type: 'restarted';
7
7
  } | {
8
8
  type: 'already-running';
9
+ } | {
10
+ type: 'shutdown';
9
11
  };
10
12
  export declare const startStudio: ({ browserArgs, browserFlag, shouldOpenBrowser, fullEntryPath, logLevel, getCurrentInputProps, getEnvVariables, desiredPort, remotionRoot, relativePublicDir, bundlerOverride, rspackOverride, webpackOverride, poll, getRenderDefaults, getRenderQueue, getNumberOfAudioTags, queueMethods, previewEntry, gitSource, binariesDirectory, forceIPv4, getAudioLatencyHint, getExperimentalKeepAudioContextAlive, getPreviewSampleRate, enableCrossSiteIsolation, forceNew, rspack, getStudioRuntimeConfig, getDefaultCodingAgent, getDefaultEditor, configFile, }: {
11
13
  browserArgs: string;
@@ -130,6 +130,7 @@ const startStudio = async ({ browserArgs, browserFlag, shouldOpenBrowser, fullEn
130
130
  url: studioUrl,
131
131
  logLevel,
132
132
  });
133
+ let action;
133
134
  try {
134
135
  await (0, maybe_open_browser_1.maybeOpenBrowser)({
135
136
  browserArgs,
@@ -138,15 +139,20 @@ const startStudio = async ({ browserArgs, browserFlag, shouldOpenBrowser, fullEn
138
139
  url: studioUrl,
139
140
  logLevel,
140
141
  });
141
- await (0, close_and_restart_1.noOpUntilRestart)();
142
+ action = await (0, close_and_restart_1.noOpUntilRestart)();
142
143
  }
143
144
  finally {
144
145
  openBrowserShortcut.cleanup();
145
146
  }
146
- renderer_1.RenderInternals.Log.info({ indent: false, logLevel }, 'Closing server to restart...');
147
+ renderer_1.RenderInternals.Log.info({ indent: false, logLevel }, action === 'shutdown'
148
+ ? 'Shutting down Studio...'
149
+ : 'Closing server to restart...');
147
150
  await liveEventsServer.closeConnections();
148
151
  cleanupLiveEventsListener();
149
152
  await close();
153
+ if (action === 'shutdown') {
154
+ return { type: 'shutdown' };
155
+ }
150
156
  renderer_1.RenderInternals.Log.info({ indent: false, logLevel }, renderer_1.RenderInternals.chalk.blue('Restarting server...'));
151
157
  return { type: 'restarted' };
152
158
  };
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.519",
6
+ "version": "4.0.521",
7
7
  "description": "Run a Remotion Studio with a server backend",
8
8
  "main": "dist",
9
9
  "scripts": {
@@ -23,21 +23,21 @@
23
23
  "access": "public"
24
24
  },
25
25
  "dependencies": {
26
- "@remotion/studio-protocol": "4.0.519",
26
+ "@remotion/studio-protocol": "4.0.521",
27
27
  "@babel/types": "7.24.0",
28
28
  "@babel/parser": "7.24.1",
29
29
  "@svgr/core": "8.1.0",
30
30
  "@svgr/plugin-jsx": "8.1.0",
31
31
  "kiwi-schema": "0.5.0",
32
32
  "semver": "7.5.3",
33
- "zod": "4.4.3",
33
+ "zod": "4.5.4",
34
34
  "prettier": "3.8.1",
35
- "remotion": "4.0.519",
35
+ "remotion": "4.0.521",
36
36
  "recast": "0.23.21",
37
- "@remotion/bundler": "4.0.519",
38
- "@remotion/renderer": "4.0.519",
39
- "@remotion/studio-codemods": "4.0.519",
40
- "@remotion/studio-shared": "4.0.519",
37
+ "@remotion/bundler": "4.0.521",
38
+ "@remotion/renderer": "4.0.521",
39
+ "@remotion/studio-codemods": "4.0.521",
40
+ "@remotion/studio-shared": "4.0.521",
41
41
  "memfs": "3.4.3",
42
42
  "open": "8.4.2"
43
43
  },
@@ -45,7 +45,7 @@
45
45
  "ast-types": "0.16.1",
46
46
  "react": "19.2.3",
47
47
  "@types/semver": "7.5.3",
48
- "@remotion/eslint-config-internal": "4.0.519",
48
+ "@remotion/eslint-config-internal": "4.0.521",
49
49
  "eslint": "9.19.0",
50
50
  "@types/node": "20.12.14",
51
51
  "@typescript/native-preview": "7.0.0-dev.20260217.1"