@owear/core 0.1.0 → 0.1.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.
- package/dist/app.d.ts +122 -0
- package/dist/app.js +276 -0
- package/dist/bridge.d.ts +79 -0
- package/dist/bridge.js +55 -0
- package/dist/browserwindow.d.ts +113 -0
- package/dist/browserwindow.js +226 -0
- package/dist/channel.d.ts +22 -0
- package/dist/channel.js +114 -0
- package/dist/dialog.d.ts +47 -0
- package/dist/dialog.js +22 -0
- package/dist/index.d.ts +76 -96
- package/dist/index.js +24 -253
- package/dist/installer.d.ts +112 -0
- package/dist/installer.js +72 -0
- package/dist/ipc/node.d.ts +7 -0
- package/dist/ipc/node.js +25 -0
- package/dist/menu.d.ts +56 -0
- package/dist/menu.js +208 -0
- package/dist/modules.d.ts +16 -0
- package/dist/modules.js +13 -0
- package/dist/nativeimage.d.ts +41 -0
- package/dist/nativeimage.js +376 -0
- package/dist/node/worker-runner.d.ts +1 -0
- package/dist/node/worker-runner.js +35 -0
- package/dist/node/worker.d.ts +29 -0
- package/dist/node/worker.js +61 -0
- package/dist/port.d.ts +28 -0
- package/dist/port.js +42 -0
- package/dist/power.d.ts +33 -0
- package/dist/power.js +99 -0
- package/dist/protocol.d.ts +14 -0
- package/dist/protocol.js +46 -0
- package/dist/safestorage.d.ts +16 -0
- package/dist/safestorage.js +21 -0
- package/dist/screen.d.ts +92 -0
- package/dist/screen.js +121 -0
- package/dist/session.d.ts +24 -0
- package/dist/session.js +42 -0
- package/dist/theme.d.ts +30 -0
- package/dist/theme.js +34 -0
- package/dist/tray.d.ts +30 -0
- package/dist/tray.js +69 -0
- package/dist/webcontents.d.ts +44 -0
- package/dist/webcontents.js +109 -0
- package/dist/webrequest.d.ts +23 -0
- package/dist/webrequest.js +76 -0
- package/package.json +4 -3
package/dist/index.js
CHANGED
|
@@ -13,258 +13,29 @@
|
|
|
13
13
|
// win.loadURL('http://localhost:5173')
|
|
14
14
|
// })
|
|
15
15
|
//
|
|
16
|
-
import * as net from 'node:net';
|
|
17
|
-
import { EventEmitter } from 'node:events';
|
|
18
16
|
import * as os from 'node:os';
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
this.buffer = this.buffer.slice(idx + 1);
|
|
44
|
-
if (line.trim())
|
|
45
|
-
this.handleLine(line);
|
|
46
|
-
}
|
|
47
|
-
});
|
|
48
|
-
sock.on('close', () => {
|
|
49
|
-
this.socket = null;
|
|
50
|
-
this.rejectAllPending(new Error('conexión cerrada'));
|
|
51
|
-
this.emit('disconnected');
|
|
52
|
-
});
|
|
53
|
-
});
|
|
54
|
-
}
|
|
55
|
-
rejectAllPending(err) {
|
|
56
|
-
for (const { reject } of this.pending.values()) {
|
|
57
|
-
reject(err);
|
|
58
|
-
}
|
|
59
|
-
this.pending.clear();
|
|
60
|
-
}
|
|
61
|
-
handleLine(line) {
|
|
62
|
-
let msg;
|
|
63
|
-
try {
|
|
64
|
-
msg = JSON.parse(line);
|
|
65
|
-
}
|
|
66
|
-
catch {
|
|
67
|
-
return;
|
|
68
|
-
}
|
|
69
|
-
if (msg.event) {
|
|
70
|
-
this.emit(msg.event, msg.params);
|
|
71
|
-
return;
|
|
72
|
-
}
|
|
73
|
-
const p = this.pending.get(msg.id);
|
|
74
|
-
if (!p)
|
|
75
|
-
return;
|
|
76
|
-
this.pending.delete(msg.id);
|
|
77
|
-
if (msg.ok)
|
|
78
|
-
p.resolve(msg.result);
|
|
79
|
-
else
|
|
80
|
-
p.reject(new Error(msg.error ?? 'error de control'));
|
|
81
|
-
}
|
|
82
|
-
call(cmd, params = {}) {
|
|
83
|
-
if (!this.socket)
|
|
84
|
-
return Promise.reject(new Error('control socket desconectado'));
|
|
85
|
-
const id = this.nextId++;
|
|
86
|
-
return new Promise((resolve, reject) => {
|
|
87
|
-
this.pending.set(id, { resolve, reject });
|
|
88
|
-
this.socket.write(JSON.stringify({ id, cmd, params }) + '\n');
|
|
89
|
-
});
|
|
90
|
-
}
|
|
91
|
-
}
|
|
92
|
-
// ── app ─────────────────────────────────────────────────────────────────────
|
|
93
|
-
const channel = new ControlChannel();
|
|
94
|
-
function socketPathFromEnv() {
|
|
95
|
-
if (process.env.OW_CONTROL_SOCKET)
|
|
96
|
-
return process.env.OW_CONTROL_SOCKET;
|
|
97
|
-
// fallback: último socket vivo en XDG_RUNTIME_DIR (útil para depurar)
|
|
98
|
-
const dir = process.env.XDG_RUNTIME_DIR;
|
|
99
|
-
if (dir) {
|
|
100
|
-
try {
|
|
101
|
-
const socks = fs
|
|
102
|
-
.readdirSync(dir)
|
|
103
|
-
.filter((f) => f.startsWith('owear-') && f.endsWith('.sock'))
|
|
104
|
-
.sort();
|
|
105
|
-
if (socks.length)
|
|
106
|
-
return path.join(dir, socks[socks.length - 1]);
|
|
107
|
-
}
|
|
108
|
-
catch {
|
|
109
|
-
/* noop */
|
|
110
|
-
}
|
|
111
|
-
}
|
|
112
|
-
throw new Error('Owear: OW_CONTROL_SOCKET no definida. Lanza la app con `ow dev` o `ow build && owear`.');
|
|
113
|
-
}
|
|
114
|
-
let readyPromise = null;
|
|
115
|
-
export const app = {
|
|
116
|
-
/** Conecta con el kernel. Resuelve cuando el canal de control está listo. */
|
|
117
|
-
whenReady() {
|
|
118
|
-
if (!readyPromise) {
|
|
119
|
-
readyPromise = channel.connect(socketPathFromEnv()).then(() => undefined);
|
|
120
|
-
}
|
|
121
|
-
return readyPromise;
|
|
122
|
-
},
|
|
123
|
-
quit(exitCode = 0) {
|
|
124
|
-
return channel.call('app.quit', { exitCode }).catch(() => undefined);
|
|
125
|
-
},
|
|
126
|
-
info() {
|
|
127
|
-
return channel.call('app.info');
|
|
128
|
-
},
|
|
129
|
-
/**
|
|
130
|
-
* Localiza (o descarga) un runtime Node. Prioridad: OW_NODE_BIN → Node del
|
|
131
|
-
* sistema → caché de Owear → descarga oficial. `source` indica de dónde
|
|
132
|
-
* salió ("env" | "system" | "cache" | "downloaded").
|
|
133
|
-
*/
|
|
134
|
-
ensureNodeRuntime(range = 'latest') {
|
|
135
|
-
return channel.call('node.ensure', { range });
|
|
136
|
-
},
|
|
137
|
-
/** Acceso crudo al canal (para módulos custom del SDK). */
|
|
138
|
-
__channel: channel,
|
|
139
|
-
};
|
|
140
|
-
/**
|
|
141
|
-
* Invoca una función de un módulo nativo del kernel desde el proceso
|
|
142
|
-
* principal (fs, process, net, clipboard…). Es el equivalente de `ow.invoke()`
|
|
143
|
-
* del renderer, pero sin depender de una ventana: es la pieza que permite
|
|
144
|
-
* portar APIs de Electron al main process.
|
|
145
|
-
*
|
|
146
|
-
* const txt = await invokeNative<string>('fs', 'readText', '/etc/hostname')
|
|
147
|
-
*/
|
|
148
|
-
export function invokeNative(module, method, ...args) {
|
|
149
|
-
return channel.call('module.invoke', { module, method, args });
|
|
150
|
-
}
|
|
151
|
-
/** Módulos nativos cargados, con versión, origen y funciones. */
|
|
152
|
-
export function listNativeModules() {
|
|
153
|
-
return channel.call('module.list');
|
|
154
|
-
}
|
|
155
|
-
/** Metadatos de un módulo nativo concreto. Rechaza si no existe. */
|
|
156
|
-
export function nativeModuleInfo(name) {
|
|
157
|
-
return channel.call('module.info', { name });
|
|
158
|
-
}
|
|
159
|
-
// ── BrowserWindow ───────────────────────────────────────────────────────────
|
|
160
|
-
export class BrowserWindow extends EventEmitter {
|
|
161
|
-
_id = null;
|
|
162
|
-
_options;
|
|
163
|
-
_onWindowEvent;
|
|
164
|
-
_onDisconnected;
|
|
165
|
-
constructor(options = {}) {
|
|
166
|
-
super();
|
|
167
|
-
this._options = options;
|
|
168
|
-
if (!readyPromise) {
|
|
169
|
-
throw new Error('BrowserWindow creado antes de app.whenReady()');
|
|
170
|
-
}
|
|
171
|
-
this._onWindowEvent = (params) => {
|
|
172
|
-
if (params.windowId !== this._id)
|
|
173
|
-
return;
|
|
174
|
-
this.emit(params.name, params.payload);
|
|
175
|
-
if (params.name === 'closed')
|
|
176
|
-
this._unwireEvents();
|
|
177
|
-
};
|
|
178
|
-
this._onDisconnected = () => this.emit('disconnected');
|
|
179
|
-
readyPromise.then(() => this._create()).catch((e) => this.emit('error', e));
|
|
180
|
-
}
|
|
181
|
-
async _create() {
|
|
182
|
-
const params = { ...this._options };
|
|
183
|
-
const res = await channel.call('window.create', params);
|
|
184
|
-
this._id = res.windowId;
|
|
185
|
-
this._wireEvents();
|
|
186
|
-
this.emit('ready-to-show', this._id);
|
|
187
|
-
}
|
|
188
|
-
_wireEvents() {
|
|
189
|
-
channel.on('window.event', this._onWindowEvent);
|
|
190
|
-
channel.on('disconnected', this._onDisconnected);
|
|
191
|
-
}
|
|
192
|
-
_unwireEvents() {
|
|
193
|
-
channel.off('window.event', this._onWindowEvent);
|
|
194
|
-
channel.off('disconnected', this._onDisconnected);
|
|
195
|
-
}
|
|
196
|
-
get id() {
|
|
197
|
-
return this._id;
|
|
198
|
-
}
|
|
199
|
-
requireId() {
|
|
200
|
-
if (this._id == null)
|
|
201
|
-
throw new Error('ventana aún no creada');
|
|
202
|
-
return this._id;
|
|
203
|
-
}
|
|
204
|
-
// ── carga ──────────────────────────────────────────────────────────────
|
|
205
|
-
loadURL(url) {
|
|
206
|
-
return channel.call('window.loadURL', { windowId: this.requireId(), url });
|
|
207
|
-
}
|
|
208
|
-
/** Evalúa JS; devuelve el resultado JSON-serializado. */
|
|
209
|
-
eval(js) {
|
|
210
|
-
return channel.call('window.eval', { windowId: this.requireId(), js });
|
|
211
|
-
}
|
|
212
|
-
// ── ciclo de vida ──────────────────────────────────────────────────────
|
|
213
|
-
show() {
|
|
214
|
-
return channel.call('window.show', { windowId: this.requireId() });
|
|
215
|
-
}
|
|
216
|
-
hide() {
|
|
217
|
-
return channel.call('window.hide', { windowId: this.requireId() });
|
|
218
|
-
}
|
|
219
|
-
focus() {
|
|
220
|
-
return channel.call('window.focus', { windowId: this.requireId() });
|
|
221
|
-
}
|
|
222
|
-
close() {
|
|
223
|
-
return channel.call('window.close', { windowId: this.requireId() });
|
|
224
|
-
}
|
|
225
|
-
destroy() {
|
|
226
|
-
return channel.call('window.destroy', { windowId: this.requireId() });
|
|
227
|
-
}
|
|
228
|
-
minimize() {
|
|
229
|
-
return channel.call('window.minimize', { windowId: this.requireId() });
|
|
230
|
-
}
|
|
231
|
-
maximize() {
|
|
232
|
-
return channel.call('window.maximize', { windowId: this.requireId(), enabled: true });
|
|
233
|
-
}
|
|
234
|
-
unmaximize() {
|
|
235
|
-
return channel.call('window.maximize', { windowId: this.requireId(), enabled: false });
|
|
236
|
-
}
|
|
237
|
-
setFullScreen(enabled) {
|
|
238
|
-
return channel.call('window.setFullScreen', { windowId: this.requireId(), enabled });
|
|
239
|
-
}
|
|
240
|
-
/**
|
|
241
|
-
* Responde a un `closeRequested` (F3.4).
|
|
242
|
-
* `allow=false` cancela el cierre; `true` destruye la ventana.
|
|
243
|
-
* Si nadie responde en `OW_CLOSE_TIMEOUT_MS` (default 1000 ms), el kernel
|
|
244
|
-
* cierra igualmente.
|
|
245
|
-
*/
|
|
246
|
-
closeRespond(requestId, allow) {
|
|
247
|
-
return channel.call('window.respondCloseRequest', {
|
|
248
|
-
windowId: this.requireId(),
|
|
249
|
-
requestId,
|
|
250
|
-
allow,
|
|
251
|
-
});
|
|
252
|
-
}
|
|
253
|
-
// ── estado ─────────────────────────────────────────────────────────────
|
|
254
|
-
isMaximized() {
|
|
255
|
-
return channel.call('window.isMaximized', { windowId: this.requireId() });
|
|
256
|
-
}
|
|
257
|
-
isMinimized() {
|
|
258
|
-
return channel.call('window.isMinimized', { windowId: this.requireId() });
|
|
259
|
-
}
|
|
260
|
-
getBounds() {
|
|
261
|
-
return channel.call('window.getBounds', { windowId: this.requireId() });
|
|
262
|
-
}
|
|
263
|
-
setBounds(b) {
|
|
264
|
-
return channel.call('window.setBounds', { windowId: this.requireId(), ...b });
|
|
265
|
-
}
|
|
266
|
-
setTitle(title) {
|
|
267
|
-
return channel.call('window.setTitle', { windowId: this.requireId(), title });
|
|
268
|
-
}
|
|
269
|
-
}
|
|
17
|
+
export { NativeImage, nativeImage } from './nativeimage.js';
|
|
18
|
+
export { invokeNative } from './channel.js';
|
|
19
|
+
export { listNativeModules, nativeModuleInfo } from './modules.js';
|
|
20
|
+
export { theme, nativeTheme } from './theme.js';
|
|
21
|
+
export { screen } from './screen.js';
|
|
22
|
+
export { powerMonitor, powerSaveBlocker } from './power.js';
|
|
23
|
+
export { safeStorage } from './safestorage.js';
|
|
24
|
+
export { session } from './session.js';
|
|
25
|
+
export { webRequest } from './webrequest.js';
|
|
26
|
+
export { dialog } from './dialog.js';
|
|
27
|
+
export { WebContents } from './webcontents.js';
|
|
28
|
+
export { BrowserWindow } from './browserwindow.js';
|
|
29
|
+
export { MenuItem, Menu } from './menu.js';
|
|
30
|
+
export { Tray } from './tray.js';
|
|
31
|
+
export { nodeHandlers, nodeContextHandlers } from './ipc/node.js';
|
|
32
|
+
export { protocolHandlers } from './protocol.js';
|
|
33
|
+
export { portRecords, makeMainPort, allocPortId } from './port.js';
|
|
34
|
+
export { app } from './app.js';
|
|
35
|
+
export { readyPromise } from './app.js';
|
|
36
|
+
// ── instalador (D1): bridge + API del modo instalador/desinstalador ──────────
|
|
37
|
+
export { installer } from './installer.js';
|
|
38
|
+
export { defineBridge } from './bridge.js';
|
|
39
|
+
// ── workers Node (utilityProcess.fork) ──────────────────────────────────────
|
|
40
|
+
export { forkWorker, resolveWorkerEntry } from './node/worker.js';
|
|
270
41
|
export const platform = os.platform();
|
|
@@ -0,0 +1,112 @@
|
|
|
1
|
+
export type InstallerMode = 'app' | 'installer' | 'uninstaller';
|
|
2
|
+
/** Entrada del plan de instalación (ruta en payload → destino). */
|
|
3
|
+
export interface PayloadEntry {
|
|
4
|
+
/** Ruta relativa dentro del payload embebido. */
|
|
5
|
+
rel: string;
|
|
6
|
+
/** Ruta destino (relativa al directorio de instalación). */
|
|
7
|
+
dst: string;
|
|
8
|
+
size: number;
|
|
9
|
+
dir: boolean;
|
|
10
|
+
}
|
|
11
|
+
/** Metadatos de la app que se instala (de `installer.json`). */
|
|
12
|
+
export interface InstallerInfo {
|
|
13
|
+
appId?: string;
|
|
14
|
+
appName?: string;
|
|
15
|
+
version?: string;
|
|
16
|
+
mode?: InstallerMode;
|
|
17
|
+
publisher?: string;
|
|
18
|
+
icon?: string;
|
|
19
|
+
[k: string]: unknown;
|
|
20
|
+
}
|
|
21
|
+
export interface PlanOptions {
|
|
22
|
+
/** `minimal` = binario único; `layout` = árbol organizado. */
|
|
23
|
+
mode?: 'minimal' | 'layout';
|
|
24
|
+
/** `flat` = basename; `tree` = ruta relativa (default según mode). */
|
|
25
|
+
layout?: 'flat' | 'tree';
|
|
26
|
+
/** Orden de colocación (prefijos de ruta o grupos). */
|
|
27
|
+
order?: string[];
|
|
28
|
+
}
|
|
29
|
+
export interface InstallOptions extends PlanOptions {
|
|
30
|
+
/** Directorio de instalación. */
|
|
31
|
+
dir: string;
|
|
32
|
+
/** Ruta del desinstalador (si se indica, se registra en el S.O.). */
|
|
33
|
+
uninstaller?: string;
|
|
34
|
+
/** Publisher para el registro de desinstalación. */
|
|
35
|
+
publisher?: string;
|
|
36
|
+
}
|
|
37
|
+
export interface InstallResult {
|
|
38
|
+
installed: boolean;
|
|
39
|
+
dir: string;
|
|
40
|
+
mode: string;
|
|
41
|
+
files: number;
|
|
42
|
+
}
|
|
43
|
+
export interface UninstallResult {
|
|
44
|
+
removed: number;
|
|
45
|
+
dir: string;
|
|
46
|
+
}
|
|
47
|
+
export interface VerifyResult {
|
|
48
|
+
ok: boolean;
|
|
49
|
+
mismatches: string[];
|
|
50
|
+
}
|
|
51
|
+
export interface StateResult {
|
|
52
|
+
installed: boolean;
|
|
53
|
+
version?: string;
|
|
54
|
+
mode?: string;
|
|
55
|
+
app?: string;
|
|
56
|
+
}
|
|
57
|
+
export interface ShortcutOptions {
|
|
58
|
+
execPath: string;
|
|
59
|
+
iconPath?: string;
|
|
60
|
+
desktop?: boolean;
|
|
61
|
+
menu?: boolean;
|
|
62
|
+
startup?: boolean;
|
|
63
|
+
}
|
|
64
|
+
export interface LaunchOptions {
|
|
65
|
+
path: string;
|
|
66
|
+
args?: string[];
|
|
67
|
+
}
|
|
68
|
+
/**
|
|
69
|
+
* API del modo instalador. Requiere un binario compilado como instalador
|
|
70
|
+
* (payload embebido + `OW_MODE=installer`).
|
|
71
|
+
*/
|
|
72
|
+
export declare const installer: {
|
|
73
|
+
/** Modo del binario actual: 'app' | 'installer' | 'uninstaller'. */
|
|
74
|
+
mode(): Promise<InstallerMode>;
|
|
75
|
+
/** Metadatos de la app a instalar (config empaquetada por `ow build`). */
|
|
76
|
+
info(): Promise<InstallerInfo>;
|
|
77
|
+
/** Bridge embebido (contrato app ↔ installer). */
|
|
78
|
+
bridge<T = unknown>(): Promise<T | null>;
|
|
79
|
+
/** Lista los ficheros del payload embebido. */
|
|
80
|
+
payloadList(): Promise<PayloadEntry[]>;
|
|
81
|
+
/** Lee un fichero del payload (base64). */
|
|
82
|
+
payloadRead(path: string): Promise<{
|
|
83
|
+
path: string;
|
|
84
|
+
data: string;
|
|
85
|
+
size: number;
|
|
86
|
+
}>;
|
|
87
|
+
/** Plan de instalación (sin escribir nada). */
|
|
88
|
+
plan(opts?: PlanOptions): Promise<PayloadEntry[]>;
|
|
89
|
+
/** Instala el payload en `dir` (respeta `order`/`layout`). */
|
|
90
|
+
install(opts: InstallOptions): Promise<InstallResult>;
|
|
91
|
+
/** Desinstala (usa el manifiesto guardado en `dir`). */
|
|
92
|
+
uninstall(opts: {
|
|
93
|
+
dir: string;
|
|
94
|
+
keepData?: boolean;
|
|
95
|
+
}): Promise<UninstallResult>;
|
|
96
|
+
/** Verifica integridad de una instalación (hashes). */
|
|
97
|
+
verify(opts: {
|
|
98
|
+
dir: string;
|
|
99
|
+
}): Promise<VerifyResult>;
|
|
100
|
+
/** Estado de instalación en `dir`. */
|
|
101
|
+
state(opts: {
|
|
102
|
+
dir: string;
|
|
103
|
+
}): Promise<StateResult>;
|
|
104
|
+
/** Crea accesos directos / integración de escritorio. */
|
|
105
|
+
shortcuts(opts: ShortcutOptions): Promise<boolean>;
|
|
106
|
+
/** Lanza un ejecutable en segundo plano (p. ej. la app instalada). */
|
|
107
|
+
launch(opts: LaunchOptions): Promise<boolean>;
|
|
108
|
+
/** ¿El proceso corre elevado (root/admin)? */
|
|
109
|
+
elevate(): Promise<{
|
|
110
|
+
elevated: boolean;
|
|
111
|
+
}>;
|
|
112
|
+
};
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
// Copyright 2026 Owear Contributors
|
|
2
|
+
// SPDX-License-Identifier: Apache-2.0
|
|
3
|
+
//
|
|
4
|
+
// @owear/core/src/installer.ts — API `installer` (modo instalador/desinstalador).
|
|
5
|
+
//
|
|
6
|
+
// Disponible en binarios compilados en modo installer/uninstaller (`OW_MODE`).
|
|
7
|
+
// El instalador es una app Owear aparte que lleva embebido el payload de la app
|
|
8
|
+
// y el bridge (contrato app ↔ installer).
|
|
9
|
+
//
|
|
10
|
+
// import { installer } from '@owear/core'
|
|
11
|
+
// const mode = await installer.mode() // 'installer'
|
|
12
|
+
// const plan = await installer.plan({ mode: 'minimal' })
|
|
13
|
+
// await installer.install({ dir: '~/.local/opt/miapp', mode: 'minimal' })
|
|
14
|
+
import { invokeNative } from './channel.js';
|
|
15
|
+
/**
|
|
16
|
+
* API del modo instalador. Requiere un binario compilado como instalador
|
|
17
|
+
* (payload embebido + `OW_MODE=installer`).
|
|
18
|
+
*/
|
|
19
|
+
export const installer = {
|
|
20
|
+
/** Modo del binario actual: 'app' | 'installer' | 'uninstaller'. */
|
|
21
|
+
mode() {
|
|
22
|
+
return invokeNative('installer', 'mode');
|
|
23
|
+
},
|
|
24
|
+
/** Metadatos de la app a instalar (config empaquetada por `ow build`). */
|
|
25
|
+
info() {
|
|
26
|
+
return invokeNative('installer', 'info');
|
|
27
|
+
},
|
|
28
|
+
/** Bridge embebido (contrato app ↔ installer). */
|
|
29
|
+
bridge() {
|
|
30
|
+
return invokeNative('installer', 'bridge');
|
|
31
|
+
},
|
|
32
|
+
/** Lista los ficheros del payload embebido. */
|
|
33
|
+
payloadList() {
|
|
34
|
+
return invokeNative('installer', 'payloadList');
|
|
35
|
+
},
|
|
36
|
+
/** Lee un fichero del payload (base64). */
|
|
37
|
+
payloadRead(path) {
|
|
38
|
+
return invokeNative('installer', 'payloadRead', { path });
|
|
39
|
+
},
|
|
40
|
+
/** Plan de instalación (sin escribir nada). */
|
|
41
|
+
plan(opts = {}) {
|
|
42
|
+
return invokeNative('installer', 'plan', opts);
|
|
43
|
+
},
|
|
44
|
+
/** Instala el payload en `dir` (respeta `order`/`layout`). */
|
|
45
|
+
install(opts) {
|
|
46
|
+
return invokeNative('installer', 'install', opts);
|
|
47
|
+
},
|
|
48
|
+
/** Desinstala (usa el manifiesto guardado en `dir`). */
|
|
49
|
+
uninstall(opts) {
|
|
50
|
+
return invokeNative('installer', 'uninstall', opts);
|
|
51
|
+
},
|
|
52
|
+
/** Verifica integridad de una instalación (hashes). */
|
|
53
|
+
verify(opts) {
|
|
54
|
+
return invokeNative('installer', 'verify', opts);
|
|
55
|
+
},
|
|
56
|
+
/** Estado de instalación en `dir`. */
|
|
57
|
+
state(opts) {
|
|
58
|
+
return invokeNative('installer', 'state', opts);
|
|
59
|
+
},
|
|
60
|
+
/** Crea accesos directos / integración de escritorio. */
|
|
61
|
+
shortcuts(opts) {
|
|
62
|
+
return invokeNative('installer', 'shortcuts', opts);
|
|
63
|
+
},
|
|
64
|
+
/** Lanza un ejecutable en segundo plano (p. ej. la app instalada). */
|
|
65
|
+
launch(opts) {
|
|
66
|
+
return invokeNative('installer', 'launch', opts);
|
|
67
|
+
},
|
|
68
|
+
/** ¿El proceso corre elevado (root/admin)? */
|
|
69
|
+
elevate() {
|
|
70
|
+
return invokeNative('installer', 'elevate');
|
|
71
|
+
},
|
|
72
|
+
};
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
export type NodeHandler = (...args: any[]) => unknown | Promise<unknown>;
|
|
2
|
+
/** Handler con contexto: recibe la ventana de origen y luego los args. */
|
|
3
|
+
export type ContextNodeHandler = (context: {
|
|
4
|
+
windowId: number;
|
|
5
|
+
}, ...args: any[]) => unknown | Promise<unknown>;
|
|
6
|
+
export declare const nodeHandlers: Map<string, NodeHandler>;
|
|
7
|
+
export declare const nodeContextHandlers: Map<string, ContextNodeHandler>;
|
package/dist/ipc/node.js
ADDED
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
// Copyright 2026 Owear Contributors
|
|
2
|
+
// SPDX-License-Identifier: Apache-2.0
|
|
3
|
+
//
|
|
4
|
+
// @owear/core/src/ipc/node.ts — puente Node (renderer ↔ main).
|
|
5
|
+
import { channel } from '../channel.js';
|
|
6
|
+
export const nodeHandlers = new Map();
|
|
7
|
+
export const nodeContextHandlers = new Map();
|
|
8
|
+
channel.on('node.request', (params) => {
|
|
9
|
+
const { reqId, fn, args, windowId } = params ?? {};
|
|
10
|
+
const handler = nodeHandlers.get(fn);
|
|
11
|
+
const ctxHandler = nodeContextHandlers.get(fn);
|
|
12
|
+
const argsArr = Array.isArray(args) ? args : args === undefined ? [] : [args];
|
|
13
|
+
Promise.resolve()
|
|
14
|
+
.then(() => ctxHandler
|
|
15
|
+
? ctxHandler({ windowId: typeof windowId === 'number' ? windowId : 0 }, ...argsArr)
|
|
16
|
+
: handler
|
|
17
|
+
? handler(...argsArr)
|
|
18
|
+
: undefined)
|
|
19
|
+
.then((result) => channel.call('node.respond', { reqId, ok: true, result }), (err) => channel.call('node.respond', {
|
|
20
|
+
reqId,
|
|
21
|
+
ok: false,
|
|
22
|
+
result: { message: err instanceof Error ? err.message : String(err) },
|
|
23
|
+
}))
|
|
24
|
+
.catch(() => undefined);
|
|
25
|
+
});
|
package/dist/menu.d.ts
ADDED
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
import { BrowserWindow } from './browserwindow.js';
|
|
2
|
+
export type MenuItemRole = 'undo' | 'redo' | 'cut' | 'copy' | 'paste' | 'pasteAndMatchStyle' | 'selectAll' | 'delete' | 'reload' | 'forceReload' | 'toggleDevTools' | 'resetZoom' | 'zoomIn' | 'zoomOut' | 'togglefullscreen' | 'minimize' | 'close' | 'quit' | 'about' | 'hide' | 'hideOthers' | 'unhide';
|
|
3
|
+
export interface MenuItemConstructorOptions {
|
|
4
|
+
id?: string;
|
|
5
|
+
label?: string;
|
|
6
|
+
role?: MenuItemRole;
|
|
7
|
+
type?: 'normal' | 'separator' | 'submenu' | 'checkbox' | 'radio';
|
|
8
|
+
checked?: boolean;
|
|
9
|
+
enabled?: boolean;
|
|
10
|
+
visible?: boolean;
|
|
11
|
+
accelerator?: string;
|
|
12
|
+
sublabel?: string;
|
|
13
|
+
toolTip?: string;
|
|
14
|
+
submenu?: Array<MenuItemConstructorOptions | MenuItem> | Menu;
|
|
15
|
+
click?: (menuItem: MenuItem, window: BrowserWindow | undefined) => void;
|
|
16
|
+
}
|
|
17
|
+
export declare class MenuItem {
|
|
18
|
+
id: string;
|
|
19
|
+
label: string;
|
|
20
|
+
role?: MenuItemRole;
|
|
21
|
+
type: 'normal' | 'separator' | 'submenu' | 'checkbox' | 'radio';
|
|
22
|
+
checked: boolean;
|
|
23
|
+
enabled: boolean;
|
|
24
|
+
visible: boolean;
|
|
25
|
+
accelerator?: string;
|
|
26
|
+
sublabel?: string;
|
|
27
|
+
toolTip?: string;
|
|
28
|
+
submenu?: Menu;
|
|
29
|
+
click?: (menuItem: MenuItem, window: BrowserWindow | undefined) => void;
|
|
30
|
+
constructor(opts?: MenuItemConstructorOptions, idHint?: string);
|
|
31
|
+
_toJSON(): Record<string, unknown>;
|
|
32
|
+
}
|
|
33
|
+
/**
|
|
34
|
+
* Menú (estilo Electron, "Owear"): se construye en el main y los clicks llaman
|
|
35
|
+
* handlers del main.
|
|
36
|
+
* Menu.setApplicationMenu(Menu.buildFromTemplate([...])) // menubar (Windows)
|
|
37
|
+
* menu.popup({ window: win }) // contextual
|
|
38
|
+
*/
|
|
39
|
+
export declare class Menu {
|
|
40
|
+
items: MenuItem[];
|
|
41
|
+
private static _appMenu;
|
|
42
|
+
constructor(items?: MenuItem[]);
|
|
43
|
+
static buildFromTemplate(template: Array<MenuItemConstructorOptions | MenuItem>, idPrefix?: string): Menu;
|
|
44
|
+
static setApplicationMenu(menu: Menu | null): void;
|
|
45
|
+
static getApplicationMenu(): Menu | null;
|
|
46
|
+
append(item: MenuItem): void;
|
|
47
|
+
/** JSON del menú (registra los items para el dispatch de clicks). */
|
|
48
|
+
_toJSON(): unknown[];
|
|
49
|
+
/** Menú contextual nativo. `window` resuelve el id del click. */
|
|
50
|
+
popup(options?: {
|
|
51
|
+
window?: BrowserWindow;
|
|
52
|
+
x?: number;
|
|
53
|
+
y?: number;
|
|
54
|
+
items?: Array<MenuItemConstructorOptions | MenuItem>;
|
|
55
|
+
}): void;
|
|
56
|
+
}
|