Next Session: Maintenance Services Stabilization
Purpose: Use a dedicated session to stabilize all maintenance micro-services (fix type issues in queries and mutations), then add/update maintenance tests, then run tests and Yaak. Do not mix with other service tests — maintenance is skipped in the current session because of its incomplete state.
Current state (why maintenance is skipped this session)
- Queries (
maintenance/queries/index.ts) and mutations (maintenance/mutation/index.ts) have many type errors and mismatches with@/types/maintenanceand the DB schema. Until these are fixed, maintenance tests would be brittle and misleading. - This session: All non-maintenance tests are in scope (auth, me, cache, storage, cookies, jwt, mailer, internal, system). Maintenance tests are skipped entirely.
What needs to be fixed (maintenance only)
1. Types: MaintenanceQueryParams vs usage in queries
- Defined in
@/types/maintenance/unified.ts:MaintenanceQueryFiltershasstatus?: string[],priority?: string[],dateFrom?,dateTo?(nodepartmentApprovalStatus,category,dueDateFrom/dueDateTo,createdAtFrom/createdAtTo,completed). - Used in
queries/index.tsas:params.departmentApprovalStatus,params.category,params.dueDateFrom/dueDateTo,params.createdAtFrom/createdAtTo,params.completed, andparams.status/params.priorityas single strings ineq(). - Fix (choose one):
- Option A: Extend
MaintenanceQueryFilters/MaintenanceQueryParamsto include all fields the query layer uses (departmentApprovalStatus, category, dueDateFrom, dueDateTo, createdAtFrom, createdAtTo, completed) and, for status/priority, either keep array and useinArray()in Drizzle or add single-value variants used byeq(). - Option B: Change query code to use only the existing params (e.g. use
dateFrom/dateTofor due-date filters, add no new filter fields) and useinArray()for status/priority when they are arrays.
- Option A: Extend
2. Queries: orderDirection and ordering
- Code uses
orderDirection(maintenanceRequests.createdAt)butorderDirectionis not defined. - Fix: Define e.g.
const orderDirection = order === 'asc' ? asc : desc(whereordercomes fromparams.order) and use it in the switch. Ensure the Drizzle chain hasorderBybeforelimit/offsetif required by your Drizzle version.
3. Queries: Drizzle select chain
- Lint reports: missing
orderByon the builder, andlimit/offsettype issues. Ensure the select builder is built in the order your Drizzle version expects (e.g..where().orderBy().limit().offset()).
4. Queries: getMaintenanceRequest return and mapping
- Return type is
Promise<PopulatedMaintenanceRequest>but the function returns the result ofmapMaintenanceRequestToResponse(...)which isMaintenanceRequestResponse(different shape: e.g. UserResponse vs DatabaseUser, dates as strings). - Fix: Either change the return type of
getMaintenanceRequesttoPromise<MaintenanceRequestResponse>or add a separate path that builds and returns aPopulatedMaintenanceRequestfrom the same data. Align with how the route layer and types in@/types/databaseexpect the response. - Mapping arguments: The select result has
submittedByUser,assignedToUser,approvedByUser(notapprovedBy), and noAttachmentsin the select list. Code incorrectly usesrequest.Attachmentsandrequest.approvedBy. Fix to passrequest.approvedByUser, and for attachments either add them to the select/join or pass[]and document that attachments are loaded elsewhere.
5. Queries: mapMaintenanceRequestToResponse and null joins
UserResponseDatais expected for staff/technician/approvedBy; leftJoin can return null. Either allowundefinedin the util signature or passreq.submittedByUser ?? undefined(and same for others) so you don’t passnull.
6. Queries: calculatePermissions and hasReadPermission
calculatePermissions(SessionData, request)is called withrequestbeing the raw DB row;request.statuscan bestring | null. EnsureMaintenanceRequestDataor the permission logic accepts nullable status or narrows it before use.hasReadPermission(sessionData, request)is called with the same row; ensure the type forrequestis consistent (e.g. a type that includes joined fields and nullables from the select).
7. Queries: createMaintenanceQueryService
- At the end of the file,
createMaintenanceQueryService(env: Env, services: InitializedServices)usesEnvandInitializedServicesbut they are not imported. Add:import type { Env } from '@/types/app';import type { InitializedServices } from '@/lib/services/init';
8. Mutations: input and return types
createMaintenanceRequest(SessionData, data: any)— replaceanywith a proper type (e.g.CreateMaintenanceRequestor the shape from your Zod/validation).updateMaintenanceRequest(SessionData, requestId, data: any): Promise<any>— use a proper update type fordataand returnPromise<PopulatedMaintenanceRequest>(or the type the route layer expects).
9. Core and other maintenance modules
- After queries and mutations are type-clean, run the linter on all maintenance modules (core, permissions, validation, utils, attachment) and fix any remaining type errors so the whole maintenance service is stable.
Order of work (next session)
- Fix types and implementation in maintenance only
- Align
MaintenanceQueryParams/MaintenanceQueryFilterswith query usage (or the reverse). - Fix queries:
orderDirection, select chain,getMaintenanceRequestreturn type and mapping (approvedByUser, Attachments), null handling for joined users,createMaintenanceQueryServiceimports. - Fix mutations: replace
anywith proper create/update types and return type. - Fix any other maintenance files (core, permissions, validation, utils, attachment) until linter is clean.
- Align
- Maintenance tests
- Add/update tests per Testing Guide: e.g.
queries.test.ts,mutation.test.ts(ormutations.test.ts),permissions.test.ts,validation.test.ts,attachment.test.ts, and optionallycore.test.ts/index.test.ts. Use real types from@/types(SessionData, PopulatedMaintenanceRequest, MaintenanceQueryParams, etc.).
- Add/update tests per Testing Guide: e.g.
- Run tests and Yaak
- Run the full test suite (including maintenance). Until then, to run only non-maintenance tests:
pnpm test --run --exclude='**/maintenance/**'. - Run maintenance flows in Yaak/Postman to validate the lifecycle (create → approve → assign → complete) against the API.
- Run the full test suite (including maintenance). Until then, to run only non-maintenance tests:
References
- Maintenance lifecycle (where data lives, stages): docs/architecture/systems/maintenance-lifecycle.md
- Maintenance caching (Phase 5): same doc, “Caching (Phase 5)” section; and PHASES.md.
- Testing structure and type-safety: docs/guides/testing.md (maintenance tests follow the same one-test-file-per-micro-service pattern).
- Current maintenance type definitions:
@/types/maintenance(unified, approve, assign, complete, status) and@/types/database(PopulatedMaintenanceRequest if used).