@remotion/studio-server 4.0.500 → 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.
- package/dist/codemods/update-inline-caption-patches.d.ts +1 -0
- package/dist/codemods/update-inline-caption-patches.js +5 -0
- package/dist/codemods/update-sequence-props/update-sequence-props.d.ts +2 -35
- package/dist/codemods/update-sequence-props/update-sequence-props.js +7 -718
- package/dist/helpers/css-shorthand-properties.d.ts +9 -3
- package/dist/helpers/css-shorthand-properties.js +16 -2
- package/dist/helpers/parse-border-radius-shorthand.d.ts +7 -0
- package/dist/helpers/parse-border-radius-shorthand.js +53 -0
- package/dist/helpers/resolve-composition-component.js +80 -52
- package/dist/preview-server/element-install-state.d.ts +16 -0
- package/dist/preview-server/element-install-state.js +43 -1
- package/dist/preview-server/handler.js +1 -1
- package/dist/preview-server/parse-body.d.ts +6 -1
- package/dist/preview-server/parse-body.js +60 -9
- package/dist/preview-server/routes/can-update-default-props.d.ts +1 -1
- package/dist/preview-server/routes/can-update-default-props.js +5 -132
- package/dist/preview-server/routes/can-update-sequence-props.d.ts +3 -2
- package/dist/preview-server/routes/can-update-sequence-props.js +130 -12
- package/dist/preview-server/routes/find-in-file.d.ts +1 -9
- package/dist/preview-server/routes/find-in-file.js +4 -17
- package/dist/preview-server/routes/insert-element.js +40 -20
- package/dist/preview-server/routes/insert-jsx-element.js +5 -5
- package/dist/preview-server/routes/save-sequence-props.js +73 -8
- package/dist/preview-server/sequence-props-watchers.js +2 -1
- package/dist/preview-server/studio-protocol/handle-discovery.d.ts +11 -0
- package/dist/preview-server/studio-protocol/handle-discovery.js +99 -0
- package/dist/preview-server/studio-protocol/handle-install.d.ts +10 -0
- package/dist/preview-server/studio-protocol/handle-install.js +139 -0
- package/dist/preview-server/studio-protocol/origin-policy.d.ts +10 -0
- package/dist/preview-server/studio-protocol/origin-policy.js +40 -0
- package/dist/preview-server/studio-protocol/protocol-response.d.ts +7 -0
- package/dist/preview-server/studio-protocol/protocol-response.js +13 -0
- package/dist/routes.js +14 -154
- package/package.json +9 -7
|
@@ -3,20 +3,26 @@ export type CssShorthandProperty = {
|
|
|
3
3
|
readonly parentKey: string;
|
|
4
4
|
readonly shorthand: string;
|
|
5
5
|
readonly longhands: readonly string[];
|
|
6
|
-
readonly parse: (value:
|
|
6
|
+
readonly parse: (value: unknown) => ParsedCssShorthand | null;
|
|
7
7
|
readonly isUnsupportedProperty: (propertyName: string) => boolean;
|
|
8
8
|
};
|
|
9
9
|
export declare const cssShorthandProperties: readonly [{
|
|
10
10
|
readonly parentKey: "style";
|
|
11
11
|
readonly shorthand: "background";
|
|
12
12
|
readonly longhands: readonly ["backgroundColor", "backgroundImage", "backgroundPosition", "backgroundSize", "backgroundRepeat", "backgroundOrigin", "backgroundClip", "backgroundAttachment"];
|
|
13
|
-
readonly parse: (value:
|
|
13
|
+
readonly parse: (value: unknown) => import("./parse-background-shorthand").ParsedBackgroundShorthand | null;
|
|
14
14
|
readonly isUnsupportedProperty: () => false;
|
|
15
15
|
}, {
|
|
16
16
|
readonly parentKey: "style";
|
|
17
17
|
readonly shorthand: "border";
|
|
18
18
|
readonly longhands: readonly ["borderWidth", "borderStyle", "borderColor"];
|
|
19
|
-
readonly parse: (value:
|
|
19
|
+
readonly parse: (value: unknown) => import("./parse-border-shorthand").ParsedBorderShorthand | null;
|
|
20
|
+
readonly isUnsupportedProperty: (propertyName: string) => boolean;
|
|
21
|
+
}, {
|
|
22
|
+
readonly parentKey: "style";
|
|
23
|
+
readonly shorthand: "borderRadius";
|
|
24
|
+
readonly longhands: readonly ["borderTopLeftRadius", "borderTopRightRadius", "borderBottomRightRadius", "borderBottomLeftRadius"];
|
|
25
|
+
readonly parse: (value: unknown) => import("./parse-border-radius-shorthand").ParsedBorderRadiusShorthand | null;
|
|
20
26
|
readonly isUnsupportedProperty: (propertyName: string) => boolean;
|
|
21
27
|
}];
|
|
22
28
|
export declare const getCssShorthandForLonghand: ({ parentKey, longhand, }: {
|
|
@@ -2,15 +2,28 @@
|
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.getCssShorthandsForUpdates = exports.getCssShorthandForLonghand = exports.cssShorthandProperties = void 0;
|
|
4
4
|
const parse_background_shorthand_1 = require("./parse-background-shorthand");
|
|
5
|
+
const parse_border_radius_shorthand_1 = require("./parse-border-radius-shorthand");
|
|
5
6
|
const parse_border_shorthand_1 = require("./parse-border-shorthand");
|
|
6
7
|
const borderSidePropertyRegex = /^border(?:Top|Right|Bottom|Left)(?:Width|Style|Color)?$/;
|
|
7
8
|
const borderShorthand = {
|
|
8
9
|
parentKey: 'style',
|
|
9
10
|
shorthand: 'border',
|
|
10
11
|
longhands: ['borderWidth', 'borderStyle', 'borderColor'],
|
|
11
|
-
parse: parse_border_shorthand_1.parseBorderShorthand,
|
|
12
|
+
parse: (value) => typeof value === 'string' ? (0, parse_border_shorthand_1.parseBorderShorthand)(value) : null,
|
|
12
13
|
isUnsupportedProperty: (propertyName) => borderSidePropertyRegex.test(propertyName),
|
|
13
14
|
};
|
|
15
|
+
const borderRadiusShorthand = {
|
|
16
|
+
parentKey: 'style',
|
|
17
|
+
shorthand: 'borderRadius',
|
|
18
|
+
longhands: [
|
|
19
|
+
'borderTopLeftRadius',
|
|
20
|
+
'borderTopRightRadius',
|
|
21
|
+
'borderBottomRightRadius',
|
|
22
|
+
'borderBottomLeftRadius',
|
|
23
|
+
],
|
|
24
|
+
parse: parse_border_radius_shorthand_1.parseBorderRadiusShorthand,
|
|
25
|
+
isUnsupportedProperty: (propertyName) => /^border(?:StartStart|StartEnd|EndStart|EndEnd)Radius$/.test(propertyName),
|
|
26
|
+
};
|
|
14
27
|
const backgroundShorthand = {
|
|
15
28
|
parentKey: 'style',
|
|
16
29
|
shorthand: 'background',
|
|
@@ -24,12 +37,13 @@ const backgroundShorthand = {
|
|
|
24
37
|
'backgroundClip',
|
|
25
38
|
'backgroundAttachment',
|
|
26
39
|
],
|
|
27
|
-
parse: parse_background_shorthand_1.parseBackgroundShorthand,
|
|
40
|
+
parse: (value) => typeof value === 'string' ? (0, parse_background_shorthand_1.parseBackgroundShorthand)(value) : null,
|
|
28
41
|
isUnsupportedProperty: () => false,
|
|
29
42
|
};
|
|
30
43
|
exports.cssShorthandProperties = [
|
|
31
44
|
backgroundShorthand,
|
|
32
45
|
borderShorthand,
|
|
46
|
+
borderRadiusShorthand,
|
|
33
47
|
];
|
|
34
48
|
const getCssShorthandForLonghand = ({ parentKey, longhand, }) => {
|
|
35
49
|
var _a;
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
export type ParsedBorderRadiusShorthand = {
|
|
2
|
+
borderTopLeftRadius: number;
|
|
3
|
+
borderTopRightRadius: number;
|
|
4
|
+
borderBottomRightRadius: number;
|
|
5
|
+
borderBottomLeftRadius: number;
|
|
6
|
+
};
|
|
7
|
+
export declare const parseBorderRadiusShorthand: (value: unknown) => ParsedBorderRadiusShorthand | null;
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.parseBorderRadiusShorthand = void 0;
|
|
4
|
+
const parsePixelRadius = (value) => {
|
|
5
|
+
if (value === '0') {
|
|
6
|
+
return 0;
|
|
7
|
+
}
|
|
8
|
+
const match = value.match(/^(\d+(?:\.\d+)?|\.\d+)px$/i);
|
|
9
|
+
return match ? Number(match[1]) : null;
|
|
10
|
+
};
|
|
11
|
+
const expandBorderRadius = (values) => {
|
|
12
|
+
if (values.length === 1) {
|
|
13
|
+
return [values[0], values[0], values[0], values[0]];
|
|
14
|
+
}
|
|
15
|
+
if (values.length === 2) {
|
|
16
|
+
return [values[0], values[1], values[0], values[1]];
|
|
17
|
+
}
|
|
18
|
+
if (values.length === 3) {
|
|
19
|
+
return [values[0], values[1], values[2], values[1]];
|
|
20
|
+
}
|
|
21
|
+
return [values[0], values[1], values[2], values[3]];
|
|
22
|
+
};
|
|
23
|
+
const parseBorderRadiusShorthand = (value) => {
|
|
24
|
+
let values;
|
|
25
|
+
if (typeof value === 'number') {
|
|
26
|
+
if (!Number.isFinite(value) || value < 0) {
|
|
27
|
+
return null;
|
|
28
|
+
}
|
|
29
|
+
values = [value];
|
|
30
|
+
}
|
|
31
|
+
else if (typeof value === 'string') {
|
|
32
|
+
const tokens = value.trim().split(/\s+/);
|
|
33
|
+
if (tokens.length < 1 || tokens.length > 4) {
|
|
34
|
+
return null;
|
|
35
|
+
}
|
|
36
|
+
const parsed = tokens.map(parsePixelRadius);
|
|
37
|
+
if (parsed.some((radius) => radius === null)) {
|
|
38
|
+
return null;
|
|
39
|
+
}
|
|
40
|
+
values = parsed;
|
|
41
|
+
}
|
|
42
|
+
else {
|
|
43
|
+
return null;
|
|
44
|
+
}
|
|
45
|
+
const [topLeft, topRight, bottomRight, bottomLeft] = expandBorderRadius(values);
|
|
46
|
+
return {
|
|
47
|
+
borderTopLeftRadius: topLeft,
|
|
48
|
+
borderTopRightRadius: topRight,
|
|
49
|
+
borderBottomRightRadius: bottomRight,
|
|
50
|
+
borderBottomLeftRadius: bottomLeft,
|
|
51
|
+
};
|
|
52
|
+
};
|
|
53
|
+
exports.parseBorderRadiusShorthand = parseBorderRadiusShorthand;
|
|
@@ -39,6 +39,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
39
39
|
exports.insertJsxElementIntoComposition = exports.resolveCompositionComponent = exports.resolveCompositionComponentWithFile = void 0;
|
|
40
40
|
const node_fs_1 = __importDefault(require("node:fs"));
|
|
41
41
|
const node_path_1 = __importDefault(require("node:path"));
|
|
42
|
+
const studio_codemods_1 = require("@remotion/studio-codemods");
|
|
42
43
|
const studio_shared_1 = require("@remotion/studio-shared");
|
|
43
44
|
const recast = __importStar(require("recast"));
|
|
44
45
|
const no_react_1 = require("remotion/no-react");
|
|
@@ -247,9 +248,6 @@ const findReExportTargets = ({ ast, exportName, }) => {
|
|
|
247
248
|
visitExportNamedDeclaration(astPath) {
|
|
248
249
|
var _a;
|
|
249
250
|
const node = astPath.node;
|
|
250
|
-
if (typeof ((_a = node.source) === null || _a === void 0 ? void 0 : _a.value) !== 'string') {
|
|
251
|
-
return false;
|
|
252
|
-
}
|
|
253
251
|
for (const specifier of node.specifiers) {
|
|
254
252
|
if (specifier.type !== 'ExportSpecifier') {
|
|
255
253
|
continue;
|
|
@@ -262,6 +260,18 @@ const findReExportTargets = ({ ast, exportName, }) => {
|
|
|
262
260
|
if (!localName) {
|
|
263
261
|
continue;
|
|
264
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
|
+
}
|
|
265
275
|
targets.push({
|
|
266
276
|
importPath: node.source.value,
|
|
267
277
|
exportName: localName === 'default' ? 'default' : localName,
|
|
@@ -313,6 +323,9 @@ const locationFromNode = (node) => {
|
|
|
313
323
|
};
|
|
314
324
|
const findLocalSymbolLocation = ({ ast, name, }) => {
|
|
315
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.
|
|
316
329
|
recast.types.visit(ast, {
|
|
317
330
|
visitVariableDeclarator(astPath) {
|
|
318
331
|
if (location) {
|
|
@@ -320,7 +333,7 @@ const findLocalSymbolLocation = ({ ast, name, }) => {
|
|
|
320
333
|
}
|
|
321
334
|
const { node } = astPath;
|
|
322
335
|
if (node.id.type === 'Identifier' && node.id.name === name) {
|
|
323
|
-
location = locationFromNode(node);
|
|
336
|
+
location = locationFromNode(node.id);
|
|
324
337
|
return false;
|
|
325
338
|
}
|
|
326
339
|
this.traverse(astPath);
|
|
@@ -333,7 +346,7 @@ const findLocalSymbolLocation = ({ ast, name, }) => {
|
|
|
333
346
|
}
|
|
334
347
|
const { node } = astPath;
|
|
335
348
|
if (((_a = node.id) === null || _a === void 0 ? void 0 : _a.name) === name) {
|
|
336
|
-
location = locationFromNode(node);
|
|
349
|
+
location = locationFromNode(node.id);
|
|
337
350
|
return false;
|
|
338
351
|
}
|
|
339
352
|
this.traverse(astPath);
|
|
@@ -346,7 +359,7 @@ const findLocalSymbolLocation = ({ ast, name, }) => {
|
|
|
346
359
|
}
|
|
347
360
|
const { node } = astPath;
|
|
348
361
|
if (((_a = node.id) === null || _a === void 0 ? void 0 : _a.name) === name) {
|
|
349
|
-
location = locationFromNode(node);
|
|
362
|
+
location = locationFromNode(node.id);
|
|
350
363
|
return false;
|
|
351
364
|
}
|
|
352
365
|
this.traverse(astPath);
|
|
@@ -1427,56 +1440,71 @@ const insertJsxElementIntoComposition = async ({ remotionRoot, compositionFile,
|
|
|
1427
1440
|
remotionRoot,
|
|
1428
1441
|
fileName: location.fileName,
|
|
1429
1442
|
});
|
|
1430
|
-
|
|
1431
|
-
|
|
1432
|
-
|
|
1433
|
-
|
|
1434
|
-
|
|
1435
|
-
|
|
1436
|
-
? {
|
|
1437
|
-
dimensions: { width: element.width, height: element.height },
|
|
1438
|
-
durationInFrames: element.durationInFrames,
|
|
1439
|
-
name: element.compositionId,
|
|
1443
|
+
let finalFile;
|
|
1444
|
+
let logLine;
|
|
1445
|
+
if (element.type === 'solid' && from === null && wrapInSequence === null) {
|
|
1446
|
+
const inserted = (0, studio_codemods_1.insertSolidIntoSource)({
|
|
1447
|
+
exportName: location.exportName,
|
|
1448
|
+
height: element.height,
|
|
1440
1449
|
position: element.position,
|
|
1441
|
-
|
|
1450
|
+
source: input,
|
|
1451
|
+
width: element.width,
|
|
1452
|
+
});
|
|
1453
|
+
finalFile = inserted.output;
|
|
1454
|
+
logLine = inserted.line;
|
|
1455
|
+
}
|
|
1456
|
+
else {
|
|
1457
|
+
const ast = (0, parse_ast_1.parseAst)(input);
|
|
1458
|
+
if (element.type === 'composition' &&
|
|
1459
|
+
element.compositionId === compositionId) {
|
|
1460
|
+
throw new Error('Cannot insert a composition into itself');
|
|
1442
1461
|
}
|
|
1443
|
-
|
|
1444
|
-
|
|
1445
|
-
|
|
1446
|
-
|
|
1447
|
-
|
|
1448
|
-
: {
|
|
1449
|
-
dimensions: null,
|
|
1450
|
-
durationInFrames: null,
|
|
1451
|
-
name: null,
|
|
1462
|
+
const sequenceWrapper = element.type === 'composition'
|
|
1463
|
+
? {
|
|
1464
|
+
dimensions: { width: element.width, height: element.height },
|
|
1465
|
+
durationInFrames: element.durationInFrames,
|
|
1466
|
+
name: element.compositionId,
|
|
1452
1467
|
position: element.position,
|
|
1453
1468
|
from,
|
|
1454
|
-
}
|
|
1455
|
-
|
|
1456
|
-
|
|
1457
|
-
|
|
1458
|
-
|
|
1459
|
-
|
|
1460
|
-
|
|
1461
|
-
|
|
1462
|
-
|
|
1463
|
-
|
|
1464
|
-
|
|
1465
|
-
|
|
1466
|
-
|
|
1467
|
-
|
|
1468
|
-
|
|
1469
|
-
|
|
1470
|
-
|
|
1471
|
-
|
|
1472
|
-
|
|
1473
|
-
|
|
1474
|
-
|
|
1475
|
-
|
|
1476
|
-
|
|
1477
|
-
|
|
1478
|
-
|
|
1479
|
-
|
|
1469
|
+
}
|
|
1470
|
+
: from === null ||
|
|
1471
|
+
element.type === 'asset' ||
|
|
1472
|
+
element.type === 'svg' ||
|
|
1473
|
+
element.type === 'component'
|
|
1474
|
+
? wrapInSequence
|
|
1475
|
+
: {
|
|
1476
|
+
dimensions: null,
|
|
1477
|
+
durationInFrames: null,
|
|
1478
|
+
name: null,
|
|
1479
|
+
position: element.position,
|
|
1480
|
+
from,
|
|
1481
|
+
};
|
|
1482
|
+
const elementToInsert = await createInsertableJsxElement({
|
|
1483
|
+
addPositionStyleToComponent: sequenceWrapper === null,
|
|
1484
|
+
ast,
|
|
1485
|
+
destinationFileName: location.fileName,
|
|
1486
|
+
element,
|
|
1487
|
+
from,
|
|
1488
|
+
remotionRoot,
|
|
1489
|
+
});
|
|
1490
|
+
const finalElementToInsert = sequenceWrapper
|
|
1491
|
+
? createSequenceWrappedElement({
|
|
1492
|
+
child: elementToInsert,
|
|
1493
|
+
dimensions: sequenceWrapper.dimensions,
|
|
1494
|
+
durationInFrames: (_a = sequenceWrapper.durationInFrames) !== null && _a !== void 0 ? _a : null,
|
|
1495
|
+
from: sequenceWrapper.from,
|
|
1496
|
+
name: sequenceWrapper.name,
|
|
1497
|
+
position: sequenceWrapper.position,
|
|
1498
|
+
sequenceLocalName: ensureSequenceImport(ast),
|
|
1499
|
+
})
|
|
1500
|
+
: elementToInsert;
|
|
1501
|
+
logLine = addElementToComponentRoot({
|
|
1502
|
+
ast,
|
|
1503
|
+
exportName: location.exportName,
|
|
1504
|
+
element: finalElementToInsert,
|
|
1505
|
+
});
|
|
1506
|
+
finalFile = (0, parse_ast_1.serializeAst)(ast);
|
|
1507
|
+
}
|
|
1480
1508
|
const { output, formatted } = await (0, format_file_content_1.formatFileContent)({
|
|
1481
1509
|
input: finalFile,
|
|
1482
1510
|
prettierConfigOverride,
|
|
@@ -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
|
|
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
|
-
|
|
5
|
-
|
|
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
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
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;
|