chore: drop the exports the reworked server modules left without an importer

knip found them once the server lanes and the client ratchets met: re-exports
and helpers that moved into place-import, nest-rpc and auth-core but kept an
export nothing reads, the demo-denied helper the central MCP gate replaced,
and two settings keys only the selector uses. @OptionalAuth stays exported
as the documented opt-out and is marked @public. The baselines for knip and
the unused en keys drop to the merged tree.
This commit is contained in:
Maurice
2026-10-10 21:52:09 +02:00
parent b9a8bfc3e7
commit 3fdae47041
20 changed files with 26 additions and 52 deletions
-3
View File
@@ -26,16 +26,13 @@
"packing.ts": 6,
"pdf.ts": 1,
"perm.ts": 4,
"photos.ts": 22,
"places.ts": 10,
"planner.ts": 53,
"register.ts": 20,
"reservations.ts": 21,
"roadtrip.ts": 38,
"settings.ts": 40,
"share.ts": 7,
"shared.ts": 2,
"stats.ts": 8,
"storage.ts": 16,
"system_notice.ts": 32,
"todo.ts": 4,
+4 -2
View File
@@ -15,8 +15,10 @@
"entry": ["scripts/ci/*.mjs", "scripts/*.{cjs,mts}"],
"project": ["scripts/**/*.{mjs,cjs,mts}"],
// An optional peer of tsdown, which loads shared/tsdown.config.ts through
// it; nothing imports it by name.
"ignoreDependencies": ["unrun"]
// it; nothing imports it by name. eslint and prettier are the workspaces'
// own copies: the shared scripts/lib takes them handed in, and its tests
// import the hoisted ones the server and shared declare.
"ignoreDependencies": ["unrun", "eslint", "prettier"]
},
"client": {
// The app, its scripts, the Playwright specs and the server launcher
+2 -13
View File
@@ -1,7 +1,4 @@
{
"devDependencies": {
"server/package.json": 3
},
"duplicates": {
"client/src/api/client.ts": 1,
"client/src/components/Map/VectorBasemap.tsx": 1,
@@ -79,11 +76,9 @@
"server/src/mcp/nest-mcp-policy.ts": 1,
"server/src/mcp/scopes.ts": 3,
"server/src/mcp/tools/_shared.ts": 8,
"server/src/nest-mcp/index.ts": 1,
"server/src/nest/accommodations/night-seat.ts": 1,
"server/src/nest/app-config/index.ts": 6,
"server/src/nest/auth/auth.helpers.ts": 1,
"server/src/nest/auth/public.decorator.ts": 1,
"server/src/nest/backup/backup-archive.ts": 1,
"server/src/nest/backup/backup.impl.ts": 3,
"server/src/nest/budget/budget.service.ts": 1,
@@ -100,7 +95,6 @@
"server/src/nest/llm-parse/image-input.ts": 2,
"server/src/nest/llm-parse/llm-config.ts": 1,
"server/src/nest/llm-parse/llm-prompt.ts": 1,
"server/src/nest/maps/maps.service.ts": 2,
"server/src/nest/maps/providers/amap.provider.ts": 2,
"server/src/nest/maps/providers/places-provider.ts": 1,
"server/src/nest/notifications/channel-registry.ts": 1,
@@ -109,7 +103,6 @@
"server/src/nest/oauth/oauth.helpers.ts": 1,
"server/src/nest/place-enrichment/place-enrichment.service.ts": 1,
"server/src/nest/place-shadow/place-shadow.service.ts": 1,
"server/src/nest/places/kml-import.helpers.ts": 1,
"server/src/nest/places/places.helpers.ts": 1,
"server/src/nest/plugins/contributions/plugin-search.helpers.ts": 2,
"server/src/nest/plugins/host/plugin-data.service.ts": 1,
@@ -121,7 +114,6 @@
"server/src/nest/route-usage/route-usage.service.ts": 1,
"server/src/nest/share/share.service.ts": 1,
"server/src/nest/storage/storage-stats.service.ts": 1,
"server/src/nest/transit/transit-provider.ts": 2,
"shared/src/roadtrip/accessSpur.ts": 3
},
"types": {
@@ -207,7 +199,7 @@
"server/src/db/repositories/UserSessions.repository.ts": 1,
"server/src/db/repositories/_shared/rows.ts": 1,
"server/src/mcp/nest-mcp-policy.ts": 1,
"server/src/nest-mcp/index.ts": 13,
"server/src/nest-mcp/index.ts": 12,
"server/src/nest-mcp/types.ts": 4,
"server/src/nest/booking-import/kitinerary.types.ts": 6,
"server/src/nest/collab/collab.service.ts": 1,
@@ -219,9 +211,7 @@
"server/src/nest/maps/trek-places.client.ts": 1,
"server/src/nest/memories/memories.helpers.ts": 1,
"server/src/nest/notifications/notifications.service.ts": 1,
"server/src/nest/places/places.helpers.ts": 1,
"server/src/nest/plugins/contributions/map-layers.controller.ts": 1,
"server/src/nest/plugins/host/rpc-kit/types.ts": 2,
"server/src/nest/plugins/install/manifest.ts": 7,
"server/src/nest/plugins/plugins.service.ts": 1,
"server/src/nest/plugins/protocol/envelope.ts": 2,
@@ -233,8 +223,7 @@
"server/src/nest/vacay/vacay.service.ts": 4,
"server/src/nest/weather/weather.impl.ts": 1,
"server/src/shutdown.ts": 1,
"server/src/systemNotices/types.ts": 7,
"server/src/types.ts": 14
"server/src/systemNotices/types.ts": 7
},
"unlisted": {
"client/src/components/Map/MapView.tsx": 1,
+1 -1
View File
@@ -27,7 +27,7 @@ import {
* inline disable must not be the cheap way under the ratchet, and an inline
* rule config, which silences without a trace, fails outright (see tally).
*/
export const AREAS = ['src', 'tests', 'suppressed'];
const AREAS = ['src', 'tests', 'suppressed'];
const areaOf = (key) => (key.startsWith('tests/') || TEST_FILE.test(key) ? 'tests' : 'src');
+1 -1
View File
@@ -38,7 +38,7 @@ export async function isFormatted(prettier, path) {
}
/** The files under root/<dirs> that accepts takes and Prettier would rewrite, keyed by their path from root. */
export async function unformatted({ prettier, root, dirs, accepts }) {
async function unformatted({ prettier, root, dirs, accepts }) {
const found = [];
for (const path of listFiles(root, dirs, accepts)) {
if (!(await isFormatted(prettier, path))) found.push(toKey(root, path));
-1
View File
@@ -6,7 +6,6 @@ import { errorResult } from '../../nest-mcp';
// the impure guards (hasTripPermission/isAdminUser/safeBroadcast) moved onto
// the injectable McpToolGuardsService (src/nest/mcp-shared/).
export {
demoDenied,
errorResult,
ok,
TOOL_ANNOTATIONS_DELETE,
-3
View File
@@ -16,8 +16,6 @@ export { McpModule } from './mcp.module';
export { McpRegistry, type McpRegistryOptions } from './registry';
export { createTestRegistry } from './testing';
export {
MCP_MODULE_OPTIONS,
MCP_TOOL_GATE,
type McpAccess,
type McpAccessGroup,
type McpAccessGroupRegistry,
@@ -37,7 +35,6 @@ export {
type McpModuleOptions,
type McpRegistryListing,
type McpToolGate,
type McpToolGateProvider,
type McpZodSchema,
type PromptArgsShape,
type PromptOptions,
+1 -1
View File
@@ -284,7 +284,7 @@ export type McpErrorMapper = (err: unknown) => unknown;
* needs, resolved from the container like any other provider. A gate that
* reads the database has to come from DI, and `forRoot` options are static.
*/
export interface McpToolGateProvider {
interface McpToolGateProvider {
/** Modules exporting what `inject` names, unless those providers are global. */
imports?: NonNullable<ModuleMetadata['imports']>;
inject?: InjectionToken[];
+1 -3
View File
@@ -32,13 +32,11 @@ export interface PluginRpcContext {
}
/** What a plugin may do to its declared dependencies. */
export interface PluginRpcPeers {
interface PluginRpcPeers {
call(targetId: string, fn: string, args: unknown, actingUserId: number | undefined): Promise<unknown>;
emit(event: string, payload: unknown): Promise<void>;
}
export type PluginRpcHandler = (params: Record<string, unknown>, ctx: PluginRpcContext) => unknown;
/**
* What a decorator records. `methodName` is the name of the decorated class method,
* `method` the wire name it answers to; they are deliberately independent.
@@ -30,4 +30,5 @@ export const Public = (reason: string) => SetMetadata(IS_PUBLIC, { reason });
* aside when there is no user, so making a route optional-auth newly enrols its
* mutations in idempotency replay.
*/
/** @public The documented opt-out for a route that reads a session when there is one; no route needs it today. */
export const OptionalAuth = (reason: string) => SetMetadata(OPTIONAL_AUTH, { reason });
+1 -1
View File
@@ -35,7 +35,7 @@ export { readBrandIdentity, readWikiIdentity, type WikiIdentity } from './provid
export { withPhotoFetchSlot } from './photo-fetch-slot';
export type { BrandLogo, CommonsCandidate } from './providers/wikimedia.client';
export { GOOGLE_SHORT_HOSTS, isGoogleMapsHost } from '../common/google-maps-hosts';
export { PLACES_PROVIDER_SETTING, PLACES_GOOGLE_ONLY_SETTING, type KeyedProvider } from './places-provider.selector';
export { type KeyedProvider } from './places-provider.selector';
// Places near a point (#976): cached longer than the POI boxes, because the
// likely caller is an import asking the same photo location again, and Google
@@ -31,13 +31,13 @@ import { isOutsideChina } from '@trek/shared';
* admin can say which one should answer. Absent, which is every install that
* predates Amap, means `auto`, which keeps Google.
*/
export const PLACES_PROVIDER_SETTING = 'places_provider';
const PLACES_PROVIDER_SETTING = 'places_provider';
/**
* The admin switch that hands search and suggestions to Google alone. Off, the
* index and OpenStreetMap answer first and Google is only asked when they find
* nothing, which is what every install has had since 4.3.0.
*/
export const PLACES_GOOGLE_ONLY_SETTING = 'places_google_only';
const PLACES_GOOGLE_ONLY_SETTING = 'places_google_only';
/**
* Whoever holds the keyed slot beside the index for one request: Google's
@@ -12,7 +12,7 @@ import { PERMISSION_ACTIONS, evaluatePermission, type PermissionAction, type Per
// @trek/shared, so the admin screen and the client read the same table the
// server enforces. Re-exported here for the server code that imported them.
export { PERMISSION_ACTIONS };
export type { PermissionAction, PermissionLevel };
export type { PermissionLevel };
const ACTIONS_MAP = new Map<string, PermissionAction>(PERMISSION_ACTIONS.map((a) => [a.key, a]));
+1 -1
View File
@@ -56,7 +56,7 @@ export function createGpxParser(mode: GpxReadMode): XMLParser {
export const gpxGeometryParser = createGpxParser('geometry');
export const gpxTextParser = createGpxParser('text');
export const GPX_NAMESPACE = 'http://www.topografix.com/GPX/1/1';
const GPX_NAMESPACE = 'http://www.topografix.com/GPX/1/1';
/** Coordinates are written with 7 decimals, ~11 mm, which is past what any consumer
* device resolves and keeps the file from carrying float noise. */
+3 -5
View File
@@ -16,7 +16,7 @@ import { XMLParser, XMLValidator } from 'fast-xml-parser';
import unzipper from 'unzipper';
import { TextDecoder } from 'util';
export type { KmlImportSummary, ParsedKmlPlacemark } from './place-import.types';
export type { ParsedKmlPlacemark } from './place-import.types';
export interface KmlPlacemarkNode {
placemark: any;
@@ -111,9 +111,7 @@ export function sanitizeKmlDescription(value: unknown): string | null {
return decoded || null;
}
export function parseKmlLineStringCoordinates(
value: unknown,
): Array<{ lat: number; lng: number; ele: number | null }> | null {
function parseKmlLineStringCoordinates(value: unknown): Array<{ lat: number; lng: number; ele: number | null }> | null {
const coordinates = asTrimmedString(value);
if (!coordinates) return null;
@@ -148,7 +146,7 @@ export function parseKmlPointCoordinates(value: unknown): { lat: number; lng: nu
return { lat, lng };
}
export function createKmlImportSummary(totalPlacemarks: number): KmlImportSummary {
function createKmlImportSummary(totalPlacemarks: number): KmlImportSummary {
return {
totalPlacemarks,
createdCount: 0,
@@ -20,7 +20,7 @@ import type { CollectionGpxExport, CollectionGpxReadResult } from '@trek/shared'
// The directions-link reading is also what the road trip planner reads a
// shared route with, and what the import routes dispatch on.
export { isDirectionsUrl, parseDirectionsUrl, MAX_DIR_WAYPOINTS, type DirWaypoint } from './directions-url.helpers';
export { isDirectionsUrl, parseDirectionsUrl, MAX_DIR_WAYPOINTS } from './directions-url.helpers';
export type { GpxExportDay, GpxExportInput, GpxExportOptions, GpxExportPlace } from './providers/gpx.provider';
export type { ExportedCollectionFile } from './providers/collection-gpx.provider';
@@ -166,7 +166,7 @@ export function gpxFilename(tripTitle: string): string {
* anything. Waypoints become places, each route and each track becomes one
* place carrying its geometry.
*/
export function prepareGpxRows(fileBuffer: Buffer, opts: GpxImportOptions = {}): PreparedGpxPlace[] {
function prepareGpxRows(fileBuffer: Buffer, opts: GpxImportOptions = {}): PreparedGpxPlace[] {
const { importWaypoints = true, importRoutes = true, importTracks = true, defaultName } = opts;
const parsed = gpxGeometryParser.parse(fileBuffer.toString('utf-8'));
+1 -7
View File
@@ -18,7 +18,7 @@ import { externalIdsOf, normalizePlaceName, placeMatchStrategies, type PlaceMatc
// while the values themselves live in @trek/shared with the rule that uses them.
export { COORD_DEDUP_TOLERANCE, externalIdsOf } from '@trek/shared';
export type { GpxImportOptions, KmlImportOptions, ListImportError } from '../place-import/place-import.types';
export type { GpxImportOptions, KmlImportOptions } from '../place-import/place-import.types';
/**
* Escape the LIKE metacharacters in a user-supplied search term so `%` and `_`
@@ -36,12 +36,6 @@ export interface ListImportOptions {
lang?: string;
}
export interface PlaceWithCategory extends Place {
category_name: string | null;
category_color: string | null;
category_icon: string | null;
}
export interface PlaceImportResult {
places: PlaceWithTags[];
count: number;
+2 -2
View File
@@ -13,14 +13,14 @@
* because that is what an assistant reliably surfaces.
*/
import type { McpZodSchema } from '../../nest-mcp';
import { MCP_TOOLS_MAX, TOOL_NAME_RE } from './protocol/manifest-rules';
import { MCP_TOOLS_MAX } from './protocol/manifest-rules';
import { sanitiseAssistantText } from './text-sanitize';
import { z } from 'zod';
// The per-plugin cap and the tool-name pattern are manifest rules: they live in
// protocol/manifest-rules.ts, which gen-plugin-facts writes into the SDK.
export { MCP_TOOLS_MAX, TOOL_NAME_RE };
export { MCP_TOOLS_MAX };
/**
* Tools all plugins together may advertise.
@@ -1,7 +1,6 @@
import tsParser from '@typescript-eslint/parser';
import { ESLint, Linter } from 'eslint';
import path from 'path';
import tseslint from 'typescript-eslint';
import { describe, expect, it } from 'vitest';
// fast-xml-parser is allowed in place-import's codecs and the WebDAV client
@@ -29,7 +28,7 @@ async function flags(file: string, source: string): Promise<boolean> {
[
{
files: ['**/*.ts'],
languageOptions: { parser: tsParser },
languageOptions: { parser: tseslint.parser },
rules: { 'no-restricted-imports': ['error', ...(options as object[])] },
},
],