Files
elizaos--eliza/packages/cloud/api/__tests__/plugin-sql-stub-mirror.test.ts
wehub-resource-sync 426e9eeabd
Voice Workbench / headless workbench (mocked backends) (push) Has been cancelled
Voice Workbench / real acoustic lane (nightly, provisioned only) (push) Has been cancelled
ci / test (push) Has been cancelled
ci / lint-and-format (push) Has been cancelled
ci / build (push) Has been cancelled
ci / dev-startup (push) Has been cancelled
gitleaks / gitleaks (push) Has been cancelled
Markdown Links / Relative Markdown Links (push) Has been cancelled
Quality (Extended) / Homepage Build (PR smoke) (push) Has been cancelled
Quality (Extended) / Comment-only diff guard (push) Has been cancelled
Quality (Extended) / Format + Type Safety Ratchet (push) Has been cancelled
Quality (Extended) / Develop Gate (secret scan + UI determinism) (push) Has been cancelled
Quality (Extended) / Develop Gate (lint) (push) Has been cancelled
Chat shell gestures / Chat shell gesture + parity e2e (push) Has been cancelled
Cloud Gateway Discord / Test (push) Has been cancelled
Benchmark Bridge Tests / benchmark (bunx @biomejs/biome check packages/lifeops-bench/src, benchmark-lint) (push) Has been cancelled
Benchmark Bridge Tests / benchmark (bunx vitest run --config packages/lifeops-bench/vitest.config.ts --root packages/lifeops-bench --passWithNoTests, benchmark-tests) (push) Has been cancelled
Build Agent Image / build-and-push (push) Has been cancelled
Dev Smoke / bun run dev onboarding chat (push) Has been cancelled
Dev Smoke / Vite HMR dependency-level smoke (push) Has been cancelled
Electrobun Submodule Guard / electrobun gitlink is fetchable (push) Has been cancelled
Publish @elizaos/example-code / check_npm (push) Has been cancelled
Publish @elizaos/example-code / publish_npm (push) Has been cancelled
Publish @elizaos/plugin-elizacloud / verify_version (push) Has been cancelled
Publish @elizaos/plugin-elizacloud / publish_npm (push) Has been cancelled
Sandbox Live Smoke / Sandbox live smoke (push) Has been cancelled
Snap Build & Test / Build Snap (amd64) (push) Has been cancelled
Snap Build & Test / Build Snap (arm64) (push) Has been cancelled
Test Packaging / elizaos CLI global-install smoke (node + bun) (push) Has been cancelled
Cloud Gateway Webhook / Test (push) Has been cancelled
Cloud Tests / lint-and-types (push) Has been cancelled
Cloud Tests / unit-tests (push) Has been cancelled
Cloud Tests / integration-tests (push) Has been cancelled
Cloud Tests / e2e-tests (push) Has been cancelled
CodeQL Advanced / Analyze (javascript-typescript) (push) Has been cancelled
Deploy Apps Worker (Product 2) / Determine environment (push) Has been cancelled
Deploy Apps Worker (Product 2) / Deploy apps worker to apps-control host (${{ needs.determine-env.outputs.environment }}) (push) Has been cancelled
Deploy Eliza Provisioning Worker / Determine environment (push) Has been cancelled
Deploy Eliza Provisioning Worker / Deploy worker to Hetzner host (${{ needs.determine-env.outputs.environment }} @ ${{ needs.determine-env.outputs.deployment_sha }}) (push) Has been cancelled
Dev Smoke / Classify changed paths (push) Has been cancelled
supply-chain / sbom (push) Has been cancelled
supply-chain / vulnerability-scan (push) Has been cancelled
Build, Push & Deploy to Phala Cloud / build-and-push (push) Has been cancelled
Test Packaging / Validate Packaging Configs (push) Has been cancelled
Test Packaging / Build & Test PyPI Package (push) Has been cancelled
Test Packaging / PyPI on Python ${{ matrix.python }} (push) Has been cancelled
Test Packaging / Pack & Test JS Tarballs (push) Has been cancelled
UI Fixture E2E / ui-fixture-e2e (push) Has been cancelled
UI Fixture E2E / fixture-e2e (push) Has been cancelled
UI Story Gate / story-gate (push) Has been cancelled
vault-ci / test (macos-latest) (push) Has been cancelled
vault-ci / test (ubuntu-latest) (push) Has been cancelled
vault-ci / test (windows-latest) (push) Has been cancelled
vault-ci / app-core wiring tests (push) Has been cancelled
verify-patches / verify patches/CHECKSUMS.sha256 (push) Has been cancelled
Voice Benchmark Smoke / voice-emotion fixture smoke (push) Has been cancelled
Voice Benchmark Smoke / voiceagentbench fixture smoke (push) Has been cancelled
Voice Benchmark Smoke / voicebench-quality unit smoke (push) Has been cancelled
Voice Benchmark Smoke / voicebench TypeScript unit (no audio) (push) Has been cancelled
Voice Benchmark Smoke / voice bench smoke summary (push) Has been cancelled
Windows CI / windows ([bun run --cwd packages/app-core test bun run --cwd packages/elizaos test bun run --cwd packages/cloud/shared test], app-and-cli) (push) Has been cancelled
Windows CI / windows ([bun run --cwd packages/scenario-runner test bun run --cwd packages/vault test bun run --cwd packages/security test bun run --cwd plugins/plugin-coding-tools test], framework-packages) (push) Has been cancelled
Windows CI / windows ([bun run --cwd plugins/plugin-elizacloud test bun run --cwd plugins/plugin-discord test bun run --cwd plugins/plugin-anthropic test bun run --cwd plugins/plugin-openai test bun run --cwd plugins/plugin-app-control test bun run --cwd plugins/pl… (push) Has been cancelled
Windows CI / windows ([node packages/scripts/run-turbo.mjs run build --filter=@elizaos/core --filter=@elizaos/shared --filter=@elizaos/agent --concurrency=4 node packages/scripts/run-bash-linux-only.mjs scripts/verify-riscv64-buildpaths.sh node packages/scripts/run… (push) Has been cancelled
Windows CI / windows ([node packages/scripts/run-turbo.mjs run typecheck --filter=@elizaos/core --filter=@elizaos/shared --filter=@elizaos/cloud-shared --concurrency=4 bun run --cwd packages/core test bun run --cwd packages/shared test], core-runtime, 75) (push) Has been cancelled
chore: import upstream snapshot with attribution
2026-07-13 12:43:05 +08:00

142 lines
5.4 KiB
TypeScript

/**
* Guards the Worker plugin-sql stub against schema drift (#13406). The
* wrangler alias swaps @elizaos/plugin-sql for src/stubs/elizaos-plugin-sql.ts
* at bundle time, so cloud-shared repositories typecheck against the REAL
* schema but execute against the STUB — a drifted stub column (42703), a
* wrong/phantom table name (42P01), or a column the stub simply lacks
* (undefined drizzle ref) all surface only in the deployed Worker as 500s on
* console page loads. Three mechanical invariants close that gap:
* 1. every stub table exists upstream under the same export name,
* 2. same SQL table name, stub columns ⊆ upstream columns (renames fail),
* 3. every `<x>Table.<column>` property that cloud Worker source actually
* dereferences exists on the stub table (partial-stub gaps fail).
*/
import { describe, expect, test } from "bun:test";
import { readdirSync, readFileSync, statSync } from "node:fs";
import { join, resolve } from "node:path";
import { getTableColumns, getTableName, is } from "drizzle-orm";
import { PgTable } from "drizzle-orm/pg-core";
import * as realSchema from "../../../../plugins/plugin-sql/src/schema/index";
import * as stubSchema from "../src/stubs/elizaos-plugin-sql";
function isPgTable(value: unknown): value is PgTable {
return is(value, PgTable);
}
function tableExports(mod: Record<string, unknown>): Map<string, PgTable> {
const tables = new Map<string, PgTable>();
for (const [name, value] of Object.entries(mod)) {
if (name.endsWith("Table") && isPgTable(value)) {
tables.set(name, value);
}
}
return tables;
}
const stubTables = tableExports(stubSchema as Record<string, unknown>);
const realTables = tableExports(realSchema as Record<string, unknown>);
describe("plugin-sql Worker stub mirrors the real schema", () => {
test("stub exports at least the tables cloud-shared destructures", () => {
expect(stubTables.size).toBeGreaterThan(0);
});
for (const [exportName, stubTable] of stubTables) {
test(`${exportName}: same table name and no drifted columns`, () => {
const realTable = realTables.get(exportName);
expect(
realTable,
`stub exports ${exportName} but plugins/plugin-sql/src/schema does not — phantom table`,
).toBeDefined();
if (!realTable) return;
expect(getTableName(stubTable)).toBe(getTableName(realTable));
// Compare property-key → SQL-name pairs: a stale SQL name is the #13495
// 42703 class, and a mismatched property key means real-schema-typechecked
// repo code dereferences `undefined` in the Worker bundle.
const realColumns = getTableColumns(realTable);
for (const [key, column] of Object.entries(getTableColumns(stubTable))) {
const realColumn = realColumns[key];
expect(
realColumn,
`${exportName}.${key} is not a column of the real ${getTableName(realTable)} table — renamed or removed upstream (the #13495 drift class)`,
).toBeDefined();
expect(
realColumn?.name,
`${exportName}.${key} maps to "${column.name}" in the stub but "${realColumn?.name}" upstream`,
).toBe(column.name);
}
});
}
test("every eliza-table column referenced by Worker source exists on the stub", () => {
// Walk the source that ends up in the Worker bundle: cloud-shared src and
// this package's route tree + src (minus the stubs themselves and tests).
const apiRoot = resolve(import.meta.dir, "..");
const roots = [resolve(apiRoot, "../shared/src"), apiRoot];
const skipDirs = new Set([
"node_modules",
"__tests__",
"test",
"stubs",
"migrations",
"dist",
".turbo",
".wrangler",
]);
const files: string[] = [];
const walk = (dir: string): void => {
for (const entry of readdirSync(dir)) {
if (skipDirs.has(entry)) continue;
const full = join(dir, entry);
if (statSync(full).isDirectory()) {
walk(full);
} else if (
entry.endsWith(".ts") &&
!entry.endsWith(".test.ts") &&
!entry.endsWith(".d.ts")
) {
files.push(full);
}
}
};
for (const root of roots) walk(root);
expect(files.length).toBeGreaterThan(0);
const columnKeysByTable = new Map<string, Set<string>>();
for (const [exportName, table] of stubTables) {
columnKeysByTable.set(
exportName,
new Set(Object.keys(getTableColumns(table))),
);
}
const missing: string[] = [];
const reference = /\b(\w+Table)\.(\w+)\b/g;
for (const file of files) {
const source = readFileSync(file, "utf8");
for (const match of source.matchAll(reference)) {
const [, tableName, property] = match;
const columns = columnKeysByTable.get(tableName);
// Only tables the stub stands in for; other *Table identifiers are
// unrelated (cloud-only tables, local variables).
if (!columns) continue;
// Non-column drizzle surface (e.g. `_`, `enableRLS`) never appears in
// repo query code for these tables; a miss here means the stub lacks
// a column the bundled Worker will dereference as `undefined`.
if (!columns.has(property)) {
missing.push(`${tableName}.${property} (${file})`);
}
}
}
expect(
missing,
`Worker source dereferences eliza-table columns the stub does not declare:\n${missing.join("\n")}`,
).toEqual([]);
});
});