@remotion/studio-server 4.0.471 → 4.0.473

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 (53) hide show
  1. package/dist/codemods/add-effect.d.ts +11 -0
  2. package/dist/codemods/add-effect.js +14 -52
  3. package/dist/codemods/effect-param-expression.d.ts +15 -0
  4. package/dist/codemods/effect-param-expression.js +131 -0
  5. package/dist/codemods/format-file-content.js +1 -1
  6. package/dist/codemods/parse-ast.js +4 -1
  7. package/dist/codemods/paste-effects.d.ts +15 -0
  8. package/dist/codemods/paste-effects.js +147 -0
  9. package/dist/codemods/recast-mods.js +178 -31
  10. package/dist/codemods/reorder-sequence.d.ts +14 -0
  11. package/dist/codemods/reorder-sequence.js +109 -0
  12. package/dist/codemods/update-effect-props/update-effect-props.d.ts +7 -0
  13. package/dist/codemods/update-effect-props/update-effect-props.js +64 -16
  14. package/dist/codemods/update-keyframes/ensure-imports-and-frame-hook.d.ts +1 -1
  15. package/dist/codemods/update-keyframes/ensure-imports-and-frame-hook.js +7 -55
  16. package/dist/codemods/update-keyframes/update-keyframes.d.ts +24 -6
  17. package/dist/codemods/update-keyframes/update-keyframes.js +279 -16
  18. package/dist/helpers/get-ast-node-path.js +6 -1
  19. package/dist/helpers/import-agnostic-node-path.d.ts +10 -0
  20. package/dist/helpers/import-agnostic-node-path.js +154 -0
  21. package/dist/helpers/imports.d.ts +16 -0
  22. package/dist/helpers/imports.js +145 -0
  23. package/dist/helpers/resolve-composition-component.js +133 -51
  24. package/dist/preview-server/api-routes.js +16 -0
  25. package/dist/preview-server/routes/add-effect-keyframe.js +2 -0
  26. package/dist/preview-server/routes/add-sequence-keyframe.js +1 -0
  27. package/dist/preview-server/routes/apply-codemod.js +18 -0
  28. package/dist/preview-server/routes/can-update-effect-props.d.ts +3 -2
  29. package/dist/preview-server/routes/can-update-effect-props.js +78 -8
  30. package/dist/preview-server/routes/can-update-sequence-props.d.ts +1 -1
  31. package/dist/preview-server/routes/can-update-sequence-props.js +82 -43
  32. package/dist/preview-server/routes/delete-keyframes.js +1 -0
  33. package/dist/preview-server/routes/download-remote-asset.d.ts +7 -0
  34. package/dist/preview-server/routes/download-remote-asset.js +267 -0
  35. package/dist/preview-server/routes/insert-jsx-element.js +26 -0
  36. package/dist/preview-server/routes/log-studio-error.d.ts +3 -0
  37. package/dist/preview-server/routes/log-studio-error.js +58 -0
  38. package/dist/preview-server/routes/move-keyframes.d.ts +7 -0
  39. package/dist/preview-server/routes/move-keyframes.js +242 -0
  40. package/dist/preview-server/routes/paste-effects.d.ts +3 -0
  41. package/dist/preview-server/routes/paste-effects.js +78 -0
  42. package/dist/preview-server/routes/rename-static-file.d.ts +3 -0
  43. package/dist/preview-server/routes/rename-static-file.js +53 -0
  44. package/dist/preview-server/routes/reorder-sequence.d.ts +3 -0
  45. package/dist/preview-server/routes/reorder-sequence.js +67 -0
  46. package/dist/preview-server/routes/save-effect-props.js +25 -9
  47. package/dist/preview-server/routes/save-sequence-props.js +2 -34
  48. package/dist/preview-server/routes/update-effect-keyframe-settings.d.ts +3 -0
  49. package/dist/preview-server/routes/update-effect-keyframe-settings.js +90 -0
  50. package/dist/preview-server/routes/update-sequence-keyframe-settings.d.ts +3 -0
  51. package/dist/preview-server/routes/update-sequence-keyframe-settings.js +85 -0
  52. package/dist/preview-server/undo-stack.d.ts +9 -1
  53. package/package.json +6 -6
