```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 order = new Set<string>();

  return {
    get(key: string): number | undefined {
      if (!cache.has(key)) {
        return undefined;
      }
      
      // Remove and re-add to update order (most recent)
      order.delete(key);
      order.add(key);
      
      return cache.get(key)!;
    },
    
    put(key: string, value: number): void {
      if (cache.has(key)) {
        // Update existing key
        cache.set(key, value);
        order.delete(key);
        order.add(key);
      } else {
        // Add new key
        if (cache.size >= capacity) {
          // Remove least recently used (first in set)
          const lruKey = order.values().next().value;
          cache.delete(lruKey);
          order.delete(lruKey);
        }
        
        cache.set(key, value);
        order.add(key);
      }
    },
    
    size(): number {
      return cache.size;
    }
  };
}
```