@remotion/studio-server 4.0.501 → 4.0.502

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 (27) hide show
  1. package/dist/codemods/update-inline-caption-patches.d.ts +1 -11
  2. package/dist/codemods/update-inline-caption-patches.js +2 -183
  3. package/dist/codemods/update-sequence-props/update-sequence-props.d.ts +2 -35
  4. package/dist/codemods/update-sequence-props/update-sequence-props.js +7 -720
  5. package/dist/helpers/resolve-composition-component.js +18 -6
  6. package/dist/preview-server/element-install-state.d.ts +16 -0
  7. package/dist/preview-server/element-install-state.js +43 -1
  8. package/dist/preview-server/handler.js +1 -1
  9. package/dist/preview-server/parse-body.d.ts +6 -1
  10. package/dist/preview-server/parse-body.js +60 -9
  11. package/dist/preview-server/routes/can-update-default-props.d.ts +1 -1
  12. package/dist/preview-server/routes/can-update-default-props.js +5 -132
  13. package/dist/preview-server/routes/can-update-sequence-props.d.ts +3 -2
  14. package/dist/preview-server/routes/can-update-sequence-props.js +51 -9
  15. package/dist/preview-server/routes/insert-element.js +5 -5
  16. package/dist/preview-server/routes/insert-jsx-element.js +5 -5
  17. package/dist/preview-server/sequence-props-watchers.js +2 -1
  18. package/dist/preview-server/studio-protocol/handle-discovery.d.ts +11 -0
  19. package/dist/preview-server/studio-protocol/handle-discovery.js +99 -0
  20. package/dist/preview-server/studio-protocol/handle-install.d.ts +10 -0
  21. package/dist/preview-server/studio-protocol/handle-install.js +139 -0
  22. package/dist/preview-server/studio-protocol/origin-policy.d.ts +10 -0
  23. package/dist/preview-server/studio-protocol/origin-policy.js +40 -0
  24. package/dist/preview-server/studio-protocol/protocol-response.d.ts +7 -0
  25. package/dist/preview-server/studio-protocol/protocol-response.js +13 -0
  26. package/dist/routes.js +14 -154
  27. package/package.json +9 -8
