```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;
      }

      // Move to end (most recently used)
      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 {
        // New key
        if (cache.size >= capacity) {
          // Remove least recently used
          const lruKey = order.values().next().value;
          order.delete(lruKey);
          cache.delete(lruKey);
        }

        cache.set(key, value);
        order.add(key);
      }
    },

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