# A.Team prisma library

- This package contains a shared Prisma schema, organized into [multiple files](https://www.prisma.io/blog/organize-your-prisma-schema-with-multi-file-support), to be used across multiple repositories/projects. 
- By centralizing the schema definitions, we ensure consistency and reduce duplication of effort:
    - **Consistency**: We are targeting the same MongoDB database. If we use different schema definition files, there's a risk of having inconsistent model definitions, which could lead to conflicts and data overrides.
    - **Efficiency**: A single schema definition can reduce redundant work. Currently, the schema file has over 300 lines, and this could easily grow to 1000+ lines as we onboard more collections. By working collaboratively on a single schema definition, we can streamline our efforts and improve the overall quality.

### Installation

- To install this package, add the following optional dependencies (where `X.Y.Z` represents the version):

```json
"optionalDependencies": {
    "@a_team/prisma-win": "npm:@a_team/prisma@X.Y.Z-win",
    "@a_team/prisma-macos": "npm:@a_team/prisma@X.Y.Z-macos",
    "@a_team/prisma-linux": "npm:@a_team/prisma@X.Y.Z-linux",
    "@a_team/prisma-linux-debian": "npm:@a_team/prisma@X.Y.Z-linux-debian"
}
```

- Add the following script as `postinstall` & change per need in your service:

```javascript
const fs = require('fs');
const path = require('path');

const getLinuxDistribution = () => {
  try {
    const osRelease = fs.readFileSync('/etc/os-release', 'utf-8');
    const match = osRelease.match(/^ID=(.+)$/m);
    return match ? match[1].replace(/"/g, '') : 'unknown';
  } catch (error) {
    console.error('Failed to detect Linux distribution:', error.message);
    return 'unknown';
  }
};

const getPlatformPackage = () => {
  switch (process.platform) {
    case 'darwin':
      return '@a_team/prisma-macos';
    case 'win32':
      return '@a_team/prisma-win';
    default:
      const linuxDistro = getLinuxDistribution();

      if (linuxDistro === 'debian') {
        return '@a_team/prisma-linux-debian';
      }

      return '@a_team/prisma-linux';
  }
};

const platformPackage = getPlatformPackage();
const nodeModulesPath = path.join(__dirname, '..', 'node_modules');
const sourcePath = path.join(nodeModulesPath, platformPackage);
const targetPath = path.join(nodeModulesPath, '@a_team/prisma');

if (fs.existsSync(sourcePath)) {
  if (fs.existsSync(targetPath)) {
    fs.rmSync(targetPath, { recursive: true, force: true });
  }

  fs.renameSync(sourcePath, targetPath);
  console.log(`Renamed ${platformPackage} to @a_team/prisma`);
} else {
  console.error(`Platform-specific package ${platformPackage} not found`);
  process.exit(1);
}
```

- The script above will link the required OS dependency as the main one.

### Usage

- To use the library:

```typescript
import { ATeamPrismaClient } from '@a_team/prisma';

export class DbClient extends ATeamPrismaClient {
  constructor(connectionUrl: string) {
    super(connectionUrl);
  }

  async onModuleInit() {
    await this.connect();
  }

  async onModuleDestroy() {
    await this.disconnect();
  }
}
```

### Playground

- The playground is a dedicated space where you can test and experiment with the prisma client and schema. 
- It contains various scripts that demonstrate how to interact with your database models.
- Before running any playground scripts, make sure to set up your environment variables. First, copy the `.env.sample` file to `.env`:

```sh
cp .env.sample .env
```

- Then, fill in the required environment variables in the `.env` file.
- To run a playground script, use the following command:

```sh
npx ts-node playground/missionSpec.ts
```

### Deployment versioning

- Given a version pattern `MAJOR.MINOR.PATCH`, incrementing and releasing should be done as:
  - `MAJOR` version must be increased when incompatible service/code changes are made,
  - `MINOR` version must be increased when functionality in a backwards-compatible manner is made,
  - `PATCH` version must be increased when backwards-compatible bug fixes (for existing features) are made.

### Publishing a new version

- Pull the latest changes on the `main` branch and push the following tag to the repository:

  ```bash
  git tag v<major>.<minor>.<patch> # matches v0.0.1
  git push origin tag v<major>.<minor>.<patch> # runs the publishing process
  ```

- This tag creates the new package versions needed and pushes them towards the npm repository,
- A `release` on the `github` repository is generated,
- A slack notification is sent to the required channel with the release changes.
