```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 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
      cache.set(key, value);
      const index = lruOrder.indexOf(key);
      if (index > -1) {
        lruOrder.splice(index, 1);
        lruOrder.push(key);
      }
    } else {
      // Add new key
      if (lruOrder.length >= 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 };
}
```