chore(server): size, strict and warning baselines follow the error-envelope work

This commit is contained in:
Maurice
2026-10-10 16:45:54 +02:00
parent e7c1acfb47
commit e5a2af5999
9 changed files with 34 additions and 26 deletions
+1 -1
View File
@@ -1,7 +1,7 @@
{
"src": {
"@typescript-eslint/no-explicit-any": 90,
"@typescript-eslint/no-non-null-assertion": 297,
"@typescript-eslint/no-non-null-assertion": 265,
"@typescript-eslint/no-require-imports": 18,
"@typescript-eslint/no-unsafe-function-type": 1,
"@typescript-eslint/no-unused-vars": 36,
+4 -4
View File
@@ -7,16 +7,16 @@
"src/db/repositories/Users.repository.ts": 1446,
"src/nest/atlas/atlas-geo.ts": 1005,
"src/nest/atlas/atlas.service.ts": 1182,
"src/nest/auth/auth.service.ts": 1150,
"src/nest/auth/auth.service.ts": 1143,
"src/nest/budget/budget.service.ts": 1702,
"src/nest/collections/collections.service.ts": 1488,
"src/nest/collections/collections.service.ts": 1483,
"src/nest/doc-sync/doc-sync.service.ts": 1060,
"src/nest/doc-sync/providers/synology-drive.client.ts": 1160,
"src/nest/journey/journey-domain.service.ts": 1799,
"src/nest/places/places.service.ts": 1601,
"src/nest/places/places.service.ts": 1598,
"src/nest/plugins/plugin-runtime.service.ts": 1463,
"src/nest/plugins/runtime/plugin-sdk.ts": 1094,
"src/nest/reservations/reservations.service.ts": 1239,
"src/nest/trips/trips.service.ts": 1009,
"src/nest/vacay/vacay.service.ts": 1440
"src/nest/vacay/vacay.service.ts": 1433
}
+2 -5
View File
@@ -58,7 +58,6 @@
"src/mcp/tools.ts": 1,
"src/nest-mcp/registry.ts": 2,
"src/nest/accommodations/accommodations.service.ts": 2,
"src/nest/admin/admin.controller.ts": 1,
"src/nest/atlas/atlas-geo.ts": 2,
"src/nest/auth/auth.service.ts": 1,
"src/nest/budget/budget.service.ts": 2,
@@ -88,8 +87,7 @@
"src/nest/packing/admin-packing-templates.controller.ts": 3,
"src/nest/packing/packing.controller.ts": 1,
"src/nest/packing/packing.dto.ts": 1,
"src/nest/packing/packing.mcp.ts": 1,
"src/nest/places/places.controller.ts": 2,
"src/nest/places/places.controller.ts": 1,
"src/nest/places/places.mcp.ts": 5,
"src/nest/platform/discovery-metadata.service.ts": 3,
"src/nest/plugins/host/plugin-jobs.ts": 1,
@@ -103,7 +101,6 @@
"src/nest/roadtrip/roadtrip-router.service.ts": 12,
"src/nest/settings/settings.service.ts": 1,
"src/nest/storage/drivers/s3.driver.ts": 1,
"src/nest/trips/trips.controller.ts": 2,
"src/nest/trips/trips.mcp.ts": 1,
"src/nest/trips/trips.controller.ts": 1,
"src/nest/trips/trips.service.ts": 1
}
+2 -2
View File
@@ -172,7 +172,7 @@ export class AdminService {
}
const pwCheck = validatePassword(password);
if (!pwCheck.ok) throw new DomainError(400, pwCheck.reason);
if (!pwCheck.ok) throw new DomainError(400, pwCheck.reason ?? '');
if (data.role && !['user', 'admin'].includes(data.role)) {
throw new DomainError(400, 'Invalid role');
@@ -236,7 +236,7 @@ export class AdminService {
if (password) {
const pwCheck = validatePassword(password);
if (!pwCheck.ok) throw new DomainError(400, pwCheck.reason);
if (!pwCheck.ok) throw new DomainError(400, pwCheck.reason ?? '');
}
const passwordHash = password ? bcrypt.hashSync(password, BCRYPT_COST) : null;
+2 -2
View File
@@ -459,7 +459,7 @@ export class AuthService {
}
const pwCheck = validatePassword(password);
if (!pwCheck.ok) throw new DomainError(400, pwCheck.reason);
if (!pwCheck.ok) throw new DomainError(400, pwCheck.reason ?? '');
if (!EMAIL_REGEX.test(email)) {
throw new DomainError(400, 'Invalid email format');
@@ -638,7 +638,7 @@ export class AuthService {
if (!new_password) throw new DomainError(400, 'New password is required');
const pwCheck = validatePassword(new_password);
if (!pwCheck.ok) throw new DomainError(400, pwCheck.reason);
if (!pwCheck.ok) throw new DomainError(400, pwCheck.reason ?? '');
const user = await this.usersRepo.getPasswordHashAndVersion(userId);
if (!user || !bcrypt.compareSync(current_password, user.password_hash)) {
+3 -2
View File
@@ -655,10 +655,11 @@ export class VacayMcp {
text: JSON.stringify(data, null, 2),
}],
});
if (!plan.holidays_enabled || !plan.holidays_region) return json([]);
const region = plan.holidays_region;
if (!plan.holidays_enabled || !region) return json([]);
const yearStr = Array.isArray(year) ? year[0] : year;
// A failed fetch reads as no holidays here, as it always has.
const result = await catchDomainError(() => this.vacay.getHolidays(yearStr, plan.holidays_region));
const result = await catchDomainError(() => this.vacay.getHolidays(yearStr, region));
return json(result instanceof DomainError ? [] : (result.data ?? []));
}
}
@@ -40,8 +40,10 @@ function methodNames(ctor: ClassRef): string[] {
async function toolSchemas(): Promise<Map<string, Record<string, unknown>>> {
const out = new Map<string, Record<string, unknown>>();
for (const file of mcpFiles(NEST_ROOT).sort()) {
const mod = (await import(file)) as Record<string, unknown>;
const files = mcpFiles(NEST_ROOT).sort();
const modules = (await Promise.all(files.map((file) => import(file)))) as Record<string, unknown>[];
for (const [index, mod] of modules.entries()) {
const file = files[index];
for (const exported of Object.values(mod)) {
if (!isMcpController(exported)) continue;
for (const name of methodNames(exported)) {
@@ -182,8 +182,10 @@ describe('stay use cases: the shared gate and checks', () => {
it('ACC-UC-006: an edit or a cancellation of a stay that is not on the trip is a 404', async () => {
const svc = makeService({ broadcast: vi.fn() }, { getAccommodation: vi.fn().mockResolvedValue(undefined) });
for (const run of [() => svc.updateStay(5, 9, {}, writer()), () => svc.deleteStay(5, 9, writer())]) {
const err = (await run().catch((e: unknown) => e)) as DomainError;
const errors = (await Promise.all(
[svc.updateStay(5, 9, {}, writer()), svc.deleteStay(5, 9, writer())].map((p) => p.catch((e: unknown) => e)),
)) as DomainError[];
for (const err of errors) {
expect(err.toBody()).toEqual({ error: 'Accommodation not found' });
expect(err.mcpMessage).toBe('Accommodation not found.');
}
@@ -149,11 +149,14 @@ describe('packing item use cases: refusals', () => {
it("PACK-UC-002: a missing item is REST's 404 and MCP's own sentence, for update and delete", async () => {
const s = setup({ updateItem: vi.fn().mockResolvedValue(null), deleteItem: vi.fn().mockResolvedValue(null) });
for (const call of [
const calls = [
(w: never) => s.writes.updateItem(5, 3, { name: 'x' }, ['name'], w),
(w: never) => s.writes.deleteItem(5, 3, w),
]) {
const err = (await s.run('mcp', call as never).catch((e: unknown) => e)) as DomainError;
];
const errors = (await Promise.all(
calls.map((call) => s.run('mcp', call as never).catch((e: unknown) => e)),
)) as DomainError[];
for (const err of errors) {
expect(err.toBody()).toEqual({ error: 'Item not found' });
expect(mcpText(err)).toBe('Packing item not found.');
}
@@ -164,11 +167,14 @@ describe('packing item use cases: refusals', () => {
createItem: vi.fn().mockResolvedValue({ invalidBag: true }),
updateItem: vi.fn().mockResolvedValue({ invalidBag: true }),
});
for (const call of [
const calls = [
(w: never) => s.writes.createItem(5, { name: 'x', bag_id: 99 }, w),
(w: never) => s.writes.updateItem(5, 3, { bag_id: 99 }, ['bag_id'], w),
]) {
const err = (await s.run('mcp', call as never).catch((e: unknown) => e)) as DomainError;
];
const errors = (await Promise.all(
calls.map((call) => s.run('mcp', call as never).catch((e: unknown) => e)),
)) as DomainError[];
for (const err of errors) {
expect(err.getStatus()).toBe(400);
expect(err.toBody()).toEqual({ error: 'Bag not found' });
expect(mcpText(err)).toBe('Bag not found.');