@remotion/studio-server 4.0.470 → 4.0.471

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 (28) hide show
  1. package/dist/codemods/add-effect.d.ts +15 -0
  2. package/dist/codemods/add-effect.js +231 -0
  3. package/dist/codemods/reorder-effect.d.ts +13 -0
  4. package/dist/codemods/reorder-effect.js +61 -0
  5. package/dist/codemods/update-keyframes/update-keyframes.d.ts +4 -0
  6. package/dist/codemods/update-keyframes/update-keyframes.js +25 -10
  7. package/dist/helpers/open-in-editor.d.ts +2 -2
  8. package/dist/helpers/open-in-editor.js +35 -2
  9. package/dist/helpers/resolve-composition-component.d.ts +15 -0
  10. package/dist/helpers/resolve-composition-component.js +269 -31
  11. package/dist/preview-server/api-routes.js +8 -4
  12. package/dist/preview-server/routes/add-effect-keyframe.js +2 -2
  13. package/dist/preview-server/routes/add-effect.d.ts +3 -0
  14. package/dist/preview-server/routes/add-effect.js +68 -0
  15. package/dist/preview-server/routes/add-sequence-keyframe.js +6 -3
  16. package/dist/preview-server/routes/can-update-sequence-props.d.ts +1 -0
  17. package/dist/preview-server/routes/can-update-sequence-props.js +15 -1
  18. package/dist/preview-server/routes/delete-keyframes.d.ts +13 -0
  19. package/dist/preview-server/routes/delete-keyframes.js +263 -0
  20. package/dist/preview-server/routes/insert-jsx-element.d.ts +3 -0
  21. package/dist/preview-server/routes/insert-jsx-element.js +79 -0
  22. package/dist/preview-server/routes/reorder-effect.d.ts +3 -0
  23. package/dist/preview-server/routes/reorder-effect.js +67 -0
  24. package/dist/preview-server/routes/subscribe-to-sequence-props.js +2 -1
  25. package/dist/preview-server/sequence-props-watchers.d.ts +2 -1
  26. package/dist/preview-server/sequence-props-watchers.js +22 -2
  27. package/dist/preview-server/undo-stack.d.ts +9 -1
  28. package/package.json +6 -6
@@ -36,10 +36,11 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
36
36
  return (mod && mod.__esModule) ? mod : { "default": mod };
37
37
  };
38
38
  Object.defineProperty(exports, "__esModule", { value: true });
39
- exports.resolveCompositionComponent = void 0;
39
+ exports.insertJsxElementIntoComposition = exports.resolveCompositionComponent = void 0;
40
40
  const node_fs_1 = __importDefault(require("node:fs"));
41
41
  const node_path_1 = __importDefault(require("node:path"));
42
42
  const recast = __importStar(require("recast"));
43
+ const format_file_content_1 = require("../codemods/format-file-content");
43
44
  const parse_ast_1 = require("../codemods/parse-ast");
44
45
  const allowedFileExtensions = new Set(['.tsx', '.ts', '.jsx', '.js']);
45
46
  const extensionsToProbe = ['.tsx', '.ts', '.jsx', '.js'];
