@remotion/studio-server 4.0.523 → 4.0.524

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.
@@ -11,4 +11,4 @@ export declare const generateCanvasCaptureComposition: ({ componentName, composi
11
11
  readonly videoHeight: number;
12
12
  readonly videoWidth: number;
13
13
  readonly width: number;
14
- }) => Promise<string>;
14
+ }) => string;
@@ -1,7 +1,40 @@
1
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
+ })();
2
35
  Object.defineProperty(exports, "__esModule", { value: true });
3
36
  exports.generateCanvasCaptureComposition = void 0;
4
- const duplicate_composition_1 = require("../codemods/duplicate-composition");
37
+ const recast = __importStar(require("recast"));
5
38
  const customCursorRegex = /^\s*url\(/;
6
39
  const collapseMouseMovementsByFrame = ({ data, keyframeFps, }) => {
7
40
  const movements = [];
@@ -30,7 +63,39 @@ const getCursorName = (cursor) => {
30
63
  }
31
64
  return ((_a = cursor.split(',').at(-1)) === null || _a === void 0 ? void 0 : _a.trim().toLowerCase()) || 'default';
32
65
  };
33
- const serialize = (value) => JSON.stringify(value);
66
+ const serialize = (value) => {
67
+ if (typeof value === 'string') {
68
+ return recast.prettyPrint(recast.types.builders.stringLiteral(value), {
69
+ quote: 'single',
70
+ }).code;
71
+ }
72
+ return JSON.stringify(value);
73
+ };
74
+ const serializeArray = (values, indentation) => {
75
+ const items = values.map(serialize);
76
+ const inline = `[${items.join(', ')}]`;
77
+ if (indentation * 2 + inline.length + 1 <= 80) {
78
+ return inline;
79
+ }
80
+ const lines = [];
81
+ const numeric = values.every((value) => typeof value === 'number');
82
+ for (const item of items) {
83
+ const previous = lines.at(-1);
84
+ if (numeric &&
85
+ previous &&
86
+ (indentation + 1) * 2 + previous.length + item.length + 2 <= 80) {
87
+ lines[lines.length - 1] = `${previous} ${item},`;
88
+ }
89
+ else {
90
+ lines.push(`${item},`);
91
+ }
92
+ }
93
+ return [
94
+ '[',
95
+ ...lines.map((line) => `${'\t'.repeat(indentation + 1)}${line}`),
96
+ `${'\t'.repeat(indentation)}]`,
97
+ ].join('\n');
98
+ };
34
99
  const generateCanvasCaptureComposition = ({ componentName, compositionId, data, durationInFrames, fps, height, keyframeFps, videoFileName, videoHeight, videoWidth, width, }) => {
35
100
  var _a;
36
101
  const movements = collapseMouseMovementsByFrame({ data, keyframeFps });
@@ -79,11 +144,11 @@ const generateCanvasCaptureComposition = ({ componentName, compositionId, data,
79
144
  }, []);
80
145
  const customCursor = (_a = movements.find((movement) => customCursorRegex.test(movement.cursor))) === null || _a === void 0 ? void 0 : _a.cursor;
81
146
  const cursorProp = cursorKeyframes.length === 1
82
- ? `cursor=${serialize(cursorKeyframes[0].value)}`
147
+ ? `cursor={${serialize(cursorKeyframes[0].value)}}`
83
148
  : `cursor={interpolate(
84
149
  frame,
85
- ${serialize(cursorKeyframes.map((keyframe) => keyframe.frame))},
86
- ${serialize(cursorKeyframes.map((keyframe) => keyframe.value))},
150
+ ${serializeArray(cursorKeyframes.map((keyframe) => keyframe.frame), 5)},
151
+ ${serializeArray(cursorKeyframes.map((keyframe) => keyframe.value), 5)},
87
152
  {
88
153
  easing: Easing.step1,
89
154
  extrapolateLeft: 'clamp',
@@ -94,8 +159,8 @@ const generateCanvasCaptureComposition = ({ componentName, compositionId, data,
94
159
  ? serialize(scaleKeyframes[0].value)
95
160
  : `interpolate(
96
161
  frame,
97
- ${serialize(scaleKeyframes.map((keyframe) => keyframe.frame))},
98
- ${serialize(scaleKeyframes.map((keyframe) => keyframe.value))},
162
+ ${serializeArray(scaleKeyframes.map((keyframe) => keyframe.frame), 6)},
163
+ ${serializeArray(scaleKeyframes.map((keyframe) => keyframe.value), 6)},
99
164
  {
100
165
  easing: Easing.step1,
101
166
  extrapolateLeft: 'clamp',
@@ -106,8 +171,8 @@ const generateCanvasCaptureComposition = ({ componentName, compositionId, data,
106
171
  ? serialize(positionKeyframes[0].value)
107
172
  : `interpolate(
108
173
  frame,
109
- ${serialize(positionKeyframes.map((keyframe) => keyframe.frame))},
110
- ${serialize(positionKeyframes.map((keyframe) => keyframe.value))},
174
+ ${serializeArray(positionKeyframes.map((keyframe) => keyframe.frame), 6)},
175
+ ${serializeArray(positionKeyframes.map((keyframe) => keyframe.value), 6)},
111
176
  {
112
177
  extrapolateLeft: 'clamp',
113
178
  extrapolateRight: 'clamp',
@@ -116,7 +181,7 @@ const generateCanvasCaptureComposition = ({ componentName, compositionId, data,
116
181
  const previewComponentName = componentName.endsWith('Composition')
117
182
  ? `${componentName.slice(0, -'Composition'.length)}Preview`
118
183
  : `${componentName}Preview`;
119
- return (0, duplicate_composition_1.formatOutput)(`import {MacOSCursor} from '@remotion/mac-cursors';
184
+ return `import {MacOSCursor} from '@remotion/mac-cursors';
120
185
  import {Video} from '@remotion/media';
121
186
  import {
122
187
  AbsoluteFill,
@@ -160,7 +225,7 @@ ${customCursor === undefined ? '' : `\t\t\t\tcustomCursor={${serialize(customCur
160
225
  export const ${componentName} = () => {
161
226
  return (
162
227
  <Composition
163
- id=${serialize(compositionId)}
228
+ id={${serialize(compositionId)}}
164
229
  component={${previewComponentName}}
165
230
  width={${width}}
166
231
  height={${height}}
@@ -169,6 +234,6 @@ export const ${componentName} = () => {
169
234
  />
170
235
  );
171
236
  };
172
- `);
237
+ `;
173
238
  };
174
239
  exports.generateCanvasCaptureComposition = generateCanvasCaptureComposition;
@@ -27,6 +27,13 @@ const applyCodemodToFile = async ({ filePath, codeMod, }) => {
27
27
  codeMod,
28
28
  input,
29
29
  });
30
- return (0, duplicate_composition_1.formatOutput)(newContents);
30
+ if (codeMod.type === 'new-composition' ||
31
+ codeMod.type === 'duplicate-composition' ||
32
+ codeMod.type === 'rename-composition' ||
33
+ codeMod.type === 'delete-composition') {
34
+ return newContents;
35
+ }
36
+ const formatted = await (0, duplicate_composition_1.formatOutput)(newContents);
37
+ return formatted;
31
38
  };
32
39
  exports.applyCodemodToFile = applyCodemodToFile;
@@ -10,7 +10,6 @@ const renderer_1 = require("@remotion/renderer");
10
10
  const studio_codemods_1 = require("@remotion/studio-codemods");
11
11
  const generate_canvas_capture_composition_1 = require("../../canvas-capture/generate-canvas-capture-composition");
12
12
  const apply_codemod_to_file_1 = require("../../codemods/apply-codemod-to-file");
13
- const duplicate_composition_1 = require("../../codemods/duplicate-composition");
14
13
  const file_watcher_1 = require("../../file-watcher");
15
14
  const format_log_file_location_1 = require("../format-log-file-location");
16
15
  const project_info_1 = require("../project-info");
@@ -33,12 +32,12 @@ const formatNewCompositionFile = (codemod) => {
33
32
  width: codemod.newWidth,
34
33
  });
35
34
  }
36
- return (0, duplicate_composition_1.formatOutput)(`import React from 'react';
35
+ return `import React from 'react';
37
36
 
38
37
  export const ${codemod.componentName}: React.FC = () => {
39
38
  return null;
40
39
  };
41
- `);
40
+ `;
42
41
  };
43
42
  const getFolderPath = (parentName, folderName) => {
44
43
  return parentName ? `${parentName}/${folderName}` : folderName;
@@ -22,6 +22,8 @@ const hasExpectedFileState = ({ expected, actual, }) => {
22
22
  return actual.sourceHash === expected.sourceHash;
23
23
  };
24
24
  const insertElementHandler = ({ input: { compositionFile, compositionId, element, installationName, expectedFileState, from, position, overwriteExisting, }, entryPoint, remotionRoot, logLevel, }) => (0, source_file_write_queue_1.withSourceFileWriteQueue)(async () => {
25
+ var _a;
26
+ var _b;
25
27
  try {
26
28
  (0, element_install_plan_1.validateElementInstallPosition)(position);
27
29
  if (from !== null &&
@@ -32,6 +34,21 @@ const insertElementHandler = ({ input: { compositionFile, compositionId, element
32
34
  ? 'wrapped'
33
35
  : element.installationMode;
34
36
  const componentOwnsSequence = installationMode === 'component-owned-sequence';
37
+ if (componentOwnsSequence &&
38
+ element.initialProps !== null &&
39
+ ['from', 'durationInFrames', 'name'].some((prop) => {
40
+ var _a;
41
+ return Object.hasOwn((_a = element.initialProps) !== null && _a !== void 0 ? _a : {}, prop);
42
+ })) {
43
+ throw new Error('Component-owned Element initial props must not override from, durationInFrames, or name');
44
+ }
45
+ if (componentOwnsSequence &&
46
+ ((_a = element.initialProps) === null || _a === void 0 ? void 0 : _a.style) !== undefined &&
47
+ (element.initialProps.style === null ||
48
+ typeof element.initialProps.style !== 'object' ||
49
+ Array.isArray(element.initialProps.style))) {
50
+ throw new Error('Component-owned Element initial style must be an object');
51
+ }
35
52
  renderer_1.RenderInternals.Log.trace({ indent: false, logLevel }, `[insert-element] Received request for compositionFile="${compositionFile}" compositionId="${compositionId}" element="${element.slug}"`);
36
53
  const plan = await (0, element_install_plan_1.getElementInstallPlan)({
37
54
  installationName,
@@ -86,19 +103,20 @@ const insertElementHandler = ({ input: { compositionFile, compositionId, element
86
103
  componentName: plan.componentName,
87
104
  importName: plan.componentName,
88
105
  importPath: plan.importPath,
89
- props: componentOwnsSequence
90
- ? [
91
- ...(element.durationInFrames === null
92
- ? []
93
- : [
94
- {
95
- name: 'durationInFrames',
96
- value: element.durationInFrames,
97
- },
98
- ]),
99
- { name: 'name', value: element.displayName },
100
- ]
101
- : [],
106
+ props: [
107
+ ...Object.entries((_b = element.initialProps) !== null && _b !== void 0 ? _b : {}).map(([name, value]) => ({ name, value })),
108
+ ...(componentOwnsSequence && element.durationInFrames !== null
109
+ ? [
110
+ {
111
+ name: 'durationInFrames',
112
+ value: element.durationInFrames,
113
+ },
114
+ ]
115
+ : []),
116
+ ...(componentOwnsSequence
117
+ ? [{ name: 'name', value: element.displayName }]
118
+ : []),
119
+ ],
102
120
  position: componentOwnsSequence ? position : null,
103
121
  },
104
122
  from: componentOwnsSequence ? from : null,
@@ -43,7 +43,7 @@ const getProject = ({ gitSource, remotionRoot, }) => (0, studio_shared_1.getProj
43
43
  });
44
44
  const handleStudioProtocolDiscovery = ({ gitSource, liveEventsServer, remotionRoot, request, response, }) => {
45
45
  (0, origin_policy_1.setStudioProtocolCorsHeaders)({ request, response });
46
- const requestOrigin = (0, origin_policy_1.getAllowedStudioProtocolOrigin)(request.headers.origin);
46
+ const requestOrigin = (0, origin_policy_1.getAllowedStudioProtocolOrigin)(request);
47
47
  if (requestOrigin === null) {
48
48
  (0, protocol_response_1.writeStudioProtocolError)({
49
49
  code: 'unsupported-origin',
@@ -11,7 +11,7 @@ const handleStudioProtocolElementLibrary = async ({ configFile, focusStudioTab,
11
11
  var _a;
12
12
  var _b;
13
13
  (0, origin_policy_1.setStudioProtocolCorsHeaders)({ request, response });
14
- const requestOrigin = (0, origin_policy_1.getAllowedStudioProtocolOrigin)(request.headers.origin);
14
+ const requestOrigin = (0, origin_policy_1.getAllowedStudioProtocolOrigin)(request);
15
15
  if (requestOrigin === null) {
16
16
  (0, protocol_response_1.writeStudioProtocolError)({
17
17
  code: 'unsupported-origin',
@@ -10,7 +10,7 @@ const protocol_response_1 = require("./protocol-response");
10
10
  // UTF-8 representation and the protocol envelope while keeping memory bounded.
11
11
  const MAX_STUDIO_PROTOCOL_INSTALL_BODY_SIZE = 1000000;
12
12
  const deliverElementInstall = ({ element, focusStudioTab, liveEventsServer, origin, target, }) => {
13
- var _a, _b;
13
+ var _a, _b, _c;
14
14
  if (target.compositionFile === null || target.compositionId === null) {
15
15
  return false;
16
16
  }
@@ -23,7 +23,8 @@ const deliverElementInstall = ({ element, focusStudioTab, liveEventsServer, orig
23
23
  element: {
24
24
  ...element,
25
25
  durationInFrames: (_a = element.durationInFrames) !== null && _a !== void 0 ? _a : null,
26
- installationMode: (_b = element.installationMode) !== null && _b !== void 0 ? _b : null,
26
+ initialProps: (_b = element.initialProps) !== null && _b !== void 0 ? _b : null,
27
+ installationMode: (_c = element.installationMode) !== null && _c !== void 0 ? _c : null,
27
28
  },
28
29
  from: null,
29
30
  position: null,
@@ -43,7 +44,7 @@ const deliverElementInstall = ({ element, focusStudioTab, liveEventsServer, orig
43
44
  };
44
45
  const handleStudioProtocolInstall = async ({ focusStudioTab, liveEventsServer, request, response, }) => {
45
46
  (0, origin_policy_1.setStudioProtocolCorsHeaders)({ request, response });
46
- const requestOrigin = (0, origin_policy_1.getAllowedStudioProtocolOrigin)(request.headers.origin);
47
+ const requestOrigin = (0, origin_policy_1.getAllowedStudioProtocolOrigin)(request);
47
48
  if (requestOrigin === null) {
48
49
  (0, protocol_response_1.writeStudioProtocolError)({
49
50
  code: 'unsupported-origin',
@@ -9,7 +9,7 @@ const protocol_response_1 = require("./protocol-response");
9
9
  const MAX_STUDIO_PROTOCOL_LICENSE_KEY_BODY_SIZE = 4096;
10
10
  const handleStudioProtocolLicenseKey = async ({ configFile, focusStudioTab, liveEventsServer, request, response, }) => {
11
11
  (0, origin_policy_1.setStudioProtocolCorsHeaders)({ request, response });
12
- const requestOrigin = (0, origin_policy_1.getAllowedStudioProtocolOrigin)(request.headers.origin);
12
+ const requestOrigin = (0, origin_policy_1.getAllowedStudioProtocolOrigin)(request);
13
13
  if (requestOrigin === null) {
14
14
  (0, protocol_response_1.writeStudioProtocolError)({
15
15
  code: 'unsupported-origin',
@@ -1,5 +1,5 @@
1
1
  import type { IncomingMessage, ServerResponse } from 'node:http';
2
- export declare const getAllowedStudioProtocolOrigin: (origin: string | undefined) => string | null;
2
+ export declare const getAllowedStudioProtocolOrigin: (request: IncomingMessage) => string | null;
3
3
  export declare const setStudioProtocolCorsHeaders: ({ request, response, }: {
4
4
  readonly request: IncomingMessage;
5
5
  readonly response: ServerResponse<IncomingMessage>;
@@ -3,11 +3,18 @@ Object.defineProperty(exports, "__esModule", { value: true });
3
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
- const getAllowedStudioProtocolOrigin = (origin) => {
7
- if (!origin) {
8
- return null;
9
- }
6
+ const getAllowedStudioProtocolOrigin = (request) => {
10
7
  try {
8
+ const { origin, referer, host } = request.headers;
9
+ if (origin === undefined) {
10
+ // Browsers omit Origin on same-origin GET requests. Only trust a
11
+ // Referer matching this local HTTP Studio, never an arbitrary site.
12
+ const refererUrl = new URL(referer !== null && referer !== void 0 ? referer : '');
13
+ return isLoopbackHttp(refererUrl) &&
14
+ refererUrl.origin === `http://${host}`
15
+ ? refererUrl.origin
16
+ : null;
17
+ }
11
18
  const url = new URL(origin);
12
19
  if (url.protocol !== 'https:' && !isLoopbackHttp(url)) {
13
20
  return null;
@@ -20,7 +27,7 @@ const getAllowedStudioProtocolOrigin = (origin) => {
20
27
  };
21
28
  exports.getAllowedStudioProtocolOrigin = getAllowedStudioProtocolOrigin;
22
29
  const setStudioProtocolCorsHeaders = ({ request, response, }) => {
23
- const origin = (0, exports.getAllowedStudioProtocolOrigin)(request.headers.origin);
30
+ const origin = (0, exports.getAllowedStudioProtocolOrigin)(request);
24
31
  if (origin === null) {
25
32
  return;
26
33
  }
@@ -34,7 +41,7 @@ const setStudioProtocolCorsHeaders = ({ request, response, }) => {
34
41
  exports.setStudioProtocolCorsHeaders = setStudioProtocolCorsHeaders;
35
42
  const handleStudioProtocolOptions = ({ request, response, }) => {
36
43
  (0, exports.setStudioProtocolCorsHeaders)({ request, response });
37
- const origin = (0, exports.getAllowedStudioProtocolOrigin)(request.headers.origin);
44
+ const origin = (0, exports.getAllowedStudioProtocolOrigin)(request);
38
45
  response.writeHead(origin === null ? 403 : 204);
39
46
  response.end();
40
47
  return Promise.resolve();
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.523",
6
+ "version": "4.0.524",
7
7
  "description": "Run a Remotion Studio with a server backend",
8
8
  "main": "dist",
9
9
  "scripts": {
@@ -23,7 +23,7 @@
23
23
  "access": "public"
24
24
  },
25
25
  "dependencies": {
26
- "@remotion/studio-protocol": "4.0.523",
26
+ "@remotion/studio-protocol": "4.0.524",
27
27
  "@babel/types": "7.24.0",
28
28
  "@babel/parser": "7.24.1",
29
29
  "@svgr/core": "8.1.0",
@@ -32,12 +32,12 @@
32
32
  "semver": "7.5.3",
33
33
  "zod": "4.5.4",
34
34
  "prettier": "3.8.1",
35
- "remotion": "4.0.523",
35
+ "remotion": "4.0.524",
36
36
  "recast": "0.23.21",
37
- "@remotion/bundler": "4.0.523",
38
- "@remotion/renderer": "4.0.523",
39
- "@remotion/studio-codemods": "4.0.523",
40
- "@remotion/studio-shared": "4.0.523",
37
+ "@remotion/bundler": "4.0.524",
38
+ "@remotion/renderer": "4.0.524",
39
+ "@remotion/studio-codemods": "4.0.524",
40
+ "@remotion/studio-shared": "4.0.524",
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.523",
48
+ "@remotion/eslint-config-internal": "4.0.524",
49
49
  "eslint": "9.19.0",
50
50
  "@types/node": "20.12.14",
51
51
  "@typescript/native-preview": "7.0.0-dev.20260217.1"