mirror of
https://github.com/mauriceboe/TREK.git
synced 2026-10-18 21:16:47 +00:00
Give day notes a domain of their own
days/ carried two fachlichkeiten with a full file set each: days.controller, days.service, days.mcp, days.rpc, days.dto next to the five day-notes ones. The note files move out unchanged; because the new directory sits at the same depth, not one import path inside them changed. The two modules deliberately do not reference each other in either direction: dayExists is raw SQL on the days table in the note service, and DaysService reads day_notes the same way, so a module edge would buy nothing and cost a cycle. DayNotesModule has to be registered in PluginsRuntimeModule as well as AppModule - DayNotesRpc owns four of the 113 wire methods and the registry boots with requireTotalCoverage, so leaving it out would stop every test app that assembles the plugin runtime. The days e2e container assembles both modules now: the note routes still nest under the days prefix, and a container that builds only DaysModule would 404 on them while production served them fine.
This commit is contained in:
@@ -60,7 +60,7 @@ export function registerResources(server: McpServer, userId: number, scopes: str
|
||||
// src/nest/reservations/reservations.mcp.ts (@ResourceTemplate).
|
||||
|
||||
// The day-notes resource moved to the DI-discovered
|
||||
// src/nest/days/day-notes.mcp.ts (@ResourceTemplate).
|
||||
// src/nest/day-notes/day-notes.mcp.ts (@ResourceTemplate).
|
||||
|
||||
// The trip-accommodations resource moved to the DI-discovered
|
||||
// src/nest/days/days.mcp.ts (@ResourceTemplate).
|
||||
|
||||
@@ -21,6 +21,7 @@ import { PackingModule } from './packing/packing.module';
|
||||
import { BudgetModule } from './budget/budget.module';
|
||||
import { ReservationsModule } from './reservations/reservations.module';
|
||||
import { DaysModule } from './days/days.module';
|
||||
import { DayNotesModule } from './day-notes/day-notes.module';
|
||||
import { AssignmentsModule } from './assignments/assignments.module';
|
||||
import { PlacesModule } from './places/places.module';
|
||||
import { TripsModule } from './trips/trips.module';
|
||||
@@ -60,7 +61,7 @@ import { IdempotencyInterceptor } from './common/idempotency.interceptor';
|
||||
* migrated.
|
||||
*/
|
||||
@Module({
|
||||
imports: [AppConfigModule, DatabaseModule, RealtimeModule, McpModule.forRoot({ accessPolicy: trekMcpAccessPolicy, validateAccess: trekMcpValidateAccess }), HealthModule, WeatherModule, HelpModule, AirportsModule, ConfigModule, SystemNoticesModule, MapsModule, PlaceEnrichmentModule, CategoriesModule, TagsModule, NotificationsModule, AtlasModule, VacayModule, PackingModule, TodoModule, BudgetModule, ReservationsModule, DaysModule, AssignmentsModule, PlacesModule, TripsModule, CollabModule, FilesModule, PhotosModule, MemoriesModule, AirtrailModule, JourneyModule, CollectionsModule, ShareModule, TripInviteModule, TransitModule, FeedsModule, SettingsModule, BackupModule, AuthModule, OidcModule, OauthModule, AdminModule, AddonsModule, AuditModule, PermissionsModule, PluginsModule, BookingImportModule, LlmParseModule],
|
||||
imports: [AppConfigModule, DatabaseModule, RealtimeModule, McpModule.forRoot({ accessPolicy: trekMcpAccessPolicy, validateAccess: trekMcpValidateAccess }), HealthModule, WeatherModule, HelpModule, AirportsModule, ConfigModule, SystemNoticesModule, MapsModule, PlaceEnrichmentModule, CategoriesModule, TagsModule, NotificationsModule, AtlasModule, VacayModule, PackingModule, TodoModule, BudgetModule, ReservationsModule, DaysModule, DayNotesModule, AssignmentsModule, PlacesModule, TripsModule, CollabModule, FilesModule, PhotosModule, MemoriesModule, AirtrailModule, JourneyModule, CollectionsModule, ShareModule, TripInviteModule, TransitModule, FeedsModule, SettingsModule, BackupModule, AuthModule, OidcModule, OauthModule, AdminModule, AddonsModule, AuditModule, PermissionsModule, PluginsModule, BookingImportModule, LlmParseModule],
|
||||
providers: [
|
||||
// Global error-envelope normaliser (DI-registered so it also catches
|
||||
// framework-level exceptions like the not-found handler).
|
||||
|
||||
@@ -0,0 +1,28 @@
|
||||
import { Module } from '@nestjs/common';
|
||||
import { DayNotesController } from './day-notes.controller';
|
||||
import { DayNotesService } from './day-notes.service';
|
||||
import { DayNotesMcp } from './day-notes.mcp';
|
||||
import { DayNotesRpc } from './day-notes.rpc';
|
||||
import { PermissionsModule } from '../permissions/permissions.module';
|
||||
import { AuthModule } from '../auth/auth.module';
|
||||
import { RealtimeModule } from '../realtime/realtime.module';
|
||||
import { PluginGuardsModule } from '../plugins/host/plugin-guards.module';
|
||||
|
||||
/**
|
||||
* Day notes. Its own domain rather than a second file set inside days/, which
|
||||
* carried two fachlichkeiten with a full controller/service/mcp/rpc/dto each.
|
||||
*
|
||||
* Deliberately unconnected to DaysModule in both directions: `dayExists` is raw
|
||||
* SQL on `days` here, and DaysService reads `day_notes` the same way. Wiring the
|
||||
* modules to each other would buy nothing and cost a cycle.
|
||||
*
|
||||
* AuthModule is only for DayNotesMcp's demo-user gate, PluginGuardsModule only
|
||||
* for DayNotesRpc.
|
||||
*/
|
||||
@Module({
|
||||
imports: [PermissionsModule, AuthModule, RealtimeModule, PluginGuardsModule],
|
||||
controllers: [DayNotesController],
|
||||
providers: [DayNotesService, DayNotesMcp, DayNotesRpc],
|
||||
exports: [DayNotesService],
|
||||
})
|
||||
export class DayNotesModule {}
|
||||
@@ -2,32 +2,28 @@ import { Module } from '@nestjs/common';
|
||||
import { DaysController } from './days.controller';
|
||||
import { DaysService } from './days.service';
|
||||
import { DaysMcp } from './days.mcp';
|
||||
import { DayNotesController } from './day-notes.controller';
|
||||
import { DayNotesService } from './day-notes.service';
|
||||
import { DayNotesRpc } from './day-notes.rpc';
|
||||
import { DaysRpc } from './days.rpc';
|
||||
import { AccommodationsRpc } from './accommodations.rpc';
|
||||
import { PluginGuardsModule } from '../plugins/host/plugin-guards.module';
|
||||
import { RealtimeModule } from '../realtime/realtime.module';
|
||||
import { DayNotesMcp } from './day-notes.mcp';
|
||||
import { PermissionsModule } from '../permissions/permissions.module';
|
||||
import { QueryHelpersModule } from '../query-helpers/query-helpers.module';
|
||||
import { PlacesModule } from '../places/places.module';
|
||||
import { AuthModule } from '../auth/auth.module';
|
||||
|
||||
/**
|
||||
* Days + day-notes domain (S6 — Phase 2 trip sub-domain). The single prefix
|
||||
* /api/trips/:tripId/days covers both the days mount and the nested
|
||||
* /days/:dayId/notes mount. DaysMcp/DayNotesMcp carry the
|
||||
* decorator-registered MCP tools + resources. DaysService and DayNotesService
|
||||
* are exported for in-container consumers (DaysRpc, DayNotesRpc,
|
||||
* AccommodationsService, TripsService, the assignments/reservations MCP
|
||||
* controllers).
|
||||
* Days (S6 — Phase 2 trip sub-domain), mounted at /api/trips/:tripId/days.
|
||||
* DaysMcp carries the decorator-registered MCP tools + resources. DaysService is
|
||||
* exported for in-container consumers (DaysRpc, AccommodationsService,
|
||||
* TripsService, the assignments/reservations MCP controllers).
|
||||
*
|
||||
* Day notes used to live here too, with their own full file set; they are their
|
||||
* own domain now (day-notes/).
|
||||
*/
|
||||
@Module({
|
||||
imports: [PermissionsModule, QueryHelpersModule, PlacesModule, AuthModule, RealtimeModule, PluginGuardsModule],
|
||||
controllers: [DaysController, DayNotesController],
|
||||
providers: [DaysService, DaysMcp, DayNotesService, DayNotesMcp, DayNotesRpc, DaysRpc, AccommodationsRpc],
|
||||
exports: [DaysService, DayNotesService],
|
||||
controllers: [DaysController],
|
||||
providers: [DaysService, DaysMcp, DaysRpc, AccommodationsRpc],
|
||||
exports: [DaysService],
|
||||
})
|
||||
export class DaysModule {}
|
||||
|
||||
@@ -20,6 +20,7 @@ import { ReservationsModule } from '../reservations/reservations.module';
|
||||
import { TodoModule } from '../todo/todo.module';
|
||||
import { PackingModule } from '../packing/packing.module';
|
||||
import { DaysModule } from '../days/days.module';
|
||||
import { DayNotesModule } from '../day-notes/day-notes.module';
|
||||
import { AssignmentsModule } from '../assignments/assignments.module';
|
||||
import { LlmParseModule } from '../llm-parse/llm-parse.module';
|
||||
import { FilesModule } from '../files/files.module';
|
||||
@@ -61,7 +62,7 @@ import { JourneyDomainModule } from '../journey/journey-domain.module';
|
||||
PluginGuardsModule,
|
||||
PluginOAuthModule,
|
||||
WeatherModule, TagsModule, CategoriesModule, BudgetModule, ReservationsModule,
|
||||
TodoModule, PackingModule, DaysModule, AssignmentsModule, LlmParseModule,
|
||||
TodoModule, PackingModule, DaysModule, DayNotesModule, AssignmentsModule, LlmParseModule,
|
||||
FilesModule, CollabModule, VacayModule, TripsModule, PlacesModule,
|
||||
PermissionsModule, AuditModule, AddonsModule, CollectionsModule, AtlasModule,
|
||||
NotificationsModule, TripMembershipModule, JourneyDomainModule,
|
||||
|
||||
@@ -81,6 +81,10 @@ import { PermissionsService } from '../../src/nest/permissions/permissions.servi
|
||||
let checkPermission: MockInstance;
|
||||
|
||||
import { DaysModule } from '../../src/nest/days/days.module';
|
||||
// The note routes nest under the days prefix but live in their own domain now;
|
||||
// this container has to assemble both or /days/:dayId/notes 404s here while
|
||||
// working in production.
|
||||
import { DayNotesModule } from '../../src/nest/day-notes/day-notes.module';
|
||||
import { TrekExceptionFilter } from '../../src/nest/common/trek-exception.filter';
|
||||
import { ZodValidationPipe } from '../../src/nest/common/zod-validation.pipe';
|
||||
|
||||
@@ -89,7 +93,7 @@ describe('Days + day-notes e2e (real auth guard + temp SQLite, real day SQL)', (
|
||||
let app: Awaited<ReturnType<typeof build>>;
|
||||
|
||||
async function build() {
|
||||
const moduleRef = await Test.createTestingModule({ imports: [DatabaseModule, RealtimeModule, DaysModule] }).compile();
|
||||
const moduleRef = await Test.createTestingModule({ imports: [DatabaseModule, RealtimeModule, DaysModule, DayNotesModule] }).compile();
|
||||
const nest = moduleRef.createNestApplication();
|
||||
nest.use(cookieParser());
|
||||
nest.useGlobalPipes(new ZodValidationPipe());
|
||||
|
||||
@@ -16,8 +16,8 @@ import { CollabService } from '../../src/nest/collab/collab.service';
|
||||
import { CollectionsMcp } from '../../src/nest/collections/collections.mcp';
|
||||
import { CollectionsService } from '../../src/nest/collections/collections.service';
|
||||
import { DatabaseService } from '../../src/nest/database/database.service';
|
||||
import { DayNotesMcp } from '../../src/nest/days/day-notes.mcp';
|
||||
import { DayNotesService } from '../../src/nest/days/day-notes.service';
|
||||
import { DayNotesMcp } from '../../src/nest/day-notes/day-notes.mcp';
|
||||
import { DayNotesService } from '../../src/nest/day-notes/day-notes.service';
|
||||
import { DaysMcp } from '../../src/nest/days/days.mcp';
|
||||
import { DaysService } from '../../src/nest/days/days.service';
|
||||
import { MapsMcp } from '../../src/nest/maps/maps.mcp';
|
||||
|
||||
@@ -18,7 +18,7 @@ import { TagsService } from '../../src/nest/tags/tags.service';
|
||||
import { CategoriesService } from '../../src/nest/categories/categories.service';
|
||||
import { TodoService } from '../../src/nest/todo/todo.service';
|
||||
import { PackingService } from '../../src/nest/packing/packing.service';
|
||||
import { DayNotesService } from '../../src/nest/days/day-notes.service';
|
||||
import { DayNotesService } from '../../src/nest/day-notes/day-notes.service';
|
||||
import { DaysService } from '../../src/nest/days/days.service';
|
||||
import { AssignmentsService } from '../../src/nest/assignments/assignments.service';
|
||||
import { LlmConfigResolver } from '../../src/nest/llm-parse/llm-config.resolver';
|
||||
@@ -44,7 +44,7 @@ import { WeatherRpc } from '../../src/nest/weather/weather.rpc';
|
||||
import { WeatherService } from '../../src/nest/weather/weather.service';
|
||||
import { ExchangeRatesRpc } from '../../src/nest/budget/exchange-rates.rpc';
|
||||
import { TodoRpc } from '../../src/nest/todo/todo.rpc';
|
||||
import { DayNotesRpc } from '../../src/nest/days/day-notes.rpc';
|
||||
import { DayNotesRpc } from '../../src/nest/day-notes/day-notes.rpc';
|
||||
import { PackingRpc } from '../../src/nest/packing/packing.rpc';
|
||||
import { FilesRpc } from '../../src/nest/files/files.rpc';
|
||||
import { PlacesRpc } from '../../src/nest/places/places.rpc';
|
||||
|
||||
@@ -5,7 +5,7 @@ import { CategoriesRpc } from '../../src/nest/categories/categories.rpc';
|
||||
import { WeatherRpc } from '../../src/nest/weather/weather.rpc';
|
||||
import { ExchangeRatesRpc } from '../../src/nest/budget/exchange-rates.rpc';
|
||||
import { TodoRpc } from '../../src/nest/todo/todo.rpc';
|
||||
import { DayNotesRpc } from '../../src/nest/days/day-notes.rpc';
|
||||
import { DayNotesRpc } from '../../src/nest/day-notes/day-notes.rpc';
|
||||
import { PackingRpc } from '../../src/nest/packing/packing.rpc';
|
||||
import { FilesRpc } from '../../src/nest/files/files.rpc';
|
||||
import { PlacesRpc } from '../../src/nest/places/places.rpc';
|
||||
|
||||
@@ -9,9 +9,9 @@ import { expectRegisteredProvider } from '../../helpers/module-providers';
|
||||
import { PluginRpcHost } from '../../../src/nest/plugins/host/rpc-host';
|
||||
import { createTestPluginRegistry } from '../../../src/nest/plugins/host/rpc-kit/testing';
|
||||
import { PluginGuards } from '../../../src/nest/plugins/host/plugin-guards.service';
|
||||
import { DayNotesRpc } from '../../../src/nest/days/day-notes.rpc';
|
||||
import { DaysModule } from '../../../src/nest/days/days.module';
|
||||
import type { DayNotesService } from '../../../src/nest/days/day-notes.service';
|
||||
import { DayNotesRpc } from '../../../src/nest/day-notes/day-notes.rpc';
|
||||
import { DayNotesModule } from '../../../src/nest/day-notes/day-notes.module';
|
||||
import type { DayNotesService } from '../../../src/nest/day-notes/day-notes.service';
|
||||
import type { RealtimeService } from '../../../src/nest/realtime/realtime.service';
|
||||
import type { DatabaseService } from '../../../src/nest/database/database.service';
|
||||
import type { PermissionsService } from '../../../src/nest/permissions/permissions.service';
|
||||
@@ -115,6 +115,6 @@ describe('DayNotesRpc through the router', () => {
|
||||
});
|
||||
|
||||
it('DAYNOTES-RPC-009 the class is listed in its module providers', () => {
|
||||
expectRegisteredProvider(DaysModule, DayNotesRpc);
|
||||
expectRegisteredProvider(DayNotesModule, DayNotesRpc);
|
||||
});
|
||||
});
|
||||
|
||||
@@ -48,7 +48,7 @@ import { resetTestDb } from '../../helpers/test-db';
|
||||
import { createUser, createTrip, createDay, addTripMember } from '../../helpers/factories';
|
||||
import { DatabaseService } from '../../../src/nest/database/database.service';
|
||||
import { PermissionsService } from '../../../src/nest/permissions/permissions.service';
|
||||
import { DayNotesService } from '../../../src/nest/days/day-notes.service';
|
||||
import { DayNotesService } from '../../../src/nest/day-notes/day-notes.service';
|
||||
import type { DayNote } from '../../../src/types';
|
||||
import { RealtimeService } from '../../../src/nest/realtime/realtime.service';
|
||||
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
import { describe, it, expect, vi } from 'vitest';
|
||||
import { HttpException } from '@nestjs/common';
|
||||
import { DaysController } from '../../../src/nest/days/days.controller';
|
||||
import { DayNotesController } from '../../../src/nest/days/day-notes.controller';
|
||||
import { DayNoteCreateDto, DayNoteUpdateDto } from '../../../src/nest/days/day-notes.dto';
|
||||
import { DayNotesController } from '../../../src/nest/day-notes/day-notes.controller';
|
||||
import { DayNoteCreateDto, DayNoteUpdateDto } from '../../../src/nest/day-notes/day-notes.dto';
|
||||
import { DayReorderError } from '../../../src/nest/days/days.service';
|
||||
import type { DaysService } from '../../../src/nest/days/days.service';
|
||||
import type { DayNotesService } from '../../../src/nest/days/day-notes.service';
|
||||
import type { DayNotesService } from '../../../src/nest/day-notes/day-notes.service';
|
||||
import type { User } from '../../../src/types';
|
||||
|
||||
const user = { id: 1, role: 'user', email: 'u@example.test' } as User;
|
||||
|
||||
@@ -13,7 +13,7 @@ import { PluginRpcHost } from '../../../src/nest/plugins/host/rpc-host';
|
||||
import { createTestPluginRegistry } from '../../../src/nest/plugins/host/rpc-kit/testing';
|
||||
import { PluginGuards } from '../../../src/nest/plugins/host/plugin-guards.service';
|
||||
import { TagsRpc } from '../../../src/nest/tags/tags.rpc';
|
||||
import { DayNotesRpc } from '../../../src/nest/days/day-notes.rpc';
|
||||
import { DayNotesRpc } from '../../../src/nest/day-notes/day-notes.rpc';
|
||||
import { PlacesRpc } from '../../../src/nest/places/places.rpc';
|
||||
import { PackingRpc } from '../../../src/nest/packing/packing.rpc';
|
||||
import { FilesRpc } from '../../../src/nest/files/files.rpc';
|
||||
|
||||
@@ -79,6 +79,7 @@ export default defineConfig({
|
||||
'src/nest/common/**/*.ts': { statements: 95, branches: 89, functions: 99, lines: 97 },
|
||||
'src/nest/config/**/*.ts': { statements: 99, branches: 100, functions: 99, lines: 99 },
|
||||
'src/nest/database/**/*.ts': { statements: 99, branches: 100, functions: 99, lines: 99 },
|
||||
'src/nest/day-notes/**/*.ts': { statements: 92, branches: 82, functions: 98, lines: 97 },
|
||||
'src/nest/days/**/*.ts': { statements: 92, branches: 82, functions: 98, lines: 97 },
|
||||
'src/nest/feeds/**/*.ts': { statements: 91, branches: 83, functions: 83, lines: 91 },
|
||||
'src/nest/files/**/*.ts': { statements: 97, branches: 95, functions: 99, lines: 98 },
|
||||
|
||||
Reference in New Issue
Block a user