@@ -0,0 +1,154 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.fromImportAgnosticNodePath = exports.toImportAgnosticNodePath = void 0;
4
+ const getActualIndex = ({ items, agnosticIndex, shouldIgnore, context, }) => {
5
+ let seenIncludedNodes = 0;
6
+ for (let i = 0; i < items.length; i++) {
7
+ if (shouldIgnore(items[i], context)) {
8
+ continue;
9
+ }
10
+ if (seenIncludedNodes === agnosticIndex) {
11
+ return i;
12
+ }
13
+ seenIncludedNodes++;
14
+ }
15
+ return null;
16
+ };
17
+ const getAgnosticIndex = ({ items, actualIndex, shouldIgnore, context, }) => {
18
+ if (actualIndex < 0 || actualIndex >= items.length) {
19
+ return null;
20
+ }
21
+ let seenIncludedNodes = 0;
22
+ for (let i = 0; i <= actualIndex; i++) {
23
+ if (shouldIgnore(items[i], context)) {
24
+ continue;
25
+ }
26
+ if (i === actualIndex) {
27
+ return seenIncludedNodes;
28
+ }
29
+ seenIncludedNodes++;
30
+ }
31
+ return null;
32
+ };
33
+ const getUseCurrentFrameLocalNames = (ast) => {
34
+ var _a;
35
+ var _b;
36
+ const names = new Set(['useCurrentFrame']);
37
+ for (const statement of ast.program.body) {
38
+ if (statement.type !== 'ImportDeclaration' ||
39
+ statement.source.value !== 'remotion') {
40
+ continue;
41
+ }
42
+ for (const specifier of statement.specifiers) {
43
+ if (specifier.type === 'ImportSpecifier' &&
44
+ specifier.imported.type === 'Identifier' &&
45
+ specifier.imported.name === 'useCurrentFrame') {
46
+ names.add((_b = (_a = specifier.local) === null || _a === void 0 ? void 0 : _a.name) !== null && _b !== void 0 ? _b : 'useCurrentFrame');
47
+ }
48
+ }
49
+ }
50
+ return names;
51
+ };
52
+ const isUseCurrentFrameCall = (node, useCurrentFrameLocalNames) => {
53
+ return ((node === null || node === void 0 ? void 0 : node.type) === 'CallExpression' &&
54
+ node.callee.type === 'Identifier' &&
55
+ useCurrentFrameLocalNames.has(node.callee.name));
56
+ };
57
+ const isUseCurrentFrameStatement = (node, useCurrentFrameLocalNames) => {
58
+ if (node.type === 'ExpressionStatement') {
59
+ return isUseCurrentFrameCall(node.expression, useCurrentFrameLocalNames);
60
+ }
61
+ if (node.type !== 'VariableDeclaration' || node.declarations.length !== 1) {
62
+ return false;
63
+ }
64
+ return isUseCurrentFrameCall(node.declarations[0].init, useCurrentFrameLocalNames);
65
+ };
66
+ const getIgnoredNodePredicate = (ast) => {
67
+ const useCurrentFrameLocalNames = getUseCurrentFrameLocalNames(ast);
68
+ return (node, { parent, property }) => {
69
+ if (parent.type === 'Program' &&
70
+ property === 'body' &&
71
+ node.type === 'ImportDeclaration') {
72
+ return true;
73
+ }
74
+ if (parent.type === 'BlockStatement' && property === 'body') {
75
+ return isUseCurrentFrameStatement(node, useCurrentFrameLocalNames);
76
+ }
77
+ return false;
78
+ };
79
+ };
80
+ const getChild = (value, segment) => {
81
+ var _a, _b;
82
+ if (value === null || value === undefined) {
83
+ return null;
84
+ }
85
+ if (Array.isArray(value)) {
86
+ return (_a = value[segment]) !== null && _a !== void 0 ? _a : null;
87
+ }
88
+ if (typeof value !== 'object') {
89
+ return null;
90
+ }
91
+ return (_b = value[segment]) !== null && _b !== void 0 ? _b : null;
92
+ };
93
+ const transformNodePathIndices = ({ ast, nodePath, direction, }) => {
94
+ const shouldIgnore = getIgnoredNodePredicate(ast);
95
+ const transformed = [];
96
+ let current = ast;
97
+ let arrayContext = null;
98
+ for (const segment of nodePath) {
99
+ if (typeof segment === 'string') {
100
+ const parent = current;
101
+ current = getChild(current, segment);
102
+ if (Array.isArray(current) &&
103
+ parent &&
104
+ typeof parent === 'object' &&
105
+ 'type' in parent) {
106
+ arrayContext = { parent: parent, property: segment };
107
+ }
108
+ else {
109
+ arrayContext = null;
110
+ }
111
+ transformed.push(segment);
112
+ continue;
113
+ }
114
+ if (!Array.isArray(current) || !arrayContext) {
115
+ current = getChild(current, segment);
116
+ transformed.push(segment);
117
+ continue;
118
+ }
119
+ const mappedIndex = direction === 'to-agnostic'
120
+ ? getAgnosticIndex({
121
+ items: current,
122
+ actualIndex: segment,
123
+ shouldIgnore,
124
+ context: arrayContext,
125
+ })
126
+ : getActualIndex({
127
+ items: current,
128
+ agnosticIndex: segment,
129
+ shouldIgnore,
130
+ context: arrayContext,
131
+ });
132
+ if (mappedIndex === null) {
133
+ if (direction === 'from-agnostic') {
134
+ return null;
135
+ }
136
+ current = getChild(current, segment);
137
+ transformed.push(segment);
138
+ continue;
139
+ }
140
+ current = getChild(current, direction === 'to-agnostic' ? segment : mappedIndex);
141
+ arrayContext = null;
142
+ transformed.push(mappedIndex);
143
+ }
144
+ return transformed;
145
+ };
146
+ const toImportAgnosticNodePath = ({ ast, nodePath, }) => {
147
+ var _a;
148
+ return ((_a = transformNodePathIndices({ ast, nodePath, direction: 'to-agnostic' })) !== null && _a !== void 0 ? _a : nodePath);
149
+ };
150
+ exports.toImportAgnosticNodePath = toImportAgnosticNodePath;
151
+ const fromImportAgnosticNodePath = ({ ast, nodePath, }) => {
152
+ return transformNodePathIndices({ ast, nodePath, direction: 'from-agnostic' });
153
+ };
154
+ exports.fromImportAgnosticNodePath = fromImportAgnosticNodePath;
@@ -0,0 +1,16 @@
1
+ import type { File, ImportDeclaration, ImportSpecifier } from '@babel/types';
2
+ export declare const getImportedName: (specifier: ImportSpecifier) => string;
3
+ export declare const findImportDeclaration: (ast: File, sourcePath: string) => ImportDeclaration | null;
4
+ export declare const insertImportDeclaration: (ast: File, importDeclaration: ImportDeclaration) => void;
5
+ export declare const normalizeImportSpacing: (input: string) => string;
6
+ export declare const ensureNamedImport: ({ ast, importedName, sourcePath, localName, }: {
7
+ ast: File;
8
+ importedName: string;
9
+ sourcePath: string;
10
+ localName: string;
11
+ }) => string;
12
+ export declare const ensureNamedImports: ({ ast, importedNames, sourcePath, }: {
13
+ ast: File;
14
+ importedNames: ReadonlySet<string>;
15
+ sourcePath: string;
16
+ }) => void;
@@ -0,0 +1,145 @@
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
+ Object.defineProperty(exports, "__esModule", { value: true });
36
+ exports.ensureNamedImports = exports.ensureNamedImport = exports.normalizeImportSpacing = exports.insertImportDeclaration = exports.findImportDeclaration = exports.getImportedName = void 0;
37
+ const recast = __importStar(require("recast"));
38
+ const b = recast.types.builders;
39
+ const getImportedName = (specifier) => {
40
+ if (specifier.imported.type === 'Identifier') {
41
+ return specifier.imported.name;
42
+ }
43
+ return specifier.imported.value;
44
+ };
45
+ exports.getImportedName = getImportedName;
46
+ const findImportDeclaration = (ast, sourcePath) => {
47
+ for (const stmt of ast.program.body) {
48
+ if (stmt.type === 'ImportDeclaration' &&
49
+ stmt.source.type === 'StringLiteral' &&
50
+ stmt.source.value === sourcePath) {
51
+ return stmt;
52
+ }
53
+ }
54
+ return null;
55
+ };
56
+ exports.findImportDeclaration = findImportDeclaration;
57
+ const findImportDeclarations = (ast, sourcePath) => {
58
+ return ast.program.body.filter((stmt) => stmt.type === 'ImportDeclaration' &&
59
+ stmt.source.type === 'StringLiteral' &&
60
+ stmt.source.value === sourcePath);
61
+ };
62
+ const insertImportDeclaration = (ast, importDeclaration) => {
63
+ const { body } = ast.program;
64
+ let lastImportIndex = -1;
65
+ for (let i = 0; i < body.length; i++) {
66
+ if (body[i].type === 'ImportDeclaration') {
67
+ lastImportIndex = i;
68
+ }
69
+ }
70
+ body.splice(lastImportIndex + 1, 0, importDeclaration);
71
+ };
72
+ exports.insertImportDeclaration = insertImportDeclaration;
73
+ const normalizeImportSpacing = (input) => {
74
+ return input.replace(/(import[^\n]*\n)\n+(?=import\b)/g, '$1');
75
+ };
76
+ exports.normalizeImportSpacing = normalizeImportSpacing;
77
+ const hasNamespaceSpecifier = (importDeclaration) => {
78
+ var _a;
79
+ return (_a = importDeclaration.specifiers) === null || _a === void 0 ? void 0 : _a.some((specifier) => specifier.type === 'ImportNamespaceSpecifier');
80
+ };
81
+ const ensureNamedImport = ({ ast, importedName, sourcePath, localName, }) => {
82
+ var _a, _b;
83
+ var _c, _d;
84
+ const existingImports = findImportDeclarations(ast, sourcePath);
85
+ for (const existingImportDeclaration of existingImports) {
86
+ const matchingSpecifier = (_a = existingImportDeclaration.specifiers) === null || _a === void 0 ? void 0 : _a.find((importSpecifierCandidate) => importSpecifierCandidate.type === 'ImportSpecifier' &&
87
+ (0, exports.getImportedName)(importSpecifierCandidate) === importedName);
88
+ if (matchingSpecifier) {
89
+ return (_c = (_b = matchingSpecifier.local) === null || _b === void 0 ? void 0 : _b.name) !== null && _c !== void 0 ? _c : importedName;
90
+ }
91
+ }
92
+ const existingImport = existingImports.find((candidateImportDeclaration) => !hasNamespaceSpecifier(candidateImportDeclaration));
93
+ if (existingImport) {
94
+ const importSpecifier = b.importSpecifier(b.identifier(importedName), localName === importedName ? null : b.identifier(localName));
95
+ existingImport.specifiers = [
96
+ ...((_d = existingImport.specifiers) !== null && _d !== void 0 ? _d : []),
97
+ importSpecifier,
98
+ ];
99
+ return localName;
100
+ }
101
+ const specifier = b.importSpecifier(b.identifier(importedName), localName === importedName ? null : b.identifier(localName));
102
+ const importDeclaration = b.importDeclaration([specifier], b.stringLiteral(sourcePath));
103
+ (0, exports.insertImportDeclaration)(ast, importDeclaration);
104
+ return localName;
105
+ };
106
+ exports.ensureNamedImport = ensureNamedImport;
107
+ const ensureNamedImports = ({ ast, importedNames, sourcePath, }) => {
108
+ var _a, _b;
109
+ if (importedNames.size === 0) {
110
+ return;
111
+ }
112
+ const existingImports = findImportDeclarations(ast, sourcePath);
113
+ const existingNames = new Set();
114
+ for (const existingImportDeclaration of existingImports) {
115
+ for (const importSpecifierCandidate of (_a = existingImportDeclaration.specifiers) !== null && _a !== void 0 ? _a : []) {
116
+ if (importSpecifierCandidate.type !== 'ImportSpecifier') {
117
+ continue;
118
+ }
119
+ existingNames.add((0, exports.getImportedName)(importSpecifierCandidate));
120
+ }
121
+ }
122
+ const existingImport = existingImports.find((candidateImportDeclaration) => !hasNamespaceSpecifier(candidateImportDeclaration));
123
+ if (existingImport) {
124
+ for (const importedName of importedNames) {
125
+ if (existingNames.has(importedName)) {
126
+ continue;
127
+ }
128
+ existingImport.specifiers = [
129
+ ...((_b = existingImport.specifiers) !== null && _b !== void 0 ? _b : []),
130
+ b.importSpecifier(b.identifier(importedName)),
131
+ ];
132
+ existingNames.add(importedName);
133
+ }
134
+ return;
135
+ }
136
+ const specifiers = [...importedNames]
137
+ .filter((importedName) => !existingNames.has(importedName))
138
+ .map((importedName) => b.importSpecifier(b.identifier(importedName)));
139
+ if (specifiers.length === 0) {
140
+ return;
141
+ }
142
+ const importDeclaration = b.importDeclaration(specifiers, b.stringLiteral(sourcePath));
143
+ (0, exports.insertImportDeclaration)(ast, importDeclaration);
144
+ };
145
+ exports.ensureNamedImports = ensureNamedImports;
@@ -42,6 +42,7 @@ const node_path_1 = __importDefault(require("node:path"));
42
42
  const recast = __importStar(require("recast"));
