@owear/core 0.1.2 → 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.
Files changed (47) hide show
  1. package/dist/app.d.ts +122 -0
  2. package/dist/app.js +276 -0
  3. package/dist/bridge.d.ts +79 -0
  4. package/dist/bridge.js +55 -0
  5. package/dist/browserwindow.d.ts +113 -0
  6. package/dist/browserwindow.js +226 -0
  7. package/dist/channel.d.ts +22 -0
  8. package/dist/channel.js +114 -0
  9. package/dist/dialog.d.ts +47 -0
  10. package/dist/dialog.js +22 -0
  11. package/dist/index.d.ts +76 -96
  12. package/dist/index.js +24 -253
  13. package/dist/installer.d.ts +112 -0
  14. package/dist/installer.js +72 -0
  15. package/dist/ipc/node.d.ts +7 -0
  16. package/dist/ipc/node.js +25 -0
  17. package/dist/menu.d.ts +56 -0
  18. package/dist/menu.js +208 -0
  19. package/dist/modules.d.ts +16 -0
  20. package/dist/modules.js +13 -0
  21. package/dist/nativeimage.d.ts +41 -0
  22. package/dist/nativeimage.js +376 -0
  23. package/dist/node/worker-runner.d.ts +1 -0
  24. package/dist/node/worker-runner.js +35 -0
  25. package/dist/node/worker.d.ts +29 -0
  26. package/dist/node/worker.js +61 -0
  27. package/dist/port.d.ts +28 -0
  28. package/dist/port.js +42 -0
  29. package/dist/power.d.ts +33 -0
  30. package/dist/power.js +99 -0
  31. package/dist/protocol.d.ts +14 -0
  32. package/dist/protocol.js +46 -0
  33. package/dist/safestorage.d.ts +16 -0
  34. package/dist/safestorage.js +21 -0
  35. package/dist/screen.d.ts +92 -0
  36. package/dist/screen.js +121 -0
  37. package/dist/session.d.ts +24 -0
  38. package/dist/session.js +42 -0
  39. package/dist/theme.d.ts +30 -0
  40. package/dist/theme.js +34 -0
  41. package/dist/tray.d.ts +30 -0
  42. package/dist/tray.js +69 -0
  43. package/dist/webcontents.d.ts +44 -0
  44. package/dist/webcontents.js +109 -0
  45. package/dist/webrequest.d.ts +23 -0
  46. package/dist/webrequest.js +76 -0
  47. package/package.json +3 -2
