ewvjs 1.0.19 → 1.0.21

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/README.md CHANGED
@@ -13,6 +13,7 @@
13
13
  - ⚡ **Node.js Integration**: Call Node.js functions directly from your frontend code.
14
14
  - 🖱️ **Context Menus**: Customizable native right-click context menus.
15
15
  - 📦 **Packaging**: Built-in CLI tool to package your app into a standalone executable.
16
+ - 🔄 **Auto Update**: Download a hosted manifest and atomically swap in a packaged app update.
16
17
  - 🔧 **Native Bindings**: High-performance C# bindings via `node-api-dotnet`.
17
18
  - 🖼️ **Customization**: Support for frameless windows, transparency, vibrancy, and more.
18
19
 
@@ -95,6 +96,37 @@ Exposes a Node.js function to the frontend.
95
96
  * `name` (string): The name of the function as it will appear in `window.ewvjs.api`.
96
97
  * `callback` (function): The Node.js function to execute. Can be async.
97
98
 
99
+ ### `autoUpdateFromManifest(manifestUrl)`
100
+
101
+ Downloads an update manifest, fetches the packaged app ZIP, stages it, and performs an atomic directory swap from a detached PowerShell helper after the current process exits. The helper then relaunches the app.
102
+
103
+ **Manifest format:**
104
+
105
+ ```json
106
+ {
107
+ "version": "0.0.2",
108
+ "url": "https://example.com/updater_test/update_balbal.zip"
109
+ }
110
+ ```
111
+
112
+ **Usage:**
113
+
114
+ ```javascript
115
+ const result = await ewvjs.autoUpdateFromManifest('https://example.com/manifest.json');
116
+
117
+ if (result.updated) {
118
+ console.log('Updated to', result.version);
119
+ } else {
120
+ console.error('Update failed:', result.error);
121
+ }
122
+ ```
123
+
124
+ **Notes:**
125
+
126
+ * The archive is extracted with Windows `tar`.
127
+ * The running app cannot overwrite itself directly, so the helper process handles the swap.
128
+ * A backup copy is kept during the swap to reduce the chance of update failure leaving the install broken.
129
+
98
130
  ### Window Options
99
131
 
