56 lines
1.5 KiB
TypeScript
56 lines
1.5 KiB
TypeScript
/**
|
|
* Branded type for process IDs to ensure type safety
|
|
*/
|
|
export type ProcessId = number & { readonly __brand: 'ProcessId' };
|
|
|
|
/**
|
|
* Input type that accepts various ID formats for backward compatibility
|
|
*/
|
|
export type ProcessIdInput = ProcessId | number | string;
|
|
|
|
/**
|
|
* Normalizes various ID input formats to a ProcessId
|
|
* @param input - The ID in various formats (string, number, or ProcessId)
|
|
* @returns A normalized ProcessId
|
|
* @throws Error if the input is not a valid process ID
|
|
*/
|
|
export function toProcessId(input: ProcessIdInput): ProcessId {
|
|
let num: number;
|
|
|
|
if (typeof input === 'string') {
|
|
const trimmed = input.trim();
|
|
if (!/^\d+$/.test(trimmed)) {
|
|
throw new Error(`Invalid process ID: "${input}" is not a numeric string`);
|
|
}
|
|
num = parseInt(trimmed, 10);
|
|
} else if (typeof input === 'number') {
|
|
num = input;
|
|
} else {
|
|
// Already a ProcessId
|
|
return input;
|
|
}
|
|
|
|
if (!Number.isInteger(num) || num < 1) {
|
|
throw new Error(`Invalid process ID: ${input} must be a positive integer`);
|
|
}
|
|
|
|
return num as ProcessId;
|
|
}
|
|
|
|
/**
|
|
* Type guard to check if a value is a ProcessId
|
|
*/
|
|
export function isProcessId(value: unknown): value is ProcessId {
|
|
return typeof value === 'number' && Number.isInteger(value) && value >= 1;
|
|
}
|
|
|
|
/**
|
|
* Gets the next sequential ID given existing IDs
|
|
*/
|
|
export function getNextProcessId(existingIds: Iterable<ProcessId>): ProcessId {
|
|
let maxId = 0;
|
|
for (const id of existingIds) {
|
|
maxId = Math.max(maxId, id);
|
|
}
|
|
return (maxId + 1) as ProcessId;
|
|
} |