@lvce-editor/shared-process 0.33.2 → 0.33.4
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 +3 -2
- package/src/parts/CrossOriginResourcePolicy/CrossOriginResourcePolicy.js +1 -1
- package/src/parts/ExtensionManagement/ExtensionManagementLanguages.js +5 -1
- package/src/parts/GetHeaders/GetHeaders.js +4 -0
- package/src/parts/GetHeadersMainFrame/GetHeadersMainFrame.js +3 -1
- package/src/parts/LaunchPreviewProcess/LaunchPreviewProcess.js +16 -0
- package/src/parts/Platform/Platform.js +3 -3
- package/src/parts/PreviewProcess/PreviewProcess.js +18 -0
- package/src/parts/PreviewProcessPath/PreviewProcessPath.js +2 -0
- package/src/parts/WebViewServer/WebViewServer.js +3 -17
- package/src/parts/CreateWebViewServer/CreateWebViewServer.js +0 -24
- package/src/parts/CreateWebViewServerHandler/CreateWebViewServerHandler.js +0 -105
- package/src/parts/PreviewInjectedCode/PreviewInjectedCode.js +0 -74
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.4",
|
|
4
4
|
"main": "index.js",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"keywords": [
|
|
@@ -18,7 +18,7 @@
|
|
|
18
18
|
},
|
|
19
19
|
"dependencies": {
|
|
20
20
|
"@lvce-editor/assert": "^1.2.0",
|
|
21
|
-
"@lvce-editor/extension-host-helper-process": "0.33.
|
|
21
|
+
"@lvce-editor/extension-host-helper-process": "0.33.4",
|
|
22
22
|
"@lvce-editor/ipc": "^10.0.4",
|
|
23
23
|
"@lvce-editor/json-rpc": "^3.0.0",
|
|
24
24
|
"@lvce-editor/jsonc-parser": "^1.4.0",
|
|
@@ -35,6 +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": "^1.2.1",
|
|
38
39
|
"open": "^10.1.0",
|
|
39
40
|
"tail": "^2.2.6",
|
|
40
41
|
"tmp-promise": "^3.0.3",
|
|
@@ -1 +1 @@
|
|
|
1
|
-
export const value = '
|
|
1
|
+
export const value = 'same-origin';
|
|
@@ -39,13 +39,17 @@ export const getLanguages = async () => {
|
|
|
39
39
|
return languages;
|
|
40
40
|
};
|
|
41
41
|
const getWebViewsFromExtensions = (extensions) => {
|
|
42
|
+
// console.log({ extensions })
|
|
42
43
|
const webViews = [];
|
|
43
44
|
for (const extension of extensions) {
|
|
44
45
|
if (extension && extension.webViews) {
|
|
45
46
|
for (const webView of extension.webViews) {
|
|
47
|
+
const path = join(extension.path, webView.path);
|
|
48
|
+
const remotePath = GetRemoteUrl.getRemoteUrl(path);
|
|
46
49
|
webViews.push({
|
|
47
50
|
id: webView.id,
|
|
48
|
-
path
|
|
51
|
+
path,
|
|
52
|
+
remotePath,
|
|
49
53
|
});
|
|
50
54
|
}
|
|
51
55
|
}
|
|
@@ -1,4 +1,6 @@
|
|
|
1
1
|
import { basename, extname } from 'path';
|
|
2
|
+
import * as CrossOriginEmbedderPolicy from '../CrossOriginEmbedderPolicy/CrossOriginEmbedderPolicy.js';
|
|
3
|
+
import * as CrossOriginResourcePolicy from '../CrossOriginResourcePolicy/CrossOriginResourcePolicy.js';
|
|
2
4
|
import * as GetHeadersDefault from '../GetHeadersDefault/GetHeadersDefault.js';
|
|
3
5
|
import * as GetHeadersEditorWorker from '../GetHeadersEditorWorker/GetHeadersEditorWorker.js';
|
|
4
6
|
import * as GetHeadersEmbedsWorker from '../GetHeadersEmbedsWorker/GetHeadersEmbedsWorker.js';
|
|
@@ -59,6 +61,8 @@ export const getHeaders = (absolutePath, pathName) => {
|
|
|
59
61
|
const mime = GetMimeType.getMimeType(extension);
|
|
60
62
|
const headers = {
|
|
61
63
|
[HttpHeader.ContentType]: mime,
|
|
64
|
+
[HttpHeader.CrossOriginResourcePolicy]: CrossOriginResourcePolicy.value,
|
|
65
|
+
[HttpHeader.CrossOriginEmbedderPolicy]: CrossOriginEmbedderPolicy.value,
|
|
62
66
|
};
|
|
63
67
|
const extraHeaders = getExtraHeaders(pathName, extension);
|
|
64
68
|
return {
|
|
@@ -1,11 +1,13 @@
|
|
|
1
1
|
import * as ContentSecurityPolicyDocument from '../ContentSecurityPolicyDocument/ContentSecurityPolicyDocument.js';
|
|
2
2
|
import * as CrossOriginEmbedderPolicy from '../CrossOriginEmbedderPolicy/CrossOriginEmbedderPolicy.js';
|
|
3
3
|
import * as CrossOriginOpenerPolicy from '../CrossOriginOpenerPolicy/CrossOriginOpenerPolicy.js';
|
|
4
|
+
import * as CrossOriginResourcePolicy from '../CrossOriginResourcePolicy/CrossOriginResourcePolicy.js';
|
|
4
5
|
import * as HttpHeader from '../HttpHeader/HttpHeader.js';
|
|
5
6
|
export const getHeadersMainFrame = () => {
|
|
6
7
|
return {
|
|
7
8
|
[HttpHeader.ContentSecurityPolicy]: ContentSecurityPolicyDocument.value,
|
|
8
|
-
[HttpHeader.CrossOriginOpenerPolicy]: CrossOriginOpenerPolicy.value,
|
|
9
9
|
[HttpHeader.CrossOriginEmbedderPolicy]: CrossOriginEmbedderPolicy.value,
|
|
10
|
+
[HttpHeader.CrossOriginOpenerPolicy]: CrossOriginOpenerPolicy.value,
|
|
11
|
+
[HttpHeader.CrossOriginResourcePolicy]: CrossOriginResourcePolicy.value,
|
|
10
12
|
};
|
|
11
13
|
};
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import * as HandleIpc from '../HandleIpc/HandleIpc.js';
|
|
2
|
+
import * as IpcParent from '../IpcParent/IpcParent.js';
|
|
3
|
+
import * as IpcParentType from '../IpcParentType/IpcParentType.js';
|
|
4
|
+
import * as PreviewProcessPath from '../PreviewProcessPath/PreviewProcessPath.js';
|
|
5
|
+
export const launchPreviewProcess = async () => {
|
|
6
|
+
const method = IpcParentType.NodeForkedProcess;
|
|
7
|
+
const previewProcess = await IpcParent.create({
|
|
8
|
+
method,
|
|
9
|
+
path: PreviewProcessPath.previewProcessPath,
|
|
10
|
+
argv: [],
|
|
11
|
+
stdio: 'inherit',
|
|
12
|
+
name: 'Preview Process',
|
|
13
|
+
});
|
|
14
|
+
HandleIpc.handleIpc(previewProcess);
|
|
15
|
+
return previewProcess;
|
|
16
|
+
};
|
|
@@ -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-08-
|
|
44
|
+
export const version = '0.33.4';
|
|
45
|
+
export const commit = 'da8ae3e';
|
|
46
|
+
export const date = '2024-08-28T17:12:51.000Z';
|
|
47
47
|
export const getVersion = () => {
|
|
48
48
|
return version;
|
|
49
49
|
};
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import * as JsonRpc from '../JsonRpc/JsonRpc.js';
|
|
2
|
+
import * as LaunchPreviewProcess from '../LaunchPreviewProcess/LaunchPreviewProcess.js';
|
|
3
|
+
export const state = {
|
|
4
|
+
/**
|
|
5
|
+
* @type {any}
|
|
6
|
+
*/
|
|
7
|
+
ipc: undefined,
|
|
8
|
+
};
|
|
9
|
+
export const getOrCreate = async () => {
|
|
10
|
+
if (!state.ipc) {
|
|
11
|
+
state.ipc = LaunchPreviewProcess.launchPreviewProcess();
|
|
12
|
+
}
|
|
13
|
+
return state.ipc;
|
|
14
|
+
};
|
|
15
|
+
export const invoke = async (method, ...params) => {
|
|
16
|
+
const ipc = await getOrCreate();
|
|
17
|
+
return JsonRpc.invoke(ipc, method, ...params);
|
|
18
|
+
};
|
|
@@ -1,21 +1,7 @@
|
|
|
1
|
-
import * as
|
|
2
|
-
import * as CreateWebViewServerHandler from '../CreateWebViewServerHandler/CreateWebViewServerHandler.js';
|
|
3
|
-
const state = {
|
|
4
|
-
/**
|
|
5
|
-
* @type {any }
|
|
6
|
-
*/
|
|
7
|
-
promise: undefined,
|
|
8
|
-
};
|
|
9
|
-
// TODO move webview preview
|
|
10
|
-
// server into separate process
|
|
1
|
+
import * as PreviewProcess from '../PreviewProcess/PreviewProcess.js';
|
|
11
2
|
export const start = async (port) => {
|
|
12
|
-
|
|
13
|
-
state.promise = CreateWebViewServer.createWebViewServer(port);
|
|
14
|
-
}
|
|
15
|
-
return state.promise;
|
|
3
|
+
await PreviewProcess.invoke('WebViewServer.start', port);
|
|
16
4
|
};
|
|
17
5
|
export const setHandler = async (frameAncestors, webViewRoot) => {
|
|
18
|
-
|
|
19
|
-
const handler = CreateWebViewServerHandler.createHandler(frameAncestors, webViewRoot);
|
|
20
|
-
server.setHandler(handler);
|
|
6
|
+
await PreviewProcess.invoke('WebViewServer.setHandler', frameAncestors, webViewRoot);
|
|
21
7
|
};
|
|
@@ -1,24 +0,0 @@
|
|
|
1
|
-
import { VError } from '@lvce-editor/verror';
|
|
2
|
-
import { createServer } from 'node:http';
|
|
3
|
-
import * as Promises from '../Promises/Promises.js';
|
|
4
|
-
export const createWebViewServer = async (port) => {
|
|
5
|
-
try {
|
|
6
|
-
const server = createServer();
|
|
7
|
-
const { resolve, promise } = Promises.withResolvers();
|
|
8
|
-
server.listen(port, resolve);
|
|
9
|
-
await promise;
|
|
10
|
-
return {
|
|
11
|
-
handler: undefined,
|
|
12
|
-
setHandler(handleRequest) {
|
|
13
|
-
if (this.handler) {
|
|
14
|
-
return;
|
|
15
|
-
}
|
|
16
|
-
this.handler = this.handler;
|
|
17
|
-
server.on('request', handleRequest);
|
|
18
|
-
},
|
|
19
|
-
};
|
|
20
|
-
}
|
|
21
|
-
catch (error) {
|
|
22
|
-
throw new VError(error, `Failed to start webview server`);
|
|
23
|
-
}
|
|
24
|
-
};
|
|
@@ -1,105 +0,0 @@
|
|
|
1
|
-
import { createReadStream } from 'node:fs';
|
|
2
|
-
import { extname } from 'node:path';
|
|
3
|
-
import { pipeline } from 'node:stream/promises';
|
|
4
|
-
import { fileURLToPath } from 'node:url';
|
|
5
|
-
import * as GetContentSecurityPolicy from '../GetContentSecurityPolicy/GetContentSecurityPolicy.js';
|
|
6
|
-
import * as SetHeaders from '../SetHeaders/SetHeaders.js';
|
|
7
|
-
import * as PreviewInjectedCode from '../PreviewInjectedCode/PreviewInjectedCode.js';
|
|
8
|
-
import { readFile } from 'node:fs/promises';
|
|
9
|
-
const getPathName = (request) => {
|
|
10
|
-
const { pathname } = new URL(request.url || '', `https://${request.headers.host}`);
|
|
11
|
-
return pathname;
|
|
12
|
-
};
|
|
13
|
-
const textMimeType = {
|
|
14
|
-
'.html': 'text/html',
|
|
15
|
-
'.js': 'text/javascript',
|
|
16
|
-
'.ts': 'text/javascript',
|
|
17
|
-
'.mjs': 'text/javascript',
|
|
18
|
-
'.json': 'application/json',
|
|
19
|
-
'.css': 'text/css',
|
|
20
|
-
'.svg': 'image/svg+xml',
|
|
21
|
-
'.avif': 'image/avif',
|
|
22
|
-
'.woff': 'application/font-woff',
|
|
23
|
-
'.ttf': 'font/ttf',
|
|
24
|
-
'.png': 'image/png',
|
|
25
|
-
'.jpe': 'image/jpg',
|
|
26
|
-
'.ico': 'image/x-icon',
|
|
27
|
-
'.jpeg': 'image/jpg',
|
|
28
|
-
'.jpg': 'image/jpg',
|
|
29
|
-
'.webp': 'image/webp',
|
|
30
|
-
};
|
|
31
|
-
const getContentType = (filePath) => {
|
|
32
|
-
return textMimeType[extname(filePath)] || 'text/plain';
|
|
33
|
-
};
|
|
34
|
-
const injectPreviewScript = (html) => {
|
|
35
|
-
const injectedCode = `<script type="module" src="/preview-injected.js"></script>\n`;
|
|
36
|
-
const titleEndIndex = html.indexOf('</title>');
|
|
37
|
-
const newHtml = html.slice(0, titleEndIndex + '</title>'.length) + '\n' + injectedCode + html.slice(titleEndIndex);
|
|
38
|
-
return newHtml;
|
|
39
|
-
};
|
|
40
|
-
const handleIndexHtml = async (response, filePath, frameAncestors) => {
|
|
41
|
-
try {
|
|
42
|
-
const csp = GetContentSecurityPolicy.getContentSecurityPolicy([`default-src 'none'`, `script-src 'self'`, `frame-ancestors ${frameAncestors}`]);
|
|
43
|
-
const contentType = getContentType(filePath);
|
|
44
|
-
const content = await readFile(filePath, 'utf8');
|
|
45
|
-
SetHeaders.setHeaders(response, {
|
|
46
|
-
'Cross-Origin-Resource-Policy': 'cross-origin',
|
|
47
|
-
'Cross-Origin-Embedder-Policy': 'require-corp',
|
|
48
|
-
'Content-Security-Policy': csp,
|
|
49
|
-
'Content-Type': contentType,
|
|
50
|
-
});
|
|
51
|
-
const newContent = injectPreviewScript(content);
|
|
52
|
-
response.end(newContent);
|
|
53
|
-
}
|
|
54
|
-
catch (error) {
|
|
55
|
-
console.error(`[preview-server] ${error}`);
|
|
56
|
-
}
|
|
57
|
-
};
|
|
58
|
-
const handleOther = async (response, filePath) => {
|
|
59
|
-
try {
|
|
60
|
-
const contentType = getContentType(filePath);
|
|
61
|
-
// TODO figure out which of these headers are actually needed
|
|
62
|
-
SetHeaders.setHeaders(response, {
|
|
63
|
-
'Cross-Origin-Resource-Policy': 'cross-origin',
|
|
64
|
-
'Cross-Origin-Embedder-Policy': 'require-corp',
|
|
65
|
-
'Access-Control-Allow-Origin': '*',
|
|
66
|
-
'Content-Type': contentType,
|
|
67
|
-
});
|
|
68
|
-
await pipeline(createReadStream(filePath), response);
|
|
69
|
-
}
|
|
70
|
-
catch (error) {
|
|
71
|
-
console.error(error);
|
|
72
|
-
response.end(`[preview-server] ${error}`);
|
|
73
|
-
}
|
|
74
|
-
};
|
|
75
|
-
const handlePreviewInjected = (response) => {
|
|
76
|
-
try {
|
|
77
|
-
const injectedCode = PreviewInjectedCode.injectedCode;
|
|
78
|
-
const contentType = getContentType('/test/file.js');
|
|
79
|
-
SetHeaders.setHeaders(response, {
|
|
80
|
-
'Content-Type': contentType,
|
|
81
|
-
});
|
|
82
|
-
response.end(injectedCode);
|
|
83
|
-
}
|
|
84
|
-
catch (error) {
|
|
85
|
-
console.error(`[preview-server] ${error}`);
|
|
86
|
-
}
|
|
87
|
-
};
|
|
88
|
-
export const createHandler = (frameAncestors, webViewRoot) => {
|
|
89
|
-
const handleRequest = async (request, response) => {
|
|
90
|
-
let pathName = getPathName(request);
|
|
91
|
-
if (pathName === '/') {
|
|
92
|
-
pathName += 'index.html';
|
|
93
|
-
}
|
|
94
|
-
const filePath = fileURLToPath(`file://${webViewRoot}${pathName}`);
|
|
95
|
-
const isHtml = filePath.endsWith('index.html');
|
|
96
|
-
if (isHtml) {
|
|
97
|
-
return handleIndexHtml(response, filePath, frameAncestors);
|
|
98
|
-
}
|
|
99
|
-
if (filePath.endsWith('preview-injected.js')) {
|
|
100
|
-
return handlePreviewInjected(response);
|
|
101
|
-
}
|
|
102
|
-
return handleOther(response, filePath);
|
|
103
|
-
};
|
|
104
|
-
return handleRequest;
|
|
105
|
-
};
|
|
@@ -1,74 +0,0 @@
|
|
|
1
|
-
export const injectedCode = `
|
|
2
|
-
let commandMap = {}
|
|
3
|
-
let port
|
|
4
|
-
const callbacks = Object.create(null)
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
const isJsonRpcResponse = message => {
|
|
8
|
-
return 'result' in message || 'error' in message
|
|
9
|
-
}
|
|
10
|
-
|
|
11
|
-
const handleMessage = async (event) => {
|
|
12
|
-
const message = event.data
|
|
13
|
-
if(isJsonRpcResponse(message)){
|
|
14
|
-
const fn = callbacks[message.id]
|
|
15
|
-
fn(message.result)
|
|
16
|
-
return
|
|
17
|
-
}
|
|
18
|
-
const { method, params } = message
|
|
19
|
-
const fn = commandMap[method]
|
|
20
|
-
if(!fn){
|
|
21
|
-
throw new Error("command not found \${method}")
|
|
22
|
-
}
|
|
23
|
-
const result = await fn(...params)
|
|
24
|
-
}
|
|
25
|
-
|
|
26
|
-
const handleFirstMessage = (event) => {
|
|
27
|
-
const message = event.data
|
|
28
|
-
port = message.params[0]
|
|
29
|
-
port.onmessage = handleMessage
|
|
30
|
-
port.postMessage('ready')
|
|
31
|
-
}
|
|
32
|
-
|
|
33
|
-
window.addEventListener('message', handleFirstMessage, {
|
|
34
|
-
once: true,
|
|
35
|
-
})
|
|
36
|
-
|
|
37
|
-
const withResolvers = () => {
|
|
38
|
-
let _resolve
|
|
39
|
-
const promise = new Promise(resolve => {
|
|
40
|
-
_resolve = resolve
|
|
41
|
-
})
|
|
42
|
-
return {
|
|
43
|
-
resolve: _resolve,
|
|
44
|
-
promise
|
|
45
|
-
}
|
|
46
|
-
}
|
|
47
|
-
|
|
48
|
-
const registerPromise = () => {
|
|
49
|
-
const id = 1
|
|
50
|
-
const {resolve, promise} = withResolvers()
|
|
51
|
-
callbacks[id] = { resolve }
|
|
52
|
-
return {
|
|
53
|
-
id, promise
|
|
54
|
-
}
|
|
55
|
-
}
|
|
56
|
-
|
|
57
|
-
globalThis.lvceRpc = (value) => {
|
|
58
|
-
commandMap = value
|
|
59
|
-
return {
|
|
60
|
-
async invoke(method, ...params){
|
|
61
|
-
const {id, promise } = registerPromise()
|
|
62
|
-
port.postMessage({
|
|
63
|
-
jsonrpc: '2.0',
|
|
64
|
-
id,
|
|
65
|
-
method,
|
|
66
|
-
params
|
|
67
|
-
})
|
|
68
|
-
const response = await promise
|
|
69
|
-
// TODO unwrap jsonrpc result
|
|
70
|
-
return response
|
|
71
|
-
}
|
|
72
|
-
}
|
|
73
|
-
}
|
|
74
|
-
`;
|