@stlite/desktop 0.49.2 → 0.49.3

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.
@@ -1,164 +1,2 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- const electron_1 = require("electron");
4
- const path = require("path");
5
- const fsPromises = require("fs/promises");
6
- const file_1 = require("./file");
7
- if (process.env.NODE_ENV === "development") {
8
- console.log("Hot-reloading Electron enabled");
9
- require("electron-reload")(__dirname, {
10
- electron: path.resolve(__dirname, process.platform === "win32"
11
- ? "../../node_modules/electron/dist/electron.exe"
12
- : "../../node_modules/.bin/electron"),
13
- });
14
- }
15
- async function readManifest() {
16
- const manifestPath = path.resolve(__dirname, "../stlite-manifest.json");
17
- const manifestText = await fsPromises.readFile(manifestPath, {
18
- encoding: "utf-8",
19
- });
20
- const maybeManifestData = JSON.parse(manifestText);
21
- return {
22
- embed: maybeManifestData.embed ?? false,
23
- };
24
- }
25
- const createWindow = async () => {
26
- const manifest = await readManifest();
27
- const mainWindow = new electron_1.BrowserWindow({
28
- width: 1280,
29
- height: 720,
30
- webPreferences: {
31
- preload: path.join(__dirname, "preload.js"),
32
- sandbox: true, // https://www.electronjs.org/docs/latest/tutorial/security#4-enable-process-sandboxing
33
- },
34
- });
35
- const indexUrlObj = new URL(electron_1.app.isPackaged || process.env.NODE_ENV === "production"
36
- ? "file:///index.html"
37
- : "http://localhost:3000/");
38
- const indexUrlParams = new URLSearchParams();
39
- if (manifest.embed) {
40
- indexUrlParams.set("embed", "true");
41
- }
42
- indexUrlObj.search = indexUrlParams.toString();
43
- const indexUrl = indexUrlObj.toString();
44
- // Check the IPC sender in every callback below,
45
- // following the security best practice, "17. Validate the sender of all IPC messages."
46
- // https://www.electronjs.org/docs/latest/tutorial/security#17-validate-the-sender-of-all-ipc-messages
47
- const isValidIpcSender = (frame) => {
48
- return frame.url === indexUrl;
49
- };
50
- electron_1.ipcMain.handle("readSitePackagesSnapshot", (ev) => {
51
- if (!isValidIpcSender(ev.senderFrame)) {
52
- throw new Error("Invalid IPC sender");
53
- }
54
- // This archive file has to be created by ./bin/dump_snapshot.ts
55
- const archiveFilePath = path.resolve(__dirname, "../site-packages-snapshot.tar.gz");
56
- return fsPromises.readFile(archiveFilePath);
57
- });
58
- electron_1.ipcMain.handle("readRequirements", async (ev) => {
59
- if (!isValidIpcSender(ev.senderFrame)) {
60
- throw new Error("Invalid IPC sender");
61
- }
62
- const requirementsTxtPath = path.resolve(__dirname, "../requirements.txt");
63
- const requirementsTxtData = await fsPromises.readFile(requirementsTxtPath, {
64
- encoding: "utf-8",
65
- });
66
- return requirementsTxtData
67
- .split("\n")
68
- .map((r) => r.trim())
69
- .filter((r) => r.length > 0); // Assuming that the input `requirements.txt` file is generated by `dump-artifacts.js` and can be parsed with this simple logic.
70
- });
71
- electron_1.ipcMain.handle("readStreamlitAppDirectory", async (ev) => {
72
- if (!isValidIpcSender(ev.senderFrame)) {
73
- throw new Error("Invalid IPC sender");
74
- }
75
- const streamlitAppDir = path.resolve(__dirname, "../streamlit_app");
76
- return (0, file_1.walkRead)(streamlitAppDir);
77
- });
78
- mainWindow.on("closed", () => {
79
- electron_1.ipcMain.removeHandler("readSitePackagesSnapshot");
80
- electron_1.ipcMain.removeHandler("readRequirements");
81
- electron_1.ipcMain.removeHandler("readStreamlitAppDirectory");
82
- });
83
- // Even when the entrypoint is a local file like the production build,
84
- // we use .loadURL() with an absolute URL with the `file://` schema
85
- // instead of passing a file path to .loadFile()
86
- // because absolute URLs with the file:// scheme will be resolved
87
- // to absolute file paths based on the special handler
88
- // registered through `interceptFileProtocol` below.
89
- mainWindow.loadURL(indexUrl);
90
- if (!electron_1.app.isPackaged) {
91
- mainWindow.webContents.openDevTools();
92
- }
93
- };
94
- // Enable process sandboxing globally (https://www.electronjs.org/docs/latest/tutorial/sandbox#enabling-the-sandbox-globally),
95
- // following the security best practice, "4. Enable process sandboxing."
96
- // https://www.electronjs.org/docs/latest/tutorial/security#4-enable-process-sandboxing
97
- electron_1.app.enableSandbox();
98
- // This method will be called when Electron has finished
99
- // initialization and is ready to create browser windows.
100
- // Some APIs can only be used after this event occurs.
101
- electron_1.app.whenReady().then(() => {
102
- // Resolve absolute paths based on the bundled directory.
103
- // It is assumed that the resource paths are absolute paths starting with "/",
104
- // which is configured at `package.json` with the `"homepage"` field.
105
- // Ref: https://github.com/electron/electron/issues/4612#issuecomment-189116655
106
- const bundleBasePath = path.resolve(__dirname, "..");
107
- electron_1.protocol.interceptFileProtocol("file", function (req, callback) {
108
- const filePath = new URL(req.url).pathname; // `file://<absolute_path>?<query>#<hash>` -> `<absolute_path>`
109
- if (path.isAbsolute(filePath)) {
110
- const resolvedFilePath = path.join(bundleBasePath, filePath);
111
- callback(path.normalize(resolvedFilePath));
112
- }
113
- else {
114
- callback(filePath);
115
- }
116
- });
117
- createWindow();
118
- electron_1.app.on("activate", () => {
119
- // On macOS it's common to re-create a window in the app when the
120
- // dock icon is clicked and there are no other windows open.
121
- if (electron_1.BrowserWindow.getAllWindows().length === 0)
122
- createWindow();
123
- });
124
- });
125
- // Quit when all windows are closed, except on macOS. There, it's common
126
- // for applications and their menu bar to stay active until the user quits
127
- // explicitly with Cmd + Q.
128
- electron_1.app.on("window-all-closed", () => {
129
- if (process.platform !== "darwin")
130
- electron_1.app.quit();
131
- });
132
- electron_1.app.on("web-contents-created", (event, contents) => {
133
- // Intercepts webView creation events and forbid all,
134
- // following the security best practice, "12. Verify WebView options before creation."
135
- // https://www.electronjs.org/docs/latest/tutorial/security#12-verify-webview-options-before-creation
136
- contents.on("will-attach-webview", (event, webPreferences, params) => {
137
- // Cancels all webView creation request
138
- event.preventDefault();
139
- });
140
- // Intercepts navigation and forbid all,
141
- // following the security best practice, "13. Disable or limit navigation."
142
- // https://www.electronjs.org/docs/latest/tutorial/security#13-disable-or-limit-navigation
143
- contents.on("will-navigate", (event, navigationUrl) => {
144
- console.debug("will-navigate", navigationUrl);
145
- event.preventDefault();
146
- });
147
- // Limit new windows creation,
148
- // following the security best practice, "14. Disable or limit creation of new windows."
149
- // https://www.electronjs.org/docs/latest/tutorial/security#14-disable-or-limit-creation-of-new-windows
150
- contents.setWindowOpenHandler(({ url }) => {
151
- console.error("Opening a new window is not allowed.");
152
- // TODO: Implement `isSafeForExternalOpen()` below with a configurable allowed list.
153
- // We'll ask the operating system
154
- // to open this event's url in the default browser.
155
- // DON'T pass an arbitrary URL to `shell.openExternal()` here
156
- // as advised at "15. Do not use shell.openExternal with untrusted content."
157
- // if (isSafeForExternalOpen(url)) {
158
- // setImmediate(() => {
159
- // shell.openExternal(url)
160
- // })
161
- // }
162
- return { action: "deny" };
163
- });
164
- });
1
+ var b=Object.create;var w=Object.defineProperty;var _=Object.getOwnPropertyDescriptor;var x=Object.getOwnPropertyNames;var R=Object.getPrototypeOf,y=Object.prototype.hasOwnProperty;var u=(t,e,r,a)=>{if(e&&typeof e=="object"||typeof e=="function")for(let s of x(e))!y.call(t,s)&&s!==r&&w(t,s,{get:()=>e[s],enumerable:!(a=_(e,s))||a.enumerable});return t};var p=(t,e,r)=>(r=t!=null?b(R(t)):{},u(e||!t||!t.__esModule?w(r,"default",{value:t,enumerable:!0}):r,t)),D=t=>u(w({},"__esModule",{value:!0}),t);var S={};module.exports=D(S);var n=require("electron"),o=p(require("path")),f=p(require("fs/promises"));var c=p(require("fs/promises")),l=p(require("path"));async function P(t){let e={},r=await c.readdir(t);return await Promise.all(r.map(async a=>{let s=l.join(t,a);if((await c.stat(s)).isDirectory()){let i=await P(s);Object.assign(e,i)}else{let i=await c.readFile(s);e[s]=i}})),e}async function g(t){let e=await P(t),r={};return Object.keys(e).forEach(a=>{let d=l.relative(t,a).split(l.sep).join(l.posix.sep);r[d]=e[a]}),r}async function F(){let t=o.resolve(__dirname,"../stlite-manifest.json"),e=await f.readFile(t,{encoding:"utf-8"});return{embed:JSON.parse(e).embed??!1}}var v=async()=>{let t=await F(),e=new n.BrowserWindow({width:1280,height:720,webPreferences:{preload:o.join(__dirname,"preload.js"),sandbox:!0}}),r=new URL((n.app.isPackaged,"file:///index.html")),a=new URLSearchParams;t.embed&&a.set("embed","true"),r.search=a.toString();let s=r.toString(),d=i=>i.url===s;n.ipcMain.handle("readSitePackagesSnapshot",i=>{if(!d(i.senderFrame))throw new Error("Invalid IPC sender");let m=o.resolve(__dirname,"../site-packages-snapshot.tar.gz");return f.readFile(m)}),n.ipcMain.handle("readRequirements",async i=>{if(!d(i.senderFrame))throw new Error("Invalid IPC sender");let m=o.resolve(__dirname,"../requirements.txt");return(await f.readFile(m,{encoding:"utf-8"})).split(`
2
+ `).map(h=>h.trim()).filter(h=>h.length>0)}),n.ipcMain.handle("readStreamlitAppDirectory",async i=>{if(!d(i.senderFrame))throw new Error("Invalid IPC sender");let m=o.resolve(__dirname,"../streamlit_app");return g(m)}),e.on("closed",()=>{n.ipcMain.removeHandler("readSitePackagesSnapshot"),n.ipcMain.removeHandler("readRequirements"),n.ipcMain.removeHandler("readStreamlitAppDirectory")}),e.loadURL(s),n.app.isPackaged||e.webContents.openDevTools()};n.app.enableSandbox();n.app.whenReady().then(()=>{let t=o.resolve(__dirname,"..");n.protocol.interceptFileProtocol("file",function(e,r){let a=new URL(e.url).pathname;if(o.isAbsolute(a)){let s=o.join(t,a);r(o.normalize(s))}else r(a)}),v(),n.app.on("activate",()=>{n.BrowserWindow.getAllWindows().length===0&&v()})});n.app.on("window-all-closed",()=>{process.platform!=="darwin"&&n.app.quit()});n.app.on("web-contents-created",(t,e)=>{e.on("will-attach-webview",(r,a,s)=>{r.preventDefault()}),e.on("will-navigate",(r,a)=>{console.debug("will-navigate",a),r.preventDefault()}),e.setWindowOpenHandler(({url:r})=>(console.error("Opening a new window is not allowed."),{action:"deny"}))});
@@ -1,8 +1 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- const electron_1 = require("electron");
4
- electron_1.contextBridge.exposeInMainWorld("archives", {
5
- readSitePackagesSnapshot: () => electron_1.ipcRenderer.invoke("readSitePackagesSnapshot"),
6
- readRequirements: () => electron_1.ipcRenderer.invoke("readRequirements"),
7
- readStreamlitAppDirectory: () => electron_1.ipcRenderer.invoke("readStreamlitAppDirectory"),
8
- });
1
+ var e=require("electron");e.contextBridge.exposeInMainWorld("archives",{readSitePackagesSnapshot:()=>e.ipcRenderer.invoke("readSitePackagesSnapshot"),readRequirements:()=>e.ipcRenderer.invoke("readRequirements"),readStreamlitAppDirectory:()=>e.ipcRenderer.invoke("readStreamlitAppDirectory")});
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@stlite/desktop",
3
- "version": "0.49.2",
3
+ "version": "0.49.3",
4
4
  "license": "Apache-2.0",
