@lvce-editor/shared-process 0.32.1 → 0.32.2

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 CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@lvce-editor/shared-process",
3
- "version": "0.32.1",
3
+ "version": "0.32.2",
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.32.1",
21
+ "@lvce-editor/extension-host-helper-process": "0.32.2",
22
22
  "@lvce-editor/ipc": "^9.4.0",
23
23
  "@lvce-editor/json-rpc": "^1.4.0",
24
24
  "@lvce-editor/jsonc-parser": "^1.4.0",
@@ -4,6 +4,8 @@ import { pipeline } from 'node:stream/promises';
4
4
  import { fileURLToPath } from 'node:url';
5
5
  import * as GetContentSecurityPolicy from '../GetContentSecurityPolicy/GetContentSecurityPolicy.js';
6
6
  import * as SetHeaders from '../SetHeaders/SetHeaders.js';
7
+ import * as PreviewInjectedCode from '../PreviewInjectedCode/PreviewInjectedCode.js';
8
+ import { readFile } from 'node:fs/promises';
7
9
  const getPathName = (request) => {
8
10
  const { pathname } = new URL(request.url || '', `https://${request.headers.host}`);
9
11
  return pathname;
@@ -29,8 +31,61 @@ const textMimeType = {
29
31
  const getContentType = (filePath) => {
30
32
  return textMimeType[extname(filePath)] || 'text/plain';
31
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
+ };
32
88
  export const createHandler = (frameAncestors, webViewRoot) => {
33
- const csp = GetContentSecurityPolicy.getContentSecurityPolicy([`default-src 'none'`, `script-src 'self'`, `frame-ancestors ${frameAncestors}`]);
34
89
  const handleRequest = async (request, response) => {
35
90
  let pathName = getPathName(request);
36
91
  if (pathName === '/') {
@@ -38,25 +93,13 @@ export const createHandler = (frameAncestors, webViewRoot) => {
38
93
  }
39
94
  const filePath = fileURLToPath(`file://${webViewRoot}${pathName}`);
40
95
  const isHtml = filePath.endsWith('index.html');
41
- const contentType = getContentType(filePath);
42
96
  if (isHtml) {
43
- SetHeaders.setHeaders(response, {
44
- 'Cross-Origin-Resource-Policy': 'cross-origin',
45
- 'Cross-Origin-Embedder-Policy': 'require-corp',
46
- 'Content-Security-Policy': csp,
47
- 'Content-Type': contentType,
48
- });
97
+ return handleIndexHtml(response, filePath, frameAncestors);
49
98
  }
50
- else {
51
- // TODO figure out which of these headers are actually needed
52
- SetHeaders.setHeaders(response, {
53
- 'Cross-Origin-Resource-Policy': 'cross-origin',
54
- 'Cross-Origin-Embedder-Policy': 'require-corp',
55
- 'Access-Control-Allow-Origin': '*',
56
- 'Content-Type': contentType,
57
- });
99
+ if (filePath.endsWith('preview-injected.js')) {
100
+ return handlePreviewInjected(response);
58
101
  }
59
- await pipeline(createReadStream(filePath), response);
102
+ return handleOther(response, filePath);
60
103
  };
61
104
  return handleRequest;
62
105
  };
@@ -6,7 +6,7 @@ export const getAppWindowOptions = (preferences, screenWidth, screenHeight) => {
6
6
  const titleBarStyle = titleBarPreference === 'custom' ? 'hidden' : undefined;
7
7
  const zoomLevelPreference = preferences['window.zoomLevel'];
8
8
  const zoomLevel = zoomLevelPreference;
9
- const windowControlsOverlayPreference = (Platform.isWindows || Platform.isMacOs) && preferences['window.controlsOverlay.enabled'];
9
+ const windowControlsOverlayPreference = (Platform.isWindows || Platform.isMacOs || Platform.isLinux) && preferences['window.controlsOverlay.enabled'];
10
10
  const titleBarOverlay = windowControlsOverlayPreference
11
11
  ? {
12
12
  color: '#1e2324',
@@ -68,3 +68,4 @@ export const HandleMessagePortForProcessExplorer = 73;
68
68
  export const HandleMessagePortForSearchProcess = 74;
69
69
  export const FileWatcher = 75;
70
70
  export const WebViewServer = 76;
71
+ export const Transferrable = 77;
@@ -277,6 +277,8 @@ export const getModuleId = (commandId) => {
277
277
  return ModuleId.HandleMessagePortForSearchProcess;
278
278
  case 'FileWatcher.watch':
279
279
  return ModuleId.FileWatcher;
280
+ case 'Transferrable.transfer':
281
+ return ModuleId.Transferrable;
280
282
  case 'WebViewServer.start':
281
283
  case 'WebViewServer.setHandler':
282
284
  return ModuleId.WebViewServer;
@@ -41,9 +41,9 @@ export const getAppImageName = () => {
41
41
  export const getSetupName = () => {
42
42
  return 'Lvce-Setup';
43
43
  };
44
- export const version = '0.32.1';
45
- export const commit = 'f51fb63';
46
- export const date = '2024-08-18T19:59:49.000Z';
44
+ export const version = '0.32.2';
45
+ export const commit = '93e00a3';
46
+ export const date = '2024-08-20T21:05:50.000Z';
47
47
  export const getVersion = () => {
48
48
  return version;
49
49
  };
@@ -0,0 +1,74 @@
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
+ `;