@remotion/studio-server 4.0.517 → 4.0.518
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/preview-server/api-routes.d.ts +3 -1
- package/dist/preview-server/api-routes.js +0 -2
- package/dist/preview-server/element-install-state.d.ts +1 -1
- package/dist/preview-server/element-install-state.js +1 -1
- package/dist/preview-server/routes/update-config.d.ts +8 -3
- package/dist/preview-server/routes/update-config.js +114 -15
- package/dist/preview-server/studio-protocol/handle-discovery.js +20 -0
- package/dist/preview-server/studio-protocol/handle-element-library.d.ts +11 -0
- package/dist/preview-server/studio-protocol/handle-element-library.js +149 -0
- package/dist/routes.js +31 -1
- package/package.json +8 -8
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
import type { ApiRoutes } from '@remotion/studio-shared';
|
|
2
2
|
import type { ApiHandler } from './api-types';
|
|
3
|
+
type StandardApiRoute = Exclude<keyof ApiRoutes, '/api/update-config'>;
|
|
3
4
|
export declare const allApiRoutes: {
|
|
4
|
-
[key in
|
|
5
|
+
[key in StandardApiRoute]: ApiHandler<ApiRoutes[key]['Request'], ApiRoutes[key]['Response']>;
|
|
5
6
|
};
|
|
7
|
+
export {};
|
|
@@ -57,7 +57,6 @@ const unsubscribe_from_default_props_1 = require("./routes/unsubscribe-from-defa
|
|
|
57
57
|
const unsubscribe_from_file_existence_1 = require("./routes/unsubscribe-from-file-existence");
|
|
58
58
|
const unsubscribe_from_sequence_props_1 = require("./routes/unsubscribe-from-sequence-props");
|
|
59
59
|
const update_available_1 = require("./routes/update-available");
|
|
60
|
-
const update_config_1 = require("./routes/update-config");
|
|
61
60
|
const update_default_props_1 = require("./routes/update-default-props");
|
|
62
61
|
const update_effect_keyframe_settings_1 = require("./routes/update-effect-keyframe-settings");
|
|
63
62
|
const update_element_install_target_1 = require("./routes/update-element-install-target");
|
|
@@ -113,7 +112,6 @@ exports.allApiRoutes = {
|
|
|
113
112
|
'/api/delete-static-file': delete_static_file_1.deleteStaticFileHandler,
|
|
114
113
|
'/api/rename-static-file': rename_static_file_1.renameStaticFileHandler,
|
|
115
114
|
'/api/restart-studio': restart_studio_1.handleRestartStudio,
|
|
116
|
-
'/api/update-config': update_config_1.updateConfigHandler,
|
|
117
115
|
'/api/default-coding-agent-info': default_coding_agent_1.getDefaultCodingAgentInfoHandler,
|
|
118
116
|
'/api/default-editor-info': default_editor_1.getDefaultEditorInfoHandler,
|
|
119
117
|
'/api/install-package': install_dependency_1.handleInstallPackage,
|
|
@@ -11,7 +11,7 @@ export type ElementInstallTarget = {
|
|
|
11
11
|
studioUrl: string;
|
|
12
12
|
updatedAt: number;
|
|
13
13
|
};
|
|
14
|
-
export type StudioProtocolTargetPurpose = 'install-element' | 'set-license-key';
|
|
14
|
+
export type StudioProtocolTargetPurpose = 'install-element' | 'set-license-key' | 'add-element-library';
|
|
15
15
|
type StudioProtocolTarget = {
|
|
16
16
|
readonly id: string;
|
|
17
17
|
readonly origin: string;
|
|
@@ -77,7 +77,7 @@ const consumeStudioProtocolTarget = ({ now, origin, purpose, targetId, }) => {
|
|
|
77
77
|
current.readOnly) {
|
|
78
78
|
return null;
|
|
79
79
|
}
|
|
80
|
-
if (purpose
|
|
80
|
+
if (purpose !== 'install-element') {
|
|
81
81
|
return issued.target;
|
|
82
82
|
}
|
|
83
83
|
if (!current.canInstall ||
|
|
@@ -1,7 +1,12 @@
|
|
|
1
|
-
import { type ConfigUpdate, type UpdateConfigRequest, type UpdateConfigResponse } from '@remotion/studio-shared';
|
|
1
|
+
import { type ConfigUpdate, type StudioRuntimeConfig, type UpdateConfigRequest, type UpdateConfigResponse } from '@remotion/studio-shared';
|
|
2
2
|
import type { ApiHandler } from '../api-types';
|
|
3
|
-
export declare const updateConfigFile: ({ configContents, updates, }: {
|
|
3
|
+
export declare const updateConfigFile: ({ configContents, existingElementLibraryUrls, updates, }: {
|
|
4
4
|
readonly configContents: string;
|
|
5
|
+
readonly existingElementLibraryUrls: readonly string[];
|
|
5
6
|
readonly updates: ConfigUpdate[];
|
|
6
7
|
}) => string;
|
|
7
|
-
|
|
8
|
+
type UpdateConfigHandlerParams = Parameters<ApiHandler<UpdateConfigRequest, UpdateConfigResponse>>[0] & {
|
|
9
|
+
readonly getStudioRuntimeConfig: () => StudioRuntimeConfig;
|
|
10
|
+
};
|
|
11
|
+
export declare const updateConfigHandler: ({ input, configFile, getStudioRuntimeConfig, }: UpdateConfigHandlerParams) => Promise<UpdateConfigResponse>;
|
|
12
|
+
export {};
|
|
@@ -74,7 +74,7 @@ const validateUpdates = (updates) => {
|
|
|
74
74
|
}
|
|
75
75
|
const { setter, type } = update;
|
|
76
76
|
if (typeof setter !== 'string' ||
|
|
77
|
-
!validSetterName.test(setter) ||
|
|
77
|
+
(!validSetterName.test(setter) && setter !== 'addElementLibrary') ||
|
|
78
78
|
!(setter in studio_shared_1.configMethodLifecycles)) {
|
|
79
79
|
return `Invalid config setter: ${JSON.stringify(setter)}.`;
|
|
80
80
|
}
|
|
@@ -82,6 +82,34 @@ const validateUpdates = (updates) => {
|
|
|
82
82
|
return `The config setter ${setter} was specified more than once.`;
|
|
83
83
|
}
|
|
84
84
|
setters.add(setter);
|
|
85
|
+
if (setter === 'addElementLibrary') {
|
|
86
|
+
if (type !== 'set' ||
|
|
87
|
+
!('value' in update) ||
|
|
88
|
+
typeof update.value !== 'object' ||
|
|
89
|
+
update.value === null ||
|
|
90
|
+
Array.isArray(update.value)) {
|
|
91
|
+
return 'Config.addElementLibrary() expects an object value.';
|
|
92
|
+
}
|
|
93
|
+
const elementLibrary = update.value;
|
|
94
|
+
const { displayName, url } = elementLibrary;
|
|
95
|
+
if (typeof url !== 'string') {
|
|
96
|
+
return 'Config.addElementLibrary() expects an HTTP or HTTPS URL.';
|
|
97
|
+
}
|
|
98
|
+
try {
|
|
99
|
+
const parsedUrl = new URL(url);
|
|
100
|
+
if (parsedUrl.protocol !== 'http:' && parsedUrl.protocol !== 'https:') {
|
|
101
|
+
return 'Config.addElementLibrary() expects an HTTP or HTTPS URL.';
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
catch (_a) {
|
|
105
|
+
return 'Config.addElementLibrary() expects an HTTP or HTTPS URL.';
|
|
106
|
+
}
|
|
107
|
+
if (displayName !== undefined &&
|
|
108
|
+
(typeof displayName !== 'string' || displayName.trim() === '')) {
|
|
109
|
+
return 'Config.addElementLibrary() expects a non-empty display name.';
|
|
110
|
+
}
|
|
111
|
+
continue;
|
|
112
|
+
}
|
|
85
113
|
if (type === 'delete') {
|
|
86
114
|
continue;
|
|
87
115
|
}
|
|
@@ -93,20 +121,64 @@ const validateUpdates = (updates) => {
|
|
|
93
121
|
}
|
|
94
122
|
return null;
|
|
95
123
|
};
|
|
96
|
-
const updateConfigFile = ({ configContents, updates, }) => {
|
|
124
|
+
const updateConfigFile = ({ configContents, existingElementLibraryUrls, updates, }) => {
|
|
97
125
|
const setters = new Set(updates.map(({ setter }) => setter));
|
|
126
|
+
const elementLibraryUrls = new Set();
|
|
127
|
+
for (const url of existingElementLibraryUrls) {
|
|
128
|
+
try {
|
|
129
|
+
elementLibraryUrls.add(new URL(url).href);
|
|
130
|
+
}
|
|
131
|
+
catch (_a) {
|
|
132
|
+
// Runtime config only contains validated URLs.
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
let changed = false;
|
|
98
136
|
const ast = (0, parse_ast_1.parseAst)(configContents);
|
|
99
137
|
recast.types.visit(ast.program, {
|
|
100
138
|
visitExpressionStatement(path) {
|
|
101
139
|
const { expression } = path.node;
|
|
102
|
-
if (expression.type
|
|
103
|
-
expression.callee.type
|
|
104
|
-
|
|
105
|
-
expression.callee.object.type
|
|
106
|
-
expression.callee.object.name
|
|
107
|
-
expression.callee.property.type
|
|
108
|
-
|
|
140
|
+
if (expression.type !== 'CallExpression' ||
|
|
141
|
+
expression.callee.type !== 'MemberExpression' ||
|
|
142
|
+
expression.callee.computed ||
|
|
143
|
+
expression.callee.object.type !== 'Identifier' ||
|
|
144
|
+
expression.callee.object.name !== 'Config' ||
|
|
145
|
+
expression.callee.property.type !== 'Identifier') {
|
|
146
|
+
this.traverse(path);
|
|
147
|
+
return;
|
|
148
|
+
}
|
|
149
|
+
const setter = expression.callee.property.name;
|
|
150
|
+
if (setter === 'addElementLibrary') {
|
|
151
|
+
const argument = expression.arguments[0];
|
|
152
|
+
if ((argument === null || argument === void 0 ? void 0 : argument.type) === 'ObjectExpression') {
|
|
153
|
+
const urlProperty = argument.properties.find((property) => {
|
|
154
|
+
if (property.type !== 'ObjectProperty' || property.computed) {
|
|
155
|
+
return false;
|
|
156
|
+
}
|
|
157
|
+
return ((property.key.type === 'Identifier' &&
|
|
158
|
+
property.key.name === 'url') ||
|
|
159
|
+
(property.key.type === 'StringLiteral' &&
|
|
160
|
+
property.key.value === 'url'));
|
|
161
|
+
});
|
|
162
|
+
if ((urlProperty === null || urlProperty === void 0 ? void 0 : urlProperty.type) === 'ObjectProperty' &&
|
|
163
|
+
urlProperty.value.type === 'StringLiteral') {
|
|
164
|
+
try {
|
|
165
|
+
const parsedUrl = new URL(urlProperty.value.value);
|
|
166
|
+
if (parsedUrl.protocol === 'http:' ||
|
|
167
|
+
parsedUrl.protocol === 'https:') {
|
|
168
|
+
elementLibraryUrls.add(parsedUrl.href);
|
|
169
|
+
}
|
|
170
|
+
}
|
|
171
|
+
catch (_a) {
|
|
172
|
+
// Preserve invalid existing config without treating it as a match.
|
|
173
|
+
}
|
|
174
|
+
}
|
|
175
|
+
}
|
|
176
|
+
this.traverse(path);
|
|
177
|
+
return;
|
|
178
|
+
}
|
|
179
|
+
if (setters.has(setter)) {
|
|
109
180
|
path.prune();
|
|
181
|
+
changed = true;
|
|
110
182
|
return false;
|
|
111
183
|
}
|
|
112
184
|
this.traverse(path);
|
|
@@ -117,22 +189,41 @@ const updateConfigFile = ({ configContents, updates, }) => {
|
|
|
117
189
|
if (update.type === 'delete') {
|
|
118
190
|
continue;
|
|
119
191
|
}
|
|
120
|
-
const
|
|
192
|
+
const { setter, value: initialValue } = update;
|
|
193
|
+
let value = initialValue;
|
|
194
|
+
if (setter === 'addElementLibrary') {
|
|
195
|
+
const elementLibrary = initialValue;
|
|
196
|
+
const { displayName: rawDisplayName, url } = elementLibrary;
|
|
197
|
+
const normalizedUrl = new URL(url).href;
|
|
198
|
+
if (elementLibraryUrls.has(normalizedUrl)) {
|
|
199
|
+
continue;
|
|
200
|
+
}
|
|
201
|
+
const displayName = typeof rawDisplayName === 'string' ? rawDisplayName.trim() : null;
|
|
202
|
+
value =
|
|
203
|
+
displayName === null
|
|
204
|
+
? { url: normalizedUrl }
|
|
205
|
+
: { url: normalizedUrl, displayName };
|
|
206
|
+
elementLibraryUrls.add(normalizedUrl);
|
|
207
|
+
}
|
|
208
|
+
const serializedValue = JSON.stringify(value)
|
|
121
209
|
.replaceAll('\u2028', '\\u2028')
|
|
122
210
|
.replaceAll('\u2029', '\\u2029');
|
|
123
|
-
const statement = (0, parse_ast_1.parseAst)(`Config.${
|
|
124
|
-
.
|
|
211
|
+
const statement = (0, parse_ast_1.parseAst)(`Config.${setter}(${serializedValue});`).program
|
|
212
|
+
.body[0];
|
|
125
213
|
const separator = updatedConfig.endsWith('\n') ? '' : '\n';
|
|
126
214
|
updatedConfig += `${separator}${recast.prettyPrint(statement, {
|
|
127
215
|
lineTerminator: '\n',
|
|
128
216
|
quote: 'single',
|
|
129
217
|
useTabs: true,
|
|
130
218
|
}).code}\n`;
|
|
219
|
+
changed = true;
|
|
131
220
|
}
|
|
132
|
-
return updatedConfig;
|
|
221
|
+
return changed ? updatedConfig : configContents;
|
|
133
222
|
};
|
|
134
223
|
exports.updateConfigFile = updateConfigFile;
|
|
135
|
-
const updateConfigHandler = async ({ input, configFile }) => {
|
|
224
|
+
const updateConfigHandler = async ({ input, configFile, getStudioRuntimeConfig, }) => {
|
|
225
|
+
var _a;
|
|
226
|
+
var _b;
|
|
136
227
|
if (configFile === null || configFile === undefined) {
|
|
137
228
|
return {
|
|
138
229
|
success: false,
|
|
@@ -182,9 +273,17 @@ const updateConfigHandler = async ({ input, configFile }) => {
|
|
|
182
273
|
}
|
|
183
274
|
}
|
|
184
275
|
const configContents = (0, node_fs_1.readFileSync)(configFile, 'utf8');
|
|
276
|
+
const updatedConfig = (0, exports.updateConfigFile)({
|
|
277
|
+
configContents,
|
|
278
|
+
existingElementLibraryUrls: (_b = (_a = getStudioRuntimeConfig().elementLibraries) === null || _a === void 0 ? void 0 : _a.map(({ url }) => url)) !== null && _b !== void 0 ? _b : [],
|
|
279
|
+
updates: input.updates,
|
|
280
|
+
});
|
|
281
|
+
if (updatedConfig === configContents) {
|
|
282
|
+
return { success: true };
|
|
283
|
+
}
|
|
185
284
|
(0, file_watcher_1.writeFileAndNotifyFileWatchers)({
|
|
186
285
|
file: configFile,
|
|
187
|
-
content:
|
|
286
|
+
content: updatedConfig,
|
|
188
287
|
originatorClientId: input.clientId,
|
|
189
288
|
metadata: null,
|
|
190
289
|
});
|
|
@@ -85,6 +85,14 @@ const handleStudioProtocolDiscovery = ({ gitSource, liveEventsServer, remotionRo
|
|
|
85
85
|
purpose: 'set-license-key',
|
|
86
86
|
target,
|
|
87
87
|
});
|
|
88
|
+
const issuedElementLibraryTarget = target === null
|
|
89
|
+
? null
|
|
90
|
+
: (0, element_install_state_1.issueStudioProtocolTarget)({
|
|
91
|
+
now,
|
|
92
|
+
origin: requestOrigin,
|
|
93
|
+
purpose: 'add-element-library',
|
|
94
|
+
target,
|
|
95
|
+
});
|
|
88
96
|
response.writeHead(200, {
|
|
89
97
|
'Cache-Control': 'no-store',
|
|
90
98
|
'Content-Type': 'application/json',
|
|
@@ -120,6 +128,18 @@ const handleStudioProtocolDiscovery = ({ gitSource, liveEventsServer, remotionRo
|
|
|
120
128
|
lastFocusedAt: target.lastFocusedAt,
|
|
121
129
|
},
|
|
122
130
|
},
|
|
131
|
+
{
|
|
132
|
+
type: 'add-element-library',
|
|
133
|
+
target: issuedElementLibraryTarget === null ||
|
|
134
|
+
target === null ||
|
|
135
|
+
target.lastFocusedAt === null
|
|
136
|
+
? null
|
|
137
|
+
: {
|
|
138
|
+
id: issuedElementLibraryTarget.id,
|
|
139
|
+
expiresAt: issuedElementLibraryTarget.expiresAt,
|
|
140
|
+
lastFocusedAt: target.lastFocusedAt,
|
|
141
|
+
},
|
|
142
|
+
},
|
|
123
143
|
],
|
|
124
144
|
}));
|
|
125
145
|
resolve();
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import type { IncomingMessage, ServerResponse } from 'node:http';
|
|
2
|
+
import type { LiveEventsServer } from '../live-events';
|
|
3
|
+
type FocusStudioTab = (studioUrl: string) => void;
|
|
4
|
+
export declare const handleStudioProtocolElementLibrary: ({ configFile, focusStudioTab, liveEventsServer, request, response, }: {
|
|
5
|
+
readonly configFile: string | null;
|
|
6
|
+
readonly focusStudioTab: FocusStudioTab;
|
|
7
|
+
readonly liveEventsServer: LiveEventsServer;
|
|
8
|
+
readonly request: IncomingMessage;
|
|
9
|
+
readonly response: ServerResponse<IncomingMessage>;
|
|
10
|
+
}) => Promise<void>;
|
|
11
|
+
export {};
|
|
@@ -0,0 +1,149 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.handleStudioProtocolElementLibrary = void 0;
|
|
4
|
+
const zod_1 = require("zod");
|
|
5
|
+
const element_install_state_1 = require("../element-install-state");
|
|
6
|
+
const parse_body_1 = require("../parse-body");
|
|
7
|
+
const origin_policy_1 = require("./origin-policy");
|
|
8
|
+
const protocol_response_1 = require("./protocol-response");
|
|
9
|
+
const studioProtocolElementLibraryRequestSchema = zod_1.z.object({
|
|
10
|
+
operation: zod_1.z.literal('add-element-library'),
|
|
11
|
+
protocol: zod_1.z.literal('remotion-studio-protocol'),
|
|
12
|
+
protocolVersion: zod_1.z.literal(1),
|
|
13
|
+
targetId: zod_1.z.string().min(1),
|
|
14
|
+
url: zod_1.z.string(),
|
|
15
|
+
displayName: zod_1.z.string().nullable(),
|
|
16
|
+
});
|
|
17
|
+
const MAX_STUDIO_PROTOCOL_ELEMENT_LIBRARY_BODY_SIZE = 16 * 1024;
|
|
18
|
+
const handleStudioProtocolElementLibrary = async ({ configFile, focusStudioTab, liveEventsServer, request, response, }) => {
|
|
19
|
+
var _a;
|
|
20
|
+
var _b;
|
|
21
|
+
(0, origin_policy_1.setStudioProtocolCorsHeaders)({ request, response });
|
|
22
|
+
const requestOrigin = (0, origin_policy_1.getAllowedStudioProtocolOrigin)(request.headers.origin);
|
|
23
|
+
if (requestOrigin === null) {
|
|
24
|
+
(0, protocol_response_1.writeStudioProtocolError)({
|
|
25
|
+
code: 'unsupported-origin',
|
|
26
|
+
message: 'Origin not allowed',
|
|
27
|
+
response,
|
|
28
|
+
status: 403,
|
|
29
|
+
});
|
|
30
|
+
return;
|
|
31
|
+
}
|
|
32
|
+
if (request.method !== 'POST') {
|
|
33
|
+
(0, protocol_response_1.writeStudioProtocolError)({
|
|
34
|
+
code: 'method-not-allowed',
|
|
35
|
+
message: 'Use POST to add an Element catalog.',
|
|
36
|
+
response,
|
|
37
|
+
status: 405,
|
|
38
|
+
});
|
|
39
|
+
return;
|
|
40
|
+
}
|
|
41
|
+
let body;
|
|
42
|
+
try {
|
|
43
|
+
body = await (0, parse_body_1.parseRequestBody)(request, {
|
|
44
|
+
maxBytes: MAX_STUDIO_PROTOCOL_ELEMENT_LIBRARY_BODY_SIZE,
|
|
45
|
+
});
|
|
46
|
+
}
|
|
47
|
+
catch (error) {
|
|
48
|
+
if (error instanceof parse_body_1.RequestBodyTooLargeError) {
|
|
49
|
+
(0, protocol_response_1.writeStudioProtocolError)({
|
|
50
|
+
code: 'request-too-large',
|
|
51
|
+
message: 'The request body is too large.',
|
|
52
|
+
response,
|
|
53
|
+
status: 413,
|
|
54
|
+
});
|
|
55
|
+
return;
|
|
56
|
+
}
|
|
57
|
+
(0, protocol_response_1.writeStudioProtocolError)({
|
|
58
|
+
code: 'invalid-request',
|
|
59
|
+
message: 'The request body is not valid JSON.',
|
|
60
|
+
response,
|
|
61
|
+
status: 400,
|
|
62
|
+
});
|
|
63
|
+
return;
|
|
64
|
+
}
|
|
65
|
+
const parsedRequest = studioProtocolElementLibraryRequestSchema.safeParse(body);
|
|
66
|
+
if (!parsedRequest.success) {
|
|
67
|
+
(0, protocol_response_1.writeStudioProtocolError)({
|
|
68
|
+
code: 'unsupported-protocol',
|
|
69
|
+
message: 'Invalid Remotion Studio Protocol request.',
|
|
70
|
+
response,
|
|
71
|
+
status: 400,
|
|
72
|
+
});
|
|
73
|
+
return;
|
|
74
|
+
}
|
|
75
|
+
let normalizedUrl;
|
|
76
|
+
try {
|
|
77
|
+
const parsedUrl = new URL(parsedRequest.data.url);
|
|
78
|
+
if (parsedUrl.protocol !== 'http:' && parsedUrl.protocol !== 'https:') {
|
|
79
|
+
throw new Error('Unsupported protocol');
|
|
80
|
+
}
|
|
81
|
+
normalizedUrl = parsedUrl.href;
|
|
82
|
+
}
|
|
83
|
+
catch (_c) {
|
|
84
|
+
(0, protocol_response_1.writeStudioProtocolError)({
|
|
85
|
+
code: 'invalid-url',
|
|
86
|
+
message: 'The Element catalog URL must be an absolute HTTP or HTTPS URL.',
|
|
87
|
+
response,
|
|
88
|
+
status: 400,
|
|
89
|
+
});
|
|
90
|
+
return;
|
|
91
|
+
}
|
|
92
|
+
const displayName = (_b = (_a = parsedRequest.data.displayName) === null || _a === void 0 ? void 0 : _a.trim()) !== null && _b !== void 0 ? _b : null;
|
|
93
|
+
if (displayName === '') {
|
|
94
|
+
(0, protocol_response_1.writeStudioProtocolError)({
|
|
95
|
+
code: 'invalid-display-name',
|
|
96
|
+
message: 'The Element catalog display name must not be empty.',
|
|
97
|
+
response,
|
|
98
|
+
status: 400,
|
|
99
|
+
});
|
|
100
|
+
return;
|
|
101
|
+
}
|
|
102
|
+
const target = (0, element_install_state_1.consumeStudioProtocolTarget)({
|
|
103
|
+
now: Date.now(),
|
|
104
|
+
origin: requestOrigin,
|
|
105
|
+
purpose: 'add-element-library',
|
|
106
|
+
targetId: parsedRequest.data.targetId,
|
|
107
|
+
});
|
|
108
|
+
if (target === null) {
|
|
109
|
+
(0, protocol_response_1.writeStudioProtocolError)({
|
|
110
|
+
code: 'target-expired',
|
|
111
|
+
message: 'The selected Studio target is no longer available.',
|
|
112
|
+
response,
|
|
113
|
+
status: 409,
|
|
114
|
+
});
|
|
115
|
+
return;
|
|
116
|
+
}
|
|
117
|
+
if (configFile === null) {
|
|
118
|
+
(0, protocol_response_1.writeStudioProtocolError)({
|
|
119
|
+
code: 'no-config-file',
|
|
120
|
+
message: 'The selected Studio did not load a Remotion config file.',
|
|
121
|
+
response,
|
|
122
|
+
status: 409,
|
|
123
|
+
});
|
|
124
|
+
return;
|
|
125
|
+
}
|
|
126
|
+
const delivered = liveEventsServer.sendEventToClientId(target.clientId, {
|
|
127
|
+
type: 'element-library-add-request',
|
|
128
|
+
url: normalizedUrl,
|
|
129
|
+
displayName,
|
|
130
|
+
origin: requestOrigin,
|
|
131
|
+
});
|
|
132
|
+
if (!delivered) {
|
|
133
|
+
(0, protocol_response_1.writeStudioProtocolError)({
|
|
134
|
+
code: 'target-expired',
|
|
135
|
+
message: 'The selected Remotion Studio tab is no longer connected.',
|
|
136
|
+
response,
|
|
137
|
+
status: 409,
|
|
138
|
+
});
|
|
139
|
+
return;
|
|
140
|
+
}
|
|
141
|
+
focusStudioTab(target.studioUrl);
|
|
142
|
+
response.writeHead(200, { 'Content-Type': 'application/json' });
|
|
143
|
+
response.end(JSON.stringify({
|
|
144
|
+
protocol: 'remotion-studio-protocol',
|
|
145
|
+
protocolVersion: 1,
|
|
146
|
+
status: 'awaiting-confirmation',
|
|
147
|
+
}));
|
|
148
|
+
};
|
|
149
|
+
exports.handleStudioProtocolElementLibrary = handleStudioProtocolElementLibrary;
|
package/dist/routes.js
CHANGED
|
@@ -53,8 +53,10 @@ const handler_1 = require("./preview-server/handler");
|
|
|
53
53
|
const public_folder_1 = require("./preview-server/public-folder");
|
|
54
54
|
const app_icon_1 = require("./preview-server/routes/app-icon");
|
|
55
55
|
const open_in_editor_1 = require("./preview-server/routes/open-in-editor");
|
|
56
|
+
const update_config_1 = require("./preview-server/routes/update-config");
|
|
56
57
|
const serve_static_1 = require("./preview-server/serve-static");
|
|
57
58
|
const handle_discovery_1 = require("./preview-server/studio-protocol/handle-discovery");
|
|
59
|
+
const handle_element_library_1 = require("./preview-server/studio-protocol/handle-element-library");
|
|
58
60
|
const handle_install_1 = require("./preview-server/studio-protocol/handle-install");
|
|
59
61
|
const handle_license_key_1 = require("./preview-server/studio-protocol/handle-license-key");
|
|
60
62
|
const origin_policy_1 = require("./preview-server/studio-protocol/origin-policy");
|
|
@@ -321,7 +323,8 @@ const handleRoutes = ({ staticHash, staticHashPrefix, outputHash, outputHashPref
|
|
|
321
323
|
}
|
|
322
324
|
if (url.pathname === '/api/studio-protocol' ||
|
|
323
325
|
url.pathname === '/api/studio-protocol/install' ||
|
|
324
|
-
url.pathname === '/api/studio-protocol/license-key'
|
|
326
|
+
url.pathname === '/api/studio-protocol/license-key' ||
|
|
327
|
+
url.pathname === '/api/studio-protocol/element-library') {
|
|
325
328
|
if (request.method === 'OPTIONS') {
|
|
326
329
|
return (0, origin_policy_1.handleStudioProtocolOptions)({
|
|
327
330
|
request,
|
|
@@ -348,6 +351,17 @@ const handleRoutes = ({ staticHash, staticHashPrefix, outputHash, outputHashPref
|
|
|
348
351
|
response,
|
|
349
352
|
});
|
|
350
353
|
}
|
|
354
|
+
if (url.pathname === '/api/studio-protocol/element-library') {
|
|
355
|
+
return (0, handle_element_library_1.handleStudioProtocolElementLibrary)({
|
|
356
|
+
configFile,
|
|
357
|
+
focusStudioTab: (studioUrl) => {
|
|
358
|
+
(0, better_opn_1.focusBrowserTab)({ url: studioUrl }).catch(() => undefined);
|
|
359
|
+
},
|
|
360
|
+
liveEventsServer,
|
|
361
|
+
request,
|
|
362
|
+
response,
|
|
363
|
+
});
|
|
364
|
+
}
|
|
351
365
|
return (0, handle_install_1.handleStudioProtocolInstall)({
|
|
352
366
|
focusStudioTab: (studioUrl) => {
|
|
353
367
|
(0, better_opn_1.focusBrowserTab)({ url: studioUrl }).catch(() => undefined);
|
|
@@ -357,6 +371,22 @@ const handleRoutes = ({ staticHash, staticHashPrefix, outputHash, outputHashPref
|
|
|
357
371
|
response,
|
|
358
372
|
});
|
|
359
373
|
}
|
|
374
|
+
if (url.pathname === '/api/update-config') {
|
|
375
|
+
return (0, handler_1.handleRequest)({
|
|
376
|
+
remotionRoot,
|
|
377
|
+
entryPoint,
|
|
378
|
+
handler: (params) => (0, update_config_1.updateConfigHandler)({ ...params, getStudioRuntimeConfig }),
|
|
379
|
+
request,
|
|
380
|
+
response,
|
|
381
|
+
logLevel,
|
|
382
|
+
methods,
|
|
383
|
+
binariesDirectory,
|
|
384
|
+
publicDir,
|
|
385
|
+
configFile,
|
|
386
|
+
getDefaultCodingAgent,
|
|
387
|
+
getDefaultEditor,
|
|
388
|
+
});
|
|
389
|
+
}
|
|
360
390
|
for (const [key, value] of Object.entries(api_routes_1.allApiRoutes)) {
|
|
361
391
|
if (url.pathname === key) {
|
|
362
392
|
return (0, handler_1.handleRequest)({
|
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.518",
|
|
7
7
|
"description": "Run a Remotion Studio with a server backend",
|
|
8
8
|
"main": "dist",
|
|
9
9
|
"scripts": {
|
|
@@ -23,7 +23,7 @@
|
|
|
23
23
|
"access": "public"
|
|
24
24
|
},
|
|
25
25
|
"dependencies": {
|
|
26
|
-
"@remotion/studio-protocol": "4.0.
|
|
26
|
+
"@remotion/studio-protocol": "4.0.518",
|
|
27
27
|
"@babel/types": "7.24.0",
|
|
28
28
|
"@babel/parser": "7.24.1",
|
|
29
29
|
"@svgr/core": "8.1.0",
|
|
@@ -32,12 +32,12 @@
|
|
|
32
32
|
"semver": "7.5.3",
|
|
33
33
|
"zod": "4.4.3",
|
|
34
34
|
"prettier": "3.8.1",
|
|
35
|
-
"remotion": "4.0.
|
|
35
|
+
"remotion": "4.0.518",
|
|
36
36
|
"recast": "0.23.21",
|
|
37
|
-
"@remotion/bundler": "4.0.
|
|
38
|
-
"@remotion/renderer": "4.0.
|
|
39
|
-
"@remotion/studio-codemods": "4.0.
|
|
40
|
-
"@remotion/studio-shared": "4.0.
|
|
37
|
+
"@remotion/bundler": "4.0.518",
|
|
38
|
+
"@remotion/renderer": "4.0.518",
|
|
39
|
+
"@remotion/studio-codemods": "4.0.518",
|
|
40
|
+
"@remotion/studio-shared": "4.0.518",
|
|
41
41
|
"memfs": "3.4.3",
|
|
42
42
|
"open": "8.4.2"
|
|
43
43
|
},
|
|
@@ -45,7 +45,7 @@
|
|
|
45
45
|
"ast-types": "0.16.1",
|
|
46
46
|
"react": "19.2.3",
|
|
47
47
|
"@types/semver": "7.5.3",
|
|
48
|
-
"@remotion/eslint-config-internal": "4.0.
|
|
48
|
+
"@remotion/eslint-config-internal": "4.0.518",
|
|
49
49
|
"eslint": "9.19.0",
|
|
50
50
|
"@types/node": "20.12.14",
|
|
51
51
|
"@typescript/native-preview": "7.0.0-dev.20260217.1"
|