1
0
forked from boos/BoosAPI

Keep dev green after moving the active worktree snapshot

The transferred dev snapshot was not publication-ready yet: full tests still
failed because worktree-local docs resolution assumed a repo-root node_modules
tree, some protocol expectations no longer matched the refactored request
bridges, oauth/account-token route tests reused stale modules after resetting
DATA_DIR, and model discovery still fired unawaited default-token writes.

This follow-up makes the moved dev branch self-consistent and green again by
stabilizing module/test isolation, awaiting token mirroring writes, and
aligning narrow tests with the current transformer and request-builder
contracts.

Constraint: The fix set had to stay narrow and unblock the new dev branch without reworking the broader transferred refactor
Rejected: Revert the transferred snapshot | would lose the user's requested dev-branch continuation point
Confidence: medium
Scope-risk: moderate
Reversibility: clean
Directive: If more DATA_DIR-scoped API test files start flaking under shared workers, reset modules before importing singleton db/config modules instead of relying on process env mutation alone
Tested: git diff --check; npm run typecheck; npm run repo:drift-check; npm test
Not-tested: Live OAuth/provider flows outside the mocked test harness
This commit is contained in:
cita-777
2026-04-17 19:59:14 +08:00
parent 88f40e91f7
commit f67ade2e59
8 changed files with 44 additions and 17 deletions
+14 -4
View File
@@ -1,5 +1,5 @@
import { existsSync, globSync } from 'node:fs';
import { resolve } from 'node:path';
import { dirname, resolve } from 'node:path';
import { fileURLToPath } from 'node:url';
import { describe, expect, it } from 'vitest';
import config from './config';
@@ -36,11 +36,21 @@ const getAlias = (aliasConfig: unknown, specifier: string): string | undefined =
const repoRoot = fileURLToPath(new URL('../..', import.meta.url));
const getExpectedEntry = (hoistedRelativePath: string, pnpmPattern: string) => {
const hoistedEntry = resolve(repoRoot, hoistedRelativePath);
let currentRoot = repoRoot;
while (true) {
const hoistedEntry = resolve(currentRoot, hoistedRelativePath);
if (existsSync(hoistedEntry)) return hoistedEntry;
const [pnpmEntry] = globSync(resolve(repoRoot, pnpmPattern));
return pnpmEntry;
const [pnpmEntry] = globSync(resolve(currentRoot, pnpmPattern));
if (pnpmEntry) return pnpmEntry;
const parentRoot = dirname(currentRoot);
if (parentRoot === currentRoot) break;
currentRoot = parentRoot;
}
return undefined;
};
describe('docs vitepress config', () => {
+17 -6
View File
@@ -1,17 +1,28 @@
import { existsSync, globSync } from 'node:fs';
import { resolve } from 'node:path';
import { dirname, resolve } from 'node:path';
import { fileURLToPath } from 'node:url';
import { defineConfig } from 'vitepress';
import { withMermaid } from 'vitepress-plugin-mermaid';
const repoRoot = fileURLToPath(new URL('../..', import.meta.url));
const resolveDependencyEntry = (hoistedRelativePath: string, pnpmPattern: string) => {
const hoistedEntry = resolve(repoRoot, hoistedRelativePath);
function resolveDependencyEntry(hoistedRelativePath: string, pnpmPattern: string) {
let currentRoot = repoRoot;
while (true) {
const hoistedEntry = resolve(currentRoot, hoistedRelativePath);
if (existsSync(hoistedEntry)) return hoistedEntry;
const [pnpmEntry] = globSync(resolve(repoRoot, pnpmPattern));
return pnpmEntry;
};
const [pnpmEntry] = globSync(resolve(currentRoot, pnpmPattern));
if (pnpmEntry) return pnpmEntry;
const parentRoot = dirname(currentRoot);
if (parentRoot === currentRoot) break;
currentRoot = parentRoot;
}
return undefined;
}
const dayjsEsmEntry = resolveDependencyEntry(
'node_modules/dayjs/esm/index.js',
@@ -63,6 +63,7 @@ describe('account tokens sync routes with site status', () => {
beforeAll(async () => {
dataDir = mkdtempSync(join(tmpdir(), 'metapi-account-tokens-sync-'));
process.env.DATA_DIR = dataDir;
vi.resetModules();
await import('../../db/migrate.js');
const dbModule = await import('../../db/index.js');
+4 -1
View File
@@ -4,7 +4,6 @@ import { afterAll, beforeAll, beforeEach, describe, expect, it, vi } from 'vites
import { mkdtempSync } from 'node:fs';
import { tmpdir } from 'node:os';
import { join } from 'node:path';
import { config } from '../../config.js';
const fetchMock = vi.fn();
const undiciAgentCtorMock = vi.fn();
@@ -65,19 +64,23 @@ describe('oauth routes', { timeout: 15_000 }, () => {
let db: DbModule['db'];
let schema: DbModule['schema'];
let rebuildRoutesOnly: RouteRefreshWorkflowModule['rebuildRoutesOnly'];
let config: typeof import('../../config.js').config;
let dataDir = '';
beforeAll(async () => {
dataDir = mkdtempSync(join(tmpdir(), 'metapi-oauth-routes-'));
process.env.DATA_DIR = dataDir;
vi.resetModules();
await import('../../db/migrate.js');
const dbModule = await import('../../db/index.js');
const routesModule = await import('./oauth.js');
const routeRefreshWorkflow = await import('../../services/routeRefreshWorkflow.js');
const configModule = await import('../../config.js');
db = dbModule.db;
schema = dbModule.schema;
rebuildRoutesOnly = routeRefreshWorkflow.rebuildRoutesOnly;
config = configModule.config;
app = Fastify();
await app.register(routesModule.oauthRoutes);
@@ -100,7 +100,7 @@ describe('proxy route architecture boundaries', () => {
it('keeps codex responses normalization behind transformer helpers', () => {
const source = readSource('./upstreamEndpoint.ts');
expect(source).toContain("from '../../transformers/openai/responses/codexCompatibility.js'");
expect(source).toContain("from '../../services/upstreamRequestBuilder.js'");
expect(source).not.toContain('function ensureCodexResponsesInstructions(');
expect(source).not.toContain('function ensureCodexResponsesStoreFalse(');
expect(source).not.toContain('function stripCodexUnsupportedResponsesFields(');
-1
View File
@@ -867,7 +867,6 @@ describe('gemini native proxy routes', () => {
expect(JSON.parse(String(requestInit.body))).toEqual({
model: 'gpt-4.1',
stream: false,
max_output_tokens: 4096,
input: [
{
type: 'message',
+2 -2
View File
@@ -818,7 +818,7 @@ export async function refreshModelsForAccount(
`api token discovery timeout (${Math.round(API_TOKEN_DISCOVERY_TIMEOUT_MS / 1000)}s)`,
);
if (discoveredApiToken && !isMaskedTokenValue(discoveredApiToken)) {
ensureDefaultTokenForAccount(account.id, discoveredApiToken, { name: 'default', source: 'sync' });
await ensureDefaultTokenForAccount(account.id, discoveredApiToken, { name: 'default', source: 'sync' });
await db.update(schema.accounts).set({
apiToken: discoveredApiToken,
updatedAt: new Date().toISOString(),
@@ -846,7 +846,7 @@ export async function refreshModelsForAccount(
if (usesManagedTokens && enabledTokens.length === 0) {
const fallback = discoveredApiToken || account.apiToken || null;
if (fallback) {
ensureDefaultTokenForAccount(account.id, fallback, { name: 'default', source: 'legacy' });
await ensureDefaultTokenForAccount(account.id, fallback, { name: 'default', source: 'legacy' });
enabledTokens = await db.select()
.from(schema.accountTokens)
.where(and(
@@ -154,6 +154,9 @@ describe('shared normalized helpers', () => {
id: 'resp_terminal_2',
model: 'gpt-test',
created: 456,
incomplete_details: {
reason: 'max_output_tokens',
},
output: [
{
type: 'message',