@@ -503,6 +504,205 @@ const getComponentRootNode = (declaration) => {
503
504
  const createSequenceElement = () => {
504
505
  return recast.types.builders.jsxElement(recast.types.builders.jsxOpeningElement(recast.types.builders.jsxIdentifier('Sequence'), []), recast.types.builders.jsxClosingElement(recast.types.builders.jsxIdentifier('Sequence')), []);
505
506
  };
507
+ const createNumberAttribute = (name, value) => {
508
+ return recast.types.builders.jsxAttribute(recast.types.builders.jsxIdentifier(name), recast.types.builders.jsxExpressionContainer(recast.types.builders.numericLiteral(value)));
509
+ };
510
+ const createSolidElement = ({ localName, width, height, }) => {
511
+ return recast.types.builders.jsxElement(recast.types.builders.jsxOpeningElement(recast.types.builders.jsxIdentifier(localName), [
512
+ createNumberAttribute('width', width),
513
+ createNumberAttribute('height', height),
514
+ recast.types.builders.jsxAttribute(recast.types.builders.jsxIdentifier('style'), recast.types.builders.jsxExpressionContainer(recast.types.builders.objectExpression([
515
+ recast.types.builders.objectProperty(recast.types.builders.identifier('position'), recast.types.builders.stringLiteral('absolute')),
516
+ ]))),
517
+ ], true), null, []);
518
+ };
519
+ const createFragmentWithElement = (element) => {
520
+ return recast.types.builders.jsxFragment(recast.types.builders.jsxOpeningFragment(), recast.types.builders.jsxClosingFragment(), [element]);
521
+ };
522
+ const replaceNullReturnInFunctionLike = ({ fn, element, }) => {
523
+ var _a, _b;
524
+ var _c, _d;
525
+ if (fn.type === 'ArrowFunctionExpression' && fn.body.type === 'NullLiteral') {
526
+ fn.body = createFragmentWithElement(element);
527
+ return (_c = (_a = fn.loc) === null || _a === void 0 ? void 0 : _a.start.line) !== null && _c !== void 0 ? _c : 1;
528
+ }
529
+ if (fn.body.type !== 'BlockStatement') {
530
+ return null;
531
+ }
532
+ const returnStatement = getTopLevelReturnStatement(fn.body.body);
533
+ if (!(returnStatement === null || returnStatement === void 0 ? void 0 : returnStatement.argument) ||
534
+ returnStatement.argument.type !== 'NullLiteral') {
535
+ return null;
536
+ }
537
+ returnStatement.argument = createFragmentWithElement(element);
538
+ return (_d = (_b = returnStatement.loc) === null || _b === void 0 ? void 0 : _b.start.line) !== null && _d !== void 0 ? _d : 1;
539
+ };
540
+ const addElementToNullComponentReturn = ({ declaration, element, }) => {
541
+ var _a;
542
+ var _b;
543
+ if (declaration.type === 'VariableDeclarator') {
544
+ if (!declaration.init ||
545
+ (declaration.init.type !== 'ArrowFunctionExpression' &&
546
+ declaration.init.type !== 'FunctionExpression')) {
547
+ return null;
548
+ }
549
+ return replaceNullReturnInFunctionLike({ fn: declaration.init, element });
550
+ }
551
+ if (declaration.type === 'ArrowFunctionExpression' ||
552
+ declaration.type === 'FunctionExpression' ||
553
+ declaration.type === 'FunctionDeclaration') {
554
+ return replaceNullReturnInFunctionLike({ fn: declaration, element });
555
+ }
556
+ if (declaration.type !== 'ClassDeclaration') {
557
+ return null;
558
+ }
559
+ const renderMethod = findRenderMethod(declaration);
560
+ if (!renderMethod) {
561
+ return null;
562
+ }
563
+ const returnStatement = getTopLevelReturnStatement(renderMethod.body.body);
564
+ if (!(returnStatement === null || returnStatement === void 0 ? void 0 : returnStatement.argument) ||
565
+ returnStatement.argument.type !== 'NullLiteral') {
566
+ return null;
567
+ }
568
+ returnStatement.argument = createFragmentWithElement(element);
569
+ return (_b = (_a = returnStatement.loc) === null || _a === void 0 ? void 0 : _a.start.line) !== null && _b !== void 0 ? _b : 1;
570
+ };
571
+ const getImportedName = (specifier) => {
572
+ if (specifier.imported.type === 'Identifier') {
573
+ return specifier.imported.name;
574
+ }
575
+ return specifier.imported.value;
576
+ };
577
+ const declarationBindsName = (declaration, name) => {
578
+ var _a;
579
+ if (declaration.type === 'FunctionDeclaration' ||
580
+ declaration.type === 'ClassDeclaration') {
581
+ return ((_a = declaration.id) === null || _a === void 0 ? void 0 : _a.name) === name;
582
+ }
583
+ return declaration.declarations.some((variableDeclaration) => {
584
+ return (variableDeclaration.id.type === 'Identifier' &&
585
+ variableDeclaration.id.name === name);
586
+ });
587
+ };
588
+ const hasTopLevelBinding = ({ ast, name }) => {
589
+ return ast.program.body.some((node) => {
590
+ var _a;
591
+ if (node.type === 'FunctionDeclaration' ||
592
+ node.type === 'ClassDeclaration' ||
593
+ node.type === 'VariableDeclaration') {
594
+ return declarationBindsName(node, name);
595
+ }
596
+ if (node.type === 'ExportNamedDeclaration' &&
597
+ node.declaration &&
598
+ (node.declaration.type === 'FunctionDeclaration' ||
599
+ node.declaration.type === 'ClassDeclaration' ||
600
+ node.declaration.type === 'VariableDeclaration')) {
601
+ return declarationBindsName(node.declaration, name);
602
+ }
603
+ if (node.type !== 'ImportDeclaration') {
604
+ return false;
605
+ }
606
+ return (_a = node.specifiers) === null || _a === void 0 ? void 0 : _a.some((specifier) => {
607
+ var _a;
608
+ return ((_a = specifier.local) === null || _a === void 0 ? void 0 : _a.name) === name;
609
+ });
610
+ });
611
+ };
612
+ const getAvailableSolidLocalName = (ast) => {
613
+ const candidates = ['Solid', 'RemotionSolid'];
614
+ const available = candidates.find((candidate) => {
615
+ return !hasTopLevelBinding({ ast, name: candidate });
616
+ });
617
+ if (!available) {
618
+ throw new Error('Cannot add <Solid> because Solid is already defined');
619
+ }
620
+ return available;
621
+ };
622
+ const insertImportDeclaration = (ast, importDeclaration) => {
623
+ const { body } = ast.program;
624
+ let lastImportIndex = -1;
625
+ for (let i = 0; i < body.length; i++) {
626
+ if (body[i].type === 'ImportDeclaration') {
627
+ lastImportIndex = i;
628
+ }
629
+ }
630
+ body.splice(lastImportIndex + 1, 0, importDeclaration);
631
+ };
632
+ const addSolidImport = ({ ast, localName, remotionImport, }) => {
633
+ var _a;
634
+ var _b;
635
+ const imported = recast.types.builders.identifier('Solid');
636
+ const local = localName === 'Solid' ? null : recast.types.builders.identifier(localName);
637
+ const specifier = recast.types.builders.importSpecifier(imported, local);
638
+ const canAddToExistingRemotionImport = remotionImport &&
639
+ !((_a = remotionImport.specifiers) === null || _a === void 0 ? void 0 : _a.some((importSpecifier) => importSpecifier.type === 'ImportNamespaceSpecifier'));
640
+ if (canAddToExistingRemotionImport) {
641
+ remotionImport.specifiers = [
642
+ ...((_b = remotionImport.specifiers) !== null && _b !== void 0 ? _b : []),
643
+ specifier,
644
+ ];
645
+ return;
646
+ }
647
+ const importDeclaration = recast.types.builders.importDeclaration([], recast.types.builders.stringLiteral('remotion'));
648
+ importDeclaration.specifiers = [specifier];
649
+ insertImportDeclaration(ast, importDeclaration);
650
+ };
651
+ const ensureSolidImport = (ast) => {
652
+ var _a, _b;
653
+ let remotionImport = null;
654
+ for (const node of ast.program.body) {
655
+ if (node.type !== 'ImportDeclaration' || node.source.value !== 'remotion') {
656
+ continue;
657
+ }
658
+ remotionImport = node;
659
+ const solidSpecifier = (_a = node.specifiers) === null || _a === void 0 ? void 0 : _a.find((specifier) => {
660
+ return (specifier.type === 'ImportSpecifier' &&
661
+ getImportedName(specifier) === 'Solid');
662
+ });
663
+ if ((_b = solidSpecifier === null || solidSpecifier === void 0 ? void 0 : solidSpecifier.local) === null || _b === void 0 ? void 0 : _b.name) {
664
+ return solidSpecifier.local.name;
665
+ }
666
+ }
667
+ const localName = getAvailableSolidLocalName(ast);
668
+ addSolidImport({ ast, localName, remotionImport });
669
+ return localName;
670
+ };
671
+ const addElementToComponentRoot = ({ ast, exportName, element, }) => {
672
+ var _a;
673
+ var _b;
674
+ const declaration = getDeclarationByExportName({ ast, exportName });
675
+ if (!declaration) {
676
+ throw new Error('Could not find composition component declaration');
677
+ }
678
+ const rootNode = getComponentRootNode(declaration);
679
+ if (!rootNode) {
680
+ const insertedAt = addElementToNullComponentReturn({ declaration, element });
681
+ if (insertedAt !== null) {
682
+ return insertedAt;
683
+ }
684
+ throw new Error('Composition component does not return JSX');
685
+ }
686
+ if (rootNode.type === 'JSXElement' && rootNode.openingElement.selfClosing) {
687
+ throw new Error('Cannot insert into a self-closing root JSX element');
688
+ }
689
+ const CANVAS_ROOT_ELEMENTS = [
690
+ 'ThreeCanvas',
691
+ 'RiveCanvas',
692
+ 'SkiaCanvas',
693
+ 'canvas',
694
+ ];
695
+ if (rootNode.type === 'JSXElement' &&
696
+ rootNode.openingElement.name.type === 'JSXIdentifier' &&
697
+ CANVAS_ROOT_ELEMENTS.includes(rootNode.openingElement.name.name)) {
698
+ throw new Error(`Cannot insert a <Solid> into a composition whose root element is <${rootNode.openingElement.name.name}>`);
699
+ }
700
+ if (!rootNode.children) {
701
+ throw new Error('Composition component root does not accept children');
702
+ }
703
+ rootNode.children.push(element);
704
+ return (_b = (_a = rootNode.loc) === null || _a === void 0 ? void 0 : _a.start.line) !== null && _b !== void 0 ? _b : 1;
705
+ };
506
706
  const getDefaultExportDeclaration = (ast) => {
507
707
  let declaration = null;
508
708
  let identifierName = null;
@@ -532,39 +732,16 @@ const getDeclarationByExportName = ({ ast, exportName, }) => {
532
732
  return findLocalComponentDeclaration({ ast, name: exportName });
533
733
  };
534
734
  const canAddSequenceToComponent = ({ ast, exportName, }) => {
535
- const declaration = getDeclarationByExportName({ ast, exportName });
536
- if (!declaration) {
537
- return false;
538
- }
539
- const rootNode = getComponentRootNode(declaration);
540
- if (!rootNode) {
541
- return false;
542
- }
543
- if (rootNode.type === 'JSXElement') {
544
- if (rootNode.openingElement.selfClosing) {
545
- return false;
546
- }
547
- if (!rootNode.children) {
548
- return false;
549
- }
550
- rootNode.children.push(createSequenceElement());
551
- try {
552
- recast.print(ast);
553
- return true;
554
- }
555
- catch (_a) {
556
- return false;
557
- }
558
- }
559
- if (!rootNode.children) {
560
- return false;
561
- }
562
- rootNode.children.push(createSequenceElement());
563
735
  try {
736
+ addElementToComponentRoot({
737
+ ast,
738
+ exportName,
739
+ element: createSequenceElement(),
740
+ });
564
741
  recast.print(ast);
565
742
  return true;
566
743
  }
567
- catch (_b) {
744
+ catch (_a) {
568
745
  return false;
569
746
  }
570
747
  };
@@ -582,6 +759,8 @@ const getComponentLocationInFile = async ({ remotionRoot, fileName, exportName,
582
759
  });
583
760
  return {
584
761
  source: node_path_1.default.relative(remotionRoot, fileName),
762
+ fileName,
763
+ exportName,
585
764
  line: (_a = location === null || location === void 0 ? void 0 : location.line) !== null && _a !== void 0 ? _a : 1,
586
765
  column: (_b = location === null || location === void 0 ? void 0 : location.column) !== null && _b !== void 0 ? _b : 0,
587
766
  canAddSequence,
@@ -641,7 +820,7 @@ const getComponentLocationRecursively = async ({ remotionRoot, fileName, exportN
641
820
  visited.delete(key);
642
821
  }
643
822
  };
644
- const resolveCompositionComponent = async ({ remotionRoot, compositionFile, compositionId, }) => {
823
+ const resolveCompositionComponentWithFile = async ({ remotionRoot, compositionFile, compositionId, }) => {
645
824
  const compositionFileName = node_path_1.default.resolve(remotionRoot, compositionFile);
646
825
  const input = await readSourceFile({
647
826
  remotionRoot,
@@ -688,4 +867,63 @@ const resolveCompositionComponent = async ({ remotionRoot, compositionFile, comp
688
867
  visited: new Set(),
689
868
  });
690
869
  };
870
+ const resolveCompositionComponent = async ({ remotionRoot, compositionFile, compositionId, }) => {
871
+ const { source, line, column, canAddSequence } = await resolveCompositionComponentWithFile({
872
+ remotionRoot,
873
+ compositionFile,
874
+ compositionId,
875
+ });
876
+ return {
877
+ source,
878
+ line,
879
+ column,
880
+ canAddSequence,
881
+ };
882
+ };
691
883
  exports.resolveCompositionComponent = resolveCompositionComponent;
884
+ const createInsertableJsxElement = ({ ast, element, }) => {
885
+ if (element.type === 'solid') {
886
+ const solidLocalName = ensureSolidImport(ast);
887
+ return createSolidElement({
888
+ localName: solidLocalName,
889
+ width: element.width,
890
+ height: element.height,
891
+ });
892
+ }
893
+ throw new Error('Unsupported element type');
894
+ };
895
+ const insertJsxElementIntoComposition = async ({ remotionRoot, compositionFile, compositionId, element, prettierConfigOverride, }) => {
896
+ const location = await resolveCompositionComponentWithFile({
897
+ remotionRoot,
898
+ compositionFile,
899
+ compositionId,
900
+ });
901
+ if (!location.canAddSequence) {
902
+ throw new Error('Cannot insert JSX element into this composition component');
903
+ }
904
+ const input = await readSourceFile({
905
+ remotionRoot,
906
+ fileName: location.fileName,
907
+ });
908
+ const ast = (0, parse_ast_1.parseAst)(input);
909
+ const elementToInsert = createInsertableJsxElement({ ast, element });
910
+ const logLine = addElementToComponentRoot({
911
+ ast,
912
+ exportName: location.exportName,
913
+ element: elementToInsert,
914
+ });
915
+ const finalFile = (0, parse_ast_1.serializeAst)(ast);
916
+ const { output, formatted } = await (0, format_file_content_1.formatFileContent)({
917
+ input: finalFile,
918
+ prettierConfigOverride,
919
+ });
920
+ return {
921
+ fileName: location.fileName,
922
+ source: location.source,
923
+ oldContents: input,
924
+ output,
925
+ formatted,
926
+ logLine,
927
+ };
928
+ };
929
+ exports.insertJsxElementIntoComposition = insertJsxElementIntoComposition;
@@ -1,6 +1,7 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.allApiRoutes = void 0;
4
+ const add_effect_1 = require("./routes/add-effect");
4
5
  const add_effect_keyframe_1 = require("./routes/add-effect-keyframe");
5
6
  const add_render_1 = require("./routes/add-render");
6
7
  const add_sequence_keyframe_1 = require("./routes/add-sequence-keyframe");
@@ -9,11 +10,11 @@ const apply_visual_control_change_1 = require("./routes/apply-visual-control-cha
9
10
  const cancel_render_1 = require("./routes/cancel-render");
10
11
  const composition_component_info_1 = require("./routes/composition-component-info");
11
12
  const delete_effect_1 = require("./routes/delete-effect");
12
- const delete_effect_keyframe_1 = require("./routes/delete-effect-keyframe");
13
13
  const delete_jsx_node_1 = require("./routes/delete-jsx-node");
14
- const delete_sequence_keyframe_1 = require("./routes/delete-sequence-keyframe");
14
+ const delete_keyframes_1 = require("./routes/delete-keyframes");
15
15
  const delete_static_file_1 = require("./routes/delete-static-file");
16
16
  const duplicate_jsx_node_1 = require("./routes/duplicate-jsx-node");
17
+ const insert_jsx_element_1 = require("./routes/insert-jsx-element");
17
18
  const install_dependency_1 = require("./routes/install-dependency");
18
19
  const open_in_editor_1 = require("./routes/open-in-editor");
19
20
  const open_in_file_explorer_1 = require("./routes/open-in-file-explorer");
@@ -21,6 +22,7 @@ const project_info_1 = require("./routes/project-info");
21
22
  const redo_1 = require("./routes/redo");
22
23
  const register_client_render_1 = require("./routes/register-client-render");
23
24
  const remove_render_1 = require("./routes/remove-render");
25
+ const reorder_effect_1 = require("./routes/reorder-effect");
24
26
  const restart_studio_1 = require("./routes/restart-studio");
25
27
  const save_effect_props_1 = require("./routes/save-effect-props");
26
28
  const save_sequence_props_1 = require("./routes/save-sequence-props");
@@ -54,9 +56,10 @@ exports.allApiRoutes = {
54
56
  '/api/unsubscribe-from-sequence-props': unsubscribe_from_sequence_props_1.unsubscribeFromSequenceProps,
55
57
  '/api/save-sequence-props': save_sequence_props_1.saveSequencePropsHandler,
56
58
  '/api/save-effect-props': save_effect_props_1.saveEffectPropsHandler,
57
- '/api/delete-sequence-keyframe': delete_sequence_keyframe_1.deleteSequenceKeyframeHandler,
59
+ '/api/add-effect': add_effect_1.addEffectHandler,
60
+ '/api/reorder-effect': reorder_effect_1.reorderEffectHandler,
61
+ '/api/delete-keyframes': delete_keyframes_1.deleteKeyframesHandler,
58
62
  '/api/add-sequence-keyframe': add_sequence_keyframe_1.addSequenceKeyframeHandler,
59
- '/api/delete-effect-keyframe': delete_effect_keyframe_1.deleteEffectKeyframeHandler,
60
63
  '/api/add-effect-keyframe': add_effect_keyframe_1.addEffectKeyframeHandler,
61
64
  '/api/delete-effect': delete_effect_1.deleteEffectHandler,
62
65
  '/api/delete-jsx-node': delete_jsx_node_1.deleteJsxNodeHandler,
@@ -66,6 +69,7 @@ exports.allApiRoutes = {
66
69
  '/api/delete-static-file': delete_static_file_1.deleteStaticFileHandler,
67
70
  '/api/restart-studio': restart_studio_1.handleRestartStudio,
68
71
  '/api/install-package': install_dependency_1.handleInstallPackage,
72
+ '/api/insert-jsx-element': insert_jsx_element_1.insertJsxElementHandler,
69
73
  '/api/undo': undo_1.undoHandler,
70
74
  '/api/redo': redo_1.redoHandler,
71
75
  };
@@ -23,7 +23,7 @@ const addEffectKeyframeHandler = ({ input: { fileName, sequenceNodePath, effectI
23
23
  });
24
24
  const fileContents = (0, node_fs_1.readFileSync)(absolutePath, 'utf-8');
25
25
  const parsedValue = JSON.parse(value);
26
- const { output, oldValueStrings, newValueStrings, formatted, logLine, effectCallee, } = await (0, update_keyframes_1.updateEffectKeyframes)({
26
+ const { output, oldValueStrings, newValueStrings, formatted, logLine, effectCallee, updatedSequenceNodePath, } = await (0, update_keyframes_1.updateEffectKeyframes)({
27
27
  input: fileContents,
28
28
  sequenceNodePath: sequenceNodePath.nodePath,
29
29
  effectIndex,
@@ -74,7 +74,7 @@ const addEffectKeyframeHandler = ({ input: { fileName, sequenceNodePath, effectI
74
74
  });
75
75
  (0, undo_stack_1.printUndoHint)(logLevel);
76
76
  const ast = (0, parse_ast_1.parseAst)((0, node_fs_1.readFileSync)(absolutePath, 'utf-8'));
77
- const jsx = (0, can_update_sequence_props_1.findJsxElementAtNodePath)(ast, sequenceNodePath.nodePath);
77
+ const jsx = (0, can_update_sequence_props_1.findJsxElementAtNodePath)(ast, updatedSequenceNodePath);
78
78
  if (!jsx) {
79
79
  return {
80
80
  canUpdate: false,
@@ -0,0 +1,3 @@
1
+ import type { AddEffectRequest, AddEffectResponse } from '@remotion/studio-shared';
2
+ import type { ApiHandler } from '../api-types';
3
+ export declare const addEffectHandler: ApiHandler<AddEffectRequest, AddEffectResponse>;
@@ -0,0 +1,68 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.addEffectHandler = void 0;
4
+ const node_fs_1 = require("node:fs");
5
+ const renderer_1 = require("@remotion/renderer");
6
+ const add_effect_1 = require("../../codemods/add-effect");
7
+ const file_watcher_1 = require("../../file-watcher");
8
+ const resolve_file_inside_project_1 = require("../../helpers/resolve-file-inside-project");
9
+ const format_log_file_location_1 = require("../format-log-file-location");
10
+ const undo_stack_1 = require("../undo-stack");
11
+ const formatting_1 = require("./log-updates/formatting");
12
+ const log_update_1 = require("./log-updates/log-update");
13
+ const addEffectHandler = async ({ input: { fileName, sequenceNodePath, effectName, effectImportPath, effectConfig, clientId, }, remotionRoot, logLevel, }) => {
14
+ try {
15
+ renderer_1.RenderInternals.Log.trace({ indent: false, logLevel }, `[add-effect] Received request for fileName="${fileName}" effect="${effectName}"`);
16
+ const { absolutePath, fileRelativeToRoot } = (0, resolve_file_inside_project_1.resolveFileInsideProject)({
17
+ remotionRoot,
18
+ fileName,
19
+ action: 'modify',
20
+ });
21
+ const fileContents = (0, node_fs_1.readFileSync)(absolutePath, 'utf-8');
22
+ const { output, formatted, effectLabel, nodeLabel, logLine } = await (0, add_effect_1.addEffect)({
23
+ input: fileContents,
24
+ sequenceNodePath: sequenceNodePath.nodePath,
25
+ effectName,
26
+ effectImportPath,
27
+ effectConfig,
28
+ });
29
+ (0, undo_stack_1.pushToUndoStack)({
30
+ filePath: absolutePath,
31
+ oldContents: fileContents,
32
+ newContents: null,
33
+ logLevel,
34
+ remotionRoot,
35
+ logLine,
36
+ description: {
37
+ undoMessage: `↩️ Addition of ${effectLabel} to ${nodeLabel}`,
38
+ redoMessage: `↪️ Addition of ${effectLabel} to ${nodeLabel}`,
39
+ },
40
+ entryType: 'add-effect',
41
+ suppressHmrOnFileRestore: false,
42
+ });
43
+ (0, undo_stack_1.suppressUndoStackInvalidation)(absolutePath);
44
+ (0, file_watcher_1.writeFileAndNotifyFileWatchers)(absolutePath, output, clientId);
45
+ const locationLabel = (0, format_log_file_location_1.formatLogFileLocation)({
46
+ remotionRoot,
47
+ absolutePath,
48
+ line: logLine,
49
+ });
50
+ renderer_1.RenderInternals.Log.info({ indent: false, logLevel }, `${renderer_1.RenderInternals.chalk.blueBright(`${locationLabel}`)} Added ${(0, formatting_1.attrName)(effectLabel)} to ${nodeLabel}`);
51
+ if (!formatted) {
52
+ (0, log_update_1.warnAboutPrettierOnce)(logLevel);
53
+ }
54
+ renderer_1.RenderInternals.Log.verbose({ indent: false, logLevel }, `[add-effect] Wrote ${fileRelativeToRoot}${formatted ? ' (formatted)' : ''}`);
55
+ (0, undo_stack_1.printUndoHint)(logLevel);
56
+ return {
57
+ success: true,
58
+ };
59
+ }
60
+ catch (err) {
61
+ return {
62
+ success: false,
63
+ reason: err.message,
64
+ stack: err.stack,
65
+ };
66
+ }
67
+ };
68
+ exports.addEffectHandler = addEffectHandler;
@@ -21,7 +21,7 @@ const addSequenceKeyframeHandler = ({ input: { fileName, nodePath, key, frame, v
21
21
  });
22
22
  const fileContents = (0, node_fs_1.readFileSync)(absolutePath, 'utf-8');
23
23
  const parsedValue = JSON.parse(value);
24
- const { output, oldValueStrings, newValueStrings, formatted, logLine } = await (0, update_keyframes_1.updateSequenceKeyframes)({
24
+ const { output, oldValueStrings, newValueStrings, formatted, logLine, updatedNodePath, } = await (0, update_keyframes_1.updateSequenceKeyframes)({
25
25
  input: fileContents,
26
26
  nodePath: nodePath.nodePath,
27
27
  updates: [
@@ -72,13 +72,16 @@ const addSequenceKeyframeHandler = ({ input: { fileName, nodePath, key, frame, v
72
72
  const status = (0, can_update_sequence_props_1.computeSequencePropsStatusFromContent)({
73
73
  fileContents: output,
74
74
  keys: (0, studio_shared_1.getAllSchemaKeys)(schema),
75
- nodePath: nodePath.nodePath,
75
+ nodePath: updatedNodePath,
76
76
  effects: [],
77
77
  });
78
+ const updatedSubscriptionKey = { ...nodePath, nodePath: updatedNodePath };
78
79
  return {
79
80
  canUpdate: true,
80
81
  props: status.props,
81
- results: [{ fileName, nodePath, props: status.props }],
82
+ results: [
83
+ { fileName, nodePath: updatedSubscriptionKey, props: status.props },
84
+ ],
82
85
  };
83
86
  });
84
87
  exports.addSequenceKeyframeHandler = addSequenceKeyframeHandler;
@@ -5,6 +5,7 @@ export declare const isStaticValue: (node: Expression) => boolean;
5
5
  export declare const extractStaticValue: (node: Expression) => unknown;
6
6
  export declare const getComputedStatus: (node: Expression) => CanUpdateSequencePropStatus;
7
7
  export declare const findJsxElementAtNodePath: (ast: File, nodePath: SequenceNodePath) => JSXOpeningElement | null;
8
+ export declare const findNodePathForJsxElement: (ast: File, target: JSXOpeningElement) => SequenceNodePath | null;
8
9
  export declare const lineColumnToNodePath: (ast: File, targetLine: number) => SequenceNodePath | null;
9
10
  export declare const computeSequencePropsStatusFromContent: ({ fileContents, nodePath, keys, effects, }: {
10
11
  fileContents: string;
@@ -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.findJsxElementAtNodePath = exports.getComputedStatus = exports.extractStaticValue = exports.isStaticValue = void 0;
36
+ exports.computeSequencePropsStatusFromFilenameByLine = exports.computeSequencePropsStatus = exports.computeSequencePropsStatusFromContent = exports.lineColumnToNodePath = exports.findNodePathForJsxElement = exports.findJsxElementAtNodePath = 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 recast = __importStar(require("recast"));
@@ -443,6 +443,20 @@ const findJsxElementAtNodePath = (ast, nodePath) => {
443
443
  return null;
444
444
  };
445
445
  exports.findJsxElementAtNodePath = findJsxElementAtNodePath;
446
+ const findNodePathForJsxElement = (ast, target) => {
447
+ let foundPath = null;
448
+ recast.types.visit(ast, {
449
+ visitJSXOpeningElement(p) {
450
+ if (p.node === target) {
451
+ foundPath = getNodePathForRecastPath(p);
452
+ return false;
453
+ }
454
+ return this.traverse(p);
455
+ },
456
+ });
457
+ return foundPath;
458
+ };
459
+ exports.findNodePathForJsxElement = findNodePathForJsxElement;
446
460
  const lineColumnToNodePath = (ast, targetLine) => {
447
461
  let foundPath = null;
448
462
  recast.types.visit(ast, {
@@ -0,0 +1,13 @@
1
+ import type { DeleteEffectKeyframe, DeleteKeyframesRequest, DeleteKeyframesResponse, DeleteSequenceKeyframe, SaveSequencePropsResult } from '@remotion/studio-shared';
2
+ import type { ApiHandler } from '../api-types';
3
+ export declare const deleteKeyframes: ({ sequenceKeyframes, effectKeyframes, clientId, remotionRoot, logLevel, }: {
4
+ sequenceKeyframes: DeleteSequenceKeyframe[];
5
+ effectKeyframes: DeleteEffectKeyframe[];
6
+ clientId: string;
7
+ remotionRoot: string;
8
+ logLevel: "error" | "info" | "trace" | "verbose" | "warn";
9
+ }) => Promise<{
10
+ sequenceResults: SaveSequencePropsResult[];
11
+ effectResults: import("remotion").CanUpdateEffectPropsResponse[];
12
+ }>;
13
+ export declare const deleteKeyframesHandler: ApiHandler<DeleteKeyframesRequest, DeleteKeyframesResponse>;