mirror of
https://github.com/callstack/agent-device.git
synced 2026-09-14 20:06:34 +08:00
afdbaa807f
* refactor(host-kit): move verified-file ownership * fix(host-kit): update verified-file closure budgets * chore(tests): remove retired exec fault fixture
73 lines
2.4 KiB
TypeScript
73 lines
2.4 KiB
TypeScript
import fs from 'node:fs';
|
|
import type {
|
|
AppLogProcessMarkerReadOutcome,
|
|
AppLogSessionArtifacts,
|
|
} from '@agent-device/contracts/app-log-runtime';
|
|
import type {
|
|
NetworkAppLogRead,
|
|
NetworkRuntimeHost,
|
|
NetworkTransport,
|
|
} from '@agent-device/contracts/network-runtime';
|
|
import type { DeviceInfo } from '@agent-device/kernel/device';
|
|
import { openVerifiedFileForRead } from '@agent-device/host-kit/file';
|
|
|
|
type ProcessMarkerReader = Readonly<{
|
|
readMarker(pathname: string): Promise<AppLogProcessMarkerReadOutcome>;
|
|
}>;
|
|
|
|
export function createNetworkRuntimeHost(
|
|
options: Readonly<{
|
|
resolveSessionArtifacts(sessionId: string): AppLogSessionArtifacts;
|
|
processes: ProcessMarkerReader;
|
|
resolveTransport(device: DeviceInfo): Promise<NetworkTransport>;
|
|
}>,
|
|
): Pick<NetworkRuntimeHost, 'appLogs' | 'networkTransports'> {
|
|
return Object.freeze({
|
|
appLogs: Object.freeze({
|
|
resolveSession: options.resolveSessionArtifacts,
|
|
readRecent: async (sessionId: string, maxScanLines: number) => {
|
|
const { outputPath } = options.resolveSessionArtifacts(sessionId);
|
|
return readRecentAppLogLines(outputPath, maxScanLines);
|
|
},
|
|
readProcessMarker: async (sessionId: string) => {
|
|
const { pidPath } = options.resolveSessionArtifacts(sessionId);
|
|
return await options.processes.readMarker(pidPath);
|
|
},
|
|
}),
|
|
networkTransports: Object.freeze({ resolve: options.resolveTransport }),
|
|
});
|
|
}
|
|
|
|
export function readRecentAppLogLines(pathname: string, maxScanLines: number): NetworkAppLogRead {
|
|
if (!Number.isInteger(maxScanLines) || maxScanLines < 1 || maxScanLines > 20_000) {
|
|
throw new TypeError('Network app-log scan lines must be between 1 and 20000');
|
|
}
|
|
const descriptor = openVerifiedFileForRead(pathname);
|
|
if (descriptor === undefined) {
|
|
return Object.freeze({ path: pathname, exists: false, text: '', skippedLines: 0 });
|
|
}
|
|
try {
|
|
const text = fs.readFileSync(descriptor, 'utf8');
|
|
const recent = selectRecentLines(text, maxScanLines);
|
|
return Object.freeze({
|
|
path: pathname,
|
|
exists: true,
|
|
...recent,
|
|
});
|
|
} finally {
|
|
fs.closeSync(descriptor);
|
|
}
|
|
}
|
|
|
|
function selectRecentLines(
|
|
text: string,
|
|
maxScanLines: number,
|
|
): Readonly<{ text: string; skippedLines: number }> {
|
|
const lines = text.split('\n');
|
|
const skippedLines = Math.max(0, lines.length - maxScanLines);
|
|
return Object.freeze({
|
|
text: lines.slice(skippedLines).join('\n'),
|
|
skippedLines,
|
|
});
|
|
}
|