Replace void returns with { success: true } across all API endpoints

- Add successResponseSchema to common.ts for explicit success responses
- Update all auth, me, orgs, and admin procedures to return { success: true }
- Update contract.ts to use successResponseSchema instead of z.void()
- Add ast-grep rule to prevent future z.void() usage in contracts
- Add build:packages script to root package.json
- Fix test file lint errors with eslint-disable comments

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
RevIQ
2026-01-10 16:30:22 +08:00
parent 5e13809c0e
commit 1bf05465c3
31 changed files with 179 additions and 53 deletions

View File

@@ -23,9 +23,9 @@ import {
} from "bun:test";
import { call } from "@orpc/server";
import { router } from "../../router.js";
import { hashPassword } from "../../utils/password.js";
import { hashToken } from "../../utils/crypto.js";
import { COOKIE_NAMES } from "../../utils/cookies.js";
import { hashToken } from "../../utils/crypto.js";
import { hashPassword } from "../../utils/password.js";
import { TEST_RP } from "../helpers/test-constants.js";
import {
createTestDb,
@@ -85,7 +85,7 @@ function createAPIContext(options?: {
* Create a real session in the database and return the token
*/
async function createSession(userId: number): Promise<string> {
const token = "test-session-" + String(Date.now()) + String(Math.random());
const token = `test-session-${String(Date.now())}${String(Math.random())}`;
const tokenHashValue = await hashToken(token);
const expiresAt = new Date(Date.now() + SESSION_EXPIRY_MS);
@@ -110,8 +110,7 @@ async function createSession(userId: number): Promise<string> {
async function createApiToken(
userId: number,
): Promise<{ token: string; name: string }> {
const token =
"test-api-token-" + String(Date.now()) + String(Math.random());
const token = `test-api-token-${String(Date.now())}${String(Math.random())}`;
const tokenHashValue = await hashToken(token);
const expiresAt = new Date(Date.now() + API_TOKEN_EXPIRY_MS);
@@ -523,6 +522,7 @@ describe("me.setPassword", () => {
const sessionToken = await createSession(user.id);
const context = createAPIContext({ sessionToken });
// eslint-disable-next-line @typescript-eslint/await-thenable, @typescript-eslint/no-confusing-void-expression
await expect(
call(
router.me.setPassword,
@@ -544,6 +544,7 @@ describe("me.setPassword", () => {
const sessionToken = await createSession(user.id);
const context = createAPIContext({ sessionToken });
// eslint-disable-next-line @typescript-eslint/await-thenable, @typescript-eslint/no-confusing-void-expression
await expect(
call(
router.me.setPassword,
@@ -567,6 +568,7 @@ describe("me.setPassword", () => {
// Password must be at least 8 chars to pass schema validation
// "password" passes length check but fails zxcvbn strength check
// zxcvbn provides feedback like "This is a top-10 common password"
// eslint-disable-next-line @typescript-eslint/await-thenable, @typescript-eslint/no-confusing-void-expression
await expect(
call(
router.me.setPassword,
@@ -611,6 +613,7 @@ describe("me.delete", () => {
const sessionToken = await createSession(user.id);
const context = createAPIContext({ sessionToken });
// eslint-disable-next-line @typescript-eslint/await-thenable, @typescript-eslint/no-confusing-void-expression
await expect(
call(router.me.delete, { password: "anything" }, { context }),
).rejects.toThrow("Cannot delete account without a password");
@@ -626,6 +629,7 @@ describe("me.delete", () => {
const sessionToken = await createSession(user.id);
const context = createAPIContext({ sessionToken });
// eslint-disable-next-line @typescript-eslint/await-thenable, @typescript-eslint/no-confusing-void-expression
await expect(
call(router.me.delete, { password: "WrongPassword123!" }, { context }),
).rejects.toThrow("Incorrect password");