5
5
  "homepage": "/",
6
6
  "main": "./build/electron/main.js",
@@ -18,10 +18,10 @@
18
18
  "build:web": "craco build && rimraf 'build/**/*.whl' && rimraf 'build/pypi'",
19
19
  "test": "craco test",
20
20
  "eject": "craco eject",
21
- "start:electron": "concurrently \"tsc -p electron -w\" \"cross-env NODE_ENV=\"development\" electron .\"",
22
- "build:electron": "tsc -p electron",
21
+ "start:electron": "tsc -p electron && cross-env NODE_ENV=development concurrently \"./scripts/build_electron.js --watch\" \"electron .\"",
22
+ "build:electron": "tsc -p electron && cross-env NODE_ENV=production ./scripts/build_electron.js",
23
23
  "build:pyodide": "curl -L https://github.com/pyodide/pyodide/releases/download/0.25.0/pyodide-core-0.25.0.tar.bz2 | tar xj -C ./build --files-from=./pyodide-files.txt",
24
- "build:bin": "./scripts/build_bin.js",
24
+ "build:bin": "tsc -p bin-src && ./scripts/build_bin.js",
25
25
  "build:wheels": "./scripts/copy_wheels.js",
26
26
  "typecheck": "yarn tsc --noEmit -p electron",