43
43
  const format_file_content_1 = require("../codemods/format-file-content");
44
44
  const parse_ast_1 = require("../codemods/parse-ast");
45
+ const imports_1 = require("./imports");
45
46
  const allowedFileExtensions = new Set(['.tsx', '.ts', '.jsx', '.js']);
46
47
  const extensionsToProbe = ['.tsx', '.ts', '.jsx', '.js'];
47
48
  const isInRemotionRoot = ({ remotionRoot, fileName, }) => {
@@ -507,13 +508,31 @@ const createSequenceElement = () => {
507
508
  const createNumberAttribute = (name, value) => {
508
509
  return recast.types.builders.jsxAttribute(recast.types.builders.jsxIdentifier(name), recast.types.builders.jsxExpressionContainer(recast.types.builders.numericLiteral(value)));
509
510
  };
511
+ const createPositionAbsoluteStyleAttribute = () => {
512
+ return recast.types.builders.jsxAttribute(recast.types.builders.jsxIdentifier('style'), recast.types.builders.jsxExpressionContainer(recast.types.builders.objectExpression([
513
+ recast.types.builders.objectProperty(recast.types.builders.identifier('position'), recast.types.builders.stringLiteral('absolute')),
514
+ ])));
515
+ };
516
+ const createStaticFileSrcAttribute = ({ staticFileLocalName, src, }) => {
517
+ return recast.types.builders.jsxAttribute(recast.types.builders.jsxIdentifier('src'), recast.types.builders.jsxExpressionContainer(recast.types.builders.callExpression(recast.types.builders.identifier(staticFileLocalName), [recast.types.builders.stringLiteral(src)])));
518
+ };
510
519
  const createSolidElement = ({ localName, width, height, }) => {
511
520
  return recast.types.builders.jsxElement(recast.types.builders.jsxOpeningElement(recast.types.builders.jsxIdentifier(localName), [
512
521
  createNumberAttribute('width', width),
513
522
  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
- ]))),
523
+ createPositionAbsoluteStyleAttribute(),
524
+ ], true), null, []);
525
+ };
526
+ const createAssetElement = ({ localName, staticFileLocalName, src, dimensions, }) => {
527
+ return recast.types.builders.jsxElement(recast.types.builders.jsxOpeningElement(recast.types.builders.jsxIdentifier(localName), [
528
+ createStaticFileSrcAttribute({ staticFileLocalName, src }),
529
+ createPositionAbsoluteStyleAttribute(),
530
+ ...(dimensions
531
+ ? [
532
+ createNumberAttribute('width', dimensions.width),
533
+ createNumberAttribute('height', dimensions.height),
534
+ ]
535
+ : []),
517
536
  ], true), null, []);
518
537
  };