@@ -248,9 +248,6 @@ const findReExportTargets = ({ ast, exportName, }) => {
248
248
  visitExportNamedDeclaration(astPath) {
249
249
  var _a;
250
250
  const node = astPath.node;
251
- if (typeof ((_a = node.source) === null || _a === void 0 ? void 0 : _a.value) !== 'string') {
252
- return false;
253
- }
254
251
  for (const specifier of node.specifiers) {
255
252
  if (specifier.type !== 'ExportSpecifier') {
256
253
  continue;
@@ -263,6 +260,18 @@ const findReExportTargets = ({ ast, exportName, }) => {
263
260
  if (!localName) {
264
261
  continue;
265
262
  }
263
+ // Support barrel files that import a component and export it in a
264
+ // separate declaration. See https://github.com/remotion-dev/remotion/issues/9172.
265
+ if (typeof ((_a = node.source) === null || _a === void 0 ? void 0 : _a.value) !== 'string') {
266
+ const importTarget = findImportTarget({
267
+ ast,
268
+ componentName: localName,
269
+ });
270
+ if (importTarget) {
271
+ targets.push(importTarget);
272
+ }
273
+ continue;
274
+ }
266
275
  targets.push({
267
276
  importPath: node.source.value,
268
277
  exportName: localName === 'default' ? 'default' : localName,
@@ -314,6 +323,9 @@ const locationFromNode = (node) => {
314
323
  };
315
324
  const findLocalSymbolLocation = ({ ast, name, }) => {
316
325
  let location = null;
326
+ // Recast can omit the declaration location for exported functions and
327
+ // classes, including components resolved through barrel files. The identifier
328
+ // keeps its location. See https://github.com/remotion-dev/remotion/issues/9172.
317
329
  recast.types.visit(ast, {
318
330
  visitVariableDeclarator(astPath) {
319
331
  if (location) {
@@ -321,7 +333,7 @@ const findLocalSymbolLocation = ({ ast, name, }) => {
321
333
  }
322
334
  const { node } = astPath;
323
335
  if (node.id.type === 'Identifier' && node.id.name === name) {
324
- location = locationFromNode(node);
336
+ location = locationFromNode(node.id);
325
337
  return false;
326
338
  }
327
339
  this.traverse(astPath);
@@ -334,7 +346,7 @@ const findLocalSymbolLocation = ({ ast, name, }) => {
334
346
  }
335
347
  const { node } = astPath;
336
348
  if (((_a = node.id) === null || _a === void 0 ? void 0 : _a.name) === name) {
337
- location = locationFromNode(node);
349
+ location = locationFromNode(node.id);
338
350
  return false;
339
351
  }
340
352
  this.traverse(astPath);
@@ -347,7 +359,7 @@ const findLocalSymbolLocation = ({ ast, name, }) => {
347
359
  }
348
360
  const { node } = astPath;
349
361
  if (((_a = node.id) === null || _a === void 0 ? void 0 : _a.name) === name) {
350
- location = locationFromNode(node);
362
+ location = locationFromNode(node.id);
351
363
  return false;
352
364
  }
353
365
  this.traverse(astPath);
@@ -1,4 +1,5 @@
1
1
  export declare const ELEMENT_INSTALL_TARGET_MAX_AGE = 5000;
2
+ export declare const STUDIO_PROTOCOL_TARGET_MAX_AGE = 4000;
2
3
  export type ElementInstallTarget = {
3
4
  requestId: string | null;
4
5
  clientId: string;
@@ -10,6 +11,21 @@ export type ElementInstallTarget = {
10
11
  studioUrl: string;
11
12
  updatedAt: number;
12
13
  };
14
+ type StudioProtocolTarget = {
15
+ readonly id: string;
16
+ readonly target: ElementInstallTarget;
17
+ readonly expiresAt: number;
18
+ };
13
19
  export declare const updateElementInstallTarget: (newTarget: Omit<ElementInstallTarget, "updatedAt">) => void;
20
+ export declare const getElementInstallTargetByClientId: (clientId: string) => ElementInstallTarget | null;
14
21
  export declare const getElementInstallTarget: (requestId: string | null) => ElementInstallTarget | null;
22
+ export declare const issueStudioProtocolTarget: ({ now, target, }: {
23
+ readonly now: number;
24
+ readonly target: ElementInstallTarget;
25
+ }) => StudioProtocolTarget;
26
+ export declare const consumeStudioProtocolTarget: ({ now, targetId, }: {
27
+ readonly now: number;
28
+ readonly targetId: string;
29
+ }) => ElementInstallTarget | null;
15
30
  export declare const clearElementInstallStateForTests: () => void;
31
+ export {};
@@ -1,8 +1,11 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.clearElementInstallStateForTests = exports.getElementInstallTarget = exports.updateElementInstallTarget = exports.ELEMENT_INSTALL_TARGET_MAX_AGE = void 0;
3
+ exports.clearElementInstallStateForTests = exports.consumeStudioProtocolTarget = exports.issueStudioProtocolTarget = exports.getElementInstallTarget = exports.getElementInstallTargetByClientId = exports.updateElementInstallTarget = exports.STUDIO_PROTOCOL_TARGET_MAX_AGE = exports.ELEMENT_INSTALL_TARGET_MAX_AGE = void 0;
4
+ const node_crypto_1 = require("node:crypto");
4
5
  exports.ELEMENT_INSTALL_TARGET_MAX_AGE = 5000;
6
+ exports.STUDIO_PROTOCOL_TARGET_MAX_AGE = 4000;
5
7
  const targetsByClientId = new Map();
8
+ const studioProtocolTargets = new Map();
6
9
  const compareTargets = (a, b) => {
7
10
  var _a, _b;
8
11
  const aFocusedAt = (_a = a.lastFocusedAt) !== null && _a !== void 0 ? _a : 0;
@@ -19,6 +22,11 @@ const updateElementInstallTarget = (newTarget) => {
19
22
  });
20
23
  };
21
24
  exports.updateElementInstallTarget = updateElementInstallTarget;
25
+ const getElementInstallTargetByClientId = (clientId) => {
26
+ var _a;
27
+ return (_a = targetsByClientId.get(clientId)) !== null && _a !== void 0 ? _a : null;
28
+ };
29
+ exports.getElementInstallTargetByClientId = getElementInstallTargetByClientId;
22
30
  const getElementInstallTarget = (requestId) => {
23
31
  const now = Date.now();
24
32
  let bestTarget = null;
@@ -37,7 +45,41 @@ const getElementInstallTarget = (requestId) => {
37
45
  return bestTarget;
38
46
  };
39
47
  exports.getElementInstallTarget = getElementInstallTarget;
48
+ const issueStudioProtocolTarget = ({ now, target, }) => {
49
+ for (const [id, existing] of studioProtocolTargets) {
50
+ if (existing.expiresAt <= now) {
51
+ studioProtocolTargets.delete(id);
52
+ }
53
+ }
54
+ const issued = {
55
+ id: (0, node_crypto_1.randomUUID)(),
56
+ target: { ...target },
57
+ expiresAt: now + exports.STUDIO_PROTOCOL_TARGET_MAX_AGE,
58
+ };
59
+ studioProtocolTargets.set(issued.id, issued);
60
+ return issued;
61
+ };
62
+ exports.issueStudioProtocolTarget = issueStudioProtocolTarget;
63
+ const consumeStudioProtocolTarget = ({ now, targetId, }) => {
64
+ const issued = studioProtocolTargets.get(targetId);
65
+ studioProtocolTargets.delete(targetId);
66
+ if (issued === undefined || issued.expiresAt <= now) {
67
+ return null;
68
+ }
69
+ const current = (0, exports.getElementInstallTargetByClientId)(issued.target.clientId);
70
+ if (current === null ||
71
+ now - current.updatedAt >= exports.ELEMENT_INSTALL_TARGET_MAX_AGE ||
72
+ !current.canInstall ||
73
+ current.readOnly ||
74
+ current.compositionFile !== issued.target.compositionFile ||
75
+ current.compositionId !== issued.target.compositionId) {
76
+ return null;
77
+ }
78
+ return issued.target;
79
+ };
80
+ exports.consumeStudioProtocolTarget = consumeStudioProtocolTarget;
40
81
  const clearElementInstallStateForTests = () => {
41
82
  targetsByClientId.clear();
83
+ studioProtocolTargets.clear();
42
84
  };
43
85
  exports.clearElementInstallStateForTests = clearElementInstallStateForTests;
@@ -13,7 +13,7 @@ const handleRequest = async ({ remotionRoot, request, response, entryPoint, hand
13
13
  response.setHeader('content-type', 'application/json');
14
14
  response.writeHead(200);
15
15
  try {
16
- const body = (await (0, parse_body_1.parseRequestBody)(request));
16
+ const body = (await (0, parse_body_1.parseRequestBody)(request, { maxBytes: null }));
17
17
  const outputData = await handler({
18
18
  entryPoint,
19
19
  remotionRoot,
@@ -1,2 +1,7 @@
1
1
  import type { IncomingMessage } from 'node:http';
2
- export declare const parseRequestBody: (req: IncomingMessage) => Promise<unknown>;
2
+ export declare class RequestBodyTooLargeError extends Error {
3
+ constructor(maxBytes: number);
4
+ }
5
+ export declare const parseRequestBody: (req: IncomingMessage, { maxBytes, }: {
6
+ readonly maxBytes: number | null;
7
+ }) => Promise<unknown>;
@@ -1,15 +1,66 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.parseRequestBody = void 0;
4
- const parseRequestBody = async (req) => {
5
- const body = await new Promise((_resolve) => {
3
+ exports.parseRequestBody = exports.RequestBodyTooLargeError = void 0;
4
+ class RequestBodyTooLargeError extends Error {
5
+ constructor(maxBytes) {
6
+ super(`Request body exceeds the limit of ${maxBytes} bytes`);
7
+ this.name = 'RequestBodyTooLargeError';
8
+ }
9
+ }
10
+ exports.RequestBodyTooLargeError = RequestBodyTooLargeError;
11
+ const parseRequestBody = async (req, { maxBytes, }) => {
12
+ const body = await new Promise((resolve, reject) => {
13
+ const decoder = new TextDecoder();
14
+ const encoder = new TextEncoder();
6
15
  let data = '';
7
- req.on('data', (chunk) => {
8
- data += chunk;
9
- });
10
- req.on('end', () => {
11
- _resolve(data.toString());
12
- });
16
+ let receivedBytes = 0;
17
+ let settled = false;
18
+ const cleanup = () => {
19
+ req.off('aborted', onAborted);
20
+ req.off('data', onData);
21
+ req.off('end', onEnd);
22
+ req.off('error', onError);
23
+ };
24
+ const rejectOnce = (error) => {
25
+ if (settled) {
26
+ return;
27
+ }
28
+ settled = true;
29
+ cleanup();
30
+ reject(error);
31
+ };
32
+ const onAborted = () => rejectOnce(new Error('Request body was aborted'));
33
+ const onData = (chunk) => {
34
+ receivedBytes +=
35
+ typeof chunk === 'string'
36
+ ? encoder.encode(chunk).byteLength
37
+ : chunk.byteLength;
38
+ if (maxBytes !== null && receivedBytes > maxBytes) {
39
+ rejectOnce(new RequestBodyTooLargeError(maxBytes));
40
+ // Discard the rest without buffering it. Keep request stream errors from
41
+ // becoming unhandled after the parser listeners have been removed.
42
+ req.on('error', () => undefined);
43
+ req.resume();
44
+ return;
45
+ }
46
+ data +=
47
+ typeof chunk === 'string'
48
+ ? decoder.decode() + chunk
49
+ : decoder.decode(chunk, { stream: true });
50
+ };
51
+ const onEnd = () => {
52
+ if (settled) {
53
+ return;
54
+ }
55
+ settled = true;
56
+ cleanup();
57
+ resolve(data + decoder.decode());
58
+ };
59
+ const onError = (error) => rejectOnce(error);
60
+ req.on('aborted', onAborted);
61
+ req.on('data', onData);
62
+ req.on('end', onEnd);
63
+ req.on('error', onError);
13
64
  });
14
65
  return JSON.parse(body);
15
66
  };
@@ -1,6 +1,6 @@
1
1
  import type { CanUpdateDefaultPropsResponse } from '@remotion/studio-shared';
2
+ export { computeCanUpdateDefaultPropsFromContent } from '@remotion/studio-codemods';
2
3
  export declare const checkIfTypeScriptFile: (file: string) => void;
3
- export declare const computeCanUpdateDefaultPropsFromContent: (content: string, compositionId: string) => CanUpdateDefaultPropsResponse;
4
4
  export declare const computeCanUpdateDefaultProps: ({ compositionId, remotionRoot, entryPoint, }: {
5
5
  compositionId: string;
6
6
  remotionRoot: string;
@@ -1,44 +1,11 @@
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
- })();
35
2
  Object.defineProperty(exports, "__esModule", { value: true });
36
- exports.computeCanUpdateDefaultProps = exports.computeCanUpdateDefaultPropsFromContent = exports.checkIfTypeScriptFile = void 0;
3
+ exports.computeCanUpdateDefaultProps = exports.checkIfTypeScriptFile = exports.computeCanUpdateDefaultPropsFromContent = void 0;
37
4
  const node_fs_1 = require("node:fs");
38
- const recast = __importStar(require("recast"));
39
- const parse_ast_1 = require("../../codemods/parse-ast");
5
+ const studio_codemods_1 = require("@remotion/studio-codemods");
40
6
  const project_info_1 = require("../project-info");
41
- const can_update_sequence_props_1 = require("./can-update-sequence-props");
7
+ const studio_codemods_2 = require("@remotion/studio-codemods");
8
+ Object.defineProperty(exports, "computeCanUpdateDefaultPropsFromContent", { enumerable: true, get: function () { return studio_codemods_2.computeCanUpdateDefaultPropsFromContent; } });
42
9
  const checkIfTypeScriptFile = (file) => {
43
10
  if (!file.endsWith('.tsx') &&
44
11
  !file.endsWith('.ts') &&
@@ -48,100 +15,6 @@ const checkIfTypeScriptFile = (file) => {
48
15
  }
49
16
  };
50
17
  exports.checkIfTypeScriptFile = checkIfTypeScriptFile;
51
- const extractDefaultPropsFromSource = (input, compositionId) => {
52
- const ast = (0, parse_ast_1.parseAst)(input);
53
- let result = null;
54
- recast.types.visit(ast, {
55
- visitJSXElement(path) {
56
- var _a;
57
- const { openingElement } = path.node;
58
- const openingName = openingElement.name;
59
- if (openingName.type !== 'JSXIdentifier' &&
60
- openingName.type !== 'JSXNamespacedName') {
61
- this.traverse(path);
62
- return;
63
- }
64
- if (openingName.name !== 'Composition' && openingName.name !== 'Still') {
65
- this.traverse(path);
66
- return;
67
- }
68
- if (!((_a = openingElement.attributes) === null || _a === void 0 ? void 0 : _a.some((attr) => {
69
- if (attr.type === 'JSXSpreadAttribute') {
70
- return;
71
- }
72
- if (!attr.value) {
73
- return;
74
- }
75
- if (attr.value.type === 'JSXElement') {
76
- return;
77
- }
78
- if (attr.value.type === 'JSXExpressionContainer') {
79
- return;
80
- }
81
- if (attr.value.type === 'JSXFragment') {
82
- return;
83
- }
84
- return attr.name.name === 'id' && attr.value.value === compositionId;
85
- }))) {
86
- this.traverse(path);
87
- return;
88
- }
89
- const defaultPropsAttr = openingElement.attributes.find((attr) => {
90
- if (attr.type === 'JSXSpreadAttribute') {
91
- return;
92
- }
93
- return attr.name.name === 'defaultProps';
94
- });
95
- if (!defaultPropsAttr || defaultPropsAttr.type === 'JSXSpreadAttribute') {
96
- this.traverse(path);
97
- return;
98
- }
99
- if (!defaultPropsAttr.value ||
100
- defaultPropsAttr.value.type !== 'JSXExpressionContainer') {
101
- this.traverse(path);
102
- return;
103
- }
104
- const { expression } = defaultPropsAttr.value;
105
- if (expression.type === 'JSXEmptyExpression') {
106
- this.traverse(path);
107
- return;
108
- }
109
- if ((0, can_update_sequence_props_1.isStaticValue)(expression, {
110
- allowSpecialValues: true,
111
- })) {
112
- const value = (0, can_update_sequence_props_1.extractStaticValue)(expression, {
113
- allowSpecialValues: true,
114
- });
115
- if (value !== null &&
116
- typeof value === 'object' &&
117
- !Array.isArray(value)) {
118
- result = value;
119
- }
120
- }
121
- this.traverse(path);
122
- },
123
- });
124
- return result;
125
- };
126
- const computeCanUpdateDefaultPropsFromContent = (content, compositionId) => {
127
- try {
128
- const currentDefaultProps = extractDefaultPropsFromSource(content, compositionId);
129
- if (currentDefaultProps === null) {
130
- throw new Error(`Could not find or extract defaultProps for composition "${compositionId}"`);
131
- }
132
- return {
133
- canUpdate: true,
134
- currentDefaultProps,
135
- };
136
- }
137
- catch (err) {
138
- return {
139
- canUpdate: false,
140
- reason: err.message,
141
- };
142
- }
143
- };
144
- exports.computeCanUpdateDefaultPropsFromContent = computeCanUpdateDefaultPropsFromContent;
145
18
  const computeCanUpdateDefaultProps = async ({ compositionId, remotionRoot, entryPoint, }) => {
146
19
  try {
147
20
  const projectInfo = await (0, project_info_1.getProjectInfo)(remotionRoot, entryPoint);
@@ -150,7 +23,7 @@ const computeCanUpdateDefaultProps = async ({ compositionId, remotionRoot, entry
150
23
  }
151
24
  (0, exports.checkIfTypeScriptFile)(projectInfo.rootFile);
152
25
  const input = (0, node_fs_1.readFileSync)(projectInfo.rootFile, 'utf-8');
153
- const result = (0, exports.computeCanUpdateDefaultPropsFromContent)(input, compositionId);
26
+ const result = (0, studio_codemods_1.computeCanUpdateDefaultPropsFromContent)(input, compositionId);
154
27
  return {
155
28
  result,
156
29
  rootFile: projectInfo.rootFile,
@@ -22,7 +22,7 @@ export declare const getStaticJsxChildrenAttribute: (jsxElement: JSXOpeningEleme
22
22
  export declare const hasJsxChildrenAttribute: (jsxElement: JSXOpeningElement) => boolean;
23
23
  export declare const getStaticJsxTextContent: (jsxElement: JSXElement) => StaticJsxTextContent | null;
24
24
  export declare const findNodePathForJsxElement: (ast: File, target: JSXOpeningElement) => SequenceNodePath | null;
25
- export declare const lineColumnToNodePath: (ast: File, targetLine: number) => SequenceNodePath | null;
25
+ export declare const lineColumnToNodePath: (ast: File, targetLine: number, targetColumn?: number | undefined, fileContents?: string | undefined) => SequenceNodePath | null;
26
26
  export declare const computeSequencePropsStatusFromContent: ({ fileContents, nodePath, componentIdentity, keys, assetKeys, effects, videoConfigValues, }: {
27
27
  fileContents: string;
28
28
  nodePath: SequenceNodePath;
@@ -42,9 +42,10 @@ export declare const computeSequencePropsStatus: ({ fileName, nodePath, componen
42
42
  remotionRoot: string;
43
43
  videoConfigValues: VideoConfigValues | null;
44
44
  }) => CanUpdateSequencePropsResponseTrue;
45
- export declare const computeSequencePropsStatusFromFilenameByLine: ({ fileName, line, componentIdentity, keys, assetKeys, effects, remotionRoot, logLevel, videoConfigValues, }: {
45
+ export declare const computeSequencePropsStatusFromFilenameByLocation: ({ fileName, line, column, componentIdentity, keys, assetKeys, effects, remotionRoot, logLevel, videoConfigValues, }: {
46
46
  fileName: string;
47
47
  line: number;
48
+ column: number;
48
49
  componentIdentity: string | null;
49
50
  keys: string[];
50
51
  assetKeys?: string[] | undefined;
@@ -33,7 +33,7 @@ var __importStar = (this && this.__importStar) || (function () {
33
33
  };
34
34
  })();
35
35
  Object.defineProperty(exports, "__esModule", { value: true });
36
- exports.computeSequencePropsStatusFromFilenameByLine = exports.computeSequencePropsStatus = exports.computeSequencePropsStatusFromContent = exports.lineColumnToNodePath = exports.findNodePathForJsxElement = exports.getStaticJsxTextContent = exports.hasJsxChildrenAttribute = exports.getStaticJsxChildrenAttribute = exports.findJsxElementNodeAtNodePath = exports.findJsxElementAtNodePath = exports.findJsxElementPathAtNodePath = exports.getComputedStatus = exports.extractStaticValue = exports.isStaticValue = void 0;
36
+ exports.computeSequencePropsStatusFromFilenameByLocation = exports.computeSequencePropsStatus = exports.computeSequencePropsStatusFromContent = exports.lineColumnToNodePath = exports.findNodePathForJsxElement = exports.getStaticJsxTextContent = exports.hasJsxChildrenAttribute = exports.getStaticJsxChildrenAttribute = exports.findJsxElementNodeAtNodePath = exports.findJsxElementAtNodePath = exports.findJsxElementPathAtNodePath = exports.getComputedStatus = exports.extractStaticValue = exports.isStaticValue = void 0;
37
37
  const node_fs_1 = require("node:fs");
38
38
  const renderer_1 = require("@remotion/renderer");
39
39
  const studio_shared_1 = require("@remotion/studio-shared");
@@ -642,19 +642,51 @@ const findNodePathForJsxElement = (ast, target) => {
642
642
  return foundPath;
643
643
  };
644
644
  exports.findNodePathForJsxElement = findNodePathForJsxElement;
645
- const lineColumnToNodePath = (ast, targetLine) => {
646
- let foundPath = null;
645
+ const RECAST_TAB_WIDTH = 4;
646
+ const sourceColumnToRecastColumn = ({ fileContents, line, column, }) => {
647
+ const sourceLine = fileContents.split('\n')[line - 1];
648
+ if (sourceLine === undefined) {
649
+ return column;
650
+ }
651
+ let recastColumn = 0;
652
+ for (let index = 0; index < column; index++) {
653
+ if (sourceLine[index] === '\t') {
654
+ recastColumn += RECAST_TAB_WIDTH - (recastColumn % RECAST_TAB_WIDTH);
655
+ }
656
+ else {
657
+ recastColumn++;
658
+ }
659
+ }
660
+ return recastColumn;
661
+ };
662
+ const lineColumnToNodePath = (ast, targetLine, targetColumn, fileContents) => {
663
+ var _a;
664
+ const lineMatches = [];
665
+ const exactMatches = [];
666
+ const recastTargetColumn = targetColumn === undefined || fileContents === undefined
667
+ ? targetColumn
668
+ : sourceColumnToRecastColumn({
669
+ fileContents,
670
+ line: targetLine,
671
+ column: targetColumn,
672
+ });
647
673
  recast.types.visit(ast, {
648
674
  visitJSXOpeningElement(p) {
649
675
  const { node } = p;
650
676
  if (node.loc && node.loc.start.line === targetLine) {
651
- foundPath = getNodePathForRecastPath(p, ast);
652
- return false;
677
+ const nodePath = getNodePathForRecastPath(p, ast);
678
+ lineMatches.push(nodePath);
679
+ if (node.loc.start.column === recastTargetColumn) {
680
+ exactMatches.push(nodePath);
681
+ }
653
682
  }
654
683
  return this.traverse(p);
655
684
  },
656
685
  });
657
- return foundPath;
686
+ if (exactMatches.length === 1) {
687
+ return exactMatches[0];
688
+ }
689
+ return (_a = lineMatches.at(-1)) !== null && _a !== void 0 ? _a : null;
658
690
  };
659
691
  exports.lineColumnToNodePath = lineColumnToNodePath;
660
692
  const PIXEL_VALUE_REGEX = /^-?\d+(\.\d+)?px$/;
@@ -944,7 +976,7 @@ const computeSequencePropsStatus = ({ fileName, nodePath, componentIdentity, key
944
976
  });
945
977
  };
946
978
  exports.computeSequencePropsStatus = computeSequencePropsStatus;
947
- const computeSequencePropsStatusFromFilenameByLine = ({ fileName, line, componentIdentity, keys, assetKeys = [], effects, remotionRoot, logLevel, videoConfigValues, }) => {
979
+ const computeSequencePropsStatusFromFilenameByLocation = ({ fileName, line, column, componentIdentity, keys, assetKeys = [], effects, remotionRoot, logLevel, videoConfigValues, }) => {
948
980
  try {
949
981
  const { absolutePath } = (0, resolve_file_inside_project_1.resolveFileInsideProject)({
950
982
  remotionRoot,
@@ -953,7 +985,7 @@ const computeSequencePropsStatusFromFilenameByLine = ({ fileName, line, componen
953
985
  });
954
986
  const fileContents = (0, node_fs_1.readFileSync)(absolutePath, 'utf-8');
955
987
  const ast = (0, parse_ast_1.parseAst)(fileContents);
956
- const resolvedNodePath = (0, exports.lineColumnToNodePath)(ast, line);
988
+ const resolvedNodePath = (0, exports.lineColumnToNodePath)(ast, line, column, fileContents);
957
989
  if (!resolvedNodePath) {
958
990
  return {
959
991
  status: {
@@ -985,6 +1017,16 @@ const computeSequencePropsStatusFromFilenameByLine = ({ fileName, line, componen
985
1017
  };
986
1018
  }
987
1019
  catch (err) {
1020
+ if (err instanceof jsx_component_identity_1.JsxElementIdentityMismatchError ||
1021
+ err instanceof jsx_element_not_found_at_location_error_1.JsxElementNotFoundAtLocationError) {
1022
+ return {
1023
+ status: {
1024
+ canUpdate: false,
1025
+ reason: 'not-found',
1026
+ },
1027
+ success: false,
1028
+ };
1029
+ }
988
1030
  renderer_1.RenderInternals.Log.error({ indent: false, logLevel }, err);
989
1031
  return {
990
1032
  status: {
@@ -995,4 +1037,4 @@ const computeSequencePropsStatusFromFilenameByLine = ({ fileName, line, componen
995
1037
  };
996
1038
  }
997
1039
  };
998
- exports.computeSequencePropsStatusFromFilenameByLine = computeSequencePropsStatusFromFilenameByLine;
1040
+ exports.computeSequencePropsStatusFromFilenameByLocation = computeSequencePropsStatusFromFilenameByLocation;
@@ -6,8 +6,8 @@ Object.defineProperty(exports, "__esModule", { value: true });
6
6
  exports.insertElementHandler = void 0;
7
7
  const node_fs_1 = require("node:fs");
8
8
  const node_path_1 = __importDefault(require("node:path"));
9
- const drag_and_drop_1 = require("@remotion/drag-and-drop");
10
9
  const renderer_1 = require("@remotion/renderer");
10
+ const studio_protocol_1 = require("@remotion/studio-protocol");
11
11
  const file_watcher_1 = require("../../file-watcher");
12
12
  const resolve_composition_component_1 = require("../../helpers/resolve-composition-component");
13
13
  const format_log_file_location_1 = require("../format-log-file-location");
@@ -56,7 +56,7 @@ const validateDimensions = (dimensions) => {
56
56
  }
57
57
  };
58
58
  const validateElement = (element) => {
59
- if (drag_and_drop_1.DragAndDropInternals.makeElementFileNameFromSlug(element.slug) === null) {
59
+ if (studio_protocol_1.StudioProtocolInternals.makeElementFileNameFromSlug(element.slug) === null) {
60
60
  throw new Error('Element slug must produce a safe lowercase .tsx file name');
61
61
  }
62
62
  if (typeof element.sourceCode !== 'string' ||
@@ -64,7 +64,7 @@ const validateElement = (element) => {
64
64
  element.sourceCode.length > 200000) {
65
65
  throw new Error('Unsupported Element source code');
66
66
  }
67
- if (drag_and_drop_1.DragAndDropInternals.getElementComponentNameFromSourceCode(element.sourceCode) === null) {
67
+ if (studio_protocol_1.StudioProtocolInternals.getElementComponentNameFromSourceCode(element.sourceCode) === null) {
68
68
  throw new Error('Element source must export exactly one named component');
69
69
  }
70
70
  validateDimensions(element.dimensions);
@@ -77,7 +77,7 @@ const insertElementHandler = ({ input: { compositionFile, compositionId, element
77
77
  (!Number.isInteger(from) || !Number.isFinite(from) || from < 0)) {
78
78
  throw new Error('from must be a non-negative integer');
79
79
  }
80
- const componentName = drag_and_drop_1.DragAndDropInternals.getElementComponentNameFromSourceCode(element.sourceCode);
80
+ const componentName = studio_protocol_1.StudioProtocolInternals.getElementComponentNameFromSourceCode(element.sourceCode);
81
81
  if (componentName === null) {
82
82
  throw new Error('Element source must export exactly one named component');
83
83
  }
@@ -90,7 +90,7 @@ const insertElementHandler = ({ input: { compositionFile, compositionId, element
90
90
  if (!location.canAddSequence) {
91
91
  throw new Error('Cannot insert Element into this composition component');
92
92
  }
93
- const derivedElementFileName = drag_and_drop_1.DragAndDropInternals.makeElementFileNameFromSlug(element.slug);
93
+ const derivedElementFileName = studio_protocol_1.StudioProtocolInternals.makeElementFileNameFromSlug(element.slug);
94
94
  if (derivedElementFileName === null) {
95
95
  throw new Error('Element slug must produce a safe lowercase .tsx file name');
96
96
  }
@@ -5,8 +5,8 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
5
5
  Object.defineProperty(exports, "__esModule", { value: true });
6
6
  exports.insertJsxElementHandler = void 0;
7
7
  const node_path_1 = __importDefault(require("node:path"));
8
- const drag_and_drop_1 = require("@remotion/drag-and-drop");
9
8
  const renderer_1 = require("@remotion/renderer");
9
+ const studio_protocol_1 = require("@remotion/studio-protocol");
10
10
  const studio_shared_1 = require("@remotion/studio-shared");
11
11
  const file_watcher_1 = require("../../file-watcher");
12
12
  const resolve_composition_component_1 = require("../../helpers/resolve-composition-component");
@@ -79,16 +79,16 @@ const validateElement = (element, remotionRoot) => {
79
79
  return;
80
80
  }
81
81
  if (element.type === 'component') {
82
- if (!drag_and_drop_1.DragAndDropInternals.isComponentIdentifier(element.componentName)) {
82
+ if (!studio_protocol_1.StudioProtocolInternals.isComponentIdentifier(element.componentName)) {
83
83
  throw new Error('Unsupported component name');
84
84
  }
85
- if (!drag_and_drop_1.DragAndDropInternals.isComponentIdentifier(element.importName)) {
85
+ if (!studio_protocol_1.StudioProtocolInternals.isComponentIdentifier(element.importName)) {
86
86
  throw new Error('Unsupported component import name');
87
87
  }
88
- if (!drag_and_drop_1.DragAndDropInternals.isComponentImportPath(element.importPath)) {
88
+ if (!studio_protocol_1.StudioProtocolInternals.isComponentImportPath(element.importPath)) {
89
89
  throw new Error('Unsupported component import path');
90
90
  }
91
- if (!drag_and_drop_1.DragAndDropInternals.areComponentProps(element.props)) {
91
+ if (!studio_protocol_1.StudioProtocolInternals.areComponentProps(element.props)) {
92
92
  throw new Error('Unsupported component props');
93
93
  }
94
94
  return;
@@ -85,9 +85,10 @@ const getSequencePropsStatus = ({ fileName, line, column, preferredNodePath, com
85
85
  };
86
86
  }
87
87
  }
88
- const status = (0, can_update_sequence_props_1.computeSequencePropsStatusFromFilenameByLine)({
88
+ const status = (0, can_update_sequence_props_1.computeSequencePropsStatusFromFilenameByLocation)({
89
89
  fileName,
90
90
  line,
91
+ column,
91
92
  componentIdentity,
92
93
  keys,
93
94
  assetKeys,
@@ -0,0 +1,11 @@
1
+ import type { IncomingMessage, ServerResponse } from 'node:http';
2
+ import type { GitSource } from '@remotion/studio-shared';
3
+ import type { LiveEventsServer } from '../live-events';
4
+ export declare const ELEMENT_INSTALL_TARGET_RESPONSE_WAIT = 250;
5
+ export declare const handleStudioProtocolDiscovery: ({ gitSource, liveEventsServer, remotionRoot, request, response, }: {
6
+ readonly gitSource: GitSource | null;
7
+ readonly liveEventsServer: LiveEventsServer;
8
+ readonly remotionRoot: string;
9
+ readonly request: IncomingMessage;
10
+ readonly response: ServerResponse<IncomingMessage>;
11
+ }) => Promise<void>;