@pmate/cli 0.35.3 → 0.35.5
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/index.js +8 -7
- package/dist/templates/electron/calls.cjs +4 -3
- package/dist/templates/electron/main.cjs +4 -3
- package/dist/templates/electron/notifications.cjs +2 -2
- package/dist/templates/electron/preload.cjs +1 -1
- package/dist/templates/electron/reach.cjs +3 -3
- package/package.json +17 -10
package/dist/index.js
CHANGED
|
@@ -17567,8 +17567,8 @@ async function buildDesktop(args) {
|
|
|
17567
17567
|
const icon = import_node_path23.default.resolve(base, c.icon);
|
|
17568
17568
|
const output = import_node_path23.default.resolve(args.outDir);
|
|
17569
17569
|
if (!(0, import_node_fs18.existsSync)(icon) || !(0, import_node_fs18.statSync)(icon).isFile()) throw new Error(`Desktop icon not found: ${icon}`);
|
|
17570
|
-
if (args.platform
|
|
17571
|
-
if (process.platform !== "darwin") throw new Error("macOS desktop packaging requires a macOS build host");
|
|
17570
|
+
if (!["mac", "win"].includes(args.platform) || !["arm64", "x64"].includes(args.arch)) throw new Error("Supported target: mac|win --arch arm64|x64");
|
|
17571
|
+
if (args.platform === "mac" && process.platform !== "darwin") throw new Error("macOS desktop packaging requires a macOS build host");
|
|
17572
17572
|
const within = (parent, child) => {
|
|
17573
17573
|
const rel = import_node_path23.default.relative(parent, child);
|
|
17574
17574
|
return !rel || !rel.startsWith("..") && !import_node_path23.default.isAbsolute(rel);
|
|
@@ -17596,7 +17596,7 @@ async function buildDesktop(args) {
|
|
|
17596
17596
|
(0, import_node_fs18.cpSync)(templateDir, appDir, { recursive: true });
|
|
17597
17597
|
(0, import_node_fs18.writeFileSync)(import_node_path23.default.join(appDir, "desktop-config.json"), JSON.stringify({ app: c.app, productName: c.productName, origin: c.origin, authOrigins: c.authOrigins, bundleId: c.bundleId }));
|
|
17598
17598
|
(0, import_node_fs18.writeFileSync)(import_node_path23.default.join(appDir, "resource-manifest.json"), JSON.stringify(manifest, null, 2));
|
|
17599
|
-
(0, import_node_fs18.writeFileSync)(import_node_path23.default.join(appDir, "package.json"), JSON.stringify({ name: c.bundleId.replace(/\./g, "-"), version: c.version, description: `${c.productName} desktop application`, author: "PMate", main: "main.cjs", dependencies: { "@pmate/chat-sdk": "0.
|
|
17599
|
+
(0, import_node_fs18.writeFileSync)(import_node_path23.default.join(appDir, "package.json"), JSON.stringify({ name: c.bundleId.replace(/\./g, "-"), version: c.version, description: `${c.productName} desktop application`, author: "PMate", main: "main.cjs", dependencies: { "@pmate/chat-sdk": "0.11.1" } }));
|
|
17600
17600
|
await runBuildCommand(["npm", "install", "--omit=dev", "--no-audit", "--no-fund"], appDir);
|
|
17601
17601
|
const cache = import_node_path23.default.join((0, import_node_os9.homedir)(), ".cache", "pmate", "electron", `${ELECTRON_VERSION}-${BUILDER_VERSION}`);
|
|
17602
17602
|
(0, import_node_fs18.mkdirSync)(cache, { recursive: true });
|
|
@@ -17614,12 +17614,13 @@ async function buildDesktop(args) {
|
|
|
17614
17614
|
asar: true,
|
|
17615
17615
|
artifactName: "${productName}-${version}-${arch}.${ext}",
|
|
17616
17616
|
mac: { icon, target: args.dir ? ["dir"] : ["dmg", "zip"], category: "public.app-category.social-networking", hardenedRuntime: args.signed, extendInfo: { NSMicrophoneUsageDescription: `${c.productName} uses your microphone for voice calls and voice messages.` }, ...args.signed ? {} : { identity: "-", notarize: false } },
|
|
17617
|
+
win: { icon, target: args.dir ? ["dir"] : ["nsis", "zip"], ...args.signed ? {} : { signExecutable: false } },
|
|
17617
17618
|
forceCodeSigning: args.signed
|
|
17618
17619
|
};
|
|
17619
17620
|
const configPath = import_node_path23.default.join(staging, "builder.json");
|
|
17620
17621
|
(0, import_node_fs18.writeFileSync)(configPath, JSON.stringify(builderConfig));
|
|
17621
|
-
await runBuildCommand([process.execPath, import_node_path23.default.join(cache, "node_modules", "electron-builder", "cli.js"), "--config", configPath, "--mac", `--${args.arch}`, "--publish", "never"], appDir, { ...process.env, ...args.signed ? {} : { CSC_IDENTITY_AUTO_DISCOVERY: "false" } });
|
|
17622
|
-
const result = { ...plan, signature: args.signed ? "configured-signing-required; verify notarization before distribution" : "ad-hoc; local development", artifacts: import_node_path23.default.join(staging, "artifacts"), resources: manifest };
|
|
17622
|
+
await runBuildCommand([process.execPath, import_node_path23.default.join(cache, "node_modules", "electron-builder", "cli.js"), "--config", configPath, args.platform === "mac" ? "--mac" : "--win", `--${args.arch}`, "--publish", "never"], appDir, { ...process.env, ...args.signed ? {} : { CSC_IDENTITY_AUTO_DISCOVERY: "false" } });
|
|
17623
|
+
const result = { ...plan, signature: args.signed ? args.platform === "mac" ? "configured-signing-required; verify notarization before distribution" : "configured-signing-required; verify Authenticode before distribution" : args.platform === "mac" ? "ad-hoc; local development" : "unsigned; local development", artifacts: import_node_path23.default.join(staging, "artifacts"), resources: manifest };
|
|
17623
17624
|
(0, import_node_fs18.writeFileSync)(import_node_path23.default.join(staging, "build-report.json"), JSON.stringify(result, null, 2));
|
|
17624
17625
|
console.log(JSON.stringify({ phase: "complete", report: import_node_path23.default.join(staging, "build-report.json"), artifacts: result.artifacts, signature: result.signature }, null, 2));
|
|
17625
17626
|
}
|
|
@@ -23466,9 +23467,9 @@ function parseAppArgs(tokens) {
|
|
|
23466
23467
|
} else throw new Error(`Unknown app build option: ${key}`);
|
|
23467
23468
|
}
|
|
23468
23469
|
if (options["--target"] !== "electron" || !options["--config"]) throw new Error("Use app build <ns:app> --target electron --config <file>");
|
|
23469
|
-
const platform = options["--platform"] ?? (process.platform === "darwin" ? "mac" : process.platform);
|
|
23470
|
+
const platform = options["--platform"] ?? (process.platform === "darwin" ? "mac" : process.platform === "win32" ? "win" : process.platform);
|
|
23470
23471
|
const arch = options["--arch"] ?? process.arch;
|
|
23471
|
-
if (
|
|
23472
|
+
if (!["mac", "win"].includes(platform) || !["arm64", "x64"].includes(arch)) throw new Error("Supported target: --platform mac|win --arch arm64|x64");
|
|
23472
23473
|
return { type: "app" /* App */, action, id, target: "electron", config: options["--config"], platform, arch, outDir: options["--out-dir"] ?? "release/desktop", dryRun: switches.has("--dry-run"), signed: switches.has("--signed"), dir: switches.has("--dir"), json: switches.has("--json") };
|
|
23473
23474
|
}
|
|
23474
23475
|
let baseUrl;
|
|
@@ -47,7 +47,7 @@ function createDesktopCalls({ appId, instanceId, origin, BrowserWindow, ipcMain,
|
|
|
47
47
|
ipcMain.handle('pmate:call:session', event => {
|
|
48
48
|
if (!trusted(event) || !identity || !client) throw new Error('Untrusted call session request')
|
|
49
49
|
const callerId = client.snapshot().peerId, caller = people.get(callerId) ?? { id: callerId, name: '联系人' }
|
|
50
|
-
return { callId: current.callId, profileId: identity.profileId, token: identity.token, clientInstanceId: instanceId, caller, url: 'wss://calls.pmate.chat/call' }
|
|
50
|
+
return { callId: current.callId, teamId: client.snapshot().teamId, profileId: identity.profileId, token: identity.token, clientInstanceId: instanceId, caller, url: 'wss://calls.pmate.chat/call' }
|
|
51
51
|
})
|
|
52
52
|
ipcMain.handle('pmate:call:state', (event, state) => {
|
|
53
53
|
if (!trusted(event) || !state || state.callId !== current.callId || !['idle', 'requesting', 'ringing', 'incoming', 'connecting', 'connected', 'ended'].includes(state.phase)) throw new Error('Invalid call window state')
|
|
@@ -87,10 +87,11 @@ function createDesktopCalls({ appId, instanceId, origin, BrowserWindow, ipcMain,
|
|
|
87
87
|
if (event.eventType === 'call.ended' && result === 'handled' && current?.callId === event.payload.callId) destroy()
|
|
88
88
|
return result
|
|
89
89
|
},
|
|
90
|
-
async incoming(callId) {
|
|
90
|
+
async incoming(callId, teamId) {
|
|
91
91
|
if (!client || typeof callId !== 'string' || !callId || callId.length > 128) throw new Error('Invalid incoming call')
|
|
92
|
+
if (teamId !== undefined && current?.callId === callId && client.snapshot().teamId !== teamId) throw new Error('CALL_TEAM_MISMATCH')
|
|
92
93
|
if (current?.callId === callId && ['incoming', 'connecting', 'connected'].includes(current.phase)) { current.window.show(); current.window.focus(); return current.ready }
|
|
93
|
-
const ownGeneration = generation, result = await client.attachAndWait(callId)
|
|
94
|
+
const ownGeneration = generation, result = await client.attachAndWait(callId, 4000, teamId)
|
|
94
95
|
if (generation !== ownGeneration) throw new Error('Call identity changed')
|
|
95
96
|
return result === 'handled' ? present(callId) : result
|
|
96
97
|
},
|
|
@@ -9,6 +9,7 @@ const { createDesktopCalls } = require('./calls.cjs')
|
|
|
9
9
|
const config = require('./desktop-config.json')
|
|
10
10
|
const manifest = require('./resource-manifest.json')
|
|
11
11
|
app.setName(config.productName)
|
|
12
|
+
if (process.platform === 'win32') app.setAppUserModelId(config.bundleId)
|
|
12
13
|
// Stable across installer versions; separate from every other packaged PMate app.
|
|
13
14
|
app.setPath('userData', path.join(app.getPath('appData'), config.bundleId))
|
|
14
15
|
const allowedNavigation = new Set([config.origin, ...config.authOrigins])
|
|
@@ -72,13 +73,13 @@ else {
|
|
|
72
73
|
if (config.app === 'pmate:hello') desktopCalls = createDesktopCalls({ appId: config.app, instanceId, origin: config.origin, BrowserWindow, ipcMain, dialog })
|
|
73
74
|
desktopReach = createDesktopReach({ appId: config.app, instanceId, present: input => desktopNotifications.display(input),
|
|
74
75
|
configureCalls: identity => { rendererReach.reset(); return desktopCalls?.configure(identity) }, stopCalls: () => { rendererReach.reset(); desktopCalls?.stop() },
|
|
75
|
-
incomingCall: callId => { if (!desktopCalls) throw new Error('Call handler unavailable'); return desktopCalls.incoming(callId) },
|
|
76
|
+
incomingCall: (callId, teamId) => { if (!desktopCalls) throw new Error('Call handler unavailable'); return desktopCalls.incoming(callId, teamId) },
|
|
76
77
|
isViewingThread: threadId => desktopNotifications.isViewingThread(threadId),
|
|
77
78
|
onReach: event => ['call.incoming', 'call.ended'].includes(event.eventType) && desktopCalls ? desktopCalls.handleReach(event) : rendererReach.deliver(event),
|
|
78
79
|
})
|
|
79
|
-
ipcMain.handle('pmate:call:incoming', (event, callId) => {
|
|
80
|
+
ipcMain.handle('pmate:call:incoming', (event, callId, teamId) => {
|
|
80
81
|
if (!desktopNotifications.trusted(event) || !desktopCalls) throw new Error('Untrusted call sender')
|
|
81
|
-
return desktopCalls.incoming(callId)
|
|
82
|
+
return desktopCalls.incoming(callId, teamId)
|
|
82
83
|
})
|
|
83
84
|
ipcMain.handle('pmate:call:reach', (event, value) => {
|
|
84
85
|
if (!desktopNotifications.trusted(event) || !desktopCalls) throw new Error('Untrusted call sender')
|
|
@@ -18,7 +18,7 @@ function createDesktopNotifications({ ipcMain, Notification, origin, appId, getW
|
|
|
18
18
|
const display = input => {
|
|
19
19
|
if (!input || input.appId !== appId || typeof input.notificationId !== 'string' || !input.notificationId || input.notificationId.length > 512
|
|
20
20
|
|| typeof input.title !== 'string' || input.title.length > 256 || typeof input.body !== 'string' || input.body.length > 4096
|
|
21
|
-
|| ['threadId', 'callId', 'meetingId'].some(key => input[key] !== undefined && (typeof input[key] !== 'string' || input[key].length > 512))) throw new Error('Invalid notification')
|
|
21
|
+
|| ['threadId', 'callId', 'meetingId', 'teamId'].some(key => input[key] !== undefined && (typeof input[key] !== 'string' || input[key].length > 512))) throw new Error('Invalid notification')
|
|
22
22
|
for (const [id, item] of shown) if (item.until <= now()) { item.notification.close(); shown.delete(id) }
|
|
23
23
|
if (input.expiresAtMs !== undefined && (!Number.isFinite(input.expiresAtMs) || input.expiresAtMs <= now())) return 'suppressed'
|
|
24
24
|
if (shown.has(input.notificationId)) return 'suppressed'
|
|
@@ -49,7 +49,7 @@ function createDesktopNotifications({ ipcMain, Notification, origin, appId, getW
|
|
|
49
49
|
notification.once('failed', () => { if (!settled) { settled = true; clearTimeout(timeout); reject(new Error('Notification display failed')) } })
|
|
50
50
|
notification.on('click', () => {
|
|
51
51
|
const main = showWindow()
|
|
52
|
-
pendingOpen = { notificationId: input.notificationId, threadId: input.threadId, callId: input.callId, meetingId: input.meetingId }
|
|
52
|
+
pendingOpen = { teamId: input.teamId, notificationId: input.notificationId, threadId: input.threadId, callId: input.callId, meetingId: input.meetingId }
|
|
53
53
|
main.webContents.send('pmate:notification:open', pendingOpen)
|
|
54
54
|
notification.close()
|
|
55
55
|
})
|
|
@@ -15,7 +15,7 @@ contextBridge.exposeInMainWorld('pmateDesktop', Object.freeze({
|
|
|
15
15
|
stop: () => ipcRenderer.invoke('pmate:reach:stop'),
|
|
16
16
|
}),
|
|
17
17
|
calls: Object.freeze({
|
|
18
|
-
incoming: callId => ipcRenderer.invoke('pmate:call:incoming', callId),
|
|
18
|
+
incoming: (callId, teamId) => ipcRenderer.invoke('pmate:call:incoming', callId, teamId),
|
|
19
19
|
handleReach: event => ipcRenderer.invoke('pmate:call:reach', event),
|
|
20
20
|
setPeople: people => ipcRenderer.invoke('pmate:call:people', people),
|
|
21
21
|
}),
|
|
@@ -33,15 +33,15 @@ function createDesktopReach({ appId, instanceId, hubUrl = 'wss://hub.pmate.chat'
|
|
|
33
33
|
if (data.type === 'call.incoming') {
|
|
34
34
|
if (!incomingCall || typeof data.callId !== 'string' || typeof data.callerId !== 'string') throw new Error('Call handler unavailable')
|
|
35
35
|
const { dmThreadId } = await import('@pmate/chat-sdk/runtime')
|
|
36
|
-
threadId = dmThreadId(appId, value.profileId, data.callerId)
|
|
36
|
+
threadId = dmThreadId(appId, value.profileId, data.callerId, data.teamId)
|
|
37
37
|
const viewed = isViewingThread?.(threadId)
|
|
38
|
-
const result = await incomingCall(data.callId)
|
|
38
|
+
const result = await incomingCall(data.callId, data.teamId)
|
|
39
39
|
if (generation !== ownGeneration) throw new Error('Reach account changed')
|
|
40
40
|
if (result === 'suppressed' || viewed) return 'suppressed'
|
|
41
41
|
}
|
|
42
42
|
const digestThreads = data.type === 'social.messageDigest' ? JSON.parse(data.threads) : undefined
|
|
43
43
|
return present({ appId, notificationId: notification.notificationId, title: notification.title ?? '', body: notification.body ?? '', digestThreads,
|
|
44
|
-
threadId, callId: data.callId, meetingId: data.meetingId, expiresAtMs: notification.expiresAtMs })
|
|
44
|
+
threadId, teamId: data.teamId, callId: data.callId, meetingId: data.meetingId, expiresAtMs: notification.expiresAtMs })
|
|
45
45
|
},
|
|
46
46
|
onReach: async event => {
|
|
47
47
|
if (generation !== ownGeneration || !onReach) throw new Error('Reach handler unavailable')
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@pmate/cli",
|
|
3
|
-
"version": "0.35.
|
|
3
|
+
"version": "0.35.5",
|
|
4
4
|
"description": "CLI utilities for the pMate project",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"bin": {
|
|
@@ -11,6 +11,16 @@
|
|
|
11
11
|
"files": [
|
|
12
12
|
"dist"
|
|
13
13
|
],
|
|
14
|
+
"scripts": {
|
|
15
|
+
"build": "npm run clean && tsup --config tsup.config.ts && node scripts/copy-templates.js",
|
|
16
|
+
"clean": "rimraf dist",
|
|
17
|
+
"dev": "ts-node src/index.ts",
|
|
18
|
+
"release": "pnpm publish",
|
|
19
|
+
"start": "node dist/index.js",
|
|
20
|
+
"test": "vitest run src/tests",
|
|
21
|
+
"typecheck": "tsc --noEmit",
|
|
22
|
+
"prepare": "npm run build"
|
|
23
|
+
},
|
|
14
24
|
"keywords": [
|
|
15
25
|
"cli",
|
|
16
26
|
"typescript",
|
|
@@ -57,13 +67,10 @@
|
|
|
57
67
|
"typescript": "^5.9.3",
|
|
58
68
|
"vitest": "^4.0.17"
|
|
59
69
|
},
|
|
60
|
-
"
|
|
61
|
-
"
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
"start": "node dist/index.js",
|
|
66
|
-
"test": "vitest run src/tests",
|
|
67
|
-
"typecheck": "tsc --noEmit"
|
|
70
|
+
"pnpm": {
|
|
71
|
+
"overrides": {
|
|
72
|
+
"@pmate/meta": "^1.3.1",
|
|
73
|
+
"@pmate/utils": "^1.1.4"
|
|
74
|
+
}
|
|
68
75
|
}
|
|
69
|
-
}
|
|
76
|
+
}
|