diff --git a/products/04-lightweight-idp/.gitea/workflows/ci.yml b/products/04-lightweight-idp/.gitea/workflows/ci.yml new file mode 100644 index 0000000..b2d8095 --- /dev/null +++ b/products/04-lightweight-idp/.gitea/workflows/ci.yml @@ -0,0 +1,27 @@ +name: CI +on: + push: + branches: [main] + pull_request: + +jobs: + test: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + + - uses: actions/setup-node@v4 + with: + node-version: '22' + + - name: Install deps + run: npm ci + working-directory: products/04-lightweight-idp + + - name: Type check + run: npx tsc --noEmit + working-directory: products/04-lightweight-idp + + - name: Test + run: npm test + working-directory: products/04-lightweight-idp diff --git a/products/04-lightweight-idp/tsconfig.json b/products/04-lightweight-idp/tsconfig.json new file mode 100644 index 0000000..7e2ce72 --- /dev/null +++ b/products/04-lightweight-idp/tsconfig.json @@ -0,0 +1,18 @@ +{ + "compilerOptions": { + "target": "ES2022", + "module": "NodeNext", + "moduleResolution": "NodeNext", + "outDir": "dist", + "rootDir": "src", + "strict": true, + "esModuleInterop": true, + "skipLibCheck": true, + "forceConsistentCasingInFileNames": true, + "resolveJsonModule": true, + "declaration": true, + "sourceMap": true + }, + "include": ["src"], + "exclude": ["node_modules", "dist", "tests"] +} diff --git a/products/05-aws-cost-anomaly/.gitea/workflows/ci.yml b/products/05-aws-cost-anomaly/.gitea/workflows/ci.yml new file mode 100644 index 0000000..ee13a05 --- /dev/null +++ b/products/05-aws-cost-anomaly/.gitea/workflows/ci.yml @@ -0,0 +1,27 @@ +name: CI +on: + push: + branches: [main] + pull_request: + +jobs: + test: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + + - uses: actions/setup-node@v4 + with: + node-version: '22' + + - name: Install deps + run: npm ci + working-directory: products/05-aws-cost-anomaly + + - name: Type check + run: npx tsc --noEmit + working-directory: products/05-aws-cost-anomaly + + - name: Test + run: npm test + working-directory: products/05-aws-cost-anomaly diff --git a/products/05-aws-cost-anomaly/tsconfig.json b/products/05-aws-cost-anomaly/tsconfig.json new file mode 100644 index 0000000..7e2ce72 --- /dev/null +++ b/products/05-aws-cost-anomaly/tsconfig.json @@ -0,0 +1,18 @@ +{ + "compilerOptions": { + "target": "ES2022", + "module": "NodeNext", + "moduleResolution": "NodeNext", + "outDir": "dist", + "rootDir": "src", + "strict": true, + "esModuleInterop": true, + "skipLibCheck": true, + "forceConsistentCasingInFileNames": true, + "resolveJsonModule": true, + "declaration": true, + "sourceMap": true + }, + "include": ["src"], + "exclude": ["node_modules", "dist", "tests"] +} diff --git a/products/06-runbook-automation/saas/src/data/db.ts b/products/06-runbook-automation/saas/src/data/db.ts new file mode 100644 index 0000000..85cd7f5 --- /dev/null +++ b/products/06-runbook-automation/saas/src/data/db.ts @@ -0,0 +1,24 @@ +import pg from 'pg'; +import pino from 'pino'; +import { config } from '../config/index.js'; + +const logger = pino({ name: 'data' }); + +export const pool = new pg.Pool({ connectionString: config.DATABASE_URL }); + +export async function withTenant(tenantId: string, fn: (client: pg.PoolClient) => Promise): Promise { + const client = await pool.connect(); + try { + await client.query('BEGIN'); + await client.query(`SET LOCAL app.tenant_id = '${tenantId}'`); + const result = await fn(client); + await client.query('COMMIT'); + return result; + } catch (err) { + await client.query('ROLLBACK'); + throw err; + } finally { + await client.query('RESET app.tenant_id'); + client.release(); + } +}