519
538
  const createFragmentWithElement = (element) => {
@@ -568,12 +587,6 @@ const addElementToNullComponentReturn = ({ declaration, element, }) => {
568
587
  returnStatement.argument = createFragmentWithElement(element);
569
588
  return (_b = (_a = returnStatement.loc) === null || _a === void 0 ? void 0 : _a.start.line) !== null && _b !== void 0 ? _b : 1;
570
589
  };
571
- const getImportedName = (specifier) => {
572
- if (specifier.imported.type === 'Identifier') {
573
- return specifier.imported.name;
574
- }
575
- return specifier.imported.value;
576
- };
577
590
  const declarationBindsName = (declaration, name) => {
578
591
  var _a;
579
592
  if (declaration.type === 'FunctionDeclaration' ||
@@ -619,54 +632,98 @@ const getAvailableSolidLocalName = (ast) => {
619
632
  }
620
633
  return available;
621
634
  };
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);
635
+ const ensureSolidImport = (ast) => {
636
+ return (0, imports_1.ensureNamedImport)({
637
+ ast,
638
+ importedName: 'Solid',
639
+ sourcePath: 'remotion',
640
+ localName: getAvailableSolidLocalName(ast),
641
+ });
642
+ };
643
+ const getImportDeclarations = ({ ast, sourcePath, }) => {
644
+ return ast.program.body.filter((node) => node.type === 'ImportDeclaration' &&
645
+ node.source.type === 'StringLiteral' &&
646
+ node.source.value === sourcePath);
631
647
  };
632
- const addSolidImport = ({ ast, localName, remotionImport, }) => {
648
+ const importDeclarationHasNamespaceSpecifier = (importDeclaration) => {
633
649
  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,
650
+ return (_a = importDeclaration.specifiers) === null || _a === void 0 ? void 0 : _a.some((specifier) => specifier.type === 'ImportNamespaceSpecifier');
651
+ };
652
+ const hasOfficialLocalImport = ({ ast, importedName, sourcePath, }) => {
653
+ return getImportDeclarations({ ast, sourcePath }).some((importDeclaration) => {
654
+ var _a;
655
+ return (_a = importDeclaration.specifiers) === null || _a === void 0 ? void 0 : _a.some((specifier) => {
656
+ var _a;
657
+ var _b;
658
+ return (specifier.type === 'ImportSpecifier' &&
659
+ (0, imports_1.getImportedName)(specifier) === importedName &&
660
+ ((_b = (_a = specifier.local) === null || _a === void 0 ? void 0 : _a.name) !== null && _b !== void 0 ? _b : importedName) === importedName);
661
+ });
662
+ });
663
+ };
664
+ const addOfficialNamedImport = ({ ast, importedName, sourcePath, }) => {
665
+ var _a;
666
+ const existingImport = getImportDeclarations({ ast, sourcePath }).find((candidate) => !importDeclarationHasNamespaceSpecifier(candidate));
667
+ const importSpecifier = recast.types.builders.importSpecifier(recast.types.builders.identifier(importedName));
668
+ if (existingImport) {
669
+ existingImport.specifiers = [
670
+ ...((_a = existingImport.specifiers) !== null && _a !== void 0 ? _a : []),
671
+ importSpecifier,
644
672
  ];
645
673
  return;
646
674
  }
647
- const importDeclaration = recast.types.builders.importDeclaration([], recast.types.builders.stringLiteral('remotion'));
648
- importDeclaration.specifiers = [specifier];
649
- insertImportDeclaration(ast, importDeclaration);
675
+ const importDeclaration = recast.types.builders.importDeclaration([importSpecifier], recast.types.builders.stringLiteral(sourcePath));
676
+ (0, imports_1.insertImportDeclaration)(ast, importDeclaration);
650
677
  };
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
- }
678
+ const ensureOfficialNamedImport = ({ ast, importedName, sourcePath, label, }) => {
679
+ if (hasOfficialLocalImport({ ast, importedName, sourcePath })) {
680
+ return importedName;
681
+ }
682
+ if (hasTopLevelBinding({ ast, name: importedName })) {
683
+ throw new Error(`Cannot add ${label} because ${importedName} is already defined`);
666
684
  }
667
- const localName = getAvailableSolidLocalName(ast);
668
- addSolidImport({ ast, localName, remotionImport });
669
- return localName;
685
+ addOfficialNamedImport({ ast, importedName, sourcePath });
686
+ return importedName;
687
+ };
688
+ const ensureStaticFileImport = (ast) => {
689
+ return ensureOfficialNamedImport({
690
+ ast,
691
+ importedName: 'staticFile',
692
+ sourcePath: 'remotion',
693
+ label: 'staticFile()',
694
+ });
695
+ };
696
+ const ensureImgImport = (ast) => {
697
+ return ensureOfficialNamedImport({
698
+ ast,
699
+ importedName: 'Img',
700
+ sourcePath: 'remotion',
701
+ label: '<Img>',
702
+ });
703
+ };
704
+ const ensureVideoImport = (ast) => {
705
+ return ensureOfficialNamedImport({
706
+ ast,
707
+ importedName: 'Video',
708
+ sourcePath: '@remotion/media',
709
+ label: '<Video>',
710
+ });
711
+ };
712
+ const ensureAudioImport = (ast) => {
713
+ return ensureOfficialNamedImport({
714
+ ast,
715
+ importedName: 'Audio',
716
+ sourcePath: '@remotion/media',
717
+ label: '<Audio>',
718
+ });
719
+ };
720
+ const ensureGifImport = (ast) => {
721
+ return ensureOfficialNamedImport({
722
+ ast,
723
+ importedName: 'Gif',
724
+ sourcePath: '@remotion/gif',
725
+ label: '<Gif>',
726
+ });
670
727
  };
671
728
  const addElementToComponentRoot = ({ ast, exportName, element, }) => {
672
729
  var _a;
@@ -695,7 +752,7 @@ const addElementToComponentRoot = ({ ast, exportName, element, }) => {
695
752
  if (rootNode.type === 'JSXElement' &&
696
753
  rootNode.openingElement.name.type === 'JSXIdentifier' &&
697
754
  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}>`);
755
+ throw new Error(`Cannot insert a JSX element into a composition whose root element is <${rootNode.openingElement.name.name}>`);
699
756
  }
700
757
  if (!rootNode.children) {
701
758
  throw new Error('Composition component root does not accept children');
@@ -890,6 +947,31 @@ const createInsertableJsxElement = ({ ast, element, }) => {
890
947
  height: element.height,
891
948
  });
892
949
  }
950
+ if (element.type === 'asset') {
951
+ const staticFileLocalName = ensureStaticFileImport(ast);
952
+ let localName;
953
+ if (element.assetType === 'image') {
954
+ localName = ensureImgImport(ast);
955
+ }
956
+ else if (element.assetType === 'video') {
957
+ localName = ensureVideoImport(ast);
958
+ }
959
+ else if (element.assetType === 'gif') {
960
+ localName = ensureGifImport(ast);
961
+ }
962
+ else if (element.assetType === 'audio') {
963
+ localName = ensureAudioImport(ast);
964
+ }
965
+ else {
966
+ throw new Error('Unsupported asset type');
967
+ }
968
+ return createAssetElement({
969
+ localName,
970
+ staticFileLocalName,
971
+ src: element.src,
972
+ dimensions: element.dimensions,
973
+ });
974
+ }
893
975
  throw new Error('Unsupported element type');
894
976
  };
895
977
  const insertJsxElementIntoComposition = async ({ remotionRoot, compositionFile, compositionId, element, prettierConfigOverride, }) => {
@@ -13,16 +13,22 @@ const delete_effect_1 = require("./routes/delete-effect");
13
13
  const delete_jsx_node_1 = require("./routes/delete-jsx-node");
14
14
  const delete_keyframes_1 = require("./routes/delete-keyframes");
15
15
  const delete_static_file_1 = require("./routes/delete-static-file");
16
+ const download_remote_asset_1 = require("./routes/download-remote-asset");
16
17
  const duplicate_jsx_node_1 = require("./routes/duplicate-jsx-node");
17
18
  const insert_jsx_element_1 = require("./routes/insert-jsx-element");
18
19
  const install_dependency_1 = require("./routes/install-dependency");
20
+ const log_studio_error_1 = require("./routes/log-studio-error");
21
+ const move_keyframes_1 = require("./routes/move-keyframes");
19
22
  const open_in_editor_1 = require("./routes/open-in-editor");
20
23
  const open_in_file_explorer_1 = require("./routes/open-in-file-explorer");
24
+ const paste_effects_1 = require("./routes/paste-effects");
21
25
  const project_info_1 = require("./routes/project-info");
22
26
  const redo_1 = require("./routes/redo");
23
27
  const register_client_render_1 = require("./routes/register-client-render");
24
28
  const remove_render_1 = require("./routes/remove-render");
29
+ const rename_static_file_1 = require("./routes/rename-static-file");
25
30
  const reorder_effect_1 = require("./routes/reorder-effect");
31
+ const reorder_sequence_1 = require("./routes/reorder-sequence");
26
32
  const restart_studio_1 = require("./routes/restart-studio");
27
33
  const save_effect_props_1 = require("./routes/save-effect-props");
28
34
  const save_sequence_props_1 = require("./routes/save-sequence-props");
@@ -36,6 +42,8 @@ const unsubscribe_from_file_existence_1 = require("./routes/unsubscribe-from-fil
36
42
  const unsubscribe_from_sequence_props_1 = require("./routes/unsubscribe-from-sequence-props");
37
43
  const update_available_1 = require("./routes/update-available");
38
44
  const update_default_props_1 = require("./routes/update-default-props");
45
+ const update_effect_keyframe_settings_1 = require("./routes/update-effect-keyframe-settings");
46
+ const update_sequence_keyframe_settings_1 = require("./routes/update-sequence-keyframe-settings");
39
47
  exports.allApiRoutes = {
40
48
  '/api/composition-component-info': composition_component_info_1.compositionComponentInfoHandler,
41
49
  '/api/cancel': cancel_render_1.handleCancelRender,
@@ -58,18 +66,26 @@ exports.allApiRoutes = {
58
66
  '/api/save-effect-props': save_effect_props_1.saveEffectPropsHandler,
59
67
  '/api/add-effect': add_effect_1.addEffectHandler,
60
68
  '/api/reorder-effect': reorder_effect_1.reorderEffectHandler,
69
+ '/api/reorder-sequence': reorder_sequence_1.reorderSequenceHandler,
61
70
  '/api/delete-keyframes': delete_keyframes_1.deleteKeyframesHandler,
71
+ '/api/move-keyframes': move_keyframes_1.moveKeyframesHandler,
62
72
  '/api/add-sequence-keyframe': add_sequence_keyframe_1.addSequenceKeyframeHandler,
63
73
  '/api/add-effect-keyframe': add_effect_keyframe_1.addEffectKeyframeHandler,
74
+ '/api/update-sequence-keyframe-settings': update_sequence_keyframe_settings_1.updateSequenceKeyframeSettingsHandler,
75
+ '/api/update-effect-keyframe-settings': update_effect_keyframe_settings_1.updateEffectKeyframeSettingsHandler,
64
76
  '/api/delete-effect': delete_effect_1.deleteEffectHandler,
77
+ '/api/paste-effects': paste_effects_1.pasteEffectsHandler,
65
78
  '/api/delete-jsx-node': delete_jsx_node_1.deleteJsxNodeHandler,
66
79
  '/api/duplicate-jsx-node': duplicate_jsx_node_1.duplicateJsxNodeHandler,
67
80
  '/api/update-available': update_available_1.handleUpdate,
68
81
  '/api/project-info': project_info_1.projectInfoHandler,
69
82
  '/api/delete-static-file': delete_static_file_1.deleteStaticFileHandler,
83
+ '/api/rename-static-file': rename_static_file_1.renameStaticFileHandler,
70
84
  '/api/restart-studio': restart_studio_1.handleRestartStudio,
71
85
  '/api/install-package': install_dependency_1.handleInstallPackage,
72
86
  '/api/insert-jsx-element': insert_jsx_element_1.insertJsxElementHandler,
87
+ '/api/download-remote-asset': download_remote_asset_1.downloadRemoteAssetHandler,
73
88
  '/api/undo': undo_1.undoHandler,
74
89
  '/api/redo': redo_1.redoHandler,
90
+ '/api/log-studio-error': log_studio_error_1.logStudioErrorHandler,
75
91
  };
@@ -27,6 +27,7 @@ const addEffectKeyframeHandler = ({ input: { fileName, sequenceNodePath, effectI
27
27
  input: fileContents,
28
28
  sequenceNodePath: sequenceNodePath.nodePath,
29
29
  effectIndex,
30
+ schema,
30
31
  updates: [
31
32
  {
32
33
  key,
@@ -83,6 +84,7 @@ const addEffectKeyframeHandler = ({ input: { fileName, sequenceNodePath, effectI
83
84
  };
84
85
  }
85
86
  return (0, can_update_effect_props_1.computeEffectPropStatus)({
87
+ ast,
86
88
  jsx,
87
89
  effectIndex,
88
90
  keys: (0, studio_shared_1.getAllSchemaKeys)(schema),
@@ -24,6 +24,7 @@ const addSequenceKeyframeHandler = ({ input: { fileName, nodePath, key, frame, v
24
24
  const { output, oldValueStrings, newValueStrings, formatted, logLine, updatedNodePath, } = await (0, update_keyframes_1.updateSequenceKeyframes)({
25
25
  input: fileContents,
26
26
  nodePath: nodePath.nodePath,
27
+ schema,
27
28
  updates: [
28
29
  {
29
30
  key,
@@ -37,6 +37,24 @@ const getCodemodUndoDescription = (codemod) => {
37
37
  entryType: codemod.type,
38
38
  };
39
39
  }
40
+ if (codemod.type === 'delete-folder') {
41
+ const label = `folder "${codemod.parentName ? `${codemod.parentName}/` : ''}${codemod.folderName}"`;
42
+ return {
43
+ undoMessage: `↩️ Deletion of ${label}`,
44
+ redoMessage: `↪️ Deletion of ${label}`,
45
+ entryType: codemod.type,
46
+ };
47
+ }
48
+ if (codemod.type === 'rename-folder') {
49
+ const oldName = `${codemod.parentName ? `${codemod.parentName}/` : ''}${codemod.folderName}`;
50
+ const newName = `${codemod.parentName ? `${codemod.parentName}/` : ''}${codemod.newName}`;
51
+ const label = `folder "${oldName}" to "${newName}"`;
52
+ return {
53
+ undoMessage: `↩️ Rename of ${label}`,
54
+ redoMessage: `↪️ Rename of ${label}`,
55
+ entryType: codemod.type,
56
+ };
57
+ }
40
58
  return {
41
59
  undoMessage: '↩️ Visual control change',
42
60
  redoMessage: '↪️ Visual control change',