Files
OpenTerminal/tests/build-bundles.cjs
T
Bill 35583b2c15 feat(lock): main-window lock screen; harden env gating, sandbox and ssh teardown
Lock screen (main-window overlay, no second window):
- scrypt password verifier in <userData>/lock.json (per-write salt,
  timingSafeEqual); salt/hash/password never leave the main process
- lock now / idle auto-lock / lock at startup, growing failure cooldown,
  lock flags persisted so a quit-and-relaunch cannot bypass the lock
- locked shell and body portals go inert while sessions keep running;
  menu accelerators (reload, DevTools, zoom) are swallowed while locked
- settings gains a Lock tab; all copy in zh-CN/zh-TW/en/ja

Security and stability:
- packaged builds ignore ELECTRON_RENDERER_URL / OT_UPDATE_URL (devEnv)
- renderer preload runs with sandbox: true
- unreadable known_hosts store fails closed instead of being overwritten
- connect-time secrets gated by the bookmark's auth method (connectPromptFor)
- ssh stream teardown is idempotent: PTY_EXIT broadcasts exactly once
- sysinfo polling is refcounted for split panes (forceStopPolling on close)
- session-log index entries are path-contained; settings store writes
  atomically with EPERM/EBUSY retry
- sync-changelog tolerates CRLF checkouts (was a silent no-op)
- retry ssh2 host-key generation (flaky malformed key, ~1/500)

Tests: lock-store + lock-controller suites; transport-death PTY_EXIT e2e;
GitHub Actions CI (typecheck + 10 offline tests + build)
2026-09-24 22:16:43 +08:00

54 lines
2.5 KiB
JavaScript

/* Rebuild every esbuild bundle the tests load, so a test run can never exercise
a stale bundle. `npm test` calls this first; run it standalone when you only
want fresh bundles.
The aliases live here (and nowhere else) so every bundle resolves `electron`
and `@shared` the same way. A bundle built without
`--alias:@shared=./src/shared` does not even compile: pty.ts reaches
@shared/theme through settingsStore.ts -> windowChrome.ts.
Usage: node tests/build-bundles.cjs */
const path = require('node:path')
const esbuild = require('esbuild')
const ROOT = path.join(__dirname, '..')
const BUNDLES = [
// Real session layer: pty.ts also re-exports the ssh + sysinfo engines.
{ entry: 'src/main/pty.ts', out: 'tests/.session-e2e.cjs', external: ['@lydell/node-pty', 'ssh2'] },
// ESM (`.mjs`): tests/sftp-*.mjs load it with `await import()`.
{ entry: 'src/main/sftp.ts', out: 'tests/.sftp-svc.mjs', format: 'esm', external: ['ssh2'] },
{ entry: 'src/main/commands.ts', out: 'tests/.commands-store.cjs' },
// Known-hosts store: TOFU / changed / unreadable fail-closed behavior.
{ entry: 'src/main/knownHosts.ts', out: 'tests/.known-hosts.cjs' },
{ entry: 'src/main/settingsStore.ts', out: 'tests/.settings-store.cjs' },
// Lock-password store: scrypt verifier, round trip, damaged-file handling.
{ entry: 'src/main/lockStore.ts', out: 'tests/.lock-store.cjs' },
// Lock controller: cooldown ladder, serialized attempts, persisted flags.
// Pulls in settingsStore + broadcast, which is why the electron stub needs
// powerMonitor as well.
{ entry: 'src/main/lockController.ts', out: 'tests/.lock-controller.cjs' },
// zmodem.js stays bundled (NOT external) — the test drives a second in-process
// Sentry from the same library.
{ entry: 'src/main/zmodem.ts', out: 'tests/.zmodem-e2e.cjs', external: ['ssh2'] },
// The smoke test imports the renderer engine (.ts), so it needs bundling too.
{ entry: 'tests/hl-split-smoke.mjs', out: 'tests/.hl-split-smoke.cjs' },
// Preset-rule assertions (word boundaries, case flag) over the same engine.
{ entry: 'tests/hl-rules.mjs', out: 'tests/.hl-rules.cjs' }
]
for (const { entry, out, format = 'cjs', external = [] } of BUNDLES) {
esbuild.buildSync({
absWorkingDir: ROOT,
entryPoints: [path.join(ROOT, entry)],
outfile: path.join(ROOT, out),
bundle: true,
platform: 'node',
format,
external,
alias: { electron: './tests/electron-stub.cjs', '@shared': './src/shared' },
logLevel: 'warning'
})
console.log(`built ${out}`)
}