```ts
export function createLruCache(capacity: number): { get: (key: string) => number | undefined; put: (key: string, value: number) => void; size: () => number } {
    if (!Number.isInteger(capacity) || capacity <= 0) {
        throw new Error('Capacity must be a positive integer');
    }

    const cache = new Map<string, number>();
    const lruOrder: string[] = [];

    function get(key: string): number | undefined {
        if (!cache.has(key)) {
            return undefined;
        }
        
        // Move key to most recently used
        const index = lruOrder.indexOf(key);
        if (index !== -1) {
            lruOrder.splice(index, 1);
        }
        lruOrder.push(key);
        
        return cache.get(key);
    }

    function put(key: string, value: number): void {
        if (cache.has(key)) {
            // Update existing key
            const index = lruOrder.indexOf(key);
            if (index !== -1) {
                lruOrder.splice(index, 1);
            }
            lruOrder.push(key);
            cache.set(key, value);
        } else {
            // Add new key
            if (cache.size >= capacity) {
                // Evict least recently used
                const lruKey = lruOrder.shift();
                if (lruKey !== undefined) {
                    cache.delete(lruKey);
                }
            }
            lruOrder.push(key);
            cache.set(key, value);
        }
    }

    function size(): number {
        return cache.size;
    }

    return { get, put, size };
}
```