```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[] = [];

    return {
        get(key: string): number | undefined {
            if (cache.has(key)) {
                // 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);
            }
            return undefined;
        },

        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);
            }
        },

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