Compare commits
No commits in common. "298898f79d65e2cfaedd4b0981730e11e42e9920" and "839eeac2c2a065d9cfdc2d6fc2ee3ce8408b6eaf" have entirely different histories.
298898f79d
...
839eeac2c2
|
|
@ -10,10 +10,9 @@ CORS_ORIGIN=*
|
|||
# Database Configuration
|
||||
DB_HOST=postgres
|
||||
DB_PORT=5432
|
||||
DB_NAME=banatie_db
|
||||
DB_NAME=banatie
|
||||
DB_USER=banatie_user
|
||||
DB_PASSWORD=banatie_secure_password
|
||||
DATABASE_URL=postgresql://banatie_user:banatie_secure_password@postgres:5432/banatie_db
|
||||
|
||||
# MinIO Storage Configuration (SNMD)
|
||||
MINIO_ROOT_USER=banatie_admin
|
||||
|
|
|
|||
|
|
@ -1,26 +0,0 @@
|
|||
# Monorepo-aware Dockerfile for API Service
|
||||
# Development stage - for docker-compose development with hot reload
|
||||
FROM node:20-alpine AS development
|
||||
WORKDIR /app
|
||||
|
||||
# Install pnpm globally
|
||||
RUN npm install -g pnpm@10.11.0
|
||||
|
||||
# Copy workspace configuration from root
|
||||
COPY pnpm-workspace.yaml package.json pnpm-lock.yaml ./
|
||||
|
||||
# Copy all workspace packages
|
||||
COPY packages/ ./packages/
|
||||
COPY apps/api-service/ ./apps/api-service/
|
||||
|
||||
# Install all dependencies (workspace-aware)
|
||||
RUN pnpm install --frozen-lockfile
|
||||
|
||||
# Set working directory to API service
|
||||
WORKDIR /app/apps/api-service
|
||||
|
||||
# Expose port
|
||||
EXPOSE 3000
|
||||
|
||||
# Use development command with hot reload
|
||||
CMD ["pnpm", "dev"]
|
||||
|
|
@ -36,7 +36,6 @@
|
|||
"pnpm": ">=8.0.0"
|
||||
},
|
||||
"dependencies": {
|
||||
"@banatie/database": "workspace:*",
|
||||
"@google/genai": "^1.17.0",
|
||||
"cors": "^2.8.5",
|
||||
"dotenv": "^17.2.2",
|
||||
|
|
|
|||
|
|
@ -6,8 +6,6 @@ import { generateRouter } from './routes/generate';
|
|||
import { enhanceRouter } from './routes/enhance';
|
||||
import { textToImageRouter } from './routes/textToImage';
|
||||
import { imagesRouter } from './routes/images';
|
||||
import bootstrapRoutes from './routes/bootstrap';
|
||||
import adminKeysRoutes from './routes/admin/keys';
|
||||
import { errorHandler, notFoundHandler } from './middleware/errorHandler';
|
||||
|
||||
// Load environment variables
|
||||
|
|
@ -27,16 +25,9 @@ export const appConfig: Config = {
|
|||
export const createApp = (): Application => {
|
||||
const app = express();
|
||||
|
||||
// Middleware - CORS configuration
|
||||
const corsOrigin = process.env['CORS_ORIGIN']?.split(',') || [
|
||||
'http://localhost:3001', // Landing
|
||||
'http://localhost:3002', // Studio
|
||||
'http://localhost:3003', // Admin
|
||||
'*' // Allow all for development
|
||||
];
|
||||
|
||||
// Middleware
|
||||
app.use(cors({
|
||||
origin: corsOrigin,
|
||||
origin: process.env['CORS_ORIGIN'] || '*',
|
||||
credentials: true
|
||||
}));
|
||||
|
||||
|
|
@ -88,14 +79,7 @@ export const createApp = (): Application => {
|
|||
res.json(info);
|
||||
});
|
||||
|
||||
// Public routes (no authentication)
|
||||
// Bootstrap route (no auth, but works only once)
|
||||
app.use('/api/bootstrap', bootstrapRoutes);
|
||||
|
||||
// Admin routes (require master key)
|
||||
app.use('/api/admin/keys', adminKeysRoutes);
|
||||
|
||||
// Protected API routes (require valid API key)
|
||||
// Mount API routes
|
||||
app.use('/api', generateRouter);
|
||||
app.use('/api', enhanceRouter);
|
||||
app.use('/api', textToImageRouter);
|
||||
|
|
|
|||
|
|
@ -1,8 +0,0 @@
|
|||
import { createDbClient } from '@banatie/database';
|
||||
|
||||
const DATABASE_URL = process.env['DATABASE_URL'] ||
|
||||
'postgresql://banatie_user:banatie_secure_password@localhost:5434/banatie_db';
|
||||
|
||||
export const db = createDbClient(DATABASE_URL);
|
||||
|
||||
console.log(`[${new Date().toISOString()}] Database client initialized - ${new URL(DATABASE_URL).host}`);
|
||||
|
|
@ -1,93 +0,0 @@
|
|||
import { Request, Response, NextFunction } from 'express';
|
||||
|
||||
/**
|
||||
* Simple in-memory rate limiter
|
||||
* Tracks requests per API key
|
||||
*/
|
||||
class RateLimiter {
|
||||
private requests: Map<string, { count: number; resetAt: number }> = new Map();
|
||||
private readonly limit: number;
|
||||
private readonly windowMs: number;
|
||||
|
||||
constructor(limit: number = 100, windowMs: number = 60 * 60 * 1000) {
|
||||
this.limit = limit;
|
||||
this.windowMs = windowMs;
|
||||
|
||||
// Cleanup old entries every 5 minutes
|
||||
setInterval(() => this.cleanup(), 5 * 60 * 1000);
|
||||
}
|
||||
|
||||
check(keyId: string): { allowed: boolean; remaining: number; resetAt: number } {
|
||||
const now = Date.now();
|
||||
const record = this.requests.get(keyId);
|
||||
|
||||
if (!record || record.resetAt < now) {
|
||||
// Create new window
|
||||
const resetAt = now + this.windowMs;
|
||||
this.requests.set(keyId, { count: 1, resetAt });
|
||||
return { allowed: true, remaining: this.limit - 1, resetAt };
|
||||
}
|
||||
|
||||
if (record.count >= this.limit) {
|
||||
return { allowed: false, remaining: 0, resetAt: record.resetAt };
|
||||
}
|
||||
|
||||
// Increment counter
|
||||
record.count++;
|
||||
return {
|
||||
allowed: true,
|
||||
remaining: this.limit - record.count,
|
||||
resetAt: record.resetAt
|
||||
};
|
||||
}
|
||||
|
||||
private cleanup() {
|
||||
const now = Date.now();
|
||||
for (const [keyId, record] of this.requests.entries()) {
|
||||
if (record.resetAt < now) {
|
||||
this.requests.delete(keyId);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const rateLimiter = new RateLimiter(100, 60 * 60 * 1000); // 100 requests per hour
|
||||
|
||||
/**
|
||||
* Rate limiting middleware
|
||||
* Must be used AFTER validateApiKey middleware
|
||||
*/
|
||||
export function rateLimitByApiKey(
|
||||
req: Request,
|
||||
res: Response,
|
||||
next: NextFunction
|
||||
): void {
|
||||
if (!req.apiKey) {
|
||||
next();
|
||||
return;
|
||||
}
|
||||
|
||||
const result = rateLimiter.check(req.apiKey.id);
|
||||
|
||||
// Add rate limit headers
|
||||
res.setHeader('X-RateLimit-Limit', '100');
|
||||
res.setHeader('X-RateLimit-Remaining', result.remaining.toString());
|
||||
res.setHeader('X-RateLimit-Reset', new Date(result.resetAt).toISOString());
|
||||
|
||||
if (!result.allowed) {
|
||||
const retryAfter = Math.ceil((result.resetAt - Date.now()) / 1000);
|
||||
|
||||
console.warn(`[${new Date().toISOString()}] Rate limit exceeded: ${req.apiKey.id} (${req.apiKey.keyType}) - reset: ${new Date(result.resetAt).toISOString()}`);
|
||||
|
||||
res.status(429)
|
||||
.setHeader('Retry-After', retryAfter.toString())
|
||||
.json({
|
||||
error: 'Rate limit exceeded',
|
||||
message: `Too many requests. Retry after ${retryAfter} seconds`,
|
||||
retryAfter,
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
next();
|
||||
}
|
||||
|
|
@ -1,31 +0,0 @@
|
|||
import { Request, Response, NextFunction } from 'express';
|
||||
|
||||
/**
|
||||
* Middleware to ensure the API key is a master key
|
||||
* Must be used AFTER validateApiKey middleware
|
||||
*/
|
||||
export function requireMasterKey(
|
||||
req: Request,
|
||||
res: Response,
|
||||
next: NextFunction
|
||||
): void {
|
||||
if (!req.apiKey) {
|
||||
res.status(401).json({
|
||||
error: 'Authentication required',
|
||||
message: 'This endpoint requires authentication',
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
if (req.apiKey.keyType !== 'master') {
|
||||
console.warn(`[${new Date().toISOString()}] Non-master key attempted admin action: ${req.apiKey.id} (${req.apiKey.keyType}) - ${req.path}`);
|
||||
|
||||
res.status(403).json({
|
||||
error: 'Master key required',
|
||||
message: 'This endpoint requires a master API key',
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
next();
|
||||
}
|
||||
|
|
@ -1,58 +0,0 @@
|
|||
import { Request, Response, NextFunction } from 'express';
|
||||
import { ApiKeyService } from '../../services/ApiKeyService';
|
||||
import type { ApiKey } from '@banatie/database';
|
||||
|
||||
// Extend Express Request type to include apiKey
|
||||
declare global {
|
||||
namespace Express {
|
||||
interface Request {
|
||||
apiKey?: ApiKey;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const apiKeyService = new ApiKeyService();
|
||||
|
||||
/**
|
||||
* Middleware to validate API key from X-API-Key header
|
||||
*/
|
||||
export async function validateApiKey(
|
||||
req: Request,
|
||||
res: Response,
|
||||
next: NextFunction
|
||||
): Promise<void> {
|
||||
const providedKey = req.headers['x-api-key'] as string;
|
||||
|
||||
if (!providedKey) {
|
||||
res.status(401).json({
|
||||
error: 'Missing API key',
|
||||
message: 'Provide your API key via X-API-Key header',
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
const apiKey = await apiKeyService.validateKey(providedKey);
|
||||
|
||||
if (!apiKey) {
|
||||
res.status(401).json({
|
||||
error: 'Invalid API key',
|
||||
message: 'The provided API key is invalid, expired, or revoked',
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
// Attach to request for use in routes
|
||||
req.apiKey = apiKey;
|
||||
|
||||
console.log(`[${new Date().toISOString()}] API key validated: ${apiKey.id} (${apiKey.keyType})`);
|
||||
|
||||
next();
|
||||
} catch (error) {
|
||||
console.error(`[${new Date().toISOString()}] API key validation error:`, error);
|
||||
res.status(500).json({
|
||||
error: 'Authentication failed',
|
||||
message: 'An error occurred during authentication',
|
||||
});
|
||||
}
|
||||
}
|
||||
|
|
@ -1,137 +0,0 @@
|
|||
import express from 'express';
|
||||
import { ApiKeyService } from '../../services/ApiKeyService';
|
||||
import { validateApiKey } from '../../middleware/auth/validateApiKey';
|
||||
import { requireMasterKey } from '../../middleware/auth/requireMasterKey';
|
||||
|
||||
const router = express.Router();
|
||||
const apiKeyService = new ApiKeyService();
|
||||
|
||||
// All admin routes require master key
|
||||
router.use(validateApiKey);
|
||||
router.use(requireMasterKey);
|
||||
|
||||
/**
|
||||
* Create a new API key
|
||||
* POST /api/admin/keys
|
||||
*/
|
||||
router.post('/', async (req, res) => {
|
||||
try {
|
||||
const { type, projectId, name, expiresInDays } = req.body;
|
||||
|
||||
// Validation
|
||||
if (!type || !['master', 'project'].includes(type)) {
|
||||
return res.status(400).json({
|
||||
error: 'Invalid type',
|
||||
message: 'Type must be either "master" or "project"',
|
||||
});
|
||||
}
|
||||
|
||||
if (type === 'project' && !projectId) {
|
||||
return res.status(400).json({
|
||||
error: 'Missing projectId',
|
||||
message: 'Project keys require a projectId',
|
||||
});
|
||||
}
|
||||
|
||||
// Create key
|
||||
const result = type === 'master'
|
||||
? await apiKeyService.createMasterKey(name, req.apiKey!.id)
|
||||
: await apiKeyService.createProjectKey(
|
||||
projectId,
|
||||
name,
|
||||
req.apiKey!.id,
|
||||
expiresInDays || 90
|
||||
);
|
||||
|
||||
console.log(`[${new Date().toISOString()}] New API key created by admin: ${result.metadata.id} (${result.metadata.keyType}) - by: ${req.apiKey!.id}`);
|
||||
|
||||
res.status(201).json({
|
||||
apiKey: result.key,
|
||||
metadata: {
|
||||
id: result.metadata.id,
|
||||
type: result.metadata.keyType,
|
||||
projectId: result.metadata.projectId,
|
||||
name: result.metadata.name,
|
||||
expiresAt: result.metadata.expiresAt,
|
||||
scopes: result.metadata.scopes,
|
||||
createdAt: result.metadata.createdAt,
|
||||
},
|
||||
message: 'IMPORTANT: Save this key securely. You will not see it again!',
|
||||
});
|
||||
} catch (error) {
|
||||
console.error(`[${new Date().toISOString()}] Error creating API key:`, error);
|
||||
res.status(500).json({
|
||||
error: 'Failed to create API key',
|
||||
message: 'An error occurred while creating the key',
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
/**
|
||||
* List all API keys
|
||||
* GET /api/admin/keys
|
||||
*/
|
||||
router.get('/', async (req, res) => {
|
||||
try {
|
||||
const keys = await apiKeyService.listKeys();
|
||||
|
||||
// Don't expose key hashes
|
||||
const safeKeys = keys.map(key => ({
|
||||
id: key.id,
|
||||
type: key.keyType,
|
||||
projectId: key.projectId,
|
||||
name: key.name,
|
||||
scopes: key.scopes,
|
||||
isActive: key.isActive,
|
||||
createdAt: key.createdAt,
|
||||
expiresAt: key.expiresAt,
|
||||
lastUsedAt: key.lastUsedAt,
|
||||
createdBy: key.createdBy,
|
||||
}));
|
||||
|
||||
res.json({
|
||||
keys: safeKeys,
|
||||
total: safeKeys.length,
|
||||
});
|
||||
} catch (error) {
|
||||
console.error(`[${new Date().toISOString()}] Error listing API keys:`, error);
|
||||
res.status(500).json({
|
||||
error: 'Failed to list keys',
|
||||
message: 'An error occurred while fetching keys',
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
/**
|
||||
* Revoke an API key
|
||||
* DELETE /api/admin/keys/:keyId
|
||||
*/
|
||||
router.delete('/:keyId', async (req, res) => {
|
||||
try {
|
||||
const { keyId } = req.params;
|
||||
|
||||
const success = await apiKeyService.revokeKey(keyId);
|
||||
|
||||
if (!success) {
|
||||
return res.status(404).json({
|
||||
error: 'Key not found',
|
||||
message: 'The specified API key does not exist',
|
||||
});
|
||||
}
|
||||
|
||||
console.log(`[${new Date().toISOString()}] API key revoked: ${keyId} - by: ${req.apiKey!.id}`);
|
||||
|
||||
res.json({
|
||||
message: 'API key revoked successfully',
|
||||
keyId,
|
||||
});
|
||||
} catch (error) {
|
||||
console.error(`[${new Date().toISOString()}] Error revoking API key:`, error);
|
||||
res.status(500).json({
|
||||
error: 'Failed to revoke key',
|
||||
message: 'An error occurred while revoking the key',
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
export default router;
|
||||
|
|
@ -1,47 +0,0 @@
|
|||
import express from 'express';
|
||||
import { ApiKeyService } from '../services/ApiKeyService';
|
||||
|
||||
const router = express.Router();
|
||||
const apiKeyService = new ApiKeyService();
|
||||
|
||||
/**
|
||||
* Bootstrap endpoint - creates the first master key
|
||||
* Only works when no keys exist in the database
|
||||
*
|
||||
* POST /api/bootstrap/initial-key
|
||||
*/
|
||||
router.post('/initial-key', async (req, res) => {
|
||||
try {
|
||||
// Check if any keys already exist
|
||||
const hasKeys = await apiKeyService.hasAnyKeys();
|
||||
|
||||
if (hasKeys) {
|
||||
console.warn(`[${new Date().toISOString()}] Bootstrap attempt when keys already exist`);
|
||||
return res.status(403).json({
|
||||
error: 'Bootstrap not allowed',
|
||||
message: 'API keys already exist. Use /api/admin/keys to create new keys.',
|
||||
});
|
||||
}
|
||||
|
||||
// Create first master key
|
||||
const { key, metadata } = await apiKeyService.createMasterKey('Initial Master Key');
|
||||
|
||||
console.log(`[${new Date().toISOString()}] Initial master key created via bootstrap: ${metadata.id}`);
|
||||
|
||||
res.status(201).json({
|
||||
apiKey: key,
|
||||
type: metadata.keyType,
|
||||
name: metadata.name,
|
||||
expiresAt: metadata.expiresAt,
|
||||
message: 'IMPORTANT: Save this key securely. You will not see it again!',
|
||||
});
|
||||
} catch (error) {
|
||||
console.error(`[${new Date().toISOString()}] Bootstrap error:`, error);
|
||||
res.status(500).json({
|
||||
error: 'Bootstrap failed',
|
||||
message: 'Failed to create initial API key',
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
export default router;
|
||||
|
|
@ -14,8 +14,6 @@ import {
|
|||
logEnhancementResult,
|
||||
} from "../middleware/promptEnhancement";
|
||||
import { asyncHandler } from "../middleware/errorHandler";
|
||||
import { validateApiKey } from "../middleware/auth/validateApiKey";
|
||||
import { rateLimitByApiKey } from "../middleware/auth/rateLimiter";
|
||||
import { GenerateImageResponse } from "../types/api";
|
||||
// Create router
|
||||
export const generateRouter: RouterType = Router();
|
||||
|
|
@ -28,10 +26,6 @@ let imageGenService: ImageGenService;
|
|||
*/
|
||||
generateRouter.post(
|
||||
"/generate",
|
||||
// Authentication middleware
|
||||
validateApiKey,
|
||||
rateLimitByApiKey,
|
||||
|
||||
// File upload middleware
|
||||
uploadReferenceImages,
|
||||
handleUploadErrors,
|
||||
|
|
|
|||
|
|
@ -1,164 +0,0 @@
|
|||
import crypto from 'crypto';
|
||||
import { db } from '../db';
|
||||
import { apiKeys, type ApiKey, type NewApiKey } from '@banatie/database';
|
||||
import { eq, and, desc } from 'drizzle-orm';
|
||||
|
||||
export class ApiKeyService {
|
||||
/**
|
||||
* Generate a new API key
|
||||
* Format: bnt_{64_hex_chars}
|
||||
*/
|
||||
private generateKey(): { fullKey: string; keyHash: string; keyPrefix: string } {
|
||||
const secret = crypto.randomBytes(32).toString('hex'); // 64 chars
|
||||
const keyPrefix = 'bnt_';
|
||||
const fullKey = keyPrefix + secret;
|
||||
|
||||
// Hash for storage (SHA-256)
|
||||
const keyHash = crypto
|
||||
.createHash('sha256')
|
||||
.update(fullKey)
|
||||
.digest('hex');
|
||||
|
||||
return { fullKey, keyHash, keyPrefix };
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a master key (admin access, never expires)
|
||||
*/
|
||||
async createMasterKey(name?: string, createdBy?: string): Promise<{ key: string; metadata: ApiKey }> {
|
||||
const { fullKey, keyHash, keyPrefix } = this.generateKey();
|
||||
|
||||
const [newKey] = await db.insert(apiKeys).values({
|
||||
keyHash,
|
||||
keyPrefix,
|
||||
keyType: 'master',
|
||||
projectId: null,
|
||||
scopes: ['*'], // Full access
|
||||
name: name || 'Master Key',
|
||||
expiresAt: null, // Never expires
|
||||
createdBy: createdBy || null,
|
||||
}).returning();
|
||||
|
||||
console.log(`[${new Date().toISOString()}] Master key created: ${newKey?.id} - ${newKey?.name}`);
|
||||
|
||||
return { key: fullKey, metadata: newKey! };
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a project key (expires in 90 days)
|
||||
*/
|
||||
async createProjectKey(
|
||||
projectId: string,
|
||||
name?: string,
|
||||
createdBy?: string,
|
||||
expiresInDays: number = 90
|
||||
): Promise<{ key: string; metadata: ApiKey }> {
|
||||
const { fullKey, keyHash, keyPrefix } = this.generateKey();
|
||||
|
||||
const expiresAt = new Date();
|
||||
expiresAt.setDate(expiresAt.getDate() + expiresInDays);
|
||||
|
||||
const [newKey] = await db.insert(apiKeys).values({
|
||||
keyHash,
|
||||
keyPrefix,
|
||||
keyType: 'project',
|
||||
projectId,
|
||||
scopes: ['generate', 'read'],
|
||||
name: name || `Project Key - ${projectId}`,
|
||||
expiresAt,
|
||||
createdBy: createdBy || null,
|
||||
}).returning();
|
||||
|
||||
console.log(`[${new Date().toISOString()}] Project key created: ${newKey?.id} - ${projectId} - expires: ${expiresAt.toISOString()}`);
|
||||
|
||||
return { key: fullKey, metadata: newKey! };
|
||||
}
|
||||
|
||||
/**
|
||||
* Validate an API key
|
||||
* Returns null if invalid/expired/revoked
|
||||
*/
|
||||
async validateKey(providedKey: string): Promise<ApiKey | null> {
|
||||
if (!providedKey || !providedKey.startsWith('bnt_')) {
|
||||
return null;
|
||||
}
|
||||
|
||||
// Hash the provided key
|
||||
const keyHash = crypto
|
||||
.createHash('sha256')
|
||||
.update(providedKey)
|
||||
.digest('hex');
|
||||
|
||||
// Find in database
|
||||
const [key] = await db
|
||||
.select()
|
||||
.from(apiKeys)
|
||||
.where(
|
||||
and(
|
||||
eq(apiKeys.keyHash, keyHash),
|
||||
eq(apiKeys.isActive, true)
|
||||
)
|
||||
)
|
||||
.limit(1);
|
||||
|
||||
if (!key) {
|
||||
console.warn(`[${new Date().toISOString()}] Invalid API key attempt: ${providedKey.substring(0, 10)}...`);
|
||||
return null;
|
||||
}
|
||||
|
||||
// Check expiration
|
||||
if (key.expiresAt && key.expiresAt < new Date()) {
|
||||
console.warn(`[${new Date().toISOString()}] Expired API key used: ${key.id} - expired: ${key.expiresAt.toISOString()}`);
|
||||
return null;
|
||||
}
|
||||
|
||||
// Update last used timestamp (async, don't wait)
|
||||
db.update(apiKeys)
|
||||
.set({ lastUsedAt: new Date() })
|
||||
.where(eq(apiKeys.id, key.id))
|
||||
.execute()
|
||||
.catch(err => console.error(`[${new Date().toISOString()}] Failed to update lastUsedAt:`, err));
|
||||
|
||||
return key;
|
||||
}
|
||||
|
||||
/**
|
||||
* Revoke a key (soft delete)
|
||||
*/
|
||||
async revokeKey(keyId: string): Promise<boolean> {
|
||||
const result = await db
|
||||
.update(apiKeys)
|
||||
.set({ isActive: false })
|
||||
.where(eq(apiKeys.id, keyId))
|
||||
.returning();
|
||||
|
||||
if (result.length > 0) {
|
||||
console.log(`[${new Date().toISOString()}] API key revoked: ${keyId}`);
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* List all keys (for admin)
|
||||
*/
|
||||
async listKeys(): Promise<ApiKey[]> {
|
||||
return db
|
||||
.select()
|
||||
.from(apiKeys)
|
||||
.orderBy(desc(apiKeys.createdAt));
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if any keys exist (for bootstrap)
|
||||
*/
|
||||
async hasAnyKeys(): Promise<boolean> {
|
||||
const keys = await db
|
||||
.select({ id: apiKeys.id })
|
||||
.from(apiKeys)
|
||||
.limit(1);
|
||||
|
||||
return keys.length > 0;
|
||||
}
|
||||
}
|
||||
|
|
@ -2,16 +2,14 @@
|
|||
services:
|
||||
app:
|
||||
build:
|
||||
context: .
|
||||
dockerfile: ./apps/api-service/Dockerfile.mono
|
||||
context: ./apps/api-service
|
||||
target: development
|
||||
container_name: banatie-app
|
||||
ports:
|
||||
- "3000:3000"
|
||||
volumes:
|
||||
- ./apps/api-service/src:/app/apps/api-service/src
|
||||
- ./apps/api-service/logs:/app/apps/api-service/logs
|
||||
- ./packages:/app/packages
|
||||
- ./apps/api-service/src:/app/src
|
||||
- ./apps/api-service/logs:/app/logs
|
||||
networks:
|
||||
- banatie-network
|
||||
depends_on:
|
||||
|
|
@ -36,11 +34,11 @@ services:
|
|||
networks:
|
||||
- banatie-network
|
||||
environment:
|
||||
POSTGRES_DB: banatie_db
|
||||
POSTGRES_DB: banatie
|
||||
POSTGRES_USER: banatie_user
|
||||
POSTGRES_PASSWORD: banatie_secure_password
|
||||
healthcheck:
|
||||
test: ["CMD-SHELL", "pg_isready -U banatie_user -d banatie_db"]
|
||||
test: ["CMD-SHELL", "pg_isready -U banatie_user -d banatie"]
|
||||
interval: 30s
|
||||
timeout: 10s
|
||||
retries: 3
|
||||
|
|
@ -86,46 +84,45 @@ services:
|
|||
depends_on:
|
||||
minio:
|
||||
condition: service_healthy
|
||||
entrypoint:
|
||||
- /bin/sh
|
||||
- -c
|
||||
- |
|
||||
echo 'Setting up MinIO alias...'
|
||||
mc alias set storage http://minio:9000 $${MINIO_ROOT_USER} $${MINIO_ROOT_PASSWORD}
|
||||
entrypoint: >
|
||||
/bin/sh -c "
|
||||
echo 'Setting up MinIO alias...';
|
||||
mc alias set storage http://minio:9000 ${MINIO_ROOT_USER} ${MINIO_ROOT_PASSWORD};
|
||||
|
||||
echo 'Creating main bucket...'
|
||||
mc mb --ignore-existing storage/banatie
|
||||
echo 'Creating main bucket...';
|
||||
mc mb --ignore-existing storage/banatie;
|
||||
|
||||
echo 'Creating service user...'
|
||||
mc admin user add storage banatie_service banatie_service_key_2024
|
||||
echo 'Creating service user...';
|
||||
mc admin user add storage banatie_service banatie_service_key_2024;
|
||||
|
||||
echo 'Attaching readwrite policy to service user...'
|
||||
mc admin policy attach storage readwrite --user=banatie_service
|
||||
echo 'Attaching readwrite policy to service user...';
|
||||
mc admin policy attach storage readwrite --user=banatie_service;
|
||||
|
||||
echo 'Setting up lifecycle policy...'
|
||||
cat > /tmp/lifecycle.json <<'LIFECYCLE'
|
||||
{
|
||||
"Rules": [
|
||||
{
|
||||
"ID": "temp-cleanup",
|
||||
"Status": "Enabled",
|
||||
"Filter": {
|
||||
"Prefix": "temp/"
|
||||
},
|
||||
"Expiration": {
|
||||
"Days": 7
|
||||
}
|
||||
echo 'Setting up lifecycle policy...';
|
||||
cat > /tmp/lifecycle.json << EOF
|
||||
{
|
||||
\"Rules\": [
|
||||
{
|
||||
\"ID\": \"temp-cleanup\",
|
||||
\"Status\": \"Enabled\",
|
||||
\"Filter\": {
|
||||
\"Prefix\": \"temp/\"
|
||||
},
|
||||
\"Expiration\": {
|
||||
\"Days\": 7
|
||||
}
|
||||
]
|
||||
}
|
||||
LIFECYCLE
|
||||
mc ilm import storage/banatie < /tmp/lifecycle.json
|
||||
}
|
||||
]
|
||||
}
|
||||
EOF
|
||||
mc ilm import storage/banatie < /tmp/lifecycle.json;
|
||||
|
||||
echo 'Storage initialization completed!'
|
||||
echo 'Bucket: banatie'
|
||||
echo 'Using presigned URLs for secure access'
|
||||
echo 'SNMD mode: Full S3 compatibility enabled'
|
||||
exit 0
|
||||
echo 'Storage initialization completed!';
|
||||
echo 'Bucket: banatie';
|
||||
echo 'Using presigned URLs for secure access';
|
||||
echo 'SNMD mode: Full S3 compatibility enabled';
|
||||
exit 0;
|
||||
"
|
||||
restart: "no"
|
||||
|
||||
networks:
|
||||
|
|
|
|||
|
|
@ -1,10 +0,0 @@
|
|||
import type { Config } from 'drizzle-kit';
|
||||
|
||||
export default {
|
||||
schema: './src/schema/index.ts',
|
||||
out: './migrations',
|
||||
dialect: 'postgresql',
|
||||
dbCredentials: {
|
||||
url: process.env.DATABASE_URL || 'postgresql://banatie_user:banatie_secure_password@localhost:5434/banatie_db',
|
||||
},
|
||||
} satisfies Config;
|
||||
|
|
@ -1,15 +0,0 @@
|
|||
CREATE TABLE IF NOT EXISTS "api_keys" (
|
||||
"id" uuid PRIMARY KEY DEFAULT gen_random_uuid() NOT NULL,
|
||||
"key_hash" text NOT NULL,
|
||||
"key_prefix" text DEFAULT 'bnt_' NOT NULL,
|
||||
"key_type" text NOT NULL,
|
||||
"project_id" text,
|
||||
"scopes" jsonb DEFAULT '["generate"]'::jsonb NOT NULL,
|
||||
"created_at" timestamp DEFAULT now() NOT NULL,
|
||||
"expires_at" timestamp,
|
||||
"last_used_at" timestamp,
|
||||
"is_active" boolean DEFAULT true NOT NULL,
|
||||
"name" text,
|
||||
"created_by" uuid,
|
||||
CONSTRAINT "api_keys_key_hash_unique" UNIQUE("key_hash")
|
||||
);
|
||||
|
|
@ -1,117 +0,0 @@
|
|||
{
|
||||
"id": "a0f532c8-8e34-4297-a580-060eb8b49306",
|
||||
"prevId": "00000000-0000-0000-0000-000000000000",
|
||||
"version": "7",
|
||||
"dialect": "postgresql",
|
||||
"tables": {
|
||||
"public.api_keys": {
|
||||
"name": "api_keys",
|
||||
"schema": "",
|
||||
"columns": {
|
||||
"id": {
|
||||
"name": "id",
|
||||
"type": "uuid",
|
||||
"primaryKey": true,
|
||||
"notNull": true,
|
||||
"default": "gen_random_uuid()"
|
||||
},
|
||||
"key_hash": {
|
||||
"name": "key_hash",
|
||||
"type": "text",
|
||||
"primaryKey": false,
|
||||
"notNull": true
|
||||
},
|
||||
"key_prefix": {
|
||||
"name": "key_prefix",
|
||||
"type": "text",
|
||||
"primaryKey": false,
|
||||
"notNull": true,
|
||||
"default": "'bnt_'"
|
||||
},
|
||||
"key_type": {
|
||||
"name": "key_type",
|
||||
"type": "text",
|
||||
"primaryKey": false,
|
||||
"notNull": true
|
||||
},
|
||||
"project_id": {
|
||||
"name": "project_id",
|
||||
"type": "text",
|
||||
"primaryKey": false,
|
||||
"notNull": false
|
||||
},
|
||||
"scopes": {
|
||||
"name": "scopes",
|
||||
"type": "jsonb",
|
||||
"primaryKey": false,
|
||||
"notNull": true,
|
||||
"default": "'[\"generate\"]'::jsonb"
|
||||
},
|
||||
"created_at": {
|
||||
"name": "created_at",
|
||||
"type": "timestamp",
|
||||
"primaryKey": false,
|
||||
"notNull": true,
|
||||
"default": "now()"
|
||||
},
|
||||
"expires_at": {
|
||||
"name": "expires_at",
|
||||
"type": "timestamp",
|
||||
"primaryKey": false,
|
||||
"notNull": false
|
||||
},
|
||||
"last_used_at": {
|
||||
"name": "last_used_at",
|
||||
"type": "timestamp",
|
||||
"primaryKey": false,
|
||||
"notNull": false
|
||||
},
|
||||
"is_active": {
|
||||
"name": "is_active",
|
||||
"type": "boolean",
|
||||
"primaryKey": false,
|
||||
"notNull": true,
|
||||
"default": true
|
||||
},
|
||||
"name": {
|
||||
"name": "name",
|
||||
"type": "text",
|
||||
"primaryKey": false,
|
||||
"notNull": false
|
||||
},
|
||||
"created_by": {
|
||||
"name": "created_by",
|
||||
"type": "uuid",
|
||||
"primaryKey": false,
|
||||
"notNull": false
|
||||
}
|
||||
},
|
||||
"indexes": {},
|
||||
"foreignKeys": {},
|
||||
"compositePrimaryKeys": {},
|
||||
"uniqueConstraints": {
|
||||
"api_keys_key_hash_unique": {
|
||||
"name": "api_keys_key_hash_unique",
|
||||
"nullsNotDistinct": false,
|
||||
"columns": [
|
||||
"key_hash"
|
||||
]
|
||||
}
|
||||
},
|
||||
"policies": {},
|
||||
"checkConstraints": {},
|
||||
"isRLSEnabled": false
|
||||
}
|
||||
},
|
||||
"enums": {},
|
||||
"schemas": {},
|
||||
"sequences": {},
|
||||
"roles": {},
|
||||
"policies": {},
|
||||
"views": {},
|
||||
"_meta": {
|
||||
"columns": {},
|
||||
"schemas": {},
|
||||
"tables": {}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,13 +0,0 @@
|
|||
{
|
||||
"version": "7",
|
||||
"dialect": "postgresql",
|
||||
"entries": [
|
||||
{
|
||||
"idx": 0,
|
||||
"version": "7",
|
||||
"when": 1759250997369,
|
||||
"tag": "0000_gifted_sunfire",
|
||||
"breakpoints": true
|
||||
}
|
||||
]
|
||||
}
|
||||
|
|
@ -1,21 +0,0 @@
|
|||
{
|
||||
"name": "@banatie/database",
|
||||
"version": "1.0.0",
|
||||
"private": true,
|
||||
"main": "./src/index.ts",
|
||||
"types": "./src/index.ts",
|
||||
"scripts": {
|
||||
"db:generate": "drizzle-kit generate",
|
||||
"db:push": "drizzle-kit push",
|
||||
"db:studio": "drizzle-kit studio"
|
||||
},
|
||||
"dependencies": {
|
||||
"drizzle-orm": "^0.36.4",
|
||||
"postgres": "^3.4.3"
|
||||
},
|
||||
"devDependencies": {
|
||||
"drizzle-kit": "^0.28.1",
|
||||
"typescript": "^5.9.2",
|
||||
"@types/node": "^20.0.0"
|
||||
}
|
||||
}
|
||||
|
|
@ -1,10 +0,0 @@
|
|||
import { drizzle } from 'drizzle-orm/postgres-js';
|
||||
import postgres from 'postgres';
|
||||
import * as schema from './schema';
|
||||
|
||||
export function createDbClient(connectionString: string) {
|
||||
const queryClient = postgres(connectionString);
|
||||
return drizzle(queryClient, { schema });
|
||||
}
|
||||
|
||||
export type DbClient = ReturnType<typeof createDbClient>;
|
||||
|
|
@ -1,3 +0,0 @@
|
|||
export * from './schema';
|
||||
export * from './client';
|
||||
export type { DbClient } from './client';
|
||||
|
|
@ -1,31 +0,0 @@
|
|||
import { pgTable, uuid, text, timestamp, boolean, jsonb } from 'drizzle-orm/pg-core';
|
||||
|
||||
export const apiKeys = pgTable('api_keys', {
|
||||
id: uuid('id').primaryKey().defaultRandom(),
|
||||
|
||||
// Key data
|
||||
keyHash: text('key_hash').notNull().unique(),
|
||||
keyPrefix: text('key_prefix').notNull().default('bnt_'),
|
||||
|
||||
// Key type: 'master' or 'project'
|
||||
keyType: text('key_type').notNull().$type<'master' | 'project'>(),
|
||||
|
||||
// For project keys
|
||||
projectId: text('project_id'),
|
||||
|
||||
// Permissions (for future use)
|
||||
scopes: jsonb('scopes').$type<string[]>().notNull().default(['generate']),
|
||||
|
||||
// Lifecycle
|
||||
createdAt: timestamp('created_at').notNull().defaultNow(),
|
||||
expiresAt: timestamp('expires_at'), // NULL for master keys, NOW() + 90 days for project
|
||||
lastUsedAt: timestamp('last_used_at'),
|
||||
isActive: boolean('is_active').notNull().default(true),
|
||||
|
||||
// Metadata
|
||||
name: text('name'), // Optional friendly name
|
||||
createdBy: uuid('created_by'), // Which key created this key (for audit)
|
||||
});
|
||||
|
||||
export type ApiKey = typeof apiKeys.$inferSelect;
|
||||
export type NewApiKey = typeof apiKeys.$inferInsert;
|
||||
|
|
@ -1 +0,0 @@
|
|||
export * from './apiKeys';
|
||||
|
|
@ -1,14 +0,0 @@
|
|||
{
|
||||
"compilerOptions": {
|
||||
"target": "ES2022",
|
||||
"module": "ESNext",
|
||||
"moduleResolution": "bundler",
|
||||
"esModuleInterop": true,
|
||||
"strict": true,
|
||||
"skipLibCheck": true,
|
||||
"declaration": true,
|
||||
"declarationMap": true,
|
||||
"outDir": "./dist"
|
||||
},
|
||||
"include": ["src/**/*"]
|
||||
}
|
||||
656
pnpm-lock.yaml
656
pnpm-lock.yaml
|
|
@ -66,9 +66,6 @@ importers:
|
|||
|
||||
apps/api-service:
|
||||
dependencies:
|
||||
'@banatie/database':
|
||||
specifier: workspace:*
|
||||
version: link:../../packages/database
|
||||
'@google/genai':
|
||||
specifier: ^1.17.0
|
||||
version: 1.20.0
|
||||
|
|
@ -259,25 +256,6 @@ importers:
|
|||
specifier: ^3.4.0
|
||||
version: 3.4.17
|
||||
|
||||
packages/database:
|
||||
dependencies:
|
||||
drizzle-orm:
|
||||
specifier: ^0.36.4
|
||||
version: 0.36.4(@types/react@18.3.24)(postgres@3.4.7)(react@18.3.1)
|
||||
postgres:
|
||||
specifier: ^3.4.3
|
||||
version: 3.4.7
|
||||
devDependencies:
|
||||
'@types/node':
|
||||
specifier: ^20.0.0
|
||||
version: 20.19.17
|
||||
drizzle-kit:
|
||||
specifier: ^0.28.1
|
||||
version: 0.28.1
|
||||
typescript:
|
||||
specifier: ^5.9.2
|
||||
version: 5.9.2
|
||||
|
||||
packages:
|
||||
|
||||
'@alloc/quick-lru@5.2.0':
|
||||
|
|
@ -460,9 +438,6 @@ packages:
|
|||
'@dabh/diagnostics@2.0.3':
|
||||
resolution: {integrity: sha512-hrlQOIi7hAfzsMqlGSFyVucrx38O+j6wiGOf//H2ecvIEqYN4ADBSS2iLMh5UFyDunCNniUIPk/q3riFv45xRA==}
|
||||
|
||||
'@drizzle-team/brocli@0.10.2':
|
||||
resolution: {integrity: sha512-z33Il7l5dKjUgGULTqBsQBQwckHh5AbIuxhdsIxDDiZAzBOrZO6q9ogcWC65kU382AfynTfgNumVcNIjuIua6w==}
|
||||
|
||||
'@emnapi/core@1.5.0':
|
||||
resolution: {integrity: sha512-sbP8GzB1WDzacS8fgNPpHlp6C9VZe+SJP3F90W9rLemaQj2PzIuTEl1qDOYQf58YIpyjViI24y9aPWCjEzY2cg==}
|
||||
|
||||
|
|
@ -472,308 +447,102 @@ packages:
|
|||
'@emnapi/wasi-threads@1.1.0':
|
||||
resolution: {integrity: sha512-WI0DdZ8xFSbgMjR1sFsKABJ/C5OnRrjT06JXbZKexJGrDuPTzZdDYfFlsgcCXCyf+suG5QU2e/y1Wo2V/OapLQ==}
|
||||
|
||||
'@esbuild-kit/core-utils@3.3.2':
|
||||
resolution: {integrity: sha512-sPRAnw9CdSsRmEtnsl2WXWdyquogVpB3yZ3dgwJfe8zrOzTsV7cJvmwrKVa+0ma5BoiGJ+BoqkMvawbayKUsqQ==}
|
||||
deprecated: 'Merged into tsx: https://tsx.is'
|
||||
|
||||
'@esbuild-kit/esm-loader@2.6.5':
|
||||
resolution: {integrity: sha512-FxEMIkJKnodyA1OaCUoEvbYRkoZlLZ4d/eXFu9Fh8CbBBgP5EmZxrfTRyN0qpXZ4vOvqnE5YdRdcrmUUXuU+dA==}
|
||||
deprecated: 'Merged into tsx: https://tsx.is'
|
||||
|
||||
'@esbuild/aix-ppc64@0.19.12':
|
||||
resolution: {integrity: sha512-bmoCYyWdEL3wDQIVbcyzRyeKLgk2WtWLTWz1ZIAZF/EGbNOwSA6ew3PftJ1PqMiOOGu0OyFMzG53L0zqIpPeNA==}
|
||||
engines: {node: '>=12'}
|
||||
cpu: [ppc64]
|
||||
os: [aix]
|
||||
|
||||
'@esbuild/aix-ppc64@0.25.10':
|
||||
resolution: {integrity: sha512-0NFWnA+7l41irNuaSVlLfgNT12caWJVLzp5eAVhZ0z1qpxbockccEt3s+149rE64VUI3Ml2zt8Nv5JVc4QXTsw==}
|
||||
engines: {node: '>=18'}
|
||||
cpu: [ppc64]
|
||||
os: [aix]
|
||||
|
||||
'@esbuild/android-arm64@0.18.20':
|
||||
resolution: {integrity: sha512-Nz4rJcchGDtENV0eMKUNa6L12zz2zBDXuhj/Vjh18zGqB44Bi7MBMSXjgunJgjRhCmKOjnPuZp4Mb6OKqtMHLQ==}
|
||||
engines: {node: '>=12'}
|
||||
cpu: [arm64]
|
||||
os: [android]
|
||||
|
||||
'@esbuild/android-arm64@0.19.12':
|
||||
resolution: {integrity: sha512-P0UVNGIienjZv3f5zq0DP3Nt2IE/3plFzuaS96vihvD0Hd6H/q4WXUGpCxD/E8YrSXfNyRPbpTq+T8ZQioSuPA==}
|
||||
engines: {node: '>=12'}
|
||||
cpu: [arm64]
|
||||
os: [android]
|
||||
|
||||
'@esbuild/android-arm64@0.25.10':
|
||||
resolution: {integrity: sha512-LSQa7eDahypv/VO6WKohZGPSJDq5OVOo3UoFR1E4t4Gj1W7zEQMUhI+lo81H+DtB+kP+tDgBp+M4oNCwp6kffg==}
|
||||
engines: {node: '>=18'}
|
||||
cpu: [arm64]
|
||||
os: [android]
|
||||
|
||||
'@esbuild/android-arm@0.18.20':
|
||||
resolution: {integrity: sha512-fyi7TDI/ijKKNZTUJAQqiG5T7YjJXgnzkURqmGj13C6dCqckZBLdl4h7bkhHt/t0WP+zO9/zwroDvANaOqO5Sw==}
|
||||
engines: {node: '>=12'}
|
||||
cpu: [arm]
|
||||
os: [android]
|
||||
|
||||
'@esbuild/android-arm@0.19.12':
|
||||
resolution: {integrity: sha512-qg/Lj1mu3CdQlDEEiWrlC4eaPZ1KztwGJ9B6J+/6G+/4ewxJg7gqj8eVYWvao1bXrqGiW2rsBZFSX3q2lcW05w==}
|
||||
engines: {node: '>=12'}
|
||||
cpu: [arm]
|
||||
os: [android]
|
||||
|
||||
'@esbuild/android-arm@0.25.10':
|
||||
resolution: {integrity: sha512-dQAxF1dW1C3zpeCDc5KqIYuZ1tgAdRXNoZP7vkBIRtKZPYe2xVr/d3SkirklCHudW1B45tGiUlz2pUWDfbDD4w==}
|
||||
engines: {node: '>=18'}
|
||||
cpu: [arm]
|
||||
os: [android]
|
||||
|
||||
'@esbuild/android-x64@0.18.20':
|
||||
resolution: {integrity: sha512-8GDdlePJA8D6zlZYJV/jnrRAi6rOiNaCC/JclcXpB+KIuvfBN4owLtgzY2bsxnx666XjJx2kDPUmnTtR8qKQUg==}
|
||||
engines: {node: '>=12'}
|
||||
cpu: [x64]
|
||||
os: [android]
|
||||
|
||||
'@esbuild/android-x64@0.19.12':
|
||||
resolution: {integrity: sha512-3k7ZoUW6Q6YqhdhIaq/WZ7HwBpnFBlW905Fa4s4qWJyiNOgT1dOqDiVAQFwBH7gBRZr17gLrlFCRzF6jFh7Kew==}
|
||||
engines: {node: '>=12'}
|
||||
cpu: [x64]
|
||||
os: [android]
|
||||
|
||||
'@esbuild/android-x64@0.25.10':
|
||||
resolution: {integrity: sha512-MiC9CWdPrfhibcXwr39p9ha1x0lZJ9KaVfvzA0Wxwz9ETX4v5CHfF09bx935nHlhi+MxhA63dKRRQLiVgSUtEg==}
|
||||
engines: {node: '>=18'}
|
||||
cpu: [x64]
|
||||
os: [android]
|
||||
|
||||
'@esbuild/darwin-arm64@0.18.20':
|
||||
resolution: {integrity: sha512-bxRHW5kHU38zS2lPTPOyuyTm+S+eobPUnTNkdJEfAddYgEcll4xkT8DB9d2008DtTbl7uJag2HuE5NZAZgnNEA==}
|
||||
engines: {node: '>=12'}
|
||||
cpu: [arm64]
|
||||
os: [darwin]
|
||||
|
||||
'@esbuild/darwin-arm64@0.19.12':
|
||||
resolution: {integrity: sha512-B6IeSgZgtEzGC42jsI+YYu9Z3HKRxp8ZT3cqhvliEHovq8HSX2YX8lNocDn79gCKJXOSaEot9MVYky7AKjCs8g==}
|
||||
engines: {node: '>=12'}
|
||||
cpu: [arm64]
|
||||
os: [darwin]
|
||||
|
||||
'@esbuild/darwin-arm64@0.25.10':
|
||||
resolution: {integrity: sha512-JC74bdXcQEpW9KkV326WpZZjLguSZ3DfS8wrrvPMHgQOIEIG/sPXEN/V8IssoJhbefLRcRqw6RQH2NnpdprtMA==}
|
||||
engines: {node: '>=18'}
|
||||
cpu: [arm64]
|
||||
os: [darwin]
|
||||
|
||||
'@esbuild/darwin-x64@0.18.20':
|
||||
resolution: {integrity: sha512-pc5gxlMDxzm513qPGbCbDukOdsGtKhfxD1zJKXjCCcU7ju50O7MeAZ8c4krSJcOIJGFR+qx21yMMVYwiQvyTyQ==}
|
||||
engines: {node: '>=12'}
|
||||
cpu: [x64]
|
||||
os: [darwin]
|
||||
|
||||
'@esbuild/darwin-x64@0.19.12':
|
||||
resolution: {integrity: sha512-hKoVkKzFiToTgn+41qGhsUJXFlIjxI/jSYeZf3ugemDYZldIXIxhvwN6erJGlX4t5h417iFuheZ7l+YVn05N3A==}
|
||||
engines: {node: '>=12'}
|
||||
cpu: [x64]
|
||||
os: [darwin]
|
||||
|
||||
'@esbuild/darwin-x64@0.25.10':
|
||||
resolution: {integrity: sha512-tguWg1olF6DGqzws97pKZ8G2L7Ig1vjDmGTwcTuYHbuU6TTjJe5FXbgs5C1BBzHbJ2bo1m3WkQDbWO2PvamRcg==}
|
||||
engines: {node: '>=18'}
|
||||
cpu: [x64]
|
||||
os: [darwin]
|
||||
|
||||
'@esbuild/freebsd-arm64@0.18.20':
|
||||
resolution: {integrity: sha512-yqDQHy4QHevpMAaxhhIwYPMv1NECwOvIpGCZkECn8w2WFHXjEwrBn3CeNIYsibZ/iZEUemj++M26W3cNR5h+Tw==}
|
||||
engines: {node: '>=12'}
|
||||
cpu: [arm64]
|
||||
os: [freebsd]
|
||||
|
||||
'@esbuild/freebsd-arm64@0.19.12':
|
||||
resolution: {integrity: sha512-4aRvFIXmwAcDBw9AueDQ2YnGmz5L6obe5kmPT8Vd+/+x/JMVKCgdcRwH6APrbpNXsPz+K653Qg8HB/oXvXVukA==}
|
||||
engines: {node: '>=12'}
|
||||
cpu: [arm64]
|
||||
os: [freebsd]
|
||||
|
||||
'@esbuild/freebsd-arm64@0.25.10':
|
||||
resolution: {integrity: sha512-3ZioSQSg1HT2N05YxeJWYR+Libe3bREVSdWhEEgExWaDtyFbbXWb49QgPvFH8u03vUPX10JhJPcz7s9t9+boWg==}
|
||||
engines: {node: '>=18'}
|
||||
cpu: [arm64]
|
||||
os: [freebsd]
|
||||
|
||||
'@esbuild/freebsd-x64@0.18.20':
|
||||
resolution: {integrity: sha512-tgWRPPuQsd3RmBZwarGVHZQvtzfEBOreNuxEMKFcd5DaDn2PbBxfwLcj4+aenoh7ctXcbXmOQIn8HI6mCSw5MQ==}
|
||||
engines: {node: '>=12'}
|
||||
cpu: [x64]
|
||||
os: [freebsd]
|
||||
|
||||
'@esbuild/freebsd-x64@0.19.12':
|
||||
resolution: {integrity: sha512-EYoXZ4d8xtBoVN7CEwWY2IN4ho76xjYXqSXMNccFSx2lgqOG/1TBPW0yPx1bJZk94qu3tX0fycJeeQsKovA8gg==}
|
||||
engines: {node: '>=12'}
|
||||
cpu: [x64]
|
||||
os: [freebsd]
|
||||
|
||||
'@esbuild/freebsd-x64@0.25.10':
|
||||
resolution: {integrity: sha512-LLgJfHJk014Aa4anGDbh8bmI5Lk+QidDmGzuC2D+vP7mv/GeSN+H39zOf7pN5N8p059FcOfs2bVlrRr4SK9WxA==}
|
||||
engines: {node: '>=18'}
|
||||
cpu: [x64]
|
||||
os: [freebsd]
|
||||
|
||||
'@esbuild/linux-arm64@0.18.20':
|
||||
resolution: {integrity: sha512-2YbscF+UL7SQAVIpnWvYwM+3LskyDmPhe31pE7/aoTMFKKzIc9lLbyGUpmmb8a8AixOL61sQ/mFh3jEjHYFvdA==}
|
||||
engines: {node: '>=12'}
|
||||
cpu: [arm64]
|
||||
os: [linux]
|
||||
|
||||
'@esbuild/linux-arm64@0.19.12':
|
||||
resolution: {integrity: sha512-EoTjyYyLuVPfdPLsGVVVC8a0p1BFFvtpQDB/YLEhaXyf/5bczaGeN15QkR+O4S5LeJ92Tqotve7i1jn35qwvdA==}
|
||||
engines: {node: '>=12'}
|
||||
cpu: [arm64]
|
||||
os: [linux]
|
||||
|
||||
'@esbuild/linux-arm64@0.25.10':
|
||||
resolution: {integrity: sha512-5luJWN6YKBsawd5f9i4+c+geYiVEw20FVW5x0v1kEMWNq8UctFjDiMATBxLvmmHA4bf7F6hTRaJgtghFr9iziQ==}
|
||||
engines: {node: '>=18'}
|
||||
cpu: [arm64]
|
||||
os: [linux]
|
||||
|
||||
'@esbuild/linux-arm@0.18.20':
|
||||
resolution: {integrity: sha512-/5bHkMWnq1EgKr1V+Ybz3s1hWXok7mDFUMQ4cG10AfW3wL02PSZi5kFpYKrptDsgb2WAJIvRcDm+qIvXf/apvg==}
|
||||
engines: {node: '>=12'}
|
||||
cpu: [arm]
|
||||
os: [linux]
|
||||
|
||||
'@esbuild/linux-arm@0.19.12':
|
||||
resolution: {integrity: sha512-J5jPms//KhSNv+LO1S1TX1UWp1ucM6N6XuL6ITdKWElCu8wXP72l9MM0zDTzzeikVyqFE6U8YAV9/tFyj0ti+w==}
|
||||
engines: {node: '>=12'}
|
||||
cpu: [arm]
|
||||
os: [linux]
|
||||
|
||||
'@esbuild/linux-arm@0.25.10':
|
||||
resolution: {integrity: sha512-oR31GtBTFYCqEBALI9r6WxoU/ZofZl962pouZRTEYECvNF/dtXKku8YXcJkhgK/beU+zedXfIzHijSRapJY3vg==}
|
||||
engines: {node: '>=18'}
|
||||
cpu: [arm]
|
||||
os: [linux]
|
||||
|
||||
'@esbuild/linux-ia32@0.18.20':
|
||||
resolution: {integrity: sha512-P4etWwq6IsReT0E1KHU40bOnzMHoH73aXp96Fs8TIT6z9Hu8G6+0SHSw9i2isWrD2nbx2qo5yUqACgdfVGx7TA==}
|
||||
engines: {node: '>=12'}
|
||||
cpu: [ia32]
|
||||
os: [linux]
|
||||
|
||||
'@esbuild/linux-ia32@0.19.12':
|
||||
resolution: {integrity: sha512-Thsa42rrP1+UIGaWz47uydHSBOgTUnwBwNq59khgIwktK6x60Hivfbux9iNR0eHCHzOLjLMLfUMLCypBkZXMHA==}
|
||||
engines: {node: '>=12'}
|
||||
cpu: [ia32]
|
||||
os: [linux]
|
||||
|
||||
'@esbuild/linux-ia32@0.25.10':
|
||||
resolution: {integrity: sha512-NrSCx2Kim3EnnWgS4Txn0QGt0Xipoumb6z6sUtl5bOEZIVKhzfyp/Lyw4C1DIYvzeW/5mWYPBFJU3a/8Yr75DQ==}
|
||||
engines: {node: '>=18'}
|
||||
cpu: [ia32]
|
||||
os: [linux]
|
||||
|
||||
'@esbuild/linux-loong64@0.18.20':
|
||||
resolution: {integrity: sha512-nXW8nqBTrOpDLPgPY9uV+/1DjxoQ7DoB2N8eocyq8I9XuqJ7BiAMDMf9n1xZM9TgW0J8zrquIb/A7s3BJv7rjg==}
|
||||
engines: {node: '>=12'}
|
||||
cpu: [loong64]
|
||||
os: [linux]
|
||||
|
||||
'@esbuild/linux-loong64@0.19.12':
|
||||
resolution: {integrity: sha512-LiXdXA0s3IqRRjm6rV6XaWATScKAXjI4R4LoDlvO7+yQqFdlr1Bax62sRwkVvRIrwXxvtYEHHI4dm50jAXkuAA==}
|
||||
engines: {node: '>=12'}
|
||||
cpu: [loong64]
|
||||
os: [linux]
|
||||
|
||||
'@esbuild/linux-loong64@0.25.10':
|
||||
resolution: {integrity: sha512-xoSphrd4AZda8+rUDDfD9J6FUMjrkTz8itpTITM4/xgerAZZcFW7Dv+sun7333IfKxGG8gAq+3NbfEMJfiY+Eg==}
|
||||
engines: {node: '>=18'}
|
||||
cpu: [loong64]
|
||||
os: [linux]
|
||||
|
||||
'@esbuild/linux-mips64el@0.18.20':
|
||||
resolution: {integrity: sha512-d5NeaXZcHp8PzYy5VnXV3VSd2D328Zb+9dEq5HE6bw6+N86JVPExrA6O68OPwobntbNJ0pzCpUFZTo3w0GyetQ==}
|
||||
engines: {node: '>=12'}
|
||||
cpu: [mips64el]
|
||||
os: [linux]
|
||||
|
||||
'@esbuild/linux-mips64el@0.19.12':
|
||||
resolution: {integrity: sha512-fEnAuj5VGTanfJ07ff0gOA6IPsvrVHLVb6Lyd1g2/ed67oU1eFzL0r9WL7ZzscD+/N6i3dWumGE1Un4f7Amf+w==}
|
||||
engines: {node: '>=12'}
|
||||
cpu: [mips64el]
|
||||
os: [linux]
|
||||
|
||||
'@esbuild/linux-mips64el@0.25.10':
|
||||
resolution: {integrity: sha512-ab6eiuCwoMmYDyTnyptoKkVS3k8fy/1Uvq7Dj5czXI6DF2GqD2ToInBI0SHOp5/X1BdZ26RKc5+qjQNGRBelRA==}
|
||||
engines: {node: '>=18'}
|
||||
cpu: [mips64el]
|
||||
os: [linux]
|
||||
|
||||
'@esbuild/linux-ppc64@0.18.20':
|
||||
resolution: {integrity: sha512-WHPyeScRNcmANnLQkq6AfyXRFr5D6N2sKgkFo2FqguP44Nw2eyDlbTdZwd9GYk98DZG9QItIiTlFLHJHjxP3FA==}
|
||||
engines: {node: '>=12'}
|
||||
cpu: [ppc64]
|
||||
os: [linux]
|
||||
|
||||
'@esbuild/linux-ppc64@0.19.12':
|
||||
resolution: {integrity: sha512-nYJA2/QPimDQOh1rKWedNOe3Gfc8PabU7HT3iXWtNUbRzXS9+vgB0Fjaqr//XNbd82mCxHzik2qotuI89cfixg==}
|
||||
engines: {node: '>=12'}
|
||||
cpu: [ppc64]
|
||||
os: [linux]
|
||||
|
||||
'@esbuild/linux-ppc64@0.25.10':
|
||||
resolution: {integrity: sha512-NLinzzOgZQsGpsTkEbdJTCanwA5/wozN9dSgEl12haXJBzMTpssebuXR42bthOF3z7zXFWH1AmvWunUCkBE4EA==}
|
||||
engines: {node: '>=18'}
|
||||
cpu: [ppc64]
|
||||
os: [linux]
|
||||
|
||||
'@esbuild/linux-riscv64@0.18.20':
|
||||
resolution: {integrity: sha512-WSxo6h5ecI5XH34KC7w5veNnKkju3zBRLEQNY7mv5mtBmrP/MjNBCAlsM2u5hDBlS3NGcTQpoBvRzqBcRtpq1A==}
|
||||
engines: {node: '>=12'}
|
||||
cpu: [riscv64]
|
||||
os: [linux]
|
||||
|
||||
'@esbuild/linux-riscv64@0.19.12':
|
||||
resolution: {integrity: sha512-2MueBrlPQCw5dVJJpQdUYgeqIzDQgw3QtiAHUC4RBz9FXPrskyyU3VI1hw7C0BSKB9OduwSJ79FTCqtGMWqJHg==}
|
||||
engines: {node: '>=12'}
|
||||
cpu: [riscv64]
|
||||
os: [linux]
|
||||
|
||||
'@esbuild/linux-riscv64@0.25.10':
|
||||
resolution: {integrity: sha512-FE557XdZDrtX8NMIeA8LBJX3dC2M8VGXwfrQWU7LB5SLOajfJIxmSdyL/gU1m64Zs9CBKvm4UAuBp5aJ8OgnrA==}
|
||||
engines: {node: '>=18'}
|
||||
cpu: [riscv64]
|
||||
os: [linux]
|
||||
|
||||
'@esbuild/linux-s390x@0.18.20':
|
||||
resolution: {integrity: sha512-+8231GMs3mAEth6Ja1iK0a1sQ3ohfcpzpRLH8uuc5/KVDFneH6jtAJLFGafpzpMRO6DzJ6AvXKze9LfFMrIHVQ==}
|
||||
engines: {node: '>=12'}
|
||||
cpu: [s390x]
|
||||
os: [linux]
|
||||
|
||||
'@esbuild/linux-s390x@0.19.12':
|
||||
resolution: {integrity: sha512-+Pil1Nv3Umes4m3AZKqA2anfhJiVmNCYkPchwFJNEJN5QxmTs1uzyy4TvmDrCRNT2ApwSari7ZIgrPeUx4UZDg==}
|
||||
engines: {node: '>=12'}
|
||||
cpu: [s390x]
|
||||
os: [linux]
|
||||
|
||||
'@esbuild/linux-s390x@0.25.10':
|
||||
resolution: {integrity: sha512-3BBSbgzuB9ajLoVZk0mGu+EHlBwkusRmeNYdqmznmMc9zGASFjSsxgkNsqmXugpPk00gJ0JNKh/97nxmjctdew==}
|
||||
engines: {node: '>=18'}
|
||||
cpu: [s390x]
|
||||
os: [linux]
|
||||
|
||||
'@esbuild/linux-x64@0.18.20':
|
||||
resolution: {integrity: sha512-UYqiqemphJcNsFEskc73jQ7B9jgwjWrSayxawS6UVFZGWrAAtkzjxSqnoclCXxWtfwLdzU+vTpcNYhpn43uP1w==}
|
||||
engines: {node: '>=12'}
|
||||
cpu: [x64]
|
||||
os: [linux]
|
||||
|
||||
'@esbuild/linux-x64@0.19.12':
|
||||
resolution: {integrity: sha512-B71g1QpxfwBvNrfyJdVDexenDIt1CiDN1TIXLbhOw0KhJzE78KIFGX6OJ9MrtC0oOqMWf+0xop4qEU8JrJTwCg==}
|
||||
engines: {node: '>=12'}
|
||||
cpu: [x64]
|
||||
os: [linux]
|
||||
|
||||
'@esbuild/linux-x64@0.25.10':
|
||||
resolution: {integrity: sha512-QSX81KhFoZGwenVyPoberggdW1nrQZSvfVDAIUXr3WqLRZGZqWk/P4T8p2SP+de2Sr5HPcvjhcJzEiulKgnxtA==}
|
||||
engines: {node: '>=18'}
|
||||
|
|
@ -786,18 +555,6 @@ packages:
|
|||
cpu: [arm64]
|
||||
os: [netbsd]
|
||||
|
||||
'@esbuild/netbsd-x64@0.18.20':
|
||||
resolution: {integrity: sha512-iO1c++VP6xUBUmltHZoMtCUdPlnPGdBom6IrO4gyKPFFVBKioIImVooR5I83nTew5UOYrk3gIJhbZh8X44y06A==}
|
||||
engines: {node: '>=12'}
|
||||
cpu: [x64]
|
||||
os: [netbsd]
|
||||
|
||||
'@esbuild/netbsd-x64@0.19.12':
|
||||
resolution: {integrity: sha512-3ltjQ7n1owJgFbuC61Oj++XhtzmymoCihNFgT84UAmJnxJfm4sYCiSLTXZtE00VWYpPMYc+ZQmB6xbSdVh0JWA==}
|
||||
engines: {node: '>=12'}
|
||||
cpu: [x64]
|
||||
os: [netbsd]
|
||||
|
||||
'@esbuild/netbsd-x64@0.25.10':
|
||||
resolution: {integrity: sha512-7RTytDPGU6fek/hWuN9qQpeGPBZFfB4zZgcz2VK2Z5VpdUxEI8JKYsg3JfO0n/Z1E/6l05n0unDCNc4HnhQGig==}
|
||||
engines: {node: '>=18'}
|
||||
|
|
@ -810,18 +567,6 @@ packages:
|
|||
cpu: [arm64]
|
||||
os: [openbsd]
|
||||
|
||||
'@esbuild/openbsd-x64@0.18.20':
|
||||
resolution: {integrity: sha512-e5e4YSsuQfX4cxcygw/UCPIEP6wbIL+se3sxPdCiMbFLBWu0eiZOJ7WoD+ptCLrmjZBK1Wk7I6D/I3NglUGOxg==}
|
||||
engines: {node: '>=12'}
|
||||
cpu: [x64]
|
||||
os: [openbsd]
|
||||
|
||||
'@esbuild/openbsd-x64@0.19.12':
|
||||
resolution: {integrity: sha512-RbrfTB9SWsr0kWmb9srfF+L933uMDdu9BIzdA7os2t0TXhCRjrQyCeOt6wVxr79CKD4c+p+YhCj31HBkYcXebw==}
|
||||
engines: {node: '>=12'}
|
||||
cpu: [x64]
|
||||
os: [openbsd]
|
||||
|
||||
'@esbuild/openbsd-x64@0.25.10':
|
||||
resolution: {integrity: sha512-XkA4frq1TLj4bEMB+2HnI0+4RnjbuGZfet2gs/LNs5Hc7D89ZQBHQ0gL2ND6Lzu1+QVkjp3x1gIcPKzRNP8bXw==}
|
||||
engines: {node: '>=18'}
|
||||
|
|
@ -834,72 +579,24 @@ packages:
|
|||
cpu: [arm64]
|
||||
os: [openharmony]
|
||||
|
||||
'@esbuild/sunos-x64@0.18.20':
|
||||
resolution: {integrity: sha512-kDbFRFp0YpTQVVrqUd5FTYmWo45zGaXe0X8E1G/LKFC0v8x0vWrhOWSLITcCn63lmZIxfOMXtCfti/RxN/0wnQ==}
|
||||
engines: {node: '>=12'}
|
||||
cpu: [x64]
|
||||
os: [sunos]
|
||||
|
||||
'@esbuild/sunos-x64@0.19.12':
|
||||
resolution: {integrity: sha512-HKjJwRrW8uWtCQnQOz9qcU3mUZhTUQvi56Q8DPTLLB+DawoiQdjsYq+j+D3s9I8VFtDr+F9CjgXKKC4ss89IeA==}
|
||||
engines: {node: '>=12'}
|
||||
cpu: [x64]
|
||||
os: [sunos]
|
||||
|
||||
'@esbuild/sunos-x64@0.25.10':
|
||||
resolution: {integrity: sha512-fswk3XT0Uf2pGJmOpDB7yknqhVkJQkAQOcW/ccVOtfx05LkbWOaRAtn5SaqXypeKQra1QaEa841PgrSL9ubSPQ==}
|
||||
engines: {node: '>=18'}
|
||||
cpu: [x64]
|
||||
os: [sunos]
|
||||
|
||||
'@esbuild/win32-arm64@0.18.20':
|
||||
resolution: {integrity: sha512-ddYFR6ItYgoaq4v4JmQQaAI5s7npztfV4Ag6NrhiaW0RrnOXqBkgwZLofVTlq1daVTQNhtI5oieTvkRPfZrePg==}
|
||||
engines: {node: '>=12'}
|
||||
cpu: [arm64]
|
||||
os: [win32]
|
||||
|
||||
'@esbuild/win32-arm64@0.19.12':
|
||||
resolution: {integrity: sha512-URgtR1dJnmGvX864pn1B2YUYNzjmXkuJOIqG2HdU62MVS4EHpU2946OZoTMnRUHklGtJdJZ33QfzdjGACXhn1A==}
|
||||
engines: {node: '>=12'}
|
||||
cpu: [arm64]
|
||||
os: [win32]
|
||||
|
||||
'@esbuild/win32-arm64@0.25.10':
|
||||
resolution: {integrity: sha512-ah+9b59KDTSfpaCg6VdJoOQvKjI33nTaQr4UluQwW7aEwZQsbMCfTmfEO4VyewOxx4RaDT/xCy9ra2GPWmO7Kw==}
|
||||
engines: {node: '>=18'}
|
||||
cpu: [arm64]
|
||||
os: [win32]
|
||||
|
||||
'@esbuild/win32-ia32@0.18.20':
|
||||
resolution: {integrity: sha512-Wv7QBi3ID/rROT08SABTS7eV4hX26sVduqDOTe1MvGMjNd3EjOz4b7zeexIR62GTIEKrfJXKL9LFxTYgkyeu7g==}
|
||||
engines: {node: '>=12'}
|
||||
cpu: [ia32]
|
||||
os: [win32]
|
||||
|
||||
'@esbuild/win32-ia32@0.19.12':
|
||||
resolution: {integrity: sha512-+ZOE6pUkMOJfmxmBZElNOx72NKpIa/HFOMGzu8fqzQJ5kgf6aTGrcJaFsNiVMH4JKpMipyK+7k0n2UXN7a8YKQ==}
|
||||
engines: {node: '>=12'}
|
||||
cpu: [ia32]
|
||||
os: [win32]
|
||||
|
||||
'@esbuild/win32-ia32@0.25.10':
|
||||
resolution: {integrity: sha512-QHPDbKkrGO8/cz9LKVnJU22HOi4pxZnZhhA2HYHez5Pz4JeffhDjf85E57Oyco163GnzNCVkZK0b/n4Y0UHcSw==}
|
||||
engines: {node: '>=18'}
|
||||
cpu: [ia32]
|
||||
os: [win32]
|
||||
|
||||
'@esbuild/win32-x64@0.18.20':
|
||||
resolution: {integrity: sha512-kTdfRcSiDfQca/y9QIkng02avJ+NCaQvrMejlsB3RRv5sE9rRoeBPISaZpKxHELzRxZyLvNts1P27W3wV+8geQ==}
|
||||
engines: {node: '>=12'}
|
||||
cpu: [x64]
|
||||
os: [win32]
|
||||
|
||||
'@esbuild/win32-x64@0.19.12':
|
||||
resolution: {integrity: sha512-T1QyPSDCyMXaO3pzBkF96E8xMkiRYbUEZADd29SyPGabqxMViNoii+NcK7eWJAEoU6RZyEm5lVSIjTmcdoB9HA==}
|
||||
engines: {node: '>=12'}
|
||||
cpu: [x64]
|
||||
os: [win32]
|
||||
|
||||
'@esbuild/win32-x64@0.25.10':
|
||||
resolution: {integrity: sha512-9KpxSVFCu0iK1owoez6aC/s/EdUQLDN3adTxGCqxMVhrPDj6bt5dbrHDXUuq+Bs2vATFBBrQS5vdQ/Ed2P+nbw==}
|
||||
engines: {node: '>=18'}
|
||||
|
|
@ -2153,102 +1850,6 @@ packages:
|
|||
resolution: {integrity: sha512-Sf2LSQP+bOlhKWWyhFsn0UsfdK/kCWRv1iuA2gXAwt3dyNabr6QSj00I2V10pidqz69soatm9ZwZvpQMTIOd5Q==}
|
||||
engines: {node: '>=12'}
|
||||
|
||||
drizzle-kit@0.28.1:
|
||||
resolution: {integrity: sha512-JimOV+ystXTWMgZkLHYHf2w3oS28hxiH1FR0dkmJLc7GHzdGJoJAQtQS5DRppnabsRZwE2U1F6CuezVBgmsBBQ==}
|
||||
hasBin: true
|
||||
|
||||
drizzle-orm@0.36.4:
|
||||
resolution: {integrity: sha512-1OZY3PXD7BR00Gl61UUOFihslDldfH4NFRH2MbP54Yxi0G/PKn4HfO65JYZ7c16DeP3SpM3Aw+VXVG9j6CRSXA==}
|
||||
peerDependencies:
|
||||
'@aws-sdk/client-rds-data': '>=3'
|
||||
'@cloudflare/workers-types': '>=3'
|
||||
'@electric-sql/pglite': '>=0.2.0'
|
||||
'@libsql/client': '>=0.10.0'
|
||||
'@libsql/client-wasm': '>=0.10.0'
|
||||
'@neondatabase/serverless': '>=0.10.0'
|
||||
'@op-engineering/op-sqlite': '>=2'
|
||||
'@opentelemetry/api': ^1.4.1
|
||||
'@planetscale/database': '>=1'
|
||||
'@prisma/client': '*'
|
||||
'@tidbcloud/serverless': '*'
|
||||
'@types/better-sqlite3': '*'
|
||||
'@types/pg': '*'
|
||||
'@types/react': '>=18'
|
||||
'@types/sql.js': '*'
|
||||
'@vercel/postgres': '>=0.8.0'
|
||||
'@xata.io/client': '*'
|
||||
better-sqlite3: '>=7'
|
||||
bun-types: '*'
|
||||
expo-sqlite: '>=14.0.0'
|
||||
knex: '*'
|
||||
kysely: '*'
|
||||
mysql2: '>=2'
|
||||
pg: '>=8'
|
||||
postgres: '>=3'
|
||||
prisma: '*'
|
||||
react: '>=18'
|
||||
sql.js: '>=1'
|
||||
sqlite3: '>=5'
|
||||
peerDependenciesMeta:
|
||||
'@aws-sdk/client-rds-data':
|
||||
optional: true
|
||||
'@cloudflare/workers-types':
|
||||
optional: true
|
||||
'@electric-sql/pglite':
|
||||
optional: true
|
||||
'@libsql/client':
|
||||
optional: true
|
||||
'@libsql/client-wasm':
|
||||
optional: true
|
||||
'@neondatabase/serverless':
|
||||
optional: true
|
||||
'@op-engineering/op-sqlite':
|
||||
optional: true
|
||||
'@opentelemetry/api':
|
||||
optional: true
|
||||
'@planetscale/database':
|
||||
optional: true
|
||||
'@prisma/client':
|
||||
optional: true
|
||||
'@tidbcloud/serverless':
|
||||
optional: true
|
||||
'@types/better-sqlite3':
|
||||
optional: true
|
||||
'@types/pg':
|
||||
optional: true
|
||||
'@types/react':
|
||||
optional: true
|
||||
'@types/sql.js':
|
||||
optional: true
|
||||
'@vercel/postgres':
|
||||
optional: true
|
||||
'@xata.io/client':
|
||||
optional: true
|
||||
better-sqlite3:
|
||||
optional: true
|
||||
bun-types:
|
||||
optional: true
|
||||
expo-sqlite:
|
||||
optional: true
|
||||
knex:
|
||||
optional: true
|
||||
kysely:
|
||||
optional: true
|
||||
mysql2:
|
||||
optional: true
|
||||
pg:
|
||||
optional: true
|
||||
postgres:
|
||||
optional: true
|
||||
prisma:
|
||||
optional: true
|
||||
react:
|
||||
optional: true
|
||||
sql.js:
|
||||
optional: true
|
||||
sqlite3:
|
||||
optional: true
|
||||
|
||||
dunder-proto@1.0.1:
|
||||
resolution: {integrity: sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A==}
|
||||
engines: {node: '>= 0.4'}
|
||||
|
|
@ -2317,21 +1918,6 @@ packages:
|
|||
resolution: {integrity: sha512-w+5mJ3GuFL+NjVtJlvydShqE1eN3h3PbI7/5LAsYJP/2qtuMXjfL2LpHSRqo4b4eSF5K/DH1JXKUAHSB2UW50g==}
|
||||
engines: {node: '>= 0.4'}
|
||||
|
||||
esbuild-register@3.6.0:
|
||||
resolution: {integrity: sha512-H2/S7Pm8a9CL1uhp9OvjwrBh5Pvx0H8qVOxNu8Wed9Y7qv56MPtq+GGM8RJpq6glYJn9Wspr8uw7l55uyinNeg==}
|
||||
peerDependencies:
|
||||
esbuild: '>=0.12 <1'
|
||||
|
||||
esbuild@0.18.20:
|
||||
resolution: {integrity: sha512-ceqxoedUrcayh7Y7ZX6NdbbDzGROiyVBgC4PriJThBKSVPWnnFHZAkfI1lJT8QFkOwH4qOS2SJkS4wvpGl8BpA==}
|
||||
engines: {node: '>=12'}
|
||||
hasBin: true
|
||||
|
||||
esbuild@0.19.12:
|
||||
resolution: {integrity: sha512-aARqgq8roFBj054KvQr5f1sFu0D65G+miZRCuJyJ0G13Zwx7vRar5Zhn2tkQNzIXcBrNVsv/8stehpj+GAjgbg==}
|
||||
engines: {node: '>=12'}
|
||||
hasBin: true
|
||||
|
||||
esbuild@0.25.10:
|
||||
resolution: {integrity: sha512-9RiGKvCwaqxO2owP61uQ4BgNborAQskMR6QusfWzQqv7AZOg5oGehdY2pRJMTKuwxd1IDBP4rSbI5lHzU7SMsQ==}
|
||||
engines: {node: '>=18'}
|
||||
|
|
@ -3681,10 +3267,6 @@ packages:
|
|||
resolution: {integrity: sha512-3Ybi1tAuwAP9s0r1UQ2J4n5Y0G05bJkpUIO0/bI9MhwmD70S5aTWbXGBwxHrelT+XM1k6dM0pk+SwNkpTRN7Pg==}
|
||||
engines: {node: ^10 || ^12 || >=14}
|
||||
|
||||
postgres@3.4.7:
|
||||
resolution: {integrity: sha512-Jtc2612XINuBjIl/QTWsV5UvE8UHuNblcO3vVADSrKsrc6RqGX6lOW1cEo3CM2v0XG4Nat8nI+YM7/f26VxXLw==}
|
||||
engines: {node: '>=12'}
|
||||
|
||||
prelude-ls@1.2.1:
|
||||
resolution: {integrity: sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==}
|
||||
engines: {node: '>= 0.8.0'}
|
||||
|
|
@ -3961,9 +3543,6 @@ packages:
|
|||
source-map-support@0.5.13:
|
||||
resolution: {integrity: sha512-SHSKFHadjVA5oR4PPqhtAVdcBWwRYVd6g6cAXnIbRiIwc2EhPrTuKUBdSLvlEKyIP3GCf89fltvcZiP9MMFA1w==}
|
||||
|
||||
source-map-support@0.5.21:
|
||||
resolution: {integrity: sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w==}
|
||||
|
||||
source-map@0.6.1:
|
||||
resolution: {integrity: sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==}
|
||||
engines: {node: '>=0.10.0'}
|
||||
|
|
@ -4660,8 +4239,6 @@ snapshots:
|
|||
enabled: 2.0.0
|
||||
kuler: 2.0.0
|
||||
|
||||
'@drizzle-team/brocli@0.10.2': {}
|
||||
|
||||
'@emnapi/core@1.5.0':
|
||||
dependencies:
|
||||
'@emnapi/wasi-threads': 1.1.0
|
||||
|
|
@ -4678,226 +4255,81 @@ snapshots:
|
|||
tslib: 2.8.1
|
||||
optional: true
|
||||
|
||||
'@esbuild-kit/core-utils@3.3.2':
|
||||
dependencies:
|
||||
esbuild: 0.18.20
|
||||
source-map-support: 0.5.21
|
||||
|
||||
'@esbuild-kit/esm-loader@2.6.5':
|
||||
dependencies:
|
||||
'@esbuild-kit/core-utils': 3.3.2
|
||||
get-tsconfig: 4.10.1
|
||||
|
||||
'@esbuild/aix-ppc64@0.19.12':
|
||||
optional: true
|
||||
|
||||
'@esbuild/aix-ppc64@0.25.10':
|
||||
optional: true
|
||||
|
||||
'@esbuild/android-arm64@0.18.20':
|
||||
optional: true
|
||||
|
||||
'@esbuild/android-arm64@0.19.12':
|
||||
optional: true
|
||||
|
||||
'@esbuild/android-arm64@0.25.10':
|
||||
optional: true
|
||||
|
||||
'@esbuild/android-arm@0.18.20':
|
||||
optional: true
|
||||
|
||||
'@esbuild/android-arm@0.19.12':
|
||||
optional: true
|
||||
|
||||
'@esbuild/android-arm@0.25.10':
|
||||
optional: true
|
||||
|
||||
'@esbuild/android-x64@0.18.20':
|
||||
optional: true
|
||||
|
||||
'@esbuild/android-x64@0.19.12':
|
||||
optional: true
|
||||
|
||||
'@esbuild/android-x64@0.25.10':
|
||||
optional: true
|
||||
|
||||
'@esbuild/darwin-arm64@0.18.20':
|
||||
optional: true
|
||||
|
||||
'@esbuild/darwin-arm64@0.19.12':
|
||||
optional: true
|
||||
|
||||
'@esbuild/darwin-arm64@0.25.10':
|
||||
optional: true
|
||||
|
||||
'@esbuild/darwin-x64@0.18.20':
|
||||
optional: true
|
||||
|
||||
'@esbuild/darwin-x64@0.19.12':
|
||||
optional: true
|
||||
|
||||
'@esbuild/darwin-x64@0.25.10':
|
||||
optional: true
|
||||
|
||||
'@esbuild/freebsd-arm64@0.18.20':
|
||||
optional: true
|
||||
|
||||
'@esbuild/freebsd-arm64@0.19.12':
|
||||
optional: true
|
||||
|
||||
'@esbuild/freebsd-arm64@0.25.10':
|
||||
optional: true
|
||||
|
||||
'@esbuild/freebsd-x64@0.18.20':
|
||||
optional: true
|
||||
|
||||
'@esbuild/freebsd-x64@0.19.12':
|
||||
optional: true
|
||||
|
||||
'@esbuild/freebsd-x64@0.25.10':
|
||||
optional: true
|
||||
|
||||
'@esbuild/linux-arm64@0.18.20':
|
||||
optional: true
|
||||
|
||||
'@esbuild/linux-arm64@0.19.12':
|
||||
optional: true
|
||||
|
||||
'@esbuild/linux-arm64@0.25.10':
|
||||
optional: true
|
||||
|
||||
'@esbuild/linux-arm@0.18.20':
|
||||
optional: true
|
||||
|
||||
'@esbuild/linux-arm@0.19.12':
|
||||
optional: true
|
||||
|
||||
'@esbuild/linux-arm@0.25.10':
|
||||
optional: true
|
||||
|
||||
'@esbuild/linux-ia32@0.18.20':
|
||||
optional: true
|
||||
|
||||
'@esbuild/linux-ia32@0.19.12':
|
||||
optional: true
|
||||
|
||||
'@esbuild/linux-ia32@0.25.10':
|
||||
optional: true
|
||||
|
||||
'@esbuild/linux-loong64@0.18.20':
|
||||
optional: true
|
||||
|
||||
'@esbuild/linux-loong64@0.19.12':
|
||||
optional: true
|
||||
|
||||
'@esbuild/linux-loong64@0.25.10':
|
||||
optional: true
|
||||
|
||||
'@esbuild/linux-mips64el@0.18.20':
|
||||
optional: true
|
||||
|
||||
'@esbuild/linux-mips64el@0.19.12':
|
||||
optional: true
|
||||
|
||||
'@esbuild/linux-mips64el@0.25.10':
|
||||
optional: true
|
||||
|
||||
'@esbuild/linux-ppc64@0.18.20':
|
||||
optional: true
|
||||
|
||||
'@esbuild/linux-ppc64@0.19.12':
|
||||
optional: true
|
||||
|
||||
'@esbuild/linux-ppc64@0.25.10':
|
||||
optional: true
|
||||
|
||||
'@esbuild/linux-riscv64@0.18.20':
|
||||
optional: true
|
||||
|
||||
'@esbuild/linux-riscv64@0.19.12':
|
||||
optional: true
|
||||
|
||||
'@esbuild/linux-riscv64@0.25.10':
|
||||
optional: true
|
||||
|
||||
'@esbuild/linux-s390x@0.18.20':
|
||||
optional: true
|
||||
|
||||
'@esbuild/linux-s390x@0.19.12':
|
||||
optional: true
|
||||
|
||||
'@esbuild/linux-s390x@0.25.10':
|
||||
optional: true
|
||||
|
||||
'@esbuild/linux-x64@0.18.20':
|
||||
optional: true
|
||||
|
||||
'@esbuild/linux-x64@0.19.12':
|
||||
optional: true
|
||||
|
||||
'@esbuild/linux-x64@0.25.10':
|
||||
optional: true
|
||||
|
||||
'@esbuild/netbsd-arm64@0.25.10':
|
||||
optional: true
|
||||
|
||||
'@esbuild/netbsd-x64@0.18.20':
|
||||
optional: true
|
||||
|
||||
'@esbuild/netbsd-x64@0.19.12':
|
||||
optional: true
|
||||
|
||||
'@esbuild/netbsd-x64@0.25.10':
|
||||
optional: true
|
||||
|
||||
'@esbuild/openbsd-arm64@0.25.10':
|
||||
optional: true
|
||||
|
||||
'@esbuild/openbsd-x64@0.18.20':
|
||||
optional: true
|
||||
|
||||
'@esbuild/openbsd-x64@0.19.12':
|
||||
optional: true
|
||||
|
||||
'@esbuild/openbsd-x64@0.25.10':
|
||||
optional: true
|
||||
|
||||
'@esbuild/openharmony-arm64@0.25.10':
|
||||
optional: true
|
||||
|
||||
'@esbuild/sunos-x64@0.18.20':
|
||||
optional: true
|
||||
|
||||
'@esbuild/sunos-x64@0.19.12':
|
||||
optional: true
|
||||
|
||||
'@esbuild/sunos-x64@0.25.10':
|
||||
optional: true
|
||||
|
||||
'@esbuild/win32-arm64@0.18.20':
|
||||
optional: true
|
||||
|
||||
'@esbuild/win32-arm64@0.19.12':
|
||||
optional: true
|
||||
|
||||
'@esbuild/win32-arm64@0.25.10':
|
||||
optional: true
|
||||
|
||||
'@esbuild/win32-ia32@0.18.20':
|
||||
optional: true
|
||||
|
||||
'@esbuild/win32-ia32@0.19.12':
|
||||
optional: true
|
||||
|
||||
'@esbuild/win32-ia32@0.25.10':
|
||||
optional: true
|
||||
|
||||
'@esbuild/win32-x64@0.18.20':
|
||||
optional: true
|
||||
|
||||
'@esbuild/win32-x64@0.19.12':
|
||||
optional: true
|
||||
|
||||
'@esbuild/win32-x64@0.25.10':
|
||||
optional: true
|
||||
|
||||
|
|
@ -5611,7 +5043,7 @@ snapshots:
|
|||
|
||||
'@types/ws@8.18.1':
|
||||
dependencies:
|
||||
'@types/node': 24.5.2
|
||||
'@types/node': 20.19.17
|
||||
|
||||
'@types/yargs-parser@21.0.3': {}
|
||||
|
||||
|
|
@ -6378,21 +5810,6 @@ snapshots:
|
|||
|
||||
dotenv@17.2.2: {}
|
||||
|
||||
drizzle-kit@0.28.1:
|
||||
dependencies:
|
||||
'@drizzle-team/brocli': 0.10.2
|
||||
'@esbuild-kit/esm-loader': 2.6.5
|
||||
esbuild: 0.19.12
|
||||
esbuild-register: 3.6.0(esbuild@0.19.12)
|
||||
transitivePeerDependencies:
|
||||
- supports-color
|
||||
|
||||
drizzle-orm@0.36.4(@types/react@18.3.24)(postgres@3.4.7)(react@18.3.1):
|
||||
optionalDependencies:
|
||||
'@types/react': 18.3.24
|
||||
postgres: 3.4.7
|
||||
react: 18.3.1
|
||||
|
||||
dunder-proto@1.0.1:
|
||||
dependencies:
|
||||
call-bind-apply-helpers: 1.0.2
|
||||
|
|
@ -6524,64 +5941,6 @@ snapshots:
|
|||
is-date-object: 1.1.0
|
||||
is-symbol: 1.1.1
|
||||
|
||||
esbuild-register@3.6.0(esbuild@0.19.12):
|
||||
dependencies:
|
||||
debug: 4.4.3(supports-color@5.5.0)
|
||||
esbuild: 0.19.12
|
||||
transitivePeerDependencies:
|
||||
- supports-color
|
||||
|
||||
esbuild@0.18.20:
|
||||
optionalDependencies:
|
||||
'@esbuild/android-arm': 0.18.20
|
||||
'@esbuild/android-arm64': 0.18.20
|
||||
'@esbuild/android-x64': 0.18.20
|
||||
'@esbuild/darwin-arm64': 0.18.20
|
||||
'@esbuild/darwin-x64': 0.18.20
|
||||
'@esbuild/freebsd-arm64': 0.18.20
|
||||
'@esbuild/freebsd-x64': 0.18.20
|
||||
'@esbuild/linux-arm': 0.18.20
|
||||
'@esbuild/linux-arm64': 0.18.20
|
||||
'@esbuild/linux-ia32': 0.18.20
|
||||
'@esbuild/linux-loong64': 0.18.20
|
||||
'@esbuild/linux-mips64el': 0.18.20
|
||||
'@esbuild/linux-ppc64': 0.18.20
|
||||
'@esbuild/linux-riscv64': 0.18.20
|
||||
'@esbuild/linux-s390x': 0.18.20
|
||||
'@esbuild/linux-x64': 0.18.20
|
||||
'@esbuild/netbsd-x64': 0.18.20
|
||||
'@esbuild/openbsd-x64': 0.18.20
|
||||
'@esbuild/sunos-x64': 0.18.20
|
||||
'@esbuild/win32-arm64': 0.18.20
|
||||
'@esbuild/win32-ia32': 0.18.20
|
||||
'@esbuild/win32-x64': 0.18.20
|
||||
|
||||
esbuild@0.19.12:
|
||||
optionalDependencies:
|
||||
'@esbuild/aix-ppc64': 0.19.12
|
||||
'@esbuild/android-arm': 0.19.12
|
||||
'@esbuild/android-arm64': 0.19.12
|
||||
'@esbuild/android-x64': 0.19.12
|
||||
'@esbuild/darwin-arm64': 0.19.12
|
||||
'@esbuild/darwin-x64': 0.19.12
|
||||
'@esbuild/freebsd-arm64': 0.19.12
|
||||
'@esbuild/freebsd-x64': 0.19.12
|
||||
'@esbuild/linux-arm': 0.19.12
|
||||
'@esbuild/linux-arm64': 0.19.12
|
||||
'@esbuild/linux-ia32': 0.19.12
|
||||
'@esbuild/linux-loong64': 0.19.12
|
||||
'@esbuild/linux-mips64el': 0.19.12
|
||||
'@esbuild/linux-ppc64': 0.19.12
|
||||
'@esbuild/linux-riscv64': 0.19.12
|
||||
'@esbuild/linux-s390x': 0.19.12
|
||||
'@esbuild/linux-x64': 0.19.12
|
||||
'@esbuild/netbsd-x64': 0.19.12
|
||||
'@esbuild/openbsd-x64': 0.19.12
|
||||
'@esbuild/sunos-x64': 0.19.12
|
||||
'@esbuild/win32-arm64': 0.19.12
|
||||
'@esbuild/win32-ia32': 0.19.12
|
||||
'@esbuild/win32-x64': 0.19.12
|
||||
|
||||
esbuild@0.25.10:
|
||||
optionalDependencies:
|
||||
'@esbuild/aix-ppc64': 0.25.10
|
||||
|
|
@ -6628,7 +5987,7 @@ snapshots:
|
|||
eslint: 8.57.1
|
||||
eslint-import-resolver-node: 0.3.9
|
||||
eslint-import-resolver-typescript: 3.10.1(eslint-plugin-import@2.32.0(@typescript-eslint/parser@8.44.0(eslint@8.57.1)(typescript@5.9.2))(eslint@8.57.1))(eslint@8.57.1)
|
||||
eslint-plugin-import: 2.32.0(@typescript-eslint/parser@8.44.0(eslint@8.57.1)(typescript@5.9.2))(eslint-import-resolver-typescript@3.10.1(eslint-plugin-import@2.32.0(@typescript-eslint/parser@8.44.0(eslint@8.57.1)(typescript@5.9.2))(eslint@8.57.1))(eslint@8.57.1))(eslint@8.57.1)
|
||||
eslint-plugin-import: 2.32.0(@typescript-eslint/parser@8.44.0(eslint@8.57.1)(typescript@5.9.2))(eslint-import-resolver-typescript@3.10.1)(eslint@8.57.1)
|
||||
eslint-plugin-jsx-a11y: 6.10.2(eslint@8.57.1)
|
||||
eslint-plugin-react: 7.37.5(eslint@8.57.1)
|
||||
eslint-plugin-react-hooks: 5.0.0-canary-7118f5dd7-20230705(eslint@8.57.1)
|
||||
|
|
@ -6662,7 +6021,7 @@ snapshots:
|
|||
tinyglobby: 0.2.15
|
||||
unrs-resolver: 1.11.1
|
||||
optionalDependencies:
|
||||
eslint-plugin-import: 2.32.0(@typescript-eslint/parser@8.44.0(eslint@8.57.1)(typescript@5.9.2))(eslint-import-resolver-typescript@3.10.1(eslint-plugin-import@2.32.0(@typescript-eslint/parser@8.44.0(eslint@8.57.1)(typescript@5.9.2))(eslint@8.57.1))(eslint@8.57.1))(eslint@8.57.1)
|
||||
eslint-plugin-import: 2.32.0(@typescript-eslint/parser@8.44.0(eslint@8.57.1)(typescript@5.9.2))(eslint-import-resolver-typescript@3.10.1)(eslint@8.57.1)
|
||||
transitivePeerDependencies:
|
||||
- supports-color
|
||||
|
||||
|
|
@ -6677,7 +6036,7 @@ snapshots:
|
|||
transitivePeerDependencies:
|
||||
- supports-color
|
||||
|
||||
eslint-plugin-import@2.32.0(@typescript-eslint/parser@8.44.0(eslint@8.57.1)(typescript@5.9.2))(eslint-import-resolver-typescript@3.10.1(eslint-plugin-import@2.32.0(@typescript-eslint/parser@8.44.0(eslint@8.57.1)(typescript@5.9.2))(eslint@8.57.1))(eslint@8.57.1))(eslint@8.57.1):
|
||||
eslint-plugin-import@2.32.0(@typescript-eslint/parser@8.44.0(eslint@8.57.1)(typescript@5.9.2))(eslint-import-resolver-typescript@3.10.1)(eslint@8.57.1):
|
||||
dependencies:
|
||||
'@rtsao/scc': 1.1.0
|
||||
array-includes: 3.1.9
|
||||
|
|
@ -8293,8 +7652,6 @@ snapshots:
|
|||
picocolors: 1.1.1
|
||||
source-map-js: 1.2.1
|
||||
|
||||
postgres@3.4.7: {}
|
||||
|
||||
prelude-ls@1.2.1: {}
|
||||
|
||||
prettier-linter-helpers@1.0.0:
|
||||
|
|
@ -8624,11 +7981,6 @@ snapshots:
|
|||
buffer-from: 1.1.2
|
||||
source-map: 0.6.1
|
||||
|
||||
source-map-support@0.5.21:
|
||||
dependencies:
|
||||
buffer-from: 1.1.2
|
||||
source-map: 0.6.1
|
||||
|
||||
source-map@0.6.1: {}
|
||||
|
||||
split-on-first@1.1.0: {}
|
||||
|
|
|
|||
|
|
@ -1,3 +1,2 @@
|
|||
packages:
|
||||
- 'apps/*'
|
||||
- 'packages/*'
|
||||
- 'apps/*'
|
||||
Loading…
Reference in New Issue