npm package: @nishanprime/sku-generator
Description: TypeORM + PostgreSQL library for generating SKUs for A5IT
Author: A5IT | info@a5it.com
Latest version: 1.1.0

```markdown
# SKU Generator (TypeORM + PostgreSQL)

A lightweight utility for generating and retrieving SKUs (Stock Keeping Units) stored in a PostgreSQL database using TypeORM. This library:

- Connects to PostgreSQL once and reuses the same connection until explicitly closed.  
- Checks if a SKU already exists for a given manufacturer and part number.  
- Creates a new SKU if none exists.  
- Stores and retrieves SKUs in a database table (named `skus` by default if using `@Entity('skus')`).

## Table of Contents

- [Installation](#installation)
- [Usage](#usage)
  - [Constructor Parameters](#constructor-parameters)
  - [Basic Example](#basic-example)
  - [Multiple Calls Example](#multiple-calls-example)
- [Methods](#methods)
  - [`init()`](#init)
  - [`getOrCreateSKU(params)`](#getorcreateskuparams)
  - [`close()`](#close)
- [Environment Variables](#environment-variables)
- [License](#license)

---

## Installation

```bash
npm install @nishanprime/sku-generator
```
---

## Usage

### Constructor Parameters

```ts
/**
 * The options you can pass to the constructor:
 * {
 *   url: string;          // PostgreSQL connection string
 *   synchronize: boolean; // Whether to auto-sync the database schema
 *   logging: boolean;     // Enable TypeORM query logging
 *   extra: {
 *     max: number;                  // Max DB connections in the pool
 *     idleTimeoutMillis: number;    // Idle timeout in ms
 *     connectionTimeoutMillis: number; // Connection timeout in ms
 *   };
 * }
 */
```

- **url**: The connection string for your Postgres DB. E.g. `"postgres://user:pass@localhost:5432/dbname"`.
- **synchronize**: In development, `true` can auto-create or update tables. In production, you typically use migrations and set this to `false`.
- **logging**: Prints SQL queries to the console if `true`.
- **extra**: Pool settings (default values shown in the code).

If you **omit** these options, it will look for a `POSTGRES_CONNECTION_STRING` in your environment variables.

### Basic Example

```ts
import { SKUGenerator } from "@nishanprime/sku-generator";

(async () => {
  // Create a new SKUGenerator instance with optional connection settings
  const skuGen = new SKUGenerator({
    url: "postgres://user:password@localhost:5432/mydb",
    synchronize: true,  // For dev only
    logging: false,      
    extra: {
      max: 10,
      idleTimeoutMillis: 30000,
      connectionTimeoutMillis: 5000,
    },
  });

  // Make sure the data source is initialized
  await skuGen.init();

  // Generate or get an existing SKU
  const sku = await skuGen.getOrCreateSKU({
    manufacturerName: "Apple",
    manufacturerPartNumber: "M1Chip",
    category: "Laptop",
    subcategory: "MacBook",
  });

  console.log("Generated or retrieved SKU:", sku);

  // Close the connection when done
  await skuGen.close();
})();
```

### Multiple Calls Example

If you have to process many items, you can do something like:

```ts
import { SKUGenerator } from "@nishanprime/sku-generator";

(async () => {
  const skuGen = new SKUGenerator({
    url: "postgres://user:password@localhost:5432/mydb",
    synchronize: false,
    logging: false,
  });

  await skuGen.init(); // connect once

  const products = [
    { manufacturerName: "Apple", manufacturerPartNumber: "M1Chip", category: "Laptop", subcategory: "MacBook" },
    { manufacturerName: "Intel", manufacturerPartNumber: "i7-12700", category: "CPU" },
    // ... potentially thousands more
  ];

  for (const product of products) {
    const sku = await skuGen.getOrCreateSKU(product);
    console.log("SKU for", product.manufacturerPartNumber, ":", sku);
  }

  await skuGen.close(); // close after all operations
})();
```

In this example, the connection is opened once (`init()`) and stays open until you explicitly `close()` it, which is important for performance when dealing with bulk operations.

---

## Methods

### `init()`

```ts
public async init(): Promise<void>;
```

Ensures the data source is initialized **exactly once**.  
- If the data source is already initialized, this does nothing.  
- Otherwise, it connects to PostgreSQL using the provided URL or the `POSTGRES_CONNECTION_STRING` environment variable.

### `getOrCreateSKU(params)`

```ts
public async getOrCreateSKU(params: SKUParams): Promise<string>;
```

- **Params**:
  ```ts
  interface SKUParams {
    manufacturerName: string;
    manufacturerPartNumber: string;
    category: string;
    subcategory?: string;
  }
  ```
- **Behavior**:
  1. Checks if a row with the same `manufacturerName` and `manufacturerPartNumber` already exists.
  2. If it does, returns the existing `sku`.
  3. If not, generates a new SKU (e.g., `A5<6-digit-random><first-letter-of-category><first-letter-of-subcategory-or-second-letter-of-category>`) and inserts a new row into the DB.
  4. Returns the newly created SKU string.

### `close()`

```ts
public async close(): Promise<void>;
```

- Closes the database connection (destroying the TypeORM data source).  
- Once closed, you can re-init if needed, but typically you close just before your application ends or if you no longer need SKU operations.

---

## Environment Variables

- **`POSTGRES_CONNECTION_STRING`**: If you do not pass a `url` in the constructor, this library will attempt to use `process.env.POSTGRES_CONNECTION_STRING`.  
  - For example:  
    ```bash
    export POSTGRES_CONNECTION_STRING="postgres://user:pass@localhost:5432/dbname"
    ```
- You can also configure the pool and logging behavior via constructor options or by editing your environment variables. However, the library as shown expects direct constructor options for advanced settings.

---

## License

[MIT](./LICENSE)  
Feel free to modify, distribute, and use this library in your own projects under the terms of the MIT license.
```