@@ -0,0 +1,30 @@
1
+ export interface ThemeInfo {
2
+ dark: boolean;
3
+ source: 'system' | 'light' | 'dark';
4
+ highContrast: boolean;
5
+ reducedTransparency: boolean;
6
+ }
7
+ /**
8
+ * Tema nativo del sistema (módulo `theme`). `watch()` emite `theme.changed`
9
+ * (recibible con `channel.on('theme.changed', …)` o en el renderer con
10
+ * `ow.on('theme.changed', …)`).
11
+ */
12
+ export declare const theme: {
13
+ get(): Promise<ThemeInfo>;
14
+ isDark(): Promise<boolean>;
15
+ /** Fuerza la preferencia: 'system' | 'light' | 'dark'. También aplica el
16
+ * esquema al contenido (Windows: WebView2 `PreferredColorScheme`). */
17
+ setSource(source: "system" | "light" | "dark"): Promise<ThemeInfo>;
18
+ watch(): Promise<void>;
19
+ unwatch(): Promise<void>;
20
+ };
21
+ /** Alias estilo Electron de `theme`. */
22
+ export declare const nativeTheme: {
23
+ get(): Promise<ThemeInfo>;
24
+ isDark(): Promise<boolean>;
25
+ /** Fuerza la preferencia: 'system' | 'light' | 'dark'. También aplica el
26
+ * esquema al contenido (Windows: WebView2 `PreferredColorScheme`). */
27
+ setSource(source: "system" | "light" | "dark"): Promise<ThemeInfo>;
28
+ watch(): Promise<void>;
29
+ unwatch(): Promise<void>;
30
+ };
package/dist/theme.js ADDED
@@ -0,0 +1,34 @@
1
+ // Copyright 2026 Owear Contributors
2
+ // SPDX-License-Identifier: Apache-2.0
3
+ //
4
+ // @owear/core/src/theme.ts — nativeTheme (módulo `theme`).
5
+ import { channel, invokeNative } from './channel.js';
6
+ /**
7
+ * Tema nativo del sistema (módulo `theme`). `watch()` emite `theme.changed`
8
+ * (recibible con `channel.on('theme.changed', …)` o en el renderer con
9
+ * `ow.on('theme.changed', …)`).
10
+ */
11
+ export const theme = {
12
+ get() {
13
+ return invokeNative('theme', 'get');
14
+ },
15
+ isDark() {
16
+ return invokeNative('theme', 'isDark');
17
+ },
18
+ /** Fuerza la preferencia: 'system' | 'light' | 'dark'. También aplica el
19
+ * esquema al contenido (Windows: WebView2 `PreferredColorScheme`). */
20
+ async setSource(source) {
21
+ const info = await invokeNative('theme', 'setSource', source);
22
+ const scheme = source === 'dark' ? 2 : source === 'light' ? 1 : 0;
23
+ void channel.call('window.setColorScheme', { scheme }).catch(() => undefined);
24
+ return info;
25
+ },
26
+ watch() {
27
+ return invokeNative('theme', 'watch');
28
+ },
29
+ unwatch() {
30
+ return invokeNative('theme', 'unwatch');
31
+ },
32
+ };
33
+ /** Alias estilo Electron de `theme`. */
34
+ export const nativeTheme = theme;
package/dist/tray.d.ts ADDED
@@ -0,0 +1,30 @@
1
+ import { EventEmitter } from 'node:events';
2
+ import { Menu } from './menu.js';
3
+ import { NativeImage } from './nativeimage.js';
4
+ /** Tray actual (solo uno). Lo lee el ruteo de eventos del SDK. */
5
+ export declare let currentTray: Tray | null;
6
+ export interface TrayEvent {
7
+ button: 'left' | 'right' | 'double';
8
+ windowId: number;
9
+ }
10
+ /**
11
+ * Icono de bandeja (intermedio Tauri/Electron). El menú contextual reutiliza
12
+ * `Menu`. Eventos: `click`, `right-click`, `double-click`.
13
+ *
14
+ * const tray = new Tray(nativeImage.createFromPath('icon.png'))
15
+ * tray.setContextMenu(Menu.buildFromTemplate([{ label: 'Mostrar', click: () => win.show() }]))
16
+ * tray.on('click', () => win.show())
17
+ */
18
+ export declare class Tray extends EventEmitter {
19
+ private _menu;
20
+ private _id;
21
+ constructor(image?: NativeImage | string);
22
+ get id(): string;
23
+ setImage(image: NativeImage | string): void;
24
+ setPressedImage(image: NativeImage | string): void;
25
+ setToolTip(tip: string): void;
26
+ setTitle(title: string): void;
27
+ setContextMenu(menu: Menu | null): void;
28
+ popupContextMenu(menu?: Menu): void;
29
+ destroy(): void;
30
+ }
package/dist/tray.js ADDED
@@ -0,0 +1,69 @@
1
+ // Copyright 2026 Owear Contributors
2
+ // SPDX-License-Identifier: Apache-2.0
3
+ //
4
+ // @owear/core/src/tray.ts — Tray (C6).
5
+ import { EventEmitter } from 'node:events';
6
+ import { invokeNative } from './channel.js';
7
+ import { app } from './app.js';
8
+ import { nativeImage } from './nativeimage.js';
9
+ /** Tray actual (solo uno). Lo lee el ruteo de eventos del SDK. */
10
+ export let currentTray = null;
11
+ function toPngBase64(image) {
12
+ const img = typeof image === 'string' ? nativeImage.createFromPath(image) : image;
13
+ return img.toPNG().toString('base64');
14
+ }
15
+ /**
16
+ * Icono de bandeja (intermedio Tauri/Electron). El menú contextual reutiliza
17
+ * `Menu`. Eventos: `click`, `right-click`, `double-click`.
18
+ *
19
+ * const tray = new Tray(nativeImage.createFromPath('icon.png'))
20
+ * tray.setContextMenu(Menu.buildFromTemplate([{ label: 'Mostrar', click: () => win.show() }]))
21
+ * tray.on('click', () => win.show())
22
+ */
23
+ export class Tray extends EventEmitter {
24
+ _menu = null;
25
+ _id;
26
+ constructor(image) {
27
+ super();
28
+ this._id = `tray-${Math.random().toString(36).slice(2, 8)}`;
29
+ currentTray = this;
30
+ app
31
+ .whenReady()
32
+ .then(async () => {
33
+ await invokeNative('tray', 'create', this._id).catch(() => undefined);
34
+ if (image)
35
+ this.setImage(image);
36
+ })
37
+ .catch(() => undefined);
38
+ }
39
+ get id() {
40
+ return this._id;
41
+ }
42
+ setImage(image) {
43
+ void invokeNative('tray', 'setImage', toPngBase64(image)).catch(() => undefined);
44
+ }
45
+ setPressedImage(image) {
46
+ void invokeNative('tray', 'setPressedImage', toPngBase64(image)).catch(() => undefined);
47
+ }
48
+ setToolTip(tip) {
49
+ void invokeNative('tray', 'setToolTip', tip).catch(() => undefined);
50
+ }
51
+ setTitle(title) {
52
+ void invokeNative('tray', 'setTitle', title).catch(() => undefined);
53
+ }
54
+ setContextMenu(menu) {
55
+ this._menu = menu;
56
+ void invokeNative('tray', 'setContextMenu', { items: menu ? menu._toJSON() : [] }).catch(() => undefined);
57
+ }
58
+ popupContextMenu(menu) {
59
+ const m = menu ?? this._menu;
60
+ if (m)
61
+ void invokeNative('tray', 'setContextMenu', { items: m._toJSON() }).catch(() => undefined);
62
+ void invokeNative('tray', 'popupContextMenu').catch(() => undefined);
63
+ }
64
+ destroy() {
65
+ if (currentTray === this)
66
+ currentTray = null;
67
+ void invokeNative('tray', 'destroy').catch(() => undefined);
68
+ }
69
+ }
@@ -0,0 +1,44 @@
1
+ import { EventEmitter } from 'node:events';
2
+ import { NativeImage } from './nativeimage.js';
3
+ export interface WindowOpenDetails {
4
+ url: string;
5
+ }
6
+ export type WindowOpenHandler = (details: WindowOpenDetails) => {
7
+ action: 'allow' | 'deny';
8
+ overrideBrowserWindowOptions?: Record<string, unknown>;
9
+ } | void;
10
+ /** Eventos de ventana → nombres estilo Electron de webContents. */
11
+ export declare const WC_EVENT_NAMES: Record<string, string>;
12
+ /** Eventos de ventana → nombres estilo Electron (dash) que emite BrowserWindow. */
13
+ export declare const WIN_EVENT_NAMES: Record<string, string>;
14
+ /**
15
+ * Vista del contenido web de una ventana (estilo Electron).
16
+ * Eventos: `did-finish-load`, `did-fail-load`, `did-start-navigation`,
17
+ * `did-navigate`, `page-title-updated`, `before-input-event`.
18
+ * `setWindowOpenHandler` controla `window.open`/`target=_blank`.
19
+ */
20
+ export declare class WebContents extends EventEmitter {
21
+ private _windowId;
22
+ constructor(windowId?: number | null);
23
+ _setWindowId(id: number): void;
24
+ get id(): number;
25
+ /** Envía un evento SOLO a esta ventana (renderer: `ow.on(name, cb)`). */
26
+ send(name: string, payload?: unknown): Promise<void>;
27
+ loadURL(url: string): Promise<void>;
28
+ reload(): Promise<void>;
29
+ openDevTools(): Promise<void>;
30
+ getURL(): Promise<string>;
31
+ getTitle(): Promise<string>;
32
+ executeJavaScript<T = unknown>(js: string): Promise<T>;
33
+ /** Captura la página (PNG) como `NativeImage` (resizable, toPNG/toDataURL). */
34
+ capturePage(): Promise<NativeImage>;
35
+ /** Exporta la página a PDF (Buffer). */
36
+ printToPDF(_options?: Record<string, unknown>): Promise<Buffer>;
37
+ /** Abre el diálogo de impresión del sistema. */
38
+ print(_options?: Record<string, unknown>): void;
39
+ /**
40
+ * Controla `window.open`/`target=_blank`. Devuelve `{action:'deny'}` para
41
+ * bloquear o `{action:'allow'}` para permitir (por defecto).
42
+ */
43
+ setWindowOpenHandler(handler: WindowOpenHandler | null): void;
44
+ }
@@ -0,0 +1,109 @@
1
+ // Copyright 2026 Owear Contributors
2
+ // SPDX-License-Identifier: Apache-2.0
3
+ //
4
+ // @owear/core/src/webcontents.ts — objeto webContents (C3).
5
+ import { EventEmitter } from 'node:events';
6
+ import { channel, invokeNative } from './channel.js';
7
+ import { nativeImage } from './nativeimage.js';
8
+ /** Eventos de ventana → nombres estilo Electron de webContents. */
9
+ export const WC_EVENT_NAMES = {
10
+ didFinishLoad: 'did-finish-load',
11
+ didFailLoad: 'did-fail-load',
12
+ navigationStarted: 'did-start-navigation',
13
+ loadCommitted: 'did-navigate',
14
+ pageTitleUpdated: 'page-title-updated',
15
+ beforeInput: 'before-input-event',
16
+ };
17
+ /** Eventos de ventana → nombres estilo Electron (dash) que emite BrowserWindow. */
18
+ export const WIN_EVENT_NAMES = {
19
+ pageTitleUpdated: 'page-title-updated',
20
+ enterFullScreen: 'enter-full-screen',
21
+ leaveFullScreen: 'leave-full-screen',
22
+ alwaysOnTopChanged: 'always-on-top-changed',
23
+ };
24
+ let windowOpenHandler = null;
25
+ channel.on('webContents.windowOpen', (params) => {
26
+ const { id, url } = params ?? {};
27
+ let action = 'allow';
28
+ try {
29
+ const r = windowOpenHandler?.({ url });
30
+ if (r && r.action === 'deny')
31
+ action = 'deny';
32
+ }
33
+ catch {
34
+ /* handler lanzó → allow */
35
+ }
36
+ void channel.call('webContents.respondWindowOpen', { id, action });
37
+ });
38
+ /**
39
+ * Vista del contenido web de una ventana (estilo Electron).
40
+ * Eventos: `did-finish-load`, `did-fail-load`, `did-start-navigation`,
41
+ * `did-navigate`, `page-title-updated`, `before-input-event`.
42
+ * `setWindowOpenHandler` controla `window.open`/`target=_blank`.
43
+ */
44
+ export class WebContents extends EventEmitter {
45
+ _windowId;
46
+ constructor(windowId = null) {
47
+ super();
48
+ this._windowId = windowId;
49
+ }
50
+ _setWindowId(id) {
51
+ this._windowId = id;
52
+ }
53
+ get id() {
54
+ return this._windowId ?? -1;
55
+ }
56
+ /** Envía un evento SOLO a esta ventana (renderer: `ow.on(name, cb)`). */
57
+ send(name, payload) {
58
+ if (this._windowId == null)
59
+ return Promise.reject(new Error('ventana aún no creada'));
60
+ return channel.call('node.emit', { name, payload, windowId: this._windowId });
61
+ }
62
+ loadURL(url) {
63
+ return channel.call('window.loadURL', { windowId: this.id, url });
64
+ }
65
+ reload() {
66
+ return invokeNative('window', 'reload', this.id);
67
+ }
68
+ openDevTools() {
69
+ return invokeNative('window', 'openDevTools', this.id);
70
+ }
71
+ getURL() {
72
+ return invokeNative('window', 'getURL', this.id);
73
+ }
74
+ getTitle() {
75
+ return invokeNative('window', 'getTitle', this.id);
76
+ }
77
+ executeJavaScript(js) {
78
+ return channel.call('window.eval', { windowId: this.id, js });
79
+ }
80
+ /** Captura la página (PNG) como `NativeImage` (resizable, toPNG/toDataURL). */
81
+ async capturePage() {
82
+ const r = await channel.call('window.capturePage', {
83
+ windowId: this.id,
84
+ base64: true,
85
+ });
86
+ return nativeImage.createFromBuffer(Buffer.from(r.data, 'base64'));
87
+ }
88
+ /** Exporta la página a PDF (Buffer). */
89
+ async printToPDF(_options = {}) {
90
+ const r = await channel.call('window.printToPDF', {
91
+ windowId: this.id,
92
+ });
93
+ return Buffer.from(r.data, 'base64');
94
+ }
95
+ /** Abre el diálogo de impresión del sistema. */
96
+ print(_options = {}) {
97
+ void invokeNative('window', 'print', this.id).catch(() => undefined);
98
+ }
99
+ /**
100
+ * Controla `window.open`/`target=_blank`. Devuelve `{action:'deny'}` para
101
+ * bloquear o `{action:'allow'}` para permitir (por defecto).
102
+ */
103
+ setWindowOpenHandler(handler) {
104
+ windowOpenHandler = handler ?? null;
105
+ void channel
106
+ .call('webContents.setWindowOpenHandler', { windowId: this.id, enabled: !!handler })
107
+ .catch(() => undefined);
108
+ }
109
+ }
@@ -0,0 +1,23 @@
1
+ export interface WebRequestDetails {
2
+ id: number;
3
+ url: string;
4
+ method: string;
5
+ headers: Record<string, string>;
6
+ }
7
+ export type WebRequestResult = {
8
+ cancel?: boolean;
9
+ redirectURL?: string;
10
+ } | void;
11
+ export type WebRequestHandler = (details: WebRequestDetails) => WebRequestResult | Promise<WebRequestResult>;
12
+ /**
13
+ * Intercepción de requests (webRequest). `onBeforeRequest` puede cancelar o
14
+ * redirigir. En **Windows** intercepta todos los requests; en **Linux** solo
15
+ * navegaciones (WebKitGTK 2.52 ya no expone `send-request` para subrecursos).
16
+ *
17
+ * webRequest.onBeforeRequest({ urls: ['https://ads.example.com/w'] }, () => ({ cancel: true }))
18
+ */
19
+ export declare const webRequest: {
20
+ onBeforeRequest(filter: {
21
+ urls?: string[];
22
+ } | string[], handler: WebRequestHandler): () => void;
23
+ };
@@ -0,0 +1,76 @@
1
+ // Copyright 2026 Owear Contributors
2
+ // SPDX-License-Identifier: Apache-2.0
3
+ //
4
+ // @owear/core/src/webrequest.ts — intercepción de requests (webRequest).
5
+ import { channel } from './channel.js';
6
+ import { app } from './index.js';
7
+ const webRequestRegistrations = [];
8
+ function globMatch(pattern, url) {
9
+ if (pattern === '<all_urls>' || pattern === '*')
10
+ return true;
11
+ const re = '^' +
12
+ pattern
13
+ .replace(/[.+^${}()|[\]\\]/g, '\\$&')
14
+ .replace(/\*/g, '.*')
15
+ .replace(/\?/g, '.') +
16
+ '$';
17
+ try {
18
+ return new RegExp(re).test(url);
19
+ }
20
+ catch {
21
+ return false;
22
+ }
23
+ }
24
+ function webRequestPatterns() {
25
+ const set = new Set();
26
+ for (const r of webRequestRegistrations)
27
+ for (const p of r.patterns)
28
+ set.add(p);
29
+ return [...set];
30
+ }
31
+ function syncWebRequest() {
32
+ app
33
+ .whenReady()
34
+ .then(() => channel.call('webRequest.register', { urls: webRequestPatterns() }))
35
+ .catch(() => undefined);
36
+ }
37
+ channel.on('webRequest.request', (params) => {
38
+ const { id, url, method, headers } = params ?? {};
39
+ const matched = webRequestRegistrations.filter((r) => r.patterns.some((p) => globMatch(p, url)));
40
+ Promise.resolve()
41
+ .then(async () => {
42
+ for (const r of matched) {
43
+ const res = await r.handler({ id, url, method, headers: headers ?? {} });
44
+ if (res && (res.cancel || res.redirectURL))
45
+ return res;
46
+ }
47
+ return null;
48
+ })
49
+ .then((res) => channel.call('webRequest.respond', {
50
+ id,
51
+ cancel: !!(res && res.cancel),
52
+ redirectURL: res && res.redirectURL,
53
+ }))
54
+ .catch(() => channel.call('webRequest.respond', { id, cancel: false }));
55
+ });
56
+ /**
57
+ * Intercepción de requests (webRequest). `onBeforeRequest` puede cancelar o
58
+ * redirigir. En **Windows** intercepta todos los requests; en **Linux** solo
59
+ * navegaciones (WebKitGTK 2.52 ya no expone `send-request` para subrecursos).
60
+ *
61
+ * webRequest.onBeforeRequest({ urls: ['https://ads.example.com/w'] }, () => ({ cancel: true }))
62
+ */
63
+ export const webRequest = {
64
+ onBeforeRequest(filter, handler) {
65
+ const patterns = Array.isArray(filter) ? filter : filter?.urls ?? ['<all_urls>'];
66
+ const reg = { patterns, handler };
67
+ webRequestRegistrations.push(reg);
68
+ syncWebRequest();
69
+ return () => {
70
+ const i = webRequestRegistrations.indexOf(reg);
71
+ if (i >= 0)
72
+ webRequestRegistrations.splice(i, 1);
73
+ syncWebRequest();
74
+ };
75
+ },
76
+ };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@owear/core",
3
- "version": "0.1.2",
3
+ "version": "0.1.3",
4
4
  "description": "Owear core SDK — controla el kernel nativo desde JavaScript",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",
@@ -32,6 +32,7 @@
32
32
  },
33
33
  "scripts": {
34
34
  "build": "tsc -p tsconfig.json",
35
- "typecheck": "tsc -p tsconfig.json --noEmit"
35
+ "typecheck": "tsc -p tsconfig.json --noEmit",
36
+ "test": "node --test test/worker.test.mjs test/port.test.mjs test/app.test.mjs test/nativeimage.test.mjs test/menu.test.mjs test/c10.test.mjs"
36
37
  }
37
38
  }