diff --git a/docker-compose.yml b/docker-compose.yml index adbcb27..c7d403c 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -1,96 +1,98 @@ version: '3.8' services: - # Databases - order-db: - image: postgres:15-alpine - environment: - POSTGRES_USER: user - POSTGRES_PASSWORD: password - POSTGRES_DB: order_db + api-gateway: + build: ./services/api-gateway ports: - - "5432:5432" - networks: - - valerix-net - - inventory-db: - image: postgres:15-alpine + - "8080:8080" environment: - POSTGRES_USER: user - POSTGRES_PASSWORD: password - POSTGRES_DB: inventory_db - ports: - - "5433:5432" - networks: - - valerix-net + - PORT=8080 + - ORDER_SERVICE_URL=http://order-service:3001 + - INVENTORY_SERVICE_URL=http://inventory-service:3002 + depends_on: + - order-service + - inventory-service + restart: always - # Services order-service: - build: ./order-service - environment: - DATABASE_URL: postgresql://user:password@order-db:5432/order_db - INVENTORY_SERVICE_URL: http://inventory-service:3001 - PORT: 3002 + build: ./services/order-service ports: - - "3002:3002" + - "3001:3001" + environment: + - PORT=3001 + - DATABASE_URL=postgresql://user:password@order-db:5432/orderdb + - INVENTORY_SERVICE_URL=http://inventory-service:3002 depends_on: - order-db - - inventory-service - networks: - - valerix-net + command: sh -c "bunx prisma db push && bun dist/index.js" + restart: always inventory-service: - build: ./inventory-service - environment: - DATABASE_URL: postgresql://user:password@inventory-db:5432/inventory_db - PORT: 3001 + build: ./services/inventory-service ports: - - "3001:3001" + - "3002:3002" + environment: + - PORT=3002 + - DATABASE_URL=postgresql://user:password@inventory-db:5432/inventorydb depends_on: - inventory-db - networks: - - valerix-net + command: sh -c "bunx prisma db push && bun dist/index.js" + restart: always -# # Monitoring -# prometheus: -# image: prom/prometheus:latest -# volumes: -# - ./prometheus/prometheus.yml:/etc/prometheus/prometheus.yml -# ports: -# - "9090:9090" -# networks: -# - valerix-net + frontend: + build: ./services/frontend + ports: + - "5173:5173" + environment: + - VITE_ORDER_SERVICE_URL=http://localhost:3001 + - VITE_INVENTORY_SERVICE_URL=http://localhost:3002 + depends_on: + - order-service + - inventory-service + + order-db: + image: postgres:14-alpine + environment: + - POSTGRES_USER=user + - POSTGRES_PASSWORD=password + - POSTGRES_DB=orderdb + volumes: + - order-db-data:/var/lib/postgresql/data + ports: + - "5434:5432" -# grafana: -# image: grafana/grafana:latest -# ports: -# - "3000:3000" -# environment: -# - GF_SECURITY_ADMIN_PASSWORD=admin -# volumes: -# - ./grafana/provisioning:/etc/grafana/provisioning -# networks: -# - valerix-net + inventory-db: + image: postgres:14-alpine + environment: + - POSTGRES_USER=user + - POSTGRES_PASSWORD=password + - POSTGRES_DB=inventorydb + volumes: + - inventory-db-data:/var/lib/postgresql/data + ports: + - "5435:5432" + + prometheus: + image: prom/prometheus + volumes: + - ./monitoring/prometheus/prometheus.yml:/etc/prometheus/prometheus.yml + ports: + - "9090:9090" -# # Frontend (Vite Dev Server) -# # Keeping it simple for dev: bind mount source and run dev -# # Note: Requires 'frontend' folder to exist and have package.json -# # We will generate frontend next. -# frontend: -# image: node:18-alpine -# working_dir: /app -# volumes: -# - ./frontend:/app -# - /app/node_modules -# command: sh -c "npm install && npm run dev -- --host" -# ports: -# - "5173:5173" -# environment: -# - VITE_ORDER_API=http://localhost:3002 -# - VITE_INVENTORY_API=http://localhost:3001 -# networks: -# - valerix-net + grafana: + image: grafana/grafana + ports: + - "3003:3000" + environment: + - GF_SECURITY_ADMIN_PASSWORD=admin + depends_on: + - prometheus + volumes: + - grafana-storage:/var/lib/grafana + - ./monitoring/grafana/provisioning:/etc/grafana/provisioning + - ./monitoring/grafana/dashboards:/var/lib/grafana/my_dashboards -networks: - valerix-net: - driver: bridge +volumes: + order-db-data: + inventory-db-data: + grafana-storage: diff --git a/monitoring/grafana/dashboards/valerix.json b/monitoring/grafana/dashboards/valerix.json new file mode 100644 index 0000000..17da403 --- /dev/null +++ b/monitoring/grafana/dashboards/valerix.json @@ -0,0 +1,84 @@ +{ + "annotations": { + "list": [] + }, + "editable": true, + "gnetId": null, + "graphTooltip": 0, + "id": null, + "links": [], + "panels": [ + { + "datasource": "Prometheus", + "fieldConfig": { + "defaults": { + "color": { + "mode": "thresholds" + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 1 + } + ] + }, + "unit": "s" + }, + "overrides": [] + }, + "gridPos": { + "h": 9, + "w": 12, + "x": 0, + "y": 0 + }, + "id": 2, + "options": { + "colorMode": "background", + "graphMode": "area", + "justifyMode": "auto", + "orientation": "auto", + "reduceOptions": { + "calcs": [ + "lastNotNull" + ], + "fields": "", + "values": false + }, + "textMode": "auto" + }, + "pluginVersion": "8.3.3", + "targets": [ + { + "expr": "rate(http_request_duration_seconds_sum{job=\"order-service\"}[30s]) / rate(http_request_duration_seconds_count{job=\"order-service\"}[30s])", + "refId": "A" + } + ], + "title": "Order Service Latency (30s Avg)", + "type": "stat" + } + ], + "schemaVersion": 34, + "style": "dark", + "tags": [], + "templating": { + "list": [] + }, + "time": { + "from": "now-5m", + "to": "now" + }, + "timepicker": {}, + "timezone": "", + "title": "Valerix Dashboard", + "uid": "valerix-main", + "version": 1, + "weekStart": "" +} \ No newline at end of file diff --git a/monitoring/grafana/provisioning/dashboards/dashboard.yml b/monitoring/grafana/provisioning/dashboards/dashboard.yml new file mode 100644 index 0000000..d53a8a0 --- /dev/null +++ b/monitoring/grafana/provisioning/dashboards/dashboard.yml @@ -0,0 +1,11 @@ +apiVersion: 1 + +providers: + - name: 'Default' + orgId: 1 + folder: '' + type: file + disableDeletion: false + editable: true + options: + path: /var/lib/grafana/my_dashboards diff --git a/monitoring/grafana/provisioning/datasources/datasource.yml b/monitoring/grafana/provisioning/datasources/datasource.yml new file mode 100644 index 0000000..86fd346 --- /dev/null +++ b/monitoring/grafana/provisioning/datasources/datasource.yml @@ -0,0 +1,8 @@ +apiVersion: 1 + +datasources: + - name: Prometheus + type: prometheus + access: proxy + url: http://prometheus:9090 + isDefault: true diff --git a/monitoring/prometheus/prometheus.yml b/monitoring/prometheus/prometheus.yml new file mode 100644 index 0000000..0bcb532 --- /dev/null +++ b/monitoring/prometheus/prometheus.yml @@ -0,0 +1,11 @@ +global: + scrape_interval: 5s + +scrape_configs: + - job_name: 'order-service' + static_configs: + - targets: ['order-service:3001'] + + - job_name: 'inventory-service' + static_configs: + - targets: ['inventory-service:3002'] diff --git a/services/api-gateway/.gitignore b/services/api-gateway/.gitignore index a14702c..3c3629e 100644 --- a/services/api-gateway/.gitignore +++ b/services/api-gateway/.gitignore @@ -1,34 +1 @@ -# dependencies (bun install) node_modules - -# output -out -dist -*.tgz - -# code coverage -coverage -*.lcov - -# logs -logs -_.log -report.[0-9]_.[0-9]_.[0-9]_.[0-9]_.json - -# dotenv environment variable files -.env -.env.development.local -.env.test.local -.env.production.local -.env.local - -# caches -.eslintcache -.cache -*.tsbuildinfo - -# IntelliJ based IDEs -.idea - -# Finder (MacOS) folder config -.DS_Store diff --git a/services/api-gateway/Dockerfile b/services/api-gateway/Dockerfile index e39fe79..32b734d 100644 --- a/services/api-gateway/Dockerfile +++ b/services/api-gateway/Dockerfile @@ -2,11 +2,14 @@ FROM oven/bun:latest WORKDIR /app -COPY package*.json ./ +COPY package.json ./ + RUN bun install -COPY src ./src -COPY tsconfig.json ./ +COPY . . + +RUN bun run build + +EXPOSE 8080 -EXPOSE 3000 -CMD ["bun", "run", "src/app.ts"] +CMD ["bun", "dist/index.js"] diff --git a/services/api-gateway/package.json b/services/api-gateway/package.json index 8041f11..6ce7751 100644 --- a/services/api-gateway/package.json +++ b/services/api-gateway/package.json @@ -1,12 +1,24 @@ { - "name": "api-gateway", - "module": "index.ts", - "type": "module", - "private": true, - "devDependencies": { - "@types/bun": "latest" - }, - "peerDependencies": { - "typescript": "^5" - } + "name": "api-gateway", + "version": "1.0.0", + "description": "API Gateway", + "main": "dist/index.js", + "scripts": { + "start": "bun dist/index.js", + "dev": "bun --watch src/index.ts", + "build": "bun build ./src/index.ts --outdir ./dist --target node" + }, + "dependencies": { + "express": "^4.18.2", + "http-proxy-middleware": "^2.0.6", + "cors": "^2.8.5", + "dotenv": "^16.4.5" + }, + "devDependencies": { + "typescript": "^5.3.3", + "@types/node": "^20.11.20", + "@types/express": "^4.17.21", + "@types/cors": "^2.8.17", + "@types/http-proxy-middleware": "^1.0.0" + } } diff --git a/services/api-gateway/src/index.ts b/services/api-gateway/src/index.ts new file mode 100644 index 0000000..20e7f04 --- /dev/null +++ b/services/api-gateway/src/index.ts @@ -0,0 +1,77 @@ +import express from 'express'; +import cors from 'cors'; +import { createProxyMiddleware } from 'http-proxy-middleware'; + +const app = express(); +const PORT = process.env.PORT || 8080; + +const ORDER_SERVICE_URL = process.env.ORDER_SERVICE_URL || 'http://localhost:3001'; +const INVENTORY_SERVICE_URL = process.env.INVENTORY_SERVICE_URL || 'http://localhost:3002'; + +app.use(cors()); + +// Proxy Options +const proxyOptions = { + changeOrigin: true, + pathRewrite: { + '^/api/orders': '/orders', + '^/api/products': '/products', + '^/api/inventory': '/inventory', + }, +}; + +// Routes +// Forward /api/orders to Order Service +app.use('/api/orders', createProxyMiddleware({ + target: ORDER_SERVICE_URL, + changeOrigin: true, + pathRewrite: { '^/api/orders': '/orders' } +})); + +// Forward /api/products to Inventory Service +app.use('/api/products', createProxyMiddleware({ + target: INVENTORY_SERVICE_URL, + changeOrigin: true, + pathRewrite: { '^/api/products': '/products' } +})); + +// Forward /api/inventory/deduct to Inventory Service (if needed directly) +app.use('/api/inventory', createProxyMiddleware({ + target: INVENTORY_SERVICE_URL, + changeOrigin: true, + pathRewrite: { '^/api/inventory': '/inventory' } +})); + +// Service Health Checks +app.use('/api/health/orders', createProxyMiddleware({ + target: ORDER_SERVICE_URL, + changeOrigin: true, + pathRewrite: { '^/api/health/orders': '/health' } +})); + +app.use('/api/health/inventory', createProxyMiddleware({ + target: INVENTORY_SERVICE_URL, + changeOrigin: true, + pathRewrite: { '^/api/health/inventory': '/health' } +})); + +// Service Metrics +app.use('/api/metrics/orders', createProxyMiddleware({ + target: ORDER_SERVICE_URL, + changeOrigin: true, + pathRewrite: { '^/api/metrics/orders': '/metrics' } +})); + +app.use('/api/metrics/inventory', createProxyMiddleware({ + target: INVENTORY_SERVICE_URL, + changeOrigin: true, + pathRewrite: { '^/api/metrics/inventory': '/metrics' } +})); + +app.get('/health', (req, res) => { + res.json({ status: 'API Gateway UP' }); +}); + +app.listen(PORT, () => { + console.log(`API Gateway running on port ${PORT}`); +}); diff --git a/services/frontend/.dockerignore b/services/frontend/.dockerignore new file mode 100644 index 0000000..01b8e10 --- /dev/null +++ b/services/frontend/.dockerignore @@ -0,0 +1,5 @@ +node_modules +dist +.git +.DS_Store +*.log diff --git a/services/frontend/.gitignore b/services/frontend/.gitignore new file mode 100644 index 0000000..b512c09 --- /dev/null +++ b/services/frontend/.gitignore @@ -0,0 +1 @@ +node_modules \ No newline at end of file diff --git a/services/frontend/Dockerfile b/services/frontend/Dockerfile new file mode 100644 index 0000000..e52e14a --- /dev/null +++ b/services/frontend/Dockerfile @@ -0,0 +1,13 @@ +FROM oven/bun:latest + +WORKDIR /app + +COPY package.json ./ + +RUN bun install + +COPY . . + +EXPOSE 5173 + +CMD ["bun", "run", "dev"] diff --git a/services/frontend/index.html b/services/frontend/index.html new file mode 100644 index 0000000..0960e2f --- /dev/null +++ b/services/frontend/index.html @@ -0,0 +1,12 @@ + + + + + + Valerix Resilient E-Commerce + + +
+ + + diff --git a/services/frontend/package.json b/services/frontend/package.json new file mode 100644 index 0000000..ecc213f --- /dev/null +++ b/services/frontend/package.json @@ -0,0 +1,23 @@ +{ + "name": "frontend", + "private": true, + "version": "0.0.0", + "type": "module", + "scripts": { + "dev": "vite", + "build": "tsc -b && vite build", + "preview": "vite preview" + }, + "dependencies": { + "react": "^18.2.0", + "react-dom": "^18.2.0", + "axios": "^1.6.7" + }, + "devDependencies": { + "@types/react": "^18.2.66", + "@types/react-dom": "^18.2.22", + "@vitejs/plugin-react": "^4.2.1", + "typescript": "^5.2.2", + "vite": "^5.2.0" + } +} \ No newline at end of file diff --git a/services/frontend/src/App.tsx b/services/frontend/src/App.tsx new file mode 100644 index 0000000..414b455 --- /dev/null +++ b/services/frontend/src/App.tsx @@ -0,0 +1,158 @@ +import { useState, useEffect } from 'react' +import axios from 'axios' +import './index.css' + +const ORDER_SERVICE_URL = import.meta.env.VITE_ORDER_SERVICE_URL || 'http://localhost:3001'; +const INVENTORY_SERVICE_URL = import.meta.env.VITE_INVENTORY_SERVICE_URL || 'http://localhost:3002'; + +interface Product { + id: string; + name: string; + stock: number; +} + +function App() { + const [loading, setLoading] = useState(false); + const [products, setProducts] = useState([]); + const [selectedProduct, setSelectedProduct] = useState(''); + const [logs, setLogs] = useState([]); + const [latency, setLatency] = useState(null); + const [health, setHealth] = useState<{ order: string }>({ order: 'CHECKING' }); + + const addLog = (msg: string) => setLogs(prev => [`[${new Date().toLocaleTimeString()}] ${msg}`, ...prev]); + + const checkHealth = async () => { + try { + await axios.get(`${ORDER_SERVICE_URL}/health`); + setHealth({ order: 'UP' }); + } catch (e) { + setHealth({ order: 'DOWN' }); + } + }; + + const fetchProducts = async () => { + try { + const res = await axios.get(`${INVENTORY_SERVICE_URL}/products`); + setProducts(res.data); + if (res.data.length > 0 && !selectedProduct) { + setSelectedProduct(res.data[0].id); + } + } catch (e) { + addLog(`⚠️ Failed to fetch products: ${e}`); + } + }; + + useEffect(() => { + checkHealth(); + fetchProducts(); + const interval = setInterval(() => { + checkHealth(); + fetchProducts(); // Refresh stock levels + }, 5000); + return () => clearInterval(interval); + }, []); + + const placeOrder = async (isGremlin: boolean) => { + if (!selectedProduct) { + addLog("⚠️ No product selected!"); + return; + } + + setLoading(true); + const start = performance.now(); + addLog(`Initiating Order... (Product: ${products.find(p => p.id === selectedProduct)?.name}, Gremlin: ${isGremlin ? 'ON' : 'OFF'})`); + + try { + // Use quantity=13 to trigger Gremlin Latency in Inventory Service + const quantity = isGremlin ? 3 : 1; + const response = await axios.post(`${ORDER_SERVICE_URL}/orders`, { + productId: selectedProduct, + quantity + }); + + const end = performance.now(); + const dur = Math.round(end - start); + setLatency(dur); + addLog(`✅ Order Success! ID: ${response.data.id}. Duration: ${dur}ms`); + fetchProducts(); // Update stock immediately + + } catch (error: any) { + const end = performance.now(); + const dur = Math.round(end - start); + setLatency(dur); + + const errMsg = error.response?.data?.error || error.message; + addLog(`❌ Order Failed: ${errMsg}. Duration: ${dur}ms`); + } finally { + setLoading(false); + } + }; + + return ( + <> +

Valerix Resilient Platform

+ +
+
+ Order Service: {health.order} +
+
+ +
+

Order Simulation

+

+ Select a product and test resilience patterns. +

+ +
+ + +
+ +
1500 ? 'var(--danger)' : 'var(--success)') : 'inherit' + }}> + {latency !== null ? `${latency}ms` : '---'} +
Last Request Latency
+
+ +
+ + +
+
+ +
+

System Logs

+ {logs.map((log, i) =>
{log}
)} +
+ + ) +} + +export default App diff --git a/services/frontend/src/index.css b/services/frontend/src/index.css new file mode 100644 index 0000000..8ea1683 --- /dev/null +++ b/services/frontend/src/index.css @@ -0,0 +1,94 @@ +:root { + --bg-color: #0d1117; + --text-color: #e6edf3; + --card-bg: #161b22; + --primary: #238636; + --danger: #da3633; + --warning: #d29922; + --success: #238636; + --border: #30363d; + font-family: 'Inter', system-ui, sans-serif; +} + +body { + margin: 0; + display: flex; + place-items: center; + min-width: 320px; + min-height: 100vh; + background-color: var(--bg-color); + color: var(--text-color); + line-height: 1.6; +} + +#root { + max-width: 1280px; + margin: 0 auto; + padding: 2rem; + text-align: center; + width: 100%; +} + +h1 { + font-size: 3.2em; + line-height: 1.1; + background: linear-gradient(90deg, #58a6ff, #a371f7); + -webkit-background-clip: text; + -webkit-text-fill-color: transparent; + margin-bottom: 2rem; +} + +.card { + background-color: var(--card-bg); + padding: 2em; + border-radius: 12px; + border: 1px solid var(--border); + margin-top: 2rem; + box-shadow: 0 4px 6px rgba(0,0,0,0.3); +} + +button { + border-radius: 8px; + border: 1px solid transparent; + padding: 0.6em 1.2em; + font-size: 1em; + font-weight: 500; + font-family: inherit; + background-color: var(--primary); + color: white; + cursor: pointer; + transition: border-color 0.25s; + margin: 0.5rem; +} + +button:hover { + filter: brightness(1.1); +} + +button.danger { + background-color: var(--danger); +} + +.status-badge { + display: inline-block; + padding: 0.2em 0.8em; + border-radius: 4px; + font-weight: bold; + font-size: 0.8em; + text-transform: uppercase; +} + +.PENDING { background-color: var(--warning); color: black; } +.CONFIRMED { background-color: var(--success); color: white; } +.FAILED { background-color: var(--danger); color: white; } + +.log-container { + text-align: left; + max-height: 300px; + overflow-y: auto; + background: #000; + padding: 1rem; + border-radius: 8px; + font-family: monospace; + margin-top: 2rem; +} diff --git a/services/frontend/src/main.tsx b/services/frontend/src/main.tsx new file mode 100644 index 0000000..379df97 --- /dev/null +++ b/services/frontend/src/main.tsx @@ -0,0 +1,10 @@ +import React from 'react' +import ReactDOM from 'react-dom/client' +import App from './App.tsx' +import './index.css' + +ReactDOM.createRoot(document.getElementById('root')!).render( + + + , +) diff --git a/services/frontend/tsconfig.json b/services/frontend/tsconfig.json new file mode 100644 index 0000000..fccecc6 --- /dev/null +++ b/services/frontend/tsconfig.json @@ -0,0 +1,26 @@ +{ + "compilerOptions": { + "target": "ES2020", + "useDefineForClassFields": true, + "lib": [ + "ES2020", + "DOM", + "DOM.Iterable" + ], + "module": "ESNext", + "skipLibCheck": true, + "moduleResolution": "bundler", + "allowImportingTsExtensions": true, + "resolveJsonModule": true, + "isolatedModules": true, + "noEmit": true, + "jsx": "react-jsx", + "strict": true, + "noUnusedLocals": true, + "noUnusedParameters": true, + "noFallthroughCasesInSwitch": true + }, + "include": [ + "src" + ] +} \ No newline at end of file diff --git a/services/frontend/vite.config.ts b/services/frontend/vite.config.ts new file mode 100644 index 0000000..16afe49 --- /dev/null +++ b/services/frontend/vite.config.ts @@ -0,0 +1,11 @@ +import { defineConfig } from 'vite' +import react from '@vitejs/plugin-react' + +// https://vitejs.dev/config/ +export default defineConfig({ + plugins: [react()], + server: { + host: true, + port: 5173 + } +}) diff --git a/services/inventory-service/Dockerfile b/services/inventory-service/Dockerfile index 5f081f9..97a9bac 100644 --- a/services/inventory-service/Dockerfile +++ b/services/inventory-service/Dockerfile @@ -3,19 +3,17 @@ FROM oven/bun:latest WORKDIR /app COPY package.json ./ -COPY bun.lock ./ - -COPY package.json ./ - -COPY package.json bun.lock* ./ RUN bun install -# COPY prisma ./prisma -# RUN bunx prisma generate +COPY prisma ./prisma +RUN bunx prisma generate -COPY src ./src COPY tsconfig.json ./ +COPY src ./src + +RUN bun run build + +EXPOSE 3002 -EXPOSE 3000 -CMD ["bun", "run", "src/app.ts"] +CMD ["bun", "dist/index.js"] diff --git a/services/inventory-service/package.json b/services/inventory-service/package.json index 2a0a675..a682502 100644 --- a/services/inventory-service/package.json +++ b/services/inventory-service/package.json @@ -1,18 +1,28 @@ { "name": "inventory-service", - "module": "index.ts", - "type": "module", - "private": true, - "devDependencies": { - "@types/bun": "latest", - "prisma": "^7.3.0" - }, - "peerDependencies": { - "typescript": "^5" + "version": "1.0.0", + "description": "Inventory Service", + "main": "dist/index.js", + "scripts": { + "start": "bun dist/index.js", + "dev": "bun --watch src/index.ts", + "build": "bun build ./src/index.ts --outdir ./dist --target node", + "prisma:generate": "bunx prisma generate", + "prisma:migrate": "bunx prisma migrate deploy" }, "dependencies": { - "@prisma/adapter-pg": "^7.3.0", - "@prisma/client": "^7.3.0", - "pg": "^8.17.2" + "express": "^4.18.2", + "prisma": "^5.10.2", + "@prisma/client": "^5.10.2", + "cors": "^2.8.5", + "prom-client": "^15.1.0", + "dotenv": "^16.4.5" + }, + "devDependencies": { + "typescript": "^5.3.3", + "@types/node": "^20.11.20", + "@types/express": "^4.17.21", + "@types/cors": "^2.8.17", + "ts-node-dev": "^2.0.0" } -} +} \ No newline at end of file diff --git a/services/inventory-service/prisma/schema.prisma b/services/inventory-service/prisma/schema.prisma index f51cc2c..e3bec11 100644 --- a/services/inventory-service/prisma/schema.prisma +++ b/services/inventory-service/prisma/schema.prisma @@ -1,14 +1,19 @@ -// This is your Prisma schema file, -// learn more about it in the docs: https://pris.ly/d/prisma-schema - -// Looking for ways to speed up your queries, or scale easily with your serverless or edge functions? -// Try Prisma Accelerate: https://pris.ly/cli/accelerate-init - generator client { - provider = "prisma-client" - output = "../src/generated/prisma" + provider = "prisma-client-js" } datasource db { provider = "postgresql" + url = env("DATABASE_URL") +} + +model Product { + id String @id @default(uuid()) + name String + stock Int +} + +model IdempotencyLog { + orderId String @id + createdAt DateTime @default(now()) } diff --git a/services/inventory-service/src/index.ts b/services/inventory-service/src/index.ts new file mode 100644 index 0000000..3ac8ecc --- /dev/null +++ b/services/inventory-service/src/index.ts @@ -0,0 +1,130 @@ +import express, { Request, Response } from 'express'; +import { PrismaClient } from '@prisma/client'; +import cors from 'cors'; +import client from 'prom-client'; + +const app = express(); +const prisma = new PrismaClient(); +const PORT = process.env.PORT || 3002; + +app.use(cors()); +app.use(express.json()); + +// Prometheus Metrics +const register = new client.Registry(); +client.collectDefaultMetrics({ register }); +app.get('/metrics', async (req, res) => { + res.setHeader('Content-Type', register.contentType); + res.send(await register.metrics()); +}); + +// Health Check +app.get('/health', async (req, res) => { + try { + await prisma.$queryRaw`SELECT 1`; + res.status(200).json({ status: 'UP', db: 'CONNECTED' }); + } catch (error) { + res.status(503).json({ status: 'DOWN', db: 'DISCONNECTED' }); + } +}); + +// Seed Products (Internal function) +const seedProducts = async () => { + try { + const count = await prisma.product.count(); + if (count === 0) { + console.log("Seeding products..."); + await prisma.product.createMany({ + data: [ + { name: 'Quantum Processor', stock: 100 }, + { name: 'Neural Interface', stock: 50 }, + { name: 'Flux Capacitor', stock: 20 }, + { name: 'Hyperdrive Unit', stock: 10 } + ] + }); + console.log("Seeding complete."); + } + } catch (e) { + console.error("Seeding failed:", e); + } +}; + +// Seed Endpoint (Manual trigger if needed) +app.post('/seed', async (req, res) => { + await seedProducts(); + res.json({ message: 'Seeding check complete' }); +}); + +// Get all products +app.get('/products', async (req, res) => { + const products = await prisma.product.findMany({ orderBy: { name: 'asc' } }); + res.json(products); +}); + +// Deduct Inventory (with Idempotency + Gremlin Latency) +app.post('/inventory/deduct', async (req: Request, res: Response) => { + const { productId, quantity, orderId } = req.body; + + if (!productId || !quantity || !orderId) { + res.status(400).json({ error: 'Missing productId, quantity, or orderId' }); + return; + } + + try { + // 1. Check Idempotency + const existingLog = await prisma.idempotencyLog.findUnique({ + where: { orderId } + }); + + if (existingLog) { + console.log(`Idempotency check: Order ${orderId} already processed.`); + // Return previous success immediately (skip Gremlin this time?) + // If we want to simulate "Vanishing Response" persisting, we might sleep again, + // but to solve the issue, we usually return success fast on retry. + res.status(200).json({ message: 'Stock already deducted (Idempotent)', success: true }); + return; + } + + // 2. Transaction: Deduct Stock + Log Idempotency + await prisma.$transaction(async (tx) => { + const product = await tx.product.findUnique({ where: { id: productId } }); + if (!product || product.stock < quantity) { + throw new Error('Insufficient stock or product not found'); + } + + await tx.product.update({ + where: { id: productId }, + data: { stock: product.stock - quantity } + }); + + await tx.idempotencyLog.create({ + data: { orderId } + }); + }); + + // 3. Gremlin Latency (The Vanishing Response) + // Deterministic delay: response delays by 5 seconds if orderId ends with 'DELAY' or basically always to force timeout demonstration. + // The requirement says "deterministic pattern". Let's say if quantity is > 5, or just always for now to verify observability. + // Let's make it deterministic based on orderId hash/char. + // If orderId starts with 'GREMLIN', we delay. + // Or simpler: Just delay 3s (Order timeout is 2s). + // But then *all* orders fail. + // Let's only delay if the 'quantity' is 13 (unlucky number). + + if (quantity === 13) { + console.log("Gremlin Triggered: Delaying response..."); + await new Promise(resolve => setTimeout(resolve, 5000)); + } + + res.status(200).json({ message: 'Stock deducted', success: true }); + + } catch (error: any) { + console.error("Inventory Error:", error.message); + res.status(400).json({ error: error.message }); + } +}); + +app.listen(PORT, async () => { + console.log(`Inventory Service running on port ${PORT}`); + await seedProducts(); +}); diff --git a/services/inventory-service/tsconfig.json b/services/inventory-service/tsconfig.json index bfa0fea..eef0f57 100644 --- a/services/inventory-service/tsconfig.json +++ b/services/inventory-service/tsconfig.json @@ -1,29 +1,12 @@ { "compilerOptions": { - // Environment setup & latest features - "lib": ["ESNext"], - "target": "ESNext", - "module": "Preserve", - "moduleDetection": "force", - "jsx": "react-jsx", - "allowJs": true, - - // Bundler mode - "moduleResolution": "bundler", - "allowImportingTsExtensions": true, - "verbatimModuleSyntax": true, - "noEmit": true, - - // Best practices + "target": "es2016", + "module": "commonjs", + "outDir": "./dist", + "rootDir": "./src", "strict": true, + "esModuleInterop": true, "skipLibCheck": true, - "noFallthroughCasesInSwitch": true, - "noUncheckedIndexedAccess": true, - "noImplicitOverride": true, - - // Some stricter flags (disabled by default) - "noUnusedLocals": false, - "noUnusedParameters": false, - "noPropertyAccessFromIndexSignature": false + "forceConsistentCasingInFileNames": true } -} +} \ No newline at end of file diff --git a/services/order-service/.env b/services/order-service/.env new file mode 100644 index 0000000..67ff43e --- /dev/null +++ b/services/order-service/.env @@ -0,0 +1,12 @@ +# Environment variables declared in this file are NOT automatically loaded by Prisma. +# Please add `import "dotenv/config";` to your `prisma.config.ts` file, or use the Prisma CLI with Bun +# to load environment variables from .env files: https://pris.ly/prisma-config-env-vars. + +# Prisma supports the native connection string format for PostgreSQL, MySQL, SQLite, SQL Server, MongoDB and CockroachDB. +# See the documentation for all the connection string options: https://pris.ly/d/connection-strings + +# The following `prisma+postgres` URL is similar to the URL produced by running a local Prisma Postgres +# server with the `prisma dev` CLI command, when not choosing any non-default ports or settings. The API key, unlike the +# one found in a remote Prisma Postgres URL, does not contain any sensitive information. + +DATABASE_URL="postgresql://user:password@order-db:5432/order_db" \ No newline at end of file diff --git a/services/order-service/.gitignore b/services/order-service/.gitignore index 2662a3a..3c3629e 100644 --- a/services/order-service/.gitignore +++ b/services/order-service/.gitignore @@ -1,36 +1 @@ -# dependencies (bun install) node_modules - -# output -out -dist -*.tgz - -# code coverage -coverage -*.lcov - -# logs -logs -_.log -report.[0-9]_.[0-9]_.[0-9]_.[0-9]_.json - -# dotenv environment variable files -.env -.env.development.local -.env.test.local -.env.production.local -.env.local - -# caches -.eslintcache -.cache -*.tsbuildinfo - -# IntelliJ based IDEs -.idea - -# Finder (MacOS) folder config -.DS_Store - -/src/generated/prisma diff --git a/services/order-service/Dockerfile b/services/order-service/Dockerfile index 5f081f9..c12e505 100644 --- a/services/order-service/Dockerfile +++ b/services/order-service/Dockerfile @@ -3,19 +3,17 @@ FROM oven/bun:latest WORKDIR /app COPY package.json ./ -COPY bun.lock ./ - -COPY package.json ./ - -COPY package.json bun.lock* ./ RUN bun install -# COPY prisma ./prisma -# RUN bunx prisma generate +COPY prisma ./prisma +RUN bunx prisma generate -COPY src ./src COPY tsconfig.json ./ +COPY src ./src + +RUN bun run build + +EXPOSE 3001 -EXPOSE 3000 -CMD ["bun", "run", "src/app.ts"] +CMD ["bun", "dist/index.js"] diff --git a/services/order-service/package.json b/services/order-service/package.json index b525c19..c9dfa02 100644 --- a/services/order-service/package.json +++ b/services/order-service/package.json @@ -1,18 +1,29 @@ { - "name": "order-service", - "module": "index.ts", - "type": "module", - "private": true, - "devDependencies": { - "@types/bun": "latest", - "prisma": "^7.3.0" - }, - "peerDependencies": { - "typescript": "^5" - }, - "dependencies": { - "@prisma/adapter-pg": "^7.3.0", - "@prisma/client": "^7.3.0", - "pg": "^8.17.2" - } + "name": "order-service", + "version": "1.0.0", + "description": "Order Service", + "main": "dist/index.js", + "scripts": { + "start": "bun dist/index.js", + "dev": "bun --watch src/index.ts", + "build": "bun build ./src/index.ts --outdir ./dist --target node", + "prisma:generate": "bunx prisma generate", + "prisma:migrate": "bunx prisma migrate deploy" + }, + "dependencies": { + "express": "^4.18.2", + "prisma": "^5.10.2", + "@prisma/client": "^5.10.2", + "cors": "^2.8.5", + "axios": "^1.6.7", + "prom-client": "^15.1.0", + "dotenv": "^16.4.5" + }, + "devDependencies": { + "typescript": "^5.3.3", + "@types/node": "^20.11.20", + "@types/express": "^4.17.21", + "@types/cors": "^2.8.17", + "ts-node-dev": "^2.0.0" + } } diff --git a/services/order-service/prisma/schema.prisma b/services/order-service/prisma/schema.prisma index 02c3067..3eb3a06 100644 --- a/services/order-service/prisma/schema.prisma +++ b/services/order-service/prisma/schema.prisma @@ -1,23 +1,17 @@ -// This is your Prisma schema file, -// learn more about it in the docs: https://pris.ly/d/prisma-schema - -// Looking for ways to speed up your queries, or scale easily with your serverless or edge functions? -// Try Prisma Accelerate: https://pris.ly/cli/accelerate-init - generator client { - provider = "prisma-client" - output = "../src/generated/prisma" + provider = "prisma-client-js" } datasource db { provider = "postgresql" + url = env("DATABASE_URL") } model Order { id String @id @default(uuid()) - itemId Int + productId String quantity Int - status String // "PENDING", "COMPLETED", "FAILED", "TIMEOUT" + status String @default("PENDING") // PENDING, CONFIRMED, FAILED createdAt DateTime @default(now()) updatedAt DateTime @updatedAt } diff --git a/services/order-service/src/generated/prisma/browser.ts b/services/order-service/src/generated/prisma/browser.ts new file mode 100644 index 0000000..2e51b40 --- /dev/null +++ b/services/order-service/src/generated/prisma/browser.ts @@ -0,0 +1,24 @@ + +/* !!! This is code generated by Prisma. Do not edit directly. !!! */ +/* eslint-disable */ +// biome-ignore-all lint: generated file +// @ts-nocheck +/* + * This file should be your main import to use Prisma-related types and utilities in a browser. + * Use it to get access to models, enums, and input types. + * + * This file does not contain a `PrismaClient` class, nor several other helpers that are intended as server-side only. + * See `client.ts` for the standard, server-side entry point. + * + * 🟢 You can import this file directly. + */ + +import * as Prisma from './internal/prismaNamespaceBrowser.ts' +export { Prisma } +export * as $Enums from './enums.ts' +export * from './enums.ts'; +/** + * Model Order + * + */ +export type Order = Prisma.OrderModel diff --git a/services/order-service/src/generated/prisma/client.ts b/services/order-service/src/generated/prisma/client.ts new file mode 100644 index 0000000..bbcada9 --- /dev/null +++ b/services/order-service/src/generated/prisma/client.ts @@ -0,0 +1,46 @@ + +/* !!! This is code generated by Prisma. Do not edit directly. !!! */ +/* eslint-disable */ +// biome-ignore-all lint: generated file +// @ts-nocheck +/* + * This file should be your main import to use Prisma. Through it you get access to all the models, enums, and input types. + * If you're looking for something you can import in the client-side of your application, please refer to the `browser.ts` file instead. + * + * 🟢 You can import this file directly. + */ + +import * as process from 'node:process' +import * as path from 'node:path' +import { fileURLToPath } from 'node:url' +globalThis['__dirname'] = path.dirname(fileURLToPath(import.meta.url)) + +import * as runtime from "@prisma/client/runtime/client" +import * as $Enums from "./enums.ts" +import * as $Class from "./internal/class.ts" +import * as Prisma from "./internal/prismaNamespace.ts" + +export * as $Enums from './enums.ts' +export * from "./enums.ts" +/** + * ## Prisma Client + * + * Type-safe database client for TypeScript + * @example + * ``` + * const prisma = new PrismaClient() + * // Fetch zero or more Orders + * const orders = await prisma.order.findMany() + * ``` + * + * Read more in our [docs](https://pris.ly/d/client). + */ +export const PrismaClient = $Class.getPrismaClientClass() +export type PrismaClient = $Class.PrismaClient +export { Prisma } + +/** + * Model Order + * + */ +export type Order = Prisma.OrderModel diff --git a/services/order-service/src/generated/prisma/commonInputTypes.ts b/services/order-service/src/generated/prisma/commonInputTypes.ts new file mode 100644 index 0000000..68101ec --- /dev/null +++ b/services/order-service/src/generated/prisma/commonInputTypes.ts @@ -0,0 +1,196 @@ + +/* !!! This is code generated by Prisma. Do not edit directly. !!! */ +/* eslint-disable */ +// biome-ignore-all lint: generated file +// @ts-nocheck +/* + * This file exports various common sort, input & filter types that are not directly linked to a particular model. + * + * 🟢 You can import this file directly. + */ + +import type * as runtime from "@prisma/client/runtime/client" +import * as $Enums from "./enums.ts" +import type * as Prisma from "./internal/prismaNamespace.ts" + + +export type StringFilter<$PrismaModel = never> = { + equals?: string | Prisma.StringFieldRefInput<$PrismaModel> + in?: string[] | Prisma.ListStringFieldRefInput<$PrismaModel> + notIn?: string[] | Prisma.ListStringFieldRefInput<$PrismaModel> + lt?: string | Prisma.StringFieldRefInput<$PrismaModel> + lte?: string | Prisma.StringFieldRefInput<$PrismaModel> + gt?: string | Prisma.StringFieldRefInput<$PrismaModel> + gte?: string | Prisma.StringFieldRefInput<$PrismaModel> + contains?: string | Prisma.StringFieldRefInput<$PrismaModel> + startsWith?: string | Prisma.StringFieldRefInput<$PrismaModel> + endsWith?: string | Prisma.StringFieldRefInput<$PrismaModel> + mode?: Prisma.QueryMode + not?: Prisma.NestedStringFilter<$PrismaModel> | string +} + +export type IntFilter<$PrismaModel = never> = { + equals?: number | Prisma.IntFieldRefInput<$PrismaModel> + in?: number[] | Prisma.ListIntFieldRefInput<$PrismaModel> + notIn?: number[] | Prisma.ListIntFieldRefInput<$PrismaModel> + lt?: number | Prisma.IntFieldRefInput<$PrismaModel> + lte?: number | Prisma.IntFieldRefInput<$PrismaModel> + gt?: number | Prisma.IntFieldRefInput<$PrismaModel> + gte?: number | Prisma.IntFieldRefInput<$PrismaModel> + not?: Prisma.NestedIntFilter<$PrismaModel> | number +} + +export type DateTimeFilter<$PrismaModel = never> = { + equals?: Date | string | Prisma.DateTimeFieldRefInput<$PrismaModel> + in?: Date[] | string[] | Prisma.ListDateTimeFieldRefInput<$PrismaModel> + notIn?: Date[] | string[] | Prisma.ListDateTimeFieldRefInput<$PrismaModel> + lt?: Date | string | Prisma.DateTimeFieldRefInput<$PrismaModel> + lte?: Date | string | Prisma.DateTimeFieldRefInput<$PrismaModel> + gt?: Date | string | Prisma.DateTimeFieldRefInput<$PrismaModel> + gte?: Date | string | Prisma.DateTimeFieldRefInput<$PrismaModel> + not?: Prisma.NestedDateTimeFilter<$PrismaModel> | Date | string +} + +export type StringWithAggregatesFilter<$PrismaModel = never> = { + equals?: string | Prisma.StringFieldRefInput<$PrismaModel> + in?: string[] | Prisma.ListStringFieldRefInput<$PrismaModel> + notIn?: string[] | Prisma.ListStringFieldRefInput<$PrismaModel> + lt?: string | Prisma.StringFieldRefInput<$PrismaModel> + lte?: string | Prisma.StringFieldRefInput<$PrismaModel> + gt?: string | Prisma.StringFieldRefInput<$PrismaModel> + gte?: string | Prisma.StringFieldRefInput<$PrismaModel> + contains?: string | Prisma.StringFieldRefInput<$PrismaModel> + startsWith?: string | Prisma.StringFieldRefInput<$PrismaModel> + endsWith?: string | Prisma.StringFieldRefInput<$PrismaModel> + mode?: Prisma.QueryMode + not?: Prisma.NestedStringWithAggregatesFilter<$PrismaModel> | string + _count?: Prisma.NestedIntFilter<$PrismaModel> + _min?: Prisma.NestedStringFilter<$PrismaModel> + _max?: Prisma.NestedStringFilter<$PrismaModel> +} + +export type IntWithAggregatesFilter<$PrismaModel = never> = { + equals?: number | Prisma.IntFieldRefInput<$PrismaModel> + in?: number[] | Prisma.ListIntFieldRefInput<$PrismaModel> + notIn?: number[] | Prisma.ListIntFieldRefInput<$PrismaModel> + lt?: number | Prisma.IntFieldRefInput<$PrismaModel> + lte?: number | Prisma.IntFieldRefInput<$PrismaModel> + gt?: number | Prisma.IntFieldRefInput<$PrismaModel> + gte?: number | Prisma.IntFieldRefInput<$PrismaModel> + not?: Prisma.NestedIntWithAggregatesFilter<$PrismaModel> | number + _count?: Prisma.NestedIntFilter<$PrismaModel> + _avg?: Prisma.NestedFloatFilter<$PrismaModel> + _sum?: Prisma.NestedIntFilter<$PrismaModel> + _min?: Prisma.NestedIntFilter<$PrismaModel> + _max?: Prisma.NestedIntFilter<$PrismaModel> +} + +export type DateTimeWithAggregatesFilter<$PrismaModel = never> = { + equals?: Date | string | Prisma.DateTimeFieldRefInput<$PrismaModel> + in?: Date[] | string[] | Prisma.ListDateTimeFieldRefInput<$PrismaModel> + notIn?: Date[] | string[] | Prisma.ListDateTimeFieldRefInput<$PrismaModel> + lt?: Date | string | Prisma.DateTimeFieldRefInput<$PrismaModel> + lte?: Date | string | Prisma.DateTimeFieldRefInput<$PrismaModel> + gt?: Date | string | Prisma.DateTimeFieldRefInput<$PrismaModel> + gte?: Date | string | Prisma.DateTimeFieldRefInput<$PrismaModel> + not?: Prisma.NestedDateTimeWithAggregatesFilter<$PrismaModel> | Date | string + _count?: Prisma.NestedIntFilter<$PrismaModel> + _min?: Prisma.NestedDateTimeFilter<$PrismaModel> + _max?: Prisma.NestedDateTimeFilter<$PrismaModel> +} + +export type NestedStringFilter<$PrismaModel = never> = { + equals?: string | Prisma.StringFieldRefInput<$PrismaModel> + in?: string[] | Prisma.ListStringFieldRefInput<$PrismaModel> + notIn?: string[] | Prisma.ListStringFieldRefInput<$PrismaModel> + lt?: string | Prisma.StringFieldRefInput<$PrismaModel> + lte?: string | Prisma.StringFieldRefInput<$PrismaModel> + gt?: string | Prisma.StringFieldRefInput<$PrismaModel> + gte?: string | Prisma.StringFieldRefInput<$PrismaModel> + contains?: string | Prisma.StringFieldRefInput<$PrismaModel> + startsWith?: string | Prisma.StringFieldRefInput<$PrismaModel> + endsWith?: string | Prisma.StringFieldRefInput<$PrismaModel> + not?: Prisma.NestedStringFilter<$PrismaModel> | string +} + +export type NestedIntFilter<$PrismaModel = never> = { + equals?: number | Prisma.IntFieldRefInput<$PrismaModel> + in?: number[] | Prisma.ListIntFieldRefInput<$PrismaModel> + notIn?: number[] | Prisma.ListIntFieldRefInput<$PrismaModel> + lt?: number | Prisma.IntFieldRefInput<$PrismaModel> + lte?: number | Prisma.IntFieldRefInput<$PrismaModel> + gt?: number | Prisma.IntFieldRefInput<$PrismaModel> + gte?: number | Prisma.IntFieldRefInput<$PrismaModel> + not?: Prisma.NestedIntFilter<$PrismaModel> | number +} + +export type NestedDateTimeFilter<$PrismaModel = never> = { + equals?: Date | string | Prisma.DateTimeFieldRefInput<$PrismaModel> + in?: Date[] | string[] | Prisma.ListDateTimeFieldRefInput<$PrismaModel> + notIn?: Date[] | string[] | Prisma.ListDateTimeFieldRefInput<$PrismaModel> + lt?: Date | string | Prisma.DateTimeFieldRefInput<$PrismaModel> + lte?: Date | string | Prisma.DateTimeFieldRefInput<$PrismaModel> + gt?: Date | string | Prisma.DateTimeFieldRefInput<$PrismaModel> + gte?: Date | string | Prisma.DateTimeFieldRefInput<$PrismaModel> + not?: Prisma.NestedDateTimeFilter<$PrismaModel> | Date | string +} + +export type NestedStringWithAggregatesFilter<$PrismaModel = never> = { + equals?: string | Prisma.StringFieldRefInput<$PrismaModel> + in?: string[] | Prisma.ListStringFieldRefInput<$PrismaModel> + notIn?: string[] | Prisma.ListStringFieldRefInput<$PrismaModel> + lt?: string | Prisma.StringFieldRefInput<$PrismaModel> + lte?: string | Prisma.StringFieldRefInput<$PrismaModel> + gt?: string | Prisma.StringFieldRefInput<$PrismaModel> + gte?: string | Prisma.StringFieldRefInput<$PrismaModel> + contains?: string | Prisma.StringFieldRefInput<$PrismaModel> + startsWith?: string | Prisma.StringFieldRefInput<$PrismaModel> + endsWith?: string | Prisma.StringFieldRefInput<$PrismaModel> + not?: Prisma.NestedStringWithAggregatesFilter<$PrismaModel> | string + _count?: Prisma.NestedIntFilter<$PrismaModel> + _min?: Prisma.NestedStringFilter<$PrismaModel> + _max?: Prisma.NestedStringFilter<$PrismaModel> +} + +export type NestedIntWithAggregatesFilter<$PrismaModel = never> = { + equals?: number | Prisma.IntFieldRefInput<$PrismaModel> + in?: number[] | Prisma.ListIntFieldRefInput<$PrismaModel> + notIn?: number[] | Prisma.ListIntFieldRefInput<$PrismaModel> + lt?: number | Prisma.IntFieldRefInput<$PrismaModel> + lte?: number | Prisma.IntFieldRefInput<$PrismaModel> + gt?: number | Prisma.IntFieldRefInput<$PrismaModel> + gte?: number | Prisma.IntFieldRefInput<$PrismaModel> + not?: Prisma.NestedIntWithAggregatesFilter<$PrismaModel> | number + _count?: Prisma.NestedIntFilter<$PrismaModel> + _avg?: Prisma.NestedFloatFilter<$PrismaModel> + _sum?: Prisma.NestedIntFilter<$PrismaModel> + _min?: Prisma.NestedIntFilter<$PrismaModel> + _max?: Prisma.NestedIntFilter<$PrismaModel> +} + +export type NestedFloatFilter<$PrismaModel = never> = { + equals?: number | Prisma.FloatFieldRefInput<$PrismaModel> + in?: number[] | Prisma.ListFloatFieldRefInput<$PrismaModel> + notIn?: number[] | Prisma.ListFloatFieldRefInput<$PrismaModel> + lt?: number | Prisma.FloatFieldRefInput<$PrismaModel> + lte?: number | Prisma.FloatFieldRefInput<$PrismaModel> + gt?: number | Prisma.FloatFieldRefInput<$PrismaModel> + gte?: number | Prisma.FloatFieldRefInput<$PrismaModel> + not?: Prisma.NestedFloatFilter<$PrismaModel> | number +} + +export type NestedDateTimeWithAggregatesFilter<$PrismaModel = never> = { + equals?: Date | string | Prisma.DateTimeFieldRefInput<$PrismaModel> + in?: Date[] | string[] | Prisma.ListDateTimeFieldRefInput<$PrismaModel> + notIn?: Date[] | string[] | Prisma.ListDateTimeFieldRefInput<$PrismaModel> + lt?: Date | string | Prisma.DateTimeFieldRefInput<$PrismaModel> + lte?: Date | string | Prisma.DateTimeFieldRefInput<$PrismaModel> + gt?: Date | string | Prisma.DateTimeFieldRefInput<$PrismaModel> + gte?: Date | string | Prisma.DateTimeFieldRefInput<$PrismaModel> + not?: Prisma.NestedDateTimeWithAggregatesFilter<$PrismaModel> | Date | string + _count?: Prisma.NestedIntFilter<$PrismaModel> + _min?: Prisma.NestedDateTimeFilter<$PrismaModel> + _max?: Prisma.NestedDateTimeFilter<$PrismaModel> +} + + diff --git a/services/order-service/src/generated/prisma/enums.ts b/services/order-service/src/generated/prisma/enums.ts new file mode 100644 index 0000000..043572d --- /dev/null +++ b/services/order-service/src/generated/prisma/enums.ts @@ -0,0 +1,15 @@ + +/* !!! This is code generated by Prisma. Do not edit directly. !!! */ +/* eslint-disable */ +// biome-ignore-all lint: generated file +// @ts-nocheck +/* +* This file exports all enum related types from the schema. +* +* 🟢 You can import this file directly. +*/ + + + +// This file is empty because there are no enums in the schema. +export {} diff --git a/services/order-service/src/generated/prisma/internal/class.ts b/services/order-service/src/generated/prisma/internal/class.ts new file mode 100644 index 0000000..7588d58 --- /dev/null +++ b/services/order-service/src/generated/prisma/internal/class.ts @@ -0,0 +1,192 @@ + +/* !!! This is code generated by Prisma. Do not edit directly. !!! */ +/* eslint-disable */ +// biome-ignore-all lint: generated file +// @ts-nocheck +/* + * WARNING: This is an internal file that is subject to change! + * + * 🛑 Under no circumstances should you import this file directly! 🛑 + * + * Please import the `PrismaClient` class from the `client.ts` file instead. + */ + +import * as runtime from "@prisma/client/runtime/client" +import type * as Prisma from "./prismaNamespace.ts" + + +const config: runtime.GetPrismaClientConfig = { + "previewFeatures": [], + "clientVersion": "7.3.0", + "engineVersion": "9d6ad21cbbceab97458517b147a6a09ff43aa735", + "activeProvider": "postgresql", + "inlineSchema": "// This is your Prisma schema file,\n// learn more about it in the docs: https://pris.ly/d/prisma-schema\n\n// Looking for ways to speed up your queries, or scale easily with your serverless or edge functions?\n// Try Prisma Accelerate: https://pris.ly/cli/accelerate-init\n\ngenerator client {\n provider = \"prisma-client\"\n output = \"../src/generated/prisma\"\n}\n\ndatasource db {\n provider = \"postgresql\"\n}\n\nmodel Order {\n id String @id @default(uuid())\n itemId Int\n quantity Int\n status String // \"PENDING\", \"COMPLETED\", \"FAILED\", \"TIMEOUT\"\n createdAt DateTime @default(now())\n updatedAt DateTime @updatedAt\n}\n", + "runtimeDataModel": { + "models": {}, + "enums": {}, + "types": {} + } +} + +config.runtimeDataModel = JSON.parse("{\"models\":{\"Order\":{\"fields\":[{\"name\":\"id\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"itemId\",\"kind\":\"scalar\",\"type\":\"Int\"},{\"name\":\"quantity\",\"kind\":\"scalar\",\"type\":\"Int\"},{\"name\":\"status\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"createdAt\",\"kind\":\"scalar\",\"type\":\"DateTime\"},{\"name\":\"updatedAt\",\"kind\":\"scalar\",\"type\":\"DateTime\"}],\"dbName\":null}},\"enums\":{},\"types\":{}}") + +async function decodeBase64AsWasm(wasmBase64: string): Promise { + const { Buffer } = await import('node:buffer') + const wasmArray = Buffer.from(wasmBase64, 'base64') + return new WebAssembly.Module(wasmArray) +} + +config.compilerWasm = { + getRuntime: async () => await import("@prisma/client/runtime/query_compiler_fast_bg.postgresql.mjs"), + + getQueryCompilerWasmModule: async () => { + const { wasm } = await import("@prisma/client/runtime/query_compiler_fast_bg.postgresql.wasm-base64.mjs") + return await decodeBase64AsWasm(wasm) + }, + + importName: "./query_compiler_fast_bg.js" +} + + + +export type LogOptions = + 'log' extends keyof ClientOptions ? ClientOptions['log'] extends Array ? Prisma.GetEvents : never : never + +export interface PrismaClientConstructor { + /** + * ## Prisma Client + * + * Type-safe database client for TypeScript + * @example + * ``` + * const prisma = new PrismaClient() + * // Fetch zero or more Orders + * const orders = await prisma.order.findMany() + * ``` + * + * Read more in our [docs](https://pris.ly/d/client). + */ + + new < + Options extends Prisma.PrismaClientOptions = Prisma.PrismaClientOptions, + LogOpts extends LogOptions = LogOptions, + OmitOpts extends Prisma.PrismaClientOptions['omit'] = Options extends { omit: infer U } ? U : Prisma.PrismaClientOptions['omit'], + ExtArgs extends runtime.Types.Extensions.InternalArgs = runtime.Types.Extensions.DefaultArgs + >(options: Prisma.Subset ): PrismaClient +} + +/** + * ## Prisma Client + * + * Type-safe database client for TypeScript + * @example + * ``` + * const prisma = new PrismaClient() + * // Fetch zero or more Orders + * const orders = await prisma.order.findMany() + * ``` + * + * Read more in our [docs](https://pris.ly/d/client). + */ + +export interface PrismaClient< + in LogOpts extends Prisma.LogLevel = never, + in out OmitOpts extends Prisma.PrismaClientOptions['omit'] = undefined, + in out ExtArgs extends runtime.Types.Extensions.InternalArgs = runtime.Types.Extensions.DefaultArgs +> { + [K: symbol]: { types: Prisma.TypeMap['other'] } + + $on(eventType: V, callback: (event: V extends 'query' ? Prisma.QueryEvent : Prisma.LogEvent) => void): PrismaClient; + + /** + * Connect with the database + */ + $connect(): runtime.Types.Utils.JsPromise; + + /** + * Disconnect from the database + */ + $disconnect(): runtime.Types.Utils.JsPromise; + +/** + * Executes a prepared raw query and returns the number of affected rows. + * @example + * ``` + * const result = await prisma.$executeRaw`UPDATE User SET cool = ${true} WHERE email = ${'user@email.com'};` + * ``` + * + * Read more in our [docs](https://pris.ly/d/raw-queries). + */ + $executeRaw(query: TemplateStringsArray | Prisma.Sql, ...values: any[]): Prisma.PrismaPromise; + + /** + * Executes a raw query and returns the number of affected rows. + * Susceptible to SQL injections, see documentation. + * @example + * ``` + * const result = await prisma.$executeRawUnsafe('UPDATE User SET cool = $1 WHERE email = $2 ;', true, 'user@email.com') + * ``` + * + * Read more in our [docs](https://pris.ly/d/raw-queries). + */ + $executeRawUnsafe(query: string, ...values: any[]): Prisma.PrismaPromise; + + /** + * Performs a prepared raw query and returns the `SELECT` data. + * @example + * ``` + * const result = await prisma.$queryRaw`SELECT * FROM User WHERE id = ${1} OR email = ${'user@email.com'};` + * ``` + * + * Read more in our [docs](https://pris.ly/d/raw-queries). + */ + $queryRaw(query: TemplateStringsArray | Prisma.Sql, ...values: any[]): Prisma.PrismaPromise; + + /** + * Performs a raw query and returns the `SELECT` data. + * Susceptible to SQL injections, see documentation. + * @example + * ``` + * const result = await prisma.$queryRawUnsafe('SELECT * FROM User WHERE id = $1 OR email = $2;', 1, 'user@email.com') + * ``` + * + * Read more in our [docs](https://pris.ly/d/raw-queries). + */ + $queryRawUnsafe(query: string, ...values: any[]): Prisma.PrismaPromise; + + + /** + * Allows the running of a sequence of read/write operations that are guaranteed to either succeed or fail as a whole. + * @example + * ``` + * const [george, bob, alice] = await prisma.$transaction([ + * prisma.user.create({ data: { name: 'George' } }), + * prisma.user.create({ data: { name: 'Bob' } }), + * prisma.user.create({ data: { name: 'Alice' } }), + * ]) + * ``` + * + * Read more in our [docs](https://www.prisma.io/docs/concepts/components/prisma-client/transactions). + */ + $transaction

[]>(arg: [...P], options?: { isolationLevel?: Prisma.TransactionIsolationLevel }): runtime.Types.Utils.JsPromise> + + $transaction(fn: (prisma: Omit) => runtime.Types.Utils.JsPromise, options?: { maxWait?: number, timeout?: number, isolationLevel?: Prisma.TransactionIsolationLevel }): runtime.Types.Utils.JsPromise + + $extends: runtime.Types.Extensions.ExtendsHook<"extends", Prisma.TypeMapCb, ExtArgs, runtime.Types.Utils.Call, { + extArgs: ExtArgs + }>> + + /** + * `prisma.order`: Exposes CRUD operations for the **Order** model. + * Example usage: + * ```ts + * // Fetch zero or more Orders + * const orders = await prisma.order.findMany() + * ``` + */ + get order(): Prisma.OrderDelegate; +} + +export function getPrismaClientClass(): PrismaClientConstructor { + return runtime.getPrismaClient(config) as unknown as PrismaClientConstructor +} diff --git a/services/order-service/src/generated/prisma/internal/prismaNamespace.ts b/services/order-service/src/generated/prisma/internal/prismaNamespace.ts new file mode 100644 index 0000000..92e7829 --- /dev/null +++ b/services/order-service/src/generated/prisma/internal/prismaNamespace.ts @@ -0,0 +1,767 @@ + +/* !!! This is code generated by Prisma. Do not edit directly. !!! */ +/* eslint-disable */ +// biome-ignore-all lint: generated file +// @ts-nocheck +/* + * WARNING: This is an internal file that is subject to change! + * + * 🛑 Under no circumstances should you import this file directly! 🛑 + * + * All exports from this file are wrapped under a `Prisma` namespace object in the client.ts file. + * While this enables partial backward compatibility, it is not part of the stable public API. + * + * If you are looking for your Models, Enums, and Input Types, please import them from the respective + * model files in the `model` directory! + */ + +import * as runtime from "@prisma/client/runtime/client" +import type * as Prisma from "../models.ts" +import { type PrismaClient } from "./class.ts" + +export type * from '../models.ts' + +export type DMMF = typeof runtime.DMMF + +export type PrismaPromise = runtime.Types.Public.PrismaPromise + +/** + * Prisma Errors + */ + +export const PrismaClientKnownRequestError = runtime.PrismaClientKnownRequestError +export type PrismaClientKnownRequestError = runtime.PrismaClientKnownRequestError + +export const PrismaClientUnknownRequestError = runtime.PrismaClientUnknownRequestError +export type PrismaClientUnknownRequestError = runtime.PrismaClientUnknownRequestError + +export const PrismaClientRustPanicError = runtime.PrismaClientRustPanicError +export type PrismaClientRustPanicError = runtime.PrismaClientRustPanicError + +export const PrismaClientInitializationError = runtime.PrismaClientInitializationError +export type PrismaClientInitializationError = runtime.PrismaClientInitializationError + +export const PrismaClientValidationError = runtime.PrismaClientValidationError +export type PrismaClientValidationError = runtime.PrismaClientValidationError + +/** + * Re-export of sql-template-tag + */ +export const sql = runtime.sqltag +export const empty = runtime.empty +export const join = runtime.join +export const raw = runtime.raw +export const Sql = runtime.Sql +export type Sql = runtime.Sql + + + +/** + * Decimal.js + */ +export const Decimal = runtime.Decimal +export type Decimal = runtime.Decimal + +export type DecimalJsLike = runtime.DecimalJsLike + +/** +* Extensions +*/ +export type Extension = runtime.Types.Extensions.UserArgs +export const getExtensionContext = runtime.Extensions.getExtensionContext +export type Args = runtime.Types.Public.Args +export type Payload = runtime.Types.Public.Payload +export type Result = runtime.Types.Public.Result +export type Exact = runtime.Types.Public.Exact + +export type PrismaVersion = { + client: string + engine: string +} + +/** + * Prisma Client JS version: 7.3.0 + * Query Engine version: 9d6ad21cbbceab97458517b147a6a09ff43aa735 + */ +export const prismaVersion: PrismaVersion = { + client: "7.3.0", + engine: "9d6ad21cbbceab97458517b147a6a09ff43aa735" +} + +/** + * Utility Types + */ + +export type Bytes = runtime.Bytes +export type JsonObject = runtime.JsonObject +export type JsonArray = runtime.JsonArray +export type JsonValue = runtime.JsonValue +export type InputJsonObject = runtime.InputJsonObject +export type InputJsonArray = runtime.InputJsonArray +export type InputJsonValue = runtime.InputJsonValue + + +export const NullTypes = { + DbNull: runtime.NullTypes.DbNull as (new (secret: never) => typeof runtime.DbNull), + JsonNull: runtime.NullTypes.JsonNull as (new (secret: never) => typeof runtime.JsonNull), + AnyNull: runtime.NullTypes.AnyNull as (new (secret: never) => typeof runtime.AnyNull), +} +/** + * Helper for filtering JSON entries that have `null` on the database (empty on the db) + * + * @see https://www.prisma.io/docs/concepts/components/prisma-client/working-with-fields/working-with-json-fields#filtering-on-a-json-field + */ +export const DbNull = runtime.DbNull + +/** + * Helper for filtering JSON entries that have JSON `null` values (not empty on the db) + * + * @see https://www.prisma.io/docs/concepts/components/prisma-client/working-with-fields/working-with-json-fields#filtering-on-a-json-field + */ +export const JsonNull = runtime.JsonNull + +/** + * Helper for filtering JSON entries that are `Prisma.DbNull` or `Prisma.JsonNull` + * + * @see https://www.prisma.io/docs/concepts/components/prisma-client/working-with-fields/working-with-json-fields#filtering-on-a-json-field + */ +export const AnyNull = runtime.AnyNull + + +type SelectAndInclude = { + select: any + include: any +} + +type SelectAndOmit = { + select: any + omit: any +} + +/** + * From T, pick a set of properties whose keys are in the union K + */ +type Prisma__Pick = { + [P in K]: T[P]; +}; + +export type Enumerable = T | Array; + +/** + * Subset + * @desc From `T` pick properties that exist in `U`. Simple version of Intersection + */ +export type Subset = { + [key in keyof T]: key extends keyof U ? T[key] : never; +}; + +/** + * SelectSubset + * @desc From `T` pick properties that exist in `U`. Simple version of Intersection. + * Additionally, it validates, if both select and include are present. If the case, it errors. + */ +export type SelectSubset = { + [key in keyof T]: key extends keyof U ? T[key] : never +} & + (T extends SelectAndInclude + ? 'Please either choose `select` or `include`.' + : T extends SelectAndOmit + ? 'Please either choose `select` or `omit`.' + : {}) + +/** + * Subset + Intersection + * @desc From `T` pick properties that exist in `U` and intersect `K` + */ +export type SubsetIntersection = { + [key in keyof T]: key extends keyof U ? T[key] : never +} & + K + +type Without = { [P in Exclude]?: never }; + +/** + * XOR is needed to have a real mutually exclusive union type + * https://stackoverflow.com/questions/42123407/does-typescript-support-mutually-exclusive-types + */ +export type XOR = + T extends object ? + U extends object ? + (Without & U) | (Without & T) + : U : T + + +/** + * Is T a Record? + */ +type IsObject = T extends Array +? False +: T extends Date +? False +: T extends Uint8Array +? False +: T extends BigInt +? False +: T extends object +? True +: False + + +/** + * If it's T[], return T + */ +export type UnEnumerate = T extends Array ? U : T + +/** + * From ts-toolbelt + */ + +type __Either = Omit & + { + // Merge all but K + [P in K]: Prisma__Pick // With K possibilities + }[K] + +type EitherStrict = Strict<__Either> + +type EitherLoose = ComputeRaw<__Either> + +type _Either< + O extends object, + K extends Key, + strict extends Boolean +> = { + 1: EitherStrict + 0: EitherLoose +}[strict] + +export type Either< + O extends object, + K extends Key, + strict extends Boolean = 1 +> = O extends unknown ? _Either : never + +export type Union = any + +export type PatchUndefined = { + [K in keyof O]: O[K] extends undefined ? At : O[K] +} & {} + +/** Helper Types for "Merge" **/ +export type IntersectOf = ( + U extends unknown ? (k: U) => void : never +) extends (k: infer I) => void + ? I + : never + +export type Overwrite = { + [K in keyof O]: K extends keyof O1 ? O1[K] : O[K]; +} & {}; + +type _Merge = IntersectOf; +}>>; + +type Key = string | number | symbol; +type AtStrict = O[K & keyof O]; +type AtLoose = O extends unknown ? AtStrict : never; +export type At = { + 1: AtStrict; + 0: AtLoose; +}[strict]; + +export type ComputeRaw = A extends Function ? A : { + [K in keyof A]: A[K]; +} & {}; + +export type OptionalFlat = { + [K in keyof O]?: O[K]; +} & {}; + +type _Record = { + [P in K]: T; +}; + +// cause typescript not to expand types and preserve names +type NoExpand = T extends unknown ? T : never; + +// this type assumes the passed object is entirely optional +export type AtLeast = NoExpand< + O extends unknown + ? | (K extends keyof O ? { [P in K]: O[P] } & O : O) + | {[P in keyof O as P extends K ? P : never]-?: O[P]} & O + : never>; + +type _Strict = U extends unknown ? U & OptionalFlat<_Record, keyof U>, never>> : never; + +export type Strict = ComputeRaw<_Strict>; +/** End Helper Types for "Merge" **/ + +export type Merge = ComputeRaw<_Merge>>; + +export type Boolean = True | False + +export type True = 1 + +export type False = 0 + +export type Not = { + 0: 1 + 1: 0 +}[B] + +export type Extends = [A1] extends [never] + ? 0 // anything `never` is false + : A1 extends A2 + ? 1 + : 0 + +export type Has = Not< + Extends, U1> +> + +export type Or = { + 0: { + 0: 0 + 1: 1 + } + 1: { + 0: 1 + 1: 1 + } +}[B1][B2] + +export type Keys = U extends unknown ? keyof U : never + +export type GetScalarType = O extends object ? { + [P in keyof T]: P extends keyof O + ? O[P] + : never +} : never + +type FieldPaths< + T, + U = Omit +> = IsObject extends True ? U : T + +export type GetHavingFields = { + [K in keyof T]: Or< + Or, Extends<'AND', K>>, + Extends<'NOT', K> + > extends True + ? // infer is only needed to not hit TS limit + // based on the brilliant idea of Pierre-Antoine Mills + // https://github.com/microsoft/TypeScript/issues/30188#issuecomment-478938437 + T[K] extends infer TK + ? GetHavingFields extends object ? Merge> : never> + : never + : {} extends FieldPaths + ? never + : K +}[keyof T] + +/** + * Convert tuple to union + */ +type _TupleToUnion = T extends (infer E)[] ? E : never +type TupleToUnion = _TupleToUnion +export type MaybeTupleToUnion = T extends any[] ? TupleToUnion : T + +/** + * Like `Pick`, but additionally can also accept an array of keys + */ +export type PickEnumerable | keyof T> = Prisma__Pick> + +/** + * Exclude all keys with underscores + */ +export type ExcludeUnderscoreKeys = T extends `_${string}` ? never : T + + +export type FieldRef = runtime.FieldRef + +type FieldRefInputType = Model extends never ? never : FieldRef + + +export const ModelName = { + Order: 'Order' +} as const + +export type ModelName = (typeof ModelName)[keyof typeof ModelName] + + + +export interface TypeMapCb extends runtime.Types.Utils.Fn<{extArgs: runtime.Types.Extensions.InternalArgs }, runtime.Types.Utils.Record> { + returns: TypeMap +} + +export type TypeMap = { + globalOmitOptions: { + omit: GlobalOmitOptions + } + meta: { + modelProps: "order" + txIsolationLevel: TransactionIsolationLevel + } + model: { + Order: { + payload: Prisma.$OrderPayload + fields: Prisma.OrderFieldRefs + operations: { + findUnique: { + args: Prisma.OrderFindUniqueArgs + result: runtime.Types.Utils.PayloadToResult | null + } + findUniqueOrThrow: { + args: Prisma.OrderFindUniqueOrThrowArgs + result: runtime.Types.Utils.PayloadToResult + } + findFirst: { + args: Prisma.OrderFindFirstArgs + result: runtime.Types.Utils.PayloadToResult | null + } + findFirstOrThrow: { + args: Prisma.OrderFindFirstOrThrowArgs + result: runtime.Types.Utils.PayloadToResult + } + findMany: { + args: Prisma.OrderFindManyArgs + result: runtime.Types.Utils.PayloadToResult[] + } + create: { + args: Prisma.OrderCreateArgs + result: runtime.Types.Utils.PayloadToResult + } + createMany: { + args: Prisma.OrderCreateManyArgs + result: BatchPayload + } + createManyAndReturn: { + args: Prisma.OrderCreateManyAndReturnArgs + result: runtime.Types.Utils.PayloadToResult[] + } + delete: { + args: Prisma.OrderDeleteArgs + result: runtime.Types.Utils.PayloadToResult + } + update: { + args: Prisma.OrderUpdateArgs + result: runtime.Types.Utils.PayloadToResult + } + deleteMany: { + args: Prisma.OrderDeleteManyArgs + result: BatchPayload + } + updateMany: { + args: Prisma.OrderUpdateManyArgs + result: BatchPayload + } + updateManyAndReturn: { + args: Prisma.OrderUpdateManyAndReturnArgs + result: runtime.Types.Utils.PayloadToResult[] + } + upsert: { + args: Prisma.OrderUpsertArgs + result: runtime.Types.Utils.PayloadToResult + } + aggregate: { + args: Prisma.OrderAggregateArgs + result: runtime.Types.Utils.Optional + } + groupBy: { + args: Prisma.OrderGroupByArgs + result: runtime.Types.Utils.Optional[] + } + count: { + args: Prisma.OrderCountArgs + result: runtime.Types.Utils.Optional | number + } + } + } + } +} & { + other: { + payload: any + operations: { + $executeRaw: { + args: [query: TemplateStringsArray | Sql, ...values: any[]], + result: any + } + $executeRawUnsafe: { + args: [query: string, ...values: any[]], + result: any + } + $queryRaw: { + args: [query: TemplateStringsArray | Sql, ...values: any[]], + result: any + } + $queryRawUnsafe: { + args: [query: string, ...values: any[]], + result: any + } + } + } +} + +/** + * Enums + */ + +export const TransactionIsolationLevel = runtime.makeStrictEnum({ + ReadUncommitted: 'ReadUncommitted', + ReadCommitted: 'ReadCommitted', + RepeatableRead: 'RepeatableRead', + Serializable: 'Serializable' +} as const) + +export type TransactionIsolationLevel = (typeof TransactionIsolationLevel)[keyof typeof TransactionIsolationLevel] + + +export const OrderScalarFieldEnum = { + id: 'id', + itemId: 'itemId', + quantity: 'quantity', + status: 'status', + createdAt: 'createdAt', + updatedAt: 'updatedAt' +} as const + +export type OrderScalarFieldEnum = (typeof OrderScalarFieldEnum)[keyof typeof OrderScalarFieldEnum] + + +export const SortOrder = { + asc: 'asc', + desc: 'desc' +} as const + +export type SortOrder = (typeof SortOrder)[keyof typeof SortOrder] + + +export const QueryMode = { + default: 'default', + insensitive: 'insensitive' +} as const + +export type QueryMode = (typeof QueryMode)[keyof typeof QueryMode] + + + +/** + * Field references + */ + + +/** + * Reference to a field of type 'String' + */ +export type StringFieldRefInput<$PrismaModel> = FieldRefInputType<$PrismaModel, 'String'> + + + +/** + * Reference to a field of type 'String[]' + */ +export type ListStringFieldRefInput<$PrismaModel> = FieldRefInputType<$PrismaModel, 'String[]'> + + + +/** + * Reference to a field of type 'Int' + */ +export type IntFieldRefInput<$PrismaModel> = FieldRefInputType<$PrismaModel, 'Int'> + + + +/** + * Reference to a field of type 'Int[]' + */ +export type ListIntFieldRefInput<$PrismaModel> = FieldRefInputType<$PrismaModel, 'Int[]'> + + + +/** + * Reference to a field of type 'DateTime' + */ +export type DateTimeFieldRefInput<$PrismaModel> = FieldRefInputType<$PrismaModel, 'DateTime'> + + + +/** + * Reference to a field of type 'DateTime[]' + */ +export type ListDateTimeFieldRefInput<$PrismaModel> = FieldRefInputType<$PrismaModel, 'DateTime[]'> + + + +/** + * Reference to a field of type 'Float' + */ +export type FloatFieldRefInput<$PrismaModel> = FieldRefInputType<$PrismaModel, 'Float'> + + + +/** + * Reference to a field of type 'Float[]' + */ +export type ListFloatFieldRefInput<$PrismaModel> = FieldRefInputType<$PrismaModel, 'Float[]'> + + +/** + * Batch Payload for updateMany & deleteMany & createMany + */ +export type BatchPayload = { + count: number +} + +export const defineExtension = runtime.Extensions.defineExtension as unknown as runtime.Types.Extensions.ExtendsHook<"define", TypeMapCb, runtime.Types.Extensions.DefaultArgs> +export type DefaultPrismaClient = PrismaClient +export type ErrorFormat = 'pretty' | 'colorless' | 'minimal' +export type PrismaClientOptions = ({ + /** + * Instance of a Driver Adapter, e.g., like one provided by `@prisma/adapter-pg`. + */ + adapter: runtime.SqlDriverAdapterFactory + accelerateUrl?: never +} | { + /** + * Prisma Accelerate URL allowing the client to connect through Accelerate instead of a direct database. + */ + accelerateUrl: string + adapter?: never +}) & { + /** + * @default "colorless" + */ + errorFormat?: ErrorFormat + /** + * @example + * ``` + * // Shorthand for `emit: 'stdout'` + * log: ['query', 'info', 'warn', 'error'] + * + * // Emit as events only + * log: [ + * { emit: 'event', level: 'query' }, + * { emit: 'event', level: 'info' }, + * { emit: 'event', level: 'warn' } + * { emit: 'event', level: 'error' } + * ] + * + * / Emit as events and log to stdout + * og: [ + * { emit: 'stdout', level: 'query' }, + * { emit: 'stdout', level: 'info' }, + * { emit: 'stdout', level: 'warn' } + * { emit: 'stdout', level: 'error' } + * + * ``` + * Read more in our [docs](https://pris.ly/d/logging). + */ + log?: (LogLevel | LogDefinition)[] + /** + * The default values for transactionOptions + * maxWait ?= 2000 + * timeout ?= 5000 + */ + transactionOptions?: { + maxWait?: number + timeout?: number + isolationLevel?: TransactionIsolationLevel + } + /** + * Global configuration for omitting model fields by default. + * + * @example + * ``` + * const prisma = new PrismaClient({ + * omit: { + * user: { + * password: true + * } + * } + * }) + * ``` + */ + omit?: GlobalOmitConfig + /** + * SQL commenter plugins that add metadata to SQL queries as comments. + * Comments follow the sqlcommenter format: https://google.github.io/sqlcommenter/ + * + * @example + * ``` + * const prisma = new PrismaClient({ + * adapter, + * comments: [ + * traceContext(), + * queryInsights(), + * ], + * }) + * ``` + */ + comments?: runtime.SqlCommenterPlugin[] +} +export type GlobalOmitConfig = { + order?: Prisma.OrderOmit +} + +/* Types for Logging */ +export type LogLevel = 'info' | 'query' | 'warn' | 'error' +export type LogDefinition = { + level: LogLevel + emit: 'stdout' | 'event' +} + +export type CheckIsLogLevel = T extends LogLevel ? T : never; + +export type GetLogType = CheckIsLogLevel< + T extends LogDefinition ? T['level'] : T +>; + +export type GetEvents = T extends Array + ? GetLogType + : never; + +export type QueryEvent = { + timestamp: Date + query: string + params: string + duration: number + target: string +} + +export type LogEvent = { + timestamp: Date + message: string + target: string +} +/* End Types for Logging */ + + +export type PrismaAction = + | 'findUnique' + | 'findUniqueOrThrow' + | 'findMany' + | 'findFirst' + | 'findFirstOrThrow' + | 'create' + | 'createMany' + | 'createManyAndReturn' + | 'update' + | 'updateMany' + | 'updateManyAndReturn' + | 'upsert' + | 'delete' + | 'deleteMany' + | 'executeRaw' + | 'queryRaw' + | 'aggregate' + | 'count' + | 'runCommandRaw' + | 'findRaw' + | 'groupBy' + +/** + * `PrismaClient` proxy available in interactive transactions. + */ +export type TransactionClient = Omit + diff --git a/services/order-service/src/generated/prisma/internal/prismaNamespaceBrowser.ts b/services/order-service/src/generated/prisma/internal/prismaNamespaceBrowser.ts new file mode 100644 index 0000000..75d9f8d --- /dev/null +++ b/services/order-service/src/generated/prisma/internal/prismaNamespaceBrowser.ts @@ -0,0 +1,99 @@ + +/* !!! This is code generated by Prisma. Do not edit directly. !!! */ +/* eslint-disable */ +// biome-ignore-all lint: generated file +// @ts-nocheck +/* + * WARNING: This is an internal file that is subject to change! + * + * 🛑 Under no circumstances should you import this file directly! 🛑 + * + * All exports from this file are wrapped under a `Prisma` namespace object in the browser.ts file. + * While this enables partial backward compatibility, it is not part of the stable public API. + * + * If you are looking for your Models, Enums, and Input Types, please import them from the respective + * model files in the `model` directory! + */ + +import * as runtime from "@prisma/client/runtime/index-browser" + +export type * from '../models.ts' +export type * from './prismaNamespace.ts' + +export const Decimal = runtime.Decimal + + +export const NullTypes = { + DbNull: runtime.NullTypes.DbNull as (new (secret: never) => typeof runtime.DbNull), + JsonNull: runtime.NullTypes.JsonNull as (new (secret: never) => typeof runtime.JsonNull), + AnyNull: runtime.NullTypes.AnyNull as (new (secret: never) => typeof runtime.AnyNull), +} +/** + * Helper for filtering JSON entries that have `null` on the database (empty on the db) + * + * @see https://www.prisma.io/docs/concepts/components/prisma-client/working-with-fields/working-with-json-fields#filtering-on-a-json-field + */ +export const DbNull = runtime.DbNull + +/** + * Helper for filtering JSON entries that have JSON `null` values (not empty on the db) + * + * @see https://www.prisma.io/docs/concepts/components/prisma-client/working-with-fields/working-with-json-fields#filtering-on-a-json-field + */ +export const JsonNull = runtime.JsonNull + +/** + * Helper for filtering JSON entries that are `Prisma.DbNull` or `Prisma.JsonNull` + * + * @see https://www.prisma.io/docs/concepts/components/prisma-client/working-with-fields/working-with-json-fields#filtering-on-a-json-field + */ +export const AnyNull = runtime.AnyNull + + +export const ModelName = { + Order: 'Order' +} as const + +export type ModelName = (typeof ModelName)[keyof typeof ModelName] + +/* + * Enums + */ + +export const TransactionIsolationLevel = runtime.makeStrictEnum({ + ReadUncommitted: 'ReadUncommitted', + ReadCommitted: 'ReadCommitted', + RepeatableRead: 'RepeatableRead', + Serializable: 'Serializable' +} as const) + +export type TransactionIsolationLevel = (typeof TransactionIsolationLevel)[keyof typeof TransactionIsolationLevel] + + +export const OrderScalarFieldEnum = { + id: 'id', + itemId: 'itemId', + quantity: 'quantity', + status: 'status', + createdAt: 'createdAt', + updatedAt: 'updatedAt' +} as const + +export type OrderScalarFieldEnum = (typeof OrderScalarFieldEnum)[keyof typeof OrderScalarFieldEnum] + + +export const SortOrder = { + asc: 'asc', + desc: 'desc' +} as const + +export type SortOrder = (typeof SortOrder)[keyof typeof SortOrder] + + +export const QueryMode = { + default: 'default', + insensitive: 'insensitive' +} as const + +export type QueryMode = (typeof QueryMode)[keyof typeof QueryMode] + diff --git a/services/order-service/src/generated/prisma/models.ts b/services/order-service/src/generated/prisma/models.ts new file mode 100644 index 0000000..d5467ca --- /dev/null +++ b/services/order-service/src/generated/prisma/models.ts @@ -0,0 +1,12 @@ + +/* !!! This is code generated by Prisma. Do not edit directly. !!! */ +/* eslint-disable */ +// biome-ignore-all lint: generated file +// @ts-nocheck +/* + * This is a barrel export file for all models and their related types. + * + * 🟢 You can import this file directly. + */ +export type * from './models/Order.ts' +export type * from './commonInputTypes.ts' \ No newline at end of file diff --git a/services/order-service/src/generated/prisma/models/Order.ts b/services/order-service/src/generated/prisma/models/Order.ts new file mode 100644 index 0000000..ec5f214 --- /dev/null +++ b/services/order-service/src/generated/prisma/models/Order.ts @@ -0,0 +1,1238 @@ + +/* !!! This is code generated by Prisma. Do not edit directly. !!! */ +/* eslint-disable */ +// biome-ignore-all lint: generated file +// @ts-nocheck +/* + * This file exports the `Order` model and its related types. + * + * 🟢 You can import this file directly. + */ +import type * as runtime from "@prisma/client/runtime/client" +import type * as $Enums from "../enums.ts" +import type * as Prisma from "../internal/prismaNamespace.ts" + +/** + * Model Order + * + */ +export type OrderModel = runtime.Types.Result.DefaultSelection + +export type AggregateOrder = { + _count: OrderCountAggregateOutputType | null + _avg: OrderAvgAggregateOutputType | null + _sum: OrderSumAggregateOutputType | null + _min: OrderMinAggregateOutputType | null + _max: OrderMaxAggregateOutputType | null +} + +export type OrderAvgAggregateOutputType = { + itemId: number | null + quantity: number | null +} + +export type OrderSumAggregateOutputType = { + itemId: number | null + quantity: number | null +} + +export type OrderMinAggregateOutputType = { + id: string | null + itemId: number | null + quantity: number | null + status: string | null + createdAt: Date | null + updatedAt: Date | null +} + +export type OrderMaxAggregateOutputType = { + id: string | null + itemId: number | null + quantity: number | null + status: string | null + createdAt: Date | null + updatedAt: Date | null +} + +export type OrderCountAggregateOutputType = { + id: number + itemId: number + quantity: number + status: number + createdAt: number + updatedAt: number + _all: number +} + + +export type OrderAvgAggregateInputType = { + itemId?: true + quantity?: true +} + +export type OrderSumAggregateInputType = { + itemId?: true + quantity?: true +} + +export type OrderMinAggregateInputType = { + id?: true + itemId?: true + quantity?: true + status?: true + createdAt?: true + updatedAt?: true +} + +export type OrderMaxAggregateInputType = { + id?: true + itemId?: true + quantity?: true + status?: true + createdAt?: true + updatedAt?: true +} + +export type OrderCountAggregateInputType = { + id?: true + itemId?: true + quantity?: true + status?: true + createdAt?: true + updatedAt?: true + _all?: true +} + +export type OrderAggregateArgs = { + /** + * Filter which Order to aggregate. + */ + where?: Prisma.OrderWhereInput + /** + * {@link https://www.prisma.io/docs/concepts/components/prisma-client/sorting Sorting Docs} + * + * Determine the order of Orders to fetch. + */ + orderBy?: Prisma.OrderOrderByWithRelationInput | Prisma.OrderOrderByWithRelationInput[] + /** + * {@link https://www.prisma.io/docs/concepts/components/prisma-client/pagination#cursor-based-pagination Cursor Docs} + * + * Sets the start position + */ + cursor?: Prisma.OrderWhereUniqueInput + /** + * {@link https://www.prisma.io/docs/concepts/components/prisma-client/pagination Pagination Docs} + * + * Take `±n` Orders from the position of the cursor. + */ + take?: number + /** + * {@link https://www.prisma.io/docs/concepts/components/prisma-client/pagination Pagination Docs} + * + * Skip the first `n` Orders. + */ + skip?: number + /** + * {@link https://www.prisma.io/docs/concepts/components/prisma-client/aggregations Aggregation Docs} + * + * Count returned Orders + **/ + _count?: true | OrderCountAggregateInputType + /** + * {@link https://www.prisma.io/docs/concepts/components/prisma-client/aggregations Aggregation Docs} + * + * Select which fields to average + **/ + _avg?: OrderAvgAggregateInputType + /** + * {@link https://www.prisma.io/docs/concepts/components/prisma-client/aggregations Aggregation Docs} + * + * Select which fields to sum + **/ + _sum?: OrderSumAggregateInputType + /** + * {@link https://www.prisma.io/docs/concepts/components/prisma-client/aggregations Aggregation Docs} + * + * Select which fields to find the minimum value + **/ + _min?: OrderMinAggregateInputType + /** + * {@link https://www.prisma.io/docs/concepts/components/prisma-client/aggregations Aggregation Docs} + * + * Select which fields to find the maximum value + **/ + _max?: OrderMaxAggregateInputType +} + +export type GetOrderAggregateType = { + [P in keyof T & keyof AggregateOrder]: P extends '_count' | 'count' + ? T[P] extends true + ? number + : Prisma.GetScalarType + : Prisma.GetScalarType +} + + + + +export type OrderGroupByArgs = { + where?: Prisma.OrderWhereInput + orderBy?: Prisma.OrderOrderByWithAggregationInput | Prisma.OrderOrderByWithAggregationInput[] + by: Prisma.OrderScalarFieldEnum[] | Prisma.OrderScalarFieldEnum + having?: Prisma.OrderScalarWhereWithAggregatesInput + take?: number + skip?: number + _count?: OrderCountAggregateInputType | true + _avg?: OrderAvgAggregateInputType + _sum?: OrderSumAggregateInputType + _min?: OrderMinAggregateInputType + _max?: OrderMaxAggregateInputType +} + +export type OrderGroupByOutputType = { + id: string + itemId: number + quantity: number + status: string + createdAt: Date + updatedAt: Date + _count: OrderCountAggregateOutputType | null + _avg: OrderAvgAggregateOutputType | null + _sum: OrderSumAggregateOutputType | null + _min: OrderMinAggregateOutputType | null + _max: OrderMaxAggregateOutputType | null +} + +type GetOrderGroupByPayload = Prisma.PrismaPromise< + Array< + Prisma.PickEnumerable & + { + [P in ((keyof T) & (keyof OrderGroupByOutputType))]: P extends '_count' + ? T[P] extends boolean + ? number + : Prisma.GetScalarType + : Prisma.GetScalarType + } + > + > + + + +export type OrderWhereInput = { + AND?: Prisma.OrderWhereInput | Prisma.OrderWhereInput[] + OR?: Prisma.OrderWhereInput[] + NOT?: Prisma.OrderWhereInput | Prisma.OrderWhereInput[] + id?: Prisma.StringFilter<"Order"> | string + itemId?: Prisma.IntFilter<"Order"> | number + quantity?: Prisma.IntFilter<"Order"> | number + status?: Prisma.StringFilter<"Order"> | string + createdAt?: Prisma.DateTimeFilter<"Order"> | Date | string + updatedAt?: Prisma.DateTimeFilter<"Order"> | Date | string +} + +export type OrderOrderByWithRelationInput = { + id?: Prisma.SortOrder + itemId?: Prisma.SortOrder + quantity?: Prisma.SortOrder + status?: Prisma.SortOrder + createdAt?: Prisma.SortOrder + updatedAt?: Prisma.SortOrder +} + +export type OrderWhereUniqueInput = Prisma.AtLeast<{ + id?: string + AND?: Prisma.OrderWhereInput | Prisma.OrderWhereInput[] + OR?: Prisma.OrderWhereInput[] + NOT?: Prisma.OrderWhereInput | Prisma.OrderWhereInput[] + itemId?: Prisma.IntFilter<"Order"> | number + quantity?: Prisma.IntFilter<"Order"> | number + status?: Prisma.StringFilter<"Order"> | string + createdAt?: Prisma.DateTimeFilter<"Order"> | Date | string + updatedAt?: Prisma.DateTimeFilter<"Order"> | Date | string +}, "id"> + +export type OrderOrderByWithAggregationInput = { + id?: Prisma.SortOrder + itemId?: Prisma.SortOrder + quantity?: Prisma.SortOrder + status?: Prisma.SortOrder + createdAt?: Prisma.SortOrder + updatedAt?: Prisma.SortOrder + _count?: Prisma.OrderCountOrderByAggregateInput + _avg?: Prisma.OrderAvgOrderByAggregateInput + _max?: Prisma.OrderMaxOrderByAggregateInput + _min?: Prisma.OrderMinOrderByAggregateInput + _sum?: Prisma.OrderSumOrderByAggregateInput +} + +export type OrderScalarWhereWithAggregatesInput = { + AND?: Prisma.OrderScalarWhereWithAggregatesInput | Prisma.OrderScalarWhereWithAggregatesInput[] + OR?: Prisma.OrderScalarWhereWithAggregatesInput[] + NOT?: Prisma.OrderScalarWhereWithAggregatesInput | Prisma.OrderScalarWhereWithAggregatesInput[] + id?: Prisma.StringWithAggregatesFilter<"Order"> | string + itemId?: Prisma.IntWithAggregatesFilter<"Order"> | number + quantity?: Prisma.IntWithAggregatesFilter<"Order"> | number + status?: Prisma.StringWithAggregatesFilter<"Order"> | string + createdAt?: Prisma.DateTimeWithAggregatesFilter<"Order"> | Date | string + updatedAt?: Prisma.DateTimeWithAggregatesFilter<"Order"> | Date | string +} + +export type OrderCreateInput = { + id?: string + itemId: number + quantity: number + status: string + createdAt?: Date | string + updatedAt?: Date | string +} + +export type OrderUncheckedCreateInput = { + id?: string + itemId: number + quantity: number + status: string + createdAt?: Date | string + updatedAt?: Date | string +} + +export type OrderUpdateInput = { + id?: Prisma.StringFieldUpdateOperationsInput | string + itemId?: Prisma.IntFieldUpdateOperationsInput | number + quantity?: Prisma.IntFieldUpdateOperationsInput | number + status?: Prisma.StringFieldUpdateOperationsInput | string + createdAt?: Prisma.DateTimeFieldUpdateOperationsInput | Date | string + updatedAt?: Prisma.DateTimeFieldUpdateOperationsInput | Date | string +} + +export type OrderUncheckedUpdateInput = { + id?: Prisma.StringFieldUpdateOperationsInput | string + itemId?: Prisma.IntFieldUpdateOperationsInput | number + quantity?: Prisma.IntFieldUpdateOperationsInput | number + status?: Prisma.StringFieldUpdateOperationsInput | string + createdAt?: Prisma.DateTimeFieldUpdateOperationsInput | Date | string + updatedAt?: Prisma.DateTimeFieldUpdateOperationsInput | Date | string +} + +export type OrderCreateManyInput = { + id?: string + itemId: number + quantity: number + status: string + createdAt?: Date | string + updatedAt?: Date | string +} + +export type OrderUpdateManyMutationInput = { + id?: Prisma.StringFieldUpdateOperationsInput | string + itemId?: Prisma.IntFieldUpdateOperationsInput | number + quantity?: Prisma.IntFieldUpdateOperationsInput | number + status?: Prisma.StringFieldUpdateOperationsInput | string + createdAt?: Prisma.DateTimeFieldUpdateOperationsInput | Date | string + updatedAt?: Prisma.DateTimeFieldUpdateOperationsInput | Date | string +} + +export type OrderUncheckedUpdateManyInput = { + id?: Prisma.StringFieldUpdateOperationsInput | string + itemId?: Prisma.IntFieldUpdateOperationsInput | number + quantity?: Prisma.IntFieldUpdateOperationsInput | number + status?: Prisma.StringFieldUpdateOperationsInput | string + createdAt?: Prisma.DateTimeFieldUpdateOperationsInput | Date | string + updatedAt?: Prisma.DateTimeFieldUpdateOperationsInput | Date | string +} + +export type OrderCountOrderByAggregateInput = { + id?: Prisma.SortOrder + itemId?: Prisma.SortOrder + quantity?: Prisma.SortOrder + status?: Prisma.SortOrder + createdAt?: Prisma.SortOrder + updatedAt?: Prisma.SortOrder +} + +export type OrderAvgOrderByAggregateInput = { + itemId?: Prisma.SortOrder + quantity?: Prisma.SortOrder +} + +export type OrderMaxOrderByAggregateInput = { + id?: Prisma.SortOrder + itemId?: Prisma.SortOrder + quantity?: Prisma.SortOrder + status?: Prisma.SortOrder + createdAt?: Prisma.SortOrder + updatedAt?: Prisma.SortOrder +} + +export type OrderMinOrderByAggregateInput = { + id?: Prisma.SortOrder + itemId?: Prisma.SortOrder + quantity?: Prisma.SortOrder + status?: Prisma.SortOrder + createdAt?: Prisma.SortOrder + updatedAt?: Prisma.SortOrder +} + +export type OrderSumOrderByAggregateInput = { + itemId?: Prisma.SortOrder + quantity?: Prisma.SortOrder +} + +export type StringFieldUpdateOperationsInput = { + set?: string +} + +export type IntFieldUpdateOperationsInput = { + set?: number + increment?: number + decrement?: number + multiply?: number + divide?: number +} + +export type DateTimeFieldUpdateOperationsInput = { + set?: Date | string +} + + + +export type OrderSelect = runtime.Types.Extensions.GetSelect<{ + id?: boolean + itemId?: boolean + quantity?: boolean + status?: boolean + createdAt?: boolean + updatedAt?: boolean +}, ExtArgs["result"]["order"]> + +export type OrderSelectCreateManyAndReturn = runtime.Types.Extensions.GetSelect<{ + id?: boolean + itemId?: boolean + quantity?: boolean + status?: boolean + createdAt?: boolean + updatedAt?: boolean +}, ExtArgs["result"]["order"]> + +export type OrderSelectUpdateManyAndReturn = runtime.Types.Extensions.GetSelect<{ + id?: boolean + itemId?: boolean + quantity?: boolean + status?: boolean + createdAt?: boolean + updatedAt?: boolean +}, ExtArgs["result"]["order"]> + +export type OrderSelectScalar = { + id?: boolean + itemId?: boolean + quantity?: boolean + status?: boolean + createdAt?: boolean + updatedAt?: boolean +} + +export type OrderOmit = runtime.Types.Extensions.GetOmit<"id" | "itemId" | "quantity" | "status" | "createdAt" | "updatedAt", ExtArgs["result"]["order"]> + +export type $OrderPayload = { + name: "Order" + objects: {} + scalars: runtime.Types.Extensions.GetPayloadResult<{ + id: string + itemId: number + quantity: number + status: string + createdAt: Date + updatedAt: Date + }, ExtArgs["result"]["order"]> + composites: {} +} + +export type OrderGetPayload = runtime.Types.Result.GetResult + +export type OrderCountArgs = + Omit & { + select?: OrderCountAggregateInputType | true + } + +export interface OrderDelegate { + [K: symbol]: { types: Prisma.TypeMap['model']['Order'], meta: { name: 'Order' } } + /** + * Find zero or one Order that matches the filter. + * @param {OrderFindUniqueArgs} args - Arguments to find a Order + * @example + * // Get one Order + * const order = await prisma.order.findUnique({ + * where: { + * // ... provide filter here + * } + * }) + */ + findUnique(args: Prisma.SelectSubset>): Prisma.Prisma__OrderClient, T, "findUnique", GlobalOmitOptions> | null, null, ExtArgs, GlobalOmitOptions> + + /** + * Find one Order that matches the filter or throw an error with `error.code='P2025'` + * if no matches were found. + * @param {OrderFindUniqueOrThrowArgs} args - Arguments to find a Order + * @example + * // Get one Order + * const order = await prisma.order.findUniqueOrThrow({ + * where: { + * // ... provide filter here + * } + * }) + */ + findUniqueOrThrow(args: Prisma.SelectSubset>): Prisma.Prisma__OrderClient, T, "findUniqueOrThrow", GlobalOmitOptions>, never, ExtArgs, GlobalOmitOptions> + + /** + * Find the first Order that matches the filter. + * Note, that providing `undefined` is treated as the value not being there. + * Read more here: https://pris.ly/d/null-undefined + * @param {OrderFindFirstArgs} args - Arguments to find a Order + * @example + * // Get one Order + * const order = await prisma.order.findFirst({ + * where: { + * // ... provide filter here + * } + * }) + */ + findFirst(args?: Prisma.SelectSubset>): Prisma.Prisma__OrderClient, T, "findFirst", GlobalOmitOptions> | null, null, ExtArgs, GlobalOmitOptions> + + /** + * Find the first Order that matches the filter or + * throw `PrismaKnownClientError` with `P2025` code if no matches were found. + * Note, that providing `undefined` is treated as the value not being there. + * Read more here: https://pris.ly/d/null-undefined + * @param {OrderFindFirstOrThrowArgs} args - Arguments to find a Order + * @example + * // Get one Order + * const order = await prisma.order.findFirstOrThrow({ + * where: { + * // ... provide filter here + * } + * }) + */ + findFirstOrThrow(args?: Prisma.SelectSubset>): Prisma.Prisma__OrderClient, T, "findFirstOrThrow", GlobalOmitOptions>, never, ExtArgs, GlobalOmitOptions> + + /** + * Find zero or more Orders that matches the filter. + * Note, that providing `undefined` is treated as the value not being there. + * Read more here: https://pris.ly/d/null-undefined + * @param {OrderFindManyArgs} args - Arguments to filter and select certain fields only. + * @example + * // Get all Orders + * const orders = await prisma.order.findMany() + * + * // Get first 10 Orders + * const orders = await prisma.order.findMany({ take: 10 }) + * + * // Only select the `id` + * const orderWithIdOnly = await prisma.order.findMany({ select: { id: true } }) + * + */ + findMany(args?: Prisma.SelectSubset>): Prisma.PrismaPromise, T, "findMany", GlobalOmitOptions>> + + /** + * Create a Order. + * @param {OrderCreateArgs} args - Arguments to create a Order. + * @example + * // Create one Order + * const Order = await prisma.order.create({ + * data: { + * // ... data to create a Order + * } + * }) + * + */ + create(args: Prisma.SelectSubset>): Prisma.Prisma__OrderClient, T, "create", GlobalOmitOptions>, never, ExtArgs, GlobalOmitOptions> + + /** + * Create many Orders. + * @param {OrderCreateManyArgs} args - Arguments to create many Orders. + * @example + * // Create many Orders + * const order = await prisma.order.createMany({ + * data: [ + * // ... provide data here + * ] + * }) + * + */ + createMany(args?: Prisma.SelectSubset>): Prisma.PrismaPromise + + /** + * Create many Orders and returns the data saved in the database. + * @param {OrderCreateManyAndReturnArgs} args - Arguments to create many Orders. + * @example + * // Create many Orders + * const order = await prisma.order.createManyAndReturn({ + * data: [ + * // ... provide data here + * ] + * }) + * + * // Create many Orders and only return the `id` + * const orderWithIdOnly = await prisma.order.createManyAndReturn({ + * select: { id: true }, + * data: [ + * // ... provide data here + * ] + * }) + * Note, that providing `undefined` is treated as the value not being there. + * Read more here: https://pris.ly/d/null-undefined + * + */ + createManyAndReturn(args?: Prisma.SelectSubset>): Prisma.PrismaPromise, T, "createManyAndReturn", GlobalOmitOptions>> + + /** + * Delete a Order. + * @param {OrderDeleteArgs} args - Arguments to delete one Order. + * @example + * // Delete one Order + * const Order = await prisma.order.delete({ + * where: { + * // ... filter to delete one Order + * } + * }) + * + */ + delete(args: Prisma.SelectSubset>): Prisma.Prisma__OrderClient, T, "delete", GlobalOmitOptions>, never, ExtArgs, GlobalOmitOptions> + + /** + * Update one Order. + * @param {OrderUpdateArgs} args - Arguments to update one Order. + * @example + * // Update one Order + * const order = await prisma.order.update({ + * where: { + * // ... provide filter here + * }, + * data: { + * // ... provide data here + * } + * }) + * + */ + update(args: Prisma.SelectSubset>): Prisma.Prisma__OrderClient, T, "update", GlobalOmitOptions>, never, ExtArgs, GlobalOmitOptions> + + /** + * Delete zero or more Orders. + * @param {OrderDeleteManyArgs} args - Arguments to filter Orders to delete. + * @example + * // Delete a few Orders + * const { count } = await prisma.order.deleteMany({ + * where: { + * // ... provide filter here + * } + * }) + * + */ + deleteMany(args?: Prisma.SelectSubset>): Prisma.PrismaPromise + + /** + * Update zero or more Orders. + * Note, that providing `undefined` is treated as the value not being there. + * Read more here: https://pris.ly/d/null-undefined + * @param {OrderUpdateManyArgs} args - Arguments to update one or more rows. + * @example + * // Update many Orders + * const order = await prisma.order.updateMany({ + * where: { + * // ... provide filter here + * }, + * data: { + * // ... provide data here + * } + * }) + * + */ + updateMany(args: Prisma.SelectSubset>): Prisma.PrismaPromise + + /** + * Update zero or more Orders and returns the data updated in the database. + * @param {OrderUpdateManyAndReturnArgs} args - Arguments to update many Orders. + * @example + * // Update many Orders + * const order = await prisma.order.updateManyAndReturn({ + * where: { + * // ... provide filter here + * }, + * data: [ + * // ... provide data here + * ] + * }) + * + * // Update zero or more Orders and only return the `id` + * const orderWithIdOnly = await prisma.order.updateManyAndReturn({ + * select: { id: true }, + * where: { + * // ... provide filter here + * }, + * data: [ + * // ... provide data here + * ] + * }) + * Note, that providing `undefined` is treated as the value not being there. + * Read more here: https://pris.ly/d/null-undefined + * + */ + updateManyAndReturn(args: Prisma.SelectSubset>): Prisma.PrismaPromise, T, "updateManyAndReturn", GlobalOmitOptions>> + + /** + * Create or update one Order. + * @param {OrderUpsertArgs} args - Arguments to update or create a Order. + * @example + * // Update or create a Order + * const order = await prisma.order.upsert({ + * create: { + * // ... data to create a Order + * }, + * update: { + * // ... in case it already exists, update + * }, + * where: { + * // ... the filter for the Order we want to update + * } + * }) + */ + upsert(args: Prisma.SelectSubset>): Prisma.Prisma__OrderClient, T, "upsert", GlobalOmitOptions>, never, ExtArgs, GlobalOmitOptions> + + + /** + * Count the number of Orders. + * Note, that providing `undefined` is treated as the value not being there. + * Read more here: https://pris.ly/d/null-undefined + * @param {OrderCountArgs} args - Arguments to filter Orders to count. + * @example + * // Count the number of Orders + * const count = await prisma.order.count({ + * where: { + * // ... the filter for the Orders we want to count + * } + * }) + **/ + count( + args?: Prisma.Subset, + ): Prisma.PrismaPromise< + T extends runtime.Types.Utils.Record<'select', any> + ? T['select'] extends true + ? number + : Prisma.GetScalarType + : number + > + + /** + * Allows you to perform aggregations operations on a Order. + * Note, that providing `undefined` is treated as the value not being there. + * Read more here: https://pris.ly/d/null-undefined + * @param {OrderAggregateArgs} args - Select which aggregations you would like to apply and on what fields. + * @example + * // Ordered by age ascending + * // Where email contains prisma.io + * // Limited to the 10 users + * const aggregations = await prisma.user.aggregate({ + * _avg: { + * age: true, + * }, + * where: { + * email: { + * contains: "prisma.io", + * }, + * }, + * orderBy: { + * age: "asc", + * }, + * take: 10, + * }) + **/ + aggregate(args: Prisma.Subset): Prisma.PrismaPromise> + + /** + * Group by Order. + * Note, that providing `undefined` is treated as the value not being there. + * Read more here: https://pris.ly/d/null-undefined + * @param {OrderGroupByArgs} args - Group by arguments. + * @example + * // Group by city, order by createdAt, get count + * const result = await prisma.user.groupBy({ + * by: ['city', 'createdAt'], + * orderBy: { + * createdAt: true + * }, + * _count: { + * _all: true + * }, + * }) + * + **/ + groupBy< + T extends OrderGroupByArgs, + HasSelectOrTake extends Prisma.Or< + Prisma.Extends<'skip', Prisma.Keys>, + Prisma.Extends<'take', Prisma.Keys> + >, + OrderByArg extends Prisma.True extends HasSelectOrTake + ? { orderBy: OrderGroupByArgs['orderBy'] } + : { orderBy?: OrderGroupByArgs['orderBy'] }, + OrderFields extends Prisma.ExcludeUnderscoreKeys>>, + ByFields extends Prisma.MaybeTupleToUnion, + ByValid extends Prisma.Has, + HavingFields extends Prisma.GetHavingFields, + HavingValid extends Prisma.Has, + ByEmpty extends T['by'] extends never[] ? Prisma.True : Prisma.False, + InputErrors extends ByEmpty extends Prisma.True + ? `Error: "by" must not be empty.` + : HavingValid extends Prisma.False + ? { + [P in HavingFields]: P extends ByFields + ? never + : P extends string + ? `Error: Field "${P}" used in "having" needs to be provided in "by".` + : [ + Error, + 'Field ', + P, + ` in "having" needs to be provided in "by"`, + ] + }[HavingFields] + : 'take' extends Prisma.Keys + ? 'orderBy' extends Prisma.Keys + ? ByValid extends Prisma.True + ? {} + : { + [P in OrderFields]: P extends ByFields + ? never + : `Error: Field "${P}" in "orderBy" needs to be provided in "by"` + }[OrderFields] + : 'Error: If you provide "take", you also need to provide "orderBy"' + : 'skip' extends Prisma.Keys + ? 'orderBy' extends Prisma.Keys + ? ByValid extends Prisma.True + ? {} + : { + [P in OrderFields]: P extends ByFields + ? never + : `Error: Field "${P}" in "orderBy" needs to be provided in "by"` + }[OrderFields] + : 'Error: If you provide "skip", you also need to provide "orderBy"' + : ByValid extends Prisma.True + ? {} + : { + [P in OrderFields]: P extends ByFields + ? never + : `Error: Field "${P}" in "orderBy" needs to be provided in "by"` + }[OrderFields] + >(args: Prisma.SubsetIntersection & InputErrors): {} extends InputErrors ? GetOrderGroupByPayload : Prisma.PrismaPromise +/** + * Fields of the Order model + */ +readonly fields: OrderFieldRefs; +} + +/** + * The delegate class that acts as a "Promise-like" for Order. + * Why is this prefixed with `Prisma__`? + * Because we want to prevent naming conflicts as mentioned in + * https://github.com/prisma/prisma-client-js/issues/707 + */ +export interface Prisma__OrderClient extends Prisma.PrismaPromise { + readonly [Symbol.toStringTag]: "PrismaPromise" + /** + * Attaches callbacks for the resolution and/or rejection of the Promise. + * @param onfulfilled The callback to execute when the Promise is resolved. + * @param onrejected The callback to execute when the Promise is rejected. + * @returns A Promise for the completion of which ever callback is executed. + */ + then(onfulfilled?: ((value: T) => TResult1 | PromiseLike) | undefined | null, onrejected?: ((reason: any) => TResult2 | PromiseLike) | undefined | null): runtime.Types.Utils.JsPromise + /** + * Attaches a callback for only the rejection of the Promise. + * @param onrejected The callback to execute when the Promise is rejected. + * @returns A Promise for the completion of the callback. + */ + catch(onrejected?: ((reason: any) => TResult | PromiseLike) | undefined | null): runtime.Types.Utils.JsPromise + /** + * Attaches a callback that is invoked when the Promise is settled (fulfilled or rejected). The + * resolved value cannot be modified from the callback. + * @param onfinally The callback to execute when the Promise is settled (fulfilled or rejected). + * @returns A Promise for the completion of the callback. + */ + finally(onfinally?: (() => void) | undefined | null): runtime.Types.Utils.JsPromise +} + + + + +/** + * Fields of the Order model + */ +export interface OrderFieldRefs { + readonly id: Prisma.FieldRef<"Order", 'String'> + readonly itemId: Prisma.FieldRef<"Order", 'Int'> + readonly quantity: Prisma.FieldRef<"Order", 'Int'> + readonly status: Prisma.FieldRef<"Order", 'String'> + readonly createdAt: Prisma.FieldRef<"Order", 'DateTime'> + readonly updatedAt: Prisma.FieldRef<"Order", 'DateTime'> +} + + +// Custom InputTypes +/** + * Order findUnique + */ +export type OrderFindUniqueArgs = { + /** + * Select specific fields to fetch from the Order + */ + select?: Prisma.OrderSelect | null + /** + * Omit specific fields from the Order + */ + omit?: Prisma.OrderOmit | null + /** + * Filter, which Order to fetch. + */ + where: Prisma.OrderWhereUniqueInput +} + +/** + * Order findUniqueOrThrow + */ +export type OrderFindUniqueOrThrowArgs = { + /** + * Select specific fields to fetch from the Order + */ + select?: Prisma.OrderSelect | null + /** + * Omit specific fields from the Order + */ + omit?: Prisma.OrderOmit | null + /** + * Filter, which Order to fetch. + */ + where: Prisma.OrderWhereUniqueInput +} + +/** + * Order findFirst + */ +export type OrderFindFirstArgs = { + /** + * Select specific fields to fetch from the Order + */ + select?: Prisma.OrderSelect | null + /** + * Omit specific fields from the Order + */ + omit?: Prisma.OrderOmit | null + /** + * Filter, which Order to fetch. + */ + where?: Prisma.OrderWhereInput + /** + * {@link https://www.prisma.io/docs/concepts/components/prisma-client/sorting Sorting Docs} + * + * Determine the order of Orders to fetch. + */ + orderBy?: Prisma.OrderOrderByWithRelationInput | Prisma.OrderOrderByWithRelationInput[] + /** + * {@link https://www.prisma.io/docs/concepts/components/prisma-client/pagination#cursor-based-pagination Cursor Docs} + * + * Sets the position for searching for Orders. + */ + cursor?: Prisma.OrderWhereUniqueInput + /** + * {@link https://www.prisma.io/docs/concepts/components/prisma-client/pagination Pagination Docs} + * + * Take `±n` Orders from the position of the cursor. + */ + take?: number + /** + * {@link https://www.prisma.io/docs/concepts/components/prisma-client/pagination Pagination Docs} + * + * Skip the first `n` Orders. + */ + skip?: number + /** + * {@link https://www.prisma.io/docs/concepts/components/prisma-client/distinct Distinct Docs} + * + * Filter by unique combinations of Orders. + */ + distinct?: Prisma.OrderScalarFieldEnum | Prisma.OrderScalarFieldEnum[] +} + +/** + * Order findFirstOrThrow + */ +export type OrderFindFirstOrThrowArgs = { + /** + * Select specific fields to fetch from the Order + */ + select?: Prisma.OrderSelect | null + /** + * Omit specific fields from the Order + */ + omit?: Prisma.OrderOmit | null + /** + * Filter, which Order to fetch. + */ + where?: Prisma.OrderWhereInput + /** + * {@link https://www.prisma.io/docs/concepts/components/prisma-client/sorting Sorting Docs} + * + * Determine the order of Orders to fetch. + */ + orderBy?: Prisma.OrderOrderByWithRelationInput | Prisma.OrderOrderByWithRelationInput[] + /** + * {@link https://www.prisma.io/docs/concepts/components/prisma-client/pagination#cursor-based-pagination Cursor Docs} + * + * Sets the position for searching for Orders. + */ + cursor?: Prisma.OrderWhereUniqueInput + /** + * {@link https://www.prisma.io/docs/concepts/components/prisma-client/pagination Pagination Docs} + * + * Take `±n` Orders from the position of the cursor. + */ + take?: number + /** + * {@link https://www.prisma.io/docs/concepts/components/prisma-client/pagination Pagination Docs} + * + * Skip the first `n` Orders. + */ + skip?: number + /** + * {@link https://www.prisma.io/docs/concepts/components/prisma-client/distinct Distinct Docs} + * + * Filter by unique combinations of Orders. + */ + distinct?: Prisma.OrderScalarFieldEnum | Prisma.OrderScalarFieldEnum[] +} + +/** + * Order findMany + */ +export type OrderFindManyArgs = { + /** + * Select specific fields to fetch from the Order + */ + select?: Prisma.OrderSelect | null + /** + * Omit specific fields from the Order + */ + omit?: Prisma.OrderOmit | null + /** + * Filter, which Orders to fetch. + */ + where?: Prisma.OrderWhereInput + /** + * {@link https://www.prisma.io/docs/concepts/components/prisma-client/sorting Sorting Docs} + * + * Determine the order of Orders to fetch. + */ + orderBy?: Prisma.OrderOrderByWithRelationInput | Prisma.OrderOrderByWithRelationInput[] + /** + * {@link https://www.prisma.io/docs/concepts/components/prisma-client/pagination#cursor-based-pagination Cursor Docs} + * + * Sets the position for listing Orders. + */ + cursor?: Prisma.OrderWhereUniqueInput + /** + * {@link https://www.prisma.io/docs/concepts/components/prisma-client/pagination Pagination Docs} + * + * Take `±n` Orders from the position of the cursor. + */ + take?: number + /** + * {@link https://www.prisma.io/docs/concepts/components/prisma-client/pagination Pagination Docs} + * + * Skip the first `n` Orders. + */ + skip?: number + distinct?: Prisma.OrderScalarFieldEnum | Prisma.OrderScalarFieldEnum[] +} + +/** + * Order create + */ +export type OrderCreateArgs = { + /** + * Select specific fields to fetch from the Order + */ + select?: Prisma.OrderSelect | null + /** + * Omit specific fields from the Order + */ + omit?: Prisma.OrderOmit | null + /** + * The data needed to create a Order. + */ + data: Prisma.XOR +} + +/** + * Order createMany + */ +export type OrderCreateManyArgs = { + /** + * The data used to create many Orders. + */ + data: Prisma.OrderCreateManyInput | Prisma.OrderCreateManyInput[] + skipDuplicates?: boolean +} + +/** + * Order createManyAndReturn + */ +export type OrderCreateManyAndReturnArgs = { + /** + * Select specific fields to fetch from the Order + */ + select?: Prisma.OrderSelectCreateManyAndReturn | null + /** + * Omit specific fields from the Order + */ + omit?: Prisma.OrderOmit | null + /** + * The data used to create many Orders. + */ + data: Prisma.OrderCreateManyInput | Prisma.OrderCreateManyInput[] + skipDuplicates?: boolean +} + +/** + * Order update + */ +export type OrderUpdateArgs = { + /** + * Select specific fields to fetch from the Order + */ + select?: Prisma.OrderSelect | null + /** + * Omit specific fields from the Order + */ + omit?: Prisma.OrderOmit | null + /** + * The data needed to update a Order. + */ + data: Prisma.XOR + /** + * Choose, which Order to update. + */ + where: Prisma.OrderWhereUniqueInput +} + +/** + * Order updateMany + */ +export type OrderUpdateManyArgs = { + /** + * The data used to update Orders. + */ + data: Prisma.XOR + /** + * Filter which Orders to update + */ + where?: Prisma.OrderWhereInput + /** + * Limit how many Orders to update. + */ + limit?: number +} + +/** + * Order updateManyAndReturn + */ +export type OrderUpdateManyAndReturnArgs = { + /** + * Select specific fields to fetch from the Order + */ + select?: Prisma.OrderSelectUpdateManyAndReturn | null + /** + * Omit specific fields from the Order + */ + omit?: Prisma.OrderOmit | null + /** + * The data used to update Orders. + */ + data: Prisma.XOR + /** + * Filter which Orders to update + */ + where?: Prisma.OrderWhereInput + /** + * Limit how many Orders to update. + */ + limit?: number +} + +/** + * Order upsert + */ +export type OrderUpsertArgs = { + /** + * Select specific fields to fetch from the Order + */ + select?: Prisma.OrderSelect | null + /** + * Omit specific fields from the Order + */ + omit?: Prisma.OrderOmit | null + /** + * The filter to search for the Order to update in case it exists. + */ + where: Prisma.OrderWhereUniqueInput + /** + * In case the Order found by the `where` argument doesn't exist, create a new Order with this data. + */ + create: Prisma.XOR + /** + * In case the Order was found with the provided `where` argument, update it with this data. + */ + update: Prisma.XOR +} + +/** + * Order delete + */ +export type OrderDeleteArgs = { + /** + * Select specific fields to fetch from the Order + */ + select?: Prisma.OrderSelect | null + /** + * Omit specific fields from the Order + */ + omit?: Prisma.OrderOmit | null + /** + * Filter which Order to delete. + */ + where: Prisma.OrderWhereUniqueInput +} + +/** + * Order deleteMany + */ +export type OrderDeleteManyArgs = { + /** + * Filter which Orders to delete + */ + where?: Prisma.OrderWhereInput + /** + * Limit how many Orders to delete. + */ + limit?: number +} + +/** + * Order without action + */ +export type OrderDefaultArgs = { + /** + * Select specific fields to fetch from the Order + */ + select?: Prisma.OrderSelect | null + /** + * Omit specific fields from the Order + */ + omit?: Prisma.OrderOmit | null +} diff --git a/services/order-service/src/index.ts b/services/order-service/src/index.ts new file mode 100644 index 0000000..38cc33c --- /dev/null +++ b/services/order-service/src/index.ts @@ -0,0 +1,118 @@ +import express, { Request, Response } from 'express'; +import { PrismaClient } from '@prisma/client'; +import axios from 'axios'; +import cors from 'cors'; +import client from 'prom-client'; + +const app = express(); +const prisma = new PrismaClient(); +const PORT = process.env.PORT || 3001; +const INVENTORY_SERVICE_URL = process.env.INVENTORY_SERVICE_URL || 'http://localhost:3002'; + +app.use(cors()); +app.use(express.json()); + +// Prometheus Metrics +const register = new client.Registry(); +client.collectDefaultMetrics({ register }); + +const httpRequestDurationMicroseconds = new client.Histogram({ + name: 'http_request_duration_seconds', + help: 'Duration of HTTP requests in seconds', + labelNames: ['method', 'route', 'code'], + buckets: [0.1, 0.5, 1, 1.5, 2, 5] +}); +register.registerMetric(httpRequestDurationMicroseconds); + +app.use((req, res, next) => { + const end = httpRequestDurationMicroseconds.startTimer(); + res.on('finish', () => { + end({ method: req.method, route: req.path, code: res.statusCode }); + }); + next(); +}); + +// Health Check +app.get('/health', async (req: Request, res: Response) => { + try { + await prisma.$queryRaw`SELECT 1`; + res.status(200).json({ status: 'UP', db: 'CONNECTED' }); + } catch (error) { + res.status(503).json({ status: 'DOWN', db: 'DISCONNECTED' }); + } +}); + +// Metrics Endpoint +app.get('/metrics', async (req: Request, res: Response) => { + res.setHeader('Content-Type', register.contentType); + res.send(await register.metrics()); +}); + +// Get all orders +app.get('/orders', async (req: Request, res: Response) => { + const orders = await prisma.order.findMany({ orderBy: { createdAt: 'desc' } }); + res.json(orders); +}); + +// Create Order (with Timeout handling) +app.post('/orders', async (req: Request, res: Response) => { + const { productId, quantity } = req.body; + + if (!productId || !quantity) { + res.status(400).json({ error: 'Missing productId or quantity' }); + return; + } + + // 1. Create Order (PENDING) + const order = await prisma.order.create({ + data: { + productId, + quantity, + status: 'PENDING' + } + }); + + try { + // 2. Call Inventory Service with Timeout + // Requirement: return clear timeout error instead of freezing. + // We set timeout to 2000ms (2s). If Inventory takes longer (Gremlin), we fail. + const inventoryResponse = await axios.post(`${INVENTORY_SERVICE_URL}/inventory/deduct`, { + productId, + quantity, + orderId: order.id // For Idempotency + }, { + timeout: 2000 + }); + + if (inventoryResponse.status === 200) { + // 3. Update Order to CONFIRMED + const updatedOrder = await prisma.order.update({ + where: { id: order.id }, + data: { status: 'CONFIRMED' } + }); + res.status(201).json(updatedOrder); + } else { + throw new Error('Inventory deduction failed'); + } + + } catch (error: any) { + console.error("Inventory call failed:", error.message); + + let errorMessage = 'Order failed due to inventory issue'; + if (error.code === 'ECONNABORTED') { + errorMessage = 'Order processing timed out waiting for inventory'; + } + + // Update to FAILED + await prisma.order.update({ + where: { id: order.id }, + data: { status: 'FAILED' } + }); + + res.status(503).json({ error: errorMessage, orderId: order.id, status: 'FAILED' }); + } +}); + +app.listen(PORT, () => { + console.log(`Order Service running on port ${PORT}`); +}); diff --git a/services/order-service/tsconfig.json b/services/order-service/tsconfig.json index bfa0fea..af4a7bc 100644 --- a/services/order-service/tsconfig.json +++ b/services/order-service/tsconfig.json @@ -1,29 +1,12 @@ { - "compilerOptions": { - // Environment setup & latest features - "lib": ["ESNext"], - "target": "ESNext", - "module": "Preserve", - "moduleDetection": "force", - "jsx": "react-jsx", - "allowJs": true, - - // Bundler mode - "moduleResolution": "bundler", - "allowImportingTsExtensions": true, - "verbatimModuleSyntax": true, - "noEmit": true, - - // Best practices - "strict": true, - "skipLibCheck": true, - "noFallthroughCasesInSwitch": true, - "noUncheckedIndexedAccess": true, - "noImplicitOverride": true, - - // Some stricter flags (disabled by default) - "noUnusedLocals": false, - "noUnusedParameters": false, - "noPropertyAccessFromIndexSignature": false - } + "compilerOptions": { + "target": "es2016", + "module": "commonjs", + "outDir": "./dist", + "rootDir": "./src", + "strict": true, + "esModuleInterop": true, + "skipLibCheck": true, + "forceConsistentCasingInFileNames": true + } }