/** * Orphan cleanup for service codegen. * * Service generation is opt-out (#81): every project `kind: object` schema * gets a `ServiceBase.php` (regenerated wholesale, no user content) * and a `Service.php` (sinh-1-lần userFile, may contain hand code). * * When a schema flips from `kind: object` → `kind: pivot`, gets renamed, * removed, opted out via `options.service: false`, or hidden, the * previously-emitted base service stays on disk forever and pollutes * Composer autoload (a class file with no backing schema = mystery code * for the next dev to inherit). * * This module mirrors the existing pivot YAML cleanup pattern * (`RemoveOrphanAutoPivots` in the Go layer): scan known service * directories, diff against the current generation's expected output set, * delete the orphan base files. Editable `*Service.php` files are NEVER * deleted — they may contain hand-written user code — instead a console * warning is printed so the user can decide whether to clean up by hand. */ import type { GeneratedFile, PhpConfig } from './types.js'; /** Matches the header emitted by `generateEditableService` in service-generator.ts */ export declare const OMNIFY_EDITABLE_SERVICE_MARKER = "SAFE TO EDIT - This file is never overwritten by Omnify."; /** * True when the file looks like an Omnify sinh-1-lần editable stub (not a * hand-written app service that merely ends in `Service.php`). */ export declare function looksLikeOmnifyEditableService(fileContent: string): boolean; export interface ServiceCleanupResult { /** Absolute paths to `*ServiceBase.php` files that were deleted. */ prunedBases: string[]; /** Absolute paths to `*Service.php` files that look orphan but are * preserved (may contain user code). Caller should print a warning. */ warnedEditables: string[]; } /** Apply service orphan cleanup only while the service layer is enabled. */ export declare function pruneOrphanServiceFilesIfEnabled(configDir: string, config: PhpConfig, generated: readonly GeneratedFile[]): ServiceCleanupResult; export interface DisabledLayerPruneSummary { layer: string; label: string; prunedCount: number; keptCount: number; } /** * When a scaffold layer is disabled (issue #252), remove stale auto-generated * BASE files that have no matching user-editable subclass on disk. */ export declare function pruneDisabledScaffoldLayerBases(configDir: string, config: PhpConfig, generated: readonly GeneratedFile[], referenced?: ReadonlySet): DisabledLayerPruneSummary[]; /** * Issue #255: is this generated base of a disabled scaffold layer still used by * hand-written code? Same question the prune above asks before deleting a base, * so a base is regenerated exactly when it would otherwise be kept. */ export declare function hasEditableSubclassForBase(config: PhpConfig, referenced: ReadonlySet, file: GeneratedFile): boolean; /** * Every class hand-written PHP under the Laravel root names in a `use` import * or a fully-qualified `extends` (#260). * * "Is this base still used?" used to be answered by looking for a file named * after it in the layer's configured directories. Real projects keep their * subclasses wherever they like — `app/Policies/`, `app/Services/Promotion/` — * so a used base looked unused and was deleted under running code. The import * is what PHP resolves, so the import is what we check. */ export declare function collectReferencedClasses(configDir: string, config: PhpConfig): Set; /** * Delete orphan `*ServiceBase.php` files; flag orphan editable services * for warning. Pure-ish: takes the generated file list (= source of * truth for "what should exist") and the resolved PhpConfig (= where to * look). Filesystem mutations are limited to `unlinkSync` on base files * that are demonstrably absent from the generated set. */ export declare function pruneOrphanServiceFiles(configDir: string, config: PhpConfig, generated: readonly GeneratedFile[]): ServiceCleanupResult;