100
132
  ```typescript
package/dist/types.d.ts CHANGED
@@ -40,5 +40,22 @@ export interface WindowOptions {
40
40
  additional_args?: string;
41
41
  jsCallback?: (message: any) => void;
42
42
  debug?: boolean;
43
+ on_close?: () => void;
44
+ on_show?: () => void;
45
+ on_hide?: () => void;
46
+ on_resize?: (size: {
47
+ width: number;
48
+ height: number;
49
+ state: string;
50
+ }) => void;
51
+ on_move?: (pos: {
52
+ x: number;
53
+ y: number;
54
+ }) => void;
55
+ on_focus?: () => void;
56
+ on_blur?: () => void;
57
+ on_maximize?: () => void;
58
+ on_minimize?: () => void;
59
+ on_restore?: () => void;
43
60
  }
44
61
  //# sourceMappingURL=types.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA,MAAM,WAAW,eAAe;IAC5B,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,EAAE,CAAC,EAAE,MAAM,CAAC;IACZ,IAAI,CAAC,EAAE,QAAQ,GAAG,WAAW,GAAG,UAAU,GAAG,SAAS,CAAC;IACvD,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,OAAO,CAAC,EAAE,eAAe,EAAE,CAAC;IAC5B,KAAK,CAAC,EAAE,MAAM,IAAI,CAAC;CACtB;AAED,MAAM,WAAW,aAAa;IAC1B,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,CAAC,CAAC,EAAE,MAAM,CAAC;IACX,CAAC,CAAC,EAAE,MAAM,CAAC;IACX,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,KAAK,CAAC,EAAE,OAAO,CAAC;IAChB,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,aAAa,CAAC,EAAE,OAAO,CAAC;IACxB,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,WAAW,CAAC,EAAE,OAAO,CAAC;IACtB,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,OAAO,CAAC,EAAE;QACN,OAAO,CAAC,EAAE,OAAO,CAAC;QAClB,IAAI,CAAC,EAAE,MAAM,CAAC;QACd,OAAO,CAAC,EAAE,MAAM,CAAC;KACpB,CAAC;IACF,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,UAAU,CAAC,EAAE,CAAC,OAAO,EAAE,GAAG,KAAK,IAAI,CAAC;IACpC,KAAK,CAAC,EAAE,OAAO,CAAC;CACnB"}
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA,MAAM,WAAW,eAAe;IAC5B,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,EAAE,CAAC,EAAE,MAAM,CAAC;IACZ,IAAI,CAAC,EAAE,QAAQ,GAAG,WAAW,GAAG,UAAU,GAAG,SAAS,CAAC;IACvD,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,OAAO,CAAC,EAAE,eAAe,EAAE,CAAC;IAC5B,KAAK,CAAC,EAAE,MAAM,IAAI,CAAC;CACtB;AAED,MAAM,WAAW,aAAa;IAC1B,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,CAAC,CAAC,EAAE,MAAM,CAAC;IACX,CAAC,CAAC,EAAE,MAAM,CAAC;IACX,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,KAAK,CAAC,EAAE,OAAO,CAAC;IAChB,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,aAAa,CAAC,EAAE,OAAO,CAAC;IACxB,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,WAAW,CAAC,EAAE,OAAO,CAAC;IACtB,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,OAAO,CAAC,EAAE;QACN,OAAO,CAAC,EAAE,OAAO,CAAC;QAClB,IAAI,CAAC,EAAE,MAAM,CAAC;QACd,OAAO,CAAC,EAAE,MAAM,CAAC;KACpB,CAAC;IACF,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,UAAU,CAAC,EAAE,CAAC,OAAO,EAAE,GAAG,KAAK,IAAI,CAAC;IACpC,KAAK,CAAC,EAAE,OAAO,CAAC;IAEhB,QAAQ,CAAC,EAAE,MAAM,IAAI,CAAC;IACtB,OAAO,CAAC,EAAE,MAAM,IAAI,CAAC;IACrB,OAAO,CAAC,EAAE,MAAM,IAAI,CAAC;IACrB,SAAS,CAAC,EAAE,CAAC,IAAI,EAAE;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAA;KAAE,KAAK,IAAI,CAAC;IAC7E,OAAO,CAAC,EAAE,CAAC,GAAG,EAAE;QAAE,CAAC,EAAE,MAAM,CAAC;QAAC,CAAC,EAAE,MAAM,CAAA;KAAE,KAAK,IAAI,CAAC;IAClD,QAAQ,CAAC,EAAE,MAAM,IAAI,CAAC;IACtB,OAAO,CAAC,EAAE,MAAM,IAAI,CAAC;IACrB,WAAW,CAAC,EAAE,MAAM,IAAI,CAAC;IACzB,WAAW,CAAC,EAAE,MAAM,IAAI,CAAC;IACzB,UAAU,CAAC,EAAE,MAAM,IAAI,CAAC;CAC3B"}
package/dist/webview.d.ts CHANGED
@@ -12,6 +12,14 @@ export declare class WebView {
12
12
  private _resolveOnce;
13
13
  private _httpServers;
14
14
  constructor();
15
+ autoUpdateFromManifest(manifestUrl: string): Promise<{
16
+ updated: boolean;
17
+ version?: string;
18
+ error?: string;
19
+ }>;
20
+ private _buildUpdateHelperScript;
21
+ private _fetchJson;
22
+ private _downloadFile;
15
23
  create_window(title: string, url_or_html?: string, options?: Partial<WindowOptions>): Promise<Window>;
16
24
  start(): Promise<void>;
17
25
  private _cleanup;
@@ -1 +1 @@
1
- {"version":3,"file":"webview.d.ts","sourceRoot":"","sources":["../src/webview.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,MAAM,EAAE,MAAM,aAAa,CAAC;AACrC,OAAO,EAAE,aAAa,EAAE,MAAM,YAAY,CAAC;AAU3C,qBAAa,OAAO;IACnB,QAAQ,EAAE,GAAG,CAAC;IACd,iBAAiB,EAAE;QAAE,CAAC,GAAG,EAAE,MAAM,GAAG,QAAQ,CAAA;KAAE,CAAM;IACpD,OAAO,CAAC,QAAQ,CAA0B;IAC1C,OAAO,CAAC,aAAa,CAA8B;IACnD,OAAO,CAAC,aAAa,CAA6B;IAClD,OAAO,CAAC,UAAU,CAA+B;IACjD,OAAO,CAAC,YAAY,CAAkB;IACtC,OAAO,CAAC,YAAY,CAAuC;;IAUrD,aAAa,CAClB,KAAK,EAAE,MAAM,EACb,WAAW,GAAE,MAAW,EACxB,OAAO,GAAE,OAAO,CAAC,aAAa,CAAM,GAClC,OAAO,CAAC,MAAM,CAAC;IAgBZ,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;IAa5B,OAAO,CAAC,QAAQ;IAyBhB,MAAM,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,QAAQ,GAAG,IAAI;IAIpC,eAAe,CAAC,OAAO,EAAE,GAAG,GAAG,OAAO,CAAC,IAAI,CAAC;IAIlD,OAAO,CAAC,YAAY;IAKpB,OAAO,CAAC,iBAAiB;YAiDX,mBAAmB;CAwCjC"}
1
+ {"version":3,"file":"webview.d.ts","sourceRoot":"","sources":["../src/webview.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,MAAM,EAAE,MAAM,aAAa,CAAC;AACrC,OAAO,EAAE,aAAa,EAAE,MAAM,YAAY,CAAC;AAa3C,qBAAa,OAAO;IACnB,QAAQ,EAAE,GAAG,CAAC;IACd,iBAAiB,EAAE;QAAE,CAAC,GAAG,EAAE,MAAM,GAAG,QAAQ,CAAA;KAAE,CAAM;IACpD,OAAO,CAAC,QAAQ,CAA0B;IAC1C,OAAO,CAAC,aAAa,CAA8B;IACnD,OAAO,CAAC,aAAa,CAA6B;IAClD,OAAO,CAAC,UAAU,CAA+B;IACjD,OAAO,CAAC,YAAY,CAAkB;IACtC,OAAO,CAAC,YAAY,CAAuC;;IAUrD,sBAAsB,CAAC,WAAW,EAAE,MAAM,GAAG,OAAO,CAAC;QAAE,OAAO,EAAE,OAAO,CAAC;QAAC,OAAO,CAAC,EAAE,MAAM,CAAC;QAAC,KAAK,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC;IA0DlH,OAAO,CAAC,wBAAwB;IAiDhC,OAAO,CAAC,UAAU;IAiBlB,OAAO,CAAC,aAAa;IAsBf,aAAa,CAClB,KAAK,EAAE,MAAM,EACb,WAAW,GAAE,MAAW,EACxB,OAAO,GAAE,OAAO,CAAC,aAAa,CAAM,GAClC,OAAO,CAAC,MAAM,CAAC;IAgBZ,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;IAa5B,OAAO,CAAC,QAAQ;IAyBhB,MAAM,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,QAAQ,GAAG,IAAI;IAIpC,eAAe,CAAC,OAAO,EAAE,GAAG,GAAG,OAAO,CAAC,IAAI,CAAC;IAIlD,OAAO,CAAC,YAAY;IAKpB,OAAO,CAAC,iBAAiB;YAiDX,mBAAmB;CAwCjC"}
package/dist/webview.js CHANGED
@@ -1,10 +1,13 @@
1
1
  import { WindowsPlatform } from "./platforms/windows.js";
2
2
  import { Window } from "./window.js";
3
3
  import * as http from "http";
4
+ import * as https from "https";
4
5
  import * as fs from "fs";
6
+ import * as os from "os";
5
7
  import * as path from "path";
6
8
  import mime from "mime-types";
7
9
  import { fileURLToPath } from 'url';
10
+ import * as child_process from 'child_process';
8
11
  const __filename = fileURLToPath(import.meta.url);
9
12
  const __dirname = path.dirname(__filename);
10
13
  export class WebView {
@@ -24,6 +27,141 @@ export class WebView {
24
27
  throw new Error("Platform not supported: " + process.platform);
25
28
  }
26
29
  }
30
+ async autoUpdateFromManifest(manifestUrl) {
31
+ try {
32
+ const manifestData = await this._fetchJson(manifestUrl);
33
+ if (!manifestData || !manifestData.url) {
34
+ return { updated: false, error: 'Invalid manifest: missing url' };
35
+ }
36
+ const downloadUrl = manifestData.url;
37
+ const version = manifestData.version;
38
+ // download zip to temp file
39
+ const tmpDir = fs.mkdtempSync(path.join(os.tmpdir(), 'ewvjs-update-'));
40
+ const zipPath = path.join(tmpDir, 'update.zip');
41
+ await this._downloadFile(downloadUrl, zipPath);
42
+ // extract zip to temp extract dir
43
+ const extractDir = path.join(tmpDir, 'extracted');
44
+ fs.mkdirSync(extractDir);
45
+ // Use system `tar` to extract the downloaded archive. Fail if tar is not available.
46
+ try {
47
+ child_process.execFileSync('tar', ['-xf', zipPath, '-C', extractDir], { stdio: 'ignore' });
48
+ }
49
+ catch (e) {
50
+ return { updated: false, error: 'Extraction failed: system tar not available or failed: ' + (e && e.message ? e.message : String(e)) };
51
+ }
52
+ // determine target dir
53
+ const isPkg = typeof process.pkg !== 'undefined';
54
+ const targetDir = isPkg ? path.dirname(process.execPath) : path.resolve(__dirname, '..');
55
+ const restartExe = process.execPath;
56
+ const restartArgsJson = JSON.stringify(process.argv.slice(1));
57
+ const helperScriptPath = path.join(tmpDir, 'ewvjs-update-helper.ps1');
58
+ fs.writeFileSync(helperScriptPath, this._buildUpdateHelperScript(), 'utf8');
59
+ const helper = child_process.spawn('powershell.exe', [
60
+ '-NoProfile',
61
+ '-ExecutionPolicy',
62
+ 'Bypass',
63
+ '-File',
64
+ helperScriptPath,
65
+ extractDir,
66
+ targetDir,
67
+ String(process.pid),
68
+ restartExe,
69
+ restartArgsJson,
70
+ targetDir,
71
+ ], { detached: true, stdio: 'ignore' });
72
+ helper.unref();
73
+ return { updated: true, version };
74
+ }
75
+ catch (err) {
76
+ return { updated: false, error: err && err.message ? err.message : String(err) };
77
+ }
78
+ }
79
+ _buildUpdateHelperScript() {
80
+ return `param(
81
+ [string]\$StagingDir,
82
+ [string]\$TargetDir,
83
+ [int]\$MainPid,
84
+ [string]\$RestartExe,
85
+ [string]\$RestartArgsJson,
86
+ [string]\$WorkingDir
87
+ )
88
+
89
+ \$ErrorActionPreference = 'Stop'
90
+
91
+ while ($true) {
92
+ try {
93
+ Get-Process -Id \$MainPid -ErrorAction Stop | Out-Null
94
+ Start-Sleep -Milliseconds 250
95
+ } catch {
96
+ break
97
+ }
98
+ }
99
+
100
+ Start-Sleep -Milliseconds 500
101
+
102
+ \$parentDir = Split-Path -Path \$TargetDir -Parent
103
+ \$targetName = Split-Path -Path \$TargetDir -Leaf
104
+ \$backupDir = Join-Path -Path \$parentDir -ChildPath ($targetName + '.bak.' + ([DateTimeOffset]::UtcNow.ToUnixTimeMilliseconds()))
105
+
106
+ if (Test-Path -LiteralPath \$backupDir) {
107
+ Remove-Item -LiteralPath \$backupDir -Recurse -Force
108
+ }
109
+
110
+ try {
111
+ Move-Item -LiteralPath \$TargetDir -Destination \$backupDir
112
+ Move-Item -LiteralPath \$StagingDir -Destination \$TargetDir
113
+
114
+ \$restartArgs = @()
115
+ if (-not [string]::IsNullOrWhiteSpace(\$RestartArgsJson)) {
116
+ \$restartArgs = \$RestartArgsJson | ConvertFrom-Json
117
+ }
118
+
119
+ Start-Process -FilePath \$RestartExe -ArgumentList \$restartArgs -WorkingDirectory \$WorkingDir
120
+ } catch {
121
+ if ((Test-Path -LiteralPath \$backupDir) -and -not (Test-Path -LiteralPath \$TargetDir)) {
122
+ Move-Item -LiteralPath \$backupDir -Destination \$TargetDir -Force
123
+ }
124
+ throw
125
+ }`;
126
+ }
127
+ _fetchJson(urlStr) {
128
+ return new Promise((resolve, reject) => {
129
+ const client = urlStr.startsWith('https:') ? https : http;
130
+ client.get(urlStr, (res) => {
131
+ let data = '';
132
+ res.on('data', (chunk) => (data += chunk));
133
+ res.on('end', () => {
134
+ try {
135
+ resolve(JSON.parse(data));
136
+ }
137
+ catch (e) {
138
+ reject(e);
139
+ }
140
+ });
141
+ }).on('error', reject);
142
+ });
143
+ }
144
+ _downloadFile(urlStr, destPath) {
145
+ return new Promise((resolve, reject) => {
146
+ const client = urlStr.startsWith('https:') ? https : http;
147
+ const file = fs.createWriteStream(destPath);
148
+ const req = client.get(urlStr, (res) => {
149
+ if (res.statusCode && res.statusCode >= 400) {
150
+ file.close();
151
+ return reject(new Error('Download failed: ' + res.statusCode));
152
+ }
153
+ res.pipe(file);
154
+ file.on('finish', () => {
155
+ file.close();
156
+ resolve();
157
+ });
158
+ });
159
+ req.on('error', (err) => {
160
+ file.close();
161
+ reject(err);
162
+ });
163
+ });
164
+ }
27
165
  async create_window(title, url_or_html = "", options = {}) {
28
166
  const opts = await this._buildWindowOptions(title, url_or_html, options);
29
167
  const window = new Window(this.platform, opts, this.exposed_functions);
package/dist/window.d.ts CHANGED
@@ -8,8 +8,26 @@ export declare class Window {
8
8
  private _menuCallbacks;
9
9
  private _exposedFunctions;
10
10
  private _isClosed;
11
+ private _closeNotified;
11
12
  private _pendingApiInjection;
12
13
  on_context_menu: (items: any[]) => ContextMenuItem[] | null | Promise<ContextMenuItem[] | null>;
14
+ on_close: () => void;
15
+ on_show: () => void;
16
+ on_hide: () => void;
17
+ on_resize: (size: {
18
+ width: number;
19
+ height: number;
20
+ state: string;
21
+ }) => void;
22
+ on_move: (pos: {
23
+ x: number;
24
+ y: number;
25
+ }) => void;
26
+ on_focus: () => void;
27
+ on_blur: () => void;
28
+ on_maximize: () => void;
29
+ on_minimize: () => void;
30
+ on_restore: () => void;
13
31
  constructor(platform: any, options: WindowOptions, exposedFunctions: {
14
32
  [key: string]: Function;
15
33
  });
@@ -44,6 +62,8 @@ export declare class Window {
44
62
  private _on_message;
45
63
  private _parseParams;
46
64
  private _handleMenuClick;
65
+ private _invokeEventCallback;
66
+ private _notifyClosed;
47
67
  private _handleContextMenu;
48
68
  private _handleExposedFunction;
49
69
  private _sendSuccessResponse;
@@ -1 +1 @@
1
- {"version":3,"file":"window.d.ts","sourceRoot":"","sources":["../src/window.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,eAAe,EAAE,aAAa,EAAE,MAAM,YAAY,CAAC;AAG5D,qBAAa,MAAM;IAClB,QAAQ,EAAE,GAAG,CAAC;IACd,OAAO,EAAE,aAAa,CAAC;IAEvB,OAAO,CAAC,UAAU,CAAM;IACxB,OAAO,CAAC,cAAc,CAAgB;IACtC,OAAO,CAAC,cAAc,CAAc;IACpC,OAAO,CAAC,cAAc,CAAsC;IAC5D,OAAO,CAAC,iBAAiB,CAA8B;IACvD,OAAO,CAAC,SAAS,CAAkB;IACnC,OAAO,CAAC,oBAAoB,CAAuB;IAEnD,eAAe,EAAE,CAChB,KAAK,EAAE,GAAG,EAAE,KACR,eAAe,EAAE,GAAG,IAAI,GAAG,OAAO,CAAC,eAAe,EAAE,GAAG,IAAI,CAAC,CAC3D;gBAGL,QAAQ,EAAE,GAAG,EACb,OAAO,EAAE,aAAa,EACtB,gBAAgB,EAAE;QAAE,CAAC,GAAG,EAAE,MAAM,GAAG,QAAQ,CAAA;KAAE;IAkB9C,IAAI,MAAM,kBAET;IAED,IAAI,SAAS,YAEZ;IAEK,GAAG;YAiBK,KAAK;IAoCb,QAAQ,CAAC,MAAM,EAAE,MAAM,EAAE,KAAK,CAAC,EAAE,MAAM,GAAG,MAAM,GAAG,OAAO,CAAC,GAAG,CAAC;IAS/D,KAAK;IAQL,OAAO;IAKP,QAAQ;IAGR,OAAO;IAGP,QAAQ;IAGR,KAAK;IAGL,IAAI;IAGJ,IAAI;IAKJ,OAAO;IAGP,OAAO,CAAC,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM;IAGrC,MAAM,CAAC,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM;IAIpC,UAAU;IAGV,UAAU,CAAC,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM;IAIxC,WAAW;IAGX,WAAW,CAAC,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,MAAM;IAGhC,IAAI,CAAC,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,MAAM;IAKzB,QAAQ,CAAC,KAAK,EAAE,MAAM;IAKtB,YAAY;IAGZ,YAAY;IAKZ,OAAO,CAAC,QAAQ,EAAE,MAAM;IAKxB,UAAU;IAGV,SAAS,CACd,IAAI,EAAE,MAAM,EACZ,KAAK,EAAE,MAAM,EACb,MAAM,GAAE,MAAW,EACnB,IAAI,GAAE,MAAY;IAIb,YAAY;YAIJ,WAAW;IA2DzB,OAAO,CAAC,YAAY;IAsBpB,OAAO,CAAC,gBAAgB;YAOV,kBAAkB;YAYlB,sBAAsB;YAmBtB,oBAAoB;YAUpB,kBAAkB;IAUhC,OAAO,CAAC,YAAY;CAkBpB"}
1
+ {"version":3,"file":"window.d.ts","sourceRoot":"","sources":["../src/window.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,eAAe,EAAE,aAAa,EAAE,MAAM,YAAY,CAAC;AAG5D,qBAAa,MAAM;IAClB,QAAQ,EAAE,GAAG,CAAC;IACd,OAAO,EAAE,aAAa,CAAC;IAEvB,OAAO,CAAC,UAAU,CAAM;IACxB,OAAO,CAAC,cAAc,CAAgB;IACtC,OAAO,CAAC,cAAc,CAAc;IACpC,OAAO,CAAC,cAAc,CAAsC;IAC5D,OAAO,CAAC,iBAAiB,CAA8B;IACvD,OAAO,CAAC,SAAS,CAAkB;IACnC,OAAO,CAAC,cAAc,CAAkB;IACxC,OAAO,CAAC,oBAAoB,CAAuB;IAEnD,eAAe,EAAE,CAChB,KAAK,EAAE,GAAG,EAAE,KACR,eAAe,EAAE,GAAG,IAAI,GAAG,OAAO,CAAC,eAAe,EAAE,GAAG,IAAI,CAAC,CAC3D;IAEN,QAAQ,EAAE,MAAM,IAAI,CAAY;IAChC,OAAO,EAAE,MAAM,IAAI,CAAY;IAC/B,OAAO,EAAE,MAAM,IAAI,CAAY;IAC/B,SAAS,EAAE,CAAC,IAAI,EAAE;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAA;KAAE,KAAK,IAAI,CACjE;IACV,OAAO,EAAE,CAAC,GAAG,EAAE;QAAE,CAAC,EAAE,MAAM,CAAC;QAAC,CAAC,EAAE,MAAM,CAAA;KAAE,KAAK,IAAI,CAAY;IAC5D,QAAQ,EAAE,MAAM,IAAI,CAAY;IAChC,OAAO,EAAE,MAAM,IAAI,CAAY;IAC/B,WAAW,EAAE,MAAM,IAAI,CAAY;IACnC,WAAW,EAAE,MAAM,IAAI,CAAY;IACnC,UAAU,EAAE,MAAM,IAAI,CAAY;gBAGjC,QAAQ,EAAE,GAAG,EACb,OAAO,EAAE,aAAa,EACtB,gBAAgB,EAAE;QAAE,CAAC,GAAG,EAAE,MAAM,GAAG,QAAQ,CAAA;KAAE;IA8B9C,IAAI,MAAM,kBAET;IAED,IAAI,SAAS,YAEZ;IAEK,GAAG;YAiBK,KAAK;IAoCb,QAAQ,CAAC,MAAM,EAAE,MAAM,EAAE,KAAK,CAAC,EAAE,MAAM,GAAG,MAAM,GAAG,OAAO,CAAC,GAAG,CAAC;IAS/D,KAAK;IAUL,OAAO;IAKP,QAAQ;IAGR,OAAO;IAGP,QAAQ;IAGR,KAAK;IAGL,IAAI;IAGJ,IAAI;IAKJ,OAAO;IAGP,OAAO,CAAC,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM;IAGrC,MAAM,CAAC,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM;IAIpC,UAAU;IAGV,UAAU,CAAC,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM;IAIxC,WAAW;IAGX,WAAW,CAAC,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,MAAM;IAGhC,IAAI,CAAC,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,MAAM;IAKzB,QAAQ,CAAC,KAAK,EAAE,MAAM;IAKtB,YAAY;IAGZ,YAAY;IAKZ,OAAO,CAAC,QAAQ,EAAE,MAAM;IAKxB,UAAU;IAGV,SAAS,CACd,IAAI,EAAE,MAAM,EACZ,KAAK,EAAE,MAAM,EACb,MAAM,GAAE,MAAW,EACnB,IAAI,GAAE,MAAY;IAIb,YAAY;YAIJ,WAAW;IAuFzB,OAAO,CAAC,YAAY;IAsBpB,OAAO,CAAC,gBAAgB;IAOxB,OAAO,CAAC,oBAAoB;IAa5B,OAAO,CAAC,aAAa;YAOP,kBAAkB;YAYlB,sBAAsB;YAmBtB,oBAAoB;YAUpB,kBAAkB;IAUhC,OAAO,CAAC,YAAY;CAkBpB"}
package/dist/window.js CHANGED
@@ -8,12 +8,44 @@ export class Window {
8
8
  _menuCallbacks = new Map();
9
9
  _exposedFunctions;
10
10
  _isClosed = false;
11
+ _closeNotified = false;
11
12
  _pendingApiInjection = null;
12
13
  on_context_menu = () => null;
14
+ on_close = () => { };
15
+ on_show = () => { };
16
+ on_hide = () => { };
17
+ on_resize = () => { };
18
+ on_move = () => { };
19
+ on_focus = () => { };
20
+ on_blur = () => { };
21
+ on_maximize = () => { };
22
+ on_minimize = () => { };
23
+ on_restore = () => { };
13
24
  constructor(platform, options, exposedFunctions) {
14
25
  this.platform = platform;
15
26
  this.options = { ...options };
16
27
  this._exposedFunctions = exposedFunctions;
28
+ // Initialize event callbacks from options
29
+ if (options.on_close)
30
+ this.on_close = options.on_close;
31
+ if (options.on_show)
32
+ this.on_show = options.on_show;
33
+ if (options.on_hide)
34
+ this.on_hide = options.on_hide;
35
+ if (options.on_resize)
36
+ this.on_resize = options.on_resize;
37
+ if (options.on_move)
38
+ this.on_move = options.on_move;
39
+ if (options.on_focus)
40
+ this.on_focus = options.on_focus;
41
+ if (options.on_blur)
42
+ this.on_blur = options.on_blur;
43
+ if (options.on_maximize)
44
+ this.on_maximize = options.on_maximize;
45
+ if (options.on_minimize)
46
+ this.on_minimize = options.on_minimize;
47
+ if (options.on_restore)
48
+ this.on_restore = options.on_restore;
17
49
  this._closedPromise = new Promise((resolve) => {
18
50
  this._resolveClosed = resolve;
19
51
  });
@@ -86,12 +118,15 @@ export class Window {
86
118
  if (this._isClosed)
87
119
  return;
88
120
  this._isClosed = true;
89
- const result = await this._call("close");
90
- this._resolveClosed();
91
- return result;
121
+ try {
122
+ return await this._call("close");
123
+ }
124
+ finally {
125
+ this._notifyClosed();
126
+ }
92
127
  }
93
128
  async destroy() {
94
- return this._call("close");
129
+ return this.close();
95
130
  }
96
131
  // Window state methods
97
132
  async maximize() {
@@ -174,7 +209,38 @@ export class Window {
174
209
  // Handle special messages
175
210
  if (funcName === "closed") {
176
211
  this._isClosed = true;
177
- this._resolveClosed();
212
+ this._notifyClosed();
213
+ return null;
214
+ }
215
+ if (funcName === "resized") {
216
+ const size = params[0];
217
+ this._invokeEventCallback("on_resize", size);
218
+ if (size.state === "maximized")
219
+ this._invokeEventCallback("on_maximize");
220
+ else if (size.state === "minimized")
221
+ this._invokeEventCallback("on_minimize");
222
+ else if (size.state === "normal")
223
+ this._invokeEventCallback("on_restore");
224
+ return null;
225
+ }
226
+ if (funcName === "moved") {
227
+ this._invokeEventCallback("on_move", params[0]);
228
+ return null;
229
+ }
230
+ if (funcName === "visibility_changed") {
231
+ const visible = params[0];
232
+ if (visible)
233
+ this._invokeEventCallback("on_show");
234
+ else
235
+ this._invokeEventCallback("on_hide");
236
+ return null;
237
+ }
238
+ if (funcName === "focus_changed") {
239
+ const focused = params[0];
240
+ if (focused)
241
+ this._invokeEventCallback("on_focus");
242
+ else
243
+ this._invokeEventCallback("on_blur");
178
244
  return null;
179
245
  }
180
246
  if (funcName === "dom_ready") {
@@ -231,6 +297,24 @@ export class Window {
231
297
  callback();
232
298
  return null;
233
299
  }
300
+ _invokeEventCallback(name, ...args) {
301
+ const instanceCallback = this[name];
302
+ const optionCallback = this.options[name];
303
+ const callback = typeof instanceCallback === "function"
304
+ ? instanceCallback
305
+ : typeof optionCallback === "function"
306
+ ? optionCallback
307
+ : null;
308
+ if (callback)
309
+ callback(...args);
310
+ }
311
+ _notifyClosed() {
312
+ if (this._closeNotified)
313
+ return;
314
+ this._closeNotified = true;
315
+ this._invokeEventCallback("on_close");
316
+ this._resolveClosed();
317
+ }
234
318
  async _handleContextMenu(params) {
235
319
  if (this.on_context_menu) {
236
320
  const customMenu = await this.on_context_menu(params);
Binary file
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "ewvjs",
3
- "version": "1.0.19",
3
+ "version": "1.0.21",
4
4
  "description": "Embedded WebView for JavaScript - Edge WebView2 bindings for Node.js",
5
5
  "workspaces": [
6
6
  "packages/*"
@@ -48,11 +48,11 @@
48
48
  ],
49
49
  "devDependencies": {
50
50
  "@types/mime-types": "^3.0.1",
51
- "@types/node": "^25.2.0",
51
+ "@types/node": "^25.9.1",
52
52
  "typescript": "^5.9.3"
53
53
  },
54
54
  "dependencies": {
55
55
  "mime-types": "^3.0.2",
56
56
  "node-api-dotnet": "^0.9.19"
57
57
  }
58
- }
58
+ }