@remotion/studio-server 4.0.437 → 4.0.439
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/client-render-queue.js +3 -3
- package/dist/codemods/apply-visual-control.js +8 -1
- package/dist/codemods/format-inline-content.d.ts +21 -0
- package/dist/codemods/format-inline-content.js +108 -0
- package/dist/codemods/read-visual-control-values.d.ts +7 -0
- package/dist/codemods/read-visual-control-values.js +166 -0
- package/dist/codemods/update-default-props.d.ts +4 -1
- package/dist/codemods/update-default-props.js +51 -22
- package/dist/file-watcher.d.ts +24 -7
- package/dist/file-watcher.js +148 -29
- package/dist/index.d.ts +5 -2
- package/dist/index.js +3 -0
- package/dist/preview-server/api-routes.js +8 -2
- package/dist/preview-server/default-props-watchers.js +12 -17
- package/dist/preview-server/file-existence-watchers.js +3 -3
- package/dist/preview-server/hot-middleware/index.js +1 -15
- package/dist/preview-server/live-events.d.ts +6 -1
- package/dist/preview-server/live-events.js +12 -2
- package/dist/preview-server/routes/apply-codemod.js +2 -1
- package/dist/preview-server/routes/apply-visual-control-change.js +103 -5
- package/dist/preview-server/routes/can-update-default-props.d.ts +10 -3
- package/dist/preview-server/routes/can-update-default-props.js +138 -13
- package/dist/preview-server/routes/can-update-sequence-props.js +4 -0
- package/dist/preview-server/routes/log-update.d.ts +8 -0
- package/dist/preview-server/routes/log-update.js +60 -27
- package/dist/preview-server/routes/save-sequence-props.js +47 -5
- package/dist/preview-server/routes/update-default-props.js +41 -4
- package/dist/preview-server/sequence-props-watchers.js +4 -9
- package/dist/preview-server/start-server.js +15 -1
- package/dist/preview-server/undo-stack.d.ts +24 -4
- package/dist/preview-server/undo-stack.js +75 -11
- package/dist/preview-server/watch-ignore-next-change.d.ts +3 -0
- package/dist/preview-server/watch-ignore-next-change.js +12 -0
- package/dist/start-studio.js +3 -0
- package/package.json +6 -6
|
@@ -1,9 +1,17 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.logUpdate = void 0;
|
|
3
|
+
exports.logUpdate = exports.formatPropChange = exports.normalizeQuotes = exports.warnAboutPrettierOnce = void 0;
|
|
4
4
|
const renderer_1 = require("@remotion/renderer");
|
|
5
5
|
const make_link_1 = require("../../hyperlinks/make-link");
|
|
6
6
|
let warnedAboutPrettier = false;
|
|
7
|
+
const warnAboutPrettierOnce = (logLevel) => {
|
|
8
|
+
if (warnedAboutPrettier) {
|
|
9
|
+
return;
|
|
10
|
+
}
|
|
11
|
+
warnedAboutPrettier = true;
|
|
12
|
+
renderer_1.RenderInternals.Log.warn({ indent: false, logLevel }, renderer_1.RenderInternals.chalk.yellow('Could not format with Prettier. File will need to be formatted manually.'));
|
|
13
|
+
};
|
|
14
|
+
exports.warnAboutPrettierOnce = warnAboutPrettierOnce;
|
|
7
15
|
const normalizeQuotes = (str) => {
|
|
8
16
|
if (str.length >= 2 &&
|
|
9
17
|
((str.startsWith("'") && str.endsWith("'")) ||
|
|
@@ -12,45 +20,71 @@ const normalizeQuotes = (str) => {
|
|
|
12
20
|
}
|
|
13
21
|
return str;
|
|
14
22
|
};
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
23
|
+
exports.normalizeQuotes = normalizeQuotes;
|
|
24
|
+
// 24-bit ANSI helpers
|
|
25
|
+
const fg = (r, g, b, str) => `\u001b[38;2;${r};${g};${b}m${str}\u001b[39m`;
|
|
26
|
+
const bg = (r, g, b, str) => `\u001b[48;2;${r};${g};${b}m${str}\u001b[49m`;
|
|
27
|
+
// Monokai-inspired syntax colors
|
|
28
|
+
const attrName = (str) => fg(166, 226, 46, str);
|
|
29
|
+
const equals = (str) => fg(249, 38, 114, str);
|
|
30
|
+
const punctuation = (str) => fg(248, 248, 242, str);
|
|
31
|
+
const stringValue = (str) => fg(230, 219, 116, str);
|
|
32
|
+
const numberValue = (str) => fg(174, 129, 255, str);
|
|
33
|
+
const colorValue = (str) => {
|
|
34
|
+
if ((str.startsWith("'") && str.endsWith("'")) ||
|
|
35
|
+
(str.startsWith('"') && str.endsWith('"'))) {
|
|
36
|
+
return stringValue(str);
|
|
19
37
|
}
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
return renderer_1.RenderInternals.chalk.green(newValueString);
|
|
38
|
+
if (/^-?\d+(\.\d+)?$/.test(str)) {
|
|
39
|
+
return numberValue(str);
|
|
23
40
|
}
|
|
24
|
-
return
|
|
41
|
+
return punctuation(str);
|
|
42
|
+
};
|
|
43
|
+
// Subtle background tints
|
|
44
|
+
const removedBg = (str) => bg(80, 20, 20, str);
|
|
45
|
+
const addedBg = (str) => bg(30, 80, 30, str);
|
|
46
|
+
const colorEnabled = () => renderer_1.RenderInternals.chalk.enabled();
|
|
47
|
+
// Format key={value} with Monokai syntax highlighting
|
|
48
|
+
const formatSimpleProp = (key, value) => {
|
|
49
|
+
return `${attrName(key)}${equals('=')}${punctuation('{')}${colorValue(value)}${punctuation('}')}`;
|
|
50
|
+
};
|
|
51
|
+
// Format parentKey={{childKey: value}} with Monokai syntax highlighting
|
|
52
|
+
const formatNestedProp = (parentKey, childKey, value) => {
|
|
53
|
+
return `${attrName(parentKey)}${equals('=')}${punctuation('{{')}${punctuation(childKey)}${punctuation(':')} ${colorValue(value)}${punctuation('}}')}`;
|
|
25
54
|
};
|
|
26
55
|
const formatPropChange = ({ key, oldValueString, newValueString, defaultValueString, }) => {
|
|
56
|
+
if (!colorEnabled()) {
|
|
57
|
+
const dotIdx = key.indexOf('.');
|
|
58
|
+
if (dotIdx === -1) {
|
|
59
|
+
return `${key}={${oldValueString}} \u2192 ${key}={${newValueString}}`;
|
|
60
|
+
}
|
|
61
|
+
const parent = key.slice(0, dotIdx);
|
|
62
|
+
const child = key.slice(dotIdx + 1);
|
|
63
|
+
return `${parent}={{${child}: ${oldValueString}}} \u2192 ${parent}={{${child}: ${newValueString}}}`;
|
|
64
|
+
}
|
|
27
65
|
const isResetToDefault = defaultValueString !== null && newValueString === defaultValueString;
|
|
28
66
|
const isChangeFromDefault = defaultValueString !== null && oldValueString === defaultValueString;
|
|
29
|
-
const valueChange = formatValueChange({
|
|
30
|
-
oldValueString,
|
|
31
|
-
newValueString,
|
|
32
|
-
defaultValueString,
|
|
33
|
-
});
|
|
34
67
|
const dotIndex = key.indexOf('.');
|
|
35
68
|
if (dotIndex === -1) {
|
|
36
69
|
if (isResetToDefault) {
|
|
37
|
-
return
|
|
70
|
+
return removedBg(formatSimpleProp(key, oldValueString));
|
|
38
71
|
}
|
|
39
72
|
if (isChangeFromDefault) {
|
|
40
|
-
return
|
|
73
|
+
return addedBg(formatSimpleProp(key, newValueString));
|
|
41
74
|
}
|
|
42
|
-
return `${key}
|
|
75
|
+
return `${removedBg(formatSimpleProp(key, oldValueString))} \u2192 ${addedBg(formatSimpleProp(key, newValueString))}`;
|
|
43
76
|
}
|
|
44
77
|
const parentKey = key.slice(0, dotIndex);
|
|
45
78
|
const childKey = key.slice(dotIndex + 1);
|
|
46
79
|
if (isResetToDefault) {
|
|
47
|
-
return
|
|
80
|
+
return removedBg(formatNestedProp(parentKey, childKey, oldValueString));
|
|
48
81
|
}
|
|
49
82
|
if (isChangeFromDefault) {
|
|
50
|
-
return
|
|
83
|
+
return addedBg(formatNestedProp(parentKey, childKey, newValueString));
|
|
51
84
|
}
|
|
52
|
-
return `${parentKey}
|
|
85
|
+
return `${removedBg(formatNestedProp(parentKey, childKey, oldValueString))} \u2192 ${addedBg(formatNestedProp(parentKey, childKey, newValueString))}`;
|
|
53
86
|
};
|
|
87
|
+
exports.formatPropChange = formatPropChange;
|
|
54
88
|
const logUpdate = ({ absolutePath, fileRelativeToRoot, key, oldValueString, newValueString, defaultValueString, formatted, logLevel, }) => {
|
|
55
89
|
const locationLabel = `${fileRelativeToRoot}`;
|
|
56
90
|
const fileLink = (0, make_link_1.makeHyperlink)({
|
|
@@ -58,16 +92,15 @@ const logUpdate = ({ absolutePath, fileRelativeToRoot, key, oldValueString, newV
|
|
|
58
92
|
text: locationLabel,
|
|
59
93
|
fallback: locationLabel,
|
|
60
94
|
});
|
|
61
|
-
const propChange = formatPropChange({
|
|
95
|
+
const propChange = (0, exports.formatPropChange)({
|
|
62
96
|
key,
|
|
63
|
-
oldValueString: normalizeQuotes(oldValueString),
|
|
64
|
-
newValueString: normalizeQuotes(newValueString),
|
|
65
|
-
defaultValueString: defaultValueString !== null ? normalizeQuotes(defaultValueString) : null,
|
|
97
|
+
oldValueString: (0, exports.normalizeQuotes)(oldValueString),
|
|
98
|
+
newValueString: (0, exports.normalizeQuotes)(newValueString),
|
|
99
|
+
defaultValueString: defaultValueString !== null ? (0, exports.normalizeQuotes)(defaultValueString) : null,
|
|
66
100
|
});
|
|
67
101
|
renderer_1.RenderInternals.Log.info({ indent: false, logLevel }, `${renderer_1.RenderInternals.chalk.blueBright(`${fileLink}:`)} ${propChange}`);
|
|
68
|
-
if (!formatted
|
|
69
|
-
|
|
70
|
-
renderer_1.RenderInternals.Log.warn({ indent: false, logLevel }, renderer_1.RenderInternals.chalk.yellow('Could not format with Prettier. File will need to be formatted manually.'));
|
|
102
|
+
if (!formatted) {
|
|
103
|
+
(0, exports.warnAboutPrettierOnce)(logLevel);
|
|
71
104
|
}
|
|
72
105
|
};
|
|
73
106
|
exports.logUpdate = logUpdate;
|
|
@@ -6,11 +6,16 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
6
6
|
exports.saveSequencePropsHandler = void 0;
|
|
7
7
|
const node_fs_1 = require("node:fs");
|
|
8
8
|
const node_path_1 = __importDefault(require("node:path"));
|
|
9
|
+
const renderer_1 = require("@remotion/renderer");
|
|
9
10
|
const update_sequence_props_1 = require("../../codemods/update-sequence-props");
|
|
10
|
-
const
|
|
11
|
+
const file_watcher_1 = require("../../file-watcher");
|
|
12
|
+
const undo_stack_1 = require("../undo-stack");
|
|
13
|
+
const watch_ignore_next_change_1 = require("../watch-ignore-next-change");
|
|
14
|
+
const can_update_sequence_props_1 = require("./can-update-sequence-props");
|
|
11
15
|
const log_update_1 = require("./log-update");
|
|
12
|
-
const saveSequencePropsHandler = async ({ input: { fileName, nodePath, key, value, defaultValue }, remotionRoot, logLevel, }) => {
|
|
16
|
+
const saveSequencePropsHandler = async ({ input: { fileName, nodePath, key, value, defaultValue, observedKeys }, remotionRoot, logLevel, }) => {
|
|
13
17
|
try {
|
|
18
|
+
renderer_1.RenderInternals.Log.trace({ indent: false, logLevel }, `[save-sequence-props] Received request for fileName="${fileName}" key="${key}"`);
|
|
14
19
|
const absolutePath = node_path_1.default.resolve(remotionRoot, fileName);
|
|
15
20
|
const fileRelativeToRoot = node_path_1.default.relative(remotionRoot, absolutePath);
|
|
16
21
|
if (fileRelativeToRoot.startsWith('..')) {
|
|
@@ -24,28 +29,65 @@ const saveSequencePropsHandler = async ({ input: { fileName, nodePath, key, valu
|
|
|
24
29
|
value: JSON.parse(value),
|
|
25
30
|
defaultValue: defaultValue !== null ? JSON.parse(defaultValue) : null,
|
|
26
31
|
});
|
|
27
|
-
(0, hmr_suppression_1.suppressHmrForFile)(absolutePath);
|
|
28
|
-
(0, node_fs_1.writeFileSync)(absolutePath, output);
|
|
29
32
|
const newValueString = JSON.stringify(JSON.parse(value));
|
|
30
33
|
const parsedDefault = defaultValue !== null ? JSON.parse(defaultValue) : null;
|
|
34
|
+
const defaultValueString = parsedDefault !== null ? JSON.stringify(parsedDefault) : null;
|
|
35
|
+
const normalizedOld = (0, log_update_1.normalizeQuotes)(oldValueString);
|
|
36
|
+
const normalizedNew = (0, log_update_1.normalizeQuotes)(newValueString);
|
|
37
|
+
const normalizedDefault = defaultValueString !== null ? (0, log_update_1.normalizeQuotes)(defaultValueString) : null;
|
|
38
|
+
const undoPropChange = (0, log_update_1.formatPropChange)({
|
|
39
|
+
key,
|
|
40
|
+
oldValueString: normalizedNew,
|
|
41
|
+
newValueString: normalizedOld,
|
|
42
|
+
defaultValueString: normalizedDefault,
|
|
43
|
+
});
|
|
44
|
+
const redoPropChange = (0, log_update_1.formatPropChange)({
|
|
45
|
+
key,
|
|
46
|
+
oldValueString: normalizedOld,
|
|
47
|
+
newValueString: normalizedNew,
|
|
48
|
+
defaultValueString: normalizedDefault,
|
|
49
|
+
});
|
|
50
|
+
(0, undo_stack_1.pushToUndoStack)({
|
|
51
|
+
filePath: absolutePath,
|
|
52
|
+
oldContents: fileContents,
|
|
53
|
+
logLevel,
|
|
54
|
+
remotionRoot,
|
|
55
|
+
description: {
|
|
56
|
+
undoMessage: `Undid ${undoPropChange}`,
|
|
57
|
+
redoMessage: `Redid ${redoPropChange}`,
|
|
58
|
+
},
|
|
59
|
+
entryType: 'sequence-props',
|
|
60
|
+
});
|
|
61
|
+
(0, undo_stack_1.suppressUndoStackInvalidation)(absolutePath);
|
|
62
|
+
(0, watch_ignore_next_change_1.suppressBundlerUpdateForFile)(absolutePath);
|
|
63
|
+
(0, file_watcher_1.writeFileAndNotifyFileWatchers)(absolutePath, output);
|
|
31
64
|
(0, log_update_1.logUpdate)({
|
|
32
65
|
absolutePath,
|
|
33
66
|
fileRelativeToRoot,
|
|
34
67
|
key,
|
|
35
68
|
oldValueString,
|
|
36
69
|
newValueString,
|
|
37
|
-
defaultValueString
|
|
70
|
+
defaultValueString,
|
|
38
71
|
formatted,
|
|
39
72
|
logLevel,
|
|
40
73
|
});
|
|
74
|
+
(0, undo_stack_1.printUndoHint)(logLevel);
|
|
75
|
+
const newStatus = (0, can_update_sequence_props_1.computeSequencePropsStatus)({
|
|
76
|
+
fileName,
|
|
77
|
+
keys: observedKeys,
|
|
78
|
+
nodePath,
|
|
79
|
+
remotionRoot,
|
|
80
|
+
});
|
|
41
81
|
return {
|
|
42
82
|
success: true,
|
|
83
|
+
newStatus,
|
|
43
84
|
};
|
|
44
85
|
}
|
|
45
86
|
catch (err) {
|
|
46
87
|
return {
|
|
47
88
|
success: false,
|
|
48
89
|
reason: err.message,
|
|
90
|
+
stack: err.stack,
|
|
49
91
|
};
|
|
50
92
|
}
|
|
51
93
|
};
|
|
@@ -1,24 +1,61 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
2
5
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
6
|
exports.updateDefaultPropsHandler = void 0;
|
|
4
7
|
const node_fs_1 = require("node:fs");
|
|
8
|
+
const node_path_1 = __importDefault(require("node:path"));
|
|
9
|
+
const renderer_1 = require("@remotion/renderer");
|
|
5
10
|
const update_default_props_1 = require("../../codemods/update-default-props");
|
|
11
|
+
const file_watcher_1 = require("../../file-watcher");
|
|
12
|
+
const make_link_1 = require("../../hyperlinks/make-link");
|
|
6
13
|
const project_info_1 = require("../project-info");
|
|
14
|
+
const undo_stack_1 = require("../undo-stack");
|
|
15
|
+
const watch_ignore_next_change_1 = require("../watch-ignore-next-change");
|
|
7
16
|
const can_update_default_props_1 = require("./can-update-default-props");
|
|
8
|
-
const
|
|
17
|
+
const log_update_1 = require("./log-update");
|
|
18
|
+
const updateDefaultPropsHandler = async ({ input: { compositionId, defaultProps, enumPaths }, remotionRoot, entryPoint, logLevel, }) => {
|
|
9
19
|
try {
|
|
20
|
+
renderer_1.RenderInternals.Log.trace({ indent: false, logLevel }, `[update-default-props] Received request for compositionId="${compositionId}"`);
|
|
10
21
|
const projectInfo = await (0, project_info_1.getProjectInfo)(remotionRoot, entryPoint);
|
|
11
22
|
if (!projectInfo.rootFile) {
|
|
12
23
|
throw new Error('Cannot find root file in project');
|
|
13
24
|
}
|
|
14
25
|
(0, can_update_default_props_1.checkIfTypeScriptFile)(projectInfo.rootFile);
|
|
15
|
-
const
|
|
26
|
+
const fileContents = (0, node_fs_1.readFileSync)(projectInfo.rootFile, 'utf-8');
|
|
27
|
+
const { output, formatted } = await (0, update_default_props_1.updateDefaultProps)({
|
|
16
28
|
compositionId,
|
|
17
|
-
input:
|
|
29
|
+
input: fileContents,
|
|
18
30
|
newDefaultProps: JSON.parse(defaultProps),
|
|
19
31
|
enumPaths,
|
|
20
32
|
});
|
|
21
|
-
(0,
|
|
33
|
+
(0, undo_stack_1.pushToUndoStack)({
|
|
34
|
+
filePath: projectInfo.rootFile,
|
|
35
|
+
oldContents: fileContents,
|
|
36
|
+
logLevel,
|
|
37
|
+
remotionRoot,
|
|
38
|
+
description: {
|
|
39
|
+
undoMessage: `Undid default props update for "${compositionId}"`,
|
|
40
|
+
redoMessage: `Redid default props update for "${compositionId}"`,
|
|
41
|
+
},
|
|
42
|
+
entryType: 'default-props',
|
|
43
|
+
});
|
|
44
|
+
(0, undo_stack_1.suppressUndoStackInvalidation)(projectInfo.rootFile);
|
|
45
|
+
(0, watch_ignore_next_change_1.suppressBundlerUpdateForFile)(projectInfo.rootFile);
|
|
46
|
+
(0, file_watcher_1.writeFileAndNotifyFileWatchers)(projectInfo.rootFile, output);
|
|
47
|
+
const fileRelativeToRoot = node_path_1.default.relative(remotionRoot, projectInfo.rootFile);
|
|
48
|
+
const locationLabel = `${fileRelativeToRoot}`;
|
|
49
|
+
const fileLink = (0, make_link_1.makeHyperlink)({
|
|
50
|
+
url: `file://${projectInfo.rootFile}`,
|
|
51
|
+
text: locationLabel,
|
|
52
|
+
fallback: locationLabel,
|
|
53
|
+
});
|
|
54
|
+
renderer_1.RenderInternals.Log.info({ indent: false, logLevel }, `${renderer_1.RenderInternals.chalk.blueBright(`${fileLink}:`)} Updated default props for "${compositionId}"`);
|
|
55
|
+
if (!formatted) {
|
|
56
|
+
(0, log_update_1.warnAboutPrettierOnce)(logLevel);
|
|
57
|
+
}
|
|
58
|
+
(0, undo_stack_1.printUndoHint)(logLevel);
|
|
22
59
|
return {
|
|
23
60
|
success: true,
|
|
24
61
|
};
|
|
@@ -33,18 +33,13 @@ const subscribeToSequencePropsWatchers = ({ fileName, line, keys, remotionRoot,
|
|
|
33
33
|
}
|
|
34
34
|
const { unwatch } = (0, file_watcher_1.installFileWatcher)({
|
|
35
35
|
file: absolutePath,
|
|
36
|
-
onChange: (
|
|
37
|
-
if (type === 'deleted') {
|
|
36
|
+
onChange: (event) => {
|
|
37
|
+
if (event.type === 'deleted') {
|
|
38
38
|
return;
|
|
39
39
|
}
|
|
40
|
-
const result = (0, can_update_sequence_props_1.
|
|
41
|
-
fileName,
|
|
42
|
-
nodePath,
|
|
43
|
-
keys,
|
|
44
|
-
remotionRoot,
|
|
45
|
-
});
|
|
40
|
+
const result = (0, can_update_sequence_props_1.computeSequencePropsStatusFromContent)(event.content, nodePath, keys);
|
|
46
41
|
(0, live_events_1.waitForLiveEventsListener)().then((listener) => {
|
|
47
|
-
listener.
|
|
42
|
+
listener.sendEventToClientId(clientId, {
|
|
48
43
|
type: 'sequence-props-updated',
|
|
49
44
|
fileName,
|
|
50
45
|
nodePath,
|
|
@@ -12,6 +12,8 @@ const routes_1 = require("../routes");
|
|
|
12
12
|
const dev_middleware_1 = require("./dev-middleware");
|
|
13
13
|
const hot_middleware_1 = require("./hot-middleware");
|
|
14
14
|
const live_events_1 = require("./live-events");
|
|
15
|
+
const undo_stack_1 = require("./undo-stack");
|
|
16
|
+
const watch_ignore_next_change_1 = require("./watch-ignore-next-change");
|
|
15
17
|
const startServer = async (options) => {
|
|
16
18
|
var _a, _b, _c;
|
|
17
19
|
const desiredPort = (_b = (_a = options === null || options === void 0 ? void 0 : options.port) !== null && _a !== void 0 ? _a : (process.env.PORT ? Number(process.env.PORT) : undefined)) !== null && _b !== void 0 ? _b : undefined;
|
|
@@ -26,6 +28,9 @@ const startServer = async (options) => {
|
|
|
26
28
|
});
|
|
27
29
|
return detection.type === 'match' ? 'stop' : 'continue';
|
|
28
30
|
};
|
|
31
|
+
const watchIgnorePlugin = new bundler_1.WatchIgnoreNextChangePlugin((...args) => {
|
|
32
|
+
renderer_1.RenderInternals.Log.trace({ indent: false, logLevel: options.logLevel }, ...args);
|
|
33
|
+
});
|
|
29
34
|
const configArgs = {
|
|
30
35
|
entry: options.entry,
|
|
31
36
|
userDefinedComponent: options.userDefinedComponent,
|
|
@@ -40,6 +45,7 @@ const startServer = async (options) => {
|
|
|
40
45
|
poll: options.poll,
|
|
41
46
|
bufferStateDelayInMilliseconds: options.bufferStateDelayInMilliseconds,
|
|
42
47
|
askAIEnabled: options.askAIEnabled,
|
|
48
|
+
extraPlugins: [watchIgnorePlugin],
|
|
43
49
|
};
|
|
44
50
|
let compiler;
|
|
45
51
|
if (options.rspack) {
|
|
@@ -50,9 +56,17 @@ const startServer = async (options) => {
|
|
|
50
56
|
const [, webpackConf] = await bundler_1.BundlerInternals.webpackConfig(configArgs);
|
|
51
57
|
compiler = (0, bundler_1.webpack)(webpackConf);
|
|
52
58
|
}
|
|
59
|
+
(0, watch_ignore_next_change_1.setWatchIgnoreNextChangePlugin)(watchIgnorePlugin);
|
|
53
60
|
const wdmMiddleware = (0, dev_middleware_1.wdm)(compiler, options.logLevel);
|
|
54
61
|
const whm = (0, hot_middleware_1.webpackHotMiddleware)(compiler, options.logLevel);
|
|
55
|
-
const liveEventsServer = (0, live_events_1.makeLiveEventsRouter)(options.logLevel)
|
|
62
|
+
const liveEventsServer = (0, live_events_1.makeLiveEventsRouter)(options.logLevel, () => {
|
|
63
|
+
const undoStack = (0, undo_stack_1.getUndoStack)();
|
|
64
|
+
const redoStack = (0, undo_stack_1.getRedoStack)();
|
|
65
|
+
return {
|
|
66
|
+
undoFile: undoStack.length > 0 ? undoStack[undoStack.length - 1].filePath : null,
|
|
67
|
+
redoFile: redoStack.length > 0 ? redoStack[redoStack.length - 1].filePath : null,
|
|
68
|
+
};
|
|
69
|
+
});
|
|
56
70
|
const server = node_http_1.default.createServer((request, response) => {
|
|
57
71
|
if (options.enableCrossSiteIsolation) {
|
|
58
72
|
response.setHeader('Cross-Origin-Opener-Policy', 'same-origin');
|
|
@@ -1,10 +1,30 @@
|
|
|
1
1
|
import type { LogLevel } from '@remotion/renderer';
|
|
2
|
-
interface
|
|
2
|
+
export interface UndoEntryDescription {
|
|
3
|
+
undoMessage: string;
|
|
4
|
+
redoMessage: string;
|
|
5
|
+
}
|
|
6
|
+
type UndoEntryType = 'visual-control' | 'default-props' | 'sequence-props';
|
|
7
|
+
type UndoEntry = {
|
|
3
8
|
filePath: string;
|
|
4
9
|
oldContents: string;
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
10
|
+
description: UndoEntryDescription;
|
|
11
|
+
} & ({
|
|
12
|
+
entryType: 'visual-control';
|
|
13
|
+
} | {
|
|
14
|
+
entryType: 'default-props';
|
|
15
|
+
} | {
|
|
16
|
+
entryType: 'sequence-props';
|
|
17
|
+
});
|
|
18
|
+
export declare function pushToUndoStack({ filePath, oldContents, logLevel, remotionRoot, description, entryType }: {
|
|
19
|
+
filePath: string;
|
|
20
|
+
oldContents: string;
|
|
21
|
+
logLevel: LogLevel;
|
|
22
|
+
remotionRoot: string;
|
|
23
|
+
description: UndoEntryDescription;
|
|
24
|
+
entryType: UndoEntryType;
|
|
25
|
+
}): void;
|
|
26
|
+
export declare function printUndoHint(logLevel: LogLevel): void;
|
|
27
|
+
export declare function pushToRedoStack(filePath: string, oldContents: string, description: UndoEntryDescription, entryType: UndoEntryType): void;
|
|
8
28
|
export declare function suppressUndoStackInvalidation(filePath: string): void;
|
|
9
29
|
export declare function popUndo(): {
|
|
10
30
|
success: true;
|
|
@@ -1,6 +1,10 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
2
5
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
6
|
exports.pushToUndoStack = pushToUndoStack;
|
|
7
|
+
exports.printUndoHint = printUndoHint;
|
|
4
8
|
exports.pushToRedoStack = pushToRedoStack;
|
|
5
9
|
exports.suppressUndoStackInvalidation = suppressUndoStackInvalidation;
|
|
6
10
|
exports.popUndo = popUndo;
|
|
@@ -8,16 +12,22 @@ exports.popRedo = popRedo;
|
|
|
8
12
|
exports.getUndoStack = getUndoStack;
|
|
9
13
|
exports.getRedoStack = getRedoStack;
|
|
10
14
|
const node_fs_1 = require("node:fs");
|
|
15
|
+
const node_path_1 = __importDefault(require("node:path"));
|
|
11
16
|
const renderer_1 = require("@remotion/renderer");
|
|
17
|
+
const parse_ast_1 = require("../codemods/parse-ast");
|
|
18
|
+
const read_visual_control_values_1 = require("../codemods/read-visual-control-values");
|
|
12
19
|
const file_watcher_1 = require("../file-watcher");
|
|
13
|
-
const
|
|
20
|
+
const make_link_1 = require("../hyperlinks/make-link");
|
|
14
21
|
const live_events_1 = require("./live-events");
|
|
22
|
+
const watch_ignore_next_change_1 = require("./watch-ignore-next-change");
|
|
15
23
|
const MAX_ENTRIES = 100;
|
|
16
24
|
const undoStack = [];
|
|
17
25
|
const redoStack = [];
|
|
18
26
|
const suppressedWrites = new Map();
|
|
19
27
|
const watchers = new Map();
|
|
20
28
|
let storedLogLevel = 'info';
|
|
29
|
+
let storedRemotionRoot = null;
|
|
30
|
+
let printedUndoHint = false;
|
|
21
31
|
function broadcastState() {
|
|
22
32
|
const undoFile = undoStack.length > 0 ? undoStack[undoStack.length - 1].filePath : null;
|
|
23
33
|
const redoFile = redoStack.length > 0 ? redoStack[redoStack.length - 1].filePath : null;
|
|
@@ -29,9 +39,10 @@ function broadcastState() {
|
|
|
29
39
|
});
|
|
30
40
|
});
|
|
31
41
|
}
|
|
32
|
-
function pushToUndoStack(filePath, oldContents, logLevel) {
|
|
42
|
+
function pushToUndoStack({ filePath, oldContents, logLevel, remotionRoot, description, entryType, }) {
|
|
33
43
|
storedLogLevel = logLevel;
|
|
34
|
-
|
|
44
|
+
storedRemotionRoot = remotionRoot;
|
|
45
|
+
undoStack.push({ filePath, oldContents, description, entryType });
|
|
35
46
|
if (undoStack.length > MAX_ENTRIES) {
|
|
36
47
|
undoStack.shift();
|
|
37
48
|
}
|
|
@@ -40,8 +51,15 @@ function pushToUndoStack(filePath, oldContents, logLevel) {
|
|
|
40
51
|
ensureWatching(filePath);
|
|
41
52
|
broadcastState();
|
|
42
53
|
}
|
|
43
|
-
function
|
|
44
|
-
|
|
54
|
+
function printUndoHint(logLevel) {
|
|
55
|
+
if (!printedUndoHint) {
|
|
56
|
+
printedUndoHint = true;
|
|
57
|
+
const shortcut = process.platform === 'darwin' ? 'Cmd+Z' : 'Ctrl+Z';
|
|
58
|
+
renderer_1.RenderInternals.Log.info({ indent: false, logLevel }, renderer_1.RenderInternals.chalk.gray(`Tip: ${shortcut} in Studio to undo`));
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
function pushToRedoStack(filePath, oldContents, description, entryType) {
|
|
62
|
+
redoStack.push({ filePath, oldContents, description, entryType });
|
|
45
63
|
if (redoStack.length > MAX_ENTRIES) {
|
|
46
64
|
redoStack.shift();
|
|
47
65
|
}
|
|
@@ -121,17 +139,54 @@ function cleanupWatchers() {
|
|
|
121
139
|
}
|
|
122
140
|
}
|
|
123
141
|
}
|
|
142
|
+
function emitVisualControlChanges(fileContents) {
|
|
143
|
+
try {
|
|
144
|
+
const ast = (0, parse_ast_1.parseAst)(fileContents);
|
|
145
|
+
const values = (0, read_visual_control_values_1.readVisualControlValues)(ast);
|
|
146
|
+
if (values.length > 0) {
|
|
147
|
+
(0, live_events_1.waitForLiveEventsListener)().then((listener) => {
|
|
148
|
+
listener.sendEventToClient({
|
|
149
|
+
type: 'visual-control-values-changed',
|
|
150
|
+
values,
|
|
151
|
+
});
|
|
152
|
+
});
|
|
153
|
+
}
|
|
154
|
+
}
|
|
155
|
+
catch (_a) {
|
|
156
|
+
// File might not contain visual controls or might not be parseable
|
|
157
|
+
}
|
|
158
|
+
}
|
|
159
|
+
function logFileAction(action, filePath) {
|
|
160
|
+
const locationLabel = storedRemotionRoot
|
|
161
|
+
? node_path_1.default.relative(storedRemotionRoot, filePath)
|
|
162
|
+
: filePath;
|
|
163
|
+
const fileLink = (0, make_link_1.makeHyperlink)({
|
|
164
|
+
url: `file://${filePath}`,
|
|
165
|
+
text: locationLabel,
|
|
166
|
+
fallback: locationLabel,
|
|
167
|
+
});
|
|
168
|
+
renderer_1.RenderInternals.Log.info({ indent: false, logLevel: storedLogLevel }, `${renderer_1.RenderInternals.chalk.blueBright(`${fileLink}:`)} ${action}`);
|
|
169
|
+
}
|
|
124
170
|
function popUndo() {
|
|
125
171
|
const entry = undoStack.pop();
|
|
126
172
|
if (!entry) {
|
|
127
173
|
return { success: false, reason: 'Nothing to undo' };
|
|
128
174
|
}
|
|
129
175
|
const currentContents = (0, node_fs_1.readFileSync)(entry.filePath, 'utf-8');
|
|
130
|
-
redoStack.push({
|
|
176
|
+
redoStack.push({
|
|
177
|
+
filePath: entry.filePath,
|
|
178
|
+
oldContents: currentContents,
|
|
179
|
+
description: entry.description,
|
|
180
|
+
entryType: entry.entryType,
|
|
181
|
+
});
|
|
131
182
|
suppressUndoStackInvalidation(entry.filePath);
|
|
132
|
-
(0,
|
|
133
|
-
(0,
|
|
183
|
+
(0, watch_ignore_next_change_1.suppressBundlerUpdateForFile)(entry.filePath);
|
|
184
|
+
(0, file_watcher_1.writeFileAndNotifyFileWatchers)(entry.filePath, entry.oldContents);
|
|
134
185
|
renderer_1.RenderInternals.Log.verbose({ indent: false, logLevel: storedLogLevel }, renderer_1.RenderInternals.chalk.gray(`Undo: restored ${entry.filePath} (undo: ${undoStack.length}, redo: ${redoStack.length})`));
|
|
186
|
+
logFileAction(entry.description.undoMessage, entry.filePath);
|
|
187
|
+
if (entry.entryType === 'visual-control') {
|
|
188
|
+
emitVisualControlChanges(entry.oldContents);
|
|
189
|
+
}
|
|
135
190
|
ensureWatching(entry.filePath);
|
|
136
191
|
broadcastState();
|
|
137
192
|
return { success: true };
|
|
@@ -142,11 +197,20 @@ function popRedo() {
|
|
|
142
197
|
return { success: false, reason: 'Nothing to redo' };
|
|
143
198
|
}
|
|
144
199
|
const currentContents = (0, node_fs_1.readFileSync)(entry.filePath, 'utf-8');
|
|
145
|
-
undoStack.push({
|
|
200
|
+
undoStack.push({
|
|
201
|
+
filePath: entry.filePath,
|
|
202
|
+
oldContents: currentContents,
|
|
203
|
+
description: entry.description,
|
|
204
|
+
entryType: entry.entryType,
|
|
205
|
+
});
|
|
146
206
|
suppressUndoStackInvalidation(entry.filePath);
|
|
147
|
-
(0,
|
|
148
|
-
(0,
|
|
207
|
+
(0, watch_ignore_next_change_1.suppressBundlerUpdateForFile)(entry.filePath);
|
|
208
|
+
(0, file_watcher_1.writeFileAndNotifyFileWatchers)(entry.filePath, entry.oldContents);
|
|
149
209
|
renderer_1.RenderInternals.Log.verbose({ indent: false, logLevel: storedLogLevel }, renderer_1.RenderInternals.chalk.gray(`Redo: restored ${entry.filePath} (undo: ${undoStack.length}, redo: ${redoStack.length})`));
|
|
210
|
+
logFileAction(entry.description.redoMessage, entry.filePath);
|
|
211
|
+
if (entry.entryType === 'visual-control') {
|
|
212
|
+
emitVisualControlChanges(entry.oldContents);
|
|
213
|
+
}
|
|
150
214
|
ensureWatching(entry.filePath);
|
|
151
215
|
broadcastState();
|
|
152
216
|
return { success: true };
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.suppressBundlerUpdateForFile = exports.setWatchIgnoreNextChangePlugin = void 0;
|
|
4
|
+
let currentPlugin = null;
|
|
5
|
+
const setWatchIgnoreNextChangePlugin = (plugin) => {
|
|
6
|
+
currentPlugin = plugin;
|
|
7
|
+
};
|
|
8
|
+
exports.setWatchIgnoreNextChangePlugin = setWatchIgnoreNextChangePlugin;
|
|
9
|
+
const suppressBundlerUpdateForFile = (absolutePath) => {
|
|
10
|
+
currentPlugin === null || currentPlugin === void 0 ? void 0 : currentPlugin.ignoreNextChange(absolutePath);
|
|
11
|
+
};
|
|
12
|
+
exports.suppressBundlerUpdateForFile = suppressBundlerUpdateForFile;
|
package/dist/start-studio.js
CHANGED
|
@@ -8,6 +8,7 @@ const node_crypto_1 = __importDefault(require("node:crypto"));
|
|
|
8
8
|
const node_fs_1 = require("node:fs");
|
|
9
9
|
const node_path_1 = __importDefault(require("node:path"));
|
|
10
10
|
const renderer_1 = require("@remotion/renderer");
|
|
11
|
+
const file_watcher_1 = require("./file-watcher");
|
|
11
12
|
const get_network_address_1 = require("./get-network-address");
|
|
12
13
|
const maybe_open_browser_1 = require("./maybe-open-browser");
|
|
13
14
|
const close_and_restart_1 = require("./preview-server/close-and-restart");
|
|
@@ -30,6 +31,8 @@ const startStudio = async ({ browserArgs, browserFlag, shouldOpenBrowser, fullEn
|
|
|
30
31
|
}
|
|
31
32
|
}
|
|
32
33
|
catch (_a) { }
|
|
34
|
+
// Validate that the file watcher registry has been initialized
|
|
35
|
+
(0, file_watcher_1.getFileWatcherRegistry)();
|
|
33
36
|
(0, watch_root_file_1.watchRootFile)(remotionRoot, previewEntry);
|
|
34
37
|
const publicDir = (0, get_absolute_public_dir_1.getAbsolutePublicDir)({
|
|
35
38
|
relativePublicDir,
|
package/package.json
CHANGED
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
"url": "https://github.com/remotion-dev/remotion/tree/main/packages/studio-server"
|
|
4
4
|
},
|
|
5
5
|
"name": "@remotion/studio-server",
|
|
6
|
-
"version": "4.0.
|
|
6
|
+
"version": "4.0.439",
|
|
7
7
|
"description": "Run a Remotion Studio with a server backend",
|
|
8
8
|
"main": "dist",
|
|
9
9
|
"sideEffects": false,
|
|
@@ -27,11 +27,11 @@
|
|
|
27
27
|
"@babel/parser": "7.24.1",
|
|
28
28
|
"semver": "7.5.3",
|
|
29
29
|
"prettier": "3.8.1",
|
|
30
|
-
"remotion": "4.0.
|
|
30
|
+
"remotion": "4.0.439",
|
|
31
31
|
"recast": "0.23.11",
|
|
32
|
-
"@remotion/bundler": "4.0.
|
|
33
|
-
"@remotion/renderer": "4.0.
|
|
34
|
-
"@remotion/studio-shared": "4.0.
|
|
32
|
+
"@remotion/bundler": "4.0.439",
|
|
33
|
+
"@remotion/renderer": "4.0.439",
|
|
34
|
+
"@remotion/studio-shared": "4.0.439",
|
|
35
35
|
"memfs": "3.4.3",
|
|
36
36
|
"source-map": "0.7.3",
|
|
37
37
|
"open": "^8.4.2"
|
|
@@ -41,7 +41,7 @@
|
|
|
41
41
|
"react": "19.2.3",
|
|
42
42
|
"@babel/types": "7.24.0",
|
|
43
43
|
"@types/semver": "^7.3.4",
|
|
44
|
-
"@remotion/eslint-config-internal": "4.0.
|
|
44
|
+
"@remotion/eslint-config-internal": "4.0.439",
|
|
45
45
|
"eslint": "9.19.0",
|
|
46
46
|
"@types/node": "20.12.14",
|
|
47
47
|
"@typescript/native-preview": "7.0.0-dev.20260217.1"
|