@lvce-editor/shared-process 0.33.4 → 0.33.5
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/package.json +5 -5
- package/src/parts/ContentSecurityPolicyDocument/ContentSecurityPolicyDocument.js +24 -11
- package/src/parts/GetElectronFileResponse/GetElectronFileResponse.js +14 -6
- package/src/parts/GetElectronFileResponseAbsolutePath/GetElectronFileResponseAbsolutePath.js +5 -0
- package/src/parts/GetElectronFileResponseRelativePath/GetElectronFileResponseRelativePath.js +21 -3
- package/src/parts/GetGitpodPreviewUrl/GetGitpodPreviewUrl.js +6 -0
- package/src/parts/LaunchPreviewProcess/LaunchPreviewProcess.js +8 -1
- package/src/parts/ModuleMap/ModuleMap.js +2 -0
- package/src/parts/Platform/Platform.js +3 -3
- package/src/parts/PreviewProcess/PreviewProcess.js +4 -0
- package/src/parts/Scheme/Scheme.js +1 -0
- package/src/parts/WebViewServer/WebViewServer.ipc.js +2 -0
- package/src/parts/WebViewServer/WebViewServer.js +23 -4
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@lvce-editor/shared-process",
|
|
3
|
-
"version": "0.33.
|
|
3
|
+
"version": "0.33.5",
|
|
4
4
|
"main": "index.js",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"keywords": [
|
|
@@ -17,9 +17,9 @@
|
|
|
17
17
|
"node": ">=18"
|
|
18
18
|
},
|
|
19
19
|
"dependencies": {
|
|
20
|
-
"@lvce-editor/assert": "^1.
|
|
21
|
-
"@lvce-editor/extension-host-helper-process": "0.33.
|
|
22
|
-
"@lvce-editor/ipc": "^10.
|
|
20
|
+
"@lvce-editor/assert": "^1.3.0",
|
|
21
|
+
"@lvce-editor/extension-host-helper-process": "0.33.5",
|
|
22
|
+
"@lvce-editor/ipc": "^10.2.1",
|
|
23
23
|
"@lvce-editor/json-rpc": "^3.0.0",
|
|
24
24
|
"@lvce-editor/jsonc-parser": "^1.4.0",
|
|
25
25
|
"@lvce-editor/pretty-error": "^1.6.0",
|
|
@@ -35,7 +35,7 @@
|
|
|
35
35
|
"@lvce-editor/typescript-compile-process": "^1.2.0",
|
|
36
36
|
"@lvce-editor/pty-host": "^2.0.0",
|
|
37
37
|
"@lvce-editor/embeds-process": "^1.5.0",
|
|
38
|
-
"@lvce-editor/preview-process": "^
|
|
38
|
+
"@lvce-editor/preview-process": "^2.7.0",
|
|
39
39
|
"open": "^10.1.0",
|
|
40
40
|
"tail": "^2.2.6",
|
|
41
41
|
"tmp-promise": "^3.0.3",
|
|
@@ -1,22 +1,35 @@
|
|
|
1
1
|
import * as GetContentSecurityPolicy from '../GetContentSecurityPolicy/GetContentSecurityPolicy.js';
|
|
2
|
+
import * as GetGitpodPreviewUrl from '../GetGitpodPreviewUrl/GetGitpodPreviewUrl.js';
|
|
2
3
|
import * as IsElectron from '../IsElectron/IsElectron.js';
|
|
3
4
|
import * as IsGitpod from '../IsGitpod/IsGitpod.js';
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
5
|
+
import * as Scheme from '../Scheme/Scheme.js';
|
|
6
|
+
const getFrameSrc = () => {
|
|
7
|
+
// TODO make ports configurable
|
|
8
|
+
if (IsGitpod.isGitpod) {
|
|
9
|
+
return [`frame-src 'self' ${GetGitpodPreviewUrl.getGitpodPreviewUrl(3001)} ${GetGitpodPreviewUrl.getGitpodPreviewUrl(3002)}`];
|
|
10
|
+
}
|
|
11
|
+
if (IsElectron.isElectron) {
|
|
12
|
+
return [`frame-src ${Scheme.WebView}:`];
|
|
13
|
+
}
|
|
14
|
+
return [`frame-src 'self' http://localhost:3001 http://localhost:3002`];
|
|
15
|
+
};
|
|
16
|
+
const getManifestSrc = () => {
|
|
17
|
+
if (IsElectron.isElectron) {
|
|
18
|
+
return [];
|
|
19
|
+
}
|
|
20
|
+
return [`manifest-src 'self'`];
|
|
21
|
+
};
|
|
22
|
+
const getFrameAncestors = () => {
|
|
23
|
+
return [`frame-ancestors 'none'`];
|
|
9
24
|
};
|
|
10
25
|
export const value = GetContentSecurityPolicy.getContentSecurityPolicy([
|
|
11
26
|
`default-src 'none'`,
|
|
12
27
|
`font-src 'self'`,
|
|
13
|
-
`img-src 'self' https: data:`,
|
|
28
|
+
`img-src 'self' https: data:`, // TODO maybe disallow https and data images
|
|
14
29
|
`media-src 'self'`,
|
|
15
30
|
`script-src 'self'`,
|
|
16
31
|
`style-src 'self'`,
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
: `frame-src 'self' http://localhost:3001 http://localhost:3002`,
|
|
21
|
-
...(IsElectron.isElectron ? [] : [`manifest-src 'self'`]),
|
|
32
|
+
...getFrameAncestors(),
|
|
33
|
+
...getFrameSrc(),
|
|
34
|
+
...getManifestSrc(),
|
|
22
35
|
]);
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { stat } from 'fs/promises';
|
|
1
|
+
import { stat } from 'node:fs/promises';
|
|
2
2
|
import * as GetElectronFileResponseAbsolutePath from '../GetElectronFileResponseAbsolutePath/GetElectronFileResponseAbsolutePath.js';
|
|
3
3
|
import * as GetElectronFileResponseContent from '../GetElectronFileResponseContent/GetElectronFileResponseContent.js';
|
|
4
4
|
import * as GetElectronFileResponseRelativePath from '../GetElectronFileResponseRelativePath/GetElectronFileResponseRelativePath.js';
|
|
@@ -7,27 +7,35 @@ import * as GetHeaders from '../GetHeaders/GetHeaders.js';
|
|
|
7
7
|
import * as GetNotFoundResponse from '../GetNotFoundResponse/GetNotFoundResponse.js';
|
|
8
8
|
import * as GetNotModifiedResponse from '../GetNotModifiedResponse/GetNotModifiedResponse.js';
|
|
9
9
|
import * as GetServerErrorResponse from '../GetServerErrorResponse/GetServerErrorResponse.js';
|
|
10
|
+
import * as HttpHeader from '../HttpHeader/HttpHeader.js';
|
|
10
11
|
import * as HttpStatusCode from '../HttpStatusCode/HttpStatusCode.js';
|
|
11
12
|
import * as IsEnoentError from '../IsEnoentError/IsEnoentError.js';
|
|
12
13
|
import * as Logger from '../Logger/Logger.js';
|
|
14
|
+
// TODO maybe handle app responses and webview responses separately
|
|
15
|
+
// maybe send webview requests directly to preview process
|
|
13
16
|
export const getElectronFileResponse = async (url, request) => {
|
|
14
17
|
try {
|
|
15
18
|
const pathName = GetElectronFileResponseRelativePath.getElectronFileResponseRelativePath(url);
|
|
16
|
-
|
|
19
|
+
let absolutePath = GetElectronFileResponseAbsolutePath.getElectronFileResponseAbsolutePath(pathName);
|
|
17
20
|
let etag;
|
|
21
|
+
// TODO when is there no request?
|
|
18
22
|
if (request) {
|
|
19
|
-
|
|
23
|
+
let stats = await stat(absolutePath);
|
|
24
|
+
if (stats.isDirectory()) {
|
|
25
|
+
absolutePath += '/index.html';
|
|
26
|
+
stats = await stat(absolutePath);
|
|
27
|
+
}
|
|
20
28
|
etag = GetEtag.getEtag(stats);
|
|
21
|
-
if (request.headers[
|
|
29
|
+
if (request.headers[HttpHeader.IfNotMatch] === etag) {
|
|
22
30
|
const headers = GetHeaders.getHeaders(absolutePath, pathName);
|
|
23
31
|
return GetNotModifiedResponse.getNotModifiedResponse(headers);
|
|
24
32
|
}
|
|
25
33
|
}
|
|
26
34
|
const content = await GetElectronFileResponseContent.getElectronFileResponseContent(request, absolutePath, url);
|
|
27
35
|
const headers = GetHeaders.getHeaders(absolutePath, pathName);
|
|
28
|
-
headers[
|
|
36
|
+
headers[HttpHeader.CacheControl] = 'public, max-age=0, must-revalidate';
|
|
29
37
|
if (etag) {
|
|
30
|
-
headers[
|
|
38
|
+
headers[HttpHeader.Etag] = etag;
|
|
31
39
|
}
|
|
32
40
|
return {
|
|
33
41
|
body: content,
|
package/src/parts/GetElectronFileResponseAbsolutePath/GetElectronFileResponseAbsolutePath.js
CHANGED
|
@@ -4,6 +4,7 @@ import { fileURLToPath } from 'node:url';
|
|
|
4
4
|
import * as Path from '../Path/Path.js';
|
|
5
5
|
import * as Platform from '../Platform/Platform.js';
|
|
6
6
|
import * as Root from '../Root/Root.js';
|
|
7
|
+
// TODO clean up this code
|
|
7
8
|
export const getElectronFileResponseAbsolutePath = (pathName) => {
|
|
8
9
|
// TODO remove if/else in prod (use replacement)
|
|
9
10
|
if (pathName === `/` || pathName.startsWith(`/?`)) {
|
|
@@ -30,5 +31,9 @@ export const getElectronFileResponseAbsolutePath = (pathName) => {
|
|
|
30
31
|
const processExplorerThemeCss = join(tmpdir(), 'process-explorer-theme.css');
|
|
31
32
|
return processExplorerThemeCss;
|
|
32
33
|
}
|
|
34
|
+
// TODO move this to preview process
|
|
35
|
+
if (pathName.startsWith('/home')) {
|
|
36
|
+
return pathName;
|
|
37
|
+
}
|
|
33
38
|
return Path.join(Root.root, 'static', pathName);
|
|
34
39
|
};
|
package/src/parts/GetElectronFileResponseRelativePath/GetElectronFileResponseRelativePath.js
CHANGED
|
@@ -1,12 +1,30 @@
|
|
|
1
1
|
import * as Platform from '../Platform/Platform.js';
|
|
2
|
+
import * as Scheme from '../Scheme/Scheme.js';
|
|
2
3
|
const { scheme } = Platform;
|
|
3
4
|
const prefix = `${scheme}://-`;
|
|
4
5
|
const prefixLength = prefix.length;
|
|
6
|
+
const webViewPrefix = `${Scheme.WebView}://-`;
|
|
7
|
+
const webViewPrefixLength = webViewPrefix.length;
|
|
5
8
|
export const getElectronFileResponseRelativePath = (requestUrl) => {
|
|
9
|
+
if (requestUrl.startsWith(prefix)) {
|
|
10
|
+
// TODO only support reading from app root and extensions
|
|
11
|
+
// maybe add a separate protocol for extensions (e.g. lvce-remote)
|
|
12
|
+
const decoded = decodeURI(requestUrl);
|
|
13
|
+
const pathName = decoded.slice(prefixLength);
|
|
14
|
+
return pathName;
|
|
15
|
+
}
|
|
16
|
+
if (requestUrl.startsWith(webViewPrefix)) {
|
|
17
|
+
// TODO group this by extension so that
|
|
18
|
+
// extension-a can only access resources in extension-a folder and
|
|
19
|
+
// extension-b can only access resources in extension-b folder
|
|
20
|
+
const decoded = decodeURI(requestUrl);
|
|
21
|
+
const pathName = decoded.slice(webViewPrefixLength);
|
|
22
|
+
return pathName;
|
|
23
|
+
}
|
|
6
24
|
if (requestUrl.startsWith('/')) {
|
|
25
|
+
// TODO this should not be supported anymore and could probably be removed
|
|
7
26
|
return requestUrl;
|
|
8
27
|
}
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
return pathName;
|
|
28
|
+
console.log({ requestUrl });
|
|
29
|
+
return '';
|
|
12
30
|
};
|
|
@@ -1,9 +1,16 @@
|
|
|
1
1
|
import * as HandleIpc from '../HandleIpc/HandleIpc.js';
|
|
2
2
|
import * as IpcParent from '../IpcParent/IpcParent.js';
|
|
3
3
|
import * as IpcParentType from '../IpcParentType/IpcParentType.js';
|
|
4
|
+
import * as IsElectron from '../IsElectron/IsElectron.js';
|
|
4
5
|
import * as PreviewProcessPath from '../PreviewProcessPath/PreviewProcessPath.js';
|
|
6
|
+
const getMethod = (isElectron) => {
|
|
7
|
+
if (isElectron) {
|
|
8
|
+
return IpcParentType.ElectronUtilityProcess;
|
|
9
|
+
}
|
|
10
|
+
return IpcParentType.NodeForkedProcess;
|
|
11
|
+
};
|
|
5
12
|
export const launchPreviewProcess = async () => {
|
|
6
|
-
const method =
|
|
13
|
+
const method = getMethod(IsElectron.isElectron);
|
|
7
14
|
const previewProcess = await IpcParent.create({
|
|
8
15
|
method,
|
|
9
16
|
path: PreviewProcessPath.previewProcessPath,
|
|
@@ -279,8 +279,10 @@ export const getModuleId = (commandId) => {
|
|
|
279
279
|
return ModuleId.FileWatcher;
|
|
280
280
|
case 'Transferrable.transfer':
|
|
281
281
|
return ModuleId.Transferrable;
|
|
282
|
+
case 'WebViewServer.create':
|
|
282
283
|
case 'WebViewServer.start':
|
|
283
284
|
case 'WebViewServer.setHandler':
|
|
285
|
+
case 'WebViewServer.registerProtocol':
|
|
284
286
|
return ModuleId.WebViewServer;
|
|
285
287
|
default:
|
|
286
288
|
throw new CommandNotFoundError(commandId);
|
|
@@ -41,9 +41,9 @@ export const getAppImageName = () => {
|
|
|
41
41
|
export const getSetupName = () => {
|
|
42
42
|
return 'Lvce-Setup';
|
|
43
43
|
};
|
|
44
|
-
export const version = '0.33.
|
|
45
|
-
export const commit = '
|
|
46
|
-
export const date = '2024-
|
|
44
|
+
export const version = '0.33.5';
|
|
45
|
+
export const commit = 'aee872d';
|
|
46
|
+
export const date = '2024-09-01T07:12:00.000Z';
|
|
47
47
|
export const getVersion = () => {
|
|
48
48
|
return version;
|
|
49
49
|
};
|
|
@@ -16,3 +16,7 @@ export const invoke = async (method, ...params) => {
|
|
|
16
16
|
const ipc = await getOrCreate();
|
|
17
17
|
return JsonRpc.invoke(ipc, method, ...params);
|
|
18
18
|
};
|
|
19
|
+
export const invokeAndTransfer = async (method, ...params) => {
|
|
20
|
+
const ipc = await getOrCreate();
|
|
21
|
+
return JsonRpc.invokeAndTransfer(ipc, method, ...params);
|
|
22
|
+
};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export const WebView = 'lvce-oss-webview';
|
|
@@ -2,5 +2,7 @@ import * as WebViewServer from '../WebViewServer/WebViewServer.js';
|
|
|
2
2
|
export const name = 'WebViewServer';
|
|
3
3
|
export const Commands = {
|
|
4
4
|
start: WebViewServer.start,
|
|
5
|
+
create: WebViewServer.create,
|
|
5
6
|
setHandler: WebViewServer.setHandler,
|
|
7
|
+
registerProtocol: WebViewServer.registerProtocol,
|
|
6
8
|
};
|
|
@@ -1,7 +1,26 @@
|
|
|
1
1
|
import * as PreviewProcess from '../PreviewProcess/PreviewProcess.js';
|
|
2
|
-
|
|
3
|
-
|
|
2
|
+
import * as ParentIpc from '../ParentIpc/ParentIpc.js';
|
|
3
|
+
import * as GetPortTuple from '../GetPortTuple/GetPortTuple.js';
|
|
4
|
+
export const registerProtocol = async () => {
|
|
5
|
+
// TODO only do this once
|
|
6
|
+
// TODO send messageport to proview process
|
|
7
|
+
// TODO send other messageport to parent process
|
|
8
|
+
console.time('get-ports');
|
|
9
|
+
const { port1, port2 } = await GetPortTuple.getPortTuple();
|
|
10
|
+
console.timeEnd('get-ports');
|
|
11
|
+
console.time('register-protocol');
|
|
12
|
+
await ParentIpc.invokeAndTransfer('ElectronSession.registerWebviewProtocol', port1);
|
|
13
|
+
console.timeEnd('register-protocol');
|
|
14
|
+
console.time('handle-port');
|
|
15
|
+
await PreviewProcess.invokeAndTransfer('HandleElectronMessagePort.handleElectronMessagePort', port2);
|
|
16
|
+
console.timeEnd('handle-port');
|
|
4
17
|
};
|
|
5
|
-
export const
|
|
6
|
-
await PreviewProcess.invoke('WebViewServer.
|
|
18
|
+
export const create = async (previewId) => {
|
|
19
|
+
await PreviewProcess.invoke('WebViewServer.create', previewId);
|
|
20
|
+
};
|
|
21
|
+
export const start = async (previewId, port) => {
|
|
22
|
+
await PreviewProcess.invoke('WebViewServer.start', previewId, port);
|
|
23
|
+
};
|
|
24
|
+
export const setHandler = async (previewId, frameAncestors, webViewRoot) => {
|
|
25
|
+
await PreviewProcess.invoke('WebViewServer.setHandler', previewId, frameAncestors, webViewRoot);
|
|
7
26
|
};
|