mirror of
https://github.com/wu736139669/hapi.git
synced 2026-08-05 06:24:37 +00:00
chore: migrate cli distribution from npm to bun executable
Migrate HAPI CLI from npm-based distribution to Bun single-executable format: - Remove npm bin wrappers (bin/happy.mjs, bin/happy-mcp.mjs) - Simplify package.json: remove npm publish config (exports, main, module, types, files, publishConfig) - Update bin entry to point to TypeScript source (src/index.ts) - Migrate shebang from Node to Bun (#!/usr/bin/env bun) - Simplify build scripts: remove npm-specific steps (pkgroll, prepublishOnly, release-it) - Update spawnHappyCLI to support compiled binaries and development TypeScript mode - Update daemon/doctor diagnostics for new process detection logic - Production: use `bun build --compile` for single-executable releases - Development: run TypeScript directly via `bun src/index.ts` or `tsx src/index.ts`
This commit is contained in:
@@ -1,30 +0,0 @@
|
||||
#!/usr/bin/env node
|
||||
|
||||
import { execFileSync } from 'child_process';
|
||||
import { fileURLToPath } from 'url';
|
||||
import { runHappyMcpStdioBridge } from '../dist/codex/happyMcpStdioBridge.mjs';
|
||||
|
||||
// Ensure Node flags to reduce noisy warnings on stdout (which could interfere with MCP)
|
||||
const hasNoWarnings = process.execArgv.includes('--no-warnings');
|
||||
const hasNoDeprecation = process.execArgv.includes('--no-deprecation');
|
||||
|
||||
if (!hasNoWarnings || !hasNoDeprecation) {
|
||||
const entrypoint = fileURLToPath(import.meta.url);
|
||||
|
||||
try {
|
||||
execFileSync(process.execPath, [
|
||||
'--no-warnings',
|
||||
'--no-deprecation',
|
||||
entrypoint,
|
||||
...process.argv.slice(2)
|
||||
], {
|
||||
stdio: 'inherit',
|
||||
env: process.env
|
||||
});
|
||||
} catch (error) {
|
||||
process.exit(error.status || 1);
|
||||
}
|
||||
} else {
|
||||
// Already have desired flags; run bridge directly
|
||||
await runHappyMcpStdioBridge(process.argv.slice(2));
|
||||
}
|
||||
@@ -1,35 +0,0 @@
|
||||
#!/usr/bin/env node
|
||||
|
||||
import { execFileSync } from 'child_process';
|
||||
import { fileURLToPath } from 'url';
|
||||
import { join, dirname } from 'path';
|
||||
|
||||
// Check if we're already running with the flags
|
||||
const hasNoWarnings = process.execArgv.includes('--no-warnings');
|
||||
const hasNoDeprecation = process.execArgv.includes('--no-deprecation');
|
||||
|
||||
if (!hasNoWarnings || !hasNoDeprecation) {
|
||||
// Get path to the actual CLI entrypoint
|
||||
const projectRoot = dirname(dirname(fileURLToPath(import.meta.url)));
|
||||
const entrypoint = join(projectRoot, 'dist', 'index.mjs');
|
||||
|
||||
// Execute the actual CLI directly with the correct flags
|
||||
try {
|
||||
execFileSync(process.execPath, [
|
||||
'--no-warnings',
|
||||
'--no-deprecation',
|
||||
entrypoint,
|
||||
...process.argv.slice(2)
|
||||
], {
|
||||
stdio: 'inherit',
|
||||
env: process.env
|
||||
});
|
||||
} catch (error) {
|
||||
// execFileSync throws if the process exits with non-zero
|
||||
process.exit(error.status || 1);
|
||||
}
|
||||
} else {
|
||||
// We're running Node with the flags we wanted, import the CLI entrypoint
|
||||
// module to avoid creating a new process.
|
||||
import("../dist/index.mjs");
|
||||
}
|
||||
+5
-60
@@ -13,43 +13,7 @@
|
||||
"directory": "cli"
|
||||
},
|
||||
"bin": {
|
||||
"hapi": "./bin/happy.mjs",
|
||||
"hapi-mcp": "./bin/happy-mcp.mjs"
|
||||
},
|
||||
"main": "./dist/index.cjs",
|
||||
"module": "./dist/index.mjs",
|
||||
"types": "./dist/index.d.cts",
|
||||
"exports": {
|
||||
".": {
|
||||
"require": {
|
||||
"types": "./dist/index.d.cts",
|
||||
"default": "./dist/index.cjs"
|
||||
},
|
||||
"import": {
|
||||
"types": "./dist/index.d.mts",
|
||||
"default": "./dist/index.mjs"
|
||||
}
|
||||
},
|
||||
"./lib": {
|
||||
"require": {
|
||||
"types": "./dist/lib.d.cts",
|
||||
"default": "./dist/lib.cjs"
|
||||
},
|
||||
"import": {
|
||||
"types": "./dist/lib.d.mts",
|
||||
"default": "./dist/lib.mjs"
|
||||
}
|
||||
},
|
||||
"./codex/happyMcpStdioBridge": {
|
||||
"require": {
|
||||
"types": "./dist/codex/happyMcpStdioBridge.d.cts",
|
||||
"default": "./dist/codex/happyMcpStdioBridge.cjs"
|
||||
},
|
||||
"import": {
|
||||
"types": "./dist/codex/happyMcpStdioBridge.d.mts",
|
||||
"default": "./dist/codex/happyMcpStdioBridge.mjs"
|
||||
}
|
||||
}
|
||||
"hapi": "./src/index.ts"
|
||||
},
|
||||
"imports": {
|
||||
"#embedded-assets": {
|
||||
@@ -57,31 +21,17 @@
|
||||
"default": "./src/runtime/embeddedAssets.stub.ts"
|
||||
}
|
||||
},
|
||||
"files": [
|
||||
"dist",
|
||||
"bin",
|
||||
"scripts",
|
||||
"tools",
|
||||
"package.json"
|
||||
],
|
||||
"scripts": {
|
||||
"why do we need to build before running tests / dev?": "We need the binary to be built so we run daemon commands which directly run the binary - we don't want them to go out of sync or have custom spawn logic depending how we started HAPI",
|
||||
"typecheck": "tsc --noEmit",
|
||||
"build": "bun run scripts/write-embedded-assets-stub.ts && shx rm -rf dist && tsc --noEmit && pkgroll",
|
||||
"build:exe": "bun run scripts/build-executable.ts",
|
||||
"build:exe:all": "bun run scripts/build-executable.ts --all",
|
||||
"build:exe:allinone": "bun run scripts/build-executable.ts --with-web-assets",
|
||||
"build:exe:allinone:all": "bun run scripts/build-executable.ts --with-web-assets --all",
|
||||
"test": "bun run build && tsx --env-file .env.integration-test node_modules/.bin/vitest run",
|
||||
"test:win": "bun run build && vitest run",
|
||||
"start": "bun run build && ./bin/happy.mjs",
|
||||
"start:win": "bun run build && node ./bin/happy.mjs",
|
||||
"test": "tsx --env-file .env.integration-test node_modules/.bin/vitest run",
|
||||
"test:win": "vitest run",
|
||||
"dev": "tsx src/index.ts",
|
||||
"dev:local-server": "bun run build && tsx --env-file .env.dev-local-server src/index.ts",
|
||||
"dev:integration-test-env": "bun run build && tsx --env-file .env.integration-test src/index.ts",
|
||||
"prepublishOnly": "bun run build && bun run test",
|
||||
"release": "release-it",
|
||||
"postinstall": "node scripts/unpack-tools.cjs"
|
||||
"dev:local-server": "tsx --env-file .env.dev-local-server src/index.ts",
|
||||
"dev:integration-test-env": "tsx --env-file .env.integration-test src/index.ts"
|
||||
},
|
||||
"dependencies": {
|
||||
"@modelcontextprotocol/sdk": "^1.22.0",
|
||||
@@ -110,8 +60,6 @@
|
||||
"dotenv": "^16.6.1",
|
||||
"eslint": "^9",
|
||||
"eslint-config-prettier": "^10",
|
||||
"pkgroll": "^2.14.2",
|
||||
"release-it": "^19.0.6",
|
||||
"shx": "^0.3.3",
|
||||
"ts-node": "^10",
|
||||
"tsx": "^4.20.6",
|
||||
@@ -123,8 +71,5 @@
|
||||
"parse-path": "7.0.3",
|
||||
"@types/parse-path": "7.0.3"
|
||||
},
|
||||
"publishConfig": {
|
||||
"registry": "https://registry.npmjs.org"
|
||||
},
|
||||
"packageManager": "bun@1.3.4"
|
||||
}
|
||||
|
||||
@@ -112,7 +112,7 @@ Local HTTP server (127.0.0.1 only) provides:
|
||||
### Doctor Command
|
||||
|
||||
`hapi doctor` uses `ps aux | grep` to find all HAPI processes:
|
||||
- Production: matches `happy.mjs`, `happy-coder`, `dist/index.mjs`
|
||||
- Production: matches `hapi` binary, `happy-coder`
|
||||
- Development: matches `tsx.*src/index.ts`
|
||||
- Categorizes by command args: daemon, daemon-spawned, user-session, doctor
|
||||
|
||||
|
||||
@@ -407,7 +407,7 @@ describe.skipIf(!await isServerHealthy())('Daemon Integration Tests', { timeout:
|
||||
*
|
||||
* Critical timing constraints:
|
||||
* - Heartbeat must be long enough (30s) for yarn build to complete before daemon tries to spawn
|
||||
* - If heartbeat fires during rebuild, spawn fails (dist/index.mjs missing) and test fails
|
||||
* - If heartbeat fires during rebuild, spawn fails (entrypoint missing) and test fails
|
||||
* - pkgroll doesn't reliably update compiled version, must use full yarn build
|
||||
* - Test modifies package.json BEFORE rebuild to ensure new version is compiled in
|
||||
*
|
||||
@@ -472,6 +472,6 @@ describe.skipIf(!await isServerHealthy())('Daemon Integration Tests', { timeout:
|
||||
// TODO: Add a test to see if a corrupted file will work
|
||||
|
||||
// TODO: Test npm uninstall scenario - daemon should gracefully handle when hapi is uninstalled
|
||||
// Current behavior: daemon tries to spawn new daemon on version mismatch but dist/index.mjs is gone
|
||||
// Current behavior: daemon tries to spawn new daemon on version mismatch but entrypoint is gone
|
||||
// Expected: daemon should detect missing entrypoint and either exit cleanly or at minimum not respawn infinitely
|
||||
});
|
||||
|
||||
@@ -22,12 +22,12 @@ export async function findAllHappyProcesses(): Promise<Array<{ pid: number, comm
|
||||
|
||||
// Check if it's a HAPI process
|
||||
const isHappyBinary = name === 'hapi' || name === 'hapi.exe' || /\bhapi(\.exe)?\b/.test(cmd);
|
||||
const isHappy = name.includes('happy') ||
|
||||
name === 'node' && (cmd.includes('happy-cli') || cmd.includes('dist/index.mjs')) ||
|
||||
cmd.includes('happy.mjs') ||
|
||||
const isHappy = name.includes('happy') ||
|
||||
name === 'node' && cmd.includes('happy-cli') ||
|
||||
cmd.includes('happy-coder') ||
|
||||
isHappyBinary ||
|
||||
(cmd.includes('tsx') && cmd.includes('src/index.ts') && cmd.includes('happy-cli'));
|
||||
(cmd.includes('tsx') && cmd.includes('src/index.ts') && cmd.includes('happy-cli')) ||
|
||||
(cmd.includes('bun') && cmd.includes('src/index.ts') && cmd.includes('happy-cli'));
|
||||
|
||||
if (!isHappy) continue;
|
||||
|
||||
|
||||
Regular → Executable
+1
-1
@@ -1,4 +1,4 @@
|
||||
#!/usr/bin/env node
|
||||
#!/usr/bin/env bun
|
||||
|
||||
/**
|
||||
* CLI entry point for hapi command
|
||||
|
||||
@@ -92,17 +92,14 @@ export async function runDoctorCommand(filter?: 'all' | 'daemon'): Promise<void>
|
||||
// Daemon spawn diagnostics
|
||||
console.log(chalk.bold('🔧 Daemon Spawn Diagnostics'));
|
||||
const projectRoot = projectPath();
|
||||
const wrapperPath = join(projectRoot, 'bin', 'happy.mjs');
|
||||
const cliEntrypoint = join(projectRoot, 'dist', 'index.mjs');
|
||||
|
||||
const cliEntrypoint = join(projectRoot, 'src', 'index.ts');
|
||||
|
||||
if (isBunCompiled()) {
|
||||
console.log(`Executable: ${chalk.blue(process.execPath)}`);
|
||||
console.log(`Runtime Assets: ${chalk.blue(runtimePath())}`);
|
||||
} else {
|
||||
console.log(`Project Root: ${chalk.blue(projectRoot)}`);
|
||||
console.log(`Wrapper Script: ${chalk.blue(wrapperPath)}`);
|
||||
console.log(`CLI Entrypoint: ${chalk.blue(cliEntrypoint)}`);
|
||||
console.log(`Wrapper Exists: ${existsSync(wrapperPath) ? chalk.green('✓ Yes') : chalk.red('❌ No')}`);
|
||||
console.log(`CLI Exists: ${existsSync(cliEntrypoint) ? chalk.green('✓ Yes') : chalk.red('❌ No')}`);
|
||||
}
|
||||
console.log('');
|
||||
|
||||
@@ -1,56 +1,28 @@
|
||||
/**
|
||||
* Cross-platform HAPI CLI spawning utility
|
||||
*
|
||||
* ## Background
|
||||
*
|
||||
* We built a command-line JavaScript program with the entrypoint at `dist/index.mjs`.
|
||||
* This needs to be run with a JS runtime (Node.js or Bun). For Node we want to hide
|
||||
* deprecation warnings and other
|
||||
* noise from end users by passing specific flags: `--no-warnings --no-deprecation`.
|
||||
*
|
||||
* Users don't care about these technical details - they just want a clean experience
|
||||
* with no warning output when using HAPI.
|
||||
*
|
||||
* ## The Wrapper Strategy
|
||||
*
|
||||
* We created a wrapper script `bin/happy.mjs` with a shebang `#!/usr/bin/env node`.
|
||||
* This allows direct execution on Unix systems and NPM automatically generates
|
||||
* Windows-specific wrapper scripts (`hapi.cmd` and `hapi.ps1`) when it sees
|
||||
* the `bin` field in package.json pointing to a JavaScript file with a shebang.
|
||||
*
|
||||
* The wrapper script either directly execs `dist/index.mjs` with the flags we want,
|
||||
* or imports it directly if Node.js already has the right flags.
|
||||
*
|
||||
* ## Execution Chains
|
||||
*
|
||||
* **Unix/Linux/macOS:**
|
||||
* 1. User runs `hapi` command
|
||||
* 2. Shell directly executes `bin/happy.mjs` (shebang: `#!/usr/bin/env node`)
|
||||
* 3. `bin/happy.mjs` either execs `node --no-warnings --no-deprecation dist/index.mjs` or imports `dist/index.mjs` directly
|
||||
*
|
||||
* **Windows:**
|
||||
* 1. User runs `hapi` command
|
||||
* 2. NPM wrapper (`hapi.cmd`) calls `node bin/happy.mjs`
|
||||
* 3. `bin/happy.mjs` either execs `node --no-warnings --no-deprecation dist/index.mjs` or imports `dist/index.mjs` directly
|
||||
*
|
||||
* ## The Spawning Problem
|
||||
*
|
||||
* When our code needs to spawn HAPI CLI as a subprocess (for daemon processes),
|
||||
* we were trying to execute `bin/happy.mjs` directly. This fails on Windows
|
||||
* because Windows doesn't understand shebangs - you get an `EFTYPE` error.
|
||||
*
|
||||
* ## The Solution
|
||||
*
|
||||
* Since we know exactly what needs to happen (run `dist/index.mjs` with the current
|
||||
* runtime), we can bypass all the wrapper layers and do it directly:
|
||||
*
|
||||
* `spawn(process.execPath, ['--no-warnings', '--no-deprecation', 'dist/index.mjs', ...args])`
|
||||
*
|
||||
* When running under Bun, we spawn the Bun executable with the entrypoint and
|
||||
* omit Node-specific flags.
|
||||
*
|
||||
* This works on all platforms and achieves the same result without any of the
|
||||
* middleman steps that were providing workarounds for Windows vs Linux differences.
|
||||
* ## Background
|
||||
*
|
||||
* HAPI CLI runs in two modes:
|
||||
* 1. **Compiled binary**: A single executable built with `bun build --compile`
|
||||
* 2. **Development mode**: Running TypeScript directly via `tsx` or `bun`
|
||||
*
|
||||
* ## Execution Modes
|
||||
*
|
||||
* **Compiled Binary (Production):**
|
||||
* - The executable is self-contained and runs directly
|
||||
* - `process.execPath` points to the compiled binary itself
|
||||
* - No additional entrypoint needed - just pass args to `process.execPath`
|
||||
*
|
||||
* **Development Mode:**
|
||||
* - Running via `tsx src/index.ts` or `bun src/index.ts`
|
||||
* - Spawn child processes using the same runtime with `src/index.ts` entrypoint
|
||||
*
|
||||
* ## Cross-Platform Support
|
||||
*
|
||||
* This utility handles spawning HAPI CLI subprocesses (for daemon processes)
|
||||
* in a cross-platform way, detecting the current runtime mode and using
|
||||
* the appropriate command and arguments.
|
||||
*/
|
||||
|
||||
import { spawn, SpawnOptions, type ChildProcess } from 'child_process';
|
||||
@@ -60,28 +32,15 @@ import { logger } from '@/ui/logger';
|
||||
import { existsSync } from 'node:fs';
|
||||
|
||||
/**
|
||||
* Spawn the HAPI CLI with the given arguments in a cross-platform way.
|
||||
*
|
||||
* This function bypasses the wrapper script (bin/happy.mjs) and spawns the
|
||||
* actual CLI entrypoint (dist/index.mjs) directly with the current runtime
|
||||
* (Node.js or Bun), ensuring compatibility across all platforms including Windows.
|
||||
*
|
||||
* @param args - Arguments to pass to the HAPI CLI
|
||||
* @param options - Spawn options (same as child_process.spawn)
|
||||
* @returns ChildProcess instance
|
||||
* Resolve the TypeScript entrypoint for development mode.
|
||||
*/
|
||||
function resolveEntrypointForBun(projectRoot: string): string {
|
||||
const distEntrypoint = join(projectRoot, 'dist', 'index.mjs');
|
||||
if (existsSync(distEntrypoint)) {
|
||||
return distEntrypoint;
|
||||
}
|
||||
|
||||
function resolveEntrypoint(projectRoot: string): string {
|
||||
const srcEntrypoint = join(projectRoot, 'src', 'index.ts');
|
||||
if (existsSync(srcEntrypoint)) {
|
||||
return srcEntrypoint;
|
||||
}
|
||||
|
||||
throw new Error('No CLI entrypoint found for Bun runtime (expected dist/index.mjs or src/index.ts)');
|
||||
throw new Error('No CLI entrypoint found (expected src/index.ts)');
|
||||
}
|
||||
|
||||
export interface HappyCliCommand {
|
||||
@@ -90,6 +49,7 @@ export interface HappyCliCommand {
|
||||
}
|
||||
|
||||
export function getHappyCliCommand(args: string[]): HappyCliCommand {
|
||||
// Compiled binary mode: just use the executable directly
|
||||
if (isBunCompiled()) {
|
||||
return {
|
||||
command: process.execPath,
|
||||
@@ -97,31 +57,23 @@ export function getHappyCliCommand(args: string[]): HappyCliCommand {
|
||||
};
|
||||
}
|
||||
|
||||
// Development mode: spawn with TypeScript entrypoint
|
||||
const projectRoot = projectPath();
|
||||
const distEntrypoint = join(projectRoot, 'dist', 'index.mjs');
|
||||
const entrypoint = resolveEntrypoint(projectRoot);
|
||||
const isBunRuntime = Boolean((process.versions as Record<string, string | undefined>).bun);
|
||||
const entrypoint = isBunRuntime ? resolveEntrypointForBun(projectRoot) : distEntrypoint;
|
||||
|
||||
const argv1 = process.argv[1] ?? '';
|
||||
const runningFromSource = argv1.endsWith(join('src', 'index.ts')) || process.execArgv.some((arg) => arg.includes('tsx'));
|
||||
const srcEntrypoint = join(projectRoot, 'src', 'index.ts');
|
||||
if (!isBunRuntime && runningFromSource && existsSync(srcEntrypoint)) {
|
||||
if (isBunRuntime) {
|
||||
// Bun can run TypeScript directly
|
||||
return {
|
||||
command: process.execPath,
|
||||
args: [...process.execArgv, srcEntrypoint, ...args]
|
||||
args: [entrypoint, ...args]
|
||||
};
|
||||
}
|
||||
|
||||
const spawnArgs = isBunRuntime ? [entrypoint, ...args] : [
|
||||
'--no-warnings',
|
||||
'--no-deprecation',
|
||||
entrypoint,
|
||||
...args
|
||||
];
|
||||
|
||||
// Node.js with tsx: preserve execArgv (which includes tsx loader)
|
||||
return {
|
||||
command: process.execPath,
|
||||
args: spawnArgs
|
||||
args: [...process.execArgv, entrypoint, ...args]
|
||||
};
|
||||
}
|
||||
|
||||
@@ -143,9 +95,9 @@ export function spawnHappyCLI(args: string[], options: SpawnOptions = {}): Child
|
||||
|
||||
const { command: spawnCommand, args: spawnArgs } = getHappyCliCommand(args);
|
||||
|
||||
// Sanity check of the entrypoint path exists
|
||||
// Sanity check that the entrypoint path exists
|
||||
if (!isBunCompiled()) {
|
||||
const entrypoint = spawnArgs.find((arg) => arg.endsWith('index.mjs') || arg.endsWith('index.ts'));
|
||||
const entrypoint = spawnArgs.find((arg) => arg.endsWith('index.ts'));
|
||||
if (entrypoint && !existsSync(entrypoint)) {
|
||||
const errorMessage = `Entrypoint ${entrypoint} does not exist`;
|
||||
logger.debug(`[SPAWN HAPI CLI] ${errorMessage}`);
|
||||
|
||||
@@ -1,57 +0,0 @@
|
||||
---
|
||||
name: telegram-optional-config
|
||||
description: Make Telegram optional; unify owner id auth
|
||||
---
|
||||
|
||||
# Plan
|
||||
|
||||
基于你的决策更新计划:绑定流程为“提示 chat id + 重启”,允许列表仅来自 env;统一 `uid` 为 owner id,确保 Web/Telegram 登录语义一致。
|
||||
|
||||
## Requirements
|
||||
- 未配置 Telegram 相关 env 时,服务端不退出,Web/CLI 正常可用。
|
||||
- Telegram bot 仅在配置 `TELEGRAM_BOT_TOKEN` 时启动;`ALLOWED_CHAT_IDS` 仅来自 env。
|
||||
- 绑定流程为:bot 提示 chat id → 用户配置 env → 重启服务。
|
||||
- `uid` 统一为 owner id(accessToken 与 telegram 登录一致)。
|
||||
|
||||
## Scope
|
||||
- In: 配置解析、启动流程、auth 逻辑、owner id 持久化、文档更新。
|
||||
- Out: 自动绑定、DB/动态 allowlist、复杂 UI 设置页。
|
||||
|
||||
## Files and entry points
|
||||
- `server/src/configuration.ts`
|
||||
- `server/src/index.ts`
|
||||
- `server/src/telegram/bot.ts`
|
||||
- `server/src/web/routes/auth.ts`
|
||||
- `server/src/web/jwtSecret.ts`(或新增轻量 owner id 持久化文件)
|
||||
- `README.md`
|
||||
- `server/README.md`
|
||||
|
||||
## Data model / API changes
|
||||
- 增加“owner id”持久化(建议 `dataDir/owner-id.json`),用于统一 auth 的 `uid`。
|
||||
- 不新增 Telegram 绑定 API(按“提示 chat id + 重启”流程)。
|
||||
|
||||
## Action items
|
||||
[ ] 配置层改为 Telegram 可选:`TELEGRAM_BOT_TOKEN`/`ALLOWED_CHAT_IDS` 允许为空;加入 `telegramEnabled`,`allowedChatIds` 为空数组可接受。
|
||||
[ ] 生成并持久化 `ownerId`(数值或 UUID -> 数值映射),`/api/auth` 的 `uid` 始终为 `ownerId`。
|
||||
[ ] 启动逻辑按 `telegramEnabled` 分支:未启用仅启动 Web/Socket/SSE,并打印 Telegram disabled 日志。
|
||||
[ ] Telegram bot 行为:
|
||||
- 已启用但 `ALLOWED_CHAT_IDS` 未配置:仅响应 `/start`,提示当前 chat id 与配置示例;不开放其它命令/通知。
|
||||
- 已启用且 allowlist 配置:按现有流程运行。
|
||||
[ ] `/api/auth` 调整:
|
||||
- accessToken:验证后直接使用 `ownerId`。
|
||||
- telegram:若 Telegram 未启用,返回清晰错误;启用时校验 initData 与 allowlist,但仍签发 `uid = ownerId`。
|
||||
[ ] 文档更新:说明 Telegram 配置可选;新增“获取 chat id 并重启绑定”的指引。
|
||||
|
||||
## Testing and validation
|
||||
- 仅设置 `CLI_API_TOKEN` 启动:服务正常、Web 登录可用、bot 不启动。
|
||||
- 设置 `TELEGRAM_BOT_TOKEN` 且未配 allowlist:`/start` 能提示 chat id,其它命令受限。
|
||||
- 完整配置 `TELEGRAM_BOT_TOKEN` + `ALLOWED_CHAT_IDS`:通知与 Mini App 正常。
|
||||
- `uid` 在两种登录方式下均为 `ownerId`。
|
||||
|
||||
## Risks and edge cases
|
||||
- `ownerId` 生成/持久化失败会导致登录不稳定。
|
||||
- 只靠 env allowlist,运维更新需重启,需在文档强调。
|
||||
- Telegram 未启用但 Web 侧仍可能尝试 Telegram auth(应给清晰错误)。
|
||||
|
||||
## Open questions
|
||||
- None.
|
||||
Reference in New Issue
Block a user