Implement Redis rate limiting middleware for spam endpoints (FRE-4507)
- Add ioredis dependency to API package - Create Redis connection utility (apps/api/src/config/redis.ts) - Create Redis-backed spam rate limit middleware with per-minute and daily limits - Create spam classification routes (SMS, number reputation, call analysis, feedback) - Register middleware and routes in API server - Add 7 passing tests for rate limit enforcement - Update vitest config with required env vars Co-Authored-By: Paperclip <noreply@paperclip.ing>
This commit is contained in:
@@ -16,7 +16,8 @@
|
||||
"@shieldsai/shared-notifications": "*",
|
||||
"@shieldsai/shared-utils": "*",
|
||||
"fastify": "^4.25.0",
|
||||
"fastify-plugin": "^4.5.0"
|
||||
"fastify-plugin": "^4.5.0",
|
||||
"ioredis": "^5.3.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/node": "^25.6.0",
|
||||
|
||||
98
apps/api/src/__tests__/spam-rate-limit.test.ts
Normal file
98
apps/api/src/__tests__/spam-rate-limit.test.ts
Normal file
@@ -0,0 +1,98 @@
|
||||
import { describe, it, expect, beforeAll, afterAll, beforeEach, afterEach } from 'vitest';
|
||||
import { RedisRateLimiter } from '../middleware/spam-rate-limit.middleware';
|
||||
import { redis } from '../config/redis';
|
||||
|
||||
describe('RedisRateLimiter', () => {
|
||||
const testKey = 'test-client';
|
||||
const limiter = new RedisRateLimiter();
|
||||
|
||||
beforeAll(async () => {
|
||||
await redis.connect();
|
||||
});
|
||||
|
||||
afterAll(async () => {
|
||||
await redis.quit();
|
||||
});
|
||||
|
||||
beforeEach(async () => {
|
||||
await redis.del('spamshield:ratelimit:test-client');
|
||||
await redis.del('spamshield:ratelimit:daily:test-client');
|
||||
});
|
||||
|
||||
afterEach(async () => {
|
||||
await redis.del('spamshield:ratelimit:test-client');
|
||||
await redis.del('spamshield:ratelimit:daily:test-client');
|
||||
});
|
||||
|
||||
describe('checkLimit (per-minute)', () => {
|
||||
it('should allow requests within the limit', async () => {
|
||||
const result = await limiter.checkLimit(testKey, 60, 10);
|
||||
|
||||
expect(result.remaining).toBe(9);
|
||||
expect(result.retryAfter).toBeUndefined();
|
||||
});
|
||||
|
||||
it('should decrement remaining on each request', async () => {
|
||||
const result1 = await limiter.checkLimit(testKey, 60, 10);
|
||||
const result2 = await limiter.checkLimit(testKey, 60, 10);
|
||||
|
||||
expect(result1.remaining).toBe(9);
|
||||
expect(result2.remaining).toBe(8);
|
||||
});
|
||||
|
||||
it('should exceed limit after max requests', async () => {
|
||||
for (let i = 0; i < 10; i++) {
|
||||
await limiter.checkLimit(testKey, 60, 10);
|
||||
}
|
||||
|
||||
const result = await limiter.checkLimit(testKey, 60, 10);
|
||||
|
||||
expect(result.remaining).toBe(0);
|
||||
expect(result.retryAfter).toBeGreaterThan(0);
|
||||
});
|
||||
|
||||
it('should return retry-after when limit is exceeded', async () => {
|
||||
for (let i = 0; i < 10; i++) {
|
||||
await limiter.checkLimit(testKey, 60, 10);
|
||||
}
|
||||
|
||||
const result = await limiter.checkLimit(testKey, 60, 10);
|
||||
|
||||
expect(result.retryAfter).toBeGreaterThan(0);
|
||||
expect(result.retryAfter).toBeLessThanOrEqual(60000);
|
||||
});
|
||||
});
|
||||
|
||||
describe('checkDailyLimit', () => {
|
||||
it('should allow requests within daily limit', async () => {
|
||||
const result = await limiter.checkDailyLimit(testKey, 100);
|
||||
|
||||
expect(result.remaining).toBe(99);
|
||||
expect(result.retryAfter).toBeUndefined();
|
||||
});
|
||||
|
||||
it('should exceed daily limit after max requests', async () => {
|
||||
for (let i = 0; i < 100; i++) {
|
||||
await limiter.checkDailyLimit(testKey, 100);
|
||||
}
|
||||
|
||||
const result = await limiter.checkDailyLimit(testKey, 100);
|
||||
|
||||
expect(result.remaining).toBe(0);
|
||||
expect(result.retryAfter).toBeGreaterThan(0);
|
||||
});
|
||||
});
|
||||
|
||||
describe('reset', () => {
|
||||
it('should clear the rate limit counter', async () => {
|
||||
await limiter.checkLimit(testKey, 60, 10);
|
||||
await limiter.checkLimit(testKey, 60, 10);
|
||||
|
||||
await limiter.reset(testKey);
|
||||
|
||||
const result = await limiter.checkLimit(testKey, 60, 10);
|
||||
|
||||
expect(result.remaining).toBe(9);
|
||||
});
|
||||
});
|
||||
});
|
||||
18
apps/api/src/config/redis.ts
Normal file
18
apps/api/src/config/redis.ts
Normal file
@@ -0,0 +1,18 @@
|
||||
import { Redis } from 'ioredis';
|
||||
|
||||
const redisHost = process.env.REDIS_HOST || 'localhost';
|
||||
const redisPort = parseInt(process.env.REDIS_PORT || '6379', 10);
|
||||
|
||||
export const redis = new Redis({
|
||||
host: redisHost,
|
||||
port: redisPort,
|
||||
retryStrategy: (times: number) => Math.min(times * 50, 2000),
|
||||
lazyConnect: true,
|
||||
});
|
||||
|
||||
export async function getRedisConnection(): Promise<Redis> {
|
||||
if (redis.status === 'wait' || redis.status === 'connecting') {
|
||||
await redis.connect();
|
||||
}
|
||||
return redis;
|
||||
}
|
||||
@@ -3,6 +3,7 @@ import cors from '@fastify/cors';
|
||||
import helmet from '@fastify/helmet';
|
||||
import { authMiddleware } from './middleware/auth.middleware';
|
||||
import { rateLimitMiddleware } from './middleware/rate-limit.middleware';
|
||||
import { spamRateLimitMiddleware } from './middleware/spam-rate-limit.middleware';
|
||||
import { errorHandlingMiddleware } from './middleware/error-handling.middleware';
|
||||
import { loggingMiddleware } from './middleware/logging.middleware';
|
||||
import { apiEnv, loggingConfig } from './config/api.config';
|
||||
@@ -32,6 +33,9 @@ async function registerPlugins() {
|
||||
// Rate limiting
|
||||
await fastify.register(rateLimitMiddleware);
|
||||
|
||||
// SpamShield rate limiting (Redis-backed)
|
||||
await fastify.register(spamRateLimitMiddleware);
|
||||
|
||||
// Authentication
|
||||
await fastify.register(authMiddleware);
|
||||
|
||||
|
||||
164
apps/api/src/middleware/spam-rate-limit.middleware.ts
Normal file
164
apps/api/src/middleware/spam-rate-limit.middleware.ts
Normal file
@@ -0,0 +1,164 @@
|
||||
import { FastifyInstance, FastifyRequest, FastifyReply } from 'fastify';
|
||||
import { redis } from '../config/redis';
|
||||
import { spamRateLimits } from '../services/spamshield/spamshield.config';
|
||||
|
||||
const REDIS_PREFIX = 'spamshield:ratelimit';
|
||||
|
||||
class RedisRateLimiter {
|
||||
async checkLimit(
|
||||
key: string,
|
||||
windowSeconds: number,
|
||||
maxRequests: number
|
||||
): Promise<{
|
||||
remaining: number;
|
||||
resetTime: number;
|
||||
retryAfter?: number;
|
||||
}> {
|
||||
const redisKey = `${REDIS_PREFIX}:${key}`;
|
||||
const now = Date.now();
|
||||
|
||||
const current = await redis.get(redisKey);
|
||||
const windowStart = now - (now % (windowSeconds * 1000));
|
||||
const resetTime = windowStart + windowSeconds * 1000;
|
||||
|
||||
if (!current) {
|
||||
const expirySeconds = Math.ceil((resetTime - now) / 1000);
|
||||
await redis.set(redisKey, '1', 'EX', expirySeconds);
|
||||
|
||||
return {
|
||||
remaining: maxRequests - 1,
|
||||
resetTime,
|
||||
};
|
||||
}
|
||||
|
||||
const count = parseInt(current, 10) + 1;
|
||||
await redis.set(redisKey, String(count), 'EX', Math.ceil((resetTime - now) / 1000));
|
||||
|
||||
const remaining = maxRequests - count;
|
||||
|
||||
if (count > maxRequests) {
|
||||
return {
|
||||
remaining: 0,
|
||||
resetTime,
|
||||
retryAfter: resetTime - now,
|
||||
};
|
||||
}
|
||||
|
||||
return {
|
||||
remaining,
|
||||
resetTime,
|
||||
};
|
||||
}
|
||||
|
||||
async checkDailyLimit(
|
||||
key: string,
|
||||
maxPerDay: number
|
||||
): Promise<{
|
||||
remaining: number;
|
||||
retryAfter?: number;
|
||||
}> {
|
||||
const redisKey = `${REDIS_PREFIX}:daily:${key}`;
|
||||
const now = Date.now();
|
||||
const dayStart = new Date(now);
|
||||
dayStart.setHours(0, 0, 0, 0);
|
||||
const dayEnd = new Date(dayStart);
|
||||
dayEnd.setDate(dayEnd.getDate() + 1);
|
||||
const resetTime = dayEnd.getTime();
|
||||
|
||||
const current = await redis.get(redisKey);
|
||||
const expirySeconds = Math.ceil((resetTime - now) / 1000);
|
||||
|
||||
if (!current) {
|
||||
await redis.set(redisKey, '1', 'EX', expirySeconds);
|
||||
|
||||
return {
|
||||
remaining: maxPerDay - 1,
|
||||
};
|
||||
}
|
||||
|
||||
const count = parseInt(current, 10) + 1;
|
||||
await redis.set(redisKey, String(count), 'EX', expirySeconds);
|
||||
|
||||
const remaining = maxPerDay - count;
|
||||
|
||||
if (count > maxPerDay) {
|
||||
return {
|
||||
remaining: 0,
|
||||
retryAfter: resetTime - now,
|
||||
};
|
||||
}
|
||||
|
||||
return {
|
||||
remaining,
|
||||
};
|
||||
}
|
||||
|
||||
reset(key: string) {
|
||||
const redisKey = `${REDIS_PREFIX}:${key}`;
|
||||
return redis.del(redisKey);
|
||||
}
|
||||
}
|
||||
|
||||
export const spamRateLimiter = new RedisRateLimiter();
|
||||
|
||||
export async function spamRateLimitMiddleware(fastify: FastifyInstance) {
|
||||
fastify.addHook('preHandler', async (request: FastifyRequest, reply: FastifyReply) => {
|
||||
const url = request.url || '';
|
||||
|
||||
if (!url.startsWith('/spamshield')) {
|
||||
return;
|
||||
}
|
||||
|
||||
const clientIp = request.ip || (request.headers['x-forwarded-for'] as string) || 'unknown';
|
||||
const apiKey = request.headers['x-api-key'] as string | undefined;
|
||||
const key = apiKey ? `api:${apiKey}` : `ip:${clientIp}`;
|
||||
|
||||
let tier = 'basic';
|
||||
if (apiKey) {
|
||||
if (apiKey.startsWith('premium_')) {
|
||||
tier = 'premium';
|
||||
} else if (apiKey.startsWith('plus_')) {
|
||||
tier = 'plus';
|
||||
}
|
||||
}
|
||||
|
||||
const config = spamRateLimits[tier as keyof typeof spamRateLimits];
|
||||
|
||||
const minuteResult = await spamRateLimiter.checkLimit(
|
||||
key,
|
||||
60,
|
||||
config.analysesPerMinute
|
||||
);
|
||||
|
||||
const dailyResult = await spamRateLimiter.checkDailyLimit(
|
||||
key,
|
||||
config.analysesPerDay
|
||||
);
|
||||
|
||||
reply.header('X-RateLimit-Limit', config.analysesPerMinute);
|
||||
reply.header('X-RateLimit-Remaining', minuteResult.remaining);
|
||||
reply.header('X-RateLimit-Reset', Math.ceil(minuteResult.resetTime / 1000));
|
||||
reply.header('X-RateLimit-Daily-Limit', config.analysesPerDay);
|
||||
reply.header('X-RateLimit-Daily-Remaining', dailyResult.remaining);
|
||||
|
||||
const retryAfter = minuteResult.retryAfter || dailyResult.retryAfter;
|
||||
|
||||
if (retryAfter) {
|
||||
reply.header('Retry-After', Math.ceil(retryAfter / 1000));
|
||||
reply.code(429);
|
||||
|
||||
return {
|
||||
error: 'Too Many Requests',
|
||||
message: `Spam analysis rate limit exceeded. Try again in ${Math.ceil(retryAfter / 1000)}s`,
|
||||
tier,
|
||||
limit: config.analysesPerMinute,
|
||||
dailyLimit: config.analysesPerDay,
|
||||
reset: new Date(minuteResult.resetTime).toISOString(),
|
||||
};
|
||||
}
|
||||
|
||||
(request as any).spamRateLimitTier = tier;
|
||||
});
|
||||
}
|
||||
|
||||
export { RedisRateLimiter };
|
||||
@@ -1,6 +1,7 @@
|
||||
import { FastifyInstance, FastifyRequest, FastifyReply } from 'fastify';
|
||||
import { authMiddleware, AuthRequest } from './auth.middleware';
|
||||
import { voiceprintRoutes } from './voiceprint.routes';
|
||||
import { spamshieldRoutes } from './spamshield.routes';
|
||||
|
||||
export async function routes(fastify: FastifyInstance) {
|
||||
// Authenticated routes group
|
||||
@@ -121,4 +122,12 @@ export async function routes(fastify: FastifyInstance) {
|
||||
},
|
||||
{ prefix: '/voiceprint' }
|
||||
);
|
||||
|
||||
// SpamShield service routes
|
||||
fastify.register(
|
||||
async (spamshieldRouter) => {
|
||||
await spamshieldRoutes(spamshieldRouter);
|
||||
},
|
||||
{ prefix: '/spamshield' }
|
||||
);
|
||||
}
|
||||
|
||||
201
apps/api/src/routes/spamshield.routes.ts
Normal file
201
apps/api/src/routes/spamshield.routes.ts
Normal file
@@ -0,0 +1,201 @@
|
||||
import { FastifyInstance, FastifyRequest, FastifyReply } from 'fastify';
|
||||
import {
|
||||
numberReputationService,
|
||||
smsClassifierService,
|
||||
callAnalysisService,
|
||||
spamFeedbackService,
|
||||
} from '../services/spamshield';
|
||||
|
||||
export async function spamshieldRoutes(fastify: FastifyInstance) {
|
||||
// Classify SMS text
|
||||
fastify.post('/sms/classify', async (request: FastifyRequest, reply: FastifyReply) => {
|
||||
const authReq = request as FastifyRequest & { user?: { id: string } };
|
||||
const userId = authReq.user?.id;
|
||||
|
||||
if (!userId) {
|
||||
return reply.code(401).send({ error: 'User ID required' });
|
||||
}
|
||||
|
||||
const body = request.body as { text: string };
|
||||
|
||||
if (!body.text || typeof body.text !== 'string') {
|
||||
return reply.code(400).send({ error: 'text is required' });
|
||||
}
|
||||
|
||||
try {
|
||||
const result = await smsClassifierService.classify(body.text);
|
||||
return reply.send({
|
||||
classification: {
|
||||
isSpam: result.isSpam,
|
||||
confidence: result.confidence,
|
||||
spamFeatures: result.spamFeatures,
|
||||
},
|
||||
});
|
||||
} catch (error) {
|
||||
const message = error instanceof Error ? error.message : 'Classification failed';
|
||||
return reply.code(422).send({ error: message });
|
||||
}
|
||||
});
|
||||
|
||||
// Check number reputation
|
||||
fastify.post('/number/reputation', async (request: FastifyRequest, reply: FastifyReply) => {
|
||||
const authReq = request as FastifyRequest & { user?: { id: string } };
|
||||
const userId = authReq.user?.id;
|
||||
|
||||
if (!userId) {
|
||||
return reply.code(401).send({ error: 'User ID required' });
|
||||
}
|
||||
|
||||
const body = request.body as { phoneNumber: string };
|
||||
|
||||
if (!body.phoneNumber || typeof body.phoneNumber !== 'string') {
|
||||
return reply.code(400).send({ error: 'phoneNumber is required' });
|
||||
}
|
||||
|
||||
try {
|
||||
const result = await numberReputationService.checkReputation(body.phoneNumber);
|
||||
return reply.send({
|
||||
reputation: {
|
||||
isSpam: result.isSpam,
|
||||
confidence: result.confidence,
|
||||
spamType: result.spamType,
|
||||
reportCount: result.reportCount,
|
||||
},
|
||||
});
|
||||
} catch (error) {
|
||||
const message = error instanceof Error ? error.message : 'Reputation check failed';
|
||||
return reply.code(422).send({ error: message });
|
||||
}
|
||||
});
|
||||
|
||||
// Analyze incoming call
|
||||
fastify.post('/call/analyze', async (request: FastifyRequest, reply: FastifyReply) => {
|
||||
const authReq = request as FastifyRequest & { user?: { id: string } };
|
||||
const userId = authReq.user?.id;
|
||||
|
||||
if (!userId) {
|
||||
return reply.code(401).send({ error: 'User ID required' });
|
||||
}
|
||||
|
||||
const body = request.body as {
|
||||
phoneNumber: string;
|
||||
duration?: number;
|
||||
callTime: string;
|
||||
isVoip?: boolean;
|
||||
};
|
||||
|
||||
if (!body.phoneNumber || !body.callTime) {
|
||||
return reply.code(400).send({ error: 'phoneNumber and callTime are required' });
|
||||
}
|
||||
|
||||
try {
|
||||
const result = await callAnalysisService.analyzeCall({
|
||||
phoneNumber: body.phoneNumber,
|
||||
duration: body.duration,
|
||||
callTime: new Date(body.callTime),
|
||||
isVoip: body.isVoip,
|
||||
});
|
||||
return reply.send({
|
||||
analysis: {
|
||||
decision: result.decision,
|
||||
confidence: result.confidence,
|
||||
reasons: result.reasons,
|
||||
},
|
||||
});
|
||||
} catch (error) {
|
||||
const message = error instanceof Error ? error.message : 'Call analysis failed';
|
||||
return reply.code(422).send({ error: message });
|
||||
}
|
||||
});
|
||||
|
||||
// Record spam feedback
|
||||
fastify.post('/feedback', async (request: FastifyRequest, reply: FastifyReply) => {
|
||||
const authReq = request as FastifyRequest & { user?: { id: string } };
|
||||
const userId = authReq.user?.id;
|
||||
|
||||
if (!userId) {
|
||||
return reply.code(401).send({ error: 'User ID required' });
|
||||
}
|
||||
|
||||
const body = request.body as {
|
||||
phoneNumber: string;
|
||||
isSpam: boolean;
|
||||
confidence?: number;
|
||||
metadata?: Record<string, unknown>;
|
||||
};
|
||||
|
||||
if (!body.phoneNumber || typeof body.isSpam !== 'boolean') {
|
||||
return reply.code(400).send({ error: 'phoneNumber and isSpam are required' });
|
||||
}
|
||||
|
||||
try {
|
||||
const feedback = await spamFeedbackService.recordFeedback(
|
||||
userId,
|
||||
body.phoneNumber,
|
||||
body.isSpam,
|
||||
body.confidence,
|
||||
body.metadata
|
||||
);
|
||||
return reply.code(201).send({
|
||||
feedback: {
|
||||
id: feedback.id,
|
||||
phoneNumber: feedback.phoneNumber,
|
||||
isSpam: feedback.isSpam,
|
||||
createdAt: feedback.createdAt,
|
||||
},
|
||||
});
|
||||
} catch (error) {
|
||||
const message = error instanceof Error ? error.message : 'Feedback recording failed';
|
||||
return reply.code(422).send({ error: message });
|
||||
}
|
||||
});
|
||||
|
||||
// Get spam history
|
||||
fastify.get('/history', async (request: FastifyRequest, reply: FastifyReply) => {
|
||||
const authReq = request as FastifyRequest & { user?: { id: string } };
|
||||
const userId = authReq.user?.id;
|
||||
|
||||
if (!userId) {
|
||||
return reply.code(401).send({ error: 'User ID required' });
|
||||
}
|
||||
|
||||
const query = request.query as {
|
||||
limit?: string;
|
||||
isSpam?: string;
|
||||
startDate?: string;
|
||||
};
|
||||
|
||||
const results = await spamFeedbackService.getSpamHistory(userId, {
|
||||
limit: query.limit ? parseInt(query.limit, 10) : undefined,
|
||||
isSpam: query.isSpam !== undefined ? query.isSpam === 'true' : undefined,
|
||||
startDate: query.startDate ? new Date(query.startDate) : undefined,
|
||||
});
|
||||
|
||||
return reply.send({
|
||||
history: results.map((r) => ({
|
||||
id: r.id,
|
||||
phoneNumber: r.phoneNumber,
|
||||
isSpam: r.isSpam,
|
||||
createdAt: r.createdAt,
|
||||
})),
|
||||
});
|
||||
});
|
||||
|
||||
// Get spam statistics
|
||||
fastify.get('/statistics', async (request: FastifyRequest, reply: FastifyReply) => {
|
||||
const authReq = request as FastifyRequest & { user?: { id: string } };
|
||||
const userId = authReq.user?.id;
|
||||
|
||||
if (!userId) {
|
||||
return reply.code(401).send({ error: 'User ID required' });
|
||||
}
|
||||
|
||||
try {
|
||||
const stats = await spamFeedbackService.getStatistics(userId);
|
||||
return reply.send({ statistics: stats });
|
||||
} catch (error) {
|
||||
const message = error instanceof Error ? error.message : 'Statistics retrieval failed';
|
||||
return reply.code(422).send({ error: message });
|
||||
}
|
||||
});
|
||||
}
|
||||
714
package-lock.json
generated
714
package-lock.json
generated
@@ -46,6 +46,7 @@
|
||||
"eslint-plugin-solid": "^0.13.2",
|
||||
"puppeteer-core": "^24.42.0",
|
||||
"tsx": "^4.7.1",
|
||||
"turbo": "^2.9.6",
|
||||
"typescript": "^5.3.3",
|
||||
"vite": "^5.1.4",
|
||||
"vite-plugin-solid": "^2.8.2",
|
||||
@@ -65,7 +66,8 @@
|
||||
"@shieldsai/shared-notifications": "*",
|
||||
"@shieldsai/shared-utils": "*",
|
||||
"fastify": "^4.25.0",
|
||||
"fastify-plugin": "^4.5.0"
|
||||
"fastify-plugin": "^4.5.0",
|
||||
"ioredis": "^5.3.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/node": "^25.6.0",
|
||||
@@ -2603,6 +2605,12 @@
|
||||
"url": "https://opencollective.com/libvips"
|
||||
}
|
||||
},
|
||||
"node_modules/@ioredis/commands": {
|
||||
"version": "1.5.1",
|
||||
"resolved": "https://registry.npmjs.org/@ioredis/commands/-/commands-1.5.1.tgz",
|
||||
"integrity": "sha512-JH8ZL/ywcJyR9MmJ5BNqZllXNZQqQbnVZOqpPQqE1vHiFgAw4NHbvE0FOduNU8IX9babitBT46571OnPTT0Zcw==",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/@isaacs/ttlcache": {
|
||||
"version": "1.4.1",
|
||||
"resolved": "https://registry.npmjs.org/@isaacs/ttlcache/-/ttlcache-1.4.1.tgz",
|
||||
@@ -2869,6 +2877,27 @@
|
||||
"win32"
|
||||
]
|
||||
},
|
||||
"node_modules/@lukeed/csprng": {
|
||||
"version": "1.1.0",
|
||||
"resolved": "https://registry.npmjs.org/@lukeed/csprng/-/csprng-1.1.0.tgz",
|
||||
"integrity": "sha512-Z7C/xXCiGWsg0KuKsHTKJxbWhpI3Vs5GwLfOean7MGyVFGqdRgBbAjOCh6u4bbjPc/8MJ2pZmK/0DLdCbivLDA==",
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">=8"
|
||||
}
|
||||
},
|
||||
"node_modules/@lukeed/uuid": {
|
||||
"version": "2.0.1",
|
||||
"resolved": "https://registry.npmjs.org/@lukeed/uuid/-/uuid-2.0.1.tgz",
|
||||
"integrity": "sha512-qC72D4+CDdjGqJvkFMMEAtancHUQ7/d/tAiHf64z8MopFDmcrtbcJuerDtFceuAfQJ2pDSfCKCtbqoGBNnwg0w==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@lukeed/csprng": "^1.1.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=8"
|
||||
}
|
||||
},
|
||||
"node_modules/@msgpack/msgpack": {
|
||||
"version": "2.8.0",
|
||||
"resolved": "https://registry.npmjs.org/@msgpack/msgpack/-/msgpack-2.8.0.tgz",
|
||||
@@ -2878,6 +2907,84 @@
|
||||
"node": ">= 10"
|
||||
}
|
||||
},
|
||||
"node_modules/@msgpackr-extract/msgpackr-extract-darwin-arm64": {
|
||||
"version": "3.0.3",
|
||||
"resolved": "https://registry.npmjs.org/@msgpackr-extract/msgpackr-extract-darwin-arm64/-/msgpackr-extract-darwin-arm64-3.0.3.tgz",
|
||||
"integrity": "sha512-QZHtlVgbAdy2zAqNA9Gu1UpIuI8Xvsd1v8ic6B2pZmeFnFcMWiPLfWXh7TVw4eGEZ/C9TH281KwhVoeQUKbyjw==",
|
||||
"cpu": [
|
||||
"arm64"
|
||||
],
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"darwin"
|
||||
]
|
||||
},
|
||||
"node_modules/@msgpackr-extract/msgpackr-extract-darwin-x64": {
|
||||
"version": "3.0.3",
|
||||
"resolved": "https://registry.npmjs.org/@msgpackr-extract/msgpackr-extract-darwin-x64/-/msgpackr-extract-darwin-x64-3.0.3.tgz",
|
||||
"integrity": "sha512-mdzd3AVzYKuUmiWOQ8GNhl64/IoFGol569zNRdkLReh6LRLHOXxU4U8eq0JwaD8iFHdVGqSy4IjFL4reoWCDFw==",
|
||||
"cpu": [
|
||||
"x64"
|
||||
],
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"darwin"
|
||||
]
|
||||
},
|
||||
"node_modules/@msgpackr-extract/msgpackr-extract-linux-arm": {
|
||||
"version": "3.0.3",
|
||||
"resolved": "https://registry.npmjs.org/@msgpackr-extract/msgpackr-extract-linux-arm/-/msgpackr-extract-linux-arm-3.0.3.tgz",
|
||||
"integrity": "sha512-fg0uy/dG/nZEXfYilKoRe7yALaNmHoYeIoJuJ7KJ+YyU2bvY8vPv27f7UKhGRpY6euFYqEVhxCFZgAUNQBM3nw==",
|
||||
"cpu": [
|
||||
"arm"
|
||||
],
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"linux"
|
||||
]
|
||||
},
|
||||
"node_modules/@msgpackr-extract/msgpackr-extract-linux-arm64": {
|
||||
"version": "3.0.3",
|
||||
"resolved": "https://registry.npmjs.org/@msgpackr-extract/msgpackr-extract-linux-arm64/-/msgpackr-extract-linux-arm64-3.0.3.tgz",
|
||||
"integrity": "sha512-YxQL+ax0XqBJDZiKimS2XQaf+2wDGVa1enVRGzEvLLVFeqa5kx2bWbtcSXgsxjQB7nRqqIGFIcLteF/sHeVtQg==",
|
||||
"cpu": [
|
||||
"arm64"
|
||||
],
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"linux"
|
||||
]
|
||||
},
|
||||
"node_modules/@msgpackr-extract/msgpackr-extract-linux-x64": {
|
||||
"version": "3.0.3",
|
||||
"resolved": "https://registry.npmjs.org/@msgpackr-extract/msgpackr-extract-linux-x64/-/msgpackr-extract-linux-x64-3.0.3.tgz",
|
||||
"integrity": "sha512-cvwNfbP07pKUfq1uH+S6KJ7dT9K8WOE4ZiAcsrSes+UY55E/0jLYc+vq+DO7jlmqRb5zAggExKm0H7O/CBaesg==",
|
||||
"cpu": [
|
||||
"x64"
|
||||
],
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"linux"
|
||||
]
|
||||
},
|
||||
"node_modules/@msgpackr-extract/msgpackr-extract-win32-x64": {
|
||||
"version": "3.0.3",
|
||||
"resolved": "https://registry.npmjs.org/@msgpackr-extract/msgpackr-extract-win32-x64/-/msgpackr-extract-win32-x64-3.0.3.tgz",
|
||||
"integrity": "sha512-x0fWaQtYp4E6sktbsdAqnehxDgEc/VwM7uLsRCYWaiGu0ykYdZPiS8zCWdnjHwyiumousxfBm4SO31eXqwEZhQ==",
|
||||
"cpu": [
|
||||
"x64"
|
||||
],
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"win32"
|
||||
]
|
||||
},
|
||||
"node_modules/@neon-rs/load": {
|
||||
"version": "0.0.4",
|
||||
"resolved": "https://registry.npmjs.org/@neon-rs/load/-/load-0.0.4.tgz",
|
||||
@@ -3154,6 +3261,74 @@
|
||||
"integrity": "sha512-k2ENnmBugE/rzQfEcdWHcCY+/FM3VLzH9cYEsbdsoqrvzAKRhUZeRNhAZvB8OitQJ1TBed3yqWtdjzS6wJKBwg==",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/@prisma/client": {
|
||||
"version": "5.22.0",
|
||||
"resolved": "https://registry.npmjs.org/@prisma/client/-/client-5.22.0.tgz",
|
||||
"integrity": "sha512-M0SVXfyHnQREBKxCgyo7sffrKttwE6R8PMq330MIUF0pTwjUhLbW84pFDlf06B27XyCR++VtjugEnIHdr07SVA==",
|
||||
"hasInstallScript": true,
|
||||
"license": "Apache-2.0",
|
||||
"engines": {
|
||||
"node": ">=16.13"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"prisma": "*"
|
||||
},
|
||||
"peerDependenciesMeta": {
|
||||
"prisma": {
|
||||
"optional": true
|
||||
}
|
||||
}
|
||||
},
|
||||
"node_modules/@prisma/debug": {
|
||||
"version": "5.22.0",
|
||||
"resolved": "https://registry.npmjs.org/@prisma/debug/-/debug-5.22.0.tgz",
|
||||
"integrity": "sha512-AUt44v3YJeggO2ZU5BkXI7M4hu9BF2zzH2iF2V5pyXT/lRTyWiElZ7It+bRH1EshoMRxHgpYg4VB6rCM+mG5jQ==",
|
||||
"devOptional": true,
|
||||
"license": "Apache-2.0"
|
||||
},
|
||||
"node_modules/@prisma/engines": {
|
||||
"version": "5.22.0",
|
||||
"resolved": "https://registry.npmjs.org/@prisma/engines/-/engines-5.22.0.tgz",
|
||||
"integrity": "sha512-UNjfslWhAt06kVL3CjkuYpHAWSO6L4kDCVPegV6itt7nD1kSJavd3vhgAEhjglLJJKEdJ7oIqDJ+yHk6qO8gPA==",
|
||||
"devOptional": true,
|
||||
"hasInstallScript": true,
|
||||
"license": "Apache-2.0",
|
||||
"dependencies": {
|
||||
"@prisma/debug": "5.22.0",
|
||||
"@prisma/engines-version": "5.22.0-44.605197351a3c8bdd595af2d2a9bc3025bca48ea2",
|
||||
"@prisma/fetch-engine": "5.22.0",
|
||||
"@prisma/get-platform": "5.22.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@prisma/engines-version": {
|
||||
"version": "5.22.0-44.605197351a3c8bdd595af2d2a9bc3025bca48ea2",
|
||||
"resolved": "https://registry.npmjs.org/@prisma/engines-version/-/engines-version-5.22.0-44.605197351a3c8bdd595af2d2a9bc3025bca48ea2.tgz",
|
||||
"integrity": "sha512-2PTmxFR2yHW/eB3uqWtcgRcgAbG1rwG9ZriSvQw+nnb7c4uCr3RAcGMb6/zfE88SKlC1Nj2ziUvc96Z379mHgQ==",
|
||||
"devOptional": true,
|
||||
"license": "Apache-2.0"
|
||||
},
|
||||
"node_modules/@prisma/fetch-engine": {
|
||||
"version": "5.22.0",
|
||||
"resolved": "https://registry.npmjs.org/@prisma/fetch-engine/-/fetch-engine-5.22.0.tgz",
|
||||
"integrity": "sha512-bkrD/Mc2fSvkQBV5EpoFcZ87AvOgDxbG99488a5cexp5Ccny+UM6MAe/UFkUC0wLYD9+9befNOqGiIJhhq+HbA==",
|
||||
"devOptional": true,
|
||||
"license": "Apache-2.0",
|
||||
"dependencies": {
|
||||
"@prisma/debug": "5.22.0",
|
||||
"@prisma/engines-version": "5.22.0-44.605197351a3c8bdd595af2d2a9bc3025bca48ea2",
|
||||
"@prisma/get-platform": "5.22.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@prisma/get-platform": {
|
||||
"version": "5.22.0",
|
||||
"resolved": "https://registry.npmjs.org/@prisma/get-platform/-/get-platform-5.22.0.tgz",
|
||||
"integrity": "sha512-pHhpQdr1UPFpt+zFfnPazhulaZYCUqeIcPpJViYoq9R+D/yw4fjE+CtnsnKzPYm0ddUbeXUzjGVGIRVgPDCk4Q==",
|
||||
"devOptional": true,
|
||||
"license": "Apache-2.0",
|
||||
"dependencies": {
|
||||
"@prisma/debug": "5.22.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@protobufjs/aspromise": {
|
||||
"version": "1.1.2",
|
||||
"resolved": "https://registry.npmjs.org/@protobufjs/aspromise/-/aspromise-1.1.2.tgz",
|
||||
@@ -4095,6 +4270,76 @@
|
||||
"url": "https://paulmillr.com/funding/"
|
||||
}
|
||||
},
|
||||
"node_modules/@segment/analytics-core": {
|
||||
"version": "1.4.1",
|
||||
"resolved": "https://registry.npmjs.org/@segment/analytics-core/-/analytics-core-1.4.1.tgz",
|
||||
"integrity": "sha512-kV0Pf33HnthuBOVdYNani21kYyj118Fn+9757bxqoksiXoZlYvBsFq6giNdCsKcTIE1eAMqNDq3xE1VQ0cfsHA==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@lukeed/uuid": "^2.0.0",
|
||||
"@segment/analytics-generic-utils": "1.1.1",
|
||||
"dset": "^3.1.2",
|
||||
"tslib": "^2.4.1"
|
||||
}
|
||||
},
|
||||
"node_modules/@segment/analytics-generic-utils": {
|
||||
"version": "1.1.1",
|
||||
"resolved": "https://registry.npmjs.org/@segment/analytics-generic-utils/-/analytics-generic-utils-1.1.1.tgz",
|
||||
"integrity": "sha512-THTIzBPHnvu1HYJU3fARdJ3qIkukO3zDXsmDm+kAeUks5R9CBXOQ6rPChiASVzSmwAIIo5uFIXXnCraojlq/Gw==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"tslib": "^2.4.1"
|
||||
}
|
||||
},
|
||||
"node_modules/@segment/analytics-node": {
|
||||
"version": "1.3.0",
|
||||
"resolved": "https://registry.npmjs.org/@segment/analytics-node/-/analytics-node-1.3.0.tgz",
|
||||
"integrity": "sha512-lRLz1WZaDokMoUe299yP5JkInc3OgJuqNNlxb6j0q22umCiq6b5iDo2gRmFn93reirIvJxWIicQsGrHd93q8GQ==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@lukeed/uuid": "^2.0.0",
|
||||
"@segment/analytics-core": "1.4.1",
|
||||
"@segment/analytics-generic-utils": "1.1.1",
|
||||
"buffer": "^6.0.3",
|
||||
"node-fetch": "^2.6.7",
|
||||
"tslib": "^2.4.1"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=14"
|
||||
}
|
||||
},
|
||||
"node_modules/@segment/analytics-node/node_modules/buffer": {
|
||||
"version": "6.0.3",
|
||||
"resolved": "https://registry.npmjs.org/buffer/-/buffer-6.0.3.tgz",
|
||||
"integrity": "sha512-FTiCpNxtwiZZHEZbcbTIcZjERVICn9yq/pDFkTl95/AxzD1naBctN7YO68riM/gLSDY7sdrMby8hofADYuuqOA==",
|
||||
"funding": [
|
||||
{
|
||||
"type": "github",
|
||||
"url": "https://github.com/sponsors/feross"
|
||||
},
|
||||
{
|
||||
"type": "patreon",
|
||||
"url": "https://www.patreon.com/feross"
|
||||
},
|
||||
{
|
||||
"type": "consulting",
|
||||
"url": "https://feross.org/support"
|
||||
}
|
||||
],
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"base64-js": "^1.3.1",
|
||||
"ieee754": "^1.2.1"
|
||||
}
|
||||
},
|
||||
"node_modules/@shieldsai/jobs": {
|
||||
"resolved": "packages/jobs",
|
||||
"link": true
|
||||
},
|
||||
"node_modules/@shieldsai/shared-analytics": {
|
||||
"resolved": "packages/shared-analytics",
|
||||
"link": true
|
||||
},
|
||||
"node_modules/@shieldsai/shared-auth": {
|
||||
"resolved": "packages/shared-auth",
|
||||
"link": true
|
||||
@@ -5016,6 +5261,90 @@
|
||||
"typescript": ">=5.7.2"
|
||||
}
|
||||
},
|
||||
"node_modules/@turbo/darwin-64": {
|
||||
"version": "2.9.6",
|
||||
"resolved": "https://registry.npmjs.org/@turbo/darwin-64/-/darwin-64-2.9.6.tgz",
|
||||
"integrity": "sha512-X/56SnVXIQZBLKwniGTwEQTGmtE5brSACnKMBWpY3YafuxVYefrC2acamfjgxP7BG5w3I+6jf0UrLoSzgPcSJg==",
|
||||
"cpu": [
|
||||
"x64"
|
||||
],
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"darwin"
|
||||
]
|
||||
},
|
||||
"node_modules/@turbo/darwin-arm64": {
|
||||
"version": "2.9.6",
|
||||
"resolved": "https://registry.npmjs.org/@turbo/darwin-arm64/-/darwin-arm64-2.9.6.tgz",
|
||||
"integrity": "sha512-aalBeSl4agT/QtYGDyf/XLajedWzUC9Vg/pm/YO6QQ93vkQ91Vz5uK1ta5RbVRDozQSz4njxUNqRNmOXDzW+qw==",
|
||||
"cpu": [
|
||||
"arm64"
|
||||
],
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"darwin"
|
||||
]
|
||||
},
|
||||
"node_modules/@turbo/linux-64": {
|
||||
"version": "2.9.6",
|
||||
"resolved": "https://registry.npmjs.org/@turbo/linux-64/-/linux-64-2.9.6.tgz",
|
||||
"integrity": "sha512-YKi05jnNHaD7vevgYwahpzGwbsNNTwzU2c7VZdmdFm7+cGDP4oREUWSsainiMfRqjRuolQxBwRn8wf1jmu+YZA==",
|
||||
"cpu": [
|
||||
"x64"
|
||||
],
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"linux"
|
||||
]
|
||||
},
|
||||
"node_modules/@turbo/linux-arm64": {
|
||||
"version": "2.9.6",
|
||||
"resolved": "https://registry.npmjs.org/@turbo/linux-arm64/-/linux-arm64-2.9.6.tgz",
|
||||
"integrity": "sha512-02o/ZS69cOYEDczXvOB2xmyrtzjQ2hVFtWZK1iqxXUfzMmTjZK4UumrfNnjckSg+gqeBfnPRHa0NstA173Ik3g==",
|
||||
"cpu": [
|
||||
"arm64"
|
||||
],
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"linux"
|
||||
]
|
||||
},
|
||||
"node_modules/@turbo/windows-64": {
|
||||
"version": "2.9.6",
|
||||
"resolved": "https://registry.npmjs.org/@turbo/windows-64/-/windows-64-2.9.6.tgz",
|
||||
"integrity": "sha512-wVdQjvnBI15wB6JrA+43CtUtagjIMmX6XYO758oZHAsCNSxqRlJtdyujih0D8OCnwCRWiGWGI63zAxR0hO6s9g==",
|
||||
"cpu": [
|
||||
"x64"
|
||||
],
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"win32"
|
||||
]
|
||||
},
|
||||
"node_modules/@turbo/windows-arm64": {
|
||||
"version": "2.9.6",
|
||||
"resolved": "https://registry.npmjs.org/@turbo/windows-arm64/-/windows-arm64-2.9.6.tgz",
|
||||
"integrity": "sha512-1XUUyWW0W6FTSqGEhU8RHVqb2wP1SPkr7hIvBlMEwH9jr+sJQK5kqeosLJ/QaUv4ecSAd1ZhIrLoW7qslAzT4A==",
|
||||
"cpu": [
|
||||
"arm64"
|
||||
],
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"win32"
|
||||
]
|
||||
},
|
||||
"node_modules/@types/babel__core": {
|
||||
"version": "7.20.5",
|
||||
"resolved": "https://registry.npmjs.org/@types/babel__core/-/babel__core-7.20.5.tgz",
|
||||
@@ -6570,6 +6899,23 @@
|
||||
"node-gyp-build-test": "build-test.js"
|
||||
}
|
||||
},
|
||||
"node_modules/bullmq": {
|
||||
"version": "5.76.4",
|
||||
"resolved": "https://registry.npmjs.org/bullmq/-/bullmq-5.76.4.tgz",
|
||||
"integrity": "sha512-hVAplia7zfN3BxSCgAoRInJnbemfLwJdQLqJy/txEX8UMSTAeg0saPFNGWIlzES/Ct5xQ20TUaik/XwS99DOMA==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"cron-parser": "4.9.0",
|
||||
"ioredis": "5.10.1",
|
||||
"msgpackr": "1.11.5",
|
||||
"node-abort-controller": "3.1.1",
|
||||
"semver": "7.7.4",
|
||||
"tslib": "2.8.1"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=12.22.0"
|
||||
}
|
||||
},
|
||||
"node_modules/cac": {
|
||||
"version": "6.7.14",
|
||||
"resolved": "https://registry.npmjs.org/cac/-/cac-6.7.14.tgz",
|
||||
@@ -6913,6 +7259,15 @@
|
||||
"node": ">=6"
|
||||
}
|
||||
},
|
||||
"node_modules/cluster-key-slot": {
|
||||
"version": "1.1.2",
|
||||
"resolved": "https://registry.npmjs.org/cluster-key-slot/-/cluster-key-slot-1.1.2.tgz",
|
||||
"integrity": "sha512-RMr0FhtfXemyinomL4hrWcYJxmX6deFdCxpJzhDttxgO1+bcCnkk+9drydLVDmAMG7NE6aN/fl4F7ucU/90gAA==",
|
||||
"license": "Apache-2.0",
|
||||
"engines": {
|
||||
"node": ">=0.10.0"
|
||||
}
|
||||
},
|
||||
"node_modules/color-convert": {
|
||||
"version": "2.0.1",
|
||||
"resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz",
|
||||
@@ -7081,6 +7436,18 @@
|
||||
"dev": true,
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/cron-parser": {
|
||||
"version": "4.9.0",
|
||||
"resolved": "https://registry.npmjs.org/cron-parser/-/cron-parser-4.9.0.tgz",
|
||||
"integrity": "sha512-p0SaNjrHOnQeR8/VnfGbmg9te2kfyYSQ7Sc/j/6DtPL3JQvKxmjO9TSjNFpujqV3vEYYBvNNvXSxzyksBWAx1Q==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"luxon": "^3.2.1"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=12.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/cross-spawn": {
|
||||
"version": "7.0.6",
|
||||
"resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.6.tgz",
|
||||
@@ -7257,6 +7624,15 @@
|
||||
"node": ">=0.4.0"
|
||||
}
|
||||
},
|
||||
"node_modules/denque": {
|
||||
"version": "2.1.0",
|
||||
"resolved": "https://registry.npmjs.org/denque/-/denque-2.1.0.tgz",
|
||||
"integrity": "sha512-HVQE3AAb/pxF8fQAoiqpvg9i3evqug3hoiwakOyZAwJm+6vZehbkYXZ0l4JxS+I3QxM97v5aaRNhj8v5oBhekw==",
|
||||
"license": "Apache-2.0",
|
||||
"engines": {
|
||||
"node": ">=0.10"
|
||||
}
|
||||
},
|
||||
"node_modules/depd": {
|
||||
"version": "2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz",
|
||||
@@ -7942,6 +8318,15 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"node_modules/dset": {
|
||||
"version": "3.1.4",
|
||||
"resolved": "https://registry.npmjs.org/dset/-/dset-3.1.4.tgz",
|
||||
"integrity": "sha512-2QF/g9/zTaPDc3BjNcVTGoBbXBgYfMTTceLaYcFJ/W9kggFUkhxD/hMEeuLKbugyef9SqAx8cpgwlIP/jinUTA==",
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">=4"
|
||||
}
|
||||
},
|
||||
"node_modules/dunder-proto": {
|
||||
"version": "1.0.1",
|
||||
"resolved": "https://registry.npmjs.org/dunder-proto/-/dunder-proto-1.0.1.tgz",
|
||||
@@ -9348,7 +9733,6 @@
|
||||
"resolved": "https://registry.npmjs.org/gaxios/-/gaxios-6.7.1.tgz",
|
||||
"integrity": "sha512-LDODD4TMYx7XXdpwxAVRAIAuB0bzv0s+ywFonY46k126qzQHT9ygyoa9tncmOiQmmDrik65UYsEkv3lbfqQ3yQ==",
|
||||
"license": "Apache-2.0",
|
||||
"optional": true,
|
||||
"dependencies": {
|
||||
"extend": "^3.0.2",
|
||||
"https-proxy-agent": "^7.0.1",
|
||||
@@ -9365,7 +9749,6 @@
|
||||
"resolved": "https://registry.npmjs.org/is-stream/-/is-stream-2.0.1.tgz",
|
||||
"integrity": "sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg==",
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"engines": {
|
||||
"node": ">=8"
|
||||
},
|
||||
@@ -9382,7 +9765,6 @@
|
||||
"https://github.com/sponsors/ctavan"
|
||||
],
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"bin": {
|
||||
"uuid": "dist/bin/uuid"
|
||||
}
|
||||
@@ -9814,6 +10196,130 @@
|
||||
"node": ">=14"
|
||||
}
|
||||
},
|
||||
"node_modules/googleapis": {
|
||||
"version": "128.0.0",
|
||||
"resolved": "https://registry.npmjs.org/googleapis/-/googleapis-128.0.0.tgz",
|
||||
"integrity": "sha512-+sLtVYNazcxaSD84N6rihVX4QiGoqRdnlz2SwmQQkadF31XonDfy4ufk3maMg27+FiySrH0rd7V8p+YJG6cknA==",
|
||||
"license": "Apache-2.0",
|
||||
"dependencies": {
|
||||
"google-auth-library": "^9.0.0",
|
||||
"googleapis-common": "^7.0.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=14.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/googleapis-common": {
|
||||
"version": "7.2.0",
|
||||
"resolved": "https://registry.npmjs.org/googleapis-common/-/googleapis-common-7.2.0.tgz",
|
||||
"integrity": "sha512-/fhDZEJZvOV3X5jmD+fKxMqma5q2Q9nZNSF3kn1F18tpxmA86BcTxAGBQdM0N89Z3bEaIs+HVznSmFJEAmMTjA==",
|
||||
"license": "Apache-2.0",
|
||||
"dependencies": {
|
||||
"extend": "^3.0.2",
|
||||
"gaxios": "^6.0.3",
|
||||
"google-auth-library": "^9.7.0",
|
||||
"qs": "^6.7.0",
|
||||
"url-template": "^2.0.8",
|
||||
"uuid": "^9.0.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=14.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/googleapis-common/node_modules/gcp-metadata": {
|
||||
"version": "6.1.1",
|
||||
"resolved": "https://registry.npmjs.org/gcp-metadata/-/gcp-metadata-6.1.1.tgz",
|
||||
"integrity": "sha512-a4tiq7E0/5fTjxPAaH4jpjkSv/uCaU2p5KC6HVGrvl0cDjA8iBZv4vv1gyzlmK0ZUKqwpOyQMKzZQe3lTit77A==",
|
||||
"license": "Apache-2.0",
|
||||
"dependencies": {
|
||||
"gaxios": "^6.1.1",
|
||||
"google-logging-utils": "^0.0.2",
|
||||
"json-bigint": "^1.0.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=14"
|
||||
}
|
||||
},
|
||||
"node_modules/googleapis-common/node_modules/google-auth-library": {
|
||||
"version": "9.15.1",
|
||||
"resolved": "https://registry.npmjs.org/google-auth-library/-/google-auth-library-9.15.1.tgz",
|
||||
"integrity": "sha512-Jb6Z0+nvECVz+2lzSMt9u98UsoakXxA2HGHMCxh+so3n90XgYWkq5dur19JAJV7ONiJY22yBTyJB1TSkvPq9Ng==",
|
||||
"license": "Apache-2.0",
|
||||
"dependencies": {
|
||||
"base64-js": "^1.3.0",
|
||||
"ecdsa-sig-formatter": "^1.0.11",
|
||||
"gaxios": "^6.1.1",
|
||||
"gcp-metadata": "^6.1.0",
|
||||
"gtoken": "^7.0.0",
|
||||
"jws": "^4.0.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=14"
|
||||
}
|
||||
},
|
||||
"node_modules/googleapis-common/node_modules/google-logging-utils": {
|
||||
"version": "0.0.2",
|
||||
"resolved": "https://registry.npmjs.org/google-logging-utils/-/google-logging-utils-0.0.2.tgz",
|
||||
"integrity": "sha512-NEgUnEcBiP5HrPzufUkBzJOD/Sxsco3rLNo1F1TNf7ieU8ryUzBhqba8r756CjLX7rn3fHl6iLEwPYuqpoKgQQ==",
|
||||
"license": "Apache-2.0",
|
||||
"engines": {
|
||||
"node": ">=14"
|
||||
}
|
||||
},
|
||||
"node_modules/googleapis-common/node_modules/uuid": {
|
||||
"version": "9.0.1",
|
||||
"resolved": "https://registry.npmjs.org/uuid/-/uuid-9.0.1.tgz",
|
||||
"integrity": "sha512-b+1eJOlsR9K8HJpow9Ok3fiWOWSIcIzXodvv0rQjVoOVNpWMpxf1wZNpt4y9h10odCNrqnYp1OBzRktckBe3sA==",
|
||||
"deprecated": "uuid@10 and below is no longer supported. For ESM codebases, update to uuid@latest. For CommonJS codebases, use uuid@11 (but be aware this version will likely be deprecated in 2028).",
|
||||
"funding": [
|
||||
"https://github.com/sponsors/broofa",
|
||||
"https://github.com/sponsors/ctavan"
|
||||
],
|
||||
"license": "MIT",
|
||||
"bin": {
|
||||
"uuid": "dist/bin/uuid"
|
||||
}
|
||||
},
|
||||
"node_modules/googleapis/node_modules/gcp-metadata": {
|
||||
"version": "6.1.1",
|
||||
"resolved": "https://registry.npmjs.org/gcp-metadata/-/gcp-metadata-6.1.1.tgz",
|
||||
"integrity": "sha512-a4tiq7E0/5fTjxPAaH4jpjkSv/uCaU2p5KC6HVGrvl0cDjA8iBZv4vv1gyzlmK0ZUKqwpOyQMKzZQe3lTit77A==",
|
||||
"license": "Apache-2.0",
|
||||
"dependencies": {
|
||||
"gaxios": "^6.1.1",
|
||||
"google-logging-utils": "^0.0.2",
|
||||
"json-bigint": "^1.0.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=14"
|
||||
}
|
||||
},
|
||||
"node_modules/googleapis/node_modules/google-auth-library": {
|
||||
"version": "9.15.1",
|
||||
"resolved": "https://registry.npmjs.org/google-auth-library/-/google-auth-library-9.15.1.tgz",
|
||||
"integrity": "sha512-Jb6Z0+nvECVz+2lzSMt9u98UsoakXxA2HGHMCxh+so3n90XgYWkq5dur19JAJV7ONiJY22yBTyJB1TSkvPq9Ng==",
|
||||
"license": "Apache-2.0",
|
||||
"dependencies": {
|
||||
"base64-js": "^1.3.0",
|
||||
"ecdsa-sig-formatter": "^1.0.11",
|
||||
"gaxios": "^6.1.1",
|
||||
"gcp-metadata": "^6.1.0",
|
||||
"gtoken": "^7.0.0",
|
||||
"jws": "^4.0.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=14"
|
||||
}
|
||||
},
|
||||
"node_modules/googleapis/node_modules/google-logging-utils": {
|
||||
"version": "0.0.2",
|
||||
"resolved": "https://registry.npmjs.org/google-logging-utils/-/google-logging-utils-0.0.2.tgz",
|
||||
"integrity": "sha512-NEgUnEcBiP5HrPzufUkBzJOD/Sxsco3rLNo1F1TNf7ieU8ryUzBhqba8r756CjLX7rn3fHl6iLEwPYuqpoKgQQ==",
|
||||
"license": "Apache-2.0",
|
||||
"engines": {
|
||||
"node": ">=14"
|
||||
}
|
||||
},
|
||||
"node_modules/gopd": {
|
||||
"version": "1.2.0",
|
||||
"resolved": "https://registry.npmjs.org/gopd/-/gopd-1.2.0.tgz",
|
||||
@@ -9871,7 +10377,6 @@
|
||||
"resolved": "https://registry.npmjs.org/gtoken/-/gtoken-7.1.0.tgz",
|
||||
"integrity": "sha512-pCcEwRi+TKpMlxAQObHDQ56KawURgyAf6jtIY046fJ5tIv3zDe/LEIubckAO8fj6JnAxLdmWkUfNyulQ2iKdEw==",
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"dependencies": {
|
||||
"gaxios": "^6.0.0",
|
||||
"jws": "^4.0.0"
|
||||
@@ -10214,6 +10719,30 @@
|
||||
"loose-envify": "^1.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/ioredis": {
|
||||
"version": "5.10.1",
|
||||
"resolved": "https://registry.npmjs.org/ioredis/-/ioredis-5.10.1.tgz",
|
||||
"integrity": "sha512-HuEDBTI70aYdx1v6U97SbNx9F1+svQKBDo30o0b9fw055LMepzpOOd0Ccg9Q6tbqmBSJaMuY0fB7yw9/vjBYCA==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@ioredis/commands": "1.5.1",
|
||||
"cluster-key-slot": "^1.1.0",
|
||||
"debug": "^4.3.4",
|
||||
"denque": "^2.1.0",
|
||||
"lodash.defaults": "^4.2.0",
|
||||
"lodash.isarguments": "^3.1.0",
|
||||
"redis-errors": "^1.2.0",
|
||||
"redis-parser": "^3.0.0",
|
||||
"standard-as-callback": "^2.1.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=12.22.0"
|
||||
},
|
||||
"funding": {
|
||||
"type": "opencollective",
|
||||
"url": "https://opencollective.com/ioredis"
|
||||
}
|
||||
},
|
||||
"node_modules/ip-address": {
|
||||
"version": "10.1.0",
|
||||
"resolved": "https://registry.npmjs.org/ip-address/-/ip-address-10.1.0.tgz",
|
||||
@@ -11137,12 +11666,24 @@
|
||||
"integrity": "sha512-FT1yDzDYEoYWhnSGnpE/4Kj1fLZkDFyqRb7fNt6FdYOSxlUWAtp42Eh6Wb0rGIv/m9Bgo7x4GhQbm5Ys4SG5ow==",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/lodash.defaults": {
|
||||
"version": "4.2.0",
|
||||
"resolved": "https://registry.npmjs.org/lodash.defaults/-/lodash.defaults-4.2.0.tgz",
|
||||
"integrity": "sha512-qjxPLHd3r5DnsdGacqOMU6pb/avJzdh9tFX2ymgoZE27BmjXrNy/y4LoaiTeAb+O3gL8AfpJGtqfX/ae2leYYQ==",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/lodash.includes": {
|
||||
"version": "4.3.0",
|
||||
"resolved": "https://registry.npmjs.org/lodash.includes/-/lodash.includes-4.3.0.tgz",
|
||||
"integrity": "sha512-W3Bx6mdkRTGtlJISOvVD/lbqjTlPPUDTMnlXZFnVwi9NKJ6tiAk6LVdlhZMm17VZisqhKcgzpO5Wz91PCt5b0w==",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/lodash.isarguments": {
|
||||
"version": "3.1.0",
|
||||
"resolved": "https://registry.npmjs.org/lodash.isarguments/-/lodash.isarguments-3.1.0.tgz",
|
||||
"integrity": "sha512-chi4NHZlZqZD18a0imDHnZPrDeBbTtVN7GXMwuGdRH9qotxAjYs3aVLKc7zNOG9eddR5Ksd8rvFEBc9SsggPpg==",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/lodash.isboolean": {
|
||||
"version": "3.0.3",
|
||||
"resolved": "https://registry.npmjs.org/lodash.isboolean/-/lodash.isboolean-3.0.3.tgz",
|
||||
@@ -11277,6 +11818,15 @@
|
||||
"license": "MIT",
|
||||
"optional": true
|
||||
},
|
||||
"node_modules/luxon": {
|
||||
"version": "3.7.2",
|
||||
"resolved": "https://registry.npmjs.org/luxon/-/luxon-3.7.2.tgz",
|
||||
"integrity": "sha512-vtEhXh/gNjI9Yg1u4jX/0YVPMvxzHuGgCm6tC5kZyb08yjGWGnqAjGJvcXbqQR2P3MyMEFnRbpcdFS6PBcLqew==",
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">=12"
|
||||
}
|
||||
},
|
||||
"node_modules/magic-string": {
|
||||
"version": "0.30.21",
|
||||
"resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.30.21.tgz",
|
||||
@@ -11996,6 +12546,37 @@
|
||||
"integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/msgpackr": {
|
||||
"version": "1.11.5",
|
||||
"resolved": "https://registry.npmjs.org/msgpackr/-/msgpackr-1.11.5.tgz",
|
||||
"integrity": "sha512-UjkUHN0yqp9RWKy0Lplhh+wlpdt9oQBYgULZOiFhV3VclSF1JnSQWZ5r9gORQlNYaUKQoR8itv7g7z1xDDuACA==",
|
||||
"license": "MIT",
|
||||
"optionalDependencies": {
|
||||
"msgpackr-extract": "^3.0.2"
|
||||
}
|
||||
},
|
||||
"node_modules/msgpackr-extract": {
|
||||
"version": "3.0.3",
|
||||
"resolved": "https://registry.npmjs.org/msgpackr-extract/-/msgpackr-extract-3.0.3.tgz",
|
||||
"integrity": "sha512-P0efT1C9jIdVRefqjzOQ9Xml57zpOXnIuS+csaB4MdZbTdmGDLo8XhzBG1N7aO11gKDDkJvBLULeFTo46wwreA==",
|
||||
"hasInstallScript": true,
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"dependencies": {
|
||||
"node-gyp-build-optional-packages": "5.2.2"
|
||||
},
|
||||
"bin": {
|
||||
"download-msgpackr-prebuilds": "bin/download-prebuilds.js"
|
||||
},
|
||||
"optionalDependencies": {
|
||||
"@msgpackr-extract/msgpackr-extract-darwin-arm64": "3.0.3",
|
||||
"@msgpackr-extract/msgpackr-extract-darwin-x64": "3.0.3",
|
||||
"@msgpackr-extract/msgpackr-extract-linux-arm": "3.0.3",
|
||||
"@msgpackr-extract/msgpackr-extract-linux-arm64": "3.0.3",
|
||||
"@msgpackr-extract/msgpackr-extract-linux-x64": "3.0.3",
|
||||
"@msgpackr-extract/msgpackr-extract-win32-x64": "3.0.3"
|
||||
}
|
||||
},
|
||||
"node_modules/nanoid": {
|
||||
"version": "3.3.11",
|
||||
"resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.11.tgz",
|
||||
@@ -12193,6 +12774,12 @@
|
||||
"node": ">=10"
|
||||
}
|
||||
},
|
||||
"node_modules/node-abort-controller": {
|
||||
"version": "3.1.1",
|
||||
"resolved": "https://registry.npmjs.org/node-abort-controller/-/node-abort-controller-3.1.1.tgz",
|
||||
"integrity": "sha512-AGK2yQKIjRuqnc6VkX2Xj5d+QW8xZ87pa1UK6yA6ouUyuxfHuMP6umE5QK7UmTeOAymo+Zx1Fxiuw9rVx8taHQ==",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/node-domexception": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/node-domexception/-/node-domexception-1.0.0.tgz",
|
||||
@@ -12254,6 +12841,21 @@
|
||||
"node-gyp-build-test": "build-test.js"
|
||||
}
|
||||
},
|
||||
"node_modules/node-gyp-build-optional-packages": {
|
||||
"version": "5.2.2",
|
||||
"resolved": "https://registry.npmjs.org/node-gyp-build-optional-packages/-/node-gyp-build-optional-packages-5.2.2.tgz",
|
||||
"integrity": "sha512-s+w+rBWnpTMwSFbaE0UXsRlg7hU4FjekKU4eyAih5T8nJuNZT1nNsskXpxmeqSK9UzkBl6UgRlnKc8hz8IEqOw==",
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"dependencies": {
|
||||
"detect-libc": "^2.0.1"
|
||||
},
|
||||
"bin": {
|
||||
"node-gyp-build-optional-packages": "bin.js",
|
||||
"node-gyp-build-optional-packages-optional": "optional.js",
|
||||
"node-gyp-build-optional-packages-test": "build-test.js"
|
||||
}
|
||||
},
|
||||
"node_modules/node-int64": {
|
||||
"version": "0.4.0",
|
||||
"resolved": "https://registry.npmjs.org/node-int64/-/node-int64-0.4.0.tgz",
|
||||
@@ -12995,6 +13597,26 @@
|
||||
"url": "https://github.com/chalk/ansi-styles?sponsor=1"
|
||||
}
|
||||
},
|
||||
"node_modules/prisma": {
|
||||
"version": "5.22.0",
|
||||
"resolved": "https://registry.npmjs.org/prisma/-/prisma-5.22.0.tgz",
|
||||
"integrity": "sha512-vtpjW3XuYCSnMsNVBjLMNkTj6OZbudcPPTPYHqX0CJfpcdWciI1dM8uHETwmDxxiqEwCIE6WvXucWUetJgfu/A==",
|
||||
"devOptional": true,
|
||||
"hasInstallScript": true,
|
||||
"license": "Apache-2.0",
|
||||
"dependencies": {
|
||||
"@prisma/engines": "5.22.0"
|
||||
},
|
||||
"bin": {
|
||||
"prisma": "build/index.js"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=16.13"
|
||||
},
|
||||
"optionalDependencies": {
|
||||
"fsevents": "2.3.3"
|
||||
}
|
||||
},
|
||||
"node_modules/process-nextick-args": {
|
||||
"version": "2.0.1",
|
||||
"resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz",
|
||||
@@ -13603,6 +14225,27 @@
|
||||
"node": ">= 12.13.0"
|
||||
}
|
||||
},
|
||||
"node_modules/redis-errors": {
|
||||
"version": "1.2.0",
|
||||
"resolved": "https://registry.npmjs.org/redis-errors/-/redis-errors-1.2.0.tgz",
|
||||
"integrity": "sha512-1qny3OExCf0UvUV/5wpYKf2YwPcOqXzkwKKSmKHiE6ZMQs5heeE/c8eXK+PNllPvmjgAbfnsbpkGZWy8cBpn9w==",
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">=4"
|
||||
}
|
||||
},
|
||||
"node_modules/redis-parser": {
|
||||
"version": "3.0.0",
|
||||
"resolved": "https://registry.npmjs.org/redis-parser/-/redis-parser-3.0.0.tgz",
|
||||
"integrity": "sha512-DJnGAeenTdpMEH6uAJRK/uiyEIH9WVsUmoLwzudwGJUwZPp80PDBWPHXSAGNPwNvIXAbe7MSUB1zQFugFml66A==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"redis-errors": "^1.0.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=4"
|
||||
}
|
||||
},
|
||||
"node_modules/regenerator-runtime": {
|
||||
"version": "0.13.11",
|
||||
"resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.13.11.tgz",
|
||||
@@ -14517,6 +15160,12 @@
|
||||
"node": ">=8"
|
||||
}
|
||||
},
|
||||
"node_modules/standard-as-callback": {
|
||||
"version": "2.1.0",
|
||||
"resolved": "https://registry.npmjs.org/standard-as-callback/-/standard-as-callback-2.1.0.tgz",
|
||||
"integrity": "sha512-qoRRSyROncaz1z0mvYqIE4lCd9p2R90i6GxW3uZv5ucSu8tU7B5HXUP1gG8pVZsYNVaXjk8ClXHPttLyxAL48A==",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/standardwebhooks": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/standardwebhooks/-/standardwebhooks-1.0.0.tgz",
|
||||
@@ -15141,6 +15790,24 @@
|
||||
"node": "*"
|
||||
}
|
||||
},
|
||||
"node_modules/turbo": {
|
||||
"version": "2.9.6",
|
||||
"resolved": "https://registry.npmjs.org/turbo/-/turbo-2.9.6.tgz",
|
||||
"integrity": "sha512-+v2QJey7ZUeUiuigkU+uFfklvNUyPI2VO2vBpMYJA+a1hKFLFiKtUYlRHdb3P9CrAvMzi0upbjI4WT+zKtqkBg==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"bin": {
|
||||
"turbo": "bin/turbo"
|
||||
},
|
||||
"optionalDependencies": {
|
||||
"@turbo/darwin-64": "2.9.6",
|
||||
"@turbo/darwin-arm64": "2.9.6",
|
||||
"@turbo/linux-64": "2.9.6",
|
||||
"@turbo/linux-arm64": "2.9.6",
|
||||
"@turbo/windows-64": "2.9.6",
|
||||
"@turbo/windows-arm64": "2.9.6"
|
||||
}
|
||||
},
|
||||
"node_modules/twilio": {
|
||||
"version": "5.13.1",
|
||||
"resolved": "https://registry.npmjs.org/twilio/-/twilio-5.13.1.tgz",
|
||||
@@ -15310,6 +15977,12 @@
|
||||
"punycode": "^2.1.0"
|
||||
}
|
||||
},
|
||||
"node_modules/url-template": {
|
||||
"version": "2.0.8",
|
||||
"resolved": "https://registry.npmjs.org/url-template/-/url-template-2.0.8.tgz",
|
||||
"integrity": "sha512-XdVKMF4SJ0nP/O7XIPB0JwAEuT9lDIYnNsK8yGVe43y0AWoKeJNdv3ZNWh7ksJ6KqQFjOO6ox/VEitLnaVNufw==",
|
||||
"license": "BSD"
|
||||
},
|
||||
"node_modules/utf-8-validate": {
|
||||
"version": "6.0.6",
|
||||
"resolved": "https://registry.npmjs.org/utf-8-validate/-/utf-8-validate-6.0.6.tgz",
|
||||
@@ -16609,6 +17282,33 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"packages/jobs": {
|
||||
"name": "@shieldsai/jobs",
|
||||
"version": "0.1.0",
|
||||
"dependencies": {
|
||||
"@shieldsai/shared-db": "*",
|
||||
"@shieldsai/shared-utils": "*",
|
||||
"bullmq": "^5.1.0",
|
||||
"ioredis": "^5.3.0",
|
||||
"zod": "^4.3.6"
|
||||
},
|
||||
"devDependencies": {
|
||||
"tsx": "^4.7.1",
|
||||
"typescript": "^5.3.3"
|
||||
}
|
||||
},
|
||||
"packages/shared-analytics": {
|
||||
"name": "@shieldsai/shared-analytics",
|
||||
"version": "0.1.0",
|
||||
"dependencies": {
|
||||
"@segment/analytics-node": "^1.0.0",
|
||||
"googleapis": "^128.0.0",
|
||||
"zod": "^4.3.6"
|
||||
},
|
||||
"devDependencies": {
|
||||
"typescript": "^5.3.3"
|
||||
}
|
||||
},
|
||||
"packages/shared-auth": {
|
||||
"name": "@shieldsai/shared-auth",
|
||||
"version": "0.1.0",
|
||||
@@ -16624,11 +17324,11 @@
|
||||
"name": "@shieldsai/shared-db",
|
||||
"version": "0.1.0",
|
||||
"dependencies": {
|
||||
"drizzle-orm": "^0.45.2",
|
||||
"@prisma/client": "^5.14.0",
|
||||
"zod": "^4.3.6"
|
||||
},
|
||||
"devDependencies": {
|
||||
"drizzle-kit": "^0.31.10",
|
||||
"prisma": "^5.14.0",
|
||||
"typescript": "^5.3.3"
|
||||
}
|
||||
},
|
||||
|
||||
@@ -7,6 +7,10 @@ export default defineConfig({
|
||||
deps: {
|
||||
interopDefault: true,
|
||||
},
|
||||
env: {
|
||||
HIYA_API_KEY: 'test-api-key',
|
||||
HIYA_API_URL: 'https://api.hiya.com/v1',
|
||||
},
|
||||
},
|
||||
optimizeDeps: {
|
||||
include: ['ws'],
|
||||
|
||||
Reference in New Issue
Block a user