@guidelytech/electron 0.0.0-stage → 0.12.0
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/LICENSE +21 -0
- package/README.md +101 -2
- package/dist/chunk-AGZOVF3N.js +16 -0
- package/dist/chunk-AGZOVF3N.js.map +1 -0
- package/dist/index.cjs +97 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.d.cts +37 -0
- package/dist/index.d.ts +37 -0
- package/dist/index.js +59 -0
- package/dist/index.js.map +1 -0
- package/dist/main.cjs +66 -0
- package/dist/main.cjs.map +1 -0
- package/dist/main.d.cts +43 -0
- package/dist/main.d.ts +43 -0
- package/dist/main.js +38 -0
- package/dist/main.js.map +1 -0
- package/dist/preload.cjs +43 -0
- package/dist/preload.cjs.map +1 -0
- package/dist/preload.d.cts +30 -0
- package/dist/preload.d.ts +30 -0
- package/dist/preload.js +17 -0
- package/dist/preload.js.map +1 -0
- package/dist/types-BEnWCecg.d.cts +31 -0
- package/dist/types-BEnWCecg.d.ts +31 -0
- package/package.json +69 -3
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Guidely
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
CHANGED
|
@@ -1,3 +1,102 @@
|
|
|
1
|
-
#
|
|
1
|
+
# @guidelytech/electron
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
Guidely guides, analytics, session replay and feature flags in Electron (and other Chromium desktop
|
|
4
|
+
shells). The web SDK runs in your renderer as it does in a browser; this package adds the desktop
|
|
5
|
+
parts:
|
|
6
|
+
|
|
7
|
+
* **Page paths that make sense.** `file:///…/Acme.app/Contents/Resources/app.asar/index.html#/settings`
|
|
8
|
+
becomes `file://app/settings`, and `app://bundle/index.html#/inbox` becomes `app://bundle/inbox`, so
|
|
9
|
+
guide URL patterns (`/settings`), Pages, Heatmaps and Funnels work the same on every machine.
|
|
10
|
+
* **App version and OS.** The main process reports the app version, OS, architecture and Electron
|
|
11
|
+
version: **App version** targeting rules, feature-flag attributes (`appVersion`), release-matched
|
|
12
|
+
source maps for errors, and optional desktop traits for your users.
|
|
13
|
+
* **Offline.** Events, guide progress and survey answers wait in `localStorage` while the machine is
|
|
14
|
+
offline and are delivered later (the web SDK's outbox), and guides run from the cached config.
|
|
15
|
+
|
|
16
|
+
```bash
|
|
17
|
+
npm install @guidelytech/electron @guidelytech/sdk-core
|
|
18
|
+
```
|
|
19
|
+
|
|
20
|
+
## 1. Main process
|
|
21
|
+
|
|
22
|
+
```ts
|
|
23
|
+
import { app, BrowserWindow, ipcMain } from "electron";
|
|
24
|
+
import { setupGuidelyMain } from "@guidelytech/electron/main";
|
|
25
|
+
|
|
26
|
+
app.whenReady().then(() => {
|
|
27
|
+
setupGuidelyMain({ app, ipcMain });
|
|
28
|
+
new BrowserWindow({ webPreferences: { preload: path.join(__dirname, "preload.js"), contextIsolation: true } }).loadFile("index.html");
|
|
29
|
+
});
|
|
30
|
+
```
|
|
31
|
+
|
|
32
|
+
## 2. Preload
|
|
33
|
+
|
|
34
|
+
```ts
|
|
35
|
+
import { contextBridge, ipcRenderer } from "electron";
|
|
36
|
+
import { exposeGuidely } from "@guidelytech/electron/preload";
|
|
37
|
+
|
|
38
|
+
exposeGuidely({ contextBridge, ipcRenderer }); // window.guidelyElectron.getAppInfo()
|
|
39
|
+
```
|
|
40
|
+
|
|
41
|
+
Sandboxed preloads (the default since Electron 20) can't `require` npm packages: bundle your preload
|
|
42
|
+
(esbuild, Vite, webpack) or inline the equivalent:
|
|
43
|
+
|
|
44
|
+
```ts
|
|
45
|
+
contextBridge.exposeInMainWorld("guidelyElectron", { getAppInfo: () => ipcRenderer.invoke("guidely:app-info") });
|
|
46
|
+
```
|
|
47
|
+
|
|
48
|
+
## 3. Renderer
|
|
49
|
+
|
|
50
|
+
```ts
|
|
51
|
+
import { createGuidelyElectron, desktopTraits } from "@guidelytech/electron";
|
|
52
|
+
|
|
53
|
+
const guidely = await createGuidelyElectron({
|
|
54
|
+
projectId: "pk_prod_…",
|
|
55
|
+
apiUrl: "https://guidelytech.com",
|
|
56
|
+
user: { id: me.id, traits: { plan: me.plan } }, // desktopOs, desktopArch, appVersion… are added
|
|
57
|
+
});
|
|
58
|
+
```
|
|
59
|
+
|
|
60
|
+
Or keep your existing setup (React, Svelte, script tag) and spread the options:
|
|
61
|
+
|
|
62
|
+
```tsx
|
|
63
|
+
import { electronOptions, getElectronAppInfo } from "@guidelytech/electron";
|
|
64
|
+
const info = await getElectronAppInfo();
|
|
65
|
+
<GuidelyProvider projectId="pk_prod_…" {...electronOptions(info)}>…</GuidelyProvider>
|
|
66
|
+
```
|
|
67
|
+
|
|
68
|
+
| Export | Where | What |
|
|
69
|
+
|---|---|---|
|
|
70
|
+
| `setupGuidelyMain({ app, ipcMain })` | main | Answers `guidely:app-info`; returns a dispose function |
|
|
71
|
+
| `exposeGuidely({ contextBridge, ipcRenderer })` | preload | Exposes `window.guidelyElectron` |
|
|
72
|
+
| `getElectronAppInfo(timeoutMs = 1000)` | renderer | `{ appName, appVersion, platform, arch, osVersion, electronVersion, chromeVersion, locale, packaged }` or `null` |
|
|
73
|
+
| `electronOptions(info)` | renderer | `{ pageUrl: normalizeAppUrl, appVersion, release }` |
|
|
74
|
+
| `desktopTraits(info)` | renderer | `{ appVersion, desktopOs, desktopOsVersion, desktopArch, electronVersion }` |
|
|
75
|
+
| `createGuidelyElectron(options)` | renderer | `createGuidely` with all of the above |
|
|
76
|
+
| `normalizeAppUrl(href)` | anywhere | The URL mapping (also exported by `@guidelytech/sdk-core`) |
|
|
77
|
+
|
|
78
|
+
## Page URLs
|
|
79
|
+
|
|
80
|
+
The SDK maps every non-http(s) URL (`file:`, custom protocols) with `normalizeAppUrl`, even without
|
|
81
|
+
this package: `<scheme>://<host or "app"><route>`, where the route is the hash route (`#/x`, `#!/x`)
|
|
82
|
+
when there is one, otherwise the page file (`index.html` → `/`, `settings.html` → `/settings`) or the
|
|
83
|
+
custom protocol's own path (`app://bundle/deals/42` → `/deals/42`). Write guide URL patterns against
|
|
84
|
+
the route: `/settings`, `/deals/*`. Pass your own `pageUrl: (href) => string` option to map URLs
|
|
85
|
+
differently (for example to keep a `?tab=` parameter out).
|
|
86
|
+
|
|
87
|
+
## Things to know
|
|
88
|
+
|
|
89
|
+
* **Allowed origins.** Requests from `file://` pages carry `Origin: null` (or `file://`), and custom
|
|
90
|
+
protocols their own origin (`app://bundle`). Leave the environment's allowed origins empty, or add
|
|
91
|
+
that origin, in Settings → Environments.
|
|
92
|
+
* **Custom protocols** need `protocol.registerSchemesAsPrivileged([{ scheme: "app", privileges: {
|
|
93
|
+
standard: true, secure: true, supportFetchAPI: true, corsEnabled: true } }])` before `app` is ready,
|
|
94
|
+
or `localStorage` (identity, offline queue) and `fetch` won't work on them.
|
|
95
|
+
* **CSP.** If your renderer sets a Content-Security-Policy, allow the Guidely API in `connect-src`
|
|
96
|
+
(and `img-src` for guide images), and `script-src` for the session-replay recorder chunk if you use
|
|
97
|
+
replay (or self-host the SDK files, see [docs/sdk-versioning.md](../../docs/sdk-versioning.md)).
|
|
98
|
+
* The **in-app element picker** opens the target URL in a browser window, which a packaged desktop app
|
|
99
|
+
can't receive: author against your app's web build or a dev server (`http://localhost:…`), or use
|
|
100
|
+
manual selectors.
|
|
101
|
+
* Guides use the **Web** platform (tick *Web* under Trigger → Platforms). Device type is `desktop`;
|
|
102
|
+
the browser is reported as `electron` and the OS from the user agent.
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
// src/types.ts
|
|
2
|
+
var APP_INFO_CHANNEL = "guidely:app-info";
|
|
3
|
+
var BRIDGE_KEY = "guidelyElectron";
|
|
4
|
+
function osName(platform) {
|
|
5
|
+
if (platform === "darwin") return "macos";
|
|
6
|
+
if (platform === "win32") return "windows";
|
|
7
|
+
if (platform === "linux") return "linux";
|
|
8
|
+
return platform;
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
export {
|
|
12
|
+
APP_INFO_CHANNEL,
|
|
13
|
+
BRIDGE_KEY,
|
|
14
|
+
osName
|
|
15
|
+
};
|
|
16
|
+
//# sourceMappingURL=chunk-AGZOVF3N.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/types.ts"],"sourcesContent":["/** What the main process knows about the desktop app, sent to the renderer over IPC. */\nexport interface ElectronAppInfo {\n /** `app.getName()`. */\n appName: string;\n /** `app.getVersion()` (from package.json). */\n appVersion: string;\n /** `process.platform`: `darwin`, `win32`, `linux`. */\n platform: string;\n /** `process.arch`: `x64`, `arm64`, … */\n arch: string;\n /** `os.release()` / `process.getSystemVersion()`, when available. */\n osVersion?: string;\n electronVersion?: string;\n chromeVersion?: string;\n /** `app.getLocale()`. */\n locale?: string;\n /** `app.isPackaged`: false while running from source (`electron .`). */\n packaged?: boolean;\n}\n\n/** The API the preload script exposes on `window.guidelyElectron`. */\nexport interface GuidelyElectronBridge {\n getAppInfo(): Promise<ElectronAppInfo>;\n}\n\n/** IPC channel used between the main-process handler and the preload bridge. */\nexport const APP_INFO_CHANNEL = \"guidely:app-info\";\n/** Global the preload bridge is exposed as (`contextBridge.exposeInMainWorld`). */\nexport const BRIDGE_KEY = \"guidelyElectron\";\n\n/** Desktop operating system names used in Guidely device properties. */\nexport function osName(platform: string): string {\n if (platform === \"darwin\") return \"macos\";\n if (platform === \"win32\") return \"windows\";\n if (platform === \"linux\") return \"linux\";\n return platform;\n}\n"],"mappings":";AA0BO,IAAM,mBAAmB;AAEzB,IAAM,aAAa;AAGnB,SAAS,OAAO,UAA0B;AAC/C,MAAI,aAAa,SAAU,QAAO;AAClC,MAAI,aAAa,QAAS,QAAO;AACjC,MAAI,aAAa,QAAS,QAAO;AACjC,SAAO;AACT;","names":[]}
|
package/dist/index.cjs
ADDED
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __defProp = Object.defineProperty;
|
|
3
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
4
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
5
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
6
|
+
var __export = (target, all) => {
|
|
7
|
+
for (var name in all)
|
|
8
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
9
|
+
};
|
|
10
|
+
var __copyProps = (to, from, except, desc) => {
|
|
11
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
12
|
+
for (let key of __getOwnPropNames(from))
|
|
13
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
14
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
15
|
+
}
|
|
16
|
+
return to;
|
|
17
|
+
};
|
|
18
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
19
|
+
|
|
20
|
+
// src/index.ts
|
|
21
|
+
var index_exports = {};
|
|
22
|
+
__export(index_exports, {
|
|
23
|
+
APP_INFO_CHANNEL: () => APP_INFO_CHANNEL,
|
|
24
|
+
BRIDGE_KEY: () => BRIDGE_KEY,
|
|
25
|
+
createGuidelyElectron: () => createGuidelyElectron,
|
|
26
|
+
desktopTraits: () => desktopTraits,
|
|
27
|
+
electronOptions: () => electronOptions,
|
|
28
|
+
getElectronAppInfo: () => getElectronAppInfo,
|
|
29
|
+
normalizeAppUrl: () => import_sdk_core2.normalizeAppUrl,
|
|
30
|
+
osName: () => osName
|
|
31
|
+
});
|
|
32
|
+
module.exports = __toCommonJS(index_exports);
|
|
33
|
+
var import_sdk_core = require("@guidelytech/sdk-core");
|
|
34
|
+
|
|
35
|
+
// src/types.ts
|
|
36
|
+
var APP_INFO_CHANNEL = "guidely:app-info";
|
|
37
|
+
var BRIDGE_KEY = "guidelyElectron";
|
|
38
|
+
function osName(platform) {
|
|
39
|
+
if (platform === "darwin") return "macos";
|
|
40
|
+
if (platform === "win32") return "windows";
|
|
41
|
+
if (platform === "linux") return "linux";
|
|
42
|
+
return platform;
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
// src/index.ts
|
|
46
|
+
var import_sdk_core2 = require("@guidelytech/sdk-core");
|
|
47
|
+
var bridge = () => {
|
|
48
|
+
const g = globalThis;
|
|
49
|
+
const b = g[BRIDGE_KEY];
|
|
50
|
+
return b && typeof b.getAppInfo === "function" ? b : null;
|
|
51
|
+
};
|
|
52
|
+
async function getElectronAppInfo(timeoutMs = 1e3) {
|
|
53
|
+
const b = bridge();
|
|
54
|
+
if (!b) return null;
|
|
55
|
+
let timer;
|
|
56
|
+
try {
|
|
57
|
+
return await Promise.race([
|
|
58
|
+
b.getAppInfo().then((info) => info && typeof info === "object" && typeof info.appVersion === "string" ? info : null),
|
|
59
|
+
new Promise((resolve) => timer = setTimeout(() => resolve(null), timeoutMs))
|
|
60
|
+
]);
|
|
61
|
+
} catch {
|
|
62
|
+
return null;
|
|
63
|
+
} finally {
|
|
64
|
+
if (timer) clearTimeout(timer);
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
function electronOptions(info) {
|
|
68
|
+
return {
|
|
69
|
+
pageUrl: import_sdk_core.normalizeAppUrl,
|
|
70
|
+
...info?.appVersion ? { appVersion: info.appVersion, release: info.appVersion } : {}
|
|
71
|
+
};
|
|
72
|
+
}
|
|
73
|
+
function desktopTraits(info) {
|
|
74
|
+
if (!info) return {};
|
|
75
|
+
const out = { appVersion: info.appVersion, desktopOs: osName(info.platform), desktopArch: info.arch };
|
|
76
|
+
if (info.osVersion) out.desktopOsVersion = info.osVersion;
|
|
77
|
+
if (info.electronVersion) out.electronVersion = info.electronVersion;
|
|
78
|
+
return out;
|
|
79
|
+
}
|
|
80
|
+
async function createGuidelyElectron(options) {
|
|
81
|
+
const { bridgeTimeoutMs, ...rest } = options;
|
|
82
|
+
const info = await getElectronAppInfo(bridgeTimeoutMs);
|
|
83
|
+
const user = rest.user ? { ...rest.user, traits: { ...desktopTraits(info), ...rest.user.traits ?? {} } } : void 0;
|
|
84
|
+
return (0, import_sdk_core.createGuidely)({ ...electronOptions(info), ...rest, ...user ? { user } : {} });
|
|
85
|
+
}
|
|
86
|
+
// Annotate the CommonJS export names for ESM import in node:
|
|
87
|
+
0 && (module.exports = {
|
|
88
|
+
APP_INFO_CHANNEL,
|
|
89
|
+
BRIDGE_KEY,
|
|
90
|
+
createGuidelyElectron,
|
|
91
|
+
desktopTraits,
|
|
92
|
+
electronOptions,
|
|
93
|
+
getElectronAppInfo,
|
|
94
|
+
normalizeAppUrl,
|
|
95
|
+
osName
|
|
96
|
+
});
|
|
97
|
+
//# sourceMappingURL=index.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/index.ts","../src/types.ts"],"sourcesContent":["import { createGuidely, normalizeAppUrl, type GuidelyClient, type GuidelyOptions } from \"@guidelytech/sdk-core\";\nimport { BRIDGE_KEY, osName, type ElectronAppInfo, type GuidelyElectronBridge } from \"./types\";\n\nexport { APP_INFO_CHANNEL, BRIDGE_KEY, osName } from \"./types\";\nexport type { ElectronAppInfo, GuidelyElectronBridge } from \"./types\";\nexport { normalizeAppUrl } from \"@guidelytech/sdk-core\";\n\nconst bridge = (): GuidelyElectronBridge | null => {\n const g = globalThis as unknown as Record<string, unknown>;\n const b = g[BRIDGE_KEY] as GuidelyElectronBridge | undefined;\n return b && typeof b.getAppInfo === \"function\" ? b : null;\n};\n\n/**\n * Renderer: the app info exposed by the preload bridge, or null when it is missing (plain browser,\n * preload not installed) or does not answer within `timeoutMs`.\n */\nexport async function getElectronAppInfo(timeoutMs = 1000): Promise<ElectronAppInfo | null> {\n const b = bridge();\n if (!b) return null;\n let timer: ReturnType<typeof setTimeout> | undefined;\n try {\n return await Promise.race([\n b.getAppInfo().then((info) => (info && typeof info === \"object\" && typeof info.appVersion === \"string\" ? info : null)),\n new Promise<null>((resolve) => (timer = setTimeout(() => resolve(null), timeoutMs))),\n ]);\n } catch {\n return null;\n } finally {\n if (timer) clearTimeout(timer);\n }\n}\n\n/**\n * SDK options for a desktop app: app-relative page URLs for `file:` and custom protocols, the app\n * version for **App version** targeting rules and flag attributes, and the release for source-mapped\n * errors. Spread your own options after it to override.\n */\nexport function electronOptions(info: ElectronAppInfo | null): Pick<GuidelyOptions, \"pageUrl\" | \"appVersion\" | \"release\"> {\n return {\n pageUrl: normalizeAppUrl,\n ...(info?.appVersion ? { appVersion: info.appVersion, release: info.appVersion } : {}),\n };\n}\n\n/**\n * Desktop details as user traits (`desktopOs`, `desktopOsVersion`, `desktopArch`, `electronVersion`,\n * `appVersion`), for `identify(userId, { ...traits, ...desktopTraits(info) })` so targeting rules,\n * audiences and the Users list can use them.\n */\nexport function desktopTraits(info: ElectronAppInfo | null): Record<string, string> {\n if (!info) return {};\n const out: Record<string, string> = { appVersion: info.appVersion, desktopOs: osName(info.platform), desktopArch: info.arch };\n if (info.osVersion) out.desktopOsVersion = info.osVersion;\n if (info.electronVersion) out.electronVersion = info.electronVersion;\n return out;\n}\n\n/**\n * Renderer: creates the Guidely client for an Electron window, after reading the app info from the\n * preload bridge (at most `bridgeTimeoutMs`, default 1 s; without the bridge it still works, with\n * app-relative page URLs but no app version). `options.user.traits` get the desktop traits added.\n *\n * ```ts\n * import { createGuidelyElectron } from \"@guidelytech/electron\";\n * const guidely = await createGuidelyElectron({ projectId: \"pk_prod_…\", user: { id: me.id, traits: { plan: me.plan } } });\n * ```\n */\nexport async function createGuidelyElectron(options: GuidelyOptions & { bridgeTimeoutMs?: number }): Promise<GuidelyClient> {\n const { bridgeTimeoutMs, ...rest } = options;\n const info = await getElectronAppInfo(bridgeTimeoutMs);\n const user = rest.user ? { ...rest.user, traits: { ...desktopTraits(info), ...(rest.user.traits ?? {}) } } : undefined;\n return createGuidely({ ...electronOptions(info), ...rest, ...(user ? { user } : {}) });\n}\n","/** What the main process knows about the desktop app, sent to the renderer over IPC. */\nexport interface ElectronAppInfo {\n /** `app.getName()`. */\n appName: string;\n /** `app.getVersion()` (from package.json). */\n appVersion: string;\n /** `process.platform`: `darwin`, `win32`, `linux`. */\n platform: string;\n /** `process.arch`: `x64`, `arm64`, … */\n arch: string;\n /** `os.release()` / `process.getSystemVersion()`, when available. */\n osVersion?: string;\n electronVersion?: string;\n chromeVersion?: string;\n /** `app.getLocale()`. */\n locale?: string;\n /** `app.isPackaged`: false while running from source (`electron .`). */\n packaged?: boolean;\n}\n\n/** The API the preload script exposes on `window.guidelyElectron`. */\nexport interface GuidelyElectronBridge {\n getAppInfo(): Promise<ElectronAppInfo>;\n}\n\n/** IPC channel used between the main-process handler and the preload bridge. */\nexport const APP_INFO_CHANNEL = \"guidely:app-info\";\n/** Global the preload bridge is exposed as (`contextBridge.exposeInMainWorld`). */\nexport const BRIDGE_KEY = \"guidelyElectron\";\n\n/** Desktop operating system names used in Guidely device properties. */\nexport function osName(platform: string): string {\n if (platform === \"darwin\") return \"macos\";\n if (platform === \"win32\") return \"windows\";\n if (platform === \"linux\") return \"linux\";\n return platform;\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,sBAAwF;;;AC0BjF,IAAM,mBAAmB;AAEzB,IAAM,aAAa;AAGnB,SAAS,OAAO,UAA0B;AAC/C,MAAI,aAAa,SAAU,QAAO;AAClC,MAAI,aAAa,QAAS,QAAO;AACjC,MAAI,aAAa,QAAS,QAAO;AACjC,SAAO;AACT;;;AD/BA,IAAAA,mBAAgC;AAEhC,IAAM,SAAS,MAAoC;AACjD,QAAM,IAAI;AACV,QAAM,IAAI,EAAE,UAAU;AACtB,SAAO,KAAK,OAAO,EAAE,eAAe,aAAa,IAAI;AACvD;AAMA,eAAsB,mBAAmB,YAAY,KAAuC;AAC1F,QAAM,IAAI,OAAO;AACjB,MAAI,CAAC,EAAG,QAAO;AACf,MAAI;AACJ,MAAI;AACF,WAAO,MAAM,QAAQ,KAAK;AAAA,MACxB,EAAE,WAAW,EAAE,KAAK,CAAC,SAAU,QAAQ,OAAO,SAAS,YAAY,OAAO,KAAK,eAAe,WAAW,OAAO,IAAK;AAAA,MACrH,IAAI,QAAc,CAAC,YAAa,QAAQ,WAAW,MAAM,QAAQ,IAAI,GAAG,SAAS,CAAE;AAAA,IACrF,CAAC;AAAA,EACH,QAAQ;AACN,WAAO;AAAA,EACT,UAAE;AACA,QAAI,MAAO,cAAa,KAAK;AAAA,EAC/B;AACF;AAOO,SAAS,gBAAgB,MAA0F;AACxH,SAAO;AAAA,IACL,SAAS;AAAA,IACT,GAAI,MAAM,aAAa,EAAE,YAAY,KAAK,YAAY,SAAS,KAAK,WAAW,IAAI,CAAC;AAAA,EACtF;AACF;AAOO,SAAS,cAAc,MAAsD;AAClF,MAAI,CAAC,KAAM,QAAO,CAAC;AACnB,QAAM,MAA8B,EAAE,YAAY,KAAK,YAAY,WAAW,OAAO,KAAK,QAAQ,GAAG,aAAa,KAAK,KAAK;AAC5H,MAAI,KAAK,UAAW,KAAI,mBAAmB,KAAK;AAChD,MAAI,KAAK,gBAAiB,KAAI,kBAAkB,KAAK;AACrD,SAAO;AACT;AAYA,eAAsB,sBAAsB,SAAgF;AAC1H,QAAM,EAAE,iBAAiB,GAAG,KAAK,IAAI;AACrC,QAAM,OAAO,MAAM,mBAAmB,eAAe;AACrD,QAAM,OAAO,KAAK,OAAO,EAAE,GAAG,KAAK,MAAM,QAAQ,EAAE,GAAG,cAAc,IAAI,GAAG,GAAI,KAAK,KAAK,UAAU,CAAC,EAAG,EAAE,IAAI;AAC7G,aAAO,+BAAc,EAAE,GAAG,gBAAgB,IAAI,GAAG,GAAG,MAAM,GAAI,OAAO,EAAE,KAAK,IAAI,CAAC,EAAG,CAAC;AACvF;","names":["import_sdk_core"]}
|
package/dist/index.d.cts
ADDED
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import { GuidelyOptions, GuidelyClient } from '@guidelytech/sdk-core';
|
|
2
|
+
export { normalizeAppUrl } from '@guidelytech/sdk-core';
|
|
3
|
+
import { E as ElectronAppInfo } from './types-BEnWCecg.cjs';
|
|
4
|
+
export { A as APP_INFO_CHANNEL, B as BRIDGE_KEY, G as GuidelyElectronBridge, o as osName } from './types-BEnWCecg.cjs';
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* Renderer: the app info exposed by the preload bridge, or null when it is missing (plain browser,
|
|
8
|
+
* preload not installed) or does not answer within `timeoutMs`.
|
|
9
|
+
*/
|
|
10
|
+
declare function getElectronAppInfo(timeoutMs?: number): Promise<ElectronAppInfo | null>;
|
|
11
|
+
/**
|
|
12
|
+
* SDK options for a desktop app: app-relative page URLs for `file:` and custom protocols, the app
|
|
13
|
+
* version for **App version** targeting rules and flag attributes, and the release for source-mapped
|
|
14
|
+
* errors. Spread your own options after it to override.
|
|
15
|
+
*/
|
|
16
|
+
declare function electronOptions(info: ElectronAppInfo | null): Pick<GuidelyOptions, "pageUrl" | "appVersion" | "release">;
|
|
17
|
+
/**
|
|
18
|
+
* Desktop details as user traits (`desktopOs`, `desktopOsVersion`, `desktopArch`, `electronVersion`,
|
|
19
|
+
* `appVersion`), for `identify(userId, { ...traits, ...desktopTraits(info) })` so targeting rules,
|
|
20
|
+
* audiences and the Users list can use them.
|
|
21
|
+
*/
|
|
22
|
+
declare function desktopTraits(info: ElectronAppInfo | null): Record<string, string>;
|
|
23
|
+
/**
|
|
24
|
+
* Renderer: creates the Guidely client for an Electron window, after reading the app info from the
|
|
25
|
+
* preload bridge (at most `bridgeTimeoutMs`, default 1 s; without the bridge it still works, with
|
|
26
|
+
* app-relative page URLs but no app version). `options.user.traits` get the desktop traits added.
|
|
27
|
+
*
|
|
28
|
+
* ```ts
|
|
29
|
+
* import { createGuidelyElectron } from "@guidelytech/electron";
|
|
30
|
+
* const guidely = await createGuidelyElectron({ projectId: "pk_prod_…", user: { id: me.id, traits: { plan: me.plan } } });
|
|
31
|
+
* ```
|
|
32
|
+
*/
|
|
33
|
+
declare function createGuidelyElectron(options: GuidelyOptions & {
|
|
34
|
+
bridgeTimeoutMs?: number;
|
|
35
|
+
}): Promise<GuidelyClient>;
|
|
36
|
+
|
|
37
|
+
export { ElectronAppInfo, createGuidelyElectron, desktopTraits, electronOptions, getElectronAppInfo };
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import { GuidelyOptions, GuidelyClient } from '@guidelytech/sdk-core';
|
|
2
|
+
export { normalizeAppUrl } from '@guidelytech/sdk-core';
|
|
3
|
+
import { E as ElectronAppInfo } from './types-BEnWCecg.js';
|
|
4
|
+
export { A as APP_INFO_CHANNEL, B as BRIDGE_KEY, G as GuidelyElectronBridge, o as osName } from './types-BEnWCecg.js';
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* Renderer: the app info exposed by the preload bridge, or null when it is missing (plain browser,
|
|
8
|
+
* preload not installed) or does not answer within `timeoutMs`.
|
|
9
|
+
*/
|
|
10
|
+
declare function getElectronAppInfo(timeoutMs?: number): Promise<ElectronAppInfo | null>;
|
|
11
|
+
/**
|
|
12
|
+
* SDK options for a desktop app: app-relative page URLs for `file:` and custom protocols, the app
|
|
13
|
+
* version for **App version** targeting rules and flag attributes, and the release for source-mapped
|
|
14
|
+
* errors. Spread your own options after it to override.
|
|
15
|
+
*/
|
|
16
|
+
declare function electronOptions(info: ElectronAppInfo | null): Pick<GuidelyOptions, "pageUrl" | "appVersion" | "release">;
|
|
17
|
+
/**
|
|
18
|
+
* Desktop details as user traits (`desktopOs`, `desktopOsVersion`, `desktopArch`, `electronVersion`,
|
|
19
|
+
* `appVersion`), for `identify(userId, { ...traits, ...desktopTraits(info) })` so targeting rules,
|
|
20
|
+
* audiences and the Users list can use them.
|
|
21
|
+
*/
|
|
22
|
+
declare function desktopTraits(info: ElectronAppInfo | null): Record<string, string>;
|
|
23
|
+
/**
|
|
24
|
+
* Renderer: creates the Guidely client for an Electron window, after reading the app info from the
|
|
25
|
+
* preload bridge (at most `bridgeTimeoutMs`, default 1 s; without the bridge it still works, with
|
|
26
|
+
* app-relative page URLs but no app version). `options.user.traits` get the desktop traits added.
|
|
27
|
+
*
|
|
28
|
+
* ```ts
|
|
29
|
+
* import { createGuidelyElectron } from "@guidelytech/electron";
|
|
30
|
+
* const guidely = await createGuidelyElectron({ projectId: "pk_prod_…", user: { id: me.id, traits: { plan: me.plan } } });
|
|
31
|
+
* ```
|
|
32
|
+
*/
|
|
33
|
+
declare function createGuidelyElectron(options: GuidelyOptions & {
|
|
34
|
+
bridgeTimeoutMs?: number;
|
|
35
|
+
}): Promise<GuidelyClient>;
|
|
36
|
+
|
|
37
|
+
export { ElectronAppInfo, createGuidelyElectron, desktopTraits, electronOptions, getElectronAppInfo };
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
import {
|
|
2
|
+
APP_INFO_CHANNEL,
|
|
3
|
+
BRIDGE_KEY,
|
|
4
|
+
osName
|
|
5
|
+
} from "./chunk-AGZOVF3N.js";
|
|
6
|
+
|
|
7
|
+
// src/index.ts
|
|
8
|
+
import { createGuidely, normalizeAppUrl } from "@guidelytech/sdk-core";
|
|
9
|
+
import { normalizeAppUrl as normalizeAppUrl2 } from "@guidelytech/sdk-core";
|
|
10
|
+
var bridge = () => {
|
|
11
|
+
const g = globalThis;
|
|
12
|
+
const b = g[BRIDGE_KEY];
|
|
13
|
+
return b && typeof b.getAppInfo === "function" ? b : null;
|
|
14
|
+
};
|
|
15
|
+
async function getElectronAppInfo(timeoutMs = 1e3) {
|
|
16
|
+
const b = bridge();
|
|
17
|
+
if (!b) return null;
|
|
18
|
+
let timer;
|
|
19
|
+
try {
|
|
20
|
+
return await Promise.race([
|
|
21
|
+
b.getAppInfo().then((info) => info && typeof info === "object" && typeof info.appVersion === "string" ? info : null),
|
|
22
|
+
new Promise((resolve) => timer = setTimeout(() => resolve(null), timeoutMs))
|
|
23
|
+
]);
|
|
24
|
+
} catch {
|
|
25
|
+
return null;
|
|
26
|
+
} finally {
|
|
27
|
+
if (timer) clearTimeout(timer);
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
function electronOptions(info) {
|
|
31
|
+
return {
|
|
32
|
+
pageUrl: normalizeAppUrl,
|
|
33
|
+
...info?.appVersion ? { appVersion: info.appVersion, release: info.appVersion } : {}
|
|
34
|
+
};
|
|
35
|
+
}
|
|
36
|
+
function desktopTraits(info) {
|
|
37
|
+
if (!info) return {};
|
|
38
|
+
const out = { appVersion: info.appVersion, desktopOs: osName(info.platform), desktopArch: info.arch };
|
|
39
|
+
if (info.osVersion) out.desktopOsVersion = info.osVersion;
|
|
40
|
+
if (info.electronVersion) out.electronVersion = info.electronVersion;
|
|
41
|
+
return out;
|
|
42
|
+
}
|
|
43
|
+
async function createGuidelyElectron(options) {
|
|
44
|
+
const { bridgeTimeoutMs, ...rest } = options;
|
|
45
|
+
const info = await getElectronAppInfo(bridgeTimeoutMs);
|
|
46
|
+
const user = rest.user ? { ...rest.user, traits: { ...desktopTraits(info), ...rest.user.traits ?? {} } } : void 0;
|
|
47
|
+
return createGuidely({ ...electronOptions(info), ...rest, ...user ? { user } : {} });
|
|
48
|
+
}
|
|
49
|
+
export {
|
|
50
|
+
APP_INFO_CHANNEL,
|
|
51
|
+
BRIDGE_KEY,
|
|
52
|
+
createGuidelyElectron,
|
|
53
|
+
desktopTraits,
|
|
54
|
+
electronOptions,
|
|
55
|
+
getElectronAppInfo,
|
|
56
|
+
normalizeAppUrl2 as normalizeAppUrl,
|
|
57
|
+
osName
|
|
58
|
+
};
|
|
59
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/index.ts"],"sourcesContent":["import { createGuidely, normalizeAppUrl, type GuidelyClient, type GuidelyOptions } from \"@guidelytech/sdk-core\";\nimport { BRIDGE_KEY, osName, type ElectronAppInfo, type GuidelyElectronBridge } from \"./types\";\n\nexport { APP_INFO_CHANNEL, BRIDGE_KEY, osName } from \"./types\";\nexport type { ElectronAppInfo, GuidelyElectronBridge } from \"./types\";\nexport { normalizeAppUrl } from \"@guidelytech/sdk-core\";\n\nconst bridge = (): GuidelyElectronBridge | null => {\n const g = globalThis as unknown as Record<string, unknown>;\n const b = g[BRIDGE_KEY] as GuidelyElectronBridge | undefined;\n return b && typeof b.getAppInfo === \"function\" ? b : null;\n};\n\n/**\n * Renderer: the app info exposed by the preload bridge, or null when it is missing (plain browser,\n * preload not installed) or does not answer within `timeoutMs`.\n */\nexport async function getElectronAppInfo(timeoutMs = 1000): Promise<ElectronAppInfo | null> {\n const b = bridge();\n if (!b) return null;\n let timer: ReturnType<typeof setTimeout> | undefined;\n try {\n return await Promise.race([\n b.getAppInfo().then((info) => (info && typeof info === \"object\" && typeof info.appVersion === \"string\" ? info : null)),\n new Promise<null>((resolve) => (timer = setTimeout(() => resolve(null), timeoutMs))),\n ]);\n } catch {\n return null;\n } finally {\n if (timer) clearTimeout(timer);\n }\n}\n\n/**\n * SDK options for a desktop app: app-relative page URLs for `file:` and custom protocols, the app\n * version for **App version** targeting rules and flag attributes, and the release for source-mapped\n * errors. Spread your own options after it to override.\n */\nexport function electronOptions(info: ElectronAppInfo | null): Pick<GuidelyOptions, \"pageUrl\" | \"appVersion\" | \"release\"> {\n return {\n pageUrl: normalizeAppUrl,\n ...(info?.appVersion ? { appVersion: info.appVersion, release: info.appVersion } : {}),\n };\n}\n\n/**\n * Desktop details as user traits (`desktopOs`, `desktopOsVersion`, `desktopArch`, `electronVersion`,\n * `appVersion`), for `identify(userId, { ...traits, ...desktopTraits(info) })` so targeting rules,\n * audiences and the Users list can use them.\n */\nexport function desktopTraits(info: ElectronAppInfo | null): Record<string, string> {\n if (!info) return {};\n const out: Record<string, string> = { appVersion: info.appVersion, desktopOs: osName(info.platform), desktopArch: info.arch };\n if (info.osVersion) out.desktopOsVersion = info.osVersion;\n if (info.electronVersion) out.electronVersion = info.electronVersion;\n return out;\n}\n\n/**\n * Renderer: creates the Guidely client for an Electron window, after reading the app info from the\n * preload bridge (at most `bridgeTimeoutMs`, default 1 s; without the bridge it still works, with\n * app-relative page URLs but no app version). `options.user.traits` get the desktop traits added.\n *\n * ```ts\n * import { createGuidelyElectron } from \"@guidelytech/electron\";\n * const guidely = await createGuidelyElectron({ projectId: \"pk_prod_…\", user: { id: me.id, traits: { plan: me.plan } } });\n * ```\n */\nexport async function createGuidelyElectron(options: GuidelyOptions & { bridgeTimeoutMs?: number }): Promise<GuidelyClient> {\n const { bridgeTimeoutMs, ...rest } = options;\n const info = await getElectronAppInfo(bridgeTimeoutMs);\n const user = rest.user ? { ...rest.user, traits: { ...desktopTraits(info), ...(rest.user.traits ?? {}) } } : undefined;\n return createGuidely({ ...electronOptions(info), ...rest, ...(user ? { user } : {}) });\n}\n"],"mappings":";;;;;;;AAAA,SAAS,eAAe,uBAAgE;AAKxF,SAAS,mBAAAA,wBAAuB;AAEhC,IAAM,SAAS,MAAoC;AACjD,QAAM,IAAI;AACV,QAAM,IAAI,EAAE,UAAU;AACtB,SAAO,KAAK,OAAO,EAAE,eAAe,aAAa,IAAI;AACvD;AAMA,eAAsB,mBAAmB,YAAY,KAAuC;AAC1F,QAAM,IAAI,OAAO;AACjB,MAAI,CAAC,EAAG,QAAO;AACf,MAAI;AACJ,MAAI;AACF,WAAO,MAAM,QAAQ,KAAK;AAAA,MACxB,EAAE,WAAW,EAAE,KAAK,CAAC,SAAU,QAAQ,OAAO,SAAS,YAAY,OAAO,KAAK,eAAe,WAAW,OAAO,IAAK;AAAA,MACrH,IAAI,QAAc,CAAC,YAAa,QAAQ,WAAW,MAAM,QAAQ,IAAI,GAAG,SAAS,CAAE;AAAA,IACrF,CAAC;AAAA,EACH,QAAQ;AACN,WAAO;AAAA,EACT,UAAE;AACA,QAAI,MAAO,cAAa,KAAK;AAAA,EAC/B;AACF;AAOO,SAAS,gBAAgB,MAA0F;AACxH,SAAO;AAAA,IACL,SAAS;AAAA,IACT,GAAI,MAAM,aAAa,EAAE,YAAY,KAAK,YAAY,SAAS,KAAK,WAAW,IAAI,CAAC;AAAA,EACtF;AACF;AAOO,SAAS,cAAc,MAAsD;AAClF,MAAI,CAAC,KAAM,QAAO,CAAC;AACnB,QAAM,MAA8B,EAAE,YAAY,KAAK,YAAY,WAAW,OAAO,KAAK,QAAQ,GAAG,aAAa,KAAK,KAAK;AAC5H,MAAI,KAAK,UAAW,KAAI,mBAAmB,KAAK;AAChD,MAAI,KAAK,gBAAiB,KAAI,kBAAkB,KAAK;AACrD,SAAO;AACT;AAYA,eAAsB,sBAAsB,SAAgF;AAC1H,QAAM,EAAE,iBAAiB,GAAG,KAAK,IAAI;AACrC,QAAM,OAAO,MAAM,mBAAmB,eAAe;AACrD,QAAM,OAAO,KAAK,OAAO,EAAE,GAAG,KAAK,MAAM,QAAQ,EAAE,GAAG,cAAc,IAAI,GAAG,GAAI,KAAK,KAAK,UAAU,CAAC,EAAG,EAAE,IAAI;AAC7G,SAAO,cAAc,EAAE,GAAG,gBAAgB,IAAI,GAAG,GAAG,MAAM,GAAI,OAAO,EAAE,KAAK,IAAI,CAAC,EAAG,CAAC;AACvF;","names":["normalizeAppUrl"]}
|
package/dist/main.cjs
ADDED
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __defProp = Object.defineProperty;
|
|
3
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
4
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
5
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
6
|
+
var __export = (target, all) => {
|
|
7
|
+
for (var name in all)
|
|
8
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
9
|
+
};
|
|
10
|
+
var __copyProps = (to, from, except, desc) => {
|
|
11
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
12
|
+
for (let key of __getOwnPropNames(from))
|
|
13
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
14
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
15
|
+
}
|
|
16
|
+
return to;
|
|
17
|
+
};
|
|
18
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
19
|
+
|
|
20
|
+
// src/main.ts
|
|
21
|
+
var main_exports = {};
|
|
22
|
+
__export(main_exports, {
|
|
23
|
+
APP_INFO_CHANNEL: () => APP_INFO_CHANNEL,
|
|
24
|
+
appInfo: () => appInfo,
|
|
25
|
+
setupGuidelyMain: () => setupGuidelyMain
|
|
26
|
+
});
|
|
27
|
+
module.exports = __toCommonJS(main_exports);
|
|
28
|
+
|
|
29
|
+
// src/types.ts
|
|
30
|
+
var APP_INFO_CHANNEL = "guidely:app-info";
|
|
31
|
+
|
|
32
|
+
// src/main.ts
|
|
33
|
+
function appInfo(app, proc = process, osRelease) {
|
|
34
|
+
const safe = (fn) => {
|
|
35
|
+
try {
|
|
36
|
+
return fn();
|
|
37
|
+
} catch {
|
|
38
|
+
return void 0;
|
|
39
|
+
}
|
|
40
|
+
};
|
|
41
|
+
const osVersion = safe(() => proc.getSystemVersion?.()) || safe(() => osRelease?.());
|
|
42
|
+
return {
|
|
43
|
+
appName: safe(() => app.getName()) ?? "app",
|
|
44
|
+
appVersion: safe(() => app.getVersion()) ?? "0.0.0",
|
|
45
|
+
platform: proc.platform,
|
|
46
|
+
arch: proc.arch,
|
|
47
|
+
...osVersion ? { osVersion } : {},
|
|
48
|
+
...proc.versions.electron ? { electronVersion: proc.versions.electron } : {},
|
|
49
|
+
...proc.versions.chrome ? { chromeVersion: proc.versions.chrome } : {},
|
|
50
|
+
...app.getLocale ? { locale: safe(() => app.getLocale()) } : {},
|
|
51
|
+
...typeof app.isPackaged === "boolean" ? { packaged: app.isPackaged } : {}
|
|
52
|
+
};
|
|
53
|
+
}
|
|
54
|
+
function setupGuidelyMain(opts) {
|
|
55
|
+
const info = appInfo(opts.app, opts.process, opts.osRelease);
|
|
56
|
+
opts.ipcMain.removeHandler?.(APP_INFO_CHANNEL);
|
|
57
|
+
opts.ipcMain.handle(APP_INFO_CHANNEL, () => info);
|
|
58
|
+
return () => opts.ipcMain.removeHandler?.(APP_INFO_CHANNEL);
|
|
59
|
+
}
|
|
60
|
+
// Annotate the CommonJS export names for ESM import in node:
|
|
61
|
+
0 && (module.exports = {
|
|
62
|
+
APP_INFO_CHANNEL,
|
|
63
|
+
appInfo,
|
|
64
|
+
setupGuidelyMain
|
|
65
|
+
});
|
|
66
|
+
//# sourceMappingURL=main.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/main.ts","../src/types.ts"],"sourcesContent":["import { APP_INFO_CHANNEL, type ElectronAppInfo } from \"./types\";\n\nexport { APP_INFO_CHANNEL } from \"./types\";\nexport type { ElectronAppInfo } from \"./types\";\n\n/** The parts of Electron's `app` the helper reads (pass `import { app } from \"electron\"`). */\nexport interface ElectronAppLike {\n getName(): string;\n getVersion(): string;\n getLocale?(): string;\n isPackaged?: boolean;\n}\n\n/** The parts of Electron's `ipcMain` the helper uses. */\nexport interface IpcMainLike {\n handle(channel: string, listener: (event: unknown, ...args: unknown[]) => unknown): void;\n removeHandler?(channel: string): void;\n}\n\n/** Node's `process` fields read for the app info (overridable for tests). */\nexport interface ProcessLike {\n platform: string;\n arch: string;\n versions: Record<string, string | undefined>;\n getSystemVersion?: () => string;\n}\n\n/** Collects the app info Guidely reports: app name and version, OS, architecture and Electron/Chrome versions. */\nexport function appInfo(app: ElectronAppLike, proc: ProcessLike = process as unknown as ProcessLike, osRelease?: () => string): ElectronAppInfo {\n const safe = <T>(fn: () => T): T | undefined => {\n try {\n return fn();\n } catch {\n return undefined;\n }\n };\n const osVersion = safe(() => proc.getSystemVersion?.()) || safe(() => osRelease?.());\n return {\n appName: safe(() => app.getName()) ?? \"app\",\n appVersion: safe(() => app.getVersion()) ?? \"0.0.0\",\n platform: proc.platform,\n arch: proc.arch,\n ...(osVersion ? { osVersion } : {}),\n ...(proc.versions.electron ? { electronVersion: proc.versions.electron } : {}),\n ...(proc.versions.chrome ? { chromeVersion: proc.versions.chrome } : {}),\n ...(app.getLocale ? { locale: safe(() => app.getLocale!()) } : {}),\n ...(typeof app.isPackaged === \"boolean\" ? { packaged: app.isPackaged } : {}),\n };\n}\n\n/**\n * Main process: answers the preload bridge's app-info request. Call once after `app` is ready:\n *\n * ```ts\n * import { app, ipcMain } from \"electron\";\n * import { setupGuidelyMain } from \"@guidelytech/electron/main\";\n * app.whenReady().then(() => { setupGuidelyMain({ app, ipcMain }); createWindow(); });\n * ```\n *\n * Returns a function that removes the handler.\n */\nexport function setupGuidelyMain(opts: { app: ElectronAppLike; ipcMain: IpcMainLike; process?: ProcessLike; osRelease?: () => string }): () => void {\n const info = appInfo(opts.app, opts.process, opts.osRelease);\n opts.ipcMain.removeHandler?.(APP_INFO_CHANNEL);\n opts.ipcMain.handle(APP_INFO_CHANNEL, () => info);\n return () => opts.ipcMain.removeHandler?.(APP_INFO_CHANNEL);\n}\n","/** What the main process knows about the desktop app, sent to the renderer over IPC. */\nexport interface ElectronAppInfo {\n /** `app.getName()`. */\n appName: string;\n /** `app.getVersion()` (from package.json). */\n appVersion: string;\n /** `process.platform`: `darwin`, `win32`, `linux`. */\n platform: string;\n /** `process.arch`: `x64`, `arm64`, … */\n arch: string;\n /** `os.release()` / `process.getSystemVersion()`, when available. */\n osVersion?: string;\n electronVersion?: string;\n chromeVersion?: string;\n /** `app.getLocale()`. */\n locale?: string;\n /** `app.isPackaged`: false while running from source (`electron .`). */\n packaged?: boolean;\n}\n\n/** The API the preload script exposes on `window.guidelyElectron`. */\nexport interface GuidelyElectronBridge {\n getAppInfo(): Promise<ElectronAppInfo>;\n}\n\n/** IPC channel used between the main-process handler and the preload bridge. */\nexport const APP_INFO_CHANNEL = \"guidely:app-info\";\n/** Global the preload bridge is exposed as (`contextBridge.exposeInMainWorld`). */\nexport const BRIDGE_KEY = \"guidelyElectron\";\n\n/** Desktop operating system names used in Guidely device properties. */\nexport function osName(platform: string): string {\n if (platform === \"darwin\") return \"macos\";\n if (platform === \"win32\") return \"windows\";\n if (platform === \"linux\") return \"linux\";\n return platform;\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;;AC0BO,IAAM,mBAAmB;;;ADEzB,SAAS,QAAQ,KAAsB,OAAoB,SAAmC,WAA2C;AAC9I,QAAM,OAAO,CAAI,OAA+B;AAC9C,QAAI;AACF,aAAO,GAAG;AAAA,IACZ,QAAQ;AACN,aAAO;AAAA,IACT;AAAA,EACF;AACA,QAAM,YAAY,KAAK,MAAM,KAAK,mBAAmB,CAAC,KAAK,KAAK,MAAM,YAAY,CAAC;AACnF,SAAO;AAAA,IACL,SAAS,KAAK,MAAM,IAAI,QAAQ,CAAC,KAAK;AAAA,IACtC,YAAY,KAAK,MAAM,IAAI,WAAW,CAAC,KAAK;AAAA,IAC5C,UAAU,KAAK;AAAA,IACf,MAAM,KAAK;AAAA,IACX,GAAI,YAAY,EAAE,UAAU,IAAI,CAAC;AAAA,IACjC,GAAI,KAAK,SAAS,WAAW,EAAE,iBAAiB,KAAK,SAAS,SAAS,IAAI,CAAC;AAAA,IAC5E,GAAI,KAAK,SAAS,SAAS,EAAE,eAAe,KAAK,SAAS,OAAO,IAAI,CAAC;AAAA,IACtE,GAAI,IAAI,YAAY,EAAE,QAAQ,KAAK,MAAM,IAAI,UAAW,CAAC,EAAE,IAAI,CAAC;AAAA,IAChE,GAAI,OAAO,IAAI,eAAe,YAAY,EAAE,UAAU,IAAI,WAAW,IAAI,CAAC;AAAA,EAC5E;AACF;AAaO,SAAS,iBAAiB,MAAmH;AAClJ,QAAM,OAAO,QAAQ,KAAK,KAAK,KAAK,SAAS,KAAK,SAAS;AAC3D,OAAK,QAAQ,gBAAgB,gBAAgB;AAC7C,OAAK,QAAQ,OAAO,kBAAkB,MAAM,IAAI;AAChD,SAAO,MAAM,KAAK,QAAQ,gBAAgB,gBAAgB;AAC5D;","names":[]}
|
package/dist/main.d.cts
ADDED
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import { E as ElectronAppInfo } from './types-BEnWCecg.cjs';
|
|
2
|
+
export { A as APP_INFO_CHANNEL } from './types-BEnWCecg.cjs';
|
|
3
|
+
|
|
4
|
+
/** The parts of Electron's `app` the helper reads (pass `import { app } from "electron"`). */
|
|
5
|
+
interface ElectronAppLike {
|
|
6
|
+
getName(): string;
|
|
7
|
+
getVersion(): string;
|
|
8
|
+
getLocale?(): string;
|
|
9
|
+
isPackaged?: boolean;
|
|
10
|
+
}
|
|
11
|
+
/** The parts of Electron's `ipcMain` the helper uses. */
|
|
12
|
+
interface IpcMainLike {
|
|
13
|
+
handle(channel: string, listener: (event: unknown, ...args: unknown[]) => unknown): void;
|
|
14
|
+
removeHandler?(channel: string): void;
|
|
15
|
+
}
|
|
16
|
+
/** Node's `process` fields read for the app info (overridable for tests). */
|
|
17
|
+
interface ProcessLike {
|
|
18
|
+
platform: string;
|
|
19
|
+
arch: string;
|
|
20
|
+
versions: Record<string, string | undefined>;
|
|
21
|
+
getSystemVersion?: () => string;
|
|
22
|
+
}
|
|
23
|
+
/** Collects the app info Guidely reports: app name and version, OS, architecture and Electron/Chrome versions. */
|
|
24
|
+
declare function appInfo(app: ElectronAppLike, proc?: ProcessLike, osRelease?: () => string): ElectronAppInfo;
|
|
25
|
+
/**
|
|
26
|
+
* Main process: answers the preload bridge's app-info request. Call once after `app` is ready:
|
|
27
|
+
*
|
|
28
|
+
* ```ts
|
|
29
|
+
* import { app, ipcMain } from "electron";
|
|
30
|
+
* import { setupGuidelyMain } from "@guidelytech/electron/main";
|
|
31
|
+
* app.whenReady().then(() => { setupGuidelyMain({ app, ipcMain }); createWindow(); });
|
|
32
|
+
* ```
|
|
33
|
+
*
|
|
34
|
+
* Returns a function that removes the handler.
|
|
35
|
+
*/
|
|
36
|
+
declare function setupGuidelyMain(opts: {
|
|
37
|
+
app: ElectronAppLike;
|
|
38
|
+
ipcMain: IpcMainLike;
|
|
39
|
+
process?: ProcessLike;
|
|
40
|
+
osRelease?: () => string;
|
|
41
|
+
}): () => void;
|
|
42
|
+
|
|
43
|
+
export { ElectronAppInfo, type ElectronAppLike, type IpcMainLike, type ProcessLike, appInfo, setupGuidelyMain };
|
package/dist/main.d.ts
ADDED
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import { E as ElectronAppInfo } from './types-BEnWCecg.js';
|
|
2
|
+
export { A as APP_INFO_CHANNEL } from './types-BEnWCecg.js';
|
|
3
|
+
|
|
4
|
+
/** The parts of Electron's `app` the helper reads (pass `import { app } from "electron"`). */
|
|
5
|
+
interface ElectronAppLike {
|
|
6
|
+
getName(): string;
|
|
7
|
+
getVersion(): string;
|
|
8
|
+
getLocale?(): string;
|
|
9
|
+
isPackaged?: boolean;
|
|
10
|
+
}
|
|
11
|
+
/** The parts of Electron's `ipcMain` the helper uses. */
|
|
12
|
+
interface IpcMainLike {
|
|
13
|
+
handle(channel: string, listener: (event: unknown, ...args: unknown[]) => unknown): void;
|
|
14
|
+
removeHandler?(channel: string): void;
|
|
15
|
+
}
|
|
16
|
+
/** Node's `process` fields read for the app info (overridable for tests). */
|
|
17
|
+
interface ProcessLike {
|
|
18
|
+
platform: string;
|
|
19
|
+
arch: string;
|
|
20
|
+
versions: Record<string, string | undefined>;
|
|
21
|
+
getSystemVersion?: () => string;
|
|
22
|
+
}
|
|
23
|
+
/** Collects the app info Guidely reports: app name and version, OS, architecture and Electron/Chrome versions. */
|
|
24
|
+
declare function appInfo(app: ElectronAppLike, proc?: ProcessLike, osRelease?: () => string): ElectronAppInfo;
|
|
25
|
+
/**
|
|
26
|
+
* Main process: answers the preload bridge's app-info request. Call once after `app` is ready:
|
|
27
|
+
*
|
|
28
|
+
* ```ts
|
|
29
|
+
* import { app, ipcMain } from "electron";
|
|
30
|
+
* import { setupGuidelyMain } from "@guidelytech/electron/main";
|
|
31
|
+
* app.whenReady().then(() => { setupGuidelyMain({ app, ipcMain }); createWindow(); });
|
|
32
|
+
* ```
|
|
33
|
+
*
|
|
34
|
+
* Returns a function that removes the handler.
|
|
35
|
+
*/
|
|
36
|
+
declare function setupGuidelyMain(opts: {
|
|
37
|
+
app: ElectronAppLike;
|
|
38
|
+
ipcMain: IpcMainLike;
|
|
39
|
+
process?: ProcessLike;
|
|
40
|
+
osRelease?: () => string;
|
|
41
|
+
}): () => void;
|
|
42
|
+
|
|
43
|
+
export { ElectronAppInfo, type ElectronAppLike, type IpcMainLike, type ProcessLike, appInfo, setupGuidelyMain };
|
package/dist/main.js
ADDED
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import {
|
|
2
|
+
APP_INFO_CHANNEL
|
|
3
|
+
} from "./chunk-AGZOVF3N.js";
|
|
4
|
+
|
|
5
|
+
// src/main.ts
|
|
6
|
+
function appInfo(app, proc = process, osRelease) {
|
|
7
|
+
const safe = (fn) => {
|
|
8
|
+
try {
|
|
9
|
+
return fn();
|
|
10
|
+
} catch {
|
|
11
|
+
return void 0;
|
|
12
|
+
}
|
|
13
|
+
};
|
|
14
|
+
const osVersion = safe(() => proc.getSystemVersion?.()) || safe(() => osRelease?.());
|
|
15
|
+
return {
|
|
16
|
+
appName: safe(() => app.getName()) ?? "app",
|
|
17
|
+
appVersion: safe(() => app.getVersion()) ?? "0.0.0",
|
|
18
|
+
platform: proc.platform,
|
|
19
|
+
arch: proc.arch,
|
|
20
|
+
...osVersion ? { osVersion } : {},
|
|
21
|
+
...proc.versions.electron ? { electronVersion: proc.versions.electron } : {},
|
|
22
|
+
...proc.versions.chrome ? { chromeVersion: proc.versions.chrome } : {},
|
|
23
|
+
...app.getLocale ? { locale: safe(() => app.getLocale()) } : {},
|
|
24
|
+
...typeof app.isPackaged === "boolean" ? { packaged: app.isPackaged } : {}
|
|
25
|
+
};
|
|
26
|
+
}
|
|
27
|
+
function setupGuidelyMain(opts) {
|
|
28
|
+
const info = appInfo(opts.app, opts.process, opts.osRelease);
|
|
29
|
+
opts.ipcMain.removeHandler?.(APP_INFO_CHANNEL);
|
|
30
|
+
opts.ipcMain.handle(APP_INFO_CHANNEL, () => info);
|
|
31
|
+
return () => opts.ipcMain.removeHandler?.(APP_INFO_CHANNEL);
|
|
32
|
+
}
|
|
33
|
+
export {
|
|
34
|
+
APP_INFO_CHANNEL,
|
|
35
|
+
appInfo,
|
|
36
|
+
setupGuidelyMain
|
|
37
|
+
};
|
|
38
|
+
//# sourceMappingURL=main.js.map
|
package/dist/main.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/main.ts"],"sourcesContent":["import { APP_INFO_CHANNEL, type ElectronAppInfo } from \"./types\";\n\nexport { APP_INFO_CHANNEL } from \"./types\";\nexport type { ElectronAppInfo } from \"./types\";\n\n/** The parts of Electron's `app` the helper reads (pass `import { app } from \"electron\"`). */\nexport interface ElectronAppLike {\n getName(): string;\n getVersion(): string;\n getLocale?(): string;\n isPackaged?: boolean;\n}\n\n/** The parts of Electron's `ipcMain` the helper uses. */\nexport interface IpcMainLike {\n handle(channel: string, listener: (event: unknown, ...args: unknown[]) => unknown): void;\n removeHandler?(channel: string): void;\n}\n\n/** Node's `process` fields read for the app info (overridable for tests). */\nexport interface ProcessLike {\n platform: string;\n arch: string;\n versions: Record<string, string | undefined>;\n getSystemVersion?: () => string;\n}\n\n/** Collects the app info Guidely reports: app name and version, OS, architecture and Electron/Chrome versions. */\nexport function appInfo(app: ElectronAppLike, proc: ProcessLike = process as unknown as ProcessLike, osRelease?: () => string): ElectronAppInfo {\n const safe = <T>(fn: () => T): T | undefined => {\n try {\n return fn();\n } catch {\n return undefined;\n }\n };\n const osVersion = safe(() => proc.getSystemVersion?.()) || safe(() => osRelease?.());\n return {\n appName: safe(() => app.getName()) ?? \"app\",\n appVersion: safe(() => app.getVersion()) ?? \"0.0.0\",\n platform: proc.platform,\n arch: proc.arch,\n ...(osVersion ? { osVersion } : {}),\n ...(proc.versions.electron ? { electronVersion: proc.versions.electron } : {}),\n ...(proc.versions.chrome ? { chromeVersion: proc.versions.chrome } : {}),\n ...(app.getLocale ? { locale: safe(() => app.getLocale!()) } : {}),\n ...(typeof app.isPackaged === \"boolean\" ? { packaged: app.isPackaged } : {}),\n };\n}\n\n/**\n * Main process: answers the preload bridge's app-info request. Call once after `app` is ready:\n *\n * ```ts\n * import { app, ipcMain } from \"electron\";\n * import { setupGuidelyMain } from \"@guidelytech/electron/main\";\n * app.whenReady().then(() => { setupGuidelyMain({ app, ipcMain }); createWindow(); });\n * ```\n *\n * Returns a function that removes the handler.\n */\nexport function setupGuidelyMain(opts: { app: ElectronAppLike; ipcMain: IpcMainLike; process?: ProcessLike; osRelease?: () => string }): () => void {\n const info = appInfo(opts.app, opts.process, opts.osRelease);\n opts.ipcMain.removeHandler?.(APP_INFO_CHANNEL);\n opts.ipcMain.handle(APP_INFO_CHANNEL, () => info);\n return () => opts.ipcMain.removeHandler?.(APP_INFO_CHANNEL);\n}\n"],"mappings":";;;;;AA4BO,SAAS,QAAQ,KAAsB,OAAoB,SAAmC,WAA2C;AAC9I,QAAM,OAAO,CAAI,OAA+B;AAC9C,QAAI;AACF,aAAO,GAAG;AAAA,IACZ,QAAQ;AACN,aAAO;AAAA,IACT;AAAA,EACF;AACA,QAAM,YAAY,KAAK,MAAM,KAAK,mBAAmB,CAAC,KAAK,KAAK,MAAM,YAAY,CAAC;AACnF,SAAO;AAAA,IACL,SAAS,KAAK,MAAM,IAAI,QAAQ,CAAC,KAAK;AAAA,IACtC,YAAY,KAAK,MAAM,IAAI,WAAW,CAAC,KAAK;AAAA,IAC5C,UAAU,KAAK;AAAA,IACf,MAAM,KAAK;AAAA,IACX,GAAI,YAAY,EAAE,UAAU,IAAI,CAAC;AAAA,IACjC,GAAI,KAAK,SAAS,WAAW,EAAE,iBAAiB,KAAK,SAAS,SAAS,IAAI,CAAC;AAAA,IAC5E,GAAI,KAAK,SAAS,SAAS,EAAE,eAAe,KAAK,SAAS,OAAO,IAAI,CAAC;AAAA,IACtE,GAAI,IAAI,YAAY,EAAE,QAAQ,KAAK,MAAM,IAAI,UAAW,CAAC,EAAE,IAAI,CAAC;AAAA,IAChE,GAAI,OAAO,IAAI,eAAe,YAAY,EAAE,UAAU,IAAI,WAAW,IAAI,CAAC;AAAA,EAC5E;AACF;AAaO,SAAS,iBAAiB,MAAmH;AAClJ,QAAM,OAAO,QAAQ,KAAK,KAAK,KAAK,SAAS,KAAK,SAAS;AAC3D,OAAK,QAAQ,gBAAgB,gBAAgB;AAC7C,OAAK,QAAQ,OAAO,kBAAkB,MAAM,IAAI;AAChD,SAAO,MAAM,KAAK,QAAQ,gBAAgB,gBAAgB;AAC5D;","names":[]}
|
package/dist/preload.cjs
ADDED
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __defProp = Object.defineProperty;
|
|
3
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
4
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
5
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
6
|
+
var __export = (target, all) => {
|
|
7
|
+
for (var name in all)
|
|
8
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
9
|
+
};
|
|
10
|
+
var __copyProps = (to, from, except, desc) => {
|
|
11
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
12
|
+
for (let key of __getOwnPropNames(from))
|
|
13
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
14
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
15
|
+
}
|
|
16
|
+
return to;
|
|
17
|
+
};
|
|
18
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
19
|
+
|
|
20
|
+
// src/preload.ts
|
|
21
|
+
var preload_exports = {};
|
|
22
|
+
__export(preload_exports, {
|
|
23
|
+
exposeGuidely: () => exposeGuidely
|
|
24
|
+
});
|
|
25
|
+
module.exports = __toCommonJS(preload_exports);
|
|
26
|
+
|
|
27
|
+
// src/types.ts
|
|
28
|
+
var APP_INFO_CHANNEL = "guidely:app-info";
|
|
29
|
+
var BRIDGE_KEY = "guidelyElectron";
|
|
30
|
+
|
|
31
|
+
// src/preload.ts
|
|
32
|
+
function exposeGuidely(opts) {
|
|
33
|
+
let cached = null;
|
|
34
|
+
const bridge = {
|
|
35
|
+
getAppInfo: () => cached ?? (cached = opts.ipcRenderer.invoke(APP_INFO_CHANNEL))
|
|
36
|
+
};
|
|
37
|
+
opts.contextBridge.exposeInMainWorld(BRIDGE_KEY, bridge);
|
|
38
|
+
}
|
|
39
|
+
// Annotate the CommonJS export names for ESM import in node:
|
|
40
|
+
0 && (module.exports = {
|
|
41
|
+
exposeGuidely
|
|
42
|
+
});
|
|
43
|
+
//# sourceMappingURL=preload.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/preload.ts","../src/types.ts"],"sourcesContent":["import { APP_INFO_CHANNEL, BRIDGE_KEY, type ElectronAppInfo, type GuidelyElectronBridge } from \"./types\";\n\nexport type { ElectronAppInfo, GuidelyElectronBridge } from \"./types\";\n\n/** The parts of Electron's `contextBridge` the helper uses. */\nexport interface ContextBridgeLike {\n exposeInMainWorld(key: string, api: unknown): void;\n}\n\n/** The parts of Electron's `ipcRenderer` the helper uses. */\nexport interface IpcRendererLike {\n invoke(channel: string, ...args: unknown[]): Promise<unknown>;\n}\n\n/**\n * Preload script: exposes `window.guidelyElectron.getAppInfo()` to the page (works with\n * `contextIsolation: true`; the page gets a function, never `ipcRenderer` itself).\n *\n * ```ts\n * // preload.ts\n * import { contextBridge, ipcRenderer } from \"electron\";\n * import { exposeGuidely } from \"@guidelytech/electron/preload\";\n * exposeGuidely({ contextBridge, ipcRenderer });\n * ```\n *\n * Sandboxed preloads (Electron's default since 20) can't `require` npm packages: bundle the preload\n * (esbuild, Vite, webpack), or copy these few lines into it.\n */\nexport function exposeGuidely(opts: { contextBridge: ContextBridgeLike; ipcRenderer: IpcRendererLike }): void {\n let cached: Promise<ElectronAppInfo> | null = null;\n const bridge: GuidelyElectronBridge = {\n getAppInfo: () => (cached ??= opts.ipcRenderer.invoke(APP_INFO_CHANNEL) as Promise<ElectronAppInfo>),\n };\n opts.contextBridge.exposeInMainWorld(BRIDGE_KEY, bridge);\n}\n","/** What the main process knows about the desktop app, sent to the renderer over IPC. */\nexport interface ElectronAppInfo {\n /** `app.getName()`. */\n appName: string;\n /** `app.getVersion()` (from package.json). */\n appVersion: string;\n /** `process.platform`: `darwin`, `win32`, `linux`. */\n platform: string;\n /** `process.arch`: `x64`, `arm64`, … */\n arch: string;\n /** `os.release()` / `process.getSystemVersion()`, when available. */\n osVersion?: string;\n electronVersion?: string;\n chromeVersion?: string;\n /** `app.getLocale()`. */\n locale?: string;\n /** `app.isPackaged`: false while running from source (`electron .`). */\n packaged?: boolean;\n}\n\n/** The API the preload script exposes on `window.guidelyElectron`. */\nexport interface GuidelyElectronBridge {\n getAppInfo(): Promise<ElectronAppInfo>;\n}\n\n/** IPC channel used between the main-process handler and the preload bridge. */\nexport const APP_INFO_CHANNEL = \"guidely:app-info\";\n/** Global the preload bridge is exposed as (`contextBridge.exposeInMainWorld`). */\nexport const BRIDGE_KEY = \"guidelyElectron\";\n\n/** Desktop operating system names used in Guidely device properties. */\nexport function osName(platform: string): string {\n if (platform === \"darwin\") return \"macos\";\n if (platform === \"win32\") return \"windows\";\n if (platform === \"linux\") return \"linux\";\n return platform;\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;;;AC0BO,IAAM,mBAAmB;AAEzB,IAAM,aAAa;;;ADAnB,SAAS,cAAc,MAAgF;AAC5G,MAAI,SAA0C;AAC9C,QAAM,SAAgC;AAAA,IACpC,YAAY,MAAO,oBAAW,KAAK,YAAY,OAAO,gBAAgB;AAAA,EACxE;AACA,OAAK,cAAc,kBAAkB,YAAY,MAAM;AACzD;","names":[]}
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
export { E as ElectronAppInfo, G as GuidelyElectronBridge } from './types-BEnWCecg.cjs';
|
|
2
|
+
|
|
3
|
+
/** The parts of Electron's `contextBridge` the helper uses. */
|
|
4
|
+
interface ContextBridgeLike {
|
|
5
|
+
exposeInMainWorld(key: string, api: unknown): void;
|
|
6
|
+
}
|
|
7
|
+
/** The parts of Electron's `ipcRenderer` the helper uses. */
|
|
8
|
+
interface IpcRendererLike {
|
|
9
|
+
invoke(channel: string, ...args: unknown[]): Promise<unknown>;
|
|
10
|
+
}
|
|
11
|
+
/**
|
|
12
|
+
* Preload script: exposes `window.guidelyElectron.getAppInfo()` to the page (works with
|
|
13
|
+
* `contextIsolation: true`; the page gets a function, never `ipcRenderer` itself).
|
|
14
|
+
*
|
|
15
|
+
* ```ts
|
|
16
|
+
* // preload.ts
|
|
17
|
+
* import { contextBridge, ipcRenderer } from "electron";
|
|
18
|
+
* import { exposeGuidely } from "@guidelytech/electron/preload";
|
|
19
|
+
* exposeGuidely({ contextBridge, ipcRenderer });
|
|
20
|
+
* ```
|
|
21
|
+
*
|
|
22
|
+
* Sandboxed preloads (Electron's default since 20) can't `require` npm packages: bundle the preload
|
|
23
|
+
* (esbuild, Vite, webpack), or copy these few lines into it.
|
|
24
|
+
*/
|
|
25
|
+
declare function exposeGuidely(opts: {
|
|
26
|
+
contextBridge: ContextBridgeLike;
|
|
27
|
+
ipcRenderer: IpcRendererLike;
|
|
28
|
+
}): void;
|
|
29
|
+
|
|
30
|
+
export { type ContextBridgeLike, type IpcRendererLike, exposeGuidely };
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
export { E as ElectronAppInfo, G as GuidelyElectronBridge } from './types-BEnWCecg.js';
|
|
2
|
+
|
|
3
|
+
/** The parts of Electron's `contextBridge` the helper uses. */
|
|
4
|
+
interface ContextBridgeLike {
|
|
5
|
+
exposeInMainWorld(key: string, api: unknown): void;
|
|
6
|
+
}
|
|
7
|
+
/** The parts of Electron's `ipcRenderer` the helper uses. */
|
|
8
|
+
interface IpcRendererLike {
|
|
9
|
+
invoke(channel: string, ...args: unknown[]): Promise<unknown>;
|
|
10
|
+
}
|
|
11
|
+
/**
|
|
12
|
+
* Preload script: exposes `window.guidelyElectron.getAppInfo()` to the page (works with
|
|
13
|
+
* `contextIsolation: true`; the page gets a function, never `ipcRenderer` itself).
|
|
14
|
+
*
|
|
15
|
+
* ```ts
|
|
16
|
+
* // preload.ts
|
|
17
|
+
* import { contextBridge, ipcRenderer } from "electron";
|
|
18
|
+
* import { exposeGuidely } from "@guidelytech/electron/preload";
|
|
19
|
+
* exposeGuidely({ contextBridge, ipcRenderer });
|
|
20
|
+
* ```
|
|
21
|
+
*
|
|
22
|
+
* Sandboxed preloads (Electron's default since 20) can't `require` npm packages: bundle the preload
|
|
23
|
+
* (esbuild, Vite, webpack), or copy these few lines into it.
|
|
24
|
+
*/
|
|
25
|
+
declare function exposeGuidely(opts: {
|
|
26
|
+
contextBridge: ContextBridgeLike;
|
|
27
|
+
ipcRenderer: IpcRendererLike;
|
|
28
|
+
}): void;
|
|
29
|
+
|
|
30
|
+
export { type ContextBridgeLike, type IpcRendererLike, exposeGuidely };
|
package/dist/preload.js
ADDED
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import {
|
|
2
|
+
APP_INFO_CHANNEL,
|
|
3
|
+
BRIDGE_KEY
|
|
4
|
+
} from "./chunk-AGZOVF3N.js";
|
|
5
|
+
|
|
6
|
+
// src/preload.ts
|
|
7
|
+
function exposeGuidely(opts) {
|
|
8
|
+
let cached = null;
|
|
9
|
+
const bridge = {
|
|
10
|
+
getAppInfo: () => cached ?? (cached = opts.ipcRenderer.invoke(APP_INFO_CHANNEL))
|
|
11
|
+
};
|
|
12
|
+
opts.contextBridge.exposeInMainWorld(BRIDGE_KEY, bridge);
|
|
13
|
+
}
|
|
14
|
+
export {
|
|
15
|
+
exposeGuidely
|
|
16
|
+
};
|
|
17
|
+
//# sourceMappingURL=preload.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/preload.ts"],"sourcesContent":["import { APP_INFO_CHANNEL, BRIDGE_KEY, type ElectronAppInfo, type GuidelyElectronBridge } from \"./types\";\n\nexport type { ElectronAppInfo, GuidelyElectronBridge } from \"./types\";\n\n/** The parts of Electron's `contextBridge` the helper uses. */\nexport interface ContextBridgeLike {\n exposeInMainWorld(key: string, api: unknown): void;\n}\n\n/** The parts of Electron's `ipcRenderer` the helper uses. */\nexport interface IpcRendererLike {\n invoke(channel: string, ...args: unknown[]): Promise<unknown>;\n}\n\n/**\n * Preload script: exposes `window.guidelyElectron.getAppInfo()` to the page (works with\n * `contextIsolation: true`; the page gets a function, never `ipcRenderer` itself).\n *\n * ```ts\n * // preload.ts\n * import { contextBridge, ipcRenderer } from \"electron\";\n * import { exposeGuidely } from \"@guidelytech/electron/preload\";\n * exposeGuidely({ contextBridge, ipcRenderer });\n * ```\n *\n * Sandboxed preloads (Electron's default since 20) can't `require` npm packages: bundle the preload\n * (esbuild, Vite, webpack), or copy these few lines into it.\n */\nexport function exposeGuidely(opts: { contextBridge: ContextBridgeLike; ipcRenderer: IpcRendererLike }): void {\n let cached: Promise<ElectronAppInfo> | null = null;\n const bridge: GuidelyElectronBridge = {\n getAppInfo: () => (cached ??= opts.ipcRenderer.invoke(APP_INFO_CHANNEL) as Promise<ElectronAppInfo>),\n };\n opts.contextBridge.exposeInMainWorld(BRIDGE_KEY, bridge);\n}\n"],"mappings":";;;;;;AA4BO,SAAS,cAAc,MAAgF;AAC5G,MAAI,SAA0C;AAC9C,QAAM,SAAgC;AAAA,IACpC,YAAY,MAAO,oBAAW,KAAK,YAAY,OAAO,gBAAgB;AAAA,EACxE;AACA,OAAK,cAAc,kBAAkB,YAAY,MAAM;AACzD;","names":[]}
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
/** What the main process knows about the desktop app, sent to the renderer over IPC. */
|
|
2
|
+
interface ElectronAppInfo {
|
|
3
|
+
/** `app.getName()`. */
|
|
4
|
+
appName: string;
|
|
5
|
+
/** `app.getVersion()` (from package.json). */
|
|
6
|
+
appVersion: string;
|
|
7
|
+
/** `process.platform`: `darwin`, `win32`, `linux`. */
|
|
8
|
+
platform: string;
|
|
9
|
+
/** `process.arch`: `x64`, `arm64`, … */
|
|
10
|
+
arch: string;
|
|
11
|
+
/** `os.release()` / `process.getSystemVersion()`, when available. */
|
|
12
|
+
osVersion?: string;
|
|
13
|
+
electronVersion?: string;
|
|
14
|
+
chromeVersion?: string;
|
|
15
|
+
/** `app.getLocale()`. */
|
|
16
|
+
locale?: string;
|
|
17
|
+
/** `app.isPackaged`: false while running from source (`electron .`). */
|
|
18
|
+
packaged?: boolean;
|
|
19
|
+
}
|
|
20
|
+
/** The API the preload script exposes on `window.guidelyElectron`. */
|
|
21
|
+
interface GuidelyElectronBridge {
|
|
22
|
+
getAppInfo(): Promise<ElectronAppInfo>;
|
|
23
|
+
}
|
|
24
|
+
/** IPC channel used between the main-process handler and the preload bridge. */
|
|
25
|
+
declare const APP_INFO_CHANNEL = "guidely:app-info";
|
|
26
|
+
/** Global the preload bridge is exposed as (`contextBridge.exposeInMainWorld`). */
|
|
27
|
+
declare const BRIDGE_KEY = "guidelyElectron";
|
|
28
|
+
/** Desktop operating system names used in Guidely device properties. */
|
|
29
|
+
declare function osName(platform: string): string;
|
|
30
|
+
|
|
31
|
+
export { APP_INFO_CHANNEL as A, BRIDGE_KEY as B, type ElectronAppInfo as E, type GuidelyElectronBridge as G, osName as o };
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
/** What the main process knows about the desktop app, sent to the renderer over IPC. */
|
|
2
|
+
interface ElectronAppInfo {
|
|
3
|
+
/** `app.getName()`. */
|
|
4
|
+
appName: string;
|
|
5
|
+
/** `app.getVersion()` (from package.json). */
|
|
6
|
+
appVersion: string;
|
|
7
|
+
/** `process.platform`: `darwin`, `win32`, `linux`. */
|
|
8
|
+
platform: string;
|
|
9
|
+
/** `process.arch`: `x64`, `arm64`, … */
|
|
10
|
+
arch: string;
|
|
11
|
+
/** `os.release()` / `process.getSystemVersion()`, when available. */
|
|
12
|
+
osVersion?: string;
|
|
13
|
+
electronVersion?: string;
|
|
14
|
+
chromeVersion?: string;
|
|
15
|
+
/** `app.getLocale()`. */
|
|
16
|
+
locale?: string;
|
|
17
|
+
/** `app.isPackaged`: false while running from source (`electron .`). */
|
|
18
|
+
packaged?: boolean;
|
|
19
|
+
}
|
|
20
|
+
/** The API the preload script exposes on `window.guidelyElectron`. */
|
|
21
|
+
interface GuidelyElectronBridge {
|
|
22
|
+
getAppInfo(): Promise<ElectronAppInfo>;
|
|
23
|
+
}
|
|
24
|
+
/** IPC channel used between the main-process handler and the preload bridge. */
|
|
25
|
+
declare const APP_INFO_CHANNEL = "guidely:app-info";
|
|
26
|
+
/** Global the preload bridge is exposed as (`contextBridge.exposeInMainWorld`). */
|
|
27
|
+
declare const BRIDGE_KEY = "guidelyElectron";
|
|
28
|
+
/** Desktop operating system names used in Guidely device properties. */
|
|
29
|
+
declare function osName(platform: string): string;
|
|
30
|
+
|
|
31
|
+
export { APP_INFO_CHANNEL as A, BRIDGE_KEY as B, type ElectronAppInfo as E, type GuidelyElectronBridge as G, osName as o };
|
package/package.json
CHANGED
|
@@ -1,6 +1,72 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@guidelytech/electron",
|
|
3
|
-
"version": "0.
|
|
4
|
-
"
|
|
5
|
-
"
|
|
3
|
+
"version": "0.12.0",
|
|
4
|
+
"description": "Guidely for Electron apps: page paths for file:// and custom protocols, app version and OS metadata, preload bridge",
|
|
5
|
+
"license": "MIT",
|
|
6
|
+
"type": "module",
|
|
7
|
+
"sideEffects": false,
|
|
8
|
+
"main": "./dist/index.cjs",
|
|
9
|
+
"module": "./dist/index.js",
|
|
10
|
+
"types": "./dist/index.d.ts",
|
|
11
|
+
"exports": {
|
|
12
|
+
".": {
|
|
13
|
+
"types": "./dist/index.d.ts",
|
|
14
|
+
"import": "./dist/index.js",
|
|
15
|
+
"require": "./dist/index.cjs"
|
|
16
|
+
},
|
|
17
|
+
"./main": {
|
|
18
|
+
"types": "./dist/main.d.ts",
|
|
19
|
+
"import": "./dist/main.js",
|
|
20
|
+
"require": "./dist/main.cjs"
|
|
21
|
+
},
|
|
22
|
+
"./preload": {
|
|
23
|
+
"types": "./dist/preload.d.ts",
|
|
24
|
+
"import": "./dist/preload.js",
|
|
25
|
+
"require": "./dist/preload.cjs"
|
|
26
|
+
}
|
|
27
|
+
},
|
|
28
|
+
"files": [
|
|
29
|
+
"dist",
|
|
30
|
+
"README.md"
|
|
31
|
+
],
|
|
32
|
+
"dependencies": {
|
|
33
|
+
"@guidelytech/sdk-core": "0.12.0"
|
|
34
|
+
},
|
|
35
|
+
"devDependencies": {
|
|
36
|
+
"@eslint/js": "^9.39.5",
|
|
37
|
+
"@types/node": "^22.20.5",
|
|
38
|
+
"eslint": "^9.39.5",
|
|
39
|
+
"tsup": "^8.5.1",
|
|
40
|
+
"typescript": "^5.9.3",
|
|
41
|
+
"typescript-eslint": "^8.46.0",
|
|
42
|
+
"vitest": "^3.2.7",
|
|
43
|
+
"happy-dom": "^17.6.3"
|
|
44
|
+
},
|
|
45
|
+
"publishConfig": {
|
|
46
|
+
"access": "public"
|
|
47
|
+
},
|
|
48
|
+
"repository": {
|
|
49
|
+
"type": "git",
|
|
50
|
+
"url": "git+https://github.com/GuidelyTech/Guidely.git",
|
|
51
|
+
"directory": "packages/electron"
|
|
52
|
+
},
|
|
53
|
+
"homepage": "https://github.com/GuidelyTech/Guidely/tree/main/packages/electron#readme",
|
|
54
|
+
"bugs": {
|
|
55
|
+
"url": "https://github.com/GuidelyTech/Guidely/issues"
|
|
56
|
+
},
|
|
57
|
+
"keywords": [
|
|
58
|
+
"guidely",
|
|
59
|
+
"electron",
|
|
60
|
+
"desktop",
|
|
61
|
+
"analytics",
|
|
62
|
+
"onboarding"
|
|
63
|
+
],
|
|
64
|
+
"scripts": {
|
|
65
|
+
"build": "rm -rf dist && tsup",
|
|
66
|
+
"dev": "tsup --watch",
|
|
67
|
+
"typecheck": "tsc --noEmit",
|
|
68
|
+
"test": "vitest run",
|
|
69
|
+
"lint": "eslint src",
|
|
70
|
+
"clean": "rm -rf dist"
|
|
71
|
+
}
|
|
6
72
|
}
|