27
27
  "start": "concurrently \"cross-env BROWSER=none yarn start:web\" \"wait-on http://localhost:3000 && yarn start:electron\"",
@@ -60,9 +60,9 @@
60
60
  },
61
61
  "devDependencies": {
62
62
  "@craco/craco": "^7.0.0",
63
- "@stlite/common": "^0.49.2",
64
- "@stlite/common-react": "^0.49.2",
65
- "@stlite/kernel": "^0.49.2",
63
+ "@stlite/common": "^0.49.3",
64
+ "@stlite/common-react": "^0.49.3",
65
+ "@stlite/kernel": "^0.49.3",
66
66
  "@streamlit/app": "1.32.2",
67
67
  "@testing-library/react": "^14.1.2",
68
68
  "@testing-library/user-event": "^14.0.0",
@@ -1,38 +0,0 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.walkRead = void 0;
4
- const fsPromises = require("fs/promises");
5
- const path = require("path");
6
- /**
7
- * Returns an object whose keys are absolute paths of the files and values are the file contents.
8
- * Note that the paths are OS-specific, "/" for POSIX and "\" for Windows,
9
- * so this function is only expected to be called from `walkRead()` that converts the paths to be POSIX.
10
- */
11
- async function walkReadAbsPath(dirPath) {
12
- const fileContents = {};
13
- const childNames = await fsPromises.readdir(dirPath);
14
- await Promise.all(childNames.map(async (childName) => {
15
- const childPath = path.join(dirPath, childName);
16
- const stat = await fsPromises.stat(childPath);
17
- if (stat.isDirectory()) {
18
- const childFileContents = await walkReadAbsPath(childPath);
19
- Object.assign(fileContents, childFileContents);
20
- }
21
- else {
22
- const fileBin = await fsPromises.readFile(childPath);
23
- fileContents[childPath] = fileBin;
24
- }
25
- }));
26
- return fileContents;
27
- }
28
- async function walkRead(dirPath) {
29
- const fileContents = await walkReadAbsPath(dirPath);
30
- const relPathFileContents = {};
31
- Object.keys(fileContents).forEach((absPath) => {
32
- const relPath = path.relative(dirPath, absPath);
33
- const posixRelPath = relPath.split(path.sep).join(path.posix.sep); // Convert the path separators on Windows to POSIX ones.
34
- relPathFileContents[posixRelPath] = fileContents[absPath];
35
- });
36
- return relPathFileContents;
37
- }
38
- exports.walkRead = walkRead;