refactor(entitlements): migrate type-only consumers to entitlements/types (#879)

Follows the Phase 1 EntitlementProvider abstraction. Two files
imported tier types from services/LicenseService via the back-compat
re-export added in Phase 1; this PR points them at the canonical
location at entitlements/types and drops the re-export block.

Migrated:
  - backend/src/types/express.ts
  - backend/src/routes/dashboard.ts

After this PR, services/LicenseService.ts has no public type re-
exports. The remaining imports of services/LicenseService are:
  - entitlements/loadProvider.ts: runtime import of the
    LicenseService class itself, the intentional Phase 1 binding
    site.
  - __tests__/license-service-id-validation.test.ts: imports
    SENCHO_LS_* catalog constants and resolveSenchoVariantFromMeta;
    these are LemonSqueezy-implementation-specific and stay in
    services/LicenseService until Phase 2 moves the file to
    @studio-saelix/sencho-pro.

Phase 2's deletion of services/LicenseService.ts now requires zero
public-core consumer changes outside the loader and the LS-specific
test file.

Test results: 89/89 backend test files clean, 1657 passing tests, 5
pre-existing skips, plus the same pre-existing database-metrics
stress test flake under parallel load that consistently passes solo.
This commit is contained in:
Anso
2026-05-02 05:21:26 -04:00
committed by GitHub
parent 3324616e59
commit 4b18109286
3 changed files with 5 additions and 13 deletions
+1 -1
View File
@@ -3,7 +3,7 @@ import { DatabaseService } from '../services/DatabaseService';
import { CloudBackupService } from '../services/CloudBackupService';
import { authMiddleware } from '../middleware/auth';
import { effectiveTier, effectiveVariant } from '../middleware/tierGates';
import type { LicenseTier, LicenseVariant } from '../services/LicenseService';
import type { LicenseTier, LicenseVariant } from '../entitlements/types';
export const dashboardRouter = Router();
+3 -11
View File
@@ -10,14 +10,6 @@ import type {
SeatLimits,
} from '../entitlements/types';
// Back-compat re-exports. The canonical type definitions live in
// `entitlements/types.ts`; this re-export keeps existing imports
// (`import type { LicenseTier } from '@/services/LicenseService'`)
// working until consumers migrate. A follow-up PR titled
// `refactor(entitlements): migrate type-only consumers to entitlements/types`
// will sweep the remaining ~20 consumers; Phase 2 deletes this file.
export type { LicenseInfo, LicenseStatus, LicenseTier, LicenseVariant, SeatLimits };
// Header constants and tier/variant normalizers previously exported
// from this file moved to `../entitlements/headers` and
// `../entitlements/normalize` respectively, where they live in the
@@ -25,9 +17,9 @@ export type { LicenseInfo, LicenseStatus, LicenseTier, LicenseVariant, SeatLimit
// LicenseService imports them back for internal use.
import { isLicenseVariant, normalizeVariant } from '../entitlements/normalize';
// LicenseInfo and SeatLimits live in `entitlements/types.ts` and are
// re-exported above. The literal seat-limit table for paid variants
// stays here because it is specific to the LemonSqueezy implementation.
// The seat-limit table for paid variants is specific to the
// LemonSqueezy implementation and stays in this file. Phase 2 moves it
// to `@studio-saelix/sencho-pro` along with the rest of the file.
const SEAT_LIMITS: Record<string, SeatLimits> = {
skipper: { maxAdmins: 1, maxViewers: 3 },
admiral: { maxAdmins: null, maxViewers: null },
+1 -1
View File
@@ -1,5 +1,5 @@
import type { UserRole, ApiTokenScope } from '../services/DatabaseService';
import type { LicenseTier, LicenseVariant } from '../services/LicenseService';
import type { LicenseTier, LicenseVariant } from '../entitlements/types';
// Extend Express Request type for user and node context.
// This file is imported for its side effects only (ambient declaration).