Files
reverse-engineering-anything/src/filesystem/OwnedRegularFile.ts
T
morluto a891bb80ae refactor(filesystem): preserve admitted file facts
Return the validated descriptor and its original metadata from regular-file
admission. Propagate that contract through owned reads, hashes, snapshots,
artifact inventory and provider file workflows instead of replacing initial
facts with another stat. Keep arbitrary output-handle operations separate.

Preserve final descriptor/path identity proofs, borrowed-source verification,
BigInt precision, cancellation provenance and failed-close ownership. Remove
the obsolete source and owned-ZIP baseline stages and update their consumers
and regressions. Tie read completion faults to actual reads instead of the
retired duplicate stat; instrument real handles without fake handle wrappers.

Validation: fresh runtime/catalog build; focused source, lifecycle, filesystem,
CLI/MCP and authored provider-fixture tests; full static checks; docs checks;
test discovery; duplication check. Platform-specific cases remain skipped on
macOS. No installed provider or device behavior was verified.
2026-10-25 04:09:11 +08:00

240 lines
7.6 KiB
TypeScript

import type { FileHandle } from "node:fs/promises";
import { OwnedFileHandle } from "./OwnedFileHandle.js";
import {
openRegularFile,
RegularFileAdmissionFailure,
assertRegularFileActive,
RegularFileOperationCancelled,
type StableRegularFileDescriptor,
} from "./RegularFile.js";
export type RegularFileOperationOutcome<Value> =
| { readonly kind: "completed"; readonly value: Value }
| { readonly kind: "failed"; readonly cause: unknown };
type CompletedRegularFileOutcome<Value> = Extract<
RegularFileOperationOutcome<Value>,
{ readonly kind: "completed" }
>;
/** Physical operation origin kept separate from caller-provided error values. */
export class OwnedRegularFileOperationFailure extends Error {
readonly _tag: string = "OwnedRegularFileOperationFailure";
constructor(readonly operationCause: unknown) {
super("Owned regular-file operation failed", { cause: operationCause });
this.name = this._tag;
}
}
/** Cancellation after confirmed close, retaining the completed physical read. */
export class RegularFileCancelled<Value = unknown> extends Error {
readonly _tag = "RegularFileCancelled";
readonly outcome: CompletedRegularFileOutcome<Value>;
readonly reason: unknown;
constructor(
readonly path: string,
readonly owner: OwnedFileHandle,
completion: {
readonly outcome: CompletedRegularFileOutcome<Value>;
readonly reason: unknown;
},
) {
super(`Regular file operation cancelled after closing ${path}`, {
cause: completion.reason,
});
this.name = this._tag;
this.outcome = completion.outcome;
this.reason = completion.reason;
}
}
/** A failed close transfers its exact descriptor owner and operation outcome. */
export interface RegularFileCleanupFacts<Value = unknown> {
readonly path: string;
readonly owner: OwnedFileHandle;
readonly outcome: RegularFileOperationOutcome<Value>;
readonly cleanupCause: unknown;
readonly retention?:
| { readonly kind: "not_requested" }
| { readonly kind: "callback_returned" }
| { readonly kind: "callback_threw"; readonly cause: unknown }
| undefined;
readonly completionCancellation?: { readonly reason: unknown } | undefined;
readonly operationFailure?: OwnedRegularFileOperationFailure | undefined;
}
export class RegularFileCleanupFailure<Value = unknown> extends Error {
readonly path: string;
readonly owner: OwnedFileHandle;
readonly outcome: RegularFileOperationOutcome<Value>;
readonly cleanupCause: unknown;
readonly retention: NonNullable<RegularFileCleanupFacts["retention"]>;
readonly completionCancellation: { readonly reason: unknown } | undefined;
readonly operationFailure: OwnedRegularFileOperationFailure | undefined;
constructor(facts: RegularFileCleanupFacts<Value>) {
const {
path,
owner,
outcome,
cleanupCause,
retention = { kind: "not_requested" },
completionCancellation,
operationFailure,
} = facts;
super(`Regular file cleanup failed for ${path}`, {
cause: new AggregateError(
[
...(outcome.kind === "failed" ? [outcome.cause] : []),
cleanupCause,
...(retention.kind === "callback_threw" ? [retention.cause] : []),
],
"File operation and cleanup failures",
),
});
this.name = "RegularFileCleanupFailure";
this.path = path;
this.owner = owner;
this.outcome = outcome;
this.cleanupCause = cleanupCause;
this.retention = retention;
this.completionCancellation = completionCancellation;
this.operationFailure = operationFailure;
}
}
export interface OwnedFileOperationOptions {
readonly signal?: AbortSignal;
readonly retainFailedClose?: (owner: OwnedFileHandle) => void;
}
/** Read only cancellation facts recorded by the operation or its final close. */
export const regularFileCancellation = (
cause: unknown,
): { readonly reason: unknown } | undefined => {
if (
cause instanceof RegularFileCleanupFailure &&
cause.operationFailure !== undefined
)
return cause.outcome.kind === "completed"
? cause.completionCancellation
: undefined;
const primary =
cause instanceof RegularFileCleanupFailure &&
cause.outcome.kind === "failed"
? cause.outcome.cause
: cause;
if (
primary instanceof RegularFileOperationCancelled ||
primary instanceof RegularFileCancelled
)
return { reason: primary.reason };
return cause instanceof RegularFileCleanupFailure &&
cause.outcome.kind === "completed"
? cause.completionCancellation
: undefined;
};
export interface OwnedRegularFileOptions extends OwnedFileOperationOptions {
readonly symlinks?: "follow" | "reject";
}
/** Run an operation while one admitted descriptor and its cleanup owner stay together. */
export const withOwnedRegularFile = async <Value>(
path: string,
options: OwnedRegularFileOptions,
operation: (source: StableRegularFileDescriptor) => Promise<Value>,
): Promise<Value> => {
const source = await openRegularFile(path, {
symlinks: options.symlinks ?? "follow",
signal: options.signal,
}).catch((cause: unknown) => {
if (!(cause instanceof RegularFileAdmissionFailure)) throw cause;
const retention = retainOwner(options.retainFailedClose, cause.owner);
throw new RegularFileCleanupFailure({
path,
owner: cause.owner,
outcome: { kind: "failed", cause: cause.cause },
cleanupCause: cause.cleanupCause,
retention,
});
});
return withOwnedFileHandle(
path,
new OwnedFileHandle(source.handle),
options,
() => operation(source),
);
};
/** Own an already admitted descriptor through its operation and final close. */
export const withOwnedFileHandle = async <Value>(
path: string,
owner: OwnedFileHandle,
options: OwnedFileOperationOptions,
operation: (handle: FileHandle) => Promise<Value>,
): Promise<Value> => {
const handle = owner.handle;
let outcome: RegularFileOperationOutcome<Value>;
try {
assertRegularFileActive(options.signal);
outcome = { kind: "completed", value: await operation(handle) };
} catch (cause: unknown) {
outcome = { kind: "failed", cause };
}
try {
await owner.close();
} catch (cleanupCause: unknown) {
const operationFailure =
outcome.kind === "failed" &&
outcome.cause instanceof OwnedRegularFileOperationFailure
? outcome.cause
: undefined;
const retainedOutcome =
operationFailure === undefined
? outcome
: {
kind: "failed" as const,
cause: operationFailure.operationCause,
};
const completionCancellation =
outcome.kind === "completed" && options.signal?.aborted === true
? { reason: options.signal.reason }
: undefined;
// Retain the physical read outcome even if the caller cancelled during
// close: consumers may need completed observations such as a file digest.
throw new RegularFileCleanupFailure({
path,
owner,
outcome: retainedOutcome,
cleanupCause,
retention: retainOwner(options.retainFailedClose, owner),
completionCancellation,
operationFailure,
});
}
if (outcome.kind === "failed") throw outcome.cause;
if (options.signal?.aborted === true)
throw new RegularFileCancelled(path, owner, {
outcome,
reason: options.signal.reason,
});
return outcome.value;
};
const retainOwner = (
retain: OwnedRegularFileOptions["retainFailedClose"],
owner: OwnedFileHandle,
): RegularFileCleanupFailure["retention"] => {
if (retain === undefined) return { kind: "not_requested" };
try {
retain(owner);
return { kind: "callback_returned" };
} catch (cause: unknown) {
return { kind: "callback_threw", cause };
}
};