From 4aa53c1ee9407b02a94b503678418bc704a706d9 Mon Sep 17 00:00:00 2001
From: Devarshi Shimpi
Date: Tue, 22 Sep 2026 01:29:40 +0530
Subject: [PATCH 01/16] feat(node): wire up BullMQ worker and Redis adapters
---
apps/node/src/adapters/node-orchestrator.ts | 38 +++++++++++++
apps/node/src/adapters/platform.ts | 13 +++++
apps/node/src/adapters/redis-session-store.ts | 36 +++++++++++++
apps/node/src/adapters/services.ts | 40 ++++++++++++++
apps/node/src/adapters/telemetry.ts | 11 ++++
apps/node/src/api-deps.ts | 5 +-
apps/node/src/env.ts | 6 +--
apps/node/src/index.ts | 39 +++++++++-----
apps/node/src/runtime.ts | 53 +++++++++++++++++++
apps/node/src/worker.ts | 37 +++++++++++++
package-lock.json | 31 ++++++++---
package.json | 1 +
12 files changed, 284 insertions(+), 26 deletions(-)
create mode 100644 apps/node/src/adapters/node-orchestrator.ts
create mode 100644 apps/node/src/adapters/platform.ts
create mode 100644 apps/node/src/adapters/redis-session-store.ts
create mode 100644 apps/node/src/adapters/services.ts
create mode 100644 apps/node/src/adapters/telemetry.ts
create mode 100644 apps/node/src/runtime.ts
create mode 100644 apps/node/src/worker.ts
diff --git a/apps/node/src/adapters/node-orchestrator.ts b/apps/node/src/adapters/node-orchestrator.ts
new file mode 100644
index 00000000..32fe8f4c
--- /dev/null
+++ b/apps/node/src/adapters/node-orchestrator.ts
@@ -0,0 +1,38 @@
+import type { JobOrchestrator, ReviewRuntime } from '@codraoss/core';
+import type { ReviewJobMessage } from '@codraoss/schema';
+import { runReview } from '@codraoss/core';
+import { runWithDb } from '@codraoss/db/client';
+import type { DbEnv } from '@codraoss/db/env';
+import { setTimeout } from 'node:timers/promises';
+
+export class NodeOrchestrator implements JobOrchestrator {
+ constructor(private readonly env: ReviewRuntime & DbEnv) {}
+
+ async startReviewJob(id: string, params: ReviewJobMessage): Promise {
+ return runWithDb(this.env, async () => {
+ let currentParams = { ...params };
+ let phase = currentParams.phase ?? 'prepare';
+
+ while (phase) {
+ currentParams.phase = phase;
+ const result = await runReview(this.env, currentParams);
+
+ if (result.action === 'next_phase') {
+ phase = result.phase;
+ if (result.jobId) {
+ currentParams.jobId = result.jobId;
+ }
+ if (result.delaySeconds > 0) {
+ await setTimeout(result.delaySeconds * 1000);
+ }
+ } else if (result.action === 'retry') {
+ if (result.delaySeconds > 0) {
+ await setTimeout(result.delaySeconds * 1000);
+ }
+ } else if (result.action === 'ack') {
+ break;
+ }
+ }
+ });
+ }
+}
diff --git a/apps/node/src/adapters/platform.ts b/apps/node/src/adapters/platform.ts
new file mode 100644
index 00000000..f3b8855b
--- /dev/null
+++ b/apps/node/src/adapters/platform.ts
@@ -0,0 +1,13 @@
+import type { Clock, IdGenerator, KvStore } from '@codraoss/core/ports';
+import type { NodeAppBindings } from '../env';
+
+export function makeKvStore(env: NodeAppBindings): KvStore {
+ return {
+ get: (key) => env.APP_KV.get(key),
+ put: (key, value, options) => env.APP_KV.put(key, value, options),
+ };
+}
+
+export const systemClock: Clock = { now: () => Date.now() };
+
+export const cryptoIds: IdGenerator = { randomUUID: () => crypto.randomUUID() };
diff --git a/apps/node/src/adapters/redis-session-store.ts b/apps/node/src/adapters/redis-session-store.ts
new file mode 100644
index 00000000..d4c75e71
--- /dev/null
+++ b/apps/node/src/adapters/redis-session-store.ts
@@ -0,0 +1,36 @@
+import type { DashboardSessionUser, SessionStore } from '@codraoss/core/ports';
+import type Redis from 'ioredis';
+import { customAlphabet } from 'nanoid';
+
+const nanoid = customAlphabet('abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789', 21);
+
+export class RedisSessionStore implements SessionStore {
+ constructor(private readonly redis: Redis) {}
+
+ private sessionKey(id: string): string {
+ return `session:${id}`;
+ }
+
+ async createSession(session: DashboardSessionUser): Promise {
+ const id = nanoid();
+ await this.redis.setex(this.sessionKey(id), 60 * 60 * 24 * 7, JSON.stringify(session)); // 7 days expiration
+ return id;
+ }
+
+ async readSession(token: string): Promise {
+ const sessionString = await this.redis.get(this.sessionKey(token));
+ if (!sessionString) {
+ return null;
+ }
+ return JSON.parse(sessionString) as DashboardSessionUser;
+ }
+
+ async destroySession(token: string): Promise {
+ await this.redis.del(this.sessionKey(token));
+ }
+
+ async renewSession(token: string): Promise {
+ // Renew by extending the expiration, if it exists
+ await this.redis.expire(this.sessionKey(token), 60 * 60 * 24 * 7); // 7 days expiration
+ }
+}
diff --git a/apps/node/src/adapters/services.ts b/apps/node/src/adapters/services.ts
new file mode 100644
index 00000000..6be696d0
--- /dev/null
+++ b/apps/node/src/adapters/services.ts
@@ -0,0 +1,40 @@
+import type { GitProviderFactory, ModelErrorClassifier, ReviewFormatter, ReviewGitProvider, ReviewModel } from '@codraoss/core/ports';
+import type { TokenTracker } from '@codraoss/core/token-tracker';
+import type { NodeAppBindings } from '../env';
+import { GitHubService } from '@codraoss/provider-github';
+import { isRetryableModelError, ModelRunner, nextChainIndexOf } from '@codraoss/models';
+import { FormatterService } from '@codraoss/core/formatter';
+import { getResolvedModelConfig } from '@codraoss/db/model-configs';
+
+export function makeGitHubFactory(env: NodeAppBindings) {
+ return (installationId: string, tracker: TokenTracker): ReviewGitProvider => new GitHubService(env, installationId, tracker);
+}
+
+export function makeModelFactory(env: NodeAppBindings) {
+ return (jobId: string, tracker: TokenTracker): ReviewModel => new ModelRunner({
+ kv: env.APP_KV as any,
+ secretStore: {
+ getSecret: async (key) => env[key as keyof NodeAppBindings] as string || process.env[key] || null,
+ },
+ getConfig: (modelId) => getResolvedModelConfig({ HYPERDRIVE: env.HYPERDRIVE, APP_KV: env.APP_KV }, modelId),
+ aiBinding: undefined,
+ tracker,
+ jobId,
+ });
+}
+
+export function makeFormatterFactory(env: NodeAppBindings) {
+ return (): ReviewFormatter => new FormatterService(env.APP_URL);
+}
+
+export function makeGitHubClientFactory(env: NodeAppBindings): GitProviderFactory {
+ return {
+ forInstallation(installationId: string): ReviewGitProvider {
+ return new GitHubService(env, installationId);
+ },
+ };
+}
+
+export function makeModelErrorClassifier(): ModelErrorClassifier {
+ return { isRetryableModelError, nextChainIndexOf };
+}
diff --git a/apps/node/src/adapters/telemetry.ts b/apps/node/src/adapters/telemetry.ts
new file mode 100644
index 00000000..9c1e28c3
--- /dev/null
+++ b/apps/node/src/adapters/telemetry.ts
@@ -0,0 +1,11 @@
+import type { TelemetrySink } from '@codraoss/core/ports';
+import type { NodeAppBindings } from '../env';
+
+export function makeTelemetrySink(_env: NodeAppBindings): TelemetrySink {
+ return {
+ send: async (_event) => {
+ // In a real setup this would batch and send to a telemetry endpoint
+ // For now, in Node open-source, telemetry can be safely stubbed or sent to logs
+ }
+ };
+}
diff --git a/apps/node/src/api-deps.ts b/apps/node/src/api-deps.ts
index 00d52bcd..930c5af2 100644
--- a/apps/node/src/api-deps.ts
+++ b/apps/node/src/api-deps.ts
@@ -1,6 +1,7 @@
import { createSharedApiDeps } from '@codraoss/api';
import type { NodeAppBindings } from './env';
import { logger } from '@codraoss/api/logger';
+import { createReviewRuntime } from './runtime';
export function createNodeApiDeps(env: NodeAppBindings) {
return createSharedApiDeps({
@@ -18,9 +19,7 @@ export function createNodeApiDeps(env: NodeAppBindings) {
scheduleBestEffortJobMaintenance: () => {
// In node, this is a long running process, we can just spawn a promise.
},
- createReviewRuntime: () => {
- throw new Error('Review runtime not implemented for Node yet.');
- },
+ createReviewRuntime: () => createReviewRuntime(env),
getOrFetchRawDiffForCompletedJob: async () => '',
logger,
getSecret: async (key) => process.env[key] ?? null,
diff --git a/apps/node/src/env.ts b/apps/node/src/env.ts
index 400d9741..4605dac7 100644
--- a/apps/node/src/env.ts
+++ b/apps/node/src/env.ts
@@ -1,8 +1,7 @@
-import type { SessionStore, IdentityProvider, KeyValueStore, QueueProducer, JobOrchestrator } from '@codraoss/core';
+import type { SessionStore, IdentityProvider, KeyValueStore, QueueProducer, JobOrchestrator } from '@codraoss/core/ports';
import type { ReviewJobMessage } from '@codraoss/schema';
export interface NodeAppBindings {
- // ── Platform stores (in-memory stubs for now) ──
SESSION_STORE: SessionStore;
IDENTITY_PROVIDER?: IdentityProvider;
APP_KV: KeyValueStore;
@@ -31,7 +30,7 @@ export function createNodeEnv(stubs: {
SESSION_STORE: SessionStore;
APP_KV: KeyValueStore;
REVIEW_QUEUE: QueueProducer;
- REVIEW_ORCHESTRATOR: JobOrchestrator;
+ REVIEW_ORCHESTRATOR?: JobOrchestrator; // Mark as optional
}): NodeAppBindings {
const requireEnv = (key: string) => {
const val = process.env[key];
@@ -41,6 +40,7 @@ export function createNodeEnv(stubs: {
return {
...stubs,
+ REVIEW_ORCHESTRATOR: stubs.REVIEW_ORCHESTRATOR!,
HYPERDRIVE: { connectionString: requireEnv('DATABASE_URL') },
APP_PRIVATE_KEY: requireEnv('APP_PRIVATE_KEY'),
GITHUB_APP_ID: requireEnv('GITHUB_APP_ID'),
diff --git a/apps/node/src/index.ts b/apps/node/src/index.ts
index c1dc488f..2590d44c 100644
--- a/apps/node/src/index.ts
+++ b/apps/node/src/index.ts
@@ -5,7 +5,6 @@ dotenv.config({ path: path.resolve(process.cwd(), '.dev.vars') }); // Root level
import { serve } from '@hono/node-server';
import { createApiRouter } from '@codraoss/api';
import { runWithDb } from '@codraoss/db/client';
-import { InMemoryOrchestrator, InMemorySessionStore } from '@codraoss/core/ports';
import { createNodeApiDeps } from './api-deps';
import { createNodeEnv } from './env';
import { logger } from '@codraoss/api/logger';
@@ -13,6 +12,10 @@ import Redis from 'ioredis';
import { RedisKVAdapter } from './adapters/redis-kv';
import { Queue } from 'bullmq';
import { RedisQueueAdapter } from './adapters/redis-queue';
+import { NodeOrchestrator } from './adapters/node-orchestrator';
+import { startWorker } from './worker';
+import { createReviewRuntime } from './runtime';
+import { RedisSessionStore } from './adapters/redis-session-store';
const redisUrl = process.env.REDIS_URL || 'redis://localhost:6379';
const redisClient = new Redis(redisUrl, { maxRetriesPerRequest: null }); // maxRetriesPerRequest: null is required for bullmq
@@ -23,13 +26,14 @@ redisClient.on('error', (err) => {
const reviewQueue = new Queue('codra-reviews', { connection: redisClient });
const stubs = {
- SESSION_STORE: new InMemorySessionStore(),
+ SESSION_STORE: new RedisSessionStore(redisClient),
APP_KV: new RedisKVAdapter(redisClient),
REVIEW_QUEUE: new RedisQueueAdapter(reviewQueue),
- REVIEW_ORCHESTRATOR: new InMemoryOrchestrator(),
+ REVIEW_ORCHESTRATOR: undefined, // Will be set to NodeOrchestrator below
};
const env = createNodeEnv(stubs);
+env.REVIEW_ORCHESTRATOR = new NodeOrchestrator(createReviewRuntime(env));
import fs from 'node:fs';
import { serveStatic } from '@hono/node-server/serve-static';
@@ -63,7 +67,13 @@ app.use('/*.svg', serveStatic({ root: process.cwd().endsWith('node') ? '../../di
app.use('/*.ico', serveStatic({ root: process.cwd().endsWith('node') ? '../../dist/client' : 'dist/client' }));
const port = parseInt(process.env.PORT || '3000', 10);
-serve({
+let worker: ReturnType | undefined;
+if (process.env.START_WORKER !== 'false') {
+ worker = startWorker(env, redisUrl);
+ logger.info('BullMQ Background Worker started.');
+}
+
+const server = serve({
fetch: async (request) => {
const apiEnv = {
...envWithAssets,
@@ -76,16 +86,17 @@ serve({
logger.info(`Codra Node server running on http://localhost:${info.port}`);
});
+const shutdown = async () => {
+ logger.info('Shutting down Codra Node server...');
+ if (worker) {
+ logger.info('Waiting for active BullMQ jobs to finish...');
+ await worker.close();
+ logger.info('BullMQ Worker closed gracefully.');
+ }
+ process.exit(0);
+};
-
-
-
-
-
-
-
-
-
-
+process.on('SIGTERM', shutdown);
+process.on('SIGINT', shutdown);
// Trigger restart for env vars
diff --git a/apps/node/src/runtime.ts b/apps/node/src/runtime.ts
new file mode 100644
index 00000000..e6e2b8c7
--- /dev/null
+++ b/apps/node/src/runtime.ts
@@ -0,0 +1,53 @@
+import type { ReviewRuntime } from '@codraoss/core/ports';
+import type { DbEnv } from '@codraoss/db/env';
+import { TokenTracker } from '@codraoss/core/token-tracker';
+import type { NodeAppBindings } from './env';
+
+// Adapters from @codraoss/db/repositories
+import { makeJobStore, makeFileReviewStore, makeLearningStore, makeModelConfigReader, makeReviewSettingsReader, makeWebhookDeliveryReader } from '@codraoss/db/repositories';
+
+// Config
+import { loadRepoConfig } from '@codraoss/api/platform';
+
+// Node-specific adapters
+import { cryptoIds, systemClock } from './adapters/platform';
+import { makeTelemetrySink } from './adapters/telemetry';
+import {
+ makeFormatterFactory,
+ makeGitHubClientFactory,
+ makeGitHubFactory,
+ makeModelErrorClassifier,
+ makeModelFactory,
+} from './adapters/services';
+
+export function createReviewRuntime(env: NodeAppBindings): ReviewRuntime & DbEnv {
+ const dbEnv = { HYPERDRIVE: env.HYPERDRIVE, APP_KV: env.APP_KV, workerMode: false };
+
+ return {
+ ...dbEnv,
+ kv: env.APP_KV,
+ clock: systemClock,
+ ids: cryptoIds,
+
+ botUsername: env.BOT_USERNAME,
+
+ jobs: makeJobStore(dbEnv),
+ fileReviews: makeFileReviewStore(dbEnv),
+ settings: makeReviewSettingsReader(dbEnv),
+ webhooks: makeWebhookDeliveryReader(dbEnv),
+ learning: makeLearningStore(dbEnv),
+ modelConfigs: makeModelConfigReader(dbEnv),
+ repoConfig: {
+ loadRepoConfig: (context) => loadRepoConfig(env.APP_KV, dbEnv, context)
+ },
+ telemetry: makeTelemetrySink(env),
+
+ createTokenTracker: () => new TokenTracker(),
+ createGitHub: makeGitHubFactory(env),
+ createModel: makeModelFactory(env),
+ createFormatter: makeFormatterFactory(env),
+
+ githubClients: makeGitHubClientFactory(env),
+ modelErrors: makeModelErrorClassifier(),
+ };
+}
diff --git a/apps/node/src/worker.ts b/apps/node/src/worker.ts
new file mode 100644
index 00000000..3da94dac
--- /dev/null
+++ b/apps/node/src/worker.ts
@@ -0,0 +1,37 @@
+import { Worker, type Job } from 'bullmq';
+import { reviewJobMessageSchema } from '@codraoss/schema';
+import { NodeOrchestrator } from './adapters/node-orchestrator';
+import { logger } from '@codraoss/api/logger';
+import type { NodeAppBindings } from './env';
+import Redis from 'ioredis';
+import { createReviewRuntime } from './runtime';
+
+export function startWorker(env: NodeAppBindings, redisUrl: string): Worker {
+ const connection = new Redis(redisUrl, { maxRetriesPerRequest: null });
+
+ const worker = new Worker(
+ 'codra-reviews',
+ async (job: Job) => {
+ const parseResult = reviewJobMessageSchema.safeParse(job.data);
+ if (!parseResult.success) {
+ logger.error(`[Worker] Invalid job payload for job ${job.id}`, parseResult.error);
+ throw new Error('Invalid job payload');
+ }
+
+ const reviewRuntime = createReviewRuntime(env);
+ const orchestrator = new NodeOrchestrator(reviewRuntime);
+ await orchestrator.startReviewJob(job.id ?? 'unknown', parseResult.data);
+ },
+ { connection }
+ );
+
+ worker.on('completed', (job) => {
+ logger.info(`[Worker] Job ${job.id} completed successfully`);
+ });
+
+ worker.on('failed', (job, err) => {
+ logger.error(`[Worker] Job ${job?.id} failed`, err);
+ });
+
+ return worker;
+}
diff --git a/package-lock.json b/package-lock.json
index 9b2b88d9..b88d9a71 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -28,6 +28,7 @@
"lenis": "^1.3.26",
"lucide-react": "^1.8.0",
"motion": "^12.42.2",
+ "nanoid": "^6.0.1",
"postgres": "^3.4.9",
"react": "^19.2.8",
"react-dom": "^19.2.8",
@@ -8505,10 +8506,9 @@
}
},
"node_modules/nanoid": {
- "version": "3.3.18",
- "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.18.tgz",
- "integrity": "sha512-DTg4MJbGMWkfi6VZFdNt2/caMbQy4Ou+Op/hJQvGEWcnVfoA1QA+xzRKAzw9jD6+GVOOeYr/mIcuDSdug6F6+w==",
- "dev": true,
+ "version": "6.0.1",
+ "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-6.0.1.tgz",
+ "integrity": "sha512-3wVS3i51pE2pi1k5FFL/95BGfVS0kSsvDVuGXHOtxox/TywUmtgq+3qiTOTbs9J7KfHaXPiN171k/A6dBnaXFw==",
"funding": [
{
"type": "github",
@@ -8517,10 +8517,10 @@
],
"license": "MIT",
"bin": {
- "nanoid": "bin/nanoid.cjs"
+ "nanoid": "bin/nanoid.js"
},
"engines": {
- "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1"
+ "node": "^22 || ^24 || >=26"
}
},
"node_modules/napi-postinstall": {
@@ -8910,6 +8910,25 @@
}
}
},
+ "node_modules/postcss/node_modules/nanoid": {
+ "version": "3.3.19",
+ "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.19.tgz",
+ "integrity": "sha512-Y2tUNy4ouw6tq5oDSKeQYGOyhkUBhNOcGV/02KC+6kd9eDGqdZd++mjMiIDilrBYvjEnCYvVtsuHCuP+okSfug==",
+ "dev": true,
+ "funding": [
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/ai"
+ }
+ ],
+ "license": "MIT",
+ "bin": {
+ "nanoid": "bin/nanoid.cjs"
+ },
+ "engines": {
+ "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1"
+ }
+ },
"node_modules/postgres": {
"version": "3.4.9",
"license": "Unlicense",
diff --git a/package.json b/package.json
index 66883cfa..0c7ea2b6 100644
--- a/package.json
+++ b/package.json
@@ -88,6 +88,7 @@
"lenis": "^1.3.26",
"lucide-react": "^1.8.0",
"motion": "^12.42.2",
+ "nanoid": "^6.0.1",
"postgres": "^3.4.9",
"react": "^19.2.8",
"react-dom": "^19.2.8",
From 42d02f03a66c13e13262f5e46087047ee688ba9d Mon Sep 17 00:00:00 2001
From: Devarshi Shimpi
Date: Tue, 22 Sep 2026 02:51:41 +0530
Subject: [PATCH 02/16] feat: add Docker support and self-hosting documentation
---
README.md | 6 ++-
apps/node/Dockerfile | 43 +++++++++++++++++++
apps/node/src/index.ts | 28 +++++++------
docker-compose.yml | 53 +++++++++++++++++++++++
docs/deployment/docker.md | 88 +++++++++++++++++++++++++++++++++++++++
5 files changed, 204 insertions(+), 14 deletions(-)
create mode 100644 apps/node/Dockerfile
create mode 100644 docker-compose.yml
create mode 100644 docs/deployment/docker.md
diff --git a/README.md b/README.md
index 201c692a..a0cd1a53 100644
--- a/README.md
+++ b/README.md
@@ -19,7 +19,9 @@
|
Docs
|
- Installation
+ Installation (Cloudflare)
+ |
+ Installation (Docker / Self-Hosted)
|
Issues
|
@@ -35,7 +37,7 @@ Codra listens to GitHub pull request events, runs AI-powered review jobs, posts
## Why Codra
-- **Own the whole review loop**: Run the GitHub App, Cloudflare Worker, queue, database, model credentials, and dashboard under your own control.
+- **Own the whole review loop**: Run the GitHub App, web server, queue, database, model credentials, and dashboard under your own control (deploy on Cloudflare Workers or your own VPS via Docker).
- **Review with repository context**: Codra checks pull request diffs for correctness, security, performance, maintainability, and repo-specific patterns.
- **Configure each repository**: Tune triggers, skipped paths, draft handling, mention reviews, labels, custom rules, and review budgets from the dashboard.
- **Route models deliberately**: Use global defaults, per-repo model chains, fallbacks, and size-based overrides for larger pull requests.
diff --git a/apps/node/Dockerfile b/apps/node/Dockerfile
new file mode 100644
index 00000000..8f234223
--- /dev/null
+++ b/apps/node/Dockerfile
@@ -0,0 +1,43 @@
+FROM node:20-alpine AS builder
+WORKDIR /app
+
+# Install build dependencies if needed
+RUN apk add --no-cache python3 make g++
+
+# Copy workspace and lock file
+COPY package.json package-lock.json tsconfig.base.json ./
+COPY apps/node/package.json ./apps/node/
+COPY packages/api/package.json ./packages/api/
+COPY packages/core/package.json ./packages/core/
+COPY packages/db/package.json ./packages/db/
+COPY packages/models/package.json ./packages/models/
+COPY packages/provider-github/package.json ./packages/provider-github/
+COPY packages/schema/package.json ./packages/schema/
+
+# Install all dependencies (with devDependencies for build)
+RUN npm ci
+
+# Copy source code
+COPY apps/node ./apps/node
+COPY packages ./packages
+
+# Build the node server and its dependencies
+RUN npm run build --workspace=@codraoss/node-server
+
+# Build runner stage
+FROM node:20-alpine AS runner
+WORKDIR /app
+
+ENV NODE_ENV=production
+
+# Copy built artifacts and necessary files
+COPY --from=builder /app/node_modules ./node_modules
+COPY --from=builder /app/apps/node/dist ./apps/node/dist
+COPY --from=builder /app/apps/node/package.json ./apps/node/package.json
+
+# Copy packages that the node app might need at runtime
+COPY --from=builder /app/packages ./packages
+
+EXPOSE 3000
+
+CMD ["node", "apps/node/dist/index.js"]
diff --git a/apps/node/src/index.ts b/apps/node/src/index.ts
index 2590d44c..fe54fd6b 100644
--- a/apps/node/src/index.ts
+++ b/apps/node/src/index.ts
@@ -73,18 +73,22 @@ if (process.env.START_WORKER !== 'false') {
logger.info('BullMQ Background Worker started.');
}
-const server = serve({
- fetch: async (request) => {
- const apiEnv = {
- ...envWithAssets,
- deps: createNodeApiDeps(env),
- };
- try { return await runWithDb(env, () => app.fetch(request, apiEnv as any)); } catch (e) { console.error('SERVE ERROR:', e); throw e; }
- },
- port,
-}, (info) => {
- logger.info(`Codra Node server running on http://localhost:${info.port}`);
-});
+if (process.env.START_API !== 'false') {
+ const server = serve({
+ fetch: async (request) => {
+ const apiEnv = {
+ ...envWithAssets,
+ deps: createNodeApiDeps(env),
+ };
+ try { return await runWithDb(env, () => app.fetch(request, apiEnv as any)); } catch (e) { console.error('SERVE ERROR:', e); throw e; }
+ },
+ port,
+ }, (info) => {
+ logger.info(`Codra Node server running on http://localhost:${info.port}`);
+ });
+} else {
+ logger.info('API Server disabled via START_API=false');
+}
const shutdown = async () => {
logger.info('Shutting down Codra Node server...');
diff --git a/docker-compose.yml b/docker-compose.yml
new file mode 100644
index 00000000..32ce5b0b
--- /dev/null
+++ b/docker-compose.yml
@@ -0,0 +1,53 @@
+version: '3.8'
+
+services:
+ postgres:
+ image: postgres:15-alpine
+ environment:
+ POSTGRES_USER: postgres
+ POSTGRES_PASSWORD: password
+ POSTGRES_DB: codra
+ ports:
+ - "5432:5432"
+ volumes:
+ - postgres_data:/var/lib/postgresql/data
+ healthcheck:
+ test: ["CMD-SHELL", "pg_isready -U postgres"]
+ interval: 5s
+ timeout: 5s
+ retries: 5
+
+ redis:
+ image: redis:7-alpine
+ ports:
+ - "6379:6379"
+ volumes:
+ - redis_data:/data
+ healthcheck:
+ test: ["CMD", "redis-cli", "ping"]
+ interval: 5s
+ timeout: 5s
+ retries: 5
+
+ codra-app:
+ build:
+ context: .
+ dockerfile: apps/node/Dockerfile
+ ports:
+ - "3000:3000"
+ environment:
+ - DATABASE_URL=postgres://postgres:password@postgres:5432/codra
+ - REDIS_URL=redis://redis:6379
+ - START_WORKER=true
+ - PORT=3000
+ env_file:
+ - .env
+ depends_on:
+ postgres:
+ condition: service_healthy
+ redis:
+ condition: service_healthy
+
+volumes:
+ postgres_data:
+ redis_data:
diff --git a/docs/deployment/docker.md b/docs/deployment/docker.md
new file mode 100644
index 00000000..edc0c922
--- /dev/null
+++ b/docs/deployment/docker.md
@@ -0,0 +1,88 @@
+# Self-Hosting with Docker
+
+While Codra is natively optimized for Cloudflare Workers, you can easily self-host the entire architecture on a dedicated server (like a VPS or EC2 instance) using Docker. This setup replaces Cloudflare infrastructure with standard open-source equivalents:
+
+* **Node.js** (Web Server and Job Runner)
+* **PostgreSQL** (Database)
+* **Redis** (Key-Value Store and Queues via BullMQ)
+
+## Prerequisites
+
+Before deploying, ensure your server has the following installed:
+- [Docker](https://docs.docker.com/get-docker/)
+- [Docker Compose](https://docs.docker.com/compose/install/)
+
+You will also need:
+- A GitHub App configured for your organization (See [GitHub App Setup](../setup/github-app.md)). You will need the **App ID**, **Client ID**, **Client Secret**, **Webhook Secret**, and **Private Key**.
+- An API Key for your chosen LLM provider (e.g., Anthropic, OpenAI, or Google).
+
+## Environment Setup
+
+Create a `.env` file in the root of the cloned repository. This file handles all your secrets.
+
+```env
+# Server Configuration
+APP_URL=https://codra.yourdomain.com
+ENVIRONMENT=production
+
+# Database & Redis (these map to the docker-compose.yml service names)
+DATABASE_URL=postgres://postgres:password@postgres:5432/codra
+REDIS_URL=redis://redis:6379
+
+# GitHub App Secrets
+GITHUB_APP_ID=your_app_id
+GITHUB_CLIENT_ID=your_client_id
+GITHUB_CLIENT_SECRET=your_client_secret
+GITHUB_APP_WEBHOOK_SECRET=your_webhook_secret
+APP_PRIVATE_KEY="-----BEGIN RSA PRIVATE KEY-----\n...\n-----END RSA PRIVATE KEY-----"
+
+# Application Settings
+AUTH_CALLBACK_URL=https://codra.yourdomain.com/api/auth/callback
+DASHBOARD_ALLOWED_USERS=your_github_username
+BOT_USERNAME=your-github-app-slug[bot]
+
+# Encryption Key (Must be 32 random characters for AES-256)
+LLM_CONFIG_ENCRYPTION_KEY=generate_a_random_32_char_string
+```
+
+## Running the Stack
+
+Once your `.env` is prepared, deploying is a single command. From the root of the repository, run:
+
+```bash
+docker compose up -d --build
+```
+
+This command will:
+1. Compile the Codra Node app and its workspace dependencies.
+2. Boot Postgres and Redis containers.
+3. Start the Codra Node application container (which runs both the HTTP server and the background worker by default).
+
+To view logs:
+```bash
+docker compose logs -f codra-app
+```
+
+The application should now be accessible at `http://localhost:3000` (or whatever `PORT` you configured).
+
+## Advanced Configuration: Scaling (Unified Process Model)
+
+By default, the `codra-app` service boots *both* the web server (Hono API) and the background worker (BullMQ) in a single Node process.
+
+For high-traffic environments, you may want to scale the API web nodes independently of the heavy AI review worker nodes.
+
+You can split these by overriding the `START_WORKER` and `START_API` environment variables across different containers.
+
+**API Node:**
+```env
+START_WORKER=false
+# START_API=true (Default)
+```
+
+**Worker Node:**
+```env
+START_WORKER=true
+START_API=false # Disables the HTTP server
+```
+
+This allows you to spin up multiple worker containers listening to Redis while load-balancing incoming HTTP requests to your API nodes.
From b3c0f70872f8afb662a59f0ae0b3823b29eb1825 Mon Sep 17 00:00:00 2001
From: Devarshi Shimpi
Date: Tue, 22 Sep 2026 20:12:40 +0530
Subject: [PATCH 03/16] feat: integrate BullMQ across node app with improved
docker configuration
---
apps/node/Dockerfile | 27 +++++++++++--
apps/node/src/adapters/node-orchestrator.ts | 42 ++++++++++-----------
apps/node/src/adapters/services.ts | 2 +-
apps/node/src/api-deps.ts | 16 ++++++--
apps/node/src/env.ts | 4 +-
apps/node/src/index.ts | 29 ++++----------
apps/node/src/runtime.ts | 2 +-
apps/node/src/worker.ts | 7 ++--
docker-compose.yml | 6 +++
9 files changed, 79 insertions(+), 56 deletions(-)
diff --git a/apps/node/Dockerfile b/apps/node/Dockerfile
index 8f234223..537bfc19 100644
--- a/apps/node/Dockerfile
+++ b/apps/node/Dockerfile
@@ -32,12 +32,33 @@ ENV NODE_ENV=production
# Copy built artifacts and necessary files
COPY --from=builder /app/node_modules ./node_modules
-COPY --from=builder /app/apps/node/dist ./apps/node/dist
+
COPY --from=builder /app/apps/node/package.json ./apps/node/package.json
+COPY --from=builder /app/apps/node/dist ./apps/node/dist
+
+# Selectively copy only workspace packages' dist folders and package.json files
+COPY --from=builder /app/packages/api/package.json ./packages/api/
+COPY --from=builder /app/packages/api/dist ./packages/api/dist
+
+COPY --from=builder /app/packages/core/package.json ./packages/core/
+COPY --from=builder /app/packages/core/dist ./packages/core/dist
-# Copy packages that the node app might need at runtime
-COPY --from=builder /app/packages ./packages
+COPY --from=builder /app/packages/db/package.json ./packages/db/
+COPY --from=builder /app/packages/db/dist ./packages/db/dist
+
+COPY --from=builder /app/packages/models/package.json ./packages/models/
+COPY --from=builder /app/packages/models/dist ./packages/models/dist
+
+COPY --from=builder /app/packages/provider-github/package.json ./packages/provider-github/
+COPY --from=builder /app/packages/provider-github/dist ./packages/provider-github/dist
+
+COPY --from=builder /app/packages/schema/package.json ./packages/schema/
+COPY --from=builder /app/packages/schema/dist ./packages/schema/dist
+
+USER node
EXPOSE 3000
+HEALTHCHECK --interval=30s --timeout=3s CMD wget -qO- http://localhost:3000/health || exit 1
+
CMD ["node", "apps/node/dist/index.js"]
diff --git a/apps/node/src/adapters/node-orchestrator.ts b/apps/node/src/adapters/node-orchestrator.ts
index 32fe8f4c..28c1080a 100644
--- a/apps/node/src/adapters/node-orchestrator.ts
+++ b/apps/node/src/adapters/node-orchestrator.ts
@@ -1,37 +1,35 @@
-import type { JobOrchestrator, ReviewRuntime } from '@codraoss/core';
+import type { JobOrchestrator, QueueProducer, ReviewRuntime } from '@codraoss/core';
import type { ReviewJobMessage } from '@codraoss/schema';
import { runReview } from '@codraoss/core';
import { runWithDb } from '@codraoss/db/client';
import type { DbEnv } from '@codraoss/db/env';
-import { setTimeout } from 'node:timers/promises';
export class NodeOrchestrator implements JobOrchestrator {
- constructor(private readonly env: ReviewRuntime & DbEnv) {}
+ constructor(
+ private readonly env: ReviewRuntime & DbEnv,
+ private readonly queue: QueueProducer
+ ) {}
async startReviewJob(id: string, params: ReviewJobMessage): Promise {
return runWithDb(this.env, async () => {
- let currentParams = { ...params };
- let phase = currentParams.phase ?? 'prepare';
+ const currentParams = { ...params };
+ currentParams.phase = currentParams.phase ?? 'prepare';
- while (phase) {
- currentParams.phase = phase;
- const result = await runReview(this.env, currentParams);
+ const result = await runReview(this.env, currentParams);
- if (result.action === 'next_phase') {
- phase = result.phase;
- if (result.jobId) {
- currentParams.jobId = result.jobId;
- }
- if (result.delaySeconds > 0) {
- await setTimeout(result.delaySeconds * 1000);
- }
- } else if (result.action === 'retry') {
- if (result.delaySeconds > 0) {
- await setTimeout(result.delaySeconds * 1000);
- }
- } else if (result.action === 'ack') {
- break;
+ if (result.action === 'next_phase') {
+ const nextParams: ReviewJobMessage = {
+ ...currentParams,
+ phase: result.phase,
+ };
+ if (result.jobId) {
+ nextParams.jobId = result.jobId;
}
+ await this.queue.send(nextParams, { delaySeconds: result.delaySeconds });
+ } else if (result.action === 'retry') {
+ await this.queue.send(currentParams, { delaySeconds: result.delaySeconds });
+ } else if (result.action === 'ack') {
+ // Job is done, nothing to enqueue
}
});
}
diff --git a/apps/node/src/adapters/services.ts b/apps/node/src/adapters/services.ts
index 6be696d0..5b36b2ba 100644
--- a/apps/node/src/adapters/services.ts
+++ b/apps/node/src/adapters/services.ts
@@ -16,7 +16,7 @@ export function makeModelFactory(env: NodeAppBindings) {
secretStore: {
getSecret: async (key) => env[key as keyof NodeAppBindings] as string || process.env[key] || null,
},
- getConfig: (modelId) => getResolvedModelConfig({ HYPERDRIVE: env.HYPERDRIVE, APP_KV: env.APP_KV }, modelId),
+ getConfig: (modelId) => getResolvedModelConfig({ HYPERDRIVE: env.DATABASE_CONFIG, APP_KV: env.APP_KV }, modelId),
aiBinding: undefined,
tracker,
jobId,
diff --git a/apps/node/src/api-deps.ts b/apps/node/src/api-deps.ts
index 930c5af2..537e4568 100644
--- a/apps/node/src/api-deps.ts
+++ b/apps/node/src/api-deps.ts
@@ -2,19 +2,29 @@ import { createSharedApiDeps } from '@codraoss/api';
import type { NodeAppBindings } from './env';
import { logger } from '@codraoss/api/logger';
import { createReviewRuntime } from './runtime';
+import { Queue } from 'bullmq';
+import Redis from 'ioredis';
export function createNodeApiDeps(env: NodeAppBindings) {
return createSharedApiDeps({
sessionStore: env.SESSION_STORE,
kv: env.APP_KV,
- db: { HYPERDRIVE: env.HYPERDRIVE, APP_KV: env.APP_KV, workerMode: false },
+ db: { HYPERDRIVE: env.DATABASE_CONFIG, APP_KV: env.APP_KV, workerMode: false },
identityProvider: env.IDENTITY_PROVIDER,
enqueueReviewJob: async (input) => {
await env.REVIEW_QUEUE.send(input);
},
- terminateJobWorkflow: async (_job) => {
- logger.warn('[STUB] terminateJobWorkflow called');
+ terminateJobWorkflow: async (job) => {
+ const workerQueue = new Queue('codra-reviews', { connection: new Redis(process.env.REDIS_URL || 'redis://localhost:6379') });
+ const bullMqJob = await workerQueue.getJob(job.id);
+ if (bullMqJob) {
+ await bullMqJob.remove();
+ logger.info(`[API Deps] Terminated job workflow for job ${job.id}`);
+ } else {
+ logger.warn(`[API Deps] Attempted to terminate non-existent or completed job ${job.id}`);
+ }
+ await workerQueue.close();
},
scheduleBestEffortJobMaintenance: () => {
// In node, this is a long running process, we can just spawn a promise.
diff --git a/apps/node/src/env.ts b/apps/node/src/env.ts
index 4605dac7..302cf134 100644
--- a/apps/node/src/env.ts
+++ b/apps/node/src/env.ts
@@ -9,7 +9,7 @@ export interface NodeAppBindings {
REVIEW_ORCHESTRATOR: JobOrchestrator;
// ── Database ──
- HYPERDRIVE: { connectionString: string };
+ DATABASE_CONFIG: { connectionString: string };
// ── Environment strings (loaded from process.env via dotenv) ──
APP_PRIVATE_KEY: string;
@@ -41,7 +41,7 @@ export function createNodeEnv(stubs: {
return {
...stubs,
REVIEW_ORCHESTRATOR: stubs.REVIEW_ORCHESTRATOR!,
- HYPERDRIVE: { connectionString: requireEnv('DATABASE_URL') },
+ DATABASE_CONFIG: { connectionString: requireEnv('DATABASE_URL') },
APP_PRIVATE_KEY: requireEnv('APP_PRIVATE_KEY'),
GITHUB_APP_ID: requireEnv('GITHUB_APP_ID'),
GITHUB_APP_SLUG: process.env.GITHUB_APP_SLUG,
diff --git a/apps/node/src/index.ts b/apps/node/src/index.ts
index fe54fd6b..7f0b3e60 100644
--- a/apps/node/src/index.ts
+++ b/apps/node/src/index.ts
@@ -33,30 +33,13 @@ const stubs = {
};
const env = createNodeEnv(stubs);
-env.REVIEW_ORCHESTRATOR = new NodeOrchestrator(createReviewRuntime(env));
+env.REVIEW_ORCHESTRATOR = new NodeOrchestrator(createReviewRuntime(env), stubs.REVIEW_QUEUE);
import fs from 'node:fs';
import { serveStatic } from '@hono/node-server/serve-static';
const dashboardDist = path.resolve(process.cwd(), process.cwd().endsWith('node') ? '../../dist/client' : 'dist/client');
-const envWithAssets = {
- ...env,
- ASSETS: {
- fetch: async (_req: Request) => {
- try {
- console.log('fetching index.html from', path.join(dashboardDist, 'index.html'));
- const html = fs.readFileSync(path.join(dashboardDist, 'index.html'), 'utf-8');
- console.log('html length:', html.length);
- return new Response(html, { headers: { 'content-type': 'text/html' } });
- } catch (e) {
- console.error('ASSETS error:', e);
- return new Response('Dashboard build not found. Run npm run build -w @codraoss/dashboard', { status: 404 });
- }
- }
- }
-};
-
const app = createApiRouter();
app.onError((err, c) => {
console.error('HONO ERROR:', err);
@@ -65,22 +48,26 @@ app.onError((err, c) => {
app.use('/assets/*', serveStatic({ root: process.cwd().endsWith('node') ? '../../dist/client' : 'dist/client' }));
app.use('/*.svg', serveStatic({ root: process.cwd().endsWith('node') ? '../../dist/client' : 'dist/client' }));
app.use('/*.ico', serveStatic({ root: process.cwd().endsWith('node') ? '../../dist/client' : 'dist/client' }));
+app.get('*', serveStatic({ root: process.cwd().endsWith('node') ? '../../dist/client' : 'dist/client', path: 'index.html' }));
+
const port = parseInt(process.env.PORT || '3000', 10);
let worker: ReturnType | undefined;
if (process.env.START_WORKER !== 'false') {
- worker = startWorker(env, redisUrl);
+ worker = startWorker(env, redisUrl, stubs.REVIEW_QUEUE);
logger.info('BullMQ Background Worker started.');
}
if (process.env.START_API !== 'false') {
+ app.get('/health', (c) => c.text('OK'));
+
const server = serve({
fetch: async (request) => {
const apiEnv = {
- ...envWithAssets,
+ ...env,
deps: createNodeApiDeps(env),
};
- try { return await runWithDb(env, () => app.fetch(request, apiEnv as any)); } catch (e) { console.error('SERVE ERROR:', e); throw e; }
+ try { return await runWithDb({ ...env, HYPERDRIVE: env.DATABASE_CONFIG }, () => app.fetch(request, apiEnv as any)); } catch (e) { console.error('SERVE ERROR:', e); throw e; }
},
port,
}, (info) => {
diff --git a/apps/node/src/runtime.ts b/apps/node/src/runtime.ts
index e6e2b8c7..935e74b5 100644
--- a/apps/node/src/runtime.ts
+++ b/apps/node/src/runtime.ts
@@ -21,7 +21,7 @@ import {
} from './adapters/services';
export function createReviewRuntime(env: NodeAppBindings): ReviewRuntime & DbEnv {
- const dbEnv = { HYPERDRIVE: env.HYPERDRIVE, APP_KV: env.APP_KV, workerMode: false };
+ const dbEnv = { HYPERDRIVE: env.DATABASE_CONFIG, APP_KV: env.APP_KV, workerMode: false };
return {
...dbEnv,
diff --git a/apps/node/src/worker.ts b/apps/node/src/worker.ts
index 3da94dac..3e3bebf4 100644
--- a/apps/node/src/worker.ts
+++ b/apps/node/src/worker.ts
@@ -1,12 +1,13 @@
import { Worker, type Job } from 'bullmq';
-import { reviewJobMessageSchema } from '@codraoss/schema';
+import { reviewJobMessageSchema, type ReviewJobMessage } from '@codraoss/schema';
import { NodeOrchestrator } from './adapters/node-orchestrator';
import { logger } from '@codraoss/api/logger';
import type { NodeAppBindings } from './env';
import Redis from 'ioredis';
import { createReviewRuntime } from './runtime';
+import type { QueueProducer } from '@codraoss/core/ports';
-export function startWorker(env: NodeAppBindings, redisUrl: string): Worker {
+export function startWorker(env: NodeAppBindings, redisUrl: string, queue: QueueProducer): Worker {
const connection = new Redis(redisUrl, { maxRetriesPerRequest: null });
const worker = new Worker(
@@ -19,7 +20,7 @@ export function startWorker(env: NodeAppBindings, redisUrl: string): Worker {
}
const reviewRuntime = createReviewRuntime(env);
- const orchestrator = new NodeOrchestrator(reviewRuntime);
+ const orchestrator = new NodeOrchestrator(reviewRuntime, queue);
await orchestrator.startReviewJob(job.id ?? 'unknown', parseResult.data);
},
{ connection }
diff --git a/docker-compose.yml b/docker-compose.yml
index 32ce5b0b..430cb958 100644
--- a/docker-compose.yml
+++ b/docker-compose.yml
@@ -47,6 +47,12 @@ services:
condition: service_healthy
redis:
condition: service_healthy
+ stop_grace_period: 2m
+ healthcheck:
+ test: ["CMD-SHELL", "wget -qO- http://localhost:3000/health || exit 1"]
+ interval: 30s
+ timeout: 3s
+ retries: 3
volumes:
postgres_data:
From 22533151abcb98a2b1277be229f58f0d7c9f16c8 Mon Sep 17 00:00:00 2001
From: Devarshi Shimpi
Date: Tue, 22 Sep 2026 22:53:07 +0530
Subject: [PATCH 04/16] refactor: extract node adapters to
@codraoss/node-adapters package
---
.changeset/README.md | 33 --
.changeset/config.json | 21 -
CHANGELOG.md | 81 ---
README.md | 3 +-
apps/node/package.json | 3 +-
apps/node/src/adapters/redis-queue.ts | 14 -
apps/node/src/api-deps.ts | 11 +-
apps/node/src/index.ts | 82 ++-
apps/node/src/runtime.ts | 2 +-
apps/worker/package.json | 2 +-
package-lock.json | 530 +++---------------
package.json | 5 +-
packages/api/CHANGELOG.md | 23 -
packages/api/package.json | 51 +-
packages/core/CHANGELOG.md | 9 -
packages/core/package.json | 4 +-
packages/core/src/ports/queue.ts | 1 +
packages/db/CHANGELOG.md | 11 -
packages/db/package.json | 6 +-
packages/db/src/client.ts | 8 +-
packages/models/CHANGELOG.md | 16 -
packages/models/package.json | 6 +-
packages/node-adapters/package.json | 58 ++
packages/node-adapters/src/index.ts | 6 +
.../node-adapters/src}/node-orchestrator.ts | 0
.../node-adapters/src}/platform.ts | 7 +-
.../node-adapters/src}/redis-kv.ts | 0
packages/node-adapters/src/redis-queue.ts | 22 +
.../node-adapters/src}/redis-session-store.ts | 7 +-
.../node-adapters}/src/worker.ts | 24 +-
packages/node-adapters/tsconfig.json | 10 +
packages/node-adapters/tsup.config.json | 10 +
packages/provider-github/CHANGELOG.md | 10 -
packages/provider-github/package.json | 6 +-
packages/schema/CHANGELOG.md | 7 -
packages/schema/package.json | 2 +-
packages/ui/CHANGELOG.md | 9 -
packages/ui/package.json | 4 +-
scripts/swap-publish-exports.mjs | 1 +
39 files changed, 320 insertions(+), 785 deletions(-)
delete mode 100644 .changeset/README.md
delete mode 100644 .changeset/config.json
delete mode 100644 CHANGELOG.md
delete mode 100644 apps/node/src/adapters/redis-queue.ts
delete mode 100644 packages/api/CHANGELOG.md
delete mode 100644 packages/core/CHANGELOG.md
delete mode 100644 packages/db/CHANGELOG.md
delete mode 100644 packages/models/CHANGELOG.md
create mode 100644 packages/node-adapters/package.json
create mode 100644 packages/node-adapters/src/index.ts
rename {apps/node/src/adapters => packages/node-adapters/src}/node-orchestrator.ts (100%)
rename {apps/node/src/adapters => packages/node-adapters/src}/platform.ts (51%)
rename {apps/node/src/adapters => packages/node-adapters/src}/redis-kv.ts (100%)
create mode 100644 packages/node-adapters/src/redis-queue.ts
rename {apps/node/src/adapters => packages/node-adapters/src}/redis-session-store.ts (87%)
rename {apps/node => packages/node-adapters}/src/worker.ts (57%)
create mode 100644 packages/node-adapters/tsconfig.json
create mode 100644 packages/node-adapters/tsup.config.json
delete mode 100644 packages/provider-github/CHANGELOG.md
delete mode 100644 packages/schema/CHANGELOG.md
delete mode 100644 packages/ui/CHANGELOG.md
diff --git a/.changeset/README.md b/.changeset/README.md
deleted file mode 100644
index 697e6f70..00000000
--- a/.changeset/README.md
+++ /dev/null
@@ -1,33 +0,0 @@
-# Changesets
-
-This folder is managed by [Changesets](https://github.com/changesets/changesets), used here only for
-**local, manual** versioning of the public `@codraoss/*` packages. There is no CI-based publishing.
-
-The seven publishable packages (`schema`, `core`, `db`, `models`, `provider-github`, `api`, `ui`)
-are a **fixed group** — they version and release in lockstep (currently `0.9.4`). The worker app
-(`@codraoss/worker`) is private and never published.
-
-## Recording a change
-
-```bash
-npx changeset # pick the bump, write a summary; commit the generated file
-```
-
-## Cutting a release (run locally, then publish by hand)
-
-```bash
-npm run version:packages # applies pending changesets: bumps all @codraoss/* in lockstep + changelog
-npm run release # builds dist and runs `changeset publish` for you
-```
-
-`npm run release` builds every package to `dist/` and publishes. Publishing is also possible per
-package with plain npm — the `prepack` hook rewrites `exports` to the compiled `dist/` paths in the
-tarball automatically:
-
-```bash
-npm run build:packages
-npm publish -w @codraoss/schema # ...repeat bottom-up: schema → core → db/models/provider-github → api → ui
-```
-
-You must be logged in to npm (`npm whoami`) and own the `@codraoss` scope. First publish of each
-package needs public access, which `publishConfig.access` already sets.
diff --git a/.changeset/config.json b/.changeset/config.json
deleted file mode 100644
index eec496e2..00000000
--- a/.changeset/config.json
+++ /dev/null
@@ -1,21 +0,0 @@
-{
- "$schema": "https://unpkg.com/@changesets/config@3.1.1/schema.json",
- "changelog": "@changesets/cli/changelog",
- "commit": false,
- "fixed": [
- [
- "@codraoss/schema",
- "@codraoss/core",
- "@codraoss/db",
- "@codraoss/models",
- "@codraoss/provider-github",
- "@codraoss/api",
- "@codraoss/ui"
- ]
- ],
- "linked": [],
- "access": "public",
- "baseBranch": "main",
- "updateInternalDependencies": "patch",
- "ignore": ["@codraoss/worker"]
-}
diff --git a/CHANGELOG.md b/CHANGELOG.md
deleted file mode 100644
index 18d490c8..00000000
--- a/CHANGELOG.md
+++ /dev/null
@@ -1,81 +0,0 @@
-# Changelog
-
-## v0.9.5
-
-### What's New
-
-- **Monorepo & Public npm Packages:** Codra is now an npm workspace monorepo, with the review engine, model adapters, GitHub provider, API router, and design system published under `@codraoss/*`.
-- **Evidence-Grounded Findings:** Findings must quote the diff they claim to describe; candidates that can't ground themselves are dropped before posting.
-- **Precision Gates & Gatekeeper Verifier:** A claim-type denylist, a dedicated verifier pass, and disposition tracking for degraded reviews.
-- **Batched Reviews & New Providers:** Files are packed into bins with structured Gemini output; Vertex AI, NVIDIA, and xAI joined the model catalog.
-- **Language Personas & Secondary Reviewer:** Configurable per-language personas and an optional second reviewer pass.
-- **Clean-Pass Summaries:** A review that finds nothing now posts a real summary and reacts with a thumbs-up instead of an empty comment.
-- **Job Detail & Stats Overhaul:** Rebuilt views with new chart primitives and bucketed trends.
-
-### Bug Fixes
-
-- Fixed `GET /api/jobs/:id` returning 503s while polling — Cloudflare's edge rewrites strong ETags to weak ones, so the 304 path never matched.
-- Dropped an invalid `propertyOrdering` keyword from Gemini response grammars that was silently disabling constrained decoding on every Google review.
-- Fixed issue-accuracy and "files reviewed" reporting, telemetry/repo settings UI, and CI dependency install failures.
-
-**Full Changelog**: https://github.com/devarshishimpi/codra/compare/v0.9.4...v0.9.5
-
-## v0.9.4
-
-### What's New
-
-- **Job Cancellation & Deletion:** Review jobs can now be cancelled and deleted directly, with improved job status handling.
-- **Telemetry Opt-Out:** Anonymous telemetry now ships with a clear opt-out and support for overriding the telemetry secret.
-- **Concurrency Controls:** Model calls now respect configurable concurrency limits, with enhanced timeout handling to keep reviews from stalling.
-- **Custom File Matchers:** Diff parsing and the review flow were refactored to support custom file matchers.
-- **Review Performance Settings:** New settings and UI for tuning review performance.
-- **Motion UI:** Smooth scrolling (Lenis) and new motion-based sidebar navigation, tabs, and select components.
-- **New Installs Experience:** Improved UI and skeleton loaders for new installs.
-
-### Improvements
-
-- Added in-memory token caching for GitHub requests to reduce redundant API calls.
-- Job continuation tracking added so long-running reviews resume more reliably under concurrency limits.
-- Improved handling of subrequest budget limits during review job processing.
-- Enhanced review job concurrency handling and caching mechanisms.
-- Improved model service caching, timeout handling, and review settings API, with added tests for concurrency limits.
-- Enhanced CI configuration, select component accessibility, and optimized stats queries.
-- Refactored stats page and model configurations.
-- Removed dead letter queue (DLQ) functionality and related dead code.
-- Updated font imports and improved the jobs search bar UI, with added stale repo cleanup.
-- Bumped vulnerable packages.
-
-### Bug Fixes
-
-- Fixed a failing Google API test case.
-- Fixed `onMouseEnter` typecheck issue.
-- Fixed sidebar active button colors.
-
-**Full Changelog**: https://github.com/devarshishimpi/codra/commits/v0.9.4
-
-## v0.9.2
-
-### What's New
-
-- **UI Redesign:** Full visual overhaul of the dashboard, landing page, and auth flows with an updated color system, improved dark mode, and a cleaner layout overall.
-- **Code Splitting:** All pages now use `React.lazy` for async loading, reducing initial bundle size and improving load times.
-- **Custom LLM Providers:** Manage custom OpenAI-compatible API providers directly from the dashboard. Rate limits are optional. No more hardcoded keys in wrangler config.
-- **Cloudflare Setup Script:** A new Node.js script automates the full Cloudflare deployment setup, making self-hosting significantly easier.
-- **Increased Review Capacity:** Max files processed per review raised from 15 to 100.
-
-### Improvements
-
-- Review jobs are now resumable and lease-aware, stalled reviews can recover automatically.
-- Added retry logic for transient model provider failures.
-- Optimized job polling with ETag caching and adaptive delays.
-- Improved settings UI, error reporting, and API robustness across the board.
-- Added GitHub Actions CI with a disposable test environment for the full test suite.
-
-### Bug Fixes
-
-- Fixed `APP_PRIVATE_KEY` parsing for single-line strings with literal `\n` sequences.
-- Fixed database migration failures on existing deployments.
-- Fixed duplicate `/api/auth/updates-email` calls on page load.
-- Fixed file review status bar rendering on the dashboard.
-
-**Full Changelog**: https://github.com/devarshishimpi/codra/commits/v0.9.2
diff --git a/README.md b/README.md
index a0cd1a53..d1a24991 100644
--- a/README.md
+++ b/README.md
@@ -10,6 +10,7 @@
+
@@ -33,7 +34,7 @@
Codra listens to GitHub pull request events, runs AI-powered review jobs, posts inline findings back to the PR, and gives you a dashboard to inspect jobs, repositories, model routing, review history, and failed queue runs.
-> **Beta** - Codra is under active development. Expect rough edges, missing features, and breaking changes between releases. Feedback and bug reports are welcome via [GitHub Issues](https://github.com/devarshishimpi/codra/issues).
+> **Beta** - Codra is under active development. Cloudflare Worker is stable for self-hosted use; Node standalone is newer and still being hardened. Expect rough edges. Bugs and feedback welcome via [GitHub Issues](https://github.com/devarshishimpi/codra/issues).
## Why Codra
diff --git a/apps/node/package.json b/apps/node/package.json
index d509b275..895968ed 100644
--- a/apps/node/package.json
+++ b/apps/node/package.json
@@ -1,6 +1,6 @@
{
"name": "@codraoss/node-server",
- "version": "0.9.6",
+ "version": "0.9.12",
"private": true,
"type": "module",
"scripts": {
@@ -14,6 +14,7 @@
"@codraoss/core": "*",
"@codraoss/db": "*",
"@codraoss/models": "*",
+ "@codraoss/node-adapters": "*",
"@codraoss/provider-github": "*",
"@codraoss/schema": "*",
"@hono/node-server": "^1.11.1",
diff --git a/apps/node/src/adapters/redis-queue.ts b/apps/node/src/adapters/redis-queue.ts
deleted file mode 100644
index 643d94e1..00000000
--- a/apps/node/src/adapters/redis-queue.ts
+++ /dev/null
@@ -1,14 +0,0 @@
-import type { QueueProducer } from '@codraoss/core/ports';
-import type { Queue } from 'bullmq';
-
-export class RedisQueueAdapter implements QueueProducer {
- constructor(private readonly queue: Queue) {}
-
- async send(message: T, options?: { delaySeconds?: number }): Promise {
- const jobOptions = options?.delaySeconds
- ? { delay: options.delaySeconds * 1000 }
- : undefined;
-
- await this.queue.add('review-job', message, jobOptions);
- }
-}
diff --git a/apps/node/src/api-deps.ts b/apps/node/src/api-deps.ts
index 537e4568..ac0f4f44 100644
--- a/apps/node/src/api-deps.ts
+++ b/apps/node/src/api-deps.ts
@@ -2,8 +2,6 @@ import { createSharedApiDeps } from '@codraoss/api';
import type { NodeAppBindings } from './env';
import { logger } from '@codraoss/api/logger';
import { createReviewRuntime } from './runtime';
-import { Queue } from 'bullmq';
-import Redis from 'ioredis';
export function createNodeApiDeps(env: NodeAppBindings) {
return createSharedApiDeps({
@@ -16,15 +14,12 @@ export function createNodeApiDeps(env: NodeAppBindings) {
await env.REVIEW_QUEUE.send(input);
},
terminateJobWorkflow: async (job) => {
- const workerQueue = new Queue('codra-reviews', { connection: new Redis(process.env.REDIS_URL || 'redis://localhost:6379') });
- const bullMqJob = await workerQueue.getJob(job.id);
- if (bullMqJob) {
- await bullMqJob.remove();
+ if (env.REVIEW_QUEUE.deleteJob) {
+ await env.REVIEW_QUEUE.deleteJob(job.id);
logger.info(`[API Deps] Terminated job workflow for job ${job.id}`);
} else {
- logger.warn(`[API Deps] Attempted to terminate non-existent or completed job ${job.id}`);
+ logger.warn(`[API Deps] QueueAdapter does not support deleteJob. Cannot terminate ${job.id}`);
}
- await workerQueue.close();
},
scheduleBestEffortJobMaintenance: () => {
// In node, this is a long running process, we can just spawn a promise.
diff --git a/apps/node/src/index.ts b/apps/node/src/index.ts
index 7f0b3e60..ca7f9795 100644
--- a/apps/node/src/index.ts
+++ b/apps/node/src/index.ts
@@ -2,23 +2,31 @@
import * as path from 'node:path';
dotenv.config({ path: path.resolve(process.cwd(), '../../.dev.vars') }); // Fallback if running from apps/node
dotenv.config({ path: path.resolve(process.cwd(), '.dev.vars') }); // Root level
+
import { serve } from '@hono/node-server';
import { createApiRouter } from '@codraoss/api';
import { runWithDb } from '@codraoss/db/client';
+
+import { NodeOrchestrator, RedisKVAdapter, RedisQueueAdapter, RedisSessionStore, startWorker } from '@codraoss/node-adapters';
import { createNodeApiDeps } from './api-deps';
-import { createNodeEnv } from './env';
+import { createNodeEnv, NodeAppBindings } from './env';
import { logger } from '@codraoss/api/logger';
import Redis from 'ioredis';
-import { RedisKVAdapter } from './adapters/redis-kv';
import { Queue } from 'bullmq';
-import { RedisQueueAdapter } from './adapters/redis-queue';
-import { NodeOrchestrator } from './adapters/node-orchestrator';
-import { startWorker } from './worker';
+
+import { serveStatic } from '@hono/node-server/serve-static';
+import { fileURLToPath } from 'url';
+import { dirname } from 'path';
import { createReviewRuntime } from './runtime';
-import { RedisSessionStore } from './adapters/redis-session-store';
+
+const __filename = fileURLToPath(import.meta.url);
+const __dirname = dirname(__filename);
const redisUrl = process.env.REDIS_URL || 'redis://localhost:6379';
-const redisClient = new Redis(redisUrl, { maxRetriesPerRequest: null }); // maxRetriesPerRequest: null is required for bullmq
+const redisClient = new Redis(redisUrl, {
+ maxRetriesPerRequest: null,
+ tls: redisUrl.startsWith('rediss://') ? { rejectUnauthorized: false } : undefined, // For managed Redis
+});
redisClient.on('error', (err) => {
logger.error('[Redis Error]', err);
});
@@ -27,67 +35,93 @@ const reviewQueue = new Queue('codra-reviews', { connection: redisClient });
const stubs = {
SESSION_STORE: new RedisSessionStore(redisClient),
- APP_KV: new RedisKVAdapter(redisClient),
+ KV_STORE: new RedisKVAdapter(redisClient),
REVIEW_QUEUE: new RedisQueueAdapter(reviewQueue),
REVIEW_ORCHESTRATOR: undefined, // Will be set to NodeOrchestrator below
};
-const env = createNodeEnv(stubs);
+const env: NodeAppBindings = createNodeEnv(stubs);
env.REVIEW_ORCHESTRATOR = new NodeOrchestrator(createReviewRuntime(env), stubs.REVIEW_QUEUE);
-import fs from 'node:fs';
-import { serveStatic } from '@hono/node-server/serve-static';
-
-const dashboardDist = path.resolve(process.cwd(), process.cwd().endsWith('node') ? '../../dist/client' : 'dist/client');
-
const app = createApiRouter();
+
app.onError((err, c) => {
console.error('HONO ERROR:', err);
return c.text('Custom Error: ' + err.message, 500);
});
-app.use('/assets/*', serveStatic({ root: process.cwd().endsWith('node') ? '../../dist/client' : 'dist/client' }));
-app.use('/*.svg', serveStatic({ root: process.cwd().endsWith('node') ? '../../dist/client' : 'dist/client' }));
-app.use('/*.ico', serveStatic({ root: process.cwd().endsWith('node') ? '../../dist/client' : 'dist/client' }));
-app.get('*', serveStatic({ root: process.cwd().endsWith('node') ? '../../dist/client' : 'dist/client', path: 'index.html' }));
+
+// Static file serving
+const distClientPath = path.resolve(__dirname, process.cwd().endsWith('node/dist') ? '../../dist/client' : '../dist/client');
+app.use('/assets/*', serveStatic({ root: distClientPath }));
+app.use('/*.svg', serveStatic({ root: distClientPath }));
+app.use('/*.ico', serveStatic({ root: distClientPath }));
+app.get('*', serveStatic({ root: distClientPath, path: 'index.html' }));
+
+app.get('/health', (c) => c.text('OK')); // Healthcheck endpoint
const port = parseInt(process.env.PORT || '3000', 10);
let worker: ReturnType | undefined;
if (process.env.START_WORKER !== 'false') {
- worker = startWorker(env, redisUrl, stubs.REVIEW_QUEUE);
+ worker = startWorker(redisClient, stubs.REVIEW_QUEUE, () => createReviewRuntime(env), logger);
logger.info('BullMQ Background Worker started.');
}
if (process.env.START_API !== 'false') {
- app.get('/health', (c) => c.text('OK'));
-
const server = serve({
fetch: async (request) => {
const apiEnv = {
...env,
deps: createNodeApiDeps(env),
};
+ // Ensure runWithDb receives correct DbEnv type
try { return await runWithDb({ ...env, HYPERDRIVE: env.DATABASE_CONFIG }, () => app.fetch(request, apiEnv as any)); } catch (e) { console.error('SERVE ERROR:', e); throw e; }
},
port,
+ hostname: '0.0.0.0',
}, (info) => {
logger.info(`Codra Node server running on http://localhost:${info.port}`);
});
-} else {
- logger.info('API Server disabled via START_API=false');
+
+ // Add server to shutdown sequence
+ if (server) {
+ const originalClose = server.close;
+ server.close = () => new Promise(resolve => {
+ originalClose(() => {
+ logger.info('HTTP server closed.');
+ resolve();
+ });
+ });
+ }
}
const shutdown = async () => {
logger.info('Shutting down Codra Node server...');
+
+ // Close BullMQ worker first to prevent new jobs
if (worker) {
logger.info('Waiting for active BullMQ jobs to finish...');
await worker.close();
logger.info('BullMQ Worker closed gracefully.');
}
+
+ // Close Redis connection
+ if (redisClient) {
+ logger.info('Closing Redis client...');
+ await redisClient.quit();
+ logger.info('Redis client closed.');
+ }
+
+ // Close Postgres connection pool
+ // The postgres.js client automatically manages its pool.
+ // runWithDb client is scoped, but a top-level client for specific operations might exist in the future
+ // For now, no explicit close needed for `postgres.js` unless it's a global client.
+ // If `runWithDb` is the only entry point, it manages its own connections.
+
+ logger.info('All services stopped. Exiting.');
process.exit(0);
};
process.on('SIGTERM', shutdown);
process.on('SIGINT', shutdown);
-// Trigger restart for env vars
diff --git a/apps/node/src/runtime.ts b/apps/node/src/runtime.ts
index 935e74b5..42c829d2 100644
--- a/apps/node/src/runtime.ts
+++ b/apps/node/src/runtime.ts
@@ -10,7 +10,7 @@ import { makeJobStore, makeFileReviewStore, makeLearningStore, makeModelConfigRe
import { loadRepoConfig } from '@codraoss/api/platform';
// Node-specific adapters
-import { cryptoIds, systemClock } from './adapters/platform';
+import { cryptoIds, systemClock } from '@codraoss/node-adapters';
import { makeTelemetrySink } from './adapters/telemetry';
import {
makeFormatterFactory,
diff --git a/apps/worker/package.json b/apps/worker/package.json
index 17115003..19f3f136 100644
--- a/apps/worker/package.json
+++ b/apps/worker/package.json
@@ -1,6 +1,6 @@
{
"name": "@codraoss/worker",
- "version": "0.9.6",
+ "version": "0.9.12",
"private": true,
"type": "module",
"dependencies": {
diff --git a/package-lock.json b/package-lock.json
index b88d9a71..174725ae 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -45,7 +45,6 @@
},
"devDependencies": {
"@arethetypeswrong/cli": "^0.18.5",
- "@changesets/cli": "^3.0.0",
"@eslint/js": "^10.0.1",
"@tailwindcss/vite": "^4.2.2",
"@testing-library/dom": "^10.4.1",
@@ -75,12 +74,13 @@
},
"apps/node": {
"name": "@codraoss/node-server",
- "version": "0.9.6",
+ "version": "0.9.12",
"dependencies": {
"@codraoss/api": "*",
"@codraoss/core": "*",
"@codraoss/db": "*",
"@codraoss/models": "*",
+ "@codraoss/node-adapters": "*",
"@codraoss/provider-github": "*",
"@codraoss/schema": "*",
"@hono/node-server": "^1.11.1",
@@ -113,7 +113,7 @@
},
"apps/worker": {
"name": "@codraoss/worker",
- "version": "0.9.6",
+ "version": "0.9.12",
"dependencies": {
"@codraoss/api": "*",
"@codraoss/core": "*",
@@ -638,289 +638,6 @@
"specificity": "bin/cli.js"
}
},
- "node_modules/@changesets/apply-release-plan": {
- "version": "8.0.0",
- "resolved": "https://registry.npmjs.org/@changesets/apply-release-plan/-/apply-release-plan-8.0.0.tgz",
- "integrity": "sha512-kUd2pbf1w5/AYmBMb0Tt+rkIPCjFJdT0SZMrkOjJT/WV/QbtmvkyB5jkV0oaNPheavprZk+SfUiozUti7TIL2w==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "@changesets/config": "^4.0.0",
- "@changesets/format": "^0.1.1",
- "@changesets/git": "^4.0.0",
- "@changesets/should-skip-package": "^1.0.0",
- "@changesets/types": "^7.0.0",
- "import-meta-resolve": "^4.2.0",
- "jsonc-parser": "^3.3.1",
- "semver": "^7.8.1"
- },
- "engines": {
- "node": "^22.11 || ^24 || >=26"
- }
- },
- "node_modules/@changesets/assemble-release-plan": {
- "version": "7.0.0",
- "resolved": "https://registry.npmjs.org/@changesets/assemble-release-plan/-/assemble-release-plan-7.0.0.tgz",
- "integrity": "sha512-oEW8BxdA604kGGtDSCiHr5w9Tv4UWe9I2k61IBNZzCOE1kbYaJj4v+lFQNgcEZFkUc2pV/+hASErGDvpJOZCTg==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "@changesets/errors": "^1.0.0",
- "@changesets/get-dependents-graph": "^3.0.0",
- "@changesets/should-skip-package": "^1.0.0",
- "@changesets/types": "^7.0.0",
- "semver": "^7.8.1"
- },
- "engines": {
- "node": "^22.11 || ^24 || >=26"
- }
- },
- "node_modules/@changesets/changelog-git": {
- "version": "1.0.0",
- "resolved": "https://registry.npmjs.org/@changesets/changelog-git/-/changelog-git-1.0.0.tgz",
- "integrity": "sha512-3Dst2Ime2Op5nd4XmWJLPIgp11ZFqJqSkVug9izK6TDcIV4YlhPS4ECbEVR+eGI0bk0r1ItogD4j2Oli87bJrA==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "@changesets/types": "^7.0.0"
- },
- "engines": {
- "node": "^22.11 || ^24 || >=26"
- }
- },
- "node_modules/@changesets/cli": {
- "version": "3.0.0",
- "resolved": "https://registry.npmjs.org/@changesets/cli/-/cli-3.0.0.tgz",
- "integrity": "sha512-V7Gm+GP5OT3mJinMI2YcJD/JyO/a4WChnaMCCzTRhWHgu1zhtsyY7zCjP6n5W6zsgSjJKs+yPmvtREvE0F2g8A==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "@changesets/apply-release-plan": "^8.0.0",
- "@changesets/assemble-release-plan": "^7.0.0",
- "@changesets/changelog-git": "^1.0.0",
- "@changesets/config": "^4.0.0",
- "@changesets/errors": "^1.0.0",
- "@changesets/get-dependents-graph": "^3.0.0",
- "@changesets/git": "^4.0.0",
- "@changesets/pre": "^3.0.0",
- "@changesets/read": "^1.0.0",
- "@changesets/should-skip-package": "^1.0.0",
- "@changesets/types": "^7.0.0",
- "@changesets/write": "^1.0.0",
- "@clack/prompts": "^1.7.0",
- "@manypkg/get-packages": "^3.1.0",
- "@pnpm/deps.graph-sequencer": "^1100.0.1",
- "cac": "^7.0.0",
- "import-meta-resolve": "^4.2.0",
- "launch-editor": "^2.14.1",
- "package-manager-detector": "^1.6.0",
- "semver": "^7.8.1",
- "tinyexec": "^1.3.0"
- },
- "bin": {
- "changeset": "bin.js"
- },
- "engines": {
- "node": "^22.11 || ^24 || >=26",
- "npm": ">=10.9.0",
- "pnpm": ">=10.0.0",
- "yarn": ">=4.5.2"
- }
- },
- "node_modules/@changesets/cli/node_modules/cac": {
- "version": "7.0.0",
- "resolved": "https://registry.npmjs.org/cac/-/cac-7.0.0.tgz",
- "integrity": "sha512-tixWYgm5ZoOD+3g6UTea91eow5z6AAHaho3g0V9CNSNb45gM8SmflpAc+GRd1InC4AqN/07Unrgp56Y94N9hJQ==",
- "dev": true,
- "license": "MIT",
- "engines": {
- "node": ">=20.19.0"
- }
- },
- "node_modules/@changesets/config": {
- "version": "4.0.0",
- "resolved": "https://registry.npmjs.org/@changesets/config/-/config-4.0.0.tgz",
- "integrity": "sha512-mw95/YrkOuhZZxfnVAA4bSXOFUi+KlhzOBTM8C4x777NhUU6HWIl9Z+K+nME+E4PVsv5NQVQwTfiHihAS1A/ow==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "@changesets/get-dependents-graph": "^3.0.0",
- "@changesets/should-skip-package": "^1.0.0",
- "@changesets/types": "^7.0.0",
- "@manypkg/get-packages": "^3.1.0",
- "picomatch": "^4.0.4"
- },
- "engines": {
- "node": "^22.11 || ^24 || >=26"
- }
- },
- "node_modules/@changesets/errors": {
- "version": "1.0.0",
- "resolved": "https://registry.npmjs.org/@changesets/errors/-/errors-1.0.0.tgz",
- "integrity": "sha512-ElN/mEzn6zmETgjwf5MclCMa9ef59sAR0lfO8VSYIsiRvbC2FbLB/92EoYw10Sl0kGixxHFiJZUSv7dA+YpR8g==",
- "dev": true,
- "license": "MIT",
- "engines": {
- "node": "^22.11 || ^24 || >=26"
- }
- },
- "node_modules/@changesets/format": {
- "version": "0.1.2",
- "resolved": "https://registry.npmjs.org/@changesets/format/-/format-0.1.2.tgz",
- "integrity": "sha512-Caez5XtNXCFS/G5bwyav3wuXL0tMxVd2ZGbaumWbzN08tyzO21asCw7JZhNtVsAZDCvDRUzZN+Iit9SyRITSYA==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "package-manager-detector": "^1.8.0",
- "tinyexec": "^1.3.0"
- },
- "engines": {
- "node": "^22.11 || ^24 || >=26"
- }
- },
- "node_modules/@changesets/get-dependents-graph": {
- "version": "3.0.0",
- "resolved": "https://registry.npmjs.org/@changesets/get-dependents-graph/-/get-dependents-graph-3.0.0.tgz",
- "integrity": "sha512-ji/t5wFA1zREKXRUePE6Qi+Qu2UgxCeSSGQrphezwvQZrp49B7sJ+8+wvM0tA7zPeSxYKCojDy3WWgrl+s+awg==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "@changesets/types": "^7.0.0",
- "semver": "^7.8.1"
- },
- "engines": {
- "node": "^22.11 || ^24 || >=26"
- }
- },
- "node_modules/@changesets/git": {
- "version": "4.0.0",
- "resolved": "https://registry.npmjs.org/@changesets/git/-/git-4.0.0.tgz",
- "integrity": "sha512-uIEswpPUgzBBqrC0qg13byNaPorzhf05LE2T+gRizEKCXvMsJC6NPJp5iNDSV/gYj4Viqh09UiOF5E7XWeH5lQ==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "@changesets/errors": "^1.0.0",
- "@changesets/types": "^7.0.0",
- "@manypkg/get-packages": "^3.1.0",
- "picomatch": "^4.0.4",
- "tinyexec": "^1.3.0"
- },
- "engines": {
- "node": "^22.11 || ^24 || >=26"
- }
- },
- "node_modules/@changesets/parse": {
- "version": "1.0.0",
- "resolved": "https://registry.npmjs.org/@changesets/parse/-/parse-1.0.0.tgz",
- "integrity": "sha512-P0iaMb9p9CRYZiTgAllEIF9AUMQHIy1G72tKlcIqJp61icZSsKQNiOPdxAMZG8m/DvZwt/oz5xEbTpike//dWg==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "@changesets/types": "^7.0.0",
- "yaml": "^2.9.0"
- },
- "engines": {
- "node": "^22.11 || ^24 || >=26"
- }
- },
- "node_modules/@changesets/pre": {
- "version": "3.0.0",
- "resolved": "https://registry.npmjs.org/@changesets/pre/-/pre-3.0.0.tgz",
- "integrity": "sha512-Zm/6YliV/a2oeWTqHJf6KxLrQwgcK1i/BRDl2m0EKZvbnxV5fG9QRhwJJGshjsZTUTS6dkfURQ2K6aAvgNw/3Q==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "@changesets/errors": "^1.0.0",
- "@changesets/types": "^7.0.0",
- "@manypkg/get-packages": "^3.1.0"
- },
- "engines": {
- "node": "^22.11 || ^24 || >=26"
- }
- },
- "node_modules/@changesets/read": {
- "version": "1.0.0",
- "resolved": "https://registry.npmjs.org/@changesets/read/-/read-1.0.0.tgz",
- "integrity": "sha512-8TdE2PwG6yArPt5Ozej83Z6iHz1G8BDBKvIEKZ455MccR4K3GNbLR2XqjBxa+5yLFnEd3xAOPXYboBg1pt8stQ==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "@changesets/git": "^4.0.0",
- "@changesets/parse": "^1.0.0",
- "@changesets/types": "^7.0.0"
- },
- "engines": {
- "node": "^22.11 || ^24 || >=26"
- }
- },
- "node_modules/@changesets/should-skip-package": {
- "version": "1.0.0",
- "resolved": "https://registry.npmjs.org/@changesets/should-skip-package/-/should-skip-package-1.0.0.tgz",
- "integrity": "sha512-pwqoJmbONn1XgXmZXPEExgAaT+HdZLjALFTDgIm+PnS5KeO2nLtzA2/Q+4aMFY14kFMuXKG30MObhvDzWgzDgg==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "@changesets/types": "^7.0.0"
- },
- "engines": {
- "node": "^22.11 || ^24 || >=26"
- }
- },
- "node_modules/@changesets/types": {
- "version": "7.0.0",
- "resolved": "https://registry.npmjs.org/@changesets/types/-/types-7.0.0.tgz",
- "integrity": "sha512-c5GoiQyt3pxiXjrWSNoP8/GRf4kG+VnKzovx1OQM8dYYALlSwgedmkPmJ+ZqGxqwg9D3Bkj85Uo4KLd5BN3A0w==",
- "dev": true,
- "license": "MIT",
- "engines": {
- "node": "^22.11 || ^24 || >=26"
- }
- },
- "node_modules/@changesets/write": {
- "version": "1.0.0",
- "resolved": "https://registry.npmjs.org/@changesets/write/-/write-1.0.0.tgz",
- "integrity": "sha512-xCK3/4C7Z7muQB/wguE6HcbjtY9iOtaK9orZKE+7xi573cMGD8rLZz7qlo6IvK7s+SIUIKajzj1l+F1QuP97tw==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "@changesets/format": "^0.1.1",
- "@changesets/types": "^7.0.0",
- "human-id": "^4.2.0"
- },
- "engines": {
- "node": "^22.11 || ^24 || >=26"
- }
- },
- "node_modules/@clack/core": {
- "version": "1.4.3",
- "resolved": "https://registry.npmjs.org/@clack/core/-/core-1.4.3.tgz",
- "integrity": "sha512-/kr3UWNtdJfxZtPgDqUOmG2pvwlmcLGheex5yiZKdwbzZJxhV+HMNR9QNmyY5cGwTNV6LrR7Jtp+KjhUAP1qBQ==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "fast-wrap-ansi": "^0.2.0",
- "sisteransi": "^1.0.5"
- },
- "engines": {
- "node": ">= 20.12.0"
- }
- },
- "node_modules/@clack/prompts": {
- "version": "1.7.0",
- "resolved": "https://registry.npmjs.org/@clack/prompts/-/prompts-1.7.0.tgz",
- "integrity": "sha512-y7/yvZ2TPAnR9+jnc00klvNNLkJiXFFrQA/hlLCcxA9a2A4zQIOimyFQ9XfwYKiGD1fb5GY8vbKIIgO8d5Tb2A==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "@clack/core": "1.4.3",
- "fast-string-width": "^3.0.2",
- "fast-wrap-ansi": "^0.2.0",
- "sisteransi": "^1.0.5"
- },
- "engines": {
- "node": ">= 20.12.0"
- }
- },
"node_modules/@cloudflare/kv-asset-handler": {
"version": "0.5.0",
"dev": true,
@@ -1044,6 +761,10 @@
"resolved": "packages/models",
"link": true
},
+ "node_modules/@codraoss/node-adapters": {
+ "resolved": "packages/node-adapters",
+ "link": true
+ },
"node_modules/@codraoss/node-server": {
"resolved": "apps/node",
"link": true
@@ -2595,48 +2316,6 @@
"@braidai/lang": "^1.0.0"
}
},
- "node_modules/@manypkg/find-root": {
- "version": "3.1.0",
- "resolved": "https://registry.npmjs.org/@manypkg/find-root/-/find-root-3.1.0.tgz",
- "integrity": "sha512-BcSqCyKhBVZ5YkSzOiheMCV41kqAFptW6xGqYSTjkVTl9XQpr+pqHhwgGCOHQtjDCv7Is6EFyA14Sm5GVbVABA==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "@manypkg/tools": "^2.1.0"
- },
- "engines": {
- "node": ">=20.0.0"
- }
- },
- "node_modules/@manypkg/get-packages": {
- "version": "3.1.0",
- "resolved": "https://registry.npmjs.org/@manypkg/get-packages/-/get-packages-3.1.0.tgz",
- "integrity": "sha512-0TbBVyvPrP7xGYBI/cP8UP+yl/z+HtbTttAD7FMAJgn/kXOTwh5/60TsqP9ZYY710forNfyV0N8P/IE/ujGZJg==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "@manypkg/find-root": "^3.1.0",
- "@manypkg/tools": "^2.1.0"
- },
- "engines": {
- "node": ">=20.0.0"
- }
- },
- "node_modules/@manypkg/tools": {
- "version": "2.1.2",
- "resolved": "https://registry.npmjs.org/@manypkg/tools/-/tools-2.1.2.tgz",
- "integrity": "sha512-6QEf6yqFbETdwGITKq57aYoPfX/3K8XFNwsAlx0C1M7o8cb79sv1M3w+tWuWvIcSbNqrLF7OD7YpZMVVz335hQ==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "jju": "^1.4.0",
- "tinyglobby": "^0.2.13",
- "yaml": "^2.9.0"
- },
- "engines": {
- "node": ">=20.0.0"
- }
- },
"node_modules/@msgpackr-extract/msgpackr-extract-darwin-arm64": {
"version": "3.0.4",
"resolved": "https://registry.npmjs.org/@msgpackr-extract/msgpackr-extract-darwin-arm64/-/msgpackr-extract-darwin-arm64-3.0.4.tgz",
@@ -2765,19 +2444,6 @@
"url": "https://github.com/sponsors/Boshen"
}
},
- "node_modules/@pnpm/deps.graph-sequencer": {
- "version": "1100.0.1",
- "resolved": "https://registry.npmjs.org/@pnpm/deps.graph-sequencer/-/deps.graph-sequencer-1100.0.1.tgz",
- "integrity": "sha512-pOr5+q1fLYKwFN3LAJuGZEnfXDcQ73zqgDHMtGy+K+uIoUqyY+6MeDCWFwfu+4EFuq76I5EPFofoNAI+Bmmq4A==",
- "dev": true,
- "license": "MIT",
- "engines": {
- "node": ">=22.13"
- },
- "funding": {
- "url": "https://opencollective.com/pnpm"
- }
- },
"node_modules/@poppinss/colors": {
"version": "4.1.6",
"resolved": "https://registry.npmjs.org/@poppinss/colors/-/colors-4.1.6.tgz",
@@ -6324,33 +5990,6 @@
"dev": true,
"license": "MIT"
},
- "node_modules/fast-string-truncated-width": {
- "version": "3.0.3",
- "resolved": "https://registry.npmjs.org/fast-string-truncated-width/-/fast-string-truncated-width-3.0.3.tgz",
- "integrity": "sha512-0jjjIEL6+0jag3l2XWWizO64/aZVtpiGE3t0Zgqxv0DPuxiMjvB3M24fCyhZUO4KomJQPj3LTSUnDP3GpdwC0g==",
- "dev": true,
- "license": "MIT"
- },
- "node_modules/fast-string-width": {
- "version": "3.0.2",
- "resolved": "https://registry.npmjs.org/fast-string-width/-/fast-string-width-3.0.2.tgz",
- "integrity": "sha512-gX8LrtNEI5hq8DVUfRQMbr5lpaS4nMIWV+7XEbXk2b8kiQIizgnlr12B4dA3ZEx3308ze0O4Q1R+cHts8kyUJg==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "fast-string-truncated-width": "^3.0.2"
- }
- },
- "node_modules/fast-wrap-ansi": {
- "version": "0.2.2",
- "resolved": "https://registry.npmjs.org/fast-wrap-ansi/-/fast-wrap-ansi-0.2.2.tgz",
- "integrity": "sha512-7F2Fl+TjRSenLqlU3UjSH0iyqopqoZIu7eZVpEirP2g1GtWa2G/ecEmBdgz31+Mxr+ELclgg6sokpSFIQiZ02Q==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "fast-string-width": "^3.0.2"
- }
- },
"node_modules/fdir": {
"version": "6.5.0",
"dev": true,
@@ -6761,16 +6400,6 @@
"url": "https://github.com/sponsors/wooorm"
}
},
- "node_modules/human-id": {
- "version": "4.2.0",
- "resolved": "https://registry.npmjs.org/human-id/-/human-id-4.2.0.tgz",
- "integrity": "sha512-K3GbkIWqyvvlpfhBPlbEvD97TtqBpAYA4kt+cn2lD2x2HuohzZCibcA2nOlnJT6exqvJLggoB5nv2dNf192nEA==",
- "dev": true,
- "license": "MIT",
- "bin": {
- "human-id": "dist/cli.js"
- }
- },
"node_modules/ignore": {
"version": "5.3.2",
"resolved": "https://registry.npmjs.org/ignore/-/ignore-5.3.2.tgz",
@@ -6789,17 +6418,6 @@
"url": "https://opencollective.com/immer"
}
},
- "node_modules/import-meta-resolve": {
- "version": "4.2.0",
- "resolved": "https://registry.npmjs.org/import-meta-resolve/-/import-meta-resolve-4.2.0.tgz",
- "integrity": "sha512-Iqv2fzaTQN28s/FwZAoFq0ZSs/7hMAHJVX+w8PZl3cY19Pxk6jFFalxQoIfW2826i/fDLXv8IiEZRIT0lDuWcg==",
- "dev": true,
- "license": "MIT",
- "funding": {
- "type": "github",
- "url": "https://github.com/sponsors/wooorm"
- }
- },
"node_modules/imurmurhash": {
"version": "0.1.4",
"resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz",
@@ -6971,13 +6589,6 @@
"jiti": "lib/jiti-cli.mjs"
}
},
- "node_modules/jju": {
- "version": "1.4.0",
- "resolved": "https://registry.npmjs.org/jju/-/jju-1.4.0.tgz",
- "integrity": "sha512-8wb9Yw966OSxApiCt0K3yNJL8pnNeIv+OEq2YMidz4FKP6nonSRoOXc80iXY4JaN2FC11B9qsNmDsm+ZOfMROA==",
- "dev": true,
- "license": "MIT"
- },
"node_modules/joycon": {
"version": "3.1.1",
"resolved": "https://registry.npmjs.org/joycon/-/joycon-3.1.1.tgz",
@@ -7079,13 +6690,6 @@
"node": ">=6"
}
},
- "node_modules/jsonc-parser": {
- "version": "3.3.1",
- "resolved": "https://registry.npmjs.org/jsonc-parser/-/jsonc-parser-3.3.1.tgz",
- "integrity": "sha512-HUgH65KyejrUFPvHFPbqOY0rsFip3Bo5wb4ngvdi1EpCYWUQDC5V+Y7mZws+DLkr4M//zQJoanu1SP+87Dv1oQ==",
- "dev": true,
- "license": "MIT"
- },
"node_modules/jsonrepair": {
"version": "3.15.0",
"resolved": "https://registry.npmjs.org/jsonrepair/-/jsonrepair-3.15.0.tgz",
@@ -7113,17 +6717,6 @@
"node": ">=6"
}
},
- "node_modules/launch-editor": {
- "version": "2.14.1",
- "resolved": "https://registry.npmjs.org/launch-editor/-/launch-editor-2.14.1.tgz",
- "integrity": "sha512-QWBrQsMpH7gPr965dsKD/3cKWiNoTjpATQf++Xq63N6sKRGMwlVXz41O1IZTMfZQgBctD/K5Zt06+/I6pP6+HA==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "picocolors": "^1.1.1",
- "shell-quote": "^1.8.4"
- }
- },
"node_modules/lenis": {
"version": "1.3.26",
"resolved": "https://registry.npmjs.org/lenis/-/lenis-1.3.26.tgz",
@@ -11259,22 +10852,6 @@
"dev": true,
"license": "ISC"
},
- "node_modules/yaml": {
- "version": "2.9.0",
- "resolved": "https://registry.npmjs.org/yaml/-/yaml-2.9.0.tgz",
- "integrity": "sha512-2AvhNX3mb8zd6Zy7INTtSpl1F15HW6Wnqj0srWlkKLcpYl/gMIMJiyuGq2KeI2YFxUPjdlB+3Lc10seMLtL4cA==",
- "dev": true,
- "license": "ISC",
- "bin": {
- "yaml": "bin.mjs"
- },
- "engines": {
- "node": ">= 14.6"
- },
- "funding": {
- "url": "https://github.com/sponsors/eemeli"
- }
- },
"node_modules/yargs": {
"version": "17.7.2",
"dev": true,
@@ -11403,14 +10980,14 @@
},
"packages/api": {
"name": "@codraoss/api",
- "version": "0.9.8",
+ "version": "0.9.12",
"license": "AGPL-3.0-only",
"dependencies": {
- "@codraoss/core": "^0.9.5",
- "@codraoss/db": "^0.9.5",
- "@codraoss/models": "^0.9.6",
- "@codraoss/provider-github": "^0.9.5",
- "@codraoss/schema": "^0.9.5",
+ "@codraoss/core": "*",
+ "@codraoss/db": "*",
+ "@codraoss/models": "*",
+ "@codraoss/provider-github": "*",
+ "@codraoss/schema": "*",
"hono": "^4.12.25",
"zod": "^4.3.6"
},
@@ -11438,10 +11015,10 @@
},
"packages/core": {
"name": "@codraoss/core",
- "version": "0.9.6",
+ "version": "0.9.12",
"license": "AGPL-3.0-only",
"dependencies": {
- "@codraoss/schema": "^0.9.5",
+ "@codraoss/schema": "*",
"jsonrepair": "^3.15.0",
"picomatch": "^4.0.5",
"zod": "^4.3.6"
@@ -11453,11 +11030,11 @@
},
"packages/db": {
"name": "@codraoss/db",
- "version": "0.9.5",
+ "version": "0.9.12",
"license": "AGPL-3.0-only",
"dependencies": {
- "@codraoss/core": "^0.9.5",
- "@codraoss/schema": "^0.9.5",
+ "@codraoss/core": "*",
+ "@codraoss/schema": "*",
"postgres": "^3.4.9"
},
"devDependencies": {
@@ -11484,23 +11061,76 @@
},
"packages/models": {
"name": "@codraoss/models",
- "version": "0.9.6",
+ "version": "0.9.12",
+ "license": "AGPL-3.0-only",
+ "dependencies": {
+ "@codraoss/core": "*",
+ "@codraoss/schema": "*"
+ },
+ "devDependencies": {
+ "tsup": "^8.0.0"
+ }
+ },
+ "packages/node-adapters": {
+ "name": "@codraoss/node-adapters",
+ "version": "0.9.12",
"license": "AGPL-3.0-only",
"dependencies": {
- "@codraoss/core": "^0.9.5",
- "@codraoss/schema": "^0.9.5"
+ "@codraoss/api": "*",
+ "@codraoss/core": "*",
+ "@codraoss/db": "*",
+ "@codraoss/schema": "*",
+ "bullmq": "^6.3.8",
+ "ioredis": "^6.0.0",
+ "nanoid": "^5.0.7"
},
"devDependencies": {
+ "@types/node": "^22.0.0",
"tsup": "^8.0.0"
}
},
+ "packages/node-adapters/node_modules/@types/node": {
+ "version": "22.20.4",
+ "resolved": "https://registry.npmjs.org/@types/node/-/node-22.20.4.tgz",
+ "integrity": "sha512-zJRE40jpHtKqE/C4fgHrAKQLJuSpzEnP9ff9Y7YtoR3Wd2pwqzlekDeEuUQXjRd+QCYnVnNwuJYmhdk9XV8gvA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "undici-types": "~6.21.0"
+ }
+ },
+ "packages/node-adapters/node_modules/nanoid": {
+ "version": "5.1.16",
+ "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-5.1.16.tgz",
+ "integrity": "sha512-kVrnsrJqMR8+oLJnGEmSWw9BivK5mt7H3FZatVRjrc5wGqFYuBxX1yG7+A7Gi5AefkX6t/oCkizcQgpu0cY1dQ==",
+ "funding": [
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/ai"
+ }
+ ],
+ "license": "MIT",
+ "bin": {
+ "nanoid": "bin/nanoid.js"
+ },
+ "engines": {
+ "node": "^18 || >=20"
+ }
+ },
+ "packages/node-adapters/node_modules/undici-types": {
+ "version": "6.21.0",
+ "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-6.21.0.tgz",
+ "integrity": "sha512-iwDZqg0QAGrg9Rav5H4n0M64c3mkR59cJ6wQp+7C4nI0gsmExaedaYLNO44eT4AtBBwjbTiGPMlt2Md0T9H9JQ==",
+ "dev": true,
+ "license": "MIT"
+ },
"packages/provider-github": {
"name": "@codraoss/provider-github",
- "version": "0.9.5",
+ "version": "0.9.12",
"license": "AGPL-3.0-only",
"dependencies": {
- "@codraoss/core": "^0.9.5",
- "@codraoss/schema": "^0.9.5"
+ "@codraoss/core": "*",
+ "@codraoss/schema": "*"
},
"devDependencies": {
"tsup": "^8.0.0"
@@ -11508,7 +11138,7 @@
},
"packages/schema": {
"name": "@codraoss/schema",
- "version": "0.9.5",
+ "version": "0.9.12",
"license": "AGPL-3.0-only",
"dependencies": {
"zod": "^4.3.6"
@@ -11519,11 +11149,11 @@
},
"packages/ui": {
"name": "@codraoss/ui",
- "version": "0.9.10",
+ "version": "0.9.12",
"license": "AGPL-3.0-only",
"dependencies": {
"@base-ui/react": "^1.6.0",
- "@codraoss/schema": "^0.9.5",
+ "@codraoss/schema": "*",
"class-variance-authority": "^0.7.1",
"clsx": "^2.1.1",
"sugar-high": "^2.0.0",
diff --git a/package.json b/package.json
index 0c7ea2b6..d89faa79 100644
--- a/package.json
+++ b/package.json
@@ -38,14 +38,11 @@
"test:watch": "vitest",
"typecheck": "tsc --noEmit",
"typecheck:all": "npm run typecheck --workspaces --if-present",
- "changeset": "changeset",
- "version:packages": "changeset version",
- "release": "npm run build:packages && changeset publish",
+ "release": "npm run build:packages",
"check:exports": "node scripts/check-package-exports.mjs"
},
"devDependencies": {
"@arethetypeswrong/cli": "^0.18.5",
- "@changesets/cli": "^3.0.0",
"@eslint/js": "^10.0.1",
"@tailwindcss/vite": "^4.2.2",
"@testing-library/dom": "^10.4.1",
diff --git a/packages/api/CHANGELOG.md b/packages/api/CHANGELOG.md
deleted file mode 100644
index db620f29..00000000
--- a/packages/api/CHANGELOG.md
+++ /dev/null
@@ -1,23 +0,0 @@
-# @codraoss/api
-
-## 0.9.6
-
-### Patch Changes
-
-- Compare `If-None-Match` on `GET /api/jobs/:id` as a weak validator. Cloudflare's edge rewrites strong ETags to `W/"..."` when it compresses the response, so a strict equality check never matched and the 304 path never fired in production; every poll re-serialized the full job detail and could exhaust the CPU limit on a large running job.
-- Updated dependencies
- - @codraoss/models@0.9.6
-
-## 0.9.5
-
-### Patch Changes
-
-- Add optional extension points. `createApiRouter(options?)` accepts `beforeAuth`, `afterAuth`, `pages`, `publicPages` and `routes`; `routes` is invoked last so anything mounted under `/api/*` still inherits the session and CSRF middleware. `ApiRouterDeps` gains optional `authz` and `checkQuota` ports, and every mutating endpoint is now checked against them. Both default to allow-all, so calling `createApiRouter()` with no arguments is unchanged. Quota denial on the webhook path answers 202-ignored rather than 429, because GitHub redelivers failed deliveries.
-- Updated dependencies
-- Updated dependencies
-- Updated dependencies
- - @codraoss/core@0.9.5
- - @codraoss/db@0.9.5
- - @codraoss/schema@0.9.5
- - @codraoss/models@0.9.5
- - @codraoss/provider-github@0.9.5
diff --git a/packages/api/package.json b/packages/api/package.json
index 1b4db67a..474f59c2 100644
--- a/packages/api/package.json
+++ b/packages/api/package.json
@@ -1,6 +1,6 @@
{
"name": "@codraoss/api",
- "version": "0.9.8",
+ "version": "0.9.12",
"description": "Codra's HTTP surface as a mountable Hono router, wired through ports.",
"author": "Devarshi Shimpi",
"license": "AGPL-3.0-only",
@@ -16,9 +16,18 @@
"type": "module",
"sideEffects": false,
"exports": {
- ".": "./src/index.ts",
- "./logger": "./src/logger.ts",
- "./platform": "./src/platform/index.ts"
+ ".": {
+ "types": "./dist/index.d.ts",
+ "import": "./dist/index.js"
+ },
+ "./logger": {
+ "types": "./dist/logger.d.ts",
+ "import": "./dist/logger.js"
+ },
+ "./platform": {
+ "types": "./dist/platform/index.d.ts",
+ "import": "./dist/platform/index.js"
+ }
},
"files": [
"dist",
@@ -26,24 +35,7 @@
"README.md"
],
"publishConfig": {
- "access": "public",
- "main": "./dist/index.js",
- "module": "./dist/index.js",
- "types": "./dist/index.d.ts",
- "exports": {
- ".": {
- "types": "./dist/index.d.ts",
- "import": "./dist/index.js"
- },
- "./logger": {
- "types": "./dist/logger.d.ts",
- "import": "./dist/logger.js"
- },
- "./platform": {
- "types": "./dist/platform/index.d.ts",
- "import": "./dist/platform/index.js"
- }
- }
+ "access": "public"
},
"scripts": {
"build": "tsup",
@@ -54,14 +46,17 @@
"dependencies": {
"hono": "^4.12.25",
"zod": "^4.3.6",
- "@codraoss/schema": "^0.9.5",
- "@codraoss/core": "^0.9.5",
- "@codraoss/db": "^0.9.5",
- "@codraoss/provider-github": "^0.9.5",
- "@codraoss/models": "^0.9.6"
+ "@codraoss/schema": "*",
+ "@codraoss/core": "*",
+ "@codraoss/db": "*",
+ "@codraoss/provider-github": "*",
+ "@codraoss/models": "*"
},
"devDependencies": {
"@types/node": "^22.0.0",
"tsup": "^8.0.0"
- }
+ },
+ "main": "./dist/index.js",
+ "module": "./dist/index.js",
+ "types": "./dist/index.d.ts"
}
diff --git a/packages/core/CHANGELOG.md b/packages/core/CHANGELOG.md
deleted file mode 100644
index cfe1e298..00000000
--- a/packages/core/CHANGELOG.md
+++ /dev/null
@@ -1,9 +0,0 @@
-# @codraoss/core
-
-## 0.9.5
-
-### Patch Changes
-
-- Raise `MAX_TOTAL_DIFF_CHARS` to 4,000,000 and centralise it in the package constants. Files dropped by the file-count and diff-size limits now mark a review as partial and are named in the job status, rather than appearing only in the pull request comment.
-- Updated dependencies
- - @codraoss/schema@0.9.5
diff --git a/packages/core/package.json b/packages/core/package.json
index 2829b7d1..69d26fe7 100644
--- a/packages/core/package.json
+++ b/packages/core/package.json
@@ -1,6 +1,6 @@
{
"name": "@codraoss/core",
- "version": "0.9.6",
+ "version": "0.9.12",
"description": "The Codra review engine: pure, transport- and platform-agnostic code review logic behind ports.",
"author": "Devarshi Shimpi",
"license": "AGPL-3.0-only",
@@ -123,7 +123,7 @@
"postpack": "node ../../scripts/swap-publish-exports.mjs restore"
},
"dependencies": {
- "@codraoss/schema": "^0.9.5",
+ "@codraoss/schema": "*",
"jsonrepair": "^3.15.0",
"picomatch": "^4.0.5",
"zod": "^4.3.6"
diff --git a/packages/core/src/ports/queue.ts b/packages/core/src/ports/queue.ts
index 745a3375..9a554cda 100644
--- a/packages/core/src/ports/queue.ts
+++ b/packages/core/src/ports/queue.ts
@@ -1,3 +1,4 @@
export interface QueueProducer {
send(message: T, options?: { delaySeconds?: number }): Promise;
+ deleteJob?(jobId: string): Promise;
}
diff --git a/packages/db/CHANGELOG.md b/packages/db/CHANGELOG.md
deleted file mode 100644
index 049396b1..00000000
--- a/packages/db/CHANGELOG.md
+++ /dev/null
@@ -1,11 +0,0 @@
-# @codraoss/db
-
-## 0.9.5
-
-### Patch Changes
-
-- Publish `migrations/` and `scripts/`, which were excluded from the tarball, so an installed copy can create its schema. The runner now accepts `--extra-dir` or `CODRA_EXTRA_MIGRATIONS_DIR`: those migrations run after the built-in set inside the same transaction and advisory lock, and are tracked under an `extra:` prefix so filenames cannot collide with future core migrations. Env-file lookup checks the working directory first so it works when run from `node_modules`.
-- Updated dependencies
-- Updated dependencies
- - @codraoss/core@0.9.5
- - @codraoss/schema@0.9.5
diff --git a/packages/db/package.json b/packages/db/package.json
index 19ad1ca1..7ffc05e4 100644
--- a/packages/db/package.json
+++ b/packages/db/package.json
@@ -1,6 +1,6 @@
{
"name": "@codraoss/db",
- "version": "0.9.5",
+ "version": "0.9.12",
"description": "Codra's Postgres persistence layer behind repository interfaces.",
"author": "Devarshi Shimpi",
"license": "AGPL-3.0-only",
@@ -67,8 +67,8 @@
"postpack": "node ../../scripts/swap-publish-exports.mjs restore"
},
"dependencies": {
- "@codraoss/schema": "^0.9.5",
- "@codraoss/core": "^0.9.5",
+ "@codraoss/schema": "*",
+ "@codraoss/core": "*",
"postgres": "^3.4.9"
},
"devDependencies": {
diff --git a/packages/db/src/client.ts b/packages/db/src/client.ts
index 020f0235..a1af66bf 100644
--- a/packages/db/src/client.ts
+++ b/packages/db/src/client.ts
@@ -11,10 +11,11 @@ const dbStorage = new AsyncLocalStorage();
function createDbClient(env: DbEnv): DbClient {
const sql = postgres(env.HYPERDRIVE.connectionString, {
- max: 5,
+ max: process.env.DB_POOL_SIZE ? parseInt(process.env.DB_POOL_SIZE, 10) : 5,
fetch_types: false,
prepare: false,
onnotice: () => {},
+ ssl: env.HYPERDRIVE.connectionString.includes('sslmode=require') ? { rejectUnauthorized: false } : false,
});
return {
@@ -91,13 +92,14 @@ async function withStaleConnectionRecovery(env: DbEnv, op: (db: DbClient) =>
try {
return await op(getDb(env));
} catch (error) {
- if (env.workerMode === false || inScope || !isStaleConnectionError(error)) throw error;
+ if (inScope || !isStaleConnectionError(error)) throw error;
const connectionString = env.HYPERDRIVE.connectionString;
fallbackClients.delete(connectionString);
const fresh = createDbClient(env);
fallbackClients.set(connectionString, fresh);
- return op(fresh);
+
+ return await op(fresh);
}
}
diff --git a/packages/models/CHANGELOG.md b/packages/models/CHANGELOG.md
deleted file mode 100644
index 64c84674..00000000
--- a/packages/models/CHANGELOG.md
+++ /dev/null
@@ -1,16 +0,0 @@
-# @codraoss/models
-
-## 0.9.6
-
-### Patch Changes
-
-- Stop sending `propertyOrdering` in Gemini response grammars. The keyword belongs to the legacy OpenAPI-style `responseSchema`; inside `responseJsonSchema` the API rejects it with a bare 400 `invalid argument`, so every constrained Google review fell back to unconstrained decoding and frequently returned prose that failed the reviewable-output gate. Property declaration order already carries the ordering the grammar relied on.
-
-## 0.9.5
-
-### Patch Changes
-
-- Updated dependencies
-- Updated dependencies
- - @codraoss/core@0.9.5
- - @codraoss/schema@0.9.5
diff --git a/packages/models/package.json b/packages/models/package.json
index 5d18172b..0a494564 100644
--- a/packages/models/package.json
+++ b/packages/models/package.json
@@ -1,6 +1,6 @@
{
"name": "@codraoss/models",
- "version": "0.9.6",
+ "version": "0.9.12",
"description": "LLM provider adapters and model catalog for the Codra review engine.",
"author": "Devarshi Shimpi",
"license": "AGPL-3.0-only",
@@ -78,8 +78,8 @@
"postpack": "node ../../scripts/swap-publish-exports.mjs restore"
},
"dependencies": {
- "@codraoss/schema": "^0.9.5",
- "@codraoss/core": "^0.9.5"
+ "@codraoss/schema": "*",
+ "@codraoss/core": "*"
},
"devDependencies": {
"tsup": "^8.0.0"
diff --git a/packages/node-adapters/package.json b/packages/node-adapters/package.json
new file mode 100644
index 00000000..9041ab33
--- /dev/null
+++ b/packages/node-adapters/package.json
@@ -0,0 +1,58 @@
+{
+ "name": "@codraoss/node-adapters",
+ "version": "0.9.12",
+ "description": "Node.js platform adapters for Codra, including BullMQ, Redis, and Stateless Orchestration.",
+ "type": "module",
+ "main": "./src/index.ts",
+ "types": "./dist/index.d.ts",
+ "exports": {
+ ".": "./src/index.ts"
+ },
+ "publishConfig": {
+ "access": "public",
+ "main": "./dist/index.js",
+ "module": "./dist/index.js",
+ "types": "./dist/index.d.ts",
+ "exports": {
+ ".": {
+ "import": "./dist/index.js",
+ "types": "./dist/index.d.ts"
+ }
+ }
+ },
+ "files": [
+ "dist",
+ "LICENSE",
+ "README.md"
+ ],
+ "author": "Devarshi Shimpi",
+ "license": "AGPL-3.0-only",
+ "repository": {
+ "type": "git",
+ "url": "git+https://github.com/devarshishimpi/codra.git",
+ "directory": "packages/node-adapters"
+ },
+ "bugs": {
+ "url": "https://github.com/devarshishimpi/codra/issues"
+ },
+ "homepage": "https://codra.run",
+ "scripts": {
+ "build": "tsup",
+ "prepack": "node ../../scripts/swap-publish-exports.mjs promote",
+ "postpack": "node ../../scripts/swap-publish-exports.mjs restore",
+ "typecheck": "tsc -p tsconfig.json"
+ },
+ "dependencies": {
+ "@codraoss/api": "*",
+ "@codraoss/core": "*",
+ "@codraoss/db": "*",
+ "@codraoss/schema": "*",
+ "bullmq": "^6.3.8",
+ "ioredis": "^6.0.0",
+ "nanoid": "^5.0.7"
+ },
+ "devDependencies": {
+ "@types/node": "^22.0.0",
+ "tsup": "^8.0.0"
+ }
+}
diff --git a/packages/node-adapters/src/index.ts b/packages/node-adapters/src/index.ts
new file mode 100644
index 00000000..3bfd71af
--- /dev/null
+++ b/packages/node-adapters/src/index.ts
@@ -0,0 +1,6 @@
+export * from './node-orchestrator.js';
+export * from './platform.js';
+export * from './redis-kv.js';
+export * from './redis-queue.js';
+export * from './redis-session-store.js';
+export * from './worker.js';
diff --git a/apps/node/src/adapters/node-orchestrator.ts b/packages/node-adapters/src/node-orchestrator.ts
similarity index 100%
rename from apps/node/src/adapters/node-orchestrator.ts
rename to packages/node-adapters/src/node-orchestrator.ts
diff --git a/apps/node/src/adapters/platform.ts b/packages/node-adapters/src/platform.ts
similarity index 51%
rename from apps/node/src/adapters/platform.ts
rename to packages/node-adapters/src/platform.ts
index f3b8855b..da811954 100644
--- a/apps/node/src/adapters/platform.ts
+++ b/packages/node-adapters/src/platform.ts
@@ -1,10 +1,9 @@
import type { Clock, IdGenerator, KvStore } from '@codraoss/core/ports';
-import type { NodeAppBindings } from '../env';
-export function makeKvStore(env: NodeAppBindings): KvStore {
+export function makeKvStore(appKv: KvStore): KvStore {
return {
- get: (key) => env.APP_KV.get(key),
- put: (key, value, options) => env.APP_KV.put(key, value, options),
+ get: (key) => appKv.get(key),
+ put: (key, value, options) => appKv.put(key, value, options),
};
}
diff --git a/apps/node/src/adapters/redis-kv.ts b/packages/node-adapters/src/redis-kv.ts
similarity index 100%
rename from apps/node/src/adapters/redis-kv.ts
rename to packages/node-adapters/src/redis-kv.ts
diff --git a/packages/node-adapters/src/redis-queue.ts b/packages/node-adapters/src/redis-queue.ts
new file mode 100644
index 00000000..704ac38b
--- /dev/null
+++ b/packages/node-adapters/src/redis-queue.ts
@@ -0,0 +1,22 @@
+import type { QueueProducer } from '@codraoss/core/ports';
+import type { Queue } from 'bullmq';
+
+export class RedisQueueAdapter implements QueueProducer {
+ constructor(private readonly queue: Queue) {}
+
+ async send(message: T, options?: { delaySeconds?: number; jobId?: string }): Promise {
+ const jobOptions: any = options?.jobId ? { jobId: options.jobId } : {};
+ if (options?.delaySeconds) {
+ jobOptions.delay = options.delaySeconds * 1000;
+ }
+
+ await this.queue.add('review-job', message, jobOptions);
+ }
+
+ async deleteJob(jobId: string): Promise {
+ const bullMqJob = await this.queue.getJob(jobId);
+ if (bullMqJob) {
+ await bullMqJob.remove();
+ }
+ }
+}
diff --git a/apps/node/src/adapters/redis-session-store.ts b/packages/node-adapters/src/redis-session-store.ts
similarity index 87%
rename from apps/node/src/adapters/redis-session-store.ts
rename to packages/node-adapters/src/redis-session-store.ts
index d4c75e71..e8ad4fd9 100644
--- a/apps/node/src/adapters/redis-session-store.ts
+++ b/packages/node-adapters/src/redis-session-store.ts
@@ -22,7 +22,12 @@ export class RedisSessionStore implements SessionStore {
if (!sessionString) {
return null;
}
- return JSON.parse(sessionString) as DashboardSessionUser;
+ try {
+ return JSON.parse(sessionString) as DashboardSessionUser;
+ } catch {
+ // Return null if parsing fails (corrupted JSON)
+ return null;
+ }
}
async destroySession(token: string): Promise {
diff --git a/apps/node/src/worker.ts b/packages/node-adapters/src/worker.ts
similarity index 57%
rename from apps/node/src/worker.ts
rename to packages/node-adapters/src/worker.ts
index 3e3bebf4..dba5151c 100644
--- a/apps/node/src/worker.ts
+++ b/packages/node-adapters/src/worker.ts
@@ -1,15 +1,16 @@
import { Worker, type Job } from 'bullmq';
import { reviewJobMessageSchema, type ReviewJobMessage } from '@codraoss/schema';
-import { NodeOrchestrator } from './adapters/node-orchestrator';
-import { logger } from '@codraoss/api/logger';
-import type { NodeAppBindings } from './env';
-import Redis from 'ioredis';
-import { createReviewRuntime } from './runtime';
+import { NodeOrchestrator } from './node-orchestrator';
+import type { ReviewRuntime } from '@codraoss/core/ports';
import type { QueueProducer } from '@codraoss/core/ports';
+import type Redis from 'ioredis';
-export function startWorker(env: NodeAppBindings, redisUrl: string, queue: QueueProducer): Worker {
- const connection = new Redis(redisUrl, { maxRetriesPerRequest: null });
-
+export function startWorker(
+ redisConnection: Redis,
+ queue: QueueProducer,
+ createRuntime: () => ReviewRuntime,
+ logger: { info: (msg: string) => void, error: (msg: string, err?: any) => void }
+): Worker {
const worker = new Worker(
'codra-reviews',
async (job: Job) => {
@@ -19,11 +20,12 @@ export function startWorker(env: NodeAppBindings, redisUrl: string, queue: Queue
throw new Error('Invalid job payload');
}
- const reviewRuntime = createReviewRuntime(env);
- const orchestrator = new NodeOrchestrator(reviewRuntime, queue);
+ const reviewRuntime = createRuntime();
+ // Need to cast to any since DbEnv is dynamically merged downstream
+ const orchestrator = new NodeOrchestrator(reviewRuntime as any, queue);
await orchestrator.startReviewJob(job.id ?? 'unknown', parseResult.data);
},
- { connection }
+ { connection: redisConnection }
);
worker.on('completed', (job) => {
diff --git a/packages/node-adapters/tsconfig.json b/packages/node-adapters/tsconfig.json
new file mode 100644
index 00000000..391e21ce
--- /dev/null
+++ b/packages/node-adapters/tsconfig.json
@@ -0,0 +1,10 @@
+{
+ "extends": "../../tsconfig.base.json",
+ "compilerOptions": {
+ "outDir": "dist",
+ "rootDir": "src",
+ "types": ["node"]
+ },
+ "include": ["src/**/*"],
+ "exclude": ["node_modules", "dist"]
+}
diff --git a/packages/node-adapters/tsup.config.json b/packages/node-adapters/tsup.config.json
new file mode 100644
index 00000000..28a3fea0
--- /dev/null
+++ b/packages/node-adapters/tsup.config.json
@@ -0,0 +1,10 @@
+{
+ "entry": ["src/index.ts"],
+ "format": ["esm"],
+ "outDir": "dist",
+ "clean": true,
+ "sourcemap": true,
+ "splitting": false,
+ "target": "node20",
+ "noExternal": []
+}
diff --git a/packages/provider-github/CHANGELOG.md b/packages/provider-github/CHANGELOG.md
deleted file mode 100644
index f3189ffd..00000000
--- a/packages/provider-github/CHANGELOG.md
+++ /dev/null
@@ -1,10 +0,0 @@
-# @codraoss/provider-github
-
-## 0.9.5
-
-### Patch Changes
-
-- Updated dependencies
-- Updated dependencies
- - @codraoss/core@0.9.5
- - @codraoss/schema@0.9.5
diff --git a/packages/provider-github/package.json b/packages/provider-github/package.json
index 1d4fec1e..2002e889 100644
--- a/packages/provider-github/package.json
+++ b/packages/provider-github/package.json
@@ -1,6 +1,6 @@
{
"name": "@codraoss/provider-github",
- "version": "0.9.5",
+ "version": "0.9.12",
"description": "GitHub git-provider adapter for Codra: App auth, webhooks, OAuth, and review posting.",
"author": "Devarshi Shimpi",
"license": "AGPL-3.0-only",
@@ -53,8 +53,8 @@
"postpack": "node ../../scripts/swap-publish-exports.mjs restore"
},
"dependencies": {
- "@codraoss/core": "^0.9.5",
- "@codraoss/schema": "^0.9.5"
+ "@codraoss/core": "*",
+ "@codraoss/schema": "*"
},
"devDependencies": {
"tsup": "^8.0.0"
diff --git a/packages/schema/CHANGELOG.md b/packages/schema/CHANGELOG.md
deleted file mode 100644
index 4a9d2817..00000000
--- a/packages/schema/CHANGELOG.md
+++ /dev/null
@@ -1,7 +0,0 @@
-# @codraoss/schema
-
-## 0.9.5
-
-### Patch Changes
-
-- Export `apiActions`, the vocabulary of permission identifiers the API checks, and `ApiAction` as an open union so consumers can add their own names. `AuthSessionResponse` gains an optional `permissions` field; omitting it means every action is allowed.
diff --git a/packages/schema/package.json b/packages/schema/package.json
index fd0ce87b..f1ddceae 100644
--- a/packages/schema/package.json
+++ b/packages/schema/package.json
@@ -1,6 +1,6 @@
{
"name": "@codraoss/schema",
- "version": "0.9.5",
+ "version": "0.9.12",
"description": "Shared types and Zod contracts for Codra, the open-source code review engine.",
"author": "Devarshi Shimpi",
"license": "AGPL-3.0-only",
diff --git a/packages/ui/CHANGELOG.md b/packages/ui/CHANGELOG.md
deleted file mode 100644
index f7b7254e..00000000
--- a/packages/ui/CHANGELOG.md
+++ /dev/null
@@ -1,9 +0,0 @@
-# @codraoss/ui
-
-## 0.9.5
-
-### Patch Changes
-
-- Ship the design tokens as `@codraoss/ui/styles`. The components reference `--ui-*`, `--btn-primary-*`, `surface`, `skeleton`, `ui-panel`, `ui-well` and `ui-font-*`, none of which were published before, so the package rendered unstyled outside this repository. Import it after `@import "tailwindcss"` and include the package in your Tailwind source globs.
-- Updated dependencies
- - @codraoss/schema@0.9.5
diff --git a/packages/ui/package.json b/packages/ui/package.json
index b03debb3..45f03693 100644
--- a/packages/ui/package.json
+++ b/packages/ui/package.json
@@ -1,6 +1,6 @@
{
"name": "@codraoss/ui",
- "version": "0.9.10",
+ "version": "0.9.12",
"description": "Codra's reusable React design-system primitives and hooks.",
"author": "Devarshi Shimpi",
"license": "AGPL-3.0-only",
@@ -105,7 +105,7 @@
"sonner": ">=2.0.0"
},
"dependencies": {
- "@codraoss/schema": "^0.9.5",
+ "@codraoss/schema": "*",
"@base-ui/react": "^1.6.0",
"class-variance-authority": "^0.7.1",
"clsx": "^2.1.1",
diff --git a/scripts/swap-publish-exports.mjs b/scripts/swap-publish-exports.mjs
index 958363eb..886f69cc 100644
--- a/scripts/swap-publish-exports.mjs
+++ b/scripts/swap-publish-exports.mjs
@@ -12,6 +12,7 @@ if (mode === 'promote') {
for (const field of PROMOTABLE) {
if (fields[field] !== undefined) {
pkg[field] = fields[field];
+ delete pkg.publishConfig[field]; // Remove to prevent npm warnings
}
}
From 046a1780fe7664dbf0c195c524d9b77045066310 Mon Sep 17 00:00:00 2001
From: Devarshi Shimpi
Date: Tue, 22 Sep 2026 23:19:50 +0530
Subject: [PATCH 05/16] chore: upgrade dependencies across monorepo
---
apps/node/package.json | 8 +-
apps/node/src/index.ts | 15 +-
apps/worker/package.json | 2 +-
package-lock.json | 1676 ++++++++++++++++---------
package.json | 31 +-
packages/api/package.json | 6 +-
packages/core/package.json | 4 +-
packages/db/package.json | 4 +-
packages/models/package.json | 2 +-
packages/node-adapters/package.json | 6 +-
packages/node-adapters/src/worker.ts | 3 +-
packages/provider-github/package.json | 2 +-
packages/schema/package.json | 2 +-
packages/ui/package.json | 4 +-
14 files changed, 1136 insertions(+), 629 deletions(-)
diff --git a/apps/node/package.json b/apps/node/package.json
index 895968ed..6a062909 100644
--- a/apps/node/package.json
+++ b/apps/node/package.json
@@ -17,14 +17,14 @@
"@codraoss/node-adapters": "*",
"@codraoss/provider-github": "*",
"@codraoss/schema": "*",
- "@hono/node-server": "^1.11.1",
+ "@hono/node-server": "^1.11.5",
"bullmq": "^6.3.8",
- "dotenv": "^16.4.5",
- "hono": "^4.6.0",
+ "dotenv": "^16.4.7",
+ "hono": "^4.6.20",
"ioredis": "^6.0.0"
},
"devDependencies": {
- "@types/node": "^20.12.12",
+ "@types/node": "^20.12.14",
"tsup": "^8.0.2"
}
}
diff --git a/apps/node/src/index.ts b/apps/node/src/index.ts
index ca7f9795..5649148d 100644
--- a/apps/node/src/index.ts
+++ b/apps/node/src/index.ts
@@ -9,7 +9,7 @@ import { runWithDb } from '@codraoss/db/client';
import { NodeOrchestrator, RedisKVAdapter, RedisQueueAdapter, RedisSessionStore, startWorker } from '@codraoss/node-adapters';
import { createNodeApiDeps } from './api-deps';
-import { createNodeEnv, NodeAppBindings } from './env';
+import { createNodeEnv, type NodeAppBindings } from './env';
import { logger } from '@codraoss/api/logger';
import Redis from 'ioredis';
import { Queue } from 'bullmq';
@@ -35,9 +35,9 @@ const reviewQueue = new Queue('codra-reviews', { connection: redisClient });
const stubs = {
SESSION_STORE: new RedisSessionStore(redisClient),
- KV_STORE: new RedisKVAdapter(redisClient),
+ APP_KV: new RedisKVAdapter(redisClient),
REVIEW_QUEUE: new RedisQueueAdapter(reviewQueue),
- REVIEW_ORCHESTRATOR: undefined, // Will be set to NodeOrchestrator below
+ REVIEW_ORCHESTRATOR: undefined as NodeOrchestrator | undefined,
};
const env: NodeAppBindings = createNodeEnv(stubs);
@@ -86,12 +86,9 @@ if (process.env.START_API !== 'false') {
// Add server to shutdown sequence
if (server) {
const originalClose = server.close;
- server.close = () => new Promise(resolve => {
- originalClose(() => {
- logger.info('HTTP server closed.');
- resolve();
- });
- });
+ server.close = () => originalClose(() => {
+ logger.info('HTTP server closed.');
+ }) as any;
}
}
diff --git a/apps/worker/package.json b/apps/worker/package.json
index 19f3f136..5f5629db 100644
--- a/apps/worker/package.json
+++ b/apps/worker/package.json
@@ -10,7 +10,7 @@
"@codraoss/models": "*",
"@codraoss/provider-github": "*",
"@codraoss/schema": "*",
- "hono": "^4.12.25"
+ "hono": "^4.12.34"
},
"devDependencies": {
"@cloudflare/workers-types": "^4.20250109.0",
diff --git a/package-lock.json b/package-lock.json
index 174725ae..1ad9c43d 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -23,7 +23,7 @@
"@codraoss/ui": "*",
"class-variance-authority": "^0.7.1",
"clsx": "^2.1.1",
- "hono": "^4.12.25",
+ "hono": "^4.12.34",
"jsonrepair": "^3.15.0",
"lenis": "^1.3.26",
"lucide-react": "^1.8.0",
@@ -33,25 +33,25 @@
"react": "^19.2.8",
"react-dom": "^19.2.8",
"react-markdown": "^10.1.0",
- "react-router-dom": "^7.18.2",
+ "react-router-dom": "^7.18.4",
"recharts": "^3.8.1",
"rehype-raw": "^7.0.0",
"rehype-sanitize": "^6.0.0",
"remark-gfm": "^4.0.1",
- "sonner": "^2.0.7",
- "sugar-high": "^2.0.0",
+ "sonner": "^2.0.8",
+ "sugar-high": "^2.0.3",
"tailwind-merge": "^3.5.0",
"zod": "^4.3.6"
},
"devDependencies": {
"@arethetypeswrong/cli": "^0.18.5",
"@eslint/js": "^10.0.1",
- "@tailwindcss/vite": "^4.2.2",
- "@testing-library/dom": "^10.4.1",
- "@testing-library/react": "^16.3.2",
- "@types/node": "^25.6.0",
+ "@tailwindcss/vite": "^4.2.4",
+ "@testing-library/dom": "^10.4.2",
+ "@testing-library/react": "^16.3.3",
+ "@types/node": "^25.6.2",
"@types/react": "^19.2.18",
- "@types/react-dom": "^19.2.4",
+ "@types/react-dom": "^19.2.7",
"@vitejs/plugin-react": "^6.0.5",
"chalk": "^5.6.2",
"concurrently": "^9.2.4",
@@ -62,13 +62,13 @@
"jsdom": "^29.0.2",
"ora": "^9.4.1",
"prompts": "^2.4.2",
- "publint": "^0.3.23",
- "tailwindcss": "^4.2.2",
+ "publint": "^0.3.24",
+ "tailwindcss": "^4.2.4",
"tsup": "^8.5.1",
- "typescript": "^6.0.2",
+ "typescript": "^6.0.3",
"typescript-eslint": "^8.66.0",
- "vite": "^8.0.8",
- "vitest": "^4.1.10",
+ "vite": "^8.0.16",
+ "vitest": "^4.1.11",
"wrangler": "^4.114.0"
}
},
@@ -83,14 +83,14 @@
"@codraoss/node-adapters": "*",
"@codraoss/provider-github": "*",
"@codraoss/schema": "*",
- "@hono/node-server": "^1.11.1",
+ "@hono/node-server": "^1.11.5",
"bullmq": "^6.3.8",
- "dotenv": "^16.4.5",
- "hono": "^4.6.0",
+ "dotenv": "^16.4.7",
+ "hono": "^4.6.20",
"ioredis": "^6.0.0"
},
"devDependencies": {
- "@types/node": "^20.12.12",
+ "@types/node": "^20.12.14",
"tsup": "^8.0.2"
}
},
@@ -121,7 +121,7 @@
"@codraoss/models": "*",
"@codraoss/provider-github": "*",
"@codraoss/schema": "*",
- "hono": "^4.12.25"
+ "hono": "^4.12.34"
},
"devDependencies": {
"@cloudflare/workers-types": "^4.20250109.0",
@@ -246,6 +246,8 @@
},
"node_modules/@asamuzakjp/css-color": {
"version": "5.1.11",
+ "resolved": "https://registry.npmjs.org/@asamuzakjp/css-color/-/css-color-5.1.11.tgz",
+ "integrity": "sha512-KVw6qIiCTUQhByfTd78h2yD1/00waTmm9uy/R7Ck/ctUyAPj+AEDLkQIdJW0T8+qGgj3j5bpNKK7Q3G+LedJWg==",
"dev": true,
"license": "MIT",
"dependencies": {
@@ -261,6 +263,8 @@
},
"node_modules/@asamuzakjp/dom-selector": {
"version": "7.1.1",
+ "resolved": "https://registry.npmjs.org/@asamuzakjp/dom-selector/-/dom-selector-7.1.1.tgz",
+ "integrity": "sha512-67RZDnYRc8H/8MLDgQCDE//zoqVFwajkepHZgmXrbwybzXOEwOWGPYGmALYl9J2DOLfFPPs6kKCqmbzV895hTQ==",
"dev": true,
"license": "MIT",
"dependencies": {
@@ -276,6 +280,8 @@
},
"node_modules/@asamuzakjp/generational-cache": {
"version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/@asamuzakjp/generational-cache/-/generational-cache-1.0.1.tgz",
+ "integrity": "sha512-wajfB8KqzMCN2KGNFdLkReeHncd0AslUSrvHVvvYWuU8ghncRJoA50kT3zP9MVL0+9g4/67H+cdvBskj9THPzg==",
"dev": true,
"license": "MIT",
"engines": {
@@ -284,6 +290,8 @@
},
"node_modules/@asamuzakjp/nwsapi": {
"version": "2.3.9",
+ "resolved": "https://registry.npmjs.org/@asamuzakjp/nwsapi/-/nwsapi-2.3.9.tgz",
+ "integrity": "sha512-n8GuYSrI9bF7FFZ/SjhwevlHc8xaVlb/7HmHelnc/PZXBD2ZR49NnN9sMMuDdEGPeeRQ5d0hqlSlEpgCX3Wl0Q==",
"dev": true,
"license": "MIT"
},
@@ -561,15 +569,15 @@
}
},
"node_modules/@base-ui/react": {
- "version": "1.6.0",
- "resolved": "https://registry.npmjs.org/@base-ui/react/-/react-1.6.0.tgz",
- "integrity": "sha512-/jzjTWJYXhRFO45Bev9lc3cHbmjzCMpUqbMZ2AgKy/z25mY9B6shGSNcXcjQar9n5doM0KYW1W8fcFv2jZBuMw==",
+ "version": "1.8.0",
+ "resolved": "https://registry.npmjs.org/@base-ui/react/-/react-1.8.0.tgz",
+ "integrity": "sha512-P0/1sxo6SBVZOklKMIedvTWqw2s2IQzi9x5bIVsXu980cuSOD4NeuRSs+/L7LZQfDkZP/uRZyGPyfFl/B1oH+Q==",
"license": "MIT",
"dependencies": {
- "@babel/runtime": "^7.29.2",
- "@base-ui/utils": "0.3.1",
- "@floating-ui/react-dom": "^2.1.8",
- "@floating-ui/utils": "^0.2.11",
+ "@babel/runtime": "^7.29.7",
+ "@base-ui/utils": "0.4.0",
+ "@floating-ui/react-dom": "^2.1.9",
+ "@floating-ui/utils": "^0.2.12",
"use-sync-external-store": "^1.6.0"
},
"engines": {
@@ -599,13 +607,13 @@
}
},
"node_modules/@base-ui/utils": {
- "version": "0.3.1",
- "resolved": "https://registry.npmjs.org/@base-ui/utils/-/utils-0.3.1.tgz",
- "integrity": "sha512-gFFiltORVmW/N6IILTGxizP3PBpVpysqML1ALY5Vk0mH+7faVkCknOU31goYHN5Aoek2dkjxva1XOD2Ce9WuIg==",
+ "version": "0.4.0",
+ "resolved": "https://registry.npmjs.org/@base-ui/utils/-/utils-0.4.0.tgz",
+ "integrity": "sha512-bO9fz25kKtPf+aZVyfQrC0PDmJdmVni31W2hCS5/Owb+inwdIL3XU26pCPRPlt4LSxZrBgLwubXQXQlKaFEZzw==",
"license": "MIT",
"dependencies": {
- "@babel/runtime": "^7.29.2",
- "@floating-ui/utils": "^0.2.11",
+ "@babel/runtime": "^7.29.7",
+ "@floating-ui/utils": "^0.2.12",
"reselect": "^5.2.0",
"use-sync-external-store": "^1.6.0"
},
@@ -638,6 +646,30 @@
"specificity": "bin/cli.js"
}
},
+ "node_modules/@cacheable/memory": {
+ "version": "2.2.0",
+ "resolved": "https://registry.npmjs.org/@cacheable/memory/-/memory-2.2.0.tgz",
+ "integrity": "sha512-CTLKqLItRCEixEAewD3/j9DB3/o96gpTPD4eJ1v+DGOlxZRZncRQkGYqqnAGCscYd6RNeXfGeiuCphsPtqyIfQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@cacheable/utils": "^2.5.0",
+ "@keyv/bigmap": "^1.3.1",
+ "hookified": "^1.15.1",
+ "keyv": "^5.6.0"
+ }
+ },
+ "node_modules/@cacheable/utils": {
+ "version": "2.5.0",
+ "resolved": "https://registry.npmjs.org/@cacheable/utils/-/utils-2.5.0.tgz",
+ "integrity": "sha512-buipgOVDkkPXNR5+xBpDw7Zk2n1EvU7qBJCNUcL7rhQ//kfpOXPAvQ511Os0vpLYJ1pZnvudNytkQt2hst3wqA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "hashery": "^1.5.1",
+ "keyv": "^5.6.0"
+ }
+ },
"node_modules/@cloudflare/kv-asset-handler": {
"version": "0.5.0",
"dev": true,
@@ -647,7 +679,9 @@
}
},
"node_modules/@cloudflare/unenv-preset": {
- "version": "2.16.1",
+ "version": "2.16.2",
+ "resolved": "https://registry.npmjs.org/@cloudflare/unenv-preset/-/unenv-preset-2.16.2.tgz",
+ "integrity": "sha512-JBP1+Z7ZSNG/d4mRP+y8VC5dka3tZVMLEZRvS+rzQ4DGV1EoxRFQckcJTTkXbHSQiTj0DtNI01Zwb/V2fX0mvQ==",
"dev": true,
"license": "MIT OR Apache-2.0",
"peerDependencies": {
@@ -661,9 +695,9 @@
}
},
"node_modules/@cloudflare/workerd-darwin-64": {
- "version": "1.20260918.1",
- "resolved": "https://registry.npmjs.org/@cloudflare/workerd-darwin-64/-/workerd-darwin-64-1.20260918.1.tgz",
- "integrity": "sha512-H5Em6Wd0jjxaloYh2rp+WLBl2eWbkk7nSP1svGt6K1RSv/rNVqmKdpjZPJTBSavOmeYGa88qvtOWwS+33OHTqQ==",
+ "version": "1.20260921.1",
+ "resolved": "https://registry.npmjs.org/@cloudflare/workerd-darwin-64/-/workerd-darwin-64-1.20260921.1.tgz",
+ "integrity": "sha512-3iB2WnYOlZ29T+1zhCwbHFExCBp6E9bgmDUMryATYwrIGEQ1YbvR78m4ydm56XKN/d/yF3803ivMGfZMYDtiMg==",
"cpu": [
"x64"
],
@@ -678,9 +712,9 @@
}
},
"node_modules/@cloudflare/workerd-darwin-arm64": {
- "version": "1.20260918.1",
- "resolved": "https://registry.npmjs.org/@cloudflare/workerd-darwin-arm64/-/workerd-darwin-arm64-1.20260918.1.tgz",
- "integrity": "sha512-CR9JRZEQo93fNgBVF4Df2H2/VYO4n7rxSseSwCVv3bJQEb0huADUSCj2FK4ipxar8ToOEB4wawyw0vJo5U/rQQ==",
+ "version": "1.20260921.1",
+ "resolved": "https://registry.npmjs.org/@cloudflare/workerd-darwin-arm64/-/workerd-darwin-arm64-1.20260921.1.tgz",
+ "integrity": "sha512-FpqVR7IQXVBmGtajyonEmhmb5UAsmV7dTaIkpemmHZXHEw7uYpkhkzKPjc4BOPhNQy8iwt2p+RZBPMY3Y7/bvQ==",
"cpu": [
"arm64"
],
@@ -695,9 +729,9 @@
}
},
"node_modules/@cloudflare/workerd-linux-64": {
- "version": "1.20260918.1",
- "resolved": "https://registry.npmjs.org/@cloudflare/workerd-linux-64/-/workerd-linux-64-1.20260918.1.tgz",
- "integrity": "sha512-UQ2nnY3qpXLzQ80frmWO+8HvtqyWaQILe8QYZwpemdjT+sqwCz4Dz+0/WVkFco0v/04kIIqikVeLTY/7gEhmkw==",
+ "version": "1.20260921.1",
+ "resolved": "https://registry.npmjs.org/@cloudflare/workerd-linux-64/-/workerd-linux-64-1.20260921.1.tgz",
+ "integrity": "sha512-riAJIohaVp5A8Sqy4yKlzHOaLPOICMf5oey+jC2rm45RVT+wK8+7UU0d31Dy/02Nc8YUkobAFwNVjX06P8WQ5g==",
"cpu": [
"x64"
],
@@ -712,9 +746,9 @@
}
},
"node_modules/@cloudflare/workerd-linux-arm64": {
- "version": "1.20260918.1",
- "resolved": "https://registry.npmjs.org/@cloudflare/workerd-linux-arm64/-/workerd-linux-arm64-1.20260918.1.tgz",
- "integrity": "sha512-4rib51MaLNWweUIUxM/Xj558M5QmyZoBSf0ffv+lYah5VTrvwnez3XGxX72pElnBKHROvAPOi5msQ5Ts8JSI0A==",
+ "version": "1.20260921.1",
+ "resolved": "https://registry.npmjs.org/@cloudflare/workerd-linux-arm64/-/workerd-linux-arm64-1.20260921.1.tgz",
+ "integrity": "sha512-tnJu08tT7s0XWDqp3O0H/vCp0voy9OqVAzspb89biMo1dh8IiEpnyXnoPmdJ7H4qBnXCmXgy0kuEphuvpDPj9w==",
"cpu": [
"arm64"
],
@@ -729,9 +763,9 @@
}
},
"node_modules/@cloudflare/workerd-windows-64": {
- "version": "1.20260918.1",
- "resolved": "https://registry.npmjs.org/@cloudflare/workerd-windows-64/-/workerd-windows-64-1.20260918.1.tgz",
- "integrity": "sha512-sATrMx5ShYYgmgUGrcTmvsFSJBFuN95NEkX3xwb1qk8w1A6h5N11sea7yN2IeibwPyPmXKjWNjXOno0hZAM71Q==",
+ "version": "1.20260921.1",
+ "resolved": "https://registry.npmjs.org/@cloudflare/workerd-windows-64/-/workerd-windows-64-1.20260921.1.tgz",
+ "integrity": "sha512-VgNcRPstoZMb1G94JTrx+jU24GtkkazNfox0gnF/2fkuXpcfW/M0e0xvdMovYfwt8ZxG5AB2ZNvanD6ufBwiuQ==",
"cpu": [
"x64"
],
@@ -821,7 +855,9 @@
}
},
"node_modules/@csstools/color-helpers": {
- "version": "6.1.0",
+ "version": "6.1.1",
+ "resolved": "https://registry.npmjs.org/@csstools/color-helpers/-/color-helpers-6.1.1.tgz",
+ "integrity": "sha512-gLNsunvwf3mCi5u5o46/Z/JcJMnhbHSaZ69rkgPzNM3J4s8hWwpPUQB6/tt0EDFyCiWzxANlx+2LJwpYj4zS1w==",
"dev": true,
"funding": [
{
@@ -839,7 +875,9 @@
}
},
"node_modules/@csstools/css-calc": {
- "version": "3.2.1",
+ "version": "3.4.0",
+ "resolved": "https://registry.npmjs.org/@csstools/css-calc/-/css-calc-3.4.0.tgz",
+ "integrity": "sha512-XQKj5B7QiZcHiegCOCAzcAOJdhGgWOHbbu62h5e5mkHnn8lWcfiJhllkqWmxu5zWR9jucPHuo1iTB56P033hcg==",
"dev": true,
"funding": [
{
@@ -861,7 +899,9 @@
}
},
"node_modules/@csstools/css-color-parser": {
- "version": "4.1.9",
+ "version": "4.2.3",
+ "resolved": "https://registry.npmjs.org/@csstools/css-color-parser/-/css-color-parser-4.2.3.tgz",
+ "integrity": "sha512-y4LpL+lmpuyKDiEFq2PnZUVFdAjsoB/qQJod79yLNokXyW7jewi+/WJ69EfItj8A2unWtxXnGjw6LYXgXu5ZjA==",
"dev": true,
"funding": [
{
@@ -875,8 +915,8 @@
],
"license": "MIT",
"dependencies": {
- "@csstools/color-helpers": "^6.1.0",
- "@csstools/css-calc": "^3.2.1"
+ "@csstools/color-helpers": "^6.1.1",
+ "@csstools/css-calc": "^3.4.0"
},
"engines": {
"node": ">=20.19.0"
@@ -888,6 +928,8 @@
},
"node_modules/@csstools/css-parser-algorithms": {
"version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/@csstools/css-parser-algorithms/-/css-parser-algorithms-4.0.0.tgz",
+ "integrity": "sha512-+B87qS7fIG3L5h3qwJ/IFbjoVoOe/bpOdh9hAjXbvx0o8ImEmUsGXN0inFOnk2ChCFgqkkGFQ+TpM5rbhkKe4w==",
"dev": true,
"funding": [
{
@@ -908,7 +950,9 @@
}
},
"node_modules/@csstools/css-syntax-patches-for-csstree": {
- "version": "1.1.6",
+ "version": "1.1.14",
+ "resolved": "https://registry.npmjs.org/@csstools/css-syntax-patches-for-csstree/-/css-syntax-patches-for-csstree-1.1.14.tgz",
+ "integrity": "sha512-HpbVXyrofRXpHpgkNIjU/3EWR4WJvOkO3emNK/L6X/mTJU7bGUI3AkkpoTNXznQLp0KRjLHELTGeKI5dIkI9JQ==",
"dev": true,
"funding": [
{
@@ -931,7 +975,9 @@
}
},
"node_modules/@csstools/css-tokenizer": {
- "version": "4.0.0",
+ "version": "4.0.1",
+ "resolved": "https://registry.npmjs.org/@csstools/css-tokenizer/-/css-tokenizer-4.0.1.tgz",
+ "integrity": "sha512-bPlN9S9O1A0euCpEWE4qnvB5YDuyYVsUTrxSgmAM1Is0j4tICHoVyOVAXfWMP/kS9ZrjvyIXWV2PmomiAXXqOw==",
"dev": true,
"funding": [
{
@@ -961,9 +1007,9 @@
}
},
"node_modules/@emnapi/runtime": {
- "version": "1.11.1",
- "resolved": "https://registry.npmjs.org/@emnapi/runtime/-/runtime-1.11.1.tgz",
- "integrity": "sha512-vgj7R3y3Wgx24IQaGPA/R6YFXLHVMOZ0uVEyIQPaWs+rd1AzfEMXlAC22FYwO1XkKR6NPsq7mUandH8oIRdZFw==",
+ "version": "1.11.3",
+ "resolved": "https://registry.npmjs.org/@emnapi/runtime/-/runtime-1.11.3.tgz",
+ "integrity": "sha512-Xz4Tpyki7XyrpbUK1jR1AhdAdaXyhhY4lZ3neLodmhpuWfy2PAQN5B46sAiU4liOXGLkHypn/qU+jvfWSCYYLA==",
"dev": true,
"license": "MIT",
"optional": true,
@@ -1537,9 +1583,9 @@
}
},
"node_modules/@eslint/plugin-kit": {
- "version": "0.7.2",
- "resolved": "https://registry.npmjs.org/@eslint/plugin-kit/-/plugin-kit-0.7.2.tgz",
- "integrity": "sha512-+CNAzxglkrpNf/kKywqQfk74QjtceuOE7Qm+AF8miRvPF/wmmK5+OJOgVh3AVTT3RP2mH3+FOaxlE5v72owk0A==",
+ "version": "0.7.3",
+ "resolved": "https://registry.npmjs.org/@eslint/plugin-kit/-/plugin-kit-0.7.3.tgz",
+ "integrity": "sha512-IkO+/KEUvwbVpiURZg+P7zF74z5Jxe0UgJxVni+RtoHQ6IZieXaO02kmadomap/q+l6bc/jdPGGqTjhuZnuz1Q==",
"dev": true,
"license": "Apache-2.0",
"dependencies": {
@@ -1567,25 +1613,31 @@
}
},
"node_modules/@floating-ui/core": {
- "version": "1.7.5",
+ "version": "1.8.0",
+ "resolved": "https://registry.npmjs.org/@floating-ui/core/-/core-1.8.0.tgz",
+ "integrity": "sha512-0CIZ5itps/8x7BG8dEIhs53BvCUH2PCoogtakwRTut+Arm58sJooJ0AuZhLw2HJYIR5cMLNPBSS728sPho2khQ==",
"license": "MIT",
"dependencies": {
- "@floating-ui/utils": "^0.2.11"
+ "@floating-ui/utils": "^0.2.12"
}
},
"node_modules/@floating-ui/dom": {
- "version": "1.7.6",
+ "version": "1.8.0",
+ "resolved": "https://registry.npmjs.org/@floating-ui/dom/-/dom-1.8.0.tgz",
+ "integrity": "sha512-yXSrzeHZBTZadLOlfyhCkJHNeLJnHRnRInwdZ40L7ZiaAtrBwoYlsDrX3v5zB1Utk7CLfzcOVnVVWoXEky7Ceg==",
"license": "MIT",
"dependencies": {
- "@floating-ui/core": "^1.7.5",
- "@floating-ui/utils": "^0.2.11"
+ "@floating-ui/core": "^1.8.0",
+ "@floating-ui/utils": "^0.2.12"
}
},
"node_modules/@floating-ui/react-dom": {
- "version": "2.1.8",
+ "version": "2.1.9",
+ "resolved": "https://registry.npmjs.org/@floating-ui/react-dom/-/react-dom-2.1.9.tgz",
+ "integrity": "sha512-JDjEFGCpImxDCA7JJKviA0M9+RtmJdj0m/NVU5IMgBK+AmZouAQQ7/+2GLH0GXXY0YMw9oXPB8hKdbPYg5QLYg==",
"license": "MIT",
"dependencies": {
- "@floating-ui/dom": "^1.7.6"
+ "@floating-ui/dom": "^1.8.0"
},
"peerDependencies": {
"react": ">=16.8.0",
@@ -1593,7 +1645,9 @@
}
},
"node_modules/@floating-ui/utils": {
- "version": "0.2.11",
+ "version": "0.2.12",
+ "resolved": "https://registry.npmjs.org/@floating-ui/utils/-/utils-0.2.12.tgz",
+ "integrity": "sha512-HpCo8tmWzLVad5s2d19EhAz5zqrrQ6s69qd6moPMQvkOuSwDT1YgRfWSVuc4ennqrgv3OHppiOGMQ7oC13yIww==",
"license": "MIT"
},
"node_modules/@hono/node-server": {
@@ -2169,17 +2223,6 @@
"url": "https://opencollective.com/libvips"
}
},
- "node_modules/@img/sharp-wasm32/node_modules/@emnapi/runtime": {
- "version": "1.11.3",
- "resolved": "https://registry.npmjs.org/@emnapi/runtime/-/runtime-1.11.3.tgz",
- "integrity": "sha512-Xz4Tpyki7XyrpbUK1jR1AhdAdaXyhhY4lZ3neLodmhpuWfy2PAQN5B46sAiU4liOXGLkHypn/qU+jvfWSCYYLA==",
- "dev": true,
- "license": "MIT",
- "optional": true,
- "dependencies": {
- "tslib": "^2.4.0"
- }
- },
"node_modules/@img/sharp-webcontainers-wasm32": {
"version": "0.35.4",
"resolved": "https://registry.npmjs.org/@img/sharp-webcontainers-wasm32/-/sharp-webcontainers-wasm32-0.35.4.tgz",
@@ -2293,7 +2336,9 @@
}
},
"node_modules/@jridgewell/sourcemap-codec": {
- "version": "1.5.5",
+ "version": "1.6.0",
+ "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.6.0.tgz",
+ "integrity": "sha512-T7jf+5zgsZHwNJ4lvQ7/aezbyk0nNX+zJVWpmHA7VYsEx7a7qr5Rg5IbtJFqkgze5Y2sruq1RUY8Q837Od7iFw==",
"dev": true,
"license": "MIT"
},
@@ -2306,6 +2351,30 @@
"@jridgewell/sourcemap-codec": "^1.4.14"
}
},
+ "node_modules/@keyv/bigmap": {
+ "version": "1.3.1",
+ "resolved": "https://registry.npmjs.org/@keyv/bigmap/-/bigmap-1.3.1.tgz",
+ "integrity": "sha512-WbzE9sdmQtKy8vrNPa9BRnwZh5UF4s1KTmSK0KUVLo3eff5BlQNNWDnFOouNpKfPKDnms9xynJjsMYjMaT/aFQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "hashery": "^1.4.0",
+ "hookified": "^1.15.0"
+ },
+ "engines": {
+ "node": ">= 18"
+ },
+ "peerDependencies": {
+ "keyv": "^5.6.0"
+ }
+ },
+ "node_modules/@keyv/serialize": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/@keyv/serialize/-/serialize-1.1.1.tgz",
+ "integrity": "sha512-dXn3FZhPv0US+7dtJsIi2R+c7qWYiReoEh5zUntWCf4oSpMNib8FDhSoed6m3QyZdx5hK7iLFkYk3rNxwt8vTA==",
+ "dev": true,
+ "license": "MIT"
+ },
"node_modules/@loaderkit/resolve": {
"version": "1.0.6",
"resolved": "https://registry.npmjs.org/@loaderkit/resolve/-/resolve-1.0.6.tgz",
@@ -2437,11 +2506,13 @@
}
},
"node_modules/@oxc-project/types": {
- "version": "0.137.0",
+ "version": "0.150.0",
+ "resolved": "https://registry.npmjs.org/@oxc-project/types/-/types-0.150.0.tgz",
+ "integrity": "sha512-rDS5/31E9HfPl/CIzGrn0DOlvBbXFseQ5URJ9sYMfstbKLD/c6Gm9vmRzRGDdAXyOIL4zmO37lc9RIwYqVruZw==",
"dev": true,
"license": "MIT",
"funding": {
- "url": "https://github.com/sponsors/Boshen"
+ "url": "https://github.com/sponsors/oxc-project"
}
},
"node_modules/@poppinss/colors": {
@@ -2476,19 +2547,6 @@
"supports-color": "^10.0.0"
}
},
- "node_modules/@poppinss/dumper/node_modules/supports-color": {
- "version": "10.2.2",
- "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-10.2.2.tgz",
- "integrity": "sha512-SS+jx45GF1QjgEXQx4NJZV9ImqmO2NPz5FNsIHrsDjh2YsHnawpan7SNQ1o8NuhrbHZy9AZhIoCUiCeaW/C80g==",
- "dev": true,
- "license": "MIT",
- "engines": {
- "node": ">=18"
- },
- "funding": {
- "url": "https://github.com/chalk/supports-color?sponsor=1"
- }
- },
"node_modules/@poppinss/exception": {
"version": "1.2.3",
"resolved": "https://registry.npmjs.org/@poppinss/exception/-/exception-1.2.3.tgz",
@@ -2497,13 +2555,13 @@
"license": "MIT"
},
"node_modules/@publint/pack": {
- "version": "0.1.6",
- "resolved": "https://registry.npmjs.org/@publint/pack/-/pack-0.1.6.tgz",
- "integrity": "sha512-3uVNyGcVplhPZSLVyeIpL7+cIRn1YCSNHLG/rUIlBQMVH8YuN9++YF+5+UDIIO9RW98dujiUoTltO7RDB5bFJA==",
+ "version": "0.1.7",
+ "resolved": "https://registry.npmjs.org/@publint/pack/-/pack-0.1.7.tgz",
+ "integrity": "sha512-4EDEmvxWtgsCnnVeBvtFIFZtUhPPt1+bA9JrSwU4Sa//6oKtzCSlGGXYJr44OD9aGISymbieJ4mCKHUygUDU+g==",
"dev": true,
"license": "MIT",
"dependencies": {
- "tinyexec": "^1.2.4"
+ "tinyexec": "^1.3.0"
},
"engines": {
"node": ">=18"
@@ -2536,18 +2594,27 @@
}
}
},
- "node_modules/@reduxjs/toolkit/node_modules/immer": {
- "version": "11.1.8",
+ "node_modules/@rolldown/binding-android-arm-eabi": {
+ "version": "1.2.9",
+ "resolved": "https://registry.npmjs.org/@rolldown/binding-android-arm-eabi/-/binding-android-arm-eabi-1.2.9.tgz",
+ "integrity": "sha512-tNISae1QEf/vkb3xkRcjV5SEdzPE97We5IVaa2Z8jSszQPZ8U60B/YCYpw4QI7VidYsBtKavczXf+DyDs9WGxw==",
+ "cpu": [
+ "arm"
+ ],
+ "dev": true,
"license": "MIT",
- "funding": {
- "type": "opencollective",
- "url": "https://opencollective.com/immer"
+ "optional": true,
+ "os": [
+ "android"
+ ],
+ "engines": {
+ "node": "^20.19.0 || >=22.12.0"
}
},
"node_modules/@rolldown/binding-android-arm64": {
- "version": "1.1.3",
- "resolved": "https://registry.npmjs.org/@rolldown/binding-android-arm64/-/binding-android-arm64-1.1.3.tgz",
- "integrity": "sha512-DT6Z3PhvioeHMvxo+xHc3KtqggrI7CCTXCmC2h/5zUlp5jVitv7XEy+9q5/7v8IolhlioawpMo8Kg0EEBy7J0g==",
+ "version": "1.2.9",
+ "resolved": "https://registry.npmjs.org/@rolldown/binding-android-arm64/-/binding-android-arm64-1.2.9.tgz",
+ "integrity": "sha512-YC8YsI30o606GTZi0VyzYlsDKFP8W61i/QzayHDkLbNEz/IShqAmTa+hsJRj13xTHA0H+6fk4b2UmGn+Q/cMlg==",
"cpu": [
"arm64"
],
@@ -2562,9 +2629,9 @@
}
},
"node_modules/@rolldown/binding-darwin-arm64": {
- "version": "1.1.3",
- "resolved": "https://registry.npmjs.org/@rolldown/binding-darwin-arm64/-/binding-darwin-arm64-1.1.3.tgz",
- "integrity": "sha512-0NwgwsjM7LrsuVnXMK3koTpagBNOhloc/BNjKqZjv4V5zI5r13qx69uVhRx+o5Z0yy4Hzq+lpy7TAgUG/ocvrw==",
+ "version": "1.2.9",
+ "resolved": "https://registry.npmjs.org/@rolldown/binding-darwin-arm64/-/binding-darwin-arm64-1.2.9.tgz",
+ "integrity": "sha512-IwhlH3qK5urrY8hZiEgGkHKEFN901p/p2bjxCxJlr4GyNnF7wYpUvK+Y43uaRYuC4hpfjzbR3SJC3arX1jGvmw==",
"cpu": [
"arm64"
],
@@ -2579,9 +2646,9 @@
}
},
"node_modules/@rolldown/binding-darwin-x64": {
- "version": "1.1.3",
- "resolved": "https://registry.npmjs.org/@rolldown/binding-darwin-x64/-/binding-darwin-x64-1.1.3.tgz",
- "integrity": "sha512-YtiBp4disu6V560loT6PjMdiRaWmVvDNrUunAalbiFx2ggeJwxdAsgZMcoGP17uyAsTwAj5V1niksxlHnVQ1Sw==",
+ "version": "1.2.9",
+ "resolved": "https://registry.npmjs.org/@rolldown/binding-darwin-x64/-/binding-darwin-x64-1.2.9.tgz",
+ "integrity": "sha512-XxpJfVzFh+jilRxIXUqcfYAYcunIc/XEzIizsOL1fcJee5Sf7H3mH8WlLmfHfluz5amqR88QQo9izKtmMlavAw==",
"cpu": [
"x64"
],
@@ -2596,9 +2663,9 @@
}
},
"node_modules/@rolldown/binding-freebsd-x64": {
- "version": "1.1.3",
- "resolved": "https://registry.npmjs.org/@rolldown/binding-freebsd-x64/-/binding-freebsd-x64-1.1.3.tgz",
- "integrity": "sha512-yD3EkEdXk2LypPxnf/kSZHirarsI8gcPzc62SukhR9VJTyvV+F9Q/GxWNuCojc7sXyuVC4DxRGhdDK4X8VSsbw==",
+ "version": "1.2.9",
+ "resolved": "https://registry.npmjs.org/@rolldown/binding-freebsd-x64/-/binding-freebsd-x64-1.2.9.tgz",
+ "integrity": "sha512-kSfvhmgeWyfkbT3p/1s5vSgboogoah2zkm9fX2zjg2hHxSV7T4KhMWRUUaRk4OXNqoD3QAUeRqLcs1aZOK4U1g==",
"cpu": [
"x64"
],
@@ -2613,9 +2680,9 @@
}
},
"node_modules/@rolldown/binding-linux-arm-gnueabihf": {
- "version": "1.1.3",
- "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-arm-gnueabihf/-/binding-linux-arm-gnueabihf-1.1.3.tgz",
- "integrity": "sha512-c+8vieQbsD7HNAHKIA34w0GJ9FedFFuJGD+7E6vz7Q3uqAIugL5p45fhlsj4UaAsHpcmlqugBWMhA0/j7o0sIg==",
+ "version": "1.2.9",
+ "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-arm-gnueabihf/-/binding-linux-arm-gnueabihf-1.2.9.tgz",
+ "integrity": "sha512-1RVzG17pxqbTfYLC352JlLt6kKLG+6Hr30n8DlIJqsnV5luUDd2Qdx9Ayw1Cabfyb1K9k0jXEZ7evxkRoT+uiw==",
"cpu": [
"arm"
],
@@ -2630,9 +2697,9 @@
}
},
"node_modules/@rolldown/binding-linux-arm64-gnu": {
- "version": "1.1.3",
- "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-arm64-gnu/-/binding-linux-arm64-gnu-1.1.3.tgz",
- "integrity": "sha512-50jD0uUwLvur7Zz9LHz17kaAdTPjn5wN93hEgjvmYFRZwiR7ZJYovTd5ipyWJDAnXKvZ+wgc+/Ika6dwSF5OcA==",
+ "version": "1.2.9",
+ "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-arm64-gnu/-/binding-linux-arm64-gnu-1.2.9.tgz",
+ "integrity": "sha512-BXqPvZ2drqVD+/Z8UpKwcs4Mp7grM+eGFku4CAEKrEtcbAsUpzREphK1sogCRZGreVPiMkiiBtw0n3TPteuqvw==",
"cpu": [
"arm64"
],
@@ -2650,9 +2717,9 @@
}
},
"node_modules/@rolldown/binding-linux-arm64-musl": {
- "version": "1.1.3",
- "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-arm64-musl/-/binding-linux-arm64-musl-1.1.3.tgz",
- "integrity": "sha512-BO9+oPL8K9poZJBfYPsXNtYjPE5uM3qeehT3aFcW4LITOl+iSqhp0abzjR2nWBUNjIZeKXjAEWBZ64WjNoHd6w==",
+ "version": "1.2.9",
+ "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-arm64-musl/-/binding-linux-arm64-musl-1.2.9.tgz",
+ "integrity": "sha512-11vWvo8YDwLzukt27J3aYDWU+gg2P7J+ZOmiJ0hkF5BXZDW7pVya7r40MXDy6ya0i9KamoENSVKIugvJNgFXIA==",
"cpu": [
"arm64"
],
@@ -2670,9 +2737,9 @@
}
},
"node_modules/@rolldown/binding-linux-ppc64-gnu": {
- "version": "1.1.3",
- "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-ppc64-gnu/-/binding-linux-ppc64-gnu-1.1.3.tgz",
- "integrity": "sha512-f3VpLB1vQ0Eo6ecr/6cekLnvYMFF4YBFoVGkfkvPLq1bAkbAwHYQPZKoAmG6OJyTcxxoC+AvezGx/S1obNC0Mw==",
+ "version": "1.2.9",
+ "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-ppc64-gnu/-/binding-linux-ppc64-gnu-1.2.9.tgz",
+ "integrity": "sha512-a1tijMkdwsIARtc0F39ApURROkf3NwqinI6TOiSSWCTR7dT96dffNvMUtDHnq64wKNTIZOIlzKrFvvFUznJiyw==",
"cpu": [
"ppc64"
],
@@ -2690,9 +2757,9 @@
}
},
"node_modules/@rolldown/binding-linux-s390x-gnu": {
- "version": "1.1.3",
- "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-s390x-gnu/-/binding-linux-s390x-gnu-1.1.3.tgz",
- "integrity": "sha512-AmurZ26Pqx/RI9N1gzEOCklkKXl927yjfXWUUS0O7Puh8ARM/Ob8qfrD3qnWksScdw6cSrW5PSHE9DyLu7+PtA==",
+ "version": "1.2.9",
+ "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-s390x-gnu/-/binding-linux-s390x-gnu-1.2.9.tgz",
+ "integrity": "sha512-x6SQNdAvv4c3hWqTMaWuawzMX9myaCs/yEmlGsxJzkdClnHW7FbrjQuSiRDhuSYzEYoEMhsaJy9qHG/XNemJPQ==",
"cpu": [
"s390x"
],
@@ -2710,9 +2777,9 @@
}
},
"node_modules/@rolldown/binding-linux-x64-gnu": {
- "version": "1.1.3",
- "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-x64-gnu/-/binding-linux-x64-gnu-1.1.3.tgz",
- "integrity": "sha512-JJpqs8bRGITDOdbkNKnlojzBabbOHrqjSvDr0IVsZObE1lBcPjxItUEY9eWIDbxaJ3cGrXPWGfGkIxFijg/URg==",
+ "version": "1.2.9",
+ "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-x64-gnu/-/binding-linux-x64-gnu-1.2.9.tgz",
+ "integrity": "sha512-9s0AZ8BFK5/n7B/TBoa2yJE3gI3KURrbXcPBlsAsvjU4VeJKgE90y1YtNxyEUIcHPQkg6/yfF3qihUrcM/Kf0Q==",
"cpu": [
"x64"
],
@@ -2730,9 +2797,9 @@
}
},
"node_modules/@rolldown/binding-linux-x64-musl": {
- "version": "1.1.3",
- "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-x64-musl/-/binding-linux-x64-musl-1.1.3.tgz",
- "integrity": "sha512-rSJcdjPxzA/by/6/rYs+v+bXU7UjvnbUWz8MJb6kh6+knqB1dCrtHg0uu7C/4haqJvqdkYHQ5IGn+tCH9GLW/g==",
+ "version": "1.2.9",
+ "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-x64-musl/-/binding-linux-x64-musl-1.2.9.tgz",
+ "integrity": "sha512-P7VWAmV+WdJluH7ovnRGoiv2i8To7GAZ+kGzfGup635cyL7SyYl3lSUaA3Gp5THf0n/Co5EyEqb2zbqq+nMOHQ==",
"cpu": [
"x64"
],
@@ -2750,9 +2817,9 @@
}
},
"node_modules/@rolldown/binding-openharmony-arm64": {
- "version": "1.1.3",
- "resolved": "https://registry.npmjs.org/@rolldown/binding-openharmony-arm64/-/binding-openharmony-arm64-1.1.3.tgz",
- "integrity": "sha512-hQ3/PYkDJICgevvyNcVrihVeqq7k1Pp3VZ9lY+dauAYUJKO+auqApvANhvR1An9BhmqYKvW2Mu1F9u4DXSMLxQ==",
+ "version": "1.2.9",
+ "resolved": "https://registry.npmjs.org/@rolldown/binding-openharmony-arm64/-/binding-openharmony-arm64-1.2.9.tgz",
+ "integrity": "sha512-1qixtsE4BK8h+yS3BfmZ09UhA7O/N4IACva6YBr7EBvCJraByTuRcgOTaiA62Tm0vey3UcKXLOaoGHtYmNGEVg==",
"cpu": [
"arm64"
],
@@ -2766,29 +2833,10 @@
"node": "^20.19.0 || >=22.12.0"
}
},
- "node_modules/@rolldown/binding-wasm32-wasi": {
- "version": "1.1.3",
- "resolved": "https://registry.npmjs.org/@rolldown/binding-wasm32-wasi/-/binding-wasm32-wasi-1.1.3.tgz",
- "integrity": "sha512-Elcv/BtML9lXrV6JuKITc/grN2kYV9gjsQpW8Jfw4ioK0TOkjBjye0nnyqQNy9STNaI20lXNaQBRrD5gSgR0Yg==",
- "cpu": [
- "wasm32"
- ],
- "dev": true,
- "license": "MIT",
- "optional": true,
- "dependencies": {
- "@emnapi/core": "1.11.1",
- "@emnapi/runtime": "1.11.1",
- "@napi-rs/wasm-runtime": "^1.1.6"
- },
- "engines": {
- "node": "^20.19.0 || >=22.12.0"
- }
- },
"node_modules/@rolldown/binding-win32-arm64-msvc": {
- "version": "1.1.3",
- "resolved": "https://registry.npmjs.org/@rolldown/binding-win32-arm64-msvc/-/binding-win32-arm64-msvc-1.1.3.tgz",
- "integrity": "sha512-2DrEfhluH9yhiaFApmsjsjwrSYbNcY1oFTzYSP1a535jDbV98zCFanA/96TBUd0iDFcxGmw9QRExwGCXz3U+/g==",
+ "version": "1.2.9",
+ "resolved": "https://registry.npmjs.org/@rolldown/binding-win32-arm64-msvc/-/binding-win32-arm64-msvc-1.2.9.tgz",
+ "integrity": "sha512-ok8IQjcEPs1AKZfuEUznVBrJw+gK4soq+bx8b1X2XoMqVClarc1q5JDmVtWXY1xfr6ZuHTAsPXHTgTrqKTZeww==",
"cpu": [
"arm64"
],
@@ -2803,7 +2851,9 @@
}
},
"node_modules/@rolldown/binding-win32-x64-msvc": {
- "version": "1.1.3",
+ "version": "1.2.9",
+ "resolved": "https://registry.npmjs.org/@rolldown/binding-win32-x64-msvc/-/binding-win32-x64-msvc-1.2.9.tgz",
+ "integrity": "sha512-Ip2mXoU0hM0boq3Rf+ekuT653OROSo6aSYcPT1VHE4q52KvyxgFkQgrgb/IEsxOuvQ2fZZbs8khJAyCEPM24/g==",
"cpu": [
"x64"
],
@@ -3240,45 +3290,49 @@
"license": "MIT"
},
"node_modules/@tailwindcss/node": {
- "version": "4.3.2",
+ "version": "4.3.3",
+ "resolved": "https://registry.npmjs.org/@tailwindcss/node/-/node-4.3.3.tgz",
+ "integrity": "sha512-/T8IKEsf9VTU6tLjgC7+sv2mOPtQxzE2jMw7u4Tt40Tx+QSZxpzh95/H6cMKoja9XuW7iMdLJYBB0o9G1CaAgg==",
"dev": true,
"license": "MIT",
"dependencies": {
"@jridgewell/remapping": "^2.3.5",
- "enhanced-resolve": "5.21.6",
+ "enhanced-resolve": "^5.24.1",
"jiti": "^2.7.0",
"lightningcss": "1.32.0",
"magic-string": "^0.30.21",
"source-map-js": "^1.2.1",
- "tailwindcss": "4.3.2"
+ "tailwindcss": "4.3.3"
}
},
"node_modules/@tailwindcss/oxide": {
- "version": "4.3.2",
+ "version": "4.3.3",
+ "resolved": "https://registry.npmjs.org/@tailwindcss/oxide/-/oxide-4.3.3.tgz",
+ "integrity": "sha512-krXjAikiaFSPaK/FkAQT5UTx3VormQaiZ5hBFlJZ9UFQGB/rwg1MZIhHAG9smMQRTdyJxP6Qt5MwMtdyU5FWrA==",
"dev": true,
"license": "MIT",
"engines": {
"node": ">= 20"
},
"optionalDependencies": {
- "@tailwindcss/oxide-android-arm64": "4.3.2",
- "@tailwindcss/oxide-darwin-arm64": "4.3.2",
- "@tailwindcss/oxide-darwin-x64": "4.3.2",
- "@tailwindcss/oxide-freebsd-x64": "4.3.2",
- "@tailwindcss/oxide-linux-arm-gnueabihf": "4.3.2",
- "@tailwindcss/oxide-linux-arm64-gnu": "4.3.2",
- "@tailwindcss/oxide-linux-arm64-musl": "4.3.2",
- "@tailwindcss/oxide-linux-x64-gnu": "4.3.2",
- "@tailwindcss/oxide-linux-x64-musl": "4.3.2",
- "@tailwindcss/oxide-wasm32-wasi": "4.3.2",
- "@tailwindcss/oxide-win32-arm64-msvc": "4.3.2",
- "@tailwindcss/oxide-win32-x64-msvc": "4.3.2"
+ "@tailwindcss/oxide-android-arm64": "4.3.3",
+ "@tailwindcss/oxide-darwin-arm64": "4.3.3",
+ "@tailwindcss/oxide-darwin-x64": "4.3.3",
+ "@tailwindcss/oxide-freebsd-x64": "4.3.3",
+ "@tailwindcss/oxide-linux-arm-gnueabihf": "4.3.3",
+ "@tailwindcss/oxide-linux-arm64-gnu": "4.3.3",
+ "@tailwindcss/oxide-linux-arm64-musl": "4.3.3",
+ "@tailwindcss/oxide-linux-x64-gnu": "4.3.3",
+ "@tailwindcss/oxide-linux-x64-musl": "4.3.3",
+ "@tailwindcss/oxide-wasm32-wasi": "4.3.3",
+ "@tailwindcss/oxide-win32-arm64-msvc": "4.3.3",
+ "@tailwindcss/oxide-win32-x64-msvc": "4.3.3"
}
},
"node_modules/@tailwindcss/oxide-android-arm64": {
- "version": "4.3.2",
- "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-android-arm64/-/oxide-android-arm64-4.3.2.tgz",
- "integrity": "sha512-WHxqIuHpvZ5VtdX6GTl1Ik/Vp2YuN42Et+0CdeaVd/frQ9jAvGmvR8vLT+jk3e8/Q3x8kECB9+R17pgpp2BulA==",
+ "version": "4.3.3",
+ "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-android-arm64/-/oxide-android-arm64-4.3.3.tgz",
+ "integrity": "sha512-Y85A2gmPSkl5Ve5qR86GL4HT509cFqQh1aes9p3sSkyTPwt0Pppf3GkwGe4JPACcRYjgJIEhQgM6dBClnr0NYw==",
"cpu": [
"arm64"
],
@@ -3293,9 +3347,9 @@
}
},
"node_modules/@tailwindcss/oxide-darwin-arm64": {
- "version": "4.3.2",
- "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-darwin-arm64/-/oxide-darwin-arm64-4.3.2.tgz",
- "integrity": "sha512-GZypeUY/IDJW3877KeM+O67vbXr3MBnbtEL4aYhNErv/JWZhye2vGSWWG9tB6iiqR2MqRNkY8IOUy4NdSZV26w==",
+ "version": "4.3.3",
+ "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-darwin-arm64/-/oxide-darwin-arm64-4.3.3.tgz",
+ "integrity": "sha512-BiaWatpBcERQFDlOjRDpIVXuFK5PJez5SA4JMg6VYZdBYU+qKfV/vqjcIs+IYmtitf1xYQZTwXvU/8y4lfZUGw==",
"cpu": [
"arm64"
],
@@ -3310,9 +3364,9 @@
}
},
"node_modules/@tailwindcss/oxide-darwin-x64": {
- "version": "4.3.2",
- "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-darwin-x64/-/oxide-darwin-x64-4.3.2.tgz",
- "integrity": "sha512-UIIzmefR6KO1sDU7MzRqAxC8iBpft/VhkGjTjnhoS6k7Z3rQ9wEgA1ODSiyH/tcSYssulNm4Ci3hOeK1jH7ccQ==",
+ "version": "4.3.3",
+ "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-darwin-x64/-/oxide-darwin-x64-4.3.3.tgz",
+ "integrity": "sha512-fAeUqfV5ndhxRwai8cXGzdLvul9utWOmeTkv69unv4ZXixjn61Z+p9lCWdwOwA3TYboG3BwdVuN/RDjhBRl0mw==",
"cpu": [
"x64"
],
@@ -3327,9 +3381,9 @@
}
},
"node_modules/@tailwindcss/oxide-freebsd-x64": {
- "version": "4.3.2",
- "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-freebsd-x64/-/oxide-freebsd-x64-4.3.2.tgz",
- "integrity": "sha512-GN+uAmcI6DNspnCDwtOAZrTz6oukJnp337qZvxqCGLd3BHBzJpO0ZbTLRvJNdztOeAmTzewewGIMPb0tk2R4WA==",
+ "version": "4.3.3",
+ "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-freebsd-x64/-/oxide-freebsd-x64-4.3.3.tgz",
+ "integrity": "sha512-iyf5bV6+wnAlflVeEy7R25dupxTNECZN5QMI0qNT6eT+EgaGdZcKhGkr5SdoaWiLJ3spLqIY9VCeSGrwmtg4kw==",
"cpu": [
"x64"
],
@@ -3344,9 +3398,9 @@
}
},
"node_modules/@tailwindcss/oxide-linux-arm-gnueabihf": {
- "version": "4.3.2",
- "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-linux-arm-gnueabihf/-/oxide-linux-arm-gnueabihf-4.3.2.tgz",
- "integrity": "sha512-4ABn7qSbdHRwTiDiuWNegCyb5+2FJ4vKIKc3DmKrvAFw7MU1Lm11dIkTPwUaFdTzc7IsOpDbqBrlh0x6y36U/w==",
+ "version": "4.3.3",
+ "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-linux-arm-gnueabihf/-/oxide-linux-arm-gnueabihf-4.3.3.tgz",
+ "integrity": "sha512-aAYUprJAJQWWbRrPvtjdroZ56Md+JM8pMiopS6xGEwDfLhqj+2ver2p4nU4Mb3CRqcMmNBjo8KkUgcxhkzVQGQ==",
"cpu": [
"arm"
],
@@ -3361,9 +3415,9 @@
}
},
"node_modules/@tailwindcss/oxide-linux-arm64-gnu": {
- "version": "4.3.2",
- "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-linux-arm64-gnu/-/oxide-linux-arm64-gnu-4.3.2.tgz",
- "integrity": "sha512-wDgEIGwoM8w8pufh9LVt1PahDgNdKXrLC2qfAnV3vAmococ9RWbxeAw4pxPttd/TsJfwjyLf90Dg1y9y8I6Emw==",
+ "version": "4.3.3",
+ "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-linux-arm64-gnu/-/oxide-linux-arm64-gnu-4.3.3.tgz",
+ "integrity": "sha512-nDxldcEENOxZRzC2uu9jrutZdAAQtb+8WWDCSnWL1zvBk1+FN+x6MtDViPB5AJMfttVCUhehGWus3XBPgatM/w==",
"cpu": [
"arm64"
],
@@ -3381,9 +3435,9 @@
}
},
"node_modules/@tailwindcss/oxide-linux-arm64-musl": {
- "version": "4.3.2",
- "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-linux-arm64-musl/-/oxide-linux-arm64-musl-4.3.2.tgz",
- "integrity": "sha512-J5Nuk0uZQIiMTJj3LEx4sAA9tMFUoXQZFv1J6An+QGYe53HKRJuFDi0rpq/tuouCZeAbOBY3kQ6g8qeD4TUjtA==",
+ "version": "4.3.3",
+ "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-linux-arm64-musl/-/oxide-linux-arm64-musl-4.3.3.tgz",
+ "integrity": "sha512-Md44bD6veX/PC5iyF8cDVnw4HBIANZepRZZ7a8DQOvkfo5WUBwcp6iAuCUz23u+4SUkhJlD3eL7hNdW8ezd/kA==",
"cpu": [
"arm64"
],
@@ -3401,9 +3455,9 @@
}
},
"node_modules/@tailwindcss/oxide-linux-x64-gnu": {
- "version": "4.3.2",
- "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-linux-x64-gnu/-/oxide-linux-x64-gnu-4.3.2.tgz",
- "integrity": "sha512-kqCZpSKOBEJO4mz7OqWoofBZeXTAwaVGPj0ErAj7CojmhKpWVWVOnrt9dE8odoIraZq4oj3ausM37kXi+Tow8w==",
+ "version": "4.3.3",
+ "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-linux-x64-gnu/-/oxide-linux-x64-gnu-4.3.3.tgz",
+ "integrity": "sha512-tx7us1muwOKAKWao2v/GaafFeQboE6aj88vC6ziN2NCGcRm8gWUhwjzg+YdVB1e4boAtdtma4L43onunI6NS4w==",
"cpu": [
"x64"
],
@@ -3421,9 +3475,9 @@
}
},
"node_modules/@tailwindcss/oxide-linux-x64-musl": {
- "version": "4.3.2",
- "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-linux-x64-musl/-/oxide-linux-x64-musl-4.3.2.tgz",
- "integrity": "sha512-cixpqbh2toJDmkuCRI68nXA8ZxNmdK9Y+9v5h3MC3ZQKy/0BO8AWzlkWyRM7JAFSGBlfig4YVTPsK6MVgqz1uw==",
+ "version": "4.3.3",
+ "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-linux-x64-musl/-/oxide-linux-x64-musl-4.3.3.tgz",
+ "integrity": "sha512-SJxX60smvHgasZoBy11dX6YRjXJFovwWBoedhbQPOBzgFWBHGB+TVPWB9BxzR7TTxU8FQZAI2AyiNCMzFm8Img==",
"cpu": [
"x64"
],
@@ -3441,9 +3495,9 @@
}
},
"node_modules/@tailwindcss/oxide-wasm32-wasi": {
- "version": "4.3.2",
- "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-wasm32-wasi/-/oxide-wasm32-wasi-4.3.2.tgz",
- "integrity": "sha512-4ec2Z/LOmRsAgU23CS4xeJfcJlmRg94A/XrbGRCF1gyU/zdDfRLYDVsS+ynSZCmGNxQ1jQriQOKMQeQxBA3Isw==",
+ "version": "4.3.3",
+ "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-wasm32-wasi/-/oxide-wasm32-wasi-4.3.3.tgz",
+ "integrity": "sha512-jx1+rPhY/5Ympkktd656HBWEBLxP7dH06losBLjjf5vgCODXvi9KhtftWcMIwTFIDqBr7cRnQkdLnAG+IOlGvQ==",
"bundleDependencies": [
"@napi-rs/wasm-runtime",
"@emnapi/core",
@@ -3471,9 +3525,9 @@
}
},
"node_modules/@tailwindcss/oxide-win32-arm64-msvc": {
- "version": "4.3.2",
- "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-win32-arm64-msvc/-/oxide-win32-arm64-msvc-4.3.2.tgz",
- "integrity": "sha512-Zyr/M0+XcYZu3bZrUytc7TXvrk0ftWfl8gN2MwekNDzhqhKRUucMPSeOzM0o0wH5AWOU49BsKRrfKxI2atCPMQ==",
+ "version": "4.3.3",
+ "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-win32-arm64-msvc/-/oxide-win32-arm64-msvc-4.3.3.tgz",
+ "integrity": "sha512-3rc292Ca2ceK6Ulcc/bAVnTs/3nDtoPhyEKlgPv+yQJQi/JS/AMJlqzxvlDacL1nekbrcf6bTqp/jV4qgnPxNQ==",
"cpu": [
"arm64"
],
@@ -3488,7 +3542,9 @@
}
},
"node_modules/@tailwindcss/oxide-win32-x64-msvc": {
- "version": "4.3.2",
+ "version": "4.3.3",
+ "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-win32-x64-msvc/-/oxide-win32-x64-msvc-4.3.3.tgz",
+ "integrity": "sha512-yJ0pwIVc/nYeGoV02WtsN8KYyLQv7kyI2wDnkezyJlGGjkd4QLwDGAwl47YpPJeuI0M0ObaXGSPjvWDPeTPggw==",
"cpu": [
"x64"
],
@@ -3503,20 +3559,24 @@
}
},
"node_modules/@tailwindcss/vite": {
- "version": "4.3.2",
+ "version": "4.3.3",
+ "resolved": "https://registry.npmjs.org/@tailwindcss/vite/-/vite-4.3.3.tgz",
+ "integrity": "sha512-yYU8cogLeSh/ms2jh8Fj7jaba/EWa7Ja6GoUqYZaraEuCI5YS6ms6ObZgjjedm+jm6XZjdNRWBpPP6Z86oOxcw==",
"dev": true,
"license": "MIT",
"dependencies": {
- "@tailwindcss/node": "4.3.2",
- "@tailwindcss/oxide": "4.3.2",
- "tailwindcss": "4.3.2"
+ "@tailwindcss/node": "4.3.3",
+ "@tailwindcss/oxide": "4.3.3",
+ "tailwindcss": "4.3.3"
},
"peerDependencies": {
"vite": "^5.2.0 || ^6 || ^7 || ^8"
}
},
"node_modules/@testing-library/dom": {
- "version": "10.4.1",
+ "version": "10.4.2",
+ "resolved": "https://registry.npmjs.org/@testing-library/dom/-/dom-10.4.2.tgz",
+ "integrity": "sha512-yzr2S9HyAIdhz2/6qHgbs665Q7PKVcDF05vsOlHPxG1mo36gKVesdYVeDLnXgfjJ03CrKRk08knc6+E/9m8v2Q==",
"dev": true,
"license": "MIT",
"dependencies": {
@@ -3534,7 +3594,9 @@
}
},
"node_modules/@testing-library/react": {
- "version": "16.3.2",
+ "version": "16.3.3",
+ "resolved": "https://registry.npmjs.org/@testing-library/react/-/react-16.3.3.tgz",
+ "integrity": "sha512-Uo193NgQbPMz6lrrhtRQQFcMC6Re/ELLFbbuVL30WDlZxlpZf9/lMHTAVxPRLw1q1iu9OJmR1c2BLiENRstdBg==",
"dev": true,
"license": "MIT",
"dependencies": {
@@ -3689,7 +3751,9 @@
"license": "MIT"
},
"node_modules/@types/node": {
- "version": "25.9.4",
+ "version": "25.9.8",
+ "resolved": "https://registry.npmjs.org/@types/node/-/node-25.9.8.tgz",
+ "integrity": "sha512-VfMrScDmMhUJQmd5hArdQnFvK0OIeD36uN2Va1FcpYaLB/BgkgM8Ulc50XtYISPMz7APJ30+N0T5EM0jlcdfRw==",
"dev": true,
"license": "MIT",
"dependencies": {
@@ -3702,22 +3766,22 @@
"license": "MIT"
},
"node_modules/@types/react": {
- "version": "19.2.18",
- "resolved": "https://registry.npmjs.org/@types/react/-/react-19.2.18.tgz",
- "integrity": "sha512-AnzbBERsrLKtk2XSfTbYRLjQPdy116Sty4q+T+Bp3IC4l6jNBvreVPAHmpq9qhXQM7CXZPjLVmGMw9sy+hxQ3w==",
+ "version": "19.3.0",
+ "resolved": "https://registry.npmjs.org/@types/react/-/react-19.3.0.tgz",
+ "integrity": "sha512-N0rFCuH9YoxG9/m61l9MfpJKfmLOVU0em7ipIz6TRgSSkvReLB9vL85GB+yr8Bs5leqpvg96JSwF4ZS1s4viQg==",
"license": "MIT",
"dependencies": {
"csstype": "^3.2.2"
}
},
"node_modules/@types/react-dom": {
- "version": "19.2.4",
- "resolved": "https://registry.npmjs.org/@types/react-dom/-/react-dom-19.2.4.tgz",
- "integrity": "sha512-Bsc+QHgp+P/F02XDzNCY9jnZNCUuLki36KT7VKrTXXLdHf+vHMNZnW1rVu5DNW/rCK+fya3DATySbLM4yhtKUw==",
+ "version": "19.3.0",
+ "resolved": "https://registry.npmjs.org/@types/react-dom/-/react-dom-19.3.0.tgz",
+ "integrity": "sha512-ZI7bU42mZXXKHn/qNLEw2IrbiINU7X5+vfgdixBHkCNpYWXjKgfQ/P+uyGb5CjOLB9UcnTeg3rylQtV2hym44Q==",
"dev": true,
"license": "MIT",
"peerDependencies": {
- "@types/react": "^19.2.0"
+ "@types/react": "^19.3.0"
}
},
"node_modules/@types/unist": {
@@ -3728,139 +3792,15 @@
"version": "0.0.6",
"license": "MIT"
},
- "node_modules/@typescript-eslint/eslint-plugin": {
- "version": "8.66.0",
- "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.66.0.tgz",
- "integrity": "sha512-p088eaGrzYz1s+7cov0aMOCkNGTJlVxF4jgubf28c8L0Cv9Rloj8YBHnv4hXLq6IIEE1AsjNWavO+k+8kP2Y0A==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "@eslint-community/regexpp": "^4.12.2",
- "@typescript-eslint/scope-manager": "8.66.0",
- "@typescript-eslint/type-utils": "8.66.0",
- "@typescript-eslint/utils": "8.66.0",
- "@typescript-eslint/visitor-keys": "8.66.0",
- "ignore": "^7.0.5",
- "natural-compare": "^1.4.0",
- "ts-api-utils": "^2.5.0"
- },
- "engines": {
- "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
- },
- "funding": {
- "type": "opencollective",
- "url": "https://opencollective.com/typescript-eslint"
- },
- "peerDependencies": {
- "@typescript-eslint/parser": "^8.66.0",
- "eslint": "^8.57.0 || ^9.0.0 || ^10.0.0",
- "typescript": ">=4.8.4 <6.1.0"
- }
- },
- "node_modules/@typescript-eslint/eslint-plugin/node_modules/ignore": {
- "version": "7.0.6",
- "resolved": "https://registry.npmjs.org/ignore/-/ignore-7.0.6.tgz",
- "integrity": "sha512-BAg6QkE8W+TuQLrrw0Ugr7HegXduRuuj8/ti2kSOc+jz1dmx8/WNcjr6XGnq5YpDWxFwwaavqD0+jIUOKelTsw==",
- "dev": true,
- "license": "MIT",
- "engines": {
- "node": ">= 4"
- }
- },
- "node_modules/@typescript-eslint/parser": {
- "version": "8.66.0",
- "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-8.66.0.tgz",
- "integrity": "sha512-X6ypGChaWYk6PBtUg2BwuTZEFFcHJAtGTVJ9/lCTOufhZ4i9fNolQNnktq+kkMCwMj7V8Svsq7+TxSDslmhE0g==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "@typescript-eslint/scope-manager": "8.66.0",
- "@typescript-eslint/types": "8.66.0",
- "@typescript-eslint/typescript-estree": "8.66.0",
- "@typescript-eslint/visitor-keys": "8.66.0",
- "debug": "^4.4.3"
- },
- "engines": {
- "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
- },
- "funding": {
- "type": "opencollective",
- "url": "https://opencollective.com/typescript-eslint"
- },
- "peerDependencies": {
- "eslint": "^8.57.0 || ^9.0.0 || ^10.0.0",
- "typescript": ">=4.8.4 <6.1.0"
- }
- },
- "node_modules/@typescript-eslint/project-service": {
- "version": "8.66.0",
- "resolved": "https://registry.npmjs.org/@typescript-eslint/project-service/-/project-service-8.66.0.tgz",
- "integrity": "sha512-7MthGPTt4BP69lSryqpqq8HQqxuzynssckL/jyDyk3+TNMQ3y2jFWkptCrktWvBrP+EH787Nl5N5Qpw7WZg+5g==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "@typescript-eslint/tsconfig-utils": "^8.66.0",
- "@typescript-eslint/types": "^8.66.0",
- "debug": "^4.4.3"
- },
- "engines": {
- "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
- },
- "funding": {
- "type": "opencollective",
- "url": "https://opencollective.com/typescript-eslint"
- },
- "peerDependencies": {
- "typescript": ">=4.8.4 <6.1.0"
- }
- },
"node_modules/@typescript-eslint/scope-manager": {
- "version": "8.66.0",
- "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-8.66.0.tgz",
- "integrity": "sha512-8TGcH25j9zqJ/IULB/ppyhRvxA8QYfFEZ7nfbg6/BN9spDgb8fPWQXlE5l8TWBL50EtUx007uZ1o9VOwrq2/9g==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "@typescript-eslint/types": "8.66.0",
- "@typescript-eslint/visitor-keys": "8.66.0"
- },
- "engines": {
- "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
- },
- "funding": {
- "type": "opencollective",
- "url": "https://opencollective.com/typescript-eslint"
- }
- },
- "node_modules/@typescript-eslint/tsconfig-utils": {
- "version": "8.66.0",
- "resolved": "https://registry.npmjs.org/@typescript-eslint/tsconfig-utils/-/tsconfig-utils-8.66.0.tgz",
- "integrity": "sha512-9D5gLYZG4rOjcoag8MQ/fWI8WqA9wcPDyOGyWtWFhvM1lHRbliqUSPIY5J3zqCU1tvSwzXxnnjhQhz5Ne7mJ4g==",
- "dev": true,
- "license": "MIT",
- "engines": {
- "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
- },
- "funding": {
- "type": "opencollective",
- "url": "https://opencollective.com/typescript-eslint"
- },
- "peerDependencies": {
- "typescript": ">=4.8.4 <6.1.0"
- }
- },
- "node_modules/@typescript-eslint/type-utils": {
- "version": "8.66.0",
- "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-8.66.0.tgz",
- "integrity": "sha512-LG2dWfjZQQp0ADtAu/EWJVayefGL2UEZ3CDeI44D9v3rXB/WYUqE/jpO28KrEKul5AySrmI+Zh1v6v+xW2U9+g==",
+ "version": "8.70.1",
+ "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-8.70.1.tgz",
+ "integrity": "sha512-Pa0EeSeAusQc1WbjQMac+YfenewYTBu0KjgYvkUKwhXaHUKbFog23Dm/rp0DX/6tyYOQ3Xl1a+3EcFNZynGHCw==",
"dev": true,
"license": "MIT",
"dependencies": {
- "@typescript-eslint/types": "8.66.0",
- "@typescript-eslint/typescript-estree": "8.66.0",
- "@typescript-eslint/utils": "8.66.0",
- "debug": "^4.4.3",
- "ts-api-utils": "^2.5.0"
+ "@typescript-eslint/types": "8.70.1",
+ "@typescript-eslint/visitor-keys": "8.70.1"
},
"engines": {
"node": "^18.18.0 || ^20.9.0 || >=21.1.0"
@@ -3868,86 +3808,30 @@
"funding": {
"type": "opencollective",
"url": "https://opencollective.com/typescript-eslint"
- },
- "peerDependencies": {
- "eslint": "^8.57.0 || ^9.0.0 || ^10.0.0",
- "typescript": ">=4.8.4 <6.1.0"
}
},
"node_modules/@typescript-eslint/types": {
- "version": "8.66.0",
- "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.66.0.tgz",
- "integrity": "sha512-H6gcYaSDOyvL3AD/jHUtUFo2jqGgn/F6nuyuZSu0QTesxL+cP4dQoIMrODRofuJC09g64+WgZ6tE19Y1N2YIFQ==",
- "dev": true,
- "license": "MIT",
- "engines": {
- "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
- },
- "funding": {
- "type": "opencollective",
- "url": "https://opencollective.com/typescript-eslint"
- }
- },
- "node_modules/@typescript-eslint/typescript-estree": {
- "version": "8.66.0",
- "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-8.66.0.tgz",
- "integrity": "sha512-8/x4INiiQb10jGgXYD7116/zQ+OL84ZIFn0za68wwFHCanT/VLbBEroWht8RV8fn0/ZCAoazHLQgwUC0UQcDfg==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "@typescript-eslint/project-service": "8.66.0",
- "@typescript-eslint/tsconfig-utils": "8.66.0",
- "@typescript-eslint/types": "8.66.0",
- "@typescript-eslint/visitor-keys": "8.66.0",
- "debug": "^4.4.3",
- "minimatch": "^10.2.2",
- "semver": "^7.7.3",
- "tinyglobby": "^0.2.15",
- "ts-api-utils": "^2.5.0"
- },
- "engines": {
- "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
- },
- "funding": {
- "type": "opencollective",
- "url": "https://opencollective.com/typescript-eslint"
- },
- "peerDependencies": {
- "typescript": ">=4.8.4 <6.1.0"
- }
- },
- "node_modules/@typescript-eslint/utils": {
- "version": "8.66.0",
- "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-8.66.0.tgz",
- "integrity": "sha512-jasearZPolBw5NJNYGMwxzHMF83niVWmMU1VdHzG1CyfI2VS7f7nZltnKtHcg20hW+7Uo5GfK4MeDPoU3qI8EA==",
+ "version": "8.70.1",
+ "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.70.1.tgz",
+ "integrity": "sha512-Dm1ypdhhrGCTyyehxElhgJ6kgk8MVCv5qXdoOVqPr1uqk42jX8KjrZqhROvdShczA8qrDoYiOWn1ykWlx2k81Q==",
"dev": true,
"license": "MIT",
- "dependencies": {
- "@eslint-community/eslint-utils": "^4.9.1",
- "@typescript-eslint/scope-manager": "8.66.0",
- "@typescript-eslint/types": "8.66.0",
- "@typescript-eslint/typescript-estree": "8.66.0"
- },
"engines": {
"node": "^18.18.0 || ^20.9.0 || >=21.1.0"
},
"funding": {
"type": "opencollective",
"url": "https://opencollective.com/typescript-eslint"
- },
- "peerDependencies": {
- "eslint": "^8.57.0 || ^9.0.0 || ^10.0.0",
- "typescript": ">=4.8.4 <6.1.0"
}
},
"node_modules/@typescript-eslint/visitor-keys": {
- "version": "8.66.0",
- "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-8.66.0.tgz",
- "integrity": "sha512-dkKR8q+lKciskj1Y3vthHktl+3cMLWGyVUP23bRiPZ5O9BRT++4EqDDV+TVeIKBL1VXVEqrJlz8MYbcnvJcAlg==",
+ "version": "8.70.1",
+ "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-8.70.1.tgz",
+ "integrity": "sha512-Vwj9lUIW5Xq3wQ9w6gv3R86g1hMK8f2zNOdGTAgeXUMMXFK78G9ruCjjqutHMNJc0+CH7LYRnHeUB9IT8wFmcw==",
"dev": true,
"license": "MIT",
"dependencies": {
- "@typescript-eslint/types": "8.66.0",
+ "@typescript-eslint/types": "8.70.1",
"eslint-visitor-keys": "^5.0.0"
},
"engines": {
@@ -4340,9 +4224,9 @@
]
},
"node_modules/@vitejs/plugin-react": {
- "version": "6.0.5",
- "resolved": "https://registry.npmjs.org/@vitejs/plugin-react/-/plugin-react-6.0.5.tgz",
- "integrity": "sha512-BOVzne/NL162sMdResB25mUv+vWMF5NoAjNf09TeGlE7ZpszZWSD3winycicLJw72yeVsoCn/2kOhEuCvEShMA==",
+ "version": "6.1.1",
+ "resolved": "https://registry.npmjs.org/@vitejs/plugin-react/-/plugin-react-6.1.1.tgz",
+ "integrity": "sha512-yxLaQV9gkhS8ezJqCM6+ndU7mDY6gqAg75NQ+0IjwEI8IYOmQCgkRwHKVSfWXW076DsqMo0Dk+0FK1U+M5RgFw==",
"dev": true,
"license": "MIT",
"dependencies": {
@@ -4354,6 +4238,7 @@
"peerDependencies": {
"@rolldown/plugin-babel": "^0.1.7 || ^0.2.0",
"babel-plugin-react-compiler": "^1.0.0",
+ "oxc-transform-react": "^0.145.0",
"vite": "^8.0.0"
},
"peerDependenciesMeta": {
@@ -4362,6 +4247,9 @@
},
"babel-plugin-react-compiler": {
"optional": true
+ },
+ "oxc-transform-react": {
+ "optional": true
}
}
},
@@ -4610,7 +4498,9 @@
}
},
"node_modules/bidi-js": {
- "version": "1.0.3",
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/bidi-js/-/bidi-js-1.1.0.tgz",
+ "integrity": "sha512-fX1Onk0tdVPC7obPWB5EbJ1z7NVhLq4m2xZLq2YXBkxzMXIGRpNMU88n0EPgWseKl12J7zXs7qrDxPK4sRs2fg==",
"dev": true,
"license": "MIT",
"dependencies": {
@@ -4731,6 +4621,20 @@
"node": ">=8"
}
},
+ "node_modules/cacheable": {
+ "version": "2.5.0",
+ "resolved": "https://registry.npmjs.org/cacheable/-/cacheable-2.5.0.tgz",
+ "integrity": "sha512-60cyAOytib/OzBw1JNSoSV/boK1AtHryDIjvVBk7XbN4ugfkM3+Sry7fEjNgPMGgOjuaZPAp8ruZ0Cxafwyq9g==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@cacheable/memory": "^2.2.0",
+ "@cacheable/utils": "^2.5.0",
+ "hookified": "^1.15.0",
+ "keyv": "^5.6.0",
+ "qified": "^0.10.1"
+ }
+ },
"node_modules/caniuse-lite": {
"version": "1.0.30001806",
"resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001806.tgz",
@@ -4772,6 +4676,8 @@
},
"node_modules/chalk": {
"version": "5.6.2",
+ "resolved": "https://registry.npmjs.org/chalk/-/chalk-5.6.2.tgz",
+ "integrity": "sha512-7NzBL0rN6fMUW+f7A6Io4h40qQlG+xGmtMxfbnH/K7TAtt8JQWVQK+6g0UXKMeVJoyV5EkkNsErQ8pVD3bLHbA==",
"dev": true,
"license": "MIT",
"engines": {
@@ -5071,6 +4977,8 @@
},
"node_modules/cliui": {
"version": "8.0.1",
+ "resolved": "https://registry.npmjs.org/cliui/-/cliui-8.0.1.tgz",
+ "integrity": "sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==",
"dev": true,
"license": "ISC",
"dependencies": {
@@ -5084,6 +4992,8 @@
},
"node_modules/cliui/node_modules/string-width": {
"version": "4.2.3",
+ "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz",
+ "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==",
"dev": true,
"license": "MIT",
"dependencies": {
@@ -5097,6 +5007,8 @@
},
"node_modules/cliui/node_modules/strip-ansi": {
"version": "6.0.1",
+ "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz",
+ "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==",
"dev": true,
"license": "MIT",
"dependencies": {
@@ -5193,6 +5105,8 @@
},
"node_modules/concurrently/node_modules/ansi-styles": {
"version": "4.3.0",
+ "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz",
+ "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==",
"dev": true,
"license": "MIT",
"dependencies": {
@@ -5207,6 +5121,8 @@
},
"node_modules/concurrently/node_modules/chalk": {
"version": "4.1.2",
+ "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz",
+ "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==",
"dev": true,
"license": "MIT",
"dependencies": {
@@ -5222,6 +5138,8 @@
},
"node_modules/concurrently/node_modules/chalk/node_modules/supports-color": {
"version": "7.2.0",
+ "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz",
+ "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==",
"dev": true,
"license": "MIT",
"dependencies": {
@@ -5231,6 +5149,22 @@
"node": ">=8"
}
},
+ "node_modules/concurrently/node_modules/supports-color": {
+ "version": "8.1.1",
+ "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz",
+ "integrity": "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "has-flag": "^4.0.0"
+ },
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/chalk/supports-color?sponsor=1"
+ }
+ },
"node_modules/confbox": {
"version": "0.1.8",
"resolved": "https://registry.npmjs.org/confbox/-/confbox-0.1.8.tgz",
@@ -5534,7 +5468,9 @@
"license": "MIT"
},
"node_modules/enhanced-resolve": {
- "version": "5.21.6",
+ "version": "5.25.1",
+ "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-5.25.1.tgz",
+ "integrity": "sha512-nGXts5znJzmWPu+mIE9izCOzdg63oJca2mDzGWWTth7sr4aCToKcoyFVBQwN75Ij5Pf6p510EwkTqViTRzDV+w==",
"dev": true,
"license": "MIT",
"dependencies": {
@@ -5580,7 +5516,9 @@
}
},
"node_modules/es-module-lexer": {
- "version": "2.2.0",
+ "version": "2.3.2",
+ "resolved": "https://registry.npmjs.org/es-module-lexer/-/es-module-lexer-2.3.2.tgz",
+ "integrity": "sha512-poHGpORABojJJucnV9KbOavETW8lBVnphkW77ER5/BQ5Fz7oXSoCNek7IH3vR5nRjdsEz926ibFYX8KtLQmdyw==",
"dev": true,
"license": "MIT"
},
@@ -5651,9 +5589,9 @@
}
},
"node_modules/eslint": {
- "version": "10.8.1",
- "resolved": "https://registry.npmjs.org/eslint/-/eslint-10.8.1.tgz",
- "integrity": "sha512-wqA7W2jbsC/BnV9Iv1UZpKVFkO1AdNoSmYW8NWG4HNOBbkAMvIqDZ27pI2f07dqn583NcIC44ckjAcOXDL1QbQ==",
+ "version": "10.11.0",
+ "resolved": "https://registry.npmjs.org/eslint/-/eslint-10.11.0.tgz",
+ "integrity": "sha512-P7a6UEEqb9G95MYAtqkmsTbVXIYyzIfl6NGOIJk162PaahFxFyeGcrlXYFSiagECg4sEm8IseJdZBKR3rx6MsQ==",
"dev": true,
"license": "MIT",
"workspaces": [
@@ -5665,7 +5603,7 @@
"@eslint/config-array": "^0.23.5",
"@eslint/config-helpers": "^0.7.0",
"@eslint/core": "^1.2.1",
- "@eslint/plugin-kit": "^0.7.2",
+ "@eslint/plugin-kit": "^0.7.3",
"@humanfs/node": "^0.16.6",
"@humanwhocodes/module-importer": "^1.0.1",
"@humanwhocodes/retry": "^0.4.2",
@@ -5680,7 +5618,7 @@
"esquery": "^1.7.0",
"esutils": "^2.0.2",
"fast-deep-equal": "^3.1.3",
- "file-entry-cache": "^8.0.0",
+ "file-entry-cache": "11.1.5 || >11.1.6 <12",
"find-up": "^5.0.0",
"glob-parent": "^6.0.2",
"ignore": "^5.2.0",
@@ -6014,16 +5952,13 @@
"license": "MIT"
},
"node_modules/file-entry-cache": {
- "version": "8.0.0",
- "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-8.0.0.tgz",
- "integrity": "sha512-XXTUwCvisa5oacNGRP9SfNtYBNAMi+RPwBFmblZEF7N7swHYQS6/Zfk7SRwx4D5j3CH211YNRco1DEMNVfZCnQ==",
+ "version": "11.1.5",
+ "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-11.1.5.tgz",
+ "integrity": "sha512-+PFTHITI08JIGhnNpGNI8T8inUpgZfk3GNEqfT9R2zZV2iFXg3CvqzSl/uEhs7TSGujYRELEANyDvS8Fj7+S7Q==",
"dev": true,
"license": "MIT",
"dependencies": {
- "flat-cache": "^4.0.0"
- },
- "engines": {
- "node": ">=16.0.0"
+ "flat-cache": "^6.1.23"
}
},
"node_modules/find-up": {
@@ -6056,17 +5991,15 @@
}
},
"node_modules/flat-cache": {
- "version": "4.0.1",
- "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-4.0.1.tgz",
- "integrity": "sha512-f7ccFPK3SXFHpx15UIGyRJ/FJQctuKZ0zVuN3frBo4HnK3cay9VEW0R6yPYFHC0AgqhukPzKjq22t5DmAyqGyw==",
+ "version": "6.1.23",
+ "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-6.1.23.tgz",
+ "integrity": "sha512-f++BY9pTk+983xK1FLzlLpmM0i0z+jHmx3QESGkURMXujQZz1k5wzwX6hjnQ8goaD0B+sYnDK1yZ6MTyZfUaqA==",
"dev": true,
"license": "MIT",
"dependencies": {
- "flatted": "^3.2.9",
- "keyv": "^4.5.4"
- },
- "engines": {
- "node": ">=16"
+ "cacheable": "^2.5.0",
+ "flatted": "^3.4.2",
+ "hookified": "^1.15.0"
}
},
"node_modules/flatted": {
@@ -6077,10 +6010,12 @@
"license": "ISC"
},
"node_modules/framer-motion": {
- "version": "12.42.2",
+ "version": "12.43.0",
+ "resolved": "https://registry.npmjs.org/framer-motion/-/framer-motion-12.43.0.tgz",
+ "integrity": "sha512-1eaL3RvR/kAlbG7UYcpMptEyzPoENO0c6w7ZnB3/hh2vSAz/6uGAFn6fdoqTBguNstf3MsFhJHsD/0DHiclG+g==",
"license": "MIT",
"dependencies": {
- "motion-dom": "^12.42.2",
+ "motion-dom": "^12.43.0",
"motion-utils": "^12.39.0",
"tslib": "^2.4.0"
},
@@ -6173,6 +6108,8 @@
},
"node_modules/graceful-fs": {
"version": "4.2.11",
+ "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz",
+ "integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==",
"dev": true,
"license": "ISC"
},
@@ -6184,6 +6121,19 @@
"node": ">=8"
}
},
+ "node_modules/hashery": {
+ "version": "1.5.1",
+ "resolved": "https://registry.npmjs.org/hashery/-/hashery-1.5.1.tgz",
+ "integrity": "sha512-iZyKG96/JwPz1N55vj2Ie2vXbhu440zfUfJvSwEqEbeLluk7NnapfGqa7LH0mOsnDxTF85Mx8/dyR6HfqcbmbQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "hookified": "^1.15.0"
+ },
+ "engines": {
+ "node": ">=20"
+ }
+ },
"node_modules/hast-util-from-parse5": {
"version": "8.0.3",
"license": "MIT",
@@ -6373,8 +6323,17 @@
"node": ">=16.9.0"
}
},
+ "node_modules/hookified": {
+ "version": "1.15.1",
+ "resolved": "https://registry.npmjs.org/hookified/-/hookified-1.15.1.tgz",
+ "integrity": "sha512-MvG/clsADq1GPM2KGo2nyfaWVyn9naPiXrqIe4jYjXNZQt238kWyOGrsyc/DmRAQ+Re6yeo6yX/yoNCG5KAEVg==",
+ "dev": true,
+ "license": "MIT"
+ },
"node_modules/html-encoding-sniffer": {
"version": "6.0.0",
+ "resolved": "https://registry.npmjs.org/html-encoding-sniffer/-/html-encoding-sniffer-6.0.0.tgz",
+ "integrity": "sha512-CV9TW3Y3f8/wT0BRFc1/KAVQ3TUHiXmaAb6VW9vtiMFf7SLoMd1PdAc4W3KFOFETBJUb90KatHqlsZMWV+R9Gg==",
"dev": true,
"license": "MIT",
"dependencies": {
@@ -6411,7 +6370,9 @@
}
},
"node_modules/immer": {
- "version": "10.2.0",
+ "version": "11.1.18",
+ "resolved": "https://registry.npmjs.org/immer/-/immer-11.1.18.tgz",
+ "integrity": "sha512-EQyQtLiYW029lyoczMl/Hh4Xu7cDecSc58JRYpHyL4tIAu3eqd1yJzQX04d2BZHDkzFFvm6qJEJWOtfDSWAXbQ==",
"license": "MIT",
"funding": {
"type": "opencollective",
@@ -6560,6 +6521,8 @@
},
"node_modules/is-potential-custom-element-name": {
"version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/is-potential-custom-element-name/-/is-potential-custom-element-name-1.0.1.tgz",
+ "integrity": "sha512-bCYeRA2rVibKZd+s2625gGnGF/t7DSqDs4dP7CrLA1m7jKWz6pps0LpYLJN8Q64HtmPKJ1hrN3nzPNKFEKOUiQ==",
"dev": true,
"license": "MIT"
},
@@ -6606,6 +6569,8 @@
},
"node_modules/jsdom": {
"version": "29.1.1",
+ "resolved": "https://registry.npmjs.org/jsdom/-/jsdom-29.1.1.tgz",
+ "integrity": "sha512-ECi4Fi2f7BdJtUKTflYRTiaMxIB0O6zfR1fX0GXpUrf6flp8QIYn1UT20YQqdSOfk2dfkCwS8LAFoJDEppNK5Q==",
"dev": true,
"license": "MIT",
"dependencies": {
@@ -6656,13 +6621,6 @@
"node": ">=6"
}
},
- "node_modules/json-buffer": {
- "version": "3.0.1",
- "resolved": "https://registry.npmjs.org/json-buffer/-/json-buffer-3.0.1.tgz",
- "integrity": "sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ==",
- "dev": true,
- "license": "MIT"
- },
"node_modules/json-schema-traverse": {
"version": "0.4.1",
"resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz",
@@ -6700,13 +6658,13 @@
}
},
"node_modules/keyv": {
- "version": "4.5.4",
- "resolved": "https://registry.npmjs.org/keyv/-/keyv-4.5.4.tgz",
- "integrity": "sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw==",
+ "version": "5.6.0",
+ "resolved": "https://registry.npmjs.org/keyv/-/keyv-5.6.0.tgz",
+ "integrity": "sha512-CYDD3SOtsHtyXeEORYRx2qBtpDJFjRTGXUtmNEMGyzYOKj1TE3tycdlho7kA1Ufx9OYWZzg52QFBGALTirzDSw==",
"dev": true,
"license": "MIT",
"dependencies": {
- "json-buffer": "3.0.1"
+ "@keyv/serialize": "^1.1.1"
}
},
"node_modules/kleur": {
@@ -6764,6 +6722,8 @@
},
"node_modules/lightningcss": {
"version": "1.32.0",
+ "resolved": "https://registry.npmjs.org/lightningcss/-/lightningcss-1.32.0.tgz",
+ "integrity": "sha512-NXYBzinNrblfraPGyrbPoD19C1h9lfI/1mzgWYvXUTe414Gz/X1FD2XBZSZM7rRTrMA8JL3OtAaGifrIKhQ5yQ==",
"dev": true,
"license": "MPL-2.0",
"dependencies": {
@@ -7014,6 +6974,8 @@
},
"node_modules/lightningcss-win32-x64-msvc": {
"version": "1.32.0",
+ "resolved": "https://registry.npmjs.org/lightningcss-win32-x64-msvc/-/lightningcss-win32-x64-msvc-1.32.0.tgz",
+ "integrity": "sha512-Amq9B/SoZYdDi1kFrojnoqPLxYhQ4Wo5XiL8EVJrVsB8ARoC1PWW6VGtT0WKCemjy8aC+louJnjS7U18x3b06Q==",
"cpu": [
"x64"
],
@@ -7101,7 +7063,9 @@
}
},
"node_modules/lru-cache": {
- "version": "11.5.1",
+ "version": "11.5.3",
+ "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-11.5.3.tgz",
+ "integrity": "sha512-U4N8FgzmWxc8k1VH8Kr6lQg18U7Fjvby6wXHVRX/ZZ7IwWbRMgrRbP0Wrb5q5NVinryp4SQampHKdvtecItxUg==",
"dev": true,
"license": "BlueOak-1.0.0",
"engines": {
@@ -7109,7 +7073,9 @@
}
},
"node_modules/lucide-react": {
- "version": "1.22.0",
+ "version": "1.47.0",
+ "resolved": "https://registry.npmjs.org/lucide-react/-/lucide-react-1.47.0.tgz",
+ "integrity": "sha512-o8C23aXpNQypRY73W7fW02EyvWJinEMXgKeGjFoKym0zj3Q73hD97A1IQps1g8C14HTGsOpZL0Am+xjfgFZAbg==",
"license": "ISC",
"peerDependencies": {
"react": "^16.5.1 || ^17.0.0 || ^18.0.0 || ^19.0.0"
@@ -7960,16 +7926,16 @@
}
},
"node_modules/miniflare": {
- "version": "5.20260918.0-alpha",
- "resolved": "https://registry.npmjs.org/miniflare/-/miniflare-5.20260918.0-alpha.tgz",
- "integrity": "sha512-vyIes7yW/OTzHtz4GhcBCTohZfqk2eQNiIkngZ07VRA5Qu24aNgW/TrFwlPkMLMjWDQ8R4JJBBHR/KX+liSDtg==",
+ "version": "5.20260921.0-alpha",
+ "resolved": "https://registry.npmjs.org/miniflare/-/miniflare-5.20260921.0-alpha.tgz",
+ "integrity": "sha512-vHH/unOYvV2jA1Q9SdkmzrQhhMoksdwg5jegu6ZeKaaRzgxZhVbt1NdTpQjHF2VTgiBjgP8SiUlUMfruB3N3SQ==",
"dev": true,
"license": "MIT",
"dependencies": {
"@cspotcode/source-map-support": "0.8.1",
"sharp": "0.35.4",
"undici": "7.29.0",
- "workerd": "1.20260918.1",
+ "workerd": "1.20260921.1",
"ws": "8.21.0",
"youch": "4.1.0-beta.10"
},
@@ -8007,10 +7973,12 @@
}
},
"node_modules/motion": {
- "version": "12.42.2",
+ "version": "12.43.0",
+ "resolved": "https://registry.npmjs.org/motion/-/motion-12.43.0.tgz",
+ "integrity": "sha512-BQgQbSa9Hn3/mtbib0MK53y6JSANa+YKUKlaYnWzAVDH424RYQ5LVpV3pNiWH00BA2z4ojsSdMzqT7g2FQwjuQ==",
"license": "MIT",
"dependencies": {
- "framer-motion": "^12.42.2",
+ "framer-motion": "^12.43.0",
"tslib": "^2.4.0"
},
"peerDependencies": {
@@ -8031,7 +7999,9 @@
}
},
"node_modules/motion-dom": {
- "version": "12.42.2",
+ "version": "12.43.0",
+ "resolved": "https://registry.npmjs.org/motion-dom/-/motion-dom-12.43.0.tgz",
+ "integrity": "sha512-azKON4d9S65PEoFUiQTMTgPheEmzf2QngdRc50AKfJp9Q9mmcBVw22c8eMq9k8kxOFHdL7+WZY7N/5F/lwiDag==",
"license": "MIT",
"dependencies": {
"motion-utils": "^12.39.0"
@@ -8039,6 +8009,8 @@
},
"node_modules/motion-utils": {
"version": "12.39.0",
+ "resolved": "https://registry.npmjs.org/motion-utils/-/motion-utils-12.39.0.tgz",
+ "integrity": "sha512-8nadJAJjTtqRkmRF36FoJTrywK9nnFmnPwnSMyxaOCU7GDjN9RTMJIxx9De8ErM+vpPhMccr/6fo5WciyQLnMQ==",
"license": "MIT"
},
"node_modules/mri": {
@@ -8210,7 +8182,9 @@
}
},
"node_modules/obug": {
- "version": "2.1.3",
+ "version": "2.2.1",
+ "resolved": "https://registry.npmjs.org/obug/-/obug-2.2.1.tgz",
+ "integrity": "sha512-XrsrhT5sybtKI6wakr2SPOlGZWWYbUXZ7a0jT8/QOeAPau+1X/bSegNe5YR75oJmEZQbKningirmGOEJCIk61Q==",
"dev": true,
"funding": [
"https://github.com/sponsors/sxzz",
@@ -8398,9 +8372,9 @@
"license": "ISC"
},
"node_modules/picomatch": {
- "version": "4.0.5",
- "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.5.tgz",
- "integrity": "sha512-RvwwcruNjI1ncT5xRakeyS9Lf8lcItv34KD+aif+VH9kduAyfYBipGh12274xtenIPZ119/R9BdTBa8gAwSh0A==",
+ "version": "4.0.7",
+ "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.7.tgz",
+ "integrity": "sha512-qcJu88Q2IWqJsDD529JKMdwGm/dvInW4HvQnRwiH9JtihJvzGOscDtHE3x1pBKeUOTysQ8kVmLnJ2kJu7yhcGA==",
"license": "MIT",
"engines": {
"node": ">=12"
@@ -8432,9 +8406,9 @@
}
},
"node_modules/postcss": {
- "version": "8.5.26",
- "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.5.26.tgz",
- "integrity": "sha512-u82N74LFzG8ca+dD8puPnplTXoGH4fTPpVGuIbt36G3qvNlkvfD0lEAZSxaly3KX8TS/L1A1gsCEmvKmBcVbkQ==",
+ "version": "8.5.28",
+ "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.5.28.tgz",
+ "integrity": "sha512-RRuzqDtt5Y9h3quz5hWhK+TPnsmVs6WwSU6LkJMeY4HstUEDuYTG8UJSdawMRzmzAtV+KEoG8N3Qg2qLy5vM/A==",
"dev": true,
"funding": [
{
@@ -8452,7 +8426,7 @@
],
"license": "MIT",
"dependencies": {
- "nanoid": "^3.3.17",
+ "nanoid": "^3.3.18",
"picocolors": "^1.1.1",
"source-map-js": "^1.2.1"
},
@@ -8582,14 +8556,14 @@
}
},
"node_modules/publint": {
- "version": "0.3.23",
- "resolved": "https://registry.npmjs.org/publint/-/publint-0.3.23.tgz",
- "integrity": "sha512-5MQipUPcB7MWw84zLUkHrg/H/UBtk3LL+A0GngTTBSsiNJLQurMUaSIRG3edlOrRz4UFe0AOKK9TZdIWviV+jQ==",
+ "version": "0.3.24",
+ "resolved": "https://registry.npmjs.org/publint/-/publint-0.3.24.tgz",
+ "integrity": "sha512-9zS56KrKBoqi5Qt8h92uMP8TTM9AYZSgnmCo4u2priMqkOZvQnTsziZ2p5LJ2ywbYkAjoCDp2jda9u4cgFefIw==",
"dev": true,
"license": "MIT",
"dependencies": {
- "@publint/pack": "^0.1.6",
- "package-manager-detector": "^1.7.0",
+ "@publint/pack": "^0.1.7",
+ "package-manager-detector": "^1.8.0",
"picocolors": "^1.1.1",
"sade": "^1.8.1"
},
@@ -8611,25 +8585,45 @@
"node": ">=6"
}
},
+ "node_modules/qified": {
+ "version": "0.10.1",
+ "resolved": "https://registry.npmjs.org/qified/-/qified-0.10.1.tgz",
+ "integrity": "sha512-+Owyggi9IxT1ePKGafcI87ubSmxol6smwJ+RAHDQlx9+9cPwFWDiKFFCPuWhr9ignlGpZ9vDQLw67N4dcTVFEA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "hookified": "^2.1.1"
+ },
+ "engines": {
+ "node": ">=20"
+ }
+ },
+ "node_modules/qified/node_modules/hookified": {
+ "version": "2.2.0",
+ "resolved": "https://registry.npmjs.org/hookified/-/hookified-2.2.0.tgz",
+ "integrity": "sha512-p/LgFzRN5FeoD3DLS6bkUapeye6E4SI6yJs6KetENd18S+FBthqYq2amJUWpt5z0EQwwHemidjY5OqJGEKm5uA==",
+ "dev": true,
+ "license": "MIT"
+ },
"node_modules/react": {
- "version": "19.2.8",
- "resolved": "https://registry.npmjs.org/react/-/react-19.2.8.tgz",
- "integrity": "sha512-PWaYA1L/q9u2u7xYQi+Y3L3Yfnie7XyLeaJICV1MGD6LprsBxcAqGjYyr0eY3p+QdsA+x/Irkt4Qif8D63+Sbw==",
+ "version": "19.3.0",
+ "resolved": "https://registry.npmjs.org/react/-/react-19.3.0.tgz",
+ "integrity": "sha512-E8LUcbtBWt20bbl2YoHfx4ZDBdxVTfOKtCZn9cDSJ4l6/nuoApcpIBcj47t2wZoVX8g2ZHuMHbiShgCR1T5Sog==",
"license": "MIT",
"engines": {
"node": ">=0.10.0"
}
},
"node_modules/react-dom": {
- "version": "19.2.8",
- "resolved": "https://registry.npmjs.org/react-dom/-/react-dom-19.2.8.tgz",
- "integrity": "sha512-rVprimfGBG3DR+Tq0IQG2DT5PxKth1WIGDmj5yPmlzr4YBe7uyE+Du4oVqTDXZSHGGGXRtTJEGSSePyQCMBglQ==",
+ "version": "19.3.0",
+ "resolved": "https://registry.npmjs.org/react-dom/-/react-dom-19.3.0.tgz",
+ "integrity": "sha512-JDk8dgif51OjFoDE70+OT9ICyYr+69HlmihNwp1+Nsfbna3t5sIiCa9ZJktDmQ4/1b/rn26hIAR2uYXDMr5r0Q==",
"license": "MIT",
"dependencies": {
- "scheduler": "^0.27.0"
+ "scheduler": "^0.28.0"
},
"peerDependencies": {
- "react": "^19.2.8"
+ "react": "^19.3.0"
}
},
"node_modules/react-is": {
@@ -8684,9 +8678,9 @@
}
},
"node_modules/react-router": {
- "version": "7.18.2",
- "resolved": "https://registry.npmjs.org/react-router/-/react-router-7.18.2.tgz",
- "integrity": "sha512-aUVMjFm3GAPTTZL7oYr5E7ETiqfQCHRLH+B+5afnICvf0r7kkK4eR6SMuwbSTJw/7t+12khT/Kahij49fqOCIg==",
+ "version": "7.18.4",
+ "resolved": "https://registry.npmjs.org/react-router/-/react-router-7.18.4.tgz",
+ "integrity": "sha512-PUPQcMhMGRAslLcvtlPz/kmzBEWPhLdgLFrL7pLNepBL6dX0lWj4WD2cUYVgYCuT3jxvghYFg81cDTj44DhetQ==",
"license": "MIT",
"dependencies": {
"cookie": "^1.0.1",
@@ -8706,12 +8700,12 @@
}
},
"node_modules/react-router-dom": {
- "version": "7.18.2",
- "resolved": "https://registry.npmjs.org/react-router-dom/-/react-router-dom-7.18.2.tgz",
- "integrity": "sha512-AIKJ/jgGlFb3EbfCXk5Gzshiwt+l3mqbCrNjmEWMMjqQxNJ3svBa6bgzFyCC2Sw3RA0VWF1kg3uQf2OFhxb8hw==",
+ "version": "7.18.4",
+ "resolved": "https://registry.npmjs.org/react-router-dom/-/react-router-dom-7.18.4.tgz",
+ "integrity": "sha512-yrfmJHIpDG7taCpqKjT1G5B6q3O2K+RN8/fgNf0lTjCwiPbQ0ei6vXX9ZjQR+7ld8Tr7Z5xmyMnZ8YJrphWQUw==",
"license": "MIT",
"dependencies": {
- "react-router": "7.18.2"
+ "react-router": "7.18.4"
},
"engines": {
"node": ">=20.0.0"
@@ -8736,7 +8730,9 @@
}
},
"node_modules/recharts": {
- "version": "3.9.0",
+ "version": "3.10.1",
+ "resolved": "https://registry.npmjs.org/recharts/-/recharts-3.10.1.tgz",
+ "integrity": "sha512-QXFrvt6IVcw7eeZCoyXTwkIJAX3Dv1nyVhMicXJ47GsGDDpcN8z6o644DibE9XjpBTThtsomLKnTV6lc+cVFUA==",
"license": "MIT",
"workspaces": [
"www"
@@ -8747,7 +8743,7 @@
"decimal.js-light": "^2.5.1",
"es-toolkit": "^1.39.3",
"eventemitter3": "^5.0.1",
- "immer": "^10.1.1",
+ "immer": "^11.1.8",
"react-redux": "8.x.x || 9.x.x",
"reselect": "5.2.0",
"tiny-invariant": "^1.3.3",
@@ -8876,6 +8872,8 @@
},
"node_modules/require-from-string": {
"version": "2.0.2",
+ "resolved": "https://registry.npmjs.org/require-from-string/-/require-from-string-2.0.2.tgz",
+ "integrity": "sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw==",
"dev": true,
"license": "MIT",
"engines": {
@@ -8922,11 +8920,13 @@
}
},
"node_modules/rolldown": {
- "version": "1.1.3",
+ "version": "1.2.9",
+ "resolved": "https://registry.npmjs.org/rolldown/-/rolldown-1.2.9.tgz",
+ "integrity": "sha512-hx/Pv0N1haXRb11qkfnK5MXB/iqr7i0yjWQqmO9uHqZpBgQSqzc8UsSnEpalsh+j1I8qQ2CkXAkJC8Br3dKSlg==",
"dev": true,
"license": "MIT",
"dependencies": {
- "@oxc-project/types": "=0.137.0",
+ "@oxc-project/types": "=0.150.0",
"@rolldown/pluginutils": "^1.0.0"
},
"bin": {
@@ -8936,21 +8936,21 @@
"node": "^20.19.0 || >=22.12.0"
},
"optionalDependencies": {
- "@rolldown/binding-android-arm64": "1.1.3",
- "@rolldown/binding-darwin-arm64": "1.1.3",
- "@rolldown/binding-darwin-x64": "1.1.3",
- "@rolldown/binding-freebsd-x64": "1.1.3",
- "@rolldown/binding-linux-arm-gnueabihf": "1.1.3",
- "@rolldown/binding-linux-arm64-gnu": "1.1.3",
- "@rolldown/binding-linux-arm64-musl": "1.1.3",
- "@rolldown/binding-linux-ppc64-gnu": "1.1.3",
- "@rolldown/binding-linux-s390x-gnu": "1.1.3",
- "@rolldown/binding-linux-x64-gnu": "1.1.3",
- "@rolldown/binding-linux-x64-musl": "1.1.3",
- "@rolldown/binding-openharmony-arm64": "1.1.3",
- "@rolldown/binding-wasm32-wasi": "1.1.3",
- "@rolldown/binding-win32-arm64-msvc": "1.1.3",
- "@rolldown/binding-win32-x64-msvc": "1.1.3"
+ "@rolldown/binding-android-arm-eabi": "1.2.9",
+ "@rolldown/binding-android-arm64": "1.2.9",
+ "@rolldown/binding-darwin-arm64": "1.2.9",
+ "@rolldown/binding-darwin-x64": "1.2.9",
+ "@rolldown/binding-freebsd-x64": "1.2.9",
+ "@rolldown/binding-linux-arm-gnueabihf": "1.2.9",
+ "@rolldown/binding-linux-arm64-gnu": "1.2.9",
+ "@rolldown/binding-linux-arm64-musl": "1.2.9",
+ "@rolldown/binding-linux-ppc64-gnu": "1.2.9",
+ "@rolldown/binding-linux-s390x-gnu": "1.2.9",
+ "@rolldown/binding-linux-x64-gnu": "1.2.9",
+ "@rolldown/binding-linux-x64-musl": "1.2.9",
+ "@rolldown/binding-openharmony-arm64": "1.2.9",
+ "@rolldown/binding-win32-arm64-msvc": "1.2.9",
+ "@rolldown/binding-win32-x64-msvc": "1.2.9"
}
},
"node_modules/rollup": {
@@ -9032,7 +9032,9 @@
}
},
"node_modules/scheduler": {
- "version": "0.27.0",
+ "version": "0.28.0",
+ "resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.28.0.tgz",
+ "integrity": "sha512-juorfCmIkIw8tT+p5BXSm6PJjQF/ycEYmKyzURCIt/RaZIhL+PulbQ9Yu2z1HdOJDdqDTlxA1+xKBmHXJsczAw==",
"license": "MIT"
},
"node_modules/semver": {
@@ -9174,11 +9176,19 @@
}
},
"node_modules/sonner": {
- "version": "2.0.7",
+ "version": "2.0.8",
+ "resolved": "https://registry.npmjs.org/sonner/-/sonner-2.0.8.tgz",
+ "integrity": "sha512-UM/ByIoFra8yzV75n1o0Puu0bw5U/9UNnDacrJNspekBewIfsQ3D6ez1nvlWpt7aTsO6rujQtifBpycwIivqlg==",
"license": "MIT",
"peerDependencies": {
+ "@types/react": "^18.0.0 || ^19.0.0",
"react": "^18.0.0 || ^19.0.0 || ^19.0.0-rc",
"react-dom": "^18.0.0 || ^19.0.0 || ^19.0.0-rc"
+ },
+ "peerDependenciesMeta": {
+ "@types/react": {
+ "optional": true
+ }
}
},
"node_modules/source-map": {
@@ -9229,7 +9239,9 @@
"license": "MIT"
},
"node_modules/std-env": {
- "version": "4.1.0",
+ "version": "4.2.0",
+ "resolved": "https://registry.npmjs.org/std-env/-/std-env-4.2.0.tgz",
+ "integrity": "sha512-oCUKSupKTHX53EyjDtuZQ64pjLJ6yYCtpmEw0goYxtjG9KpbRe8KAsl2tBUGU9DyMcJ0RwJ8GqJAFzMXcXW1Rw==",
"dev": true,
"license": "MIT"
},
@@ -9344,20 +9356,27 @@
}
},
"node_modules/sugar-high": {
- "version": "2.0.0",
- "resolved": "https://registry.npmjs.org/sugar-high/-/sugar-high-2.0.0.tgz",
- "integrity": "sha512-qZQaa+3vbmKSx00G465bY1LqVUU0RaUkY/7xDV63cQzezD6dF/DJCthztRQqYLGA7HXdObvCEtcCRpvoIrrbCg==",
- "license": "MIT"
+ "version": "2.4.1",
+ "resolved": "https://registry.npmjs.org/sugar-high/-/sugar-high-2.4.1.tgz",
+ "integrity": "sha512-w4uhunMgEP+9f/2W/ZLBjvrVBLY14oL4b6a2+Ca/JWECd0Rc45KqL89bDvUOVFGrr0D14q5hoEqBXkgxwxL6RQ==",
+ "license": "MIT",
+ "peerDependencies": {
+ "gpu-lexer": ">=0.0.2"
+ },
+ "peerDependenciesMeta": {
+ "gpu-lexer": {
+ "optional": true
+ }
+ }
},
"node_modules/supports-color": {
- "version": "8.1.1",
+ "version": "10.2.2",
+ "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-10.2.2.tgz",
+ "integrity": "sha512-SS+jx45GF1QjgEXQx4NJZV9ImqmO2NPz5FNsIHrsDjh2YsHnawpan7SNQ1o8NuhrbHZy9AZhIoCUiCeaW/C80g==",
"dev": true,
"license": "MIT",
- "dependencies": {
- "has-flag": "^4.0.0"
- },
"engines": {
- "node": ">=10"
+ "node": ">=18"
},
"funding": {
"url": "https://github.com/chalk/supports-color?sponsor=1"
@@ -9395,11 +9414,15 @@
},
"node_modules/symbol-tree": {
"version": "3.2.4",
+ "resolved": "https://registry.npmjs.org/symbol-tree/-/symbol-tree-3.2.4.tgz",
+ "integrity": "sha512-9QNk5KwDF+Bvz+PyObkmSYjI5ksVUYtjW7AU22r2NKcfLJcXp96hkDWU3+XndOsUb+AQ9QhfzfCT2O+CNWT5Tw==",
"dev": true,
"license": "MIT"
},
"node_modules/tailwind-merge": {
- "version": "3.6.0",
+ "version": "3.7.0",
+ "resolved": "https://registry.npmjs.org/tailwind-merge/-/tailwind-merge-3.7.0.tgz",
+ "integrity": "sha512-XPPUyAc+cvspz3lHTcR/QgPfW2A0lv/xQNIjX3HGhLR+Nq2lHaLq5MtTesHn8GUr3W3DguT2KT5x3NVgRtYwmA==",
"license": "MIT",
"funding": {
"type": "github",
@@ -9407,12 +9430,16 @@
}
},
"node_modules/tailwindcss": {
- "version": "4.3.2",
+ "version": "4.3.3",
+ "resolved": "https://registry.npmjs.org/tailwindcss/-/tailwindcss-4.3.3.tgz",
+ "integrity": "sha512-gOhV3P7ufE62QDGg1zVaTgCR+EtPv92k2nIhVcVKcLmxT1sUBsQGhnZj175j+MqRt4zLF7ic+sCYjfhxMxj7YQ==",
"dev": true,
"license": "MIT"
},
"node_modules/tapable": {
"version": "2.3.3",
+ "resolved": "https://registry.npmjs.org/tapable/-/tapable-2.3.3.tgz",
+ "integrity": "sha512-uxc/zpqFg6x7C8vOE7lh6Lbda8eEL9zmVm/PLeTPBRhh1xCgdWaQ+J1CUieGpIfm2HdtsUpRv+HshiasBMcc6A==",
"dev": true,
"license": "MIT",
"engines": {
@@ -9452,6 +9479,8 @@
},
"node_modules/tinybench": {
"version": "2.9.0",
+ "resolved": "https://registry.npmjs.org/tinybench/-/tinybench-2.9.0.tgz",
+ "integrity": "sha512-0+DUvqWMValLmha6lr4kD8iAMK1HzV0/aKnCtWb9v9641TnP/MFb7Pc2bxoxQjTXAErryXVgUOfv2YqNllqGeg==",
"dev": true,
"license": "MIT"
},
@@ -9491,23 +9520,29 @@
}
},
"node_modules/tldts": {
- "version": "7.4.5",
+ "version": "7.4.14",
+ "resolved": "https://registry.npmjs.org/tldts/-/tldts-7.4.14.tgz",
+ "integrity": "sha512-EahQoi+Q5oqmG3yxRHx+bwn36OaLbtw6jnTFcGjc8fcmktzTgk45xRnzAx8Ch87PFEiqRhoc3FWBmY+LBrvEGQ==",
"dev": true,
"license": "MIT",
"dependencies": {
- "tldts-core": "^7.4.5"
+ "tldts-core": "^7.4.14"
},
"bin": {
"tldts": "bin/cli.js"
}
},
"node_modules/tldts-core": {
- "version": "7.4.5",
+ "version": "7.4.14",
+ "resolved": "https://registry.npmjs.org/tldts-core/-/tldts-core-7.4.14.tgz",
+ "integrity": "sha512-KYkjfJHnIC5t+Gy7hPrMHgJmWc/N9FfmS+fggRPSlpFckidpB9HD6OzPsSTkfDH+MpZgcu2tJPGgLfHl979N1Q==",
"dev": true,
"license": "MIT"
},
"node_modules/tough-cookie": {
- "version": "6.0.1",
+ "version": "6.0.2",
+ "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-6.0.2.tgz",
+ "integrity": "sha512-exgYmnmL/sJpR3upZfXG5PoatXQii55xAiXGXzY+sROLZ/Y+SLcp9PgJNI9Vz37HpQ74WvDcLT8eqm+kV3FzrA==",
"dev": true,
"license": "BSD-3-Clause",
"dependencies": {
@@ -10135,6 +10170,8 @@
},
"node_modules/typescript": {
"version": "6.0.3",
+ "resolved": "https://registry.npmjs.org/typescript/-/typescript-6.0.3.tgz",
+ "integrity": "sha512-y2TvuxSZPDyQakkFRPZHKFm+KKVqIisdg9/CZwm9ftvKXLP8NRWj38/ODjNbr43SsoXqNuAisEf1GdCxqWcdBw==",
"dev": true,
"license": "Apache-2.0",
"bin": {
@@ -10146,16 +10183,70 @@
}
},
"node_modules/typescript-eslint": {
- "version": "8.66.0",
- "resolved": "https://registry.npmjs.org/typescript-eslint/-/typescript-eslint-8.66.0.tgz",
- "integrity": "sha512-QlEbBPz/RuJ1XUHj29nm3t0F/O/cSlEnntozqPOYHnnTGAXFamnMBu5i9Vn6vhUPHGAjR+Vl+5J8vPN/BMUrJw==",
+ "version": "8.70.1",
+ "resolved": "https://registry.npmjs.org/typescript-eslint/-/typescript-eslint-8.70.1.tgz",
+ "integrity": "sha512-AcWG7KDjZ2THNXsgwttMaGmzVi0VFRlFYfqFHYQRbDpF3owuYbuiL8c7UUrd2k8s3PoSfIQrWfrGXfcElrWLYA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@typescript-eslint/eslint-plugin": "8.70.1",
+ "@typescript-eslint/parser": "8.70.1",
+ "@typescript-eslint/typescript-estree": "8.70.1",
+ "@typescript-eslint/utils": "8.70.1"
+ },
+ "engines": {
+ "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/typescript-eslint"
+ },
+ "peerDependencies": {
+ "eslint": "^8.57.0 || ^9.0.0 || ^10.0.0",
+ "typescript": ">=4.8.4 <6.1.0"
+ }
+ },
+ "node_modules/typescript-eslint/node_modules/@typescript-eslint/eslint-plugin": {
+ "version": "8.70.1",
+ "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.70.1.tgz",
+ "integrity": "sha512-nDNrUQ/4ruSNYbu749TRY7cfrzPtoLHEXSNBI8aaNY32LlZCajixqRf3FqcKC4p5Cam4VOHYx/t+i5+nKXvrqA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@eslint-community/regexpp": "^4.12.2",
+ "@typescript-eslint/scope-manager": "8.70.1",
+ "@typescript-eslint/type-utils": "8.70.1",
+ "@typescript-eslint/utils": "8.70.1",
+ "@typescript-eslint/visitor-keys": "8.70.1",
+ "ignore": "^7.0.5",
+ "natural-compare": "^1.4.0",
+ "ts-api-utils": "^2.5.0"
+ },
+ "engines": {
+ "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/typescript-eslint"
+ },
+ "peerDependencies": {
+ "@typescript-eslint/parser": "^8.70.1",
+ "eslint": "^8.57.0 || ^9.0.0 || ^10.0.0",
+ "typescript": ">=4.8.4 <6.1.0"
+ }
+ },
+ "node_modules/typescript-eslint/node_modules/@typescript-eslint/eslint-plugin/node_modules/@typescript-eslint/type-utils": {
+ "version": "8.70.1",
+ "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-8.70.1.tgz",
+ "integrity": "sha512-7zKTnyvaVWqzLZHPFQtX1hVHqgkMC+WebPWakNCSyrQVbIP1AM0L0TlBZtACldIRb6PptI8Odk+jyZ5kP3B1VA==",
"dev": true,
"license": "MIT",
"dependencies": {
- "@typescript-eslint/eslint-plugin": "8.66.0",
- "@typescript-eslint/parser": "8.66.0",
- "@typescript-eslint/typescript-estree": "8.66.0",
- "@typescript-eslint/utils": "8.66.0"
+ "@typescript-eslint/types": "8.70.1",
+ "@typescript-eslint/typescript-estree": "8.70.1",
+ "@typescript-eslint/utils": "8.70.1",
+ "debug": "^4.4.3",
+ "ts-api-utils": "^2.5.0"
},
"engines": {
"node": "^18.18.0 || ^20.9.0 || >=21.1.0"
@@ -10169,6 +10260,132 @@
"typescript": ">=4.8.4 <6.1.0"
}
},
+ "node_modules/typescript-eslint/node_modules/@typescript-eslint/parser": {
+ "version": "8.70.1",
+ "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-8.70.1.tgz",
+ "integrity": "sha512-nO974WLllwhSFWQXnMLj6nDGa8f0khKEz1JzpPJ1u7Vm/4X1X6ZHajpoknU4bb41vJyMB0HHVyS2GqdhWfIXZw==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@typescript-eslint/scope-manager": "8.70.1",
+ "@typescript-eslint/types": "8.70.1",
+ "@typescript-eslint/typescript-estree": "8.70.1",
+ "@typescript-eslint/visitor-keys": "8.70.1",
+ "debug": "^4.4.3"
+ },
+ "engines": {
+ "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/typescript-eslint"
+ },
+ "peerDependencies": {
+ "eslint": "^8.57.0 || ^9.0.0 || ^10.0.0",
+ "typescript": ">=4.8.4 <6.1.0"
+ }
+ },
+ "node_modules/typescript-eslint/node_modules/@typescript-eslint/typescript-estree": {
+ "version": "8.70.1",
+ "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-8.70.1.tgz",
+ "integrity": "sha512-TU8PwyGN0PQJUcE96mw8eCQ44SmxGdQlJmlWakHaHQ15eIuuvye5yNtmh/i6oS88jzXVQB71xdNkbkB/fMwL0g==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@typescript-eslint/project-service": "8.70.1",
+ "@typescript-eslint/tsconfig-utils": "8.70.1",
+ "@typescript-eslint/types": "8.70.1",
+ "@typescript-eslint/visitor-keys": "8.70.1",
+ "debug": "^4.4.3",
+ "minimatch": "^10.2.2",
+ "semver": "^7.7.3",
+ "tinyglobby": "^0.2.15",
+ "ts-api-utils": "^2.5.0"
+ },
+ "engines": {
+ "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/typescript-eslint"
+ },
+ "peerDependencies": {
+ "typescript": ">=4.8.4 <6.1.0"
+ }
+ },
+ "node_modules/typescript-eslint/node_modules/@typescript-eslint/typescript-estree/node_modules/@typescript-eslint/project-service": {
+ "version": "8.70.1",
+ "resolved": "https://registry.npmjs.org/@typescript-eslint/project-service/-/project-service-8.70.1.tgz",
+ "integrity": "sha512-62xOgboPfwc3/IgPSX/W6oQR3ZbF04194FPGUGH8HL8iLFHbt/456/8Ph1wLNUgVF+s94FlHoipBsz+v7+LMnA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@typescript-eslint/tsconfig-utils": "^8.70.1",
+ "@typescript-eslint/types": "^8.70.1",
+ "debug": "^4.4.3"
+ },
+ "engines": {
+ "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/typescript-eslint"
+ },
+ "peerDependencies": {
+ "typescript": ">=4.8.4 <6.1.0"
+ }
+ },
+ "node_modules/typescript-eslint/node_modules/@typescript-eslint/typescript-estree/node_modules/@typescript-eslint/tsconfig-utils": {
+ "version": "8.70.1",
+ "resolved": "https://registry.npmjs.org/@typescript-eslint/tsconfig-utils/-/tsconfig-utils-8.70.1.tgz",
+ "integrity": "sha512-jumze1fPI+sDOaM2TWGQdn39PDxTr7TZGeuyLkAbNyx2vtMT3uRnVKChN0hfht5V2TugphJzF6bYXvBcE09qqg==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/typescript-eslint"
+ },
+ "peerDependencies": {
+ "typescript": ">=4.8.4 <6.1.0"
+ }
+ },
+ "node_modules/typescript-eslint/node_modules/@typescript-eslint/utils": {
+ "version": "8.70.1",
+ "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-8.70.1.tgz",
+ "integrity": "sha512-Esgul8MsnKnRLdYU2Eb2cRV9bS5HJYtKj1ByJnOzzG2M58DGdSUQ1jUuILxipqcpB2h9WLrbD5GijIWUjX/Tqw==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@eslint-community/eslint-utils": "^4.9.1",
+ "@typescript-eslint/scope-manager": "8.70.1",
+ "@typescript-eslint/types": "8.70.1",
+ "@typescript-eslint/typescript-estree": "8.70.1"
+ },
+ "engines": {
+ "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/typescript-eslint"
+ },
+ "peerDependencies": {
+ "eslint": "^8.57.0 || ^9.0.0 || ^10.0.0",
+ "typescript": ">=4.8.4 <6.1.0"
+ }
+ },
+ "node_modules/typescript-eslint/node_modules/ignore": {
+ "version": "7.0.10",
+ "resolved": "https://registry.npmjs.org/ignore/-/ignore-7.0.10.tgz",
+ "integrity": "sha512-HpbUakT7xp5miBUywCHf36ZEuAJNklBJDDsGpUIjMzOSmM8ELSfA9Sa/QDPeNeqeoN31u+UTCkL4klCOVvRm4Q==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">= 4"
+ }
+ },
"node_modules/ufo": {
"version": "1.6.4",
"resolved": "https://registry.npmjs.org/ufo/-/ufo-1.6.4.tgz",
@@ -10188,11 +10405,15 @@
},
"node_modules/undici-types": {
"version": "7.24.6",
+ "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-7.24.6.tgz",
+ "integrity": "sha512-WRNW+sJgj5OBN4/0JpHFqtqzhpbnV0GuB+OozA9gCL7a993SmU+1JBZCzLNxYsbMfIeDL+lTsphD5jN5N+n0zg==",
"dev": true,
"license": "MIT"
},
"node_modules/unenv": {
"version": "2.0.0-rc.24",
+ "resolved": "https://registry.npmjs.org/unenv/-/unenv-2.0.0-rc.24.tgz",
+ "integrity": "sha512-i7qRCmY42zmCwnYlh9H2SvLEypEFGye5iRmEMKjcGi7zk9UquigRjFtTLz0TYqr0ZGLZhaMHl/foy1bZR+Cwlw==",
"dev": true,
"license": "MIT",
"dependencies": {
@@ -10437,14 +10658,16 @@
}
},
"node_modules/vite": {
- "version": "8.1.0",
+ "version": "8.3.0",
+ "resolved": "https://registry.npmjs.org/vite/-/vite-8.3.0.tgz",
+ "integrity": "sha512-lhZBVvEHefgE+HQZC9O7EBJgCU/nVzFNl7vkS4RE0APtWLP02/8QVIkQtzBxPquh7lq5/78NHipTj7ODQ6XuyQ==",
"dev": true,
"license": "MIT",
"dependencies": {
- "lightningcss": "^1.32.0",
- "picomatch": "^4.0.4",
- "postcss": "^8.5.15",
- "rolldown": "~1.1.2",
+ "lightningcss": "^1.33.0",
+ "picomatch": "^4.0.7",
+ "postcss": "^8.5.28",
+ "rolldown": "~1.2.6",
"tinyglobby": "^0.2.17"
},
"bin": {
@@ -10461,7 +10684,7 @@
},
"peerDependencies": {
"@types/node": "^20.19.0 || >=22.12.0",
- "@vitejs/devtools": "^0.3.0",
+ "@vitejs/devtools": "^0.7.1",
"esbuild": "^0.27.0 || ^0.28.0",
"jiti": ">=1.21.0",
"less": "^4.0.0",
@@ -10512,6 +10735,279 @@
}
}
},
+ "node_modules/vite/node_modules/lightningcss": {
+ "version": "1.33.0",
+ "resolved": "https://registry.npmjs.org/lightningcss/-/lightningcss-1.33.0.tgz",
+ "integrity": "sha512-WkUDrojuJs0xkgGf2udWxa3yGBRxPtxUkB79i6aCZLRgc7PM8fZe9TosfPDcvEpQZbuFASnHYmRLBLUbmLOIIA==",
+ "dev": true,
+ "license": "MPL-2.0",
+ "dependencies": {
+ "detect-libc": "^2.0.3"
+ },
+ "engines": {
+ "node": ">= 12.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/parcel"
+ },
+ "optionalDependencies": {
+ "lightningcss-android-arm64": "1.33.0",
+ "lightningcss-darwin-arm64": "1.33.0",
+ "lightningcss-darwin-x64": "1.33.0",
+ "lightningcss-freebsd-x64": "1.33.0",
+ "lightningcss-linux-arm-gnueabihf": "1.33.0",
+ "lightningcss-linux-arm64-gnu": "1.33.0",
+ "lightningcss-linux-arm64-musl": "1.33.0",
+ "lightningcss-linux-x64-gnu": "1.33.0",
+ "lightningcss-linux-x64-musl": "1.33.0",
+ "lightningcss-win32-arm64-msvc": "1.33.0",
+ "lightningcss-win32-x64-msvc": "1.33.0"
+ }
+ },
+ "node_modules/vite/node_modules/lightningcss-android-arm64": {
+ "version": "1.33.0",
+ "resolved": "https://registry.npmjs.org/lightningcss-android-arm64/-/lightningcss-android-arm64-1.33.0.tgz",
+ "integrity": "sha512-gEpRTalKdosp4Bb8qWtc2iOgE5SeIHlpS1up9bFq2wAyYhl1UdTObYiHe98zEM9SQvSoqQZ1IQD0JNpg3Ml5pg==",
+ "cpu": [
+ "arm64"
+ ],
+ "dev": true,
+ "license": "MPL-2.0",
+ "optional": true,
+ "os": [
+ "android"
+ ],
+ "engines": {
+ "node": ">= 12.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/parcel"
+ }
+ },
+ "node_modules/vite/node_modules/lightningcss-darwin-arm64": {
+ "version": "1.33.0",
+ "resolved": "https://registry.npmjs.org/lightningcss-darwin-arm64/-/lightningcss-darwin-arm64-1.33.0.tgz",
+ "integrity": "sha512-Sciaz8eenNTKn9b3t7+xr0ipTp9YxKQY4npwQ3mrRuL0BAVHBLyZxofhaKBAVtzmtRZ/zTyo0/to4B1uWG/Djg==",
+ "cpu": [
+ "arm64"
+ ],
+ "dev": true,
+ "license": "MPL-2.0",
+ "optional": true,
+ "os": [
+ "darwin"
+ ],
+ "engines": {
+ "node": ">= 12.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/parcel"
+ }
+ },
+ "node_modules/vite/node_modules/lightningcss-darwin-x64": {
+ "version": "1.33.0",
+ "resolved": "https://registry.npmjs.org/lightningcss-darwin-x64/-/lightningcss-darwin-x64-1.33.0.tgz",
+ "integrity": "sha512-Z5UPAxzrjlWNNyGy6i65cJzzvgJ5D3T6wMvs+gWpY9d7qRhANrxqAp6LhxIgZhWEw18RfJTGcRxjuLIBr+m8XQ==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "license": "MPL-2.0",
+ "optional": true,
+ "os": [
+ "darwin"
+ ],
+ "engines": {
+ "node": ">= 12.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/parcel"
+ }
+ },
+ "node_modules/vite/node_modules/lightningcss-freebsd-x64": {
+ "version": "1.33.0",
+ "resolved": "https://registry.npmjs.org/lightningcss-freebsd-x64/-/lightningcss-freebsd-x64-1.33.0.tgz",
+ "integrity": "sha512-QQM/Ti/hQajJwCY+RiWuCZ9sdtI/XQk7nDK5vC8kkdwixezOlDgvDx7+RT+QjK6FcFT4MpsuoBnHIo/O3StRRg==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "license": "MPL-2.0",
+ "optional": true,
+ "os": [
+ "freebsd"
+ ],
+ "engines": {
+ "node": ">= 12.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/parcel"
+ }
+ },
+ "node_modules/vite/node_modules/lightningcss-linux-arm-gnueabihf": {
+ "version": "1.33.0",
+ "resolved": "https://registry.npmjs.org/lightningcss-linux-arm-gnueabihf/-/lightningcss-linux-arm-gnueabihf-1.33.0.tgz",
+ "integrity": "sha512-N7FVBe6iS24MlM6R/4RBTxGhQheZGs7tiQ9U32UtF75NzP5Q7xWPRqLBCKxlRQRk3rY1jCIPLzx7WzOhuUIRLQ==",
+ "cpu": [
+ "arm"
+ ],
+ "dev": true,
+ "license": "MPL-2.0",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">= 12.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/parcel"
+ }
+ },
+ "node_modules/vite/node_modules/lightningcss-linux-arm64-gnu": {
+ "version": "1.33.0",
+ "resolved": "https://registry.npmjs.org/lightningcss-linux-arm64-gnu/-/lightningcss-linux-arm64-gnu-1.33.0.tgz",
+ "integrity": "sha512-j2v/itmy4HlNxlc6voKXYgBqNi0Ng2LShg4z7GufpEgs05P+2suBVyi9I6YHq5uoVFx9ETin3eCEhLVyXGQnKg==",
+ "cpu": [
+ "arm64"
+ ],
+ "dev": true,
+ "libc": [
+ "glibc"
+ ],
+ "license": "MPL-2.0",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">= 12.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/parcel"
+ }
+ },
+ "node_modules/vite/node_modules/lightningcss-linux-arm64-musl": {
+ "version": "1.33.0",
+ "resolved": "https://registry.npmjs.org/lightningcss-linux-arm64-musl/-/lightningcss-linux-arm64-musl-1.33.0.tgz",
+ "integrity": "sha512-yiO5ROMuYQgXbC60yjZU5CYSFZGKXL0HFATXt9mHJn1+zW55oCtMI9NfcVhYLMFDL7gV7oBPon/EmMMGg2OvtQ==",
+ "cpu": [
+ "arm64"
+ ],
+ "dev": true,
+ "libc": [
+ "musl"
+ ],
+ "license": "MPL-2.0",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">= 12.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/parcel"
+ }
+ },
+ "node_modules/vite/node_modules/lightningcss-linux-x64-gnu": {
+ "version": "1.33.0",
+ "resolved": "https://registry.npmjs.org/lightningcss-linux-x64-gnu/-/lightningcss-linux-x64-gnu-1.33.0.tgz",
+ "integrity": "sha512-ar+Ju7LmcN0Jo4FpL4hpFybwNG9/3A/Br5KW2n2jyODg3MEZXaDYADdemoNS+BDNfMgKvylJLj4S5tyRActuAg==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "libc": [
+ "glibc"
+ ],
+ "license": "MPL-2.0",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">= 12.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/parcel"
+ }
+ },
+ "node_modules/vite/node_modules/lightningcss-linux-x64-musl": {
+ "version": "1.33.0",
+ "resolved": "https://registry.npmjs.org/lightningcss-linux-x64-musl/-/lightningcss-linux-x64-musl-1.33.0.tgz",
+ "integrity": "sha512-RYiYbkokw0trfKqqzfF55lginwEPrD3OJDfTuJzFs1MK6iFnDenaz1fqLLtX4ITG3OktJQXOeTaw1awrBAlZPw==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "libc": [
+ "musl"
+ ],
+ "license": "MPL-2.0",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">= 12.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/parcel"
+ }
+ },
+ "node_modules/vite/node_modules/lightningcss-win32-arm64-msvc": {
+ "version": "1.33.0",
+ "resolved": "https://registry.npmjs.org/lightningcss-win32-arm64-msvc/-/lightningcss-win32-arm64-msvc-1.33.0.tgz",
+ "integrity": "sha512-1K+MPfLSFVpphzpdbfkhlWk6wBrTObBzS2T6db10PNOZgR9GoVsAWzwNyuhUYYbTp23j+4RrncfujZ4uAzXvwA==",
+ "cpu": [
+ "arm64"
+ ],
+ "dev": true,
+ "license": "MPL-2.0",
+ "optional": true,
+ "os": [
+ "win32"
+ ],
+ "engines": {
+ "node": ">= 12.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/parcel"
+ }
+ },
+ "node_modules/vite/node_modules/lightningcss-win32-x64-msvc": {
+ "version": "1.33.0",
+ "resolved": "https://registry.npmjs.org/lightningcss-win32-x64-msvc/-/lightningcss-win32-x64-msvc-1.33.0.tgz",
+ "integrity": "sha512-OlEICDx/Xl0FqSp4bry8zFnCvGpig3Gl4gCquvYwHuqJKEC1+n9NgDniFvqHGmMv1ZkqDJrDqKKSykTDX+ehuA==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "license": "MPL-2.0",
+ "optional": true,
+ "os": [
+ "win32"
+ ],
+ "engines": {
+ "node": ">= 12.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/parcel"
+ }
+ },
"node_modules/vitest": {
"version": "4.1.11",
"resolved": "https://registry.npmjs.org/vitest/-/vitest-4.1.11.tgz",
@@ -10604,6 +11100,8 @@
},
"node_modules/w3c-xmlserializer": {
"version": "5.0.0",
+ "resolved": "https://registry.npmjs.org/w3c-xmlserializer/-/w3c-xmlserializer-5.0.0.tgz",
+ "integrity": "sha512-o8qghlI8NZHU1lLPrpi2+Uq7abh4GGPpYANlalzWxyWteJOCsr/P+oPBA49TOLu5FTZO4d3F9MnWJfiMo4BkmA==",
"dev": true,
"license": "MIT",
"dependencies": {
@@ -10692,9 +11190,9 @@
}
},
"node_modules/workerd": {
- "version": "1.20260918.1",
- "resolved": "https://registry.npmjs.org/workerd/-/workerd-1.20260918.1.tgz",
- "integrity": "sha512-NsjfQlBNQ0iEniv/STOy4zbp8s5k60PzL1Ter02Eg44arbDhHtf6UOs03E31XDRmmBFxSIkAZuCyld3RKH1wqA==",
+ "version": "1.20260921.1",
+ "resolved": "https://registry.npmjs.org/workerd/-/workerd-1.20260921.1.tgz",
+ "integrity": "sha512-4HyG7G1W4ksa6tUZ8bV2jxDRWuL5PXnHm9+Z1sjFPb9OZNoYtXz4y7QQRh4ibi0BF/lOmlAVjbhkUqsAVZuUKA==",
"dev": true,
"hasInstallScript": true,
"license": "Apache-2.0",
@@ -10705,28 +11203,28 @@
"node": ">=16"
},
"optionalDependencies": {
- "@cloudflare/workerd-darwin-64": "1.20260918.1",
- "@cloudflare/workerd-darwin-arm64": "1.20260918.1",
- "@cloudflare/workerd-linux-64": "1.20260918.1",
- "@cloudflare/workerd-linux-arm64": "1.20260918.1",
- "@cloudflare/workerd-windows-64": "1.20260918.1"
+ "@cloudflare/workerd-darwin-64": "1.20260921.1",
+ "@cloudflare/workerd-darwin-arm64": "1.20260921.1",
+ "@cloudflare/workerd-linux-64": "1.20260921.1",
+ "@cloudflare/workerd-linux-arm64": "1.20260921.1",
+ "@cloudflare/workerd-windows-64": "1.20260921.1"
}
},
"node_modules/wrangler": {
- "version": "4.135.0",
- "resolved": "https://registry.npmjs.org/wrangler/-/wrangler-4.135.0.tgz",
- "integrity": "sha512-WrNBQSfIG6YcILJcodYr5ty8vgkzGsV8YX+kfd+uZ5/Bd8cUW0GnUIRKAVfn5kYKqh1m/BPcji9h1d7mE8euFw==",
+ "version": "4.136.3",
+ "resolved": "https://registry.npmjs.org/wrangler/-/wrangler-4.136.3.tgz",
+ "integrity": "sha512-L1bS8BI9xoEk3RRr5XoZn5q5k1jCRo8+37ZEEab/jsUFzE1Ea2sIBAbmP1CdwSeD6mZYmnUtR6xpi9esHIl6GA==",
"dev": true,
"license": "MIT OR Apache-2.0",
"dependencies": {
"@cloudflare/kv-asset-handler": "0.5.0",
- "@cloudflare/unenv-preset": "2.16.1",
+ "@cloudflare/unenv-preset": "2.16.2",
"blake3-wasm": "2.1.5",
"esbuild": "0.28.1",
- "miniflare": "5.20260918.0-alpha",
+ "miniflare": "5.20260921.0-alpha",
"path-to-regexp": "6.3.0",
"unenv": "2.0.0-rc.24",
- "workerd": "1.20260918.1"
+ "workerd": "1.20260921.1"
},
"bin": {
"cf-wrangler": "bin/cf-wrangler.js",
@@ -10740,7 +11238,7 @@
"fsevents": "2.3.3"
},
"peerDependencies": {
- "@cloudflare/workers-types": "^5.20260918.1"
+ "@cloudflare/workers-types": "^5.20260921.1"
},
"peerDependenciesMeta": {
"@cloudflare/workers-types": {
@@ -10826,6 +11324,8 @@
},
"node_modules/xml-name-validator": {
"version": "5.0.0",
+ "resolved": "https://registry.npmjs.org/xml-name-validator/-/xml-name-validator-5.0.0.tgz",
+ "integrity": "sha512-EvGK8EJ3DhaHfbRlETOWAS5pO9MZITeauHKJyb8wyajUfQUenkIg2MvLDTZ4T/TgIcm3HU0TFBgWWboAZ30UHg==",
"dev": true,
"license": "Apache-2.0",
"engines": {
@@ -10854,6 +11354,8 @@
},
"node_modules/yargs": {
"version": "17.7.2",
+ "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.7.2.tgz",
+ "integrity": "sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w==",
"dev": true,
"license": "MIT",
"dependencies": {
@@ -10871,6 +11373,8 @@
},
"node_modules/yargs-parser": {
"version": "21.1.1",
+ "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-21.1.1.tgz",
+ "integrity": "sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==",
"dev": true,
"license": "ISC",
"engines": {
@@ -10879,6 +11383,8 @@
},
"node_modules/yargs/node_modules/string-width": {
"version": "4.2.3",
+ "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz",
+ "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==",
"dev": true,
"license": "MIT",
"dependencies": {
@@ -10892,6 +11398,8 @@
},
"node_modules/yargs/node_modules/strip-ansi": {
"version": "6.0.1",
+ "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz",
+ "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==",
"dev": true,
"license": "MIT",
"dependencies": {
@@ -10951,7 +11459,9 @@
}
},
"node_modules/zod": {
- "version": "4.4.3",
+ "version": "4.6.5",
+ "resolved": "https://registry.npmjs.org/zod/-/zod-4.6.5.tgz",
+ "integrity": "sha512-v5l/aFXZQeai4awLbOpSoHecE9UiMrnfx75tEXLjNonXVARxQ5mOeipTjROUchszUNCqnE+hqAMujRsRHsut2Q==",
"license": "MIT",
"funding": {
"url": "https://github.com/sponsors/colinhacks"
@@ -10988,18 +11498,18 @@
"@codraoss/models": "*",
"@codraoss/provider-github": "*",
"@codraoss/schema": "*",
- "hono": "^4.12.25",
+ "hono": "^4.12.34",
"zod": "^4.3.6"
},
"devDependencies": {
- "@types/node": "^22.0.0",
- "tsup": "^8.0.0"
+ "@types/node": "^22.0.3",
+ "tsup": "^8.0.2"
}
},
"packages/api/node_modules/@types/node": {
- "version": "22.20.1",
- "resolved": "https://registry.npmjs.org/@types/node/-/node-22.20.1.tgz",
- "integrity": "sha512-EANqOCF9QFyra+4pfxUcX9STKJpCLjMbObVzljIJomAWSnuSIEAvyzEU53GaajbXJEgdh0iEcPL+DGvpUd4k1Q==",
+ "version": "22.20.4",
+ "resolved": "https://registry.npmjs.org/@types/node/-/node-22.20.4.tgz",
+ "integrity": "sha512-zJRE40jpHtKqE/C4fgHrAKQLJuSpzEnP9ff9Y7YtoR3Wd2pwqzlekDeEuUQXjRd+QCYnVnNwuJYmhdk9XV8gvA==",
"dev": true,
"license": "MIT",
"dependencies": {
@@ -11020,12 +11530,12 @@
"dependencies": {
"@codraoss/schema": "*",
"jsonrepair": "^3.15.0",
- "picomatch": "^4.0.5",
+ "picomatch": "^4.0.7",
"zod": "^4.3.6"
},
"devDependencies": {
"@types/picomatch": "^4.0.3",
- "tsup": "^8.0.0"
+ "tsup": "^8.0.2"
}
},
"packages/db": {
@@ -11038,14 +11548,14 @@
"postgres": "^3.4.9"
},
"devDependencies": {
- "@types/node": "^22.0.0",
- "tsup": "^8.0.0"
+ "@types/node": "^22.0.3",
+ "tsup": "^8.0.2"
}
},
"packages/db/node_modules/@types/node": {
- "version": "22.20.1",
- "resolved": "https://registry.npmjs.org/@types/node/-/node-22.20.1.tgz",
- "integrity": "sha512-EANqOCF9QFyra+4pfxUcX9STKJpCLjMbObVzljIJomAWSnuSIEAvyzEU53GaajbXJEgdh0iEcPL+DGvpUd4k1Q==",
+ "version": "22.20.4",
+ "resolved": "https://registry.npmjs.org/@types/node/-/node-22.20.4.tgz",
+ "integrity": "sha512-zJRE40jpHtKqE/C4fgHrAKQLJuSpzEnP9ff9Y7YtoR3Wd2pwqzlekDeEuUQXjRd+QCYnVnNwuJYmhdk9XV8gvA==",
"dev": true,
"license": "MIT",
"dependencies": {
@@ -11068,7 +11578,7 @@
"@codraoss/schema": "*"
},
"devDependencies": {
- "tsup": "^8.0.0"
+ "tsup": "^8.0.2"
}
},
"packages/node-adapters": {
@@ -11082,11 +11592,11 @@
"@codraoss/schema": "*",
"bullmq": "^6.3.8",
"ioredis": "^6.0.0",
- "nanoid": "^5.0.7"
+ "nanoid": "^5.0.9"
},
"devDependencies": {
- "@types/node": "^22.0.0",
- "tsup": "^8.0.0"
+ "@types/node": "^22.0.3",
+ "tsup": "^8.0.2"
}
},
"packages/node-adapters/node_modules/@types/node": {
@@ -11133,7 +11643,7 @@
"@codraoss/schema": "*"
},
"devDependencies": {
- "tsup": "^8.0.0"
+ "tsup": "^8.0.2"
}
},
"packages/schema": {
@@ -11144,7 +11654,7 @@
"zod": "^4.3.6"
},
"devDependencies": {
- "tsup": "^8.0.0"
+ "tsup": "^8.0.2"
}
},
"packages/ui": {
@@ -11156,11 +11666,11 @@
"@codraoss/schema": "*",
"class-variance-authority": "^0.7.1",
"clsx": "^2.1.1",
- "sugar-high": "^2.0.0",
+ "sugar-high": "^2.0.3",
"tailwind-merge": "^3.5.0"
},
"devDependencies": {
- "tsup": "^8.0.0"
+ "tsup": "^8.0.2"
},
"peerDependencies": {
"lenis": ">=1.0.0",
diff --git a/package.json b/package.json
index d89faa79..9da8f25c 100644
--- a/package.json
+++ b/package.json
@@ -44,12 +44,12 @@
"devDependencies": {
"@arethetypeswrong/cli": "^0.18.5",
"@eslint/js": "^10.0.1",
- "@tailwindcss/vite": "^4.2.2",
- "@testing-library/dom": "^10.4.1",
- "@testing-library/react": "^16.3.2",
- "@types/node": "^25.6.0",
+ "@tailwindcss/vite": "^4.2.4",
+ "@testing-library/dom": "^10.4.2",
+ "@testing-library/react": "^16.3.3",
+ "@types/node": "^25.6.2",
"@types/react": "^19.2.18",
- "@types/react-dom": "^19.2.4",
+ "@types/react-dom": "^19.2.7",
"@vitejs/plugin-react": "^6.0.5",
"chalk": "^5.6.2",
"concurrently": "^9.2.4",
@@ -60,13 +60,13 @@
"jsdom": "^29.0.2",
"ora": "^9.4.1",
"prompts": "^2.4.2",
- "publint": "^0.3.23",
- "tailwindcss": "^4.2.2",
+ "publint": "^0.3.24",
+ "tailwindcss": "^4.2.4",
"tsup": "^8.5.1",
- "typescript": "^6.0.2",
+ "typescript": "^6.0.3",
"typescript-eslint": "^8.66.0",
- "vite": "^8.0.8",
- "vitest": "^4.1.10",
+ "vite": "^8.0.16",
+ "vitest": "^4.1.11",
"wrangler": "^4.114.0"
},
"dependencies": {
@@ -80,7 +80,7 @@
"@codraoss/ui": "*",
"class-variance-authority": "^0.7.1",
"clsx": "^2.1.1",
- "hono": "^4.12.25",
+ "hono": "^4.12.34",
"jsonrepair": "^3.15.0",
"lenis": "^1.3.26",
"lucide-react": "^1.8.0",
@@ -90,19 +90,20 @@
"react": "^19.2.8",
"react-dom": "^19.2.8",
"react-markdown": "^10.1.0",
- "react-router-dom": "^7.18.2",
+ "react-router-dom": "^7.18.4",
"recharts": "^3.8.1",
"rehype-raw": "^7.0.0",
"rehype-sanitize": "^6.0.0",
"remark-gfm": "^4.0.1",
- "sonner": "^2.0.7",
- "sugar-high": "^2.0.0",
+ "sonner": "^2.0.8",
+ "sugar-high": "^2.0.3",
"tailwind-merge": "^3.5.0",
"zod": "^4.3.6"
},
"allowScripts": {
"esbuild": true,
"unrs-resolver@1.12.2": true,
- "workerd@1.20260918.1": true
+ "workerd@1.20260918.1": true,
+ "msgpackr-extract@3.0.4": true
}
}
diff --git a/packages/api/package.json b/packages/api/package.json
index 474f59c2..718e6efb 100644
--- a/packages/api/package.json
+++ b/packages/api/package.json
@@ -44,7 +44,7 @@
"postpack": "node ../../scripts/swap-publish-exports.mjs restore"
},
"dependencies": {
- "hono": "^4.12.25",
+ "hono": "^4.12.34",
"zod": "^4.3.6",
"@codraoss/schema": "*",
"@codraoss/core": "*",
@@ -53,8 +53,8 @@
"@codraoss/models": "*"
},
"devDependencies": {
- "@types/node": "^22.0.0",
- "tsup": "^8.0.0"
+ "@types/node": "^22.0.3",
+ "tsup": "^8.0.2"
},
"main": "./dist/index.js",
"module": "./dist/index.js",
diff --git a/packages/core/package.json b/packages/core/package.json
index 69d26fe7..8b6bb82a 100644
--- a/packages/core/package.json
+++ b/packages/core/package.json
@@ -125,11 +125,11 @@
"dependencies": {
"@codraoss/schema": "*",
"jsonrepair": "^3.15.0",
- "picomatch": "^4.0.5",
+ "picomatch": "^4.0.7",
"zod": "^4.3.6"
},
"devDependencies": {
"@types/picomatch": "^4.0.3",
- "tsup": "^8.0.0"
+ "tsup": "^8.0.2"
}
}
diff --git a/packages/db/package.json b/packages/db/package.json
index 7ffc05e4..46bb56b0 100644
--- a/packages/db/package.json
+++ b/packages/db/package.json
@@ -72,7 +72,7 @@
"postgres": "^3.4.9"
},
"devDependencies": {
- "@types/node": "^22.0.0",
- "tsup": "^8.0.0"
+ "@types/node": "^22.0.3",
+ "tsup": "^8.0.2"
}
}
diff --git a/packages/models/package.json b/packages/models/package.json
index 0a494564..ca597e43 100644
--- a/packages/models/package.json
+++ b/packages/models/package.json
@@ -82,6 +82,6 @@
"@codraoss/core": "*"
},
"devDependencies": {
- "tsup": "^8.0.0"
+ "tsup": "^8.0.2"
}
}
diff --git a/packages/node-adapters/package.json b/packages/node-adapters/package.json
index 9041ab33..55a02800 100644
--- a/packages/node-adapters/package.json
+++ b/packages/node-adapters/package.json
@@ -49,10 +49,10 @@
"@codraoss/schema": "*",
"bullmq": "^6.3.8",
"ioredis": "^6.0.0",
- "nanoid": "^5.0.7"
+ "nanoid": "^5.0.9"
},
"devDependencies": {
- "@types/node": "^22.0.0",
- "tsup": "^8.0.0"
+ "@types/node": "^22.0.3",
+ "tsup": "^8.0.2"
}
}
diff --git a/packages/node-adapters/src/worker.ts b/packages/node-adapters/src/worker.ts
index dba5151c..6c5789e4 100644
--- a/packages/node-adapters/src/worker.ts
+++ b/packages/node-adapters/src/worker.ts
@@ -1,8 +1,7 @@
import { Worker, type Job } from 'bullmq';
import { reviewJobMessageSchema, type ReviewJobMessage } from '@codraoss/schema';
import { NodeOrchestrator } from './node-orchestrator';
-import type { ReviewRuntime } from '@codraoss/core/ports';
-import type { QueueProducer } from '@codraoss/core/ports';
+import type { ReviewRuntime, QueueProducer } from '@codraoss/core/ports';
import type Redis from 'ioredis';
export function startWorker(
diff --git a/packages/provider-github/package.json b/packages/provider-github/package.json
index 2002e889..7413c9d2 100644
--- a/packages/provider-github/package.json
+++ b/packages/provider-github/package.json
@@ -57,6 +57,6 @@
"@codraoss/schema": "*"
},
"devDependencies": {
- "tsup": "^8.0.0"
+ "tsup": "^8.0.2"
}
}
diff --git a/packages/schema/package.json b/packages/schema/package.json
index f1ddceae..048e988c 100644
--- a/packages/schema/package.json
+++ b/packages/schema/package.json
@@ -80,6 +80,6 @@
"zod": "^4.3.6"
},
"devDependencies": {
- "tsup": "^8.0.0"
+ "tsup": "^8.0.2"
}
}
diff --git a/packages/ui/package.json b/packages/ui/package.json
index 45f03693..67870ca3 100644
--- a/packages/ui/package.json
+++ b/packages/ui/package.json
@@ -110,9 +110,9 @@
"class-variance-authority": "^0.7.1",
"clsx": "^2.1.1",
"tailwind-merge": "^3.5.0",
- "sugar-high": "^2.0.0"
+ "sugar-high": "^2.0.3"
},
"devDependencies": {
- "tsup": "^8.0.0"
+ "tsup": "^8.0.2"
}
}
From e417dd605eeaf7e840e2a2bbed92289013c502a3 Mon Sep 17 00:00:00 2001
From: Devarshi Shimpi
Date: Wed, 23 Sep 2026 01:20:39 +0530
Subject: [PATCH 06/16] chore: strip verbose comments and use workspace
dependencies
---
apps/node/package.json | 2 +-
apps/node/src/adapters/telemetry.ts | 3 +-
apps/node/src/api-deps.ts | 10 +++--
apps/node/src/env.ts | 6 +--
apps/node/src/index.ts | 22 ++++------
apps/node/src/runtime.ts | 6 +--
apps/worker/package.json | 2 +-
apps/worker/src/worker-env.d.ts | 25 ++++++++++-
docker-compose.yml | 4 +-
package-lock.json | 4 +-
package.json | 2 +-
packages/api/package.json | 43 +++++++++++--------
packages/core/package.json | 4 +-
packages/db/package.json | 6 +--
packages/db/src/client.ts | 4 +-
packages/models/package.json | 6 +--
.../models/src/internal/model-chain-runner.ts | 10 ++---
.../models/src/internal/model-rate-limits.ts | 4 +-
.../models/src/internal/model-review-chain.ts | 25 ++++++-----
.../models/src/internal/model-review-file.ts | 2 +-
packages/models/src/internal/model-support.ts | 8 ++--
packages/models/src/providers/cloudflare.ts | 13 +++---
packages/models/src/providers/google.ts | 18 ++++----
packages/models/src/providers/openai.ts | 2 -
packages/models/src/providers/vertex.ts | 14 +++---
packages/models/src/runner.ts | 29 +++++--------
packages/models/src/types.ts | 2 +-
packages/models/src/url-guard.ts | 14 +++---
packages/node-adapters/package.json | 10 ++---
packages/node-adapters/src/platform.ts | 5 +--
packages/provider-github/package.json | 6 +--
packages/schema/package.json | 2 +-
packages/schema/src/api.ts | 8 ----
packages/schema/src/hex.ts | 4 --
packages/schema/src/schema-claims.ts | 5 ---
packages/schema/src/schema-enums.ts | 2 -
packages/schema/src/schema-repo-config.ts | 7 ---
packages/schema/src/schema.ts | 1 -
packages/ui/package.json | 4 +-
packages/ui/src/components/bar-sparkline.tsx | 10 +----
packages/ui/src/components/button.tsx | 5 ---
.../ui/src/components/chart-primitives.tsx | 10 -----
packages/ui/src/components/load-error.tsx | 4 --
.../src/components/motion/smooth-scroll.tsx | 8 ----
.../src/components/motion/stepped-slider.tsx | 16 +------
packages/ui/src/components/motion/tabs.tsx | 8 +---
.../ui/src/components/onboarding-card.tsx | 30 ++++++-------
packages/ui/src/components/select-panel.tsx | 6 +--
packages/ui/src/components/select-shared.ts | 5 +--
packages/ui/src/components/select.tsx | 9 ----
packages/ui/src/lib/constants.ts | 4 +-
packages/ui/src/lib/prompt-diff.ts | 8 ++--
52 files changed, 186 insertions(+), 281 deletions(-)
diff --git a/apps/node/package.json b/apps/node/package.json
index 6a062909..bca66afc 100644
--- a/apps/node/package.json
+++ b/apps/node/package.json
@@ -1,6 +1,6 @@
{
"name": "@codraoss/node-server",
- "version": "0.9.12",
+ "version": "0.9.13",
"private": true,
"type": "module",
"scripts": {
diff --git a/apps/node/src/adapters/telemetry.ts b/apps/node/src/adapters/telemetry.ts
index 9c1e28c3..1f0b2046 100644
--- a/apps/node/src/adapters/telemetry.ts
+++ b/apps/node/src/adapters/telemetry.ts
@@ -4,8 +4,7 @@ import type { NodeAppBindings } from '../env';
export function makeTelemetrySink(_env: NodeAppBindings): TelemetrySink {
return {
send: async (_event) => {
- // In a real setup this would batch and send to a telemetry endpoint
- // For now, in Node open-source, telemetry can be safely stubbed or sent to logs
+ // Telemetry stubbed in Node open-source.
}
};
}
diff --git a/apps/node/src/api-deps.ts b/apps/node/src/api-deps.ts
index ac0f4f44..6007ca62 100644
--- a/apps/node/src/api-deps.ts
+++ b/apps/node/src/api-deps.ts
@@ -15,14 +15,18 @@ export function createNodeApiDeps(env: NodeAppBindings) {
},
terminateJobWorkflow: async (job) => {
if (env.REVIEW_QUEUE.deleteJob) {
- await env.REVIEW_QUEUE.deleteJob(job.id);
- logger.info(`[API Deps] Terminated job workflow for job ${job.id}`);
+ try {
+ await env.REVIEW_QUEUE.deleteJob(job.id);
+ logger.info(`[API Deps] Terminated job workflow for job ${job.id}`);
+ } catch (error) {
+ logger.error(`[API Deps] Failed to terminate job workflow for job ${job.id}: ${error}`);
+ }
} else {
logger.warn(`[API Deps] QueueAdapter does not support deleteJob. Cannot terminate ${job.id}`);
}
},
scheduleBestEffortJobMaintenance: () => {
- // In node, this is a long running process, we can just spawn a promise.
+
},
createReviewRuntime: () => createReviewRuntime(env),
getOrFetchRawDiffForCompletedJob: async () => '',
diff --git a/apps/node/src/env.ts b/apps/node/src/env.ts
index 302cf134..9b975777 100644
--- a/apps/node/src/env.ts
+++ b/apps/node/src/env.ts
@@ -8,10 +8,10 @@ export interface NodeAppBindings {
REVIEW_QUEUE: QueueProducer;
REVIEW_ORCHESTRATOR: JobOrchestrator;
- // ── Database ──
+
DATABASE_CONFIG: { connectionString: string };
- // ── Environment strings (loaded from process.env via dotenv) ──
+
APP_PRIVATE_KEY: string;
GITHUB_APP_ID: string;
GITHUB_APP_SLUG?: string;
@@ -30,7 +30,7 @@ export function createNodeEnv(stubs: {
SESSION_STORE: SessionStore;
APP_KV: KeyValueStore;
REVIEW_QUEUE: QueueProducer;
- REVIEW_ORCHESTRATOR?: JobOrchestrator; // Mark as optional
+ REVIEW_ORCHESTRATOR?: JobOrchestrator;
}): NodeAppBindings {
const requireEnv = (key: string) => {
const val = process.env[key];
diff --git a/apps/node/src/index.ts b/apps/node/src/index.ts
index 5649148d..d471cbe7 100644
--- a/apps/node/src/index.ts
+++ b/apps/node/src/index.ts
@@ -1,7 +1,7 @@
import * as dotenv from 'dotenv';
import * as path from 'node:path';
-dotenv.config({ path: path.resolve(process.cwd(), '../../.dev.vars') }); // Fallback if running from apps/node
-dotenv.config({ path: path.resolve(process.cwd(), '.dev.vars') }); // Root level
+dotenv.config({ path: path.resolve(process.cwd(), '../../.dev.vars') });
+dotenv.config({ path: path.resolve(process.cwd(), '.dev.vars') });
import { serve } from '@hono/node-server';
import { createApiRouter } from '@codraoss/api';
@@ -25,7 +25,7 @@ const __dirname = dirname(__filename);
const redisUrl = process.env.REDIS_URL || 'redis://localhost:6379';
const redisClient = new Redis(redisUrl, {
maxRetriesPerRequest: null,
- tls: redisUrl.startsWith('rediss://') ? { rejectUnauthorized: false } : undefined, // For managed Redis
+ tls: redisUrl.startsWith('rediss://') ? { rejectUnauthorized: false } : undefined, // Managed Redis
});
redisClient.on('error', (err) => {
logger.error('[Redis Error]', err);
@@ -50,14 +50,14 @@ app.onError((err, c) => {
return c.text('Custom Error: ' + err.message, 500);
});
-// Static file serving
+
const distClientPath = path.resolve(__dirname, process.cwd().endsWith('node/dist') ? '../../dist/client' : '../dist/client');
app.use('/assets/*', serveStatic({ root: distClientPath }));
app.use('/*.svg', serveStatic({ root: distClientPath }));
app.use('/*.ico', serveStatic({ root: distClientPath }));
app.get('*', serveStatic({ root: distClientPath, path: 'index.html' }));
-app.get('/health', (c) => c.text('OK')); // Healthcheck endpoint
+app.get('/health', (c) => c.text('OK'));
const port = parseInt(process.env.PORT || '3000', 10);
@@ -74,7 +74,7 @@ if (process.env.START_API !== 'false') {
...env,
deps: createNodeApiDeps(env),
};
- // Ensure runWithDb receives correct DbEnv type
+
try { return await runWithDb({ ...env, HYPERDRIVE: env.DATABASE_CONFIG }, () => app.fetch(request, apiEnv as any)); } catch (e) { console.error('SERVE ERROR:', e); throw e; }
},
port,
@@ -83,7 +83,7 @@ if (process.env.START_API !== 'false') {
logger.info(`Codra Node server running on http://localhost:${info.port}`);
});
- // Add server to shutdown sequence
+
if (server) {
const originalClose = server.close;
server.close = () => originalClose(() => {
@@ -95,7 +95,7 @@ if (process.env.START_API !== 'false') {
const shutdown = async () => {
logger.info('Shutting down Codra Node server...');
- // Close BullMQ worker first to prevent new jobs
+ // Close BullMQ worker
if (worker) {
logger.info('Waiting for active BullMQ jobs to finish...');
await worker.close();
@@ -109,11 +109,7 @@ const shutdown = async () => {
logger.info('Redis client closed.');
}
- // Close Postgres connection pool
- // The postgres.js client automatically manages its pool.
- // runWithDb client is scoped, but a top-level client for specific operations might exist in the future
- // For now, no explicit close needed for `postgres.js` unless it's a global client.
- // If `runWithDb` is the only entry point, it manages its own connections.
+ // Postgres client manages its own pool.
logger.info('All services stopped. Exiting.');
process.exit(0);
diff --git a/apps/node/src/runtime.ts b/apps/node/src/runtime.ts
index 42c829d2..485d1de0 100644
--- a/apps/node/src/runtime.ts
+++ b/apps/node/src/runtime.ts
@@ -3,13 +3,13 @@ import type { DbEnv } from '@codraoss/db/env';
import { TokenTracker } from '@codraoss/core/token-tracker';
import type { NodeAppBindings } from './env';
-// Adapters from @codraoss/db/repositories
+
import { makeJobStore, makeFileReviewStore, makeLearningStore, makeModelConfigReader, makeReviewSettingsReader, makeWebhookDeliveryReader } from '@codraoss/db/repositories';
-// Config
+
import { loadRepoConfig } from '@codraoss/api/platform';
-// Node-specific adapters
+
import { cryptoIds, systemClock } from '@codraoss/node-adapters';
import { makeTelemetrySink } from './adapters/telemetry';
import {
diff --git a/apps/worker/package.json b/apps/worker/package.json
index 5f5629db..7bc6ce5a 100644
--- a/apps/worker/package.json
+++ b/apps/worker/package.json
@@ -1,6 +1,6 @@
{
"name": "@codraoss/worker",
- "version": "0.9.12",
+ "version": "0.9.13",
"private": true,
"type": "module",
"dependencies": {
diff --git a/apps/worker/src/worker-env.d.ts b/apps/worker/src/worker-env.d.ts
index c59da585..ba16eb88 100644
--- a/apps/worker/src/worker-env.d.ts
+++ b/apps/worker/src/worker-env.d.ts
@@ -1,6 +1,6 @@
/* eslint-disable */
// Generated by Wrangler by running `wrangler types ./src/worker-env.d.ts` (hash: 76d8ec86de20e8aacd6c22180ec1b53d)
-// Runtime types generated with workerd@1.20260918.1 2026-04-16 nodejs_compat
+// Runtime types generated with workerd@1.20260921.1 2026-04-16 nodejs_compat
interface __BaseEnv_Env {
APP_KV: KVNamespace;
HYPERDRIVE: Hyperdrive;
@@ -10674,6 +10674,29 @@ declare abstract class AiGateway {
}): Promise;
getUrl(provider?: AIGatewayProviders | string): Promise; // eslint-disable-line
}
+/** A parameter accepted by an Analytics SQL query. */
+type AnalyticsSQLParameter = string | number | boolean | null;
+/** An Analytics SQL query and its optional positional or named parameters. */
+interface AnalyticsSQLQuery {
+ query: string;
+ params?: readonly AnalyticsSQLParameter[] | Readonly>;
+}
+/** Execution statistics returned by Analytics SQL. */
+interface AnalyticsSQLStatistics {
+ elapsed_ms: number;
+ rows_read: number;
+ bytes_read: number;
+}
+/** The rows and execution statistics returned by an Analytics SQL query. */
+interface AnalyticsSQLResult = Record> {
+ data: T[];
+ rows: number;
+ statistics: AnalyticsSQLStatistics;
+}
+/** An Analytics SQL binding. */
+interface AnalyticsSQLBinding {
+ query = Record>(request: AnalyticsSQLQuery): Promise>;
+}
// Copyright (c) 2022-2025 Cloudflare, Inc.
// Licensed under the Apache 2.0 license found in the LICENSE file or at:
// https://opensource.org/licenses/Apache-2.0
diff --git a/docker-compose.yml b/docker-compose.yml
index 430cb958..27292d61 100644
--- a/docker-compose.yml
+++ b/docker-compose.yml
@@ -5,7 +5,7 @@ services:
image: postgres:15-alpine
environment:
POSTGRES_USER: postgres
- POSTGRES_PASSWORD: password
+ POSTGRES_PASSWORD: ${POSTGRES_PASSWORD:-codra_secure_default_pass}
POSTGRES_DB: codra
ports:
- "5432:5432"
@@ -36,7 +36,7 @@ services:
ports:
- "3000:3000"
environment:
- - DATABASE_URL=postgres://postgres:password@postgres:5432/codra
+ - DATABASE_URL=postgres://postgres:${POSTGRES_PASSWORD:-codra_secure_default_pass}@postgres:5432/codra
- REDIS_URL=redis://redis:6379
- START_WORKER=true
- PORT=3000
diff --git a/package-lock.json b/package-lock.json
index 1ad9c43d..deb8f494 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -1,12 +1,12 @@
{
"name": "codra",
- "version": "0.9.6",
+ "version": "0.9.13",
"lockfileVersion": 3,
"requires": true,
"packages": {
"": {
"name": "codra",
- "version": "0.9.6",
+ "version": "0.9.13",
"license": "AGPL-3.0-only",
"workspaces": [
"packages/*",
diff --git a/package.json b/package.json
index 9da8f25c..1e688991 100644
--- a/package.json
+++ b/package.json
@@ -1,6 +1,6 @@
{
"name": "codra",
- "version": "0.9.6",
+ "version": "0.9.13",
"description": "Open-source code review engine",
"private": true,
"author": "Devarshi Shimpi",
diff --git a/packages/api/package.json b/packages/api/package.json
index 718e6efb..1dd148fa 100644
--- a/packages/api/package.json
+++ b/packages/api/package.json
@@ -1,6 +1,6 @@
{
"name": "@codraoss/api",
- "version": "0.9.12",
+ "version": "0.9.13",
"description": "Codra's HTTP surface as a mountable Hono router, wired through ports.",
"author": "Devarshi Shimpi",
"license": "AGPL-3.0-only",
@@ -16,18 +16,9 @@
"type": "module",
"sideEffects": false,
"exports": {
- ".": {
- "types": "./dist/index.d.ts",
- "import": "./dist/index.js"
- },
- "./logger": {
- "types": "./dist/logger.d.ts",
- "import": "./dist/logger.js"
- },
- "./platform": {
- "types": "./dist/platform/index.d.ts",
- "import": "./dist/platform/index.js"
- }
+ ".": "./src/index.ts",
+ "./logger": "./src/logger.ts",
+ "./platform": "./src/platform/index.ts"
},
"files": [
"dist",
@@ -35,7 +26,21 @@
"README.md"
],
"publishConfig": {
- "access": "public"
+ "access": "public",
+ "exports": {
+ ".": {
+ "import": "./dist/index.js",
+ "types": "./dist/index.d.ts"
+ },
+ "./logger": {
+ "import": "./dist/logger.js",
+ "types": "./dist/logger.d.ts"
+ },
+ "./platform": {
+ "import": "./dist/platform/index.js",
+ "types": "./dist/platform/index.d.ts"
+ }
+ }
},
"scripts": {
"build": "tsup",
@@ -46,11 +51,11 @@
"dependencies": {
"hono": "^4.12.34",
"zod": "^4.3.6",
- "@codraoss/schema": "*",
- "@codraoss/core": "*",
- "@codraoss/db": "*",
- "@codraoss/provider-github": "*",
- "@codraoss/models": "*"
+ "@codraoss/schema": "workspace:*",
+ "@codraoss/core": "workspace:*",
+ "@codraoss/db": "workspace:*",
+ "@codraoss/provider-github": "workspace:*",
+ "@codraoss/models": "workspace:*"
},
"devDependencies": {
"@types/node": "^22.0.3",
diff --git a/packages/core/package.json b/packages/core/package.json
index 8b6bb82a..3f872975 100644
--- a/packages/core/package.json
+++ b/packages/core/package.json
@@ -1,6 +1,6 @@
{
"name": "@codraoss/core",
- "version": "0.9.12",
+ "version": "0.9.13",
"description": "The Codra review engine: pure, transport- and platform-agnostic code review logic behind ports.",
"author": "Devarshi Shimpi",
"license": "AGPL-3.0-only",
@@ -123,7 +123,7 @@
"postpack": "node ../../scripts/swap-publish-exports.mjs restore"
},
"dependencies": {
- "@codraoss/schema": "*",
+ "@codraoss/schema": "workspace:*",
"jsonrepair": "^3.15.0",
"picomatch": "^4.0.7",
"zod": "^4.3.6"
diff --git a/packages/db/package.json b/packages/db/package.json
index 46bb56b0..6e7125db 100644
--- a/packages/db/package.json
+++ b/packages/db/package.json
@@ -1,6 +1,6 @@
{
"name": "@codraoss/db",
- "version": "0.9.12",
+ "version": "0.9.13",
"description": "Codra's Postgres persistence layer behind repository interfaces.",
"author": "Devarshi Shimpi",
"license": "AGPL-3.0-only",
@@ -67,8 +67,8 @@
"postpack": "node ../../scripts/swap-publish-exports.mjs restore"
},
"dependencies": {
- "@codraoss/schema": "*",
- "@codraoss/core": "*",
+ "@codraoss/schema": "workspace:*",
+ "@codraoss/core": "workspace:*",
"postgres": "^3.4.9"
},
"devDependencies": {
diff --git a/packages/db/src/client.ts b/packages/db/src/client.ts
index a1af66bf..c038f720 100644
--- a/packages/db/src/client.ts
+++ b/packages/db/src/client.ts
@@ -15,7 +15,7 @@ function createDbClient(env: DbEnv): DbClient {
fetch_types: false,
prepare: false,
onnotice: () => {},
- ssl: env.HYPERDRIVE.connectionString.includes('sslmode=require') ? { rejectUnauthorized: false } : false,
+ ssl: env.HYPERDRIVE.connectionString.includes('sslmode=require') ? { rejectUnauthorized: process.env.NODE_ENV !== 'production' } : false,
});
return {
@@ -92,7 +92,7 @@ async function withStaleConnectionRecovery(env: DbEnv, op: (db: DbClient) =>
try {
return await op(getDb(env));
} catch (error) {
- if (inScope || !isStaleConnectionError(error)) throw error;
+ if (inScope || env.workerMode !== false || !isStaleConnectionError(error)) throw error;
const connectionString = env.HYPERDRIVE.connectionString;
fallbackClients.delete(connectionString);
diff --git a/packages/models/package.json b/packages/models/package.json
index ca597e43..d3836ded 100644
--- a/packages/models/package.json
+++ b/packages/models/package.json
@@ -1,6 +1,6 @@
{
"name": "@codraoss/models",
- "version": "0.9.12",
+ "version": "0.9.13",
"description": "LLM provider adapters and model catalog for the Codra review engine.",
"author": "Devarshi Shimpi",
"license": "AGPL-3.0-only",
@@ -78,8 +78,8 @@
"postpack": "node ../../scripts/swap-publish-exports.mjs restore"
},
"dependencies": {
- "@codraoss/schema": "*",
- "@codraoss/core": "*"
+ "@codraoss/schema": "workspace:*",
+ "@codraoss/core": "workspace:*"
},
"devDependencies": {
"tsup": "^8.0.2"
diff --git a/packages/models/src/internal/model-chain-runner.ts b/packages/models/src/internal/model-chain-runner.ts
index 707cbc6b..b98736a3 100644
--- a/packages/models/src/internal/model-chain-runner.ts
+++ b/packages/models/src/internal/model-chain-runner.ts
@@ -16,7 +16,7 @@ import type { ModelInput, ModelResponse } from '../types';
// Import from services/model.ts, not here -- four specs vi.mock that specifier.
-// Implementation detail, NOT new public API: kept private on ModelRunner because three specs reach these via `(service as any)`.
+// `ModelChainContext` kept private as an implementation detail.
export type ModelChainContext = {
selectModel(params: { totalLineCount: number; config: RepoConfig }): { primary: string; fallbacks: string[] };
resolveModel(model: string): Promise;
@@ -97,16 +97,16 @@ export async function generateSummary(ctx: ModelChainContext, params: {
throw lastError;
}
-// Best-effort: any throw here means "verification unavailable", keeping the pre-verification findings.
+// Best-effort: failures retain pre-verification findings.
export async function verifyFindings(ctx: ModelChainContext, params: { candidates: VerifyCandidate[]; config: RepoConfig }): Promise {
const { primary, fallbacks } = ctx.selectModel({ totalLineCount: 0, config: params.config });
const modelsToTry = [primary, ...fallbacks];
const input: ModelInput = {
systemPrompt: VERIFY_SYSTEM_PROMPT,
userPrompt: buildVerifyPrompt(params.candidates),
- // Must be the verify grammar, not the file-review one -- that schema makes strict decoding unsatisfiable and the pass a silent no-op.
+ // Must use verify grammar, not file-review.
responseSchema: VERIFY_RESPONSE_SCHEMA as unknown as ModelInput['responseSchema'],
- // A missing verdict is not a pass; a truncated list would silently withhold findings.
+ // Truncated list silently withholds findings.
truncationIntolerant: true,
};
const requestedTimeoutMs = clampTimeoutToChainBudget(verifyTimeoutMs(params.candidates.length));
@@ -117,7 +117,7 @@ export async function verifyFindings(ctx: ModelChainContext, params: { candidate
const recordGateWait = (waitedMs: number) => { gateWaitMs += waitedMs; };
for (const [modelIndex, currentModel] of modelsToTry.entries()) {
- // Matters more here than in reviewFileChunk: finalize can't hibernate, so a full model chain through an outage can burn the whole invocation budget and fail the job terminally.
+ // Finalize can't hibernate; prevent full-chain budget burn.
if (modelIndex > 0 && ctx.tracker?.isNearLimit()) {
logger.warn('Stopping the verification chain; subrequest budget for this invocation is nearly exhausted', {
skippedModels: modelsToTry.slice(modelIndex),
diff --git a/packages/models/src/internal/model-rate-limits.ts b/packages/models/src/internal/model-rate-limits.ts
index 16a5c473..66b28d7d 100644
--- a/packages/models/src/internal/model-rate-limits.ts
+++ b/packages/models/src/internal/model-rate-limits.ts
@@ -9,12 +9,12 @@ export interface RateLimitPersistence {
}
export class ModelRateLimitBook {
- // Slot held before client timeout starts (Workers: 6 concurrent conns/invocation).
+ // Slot held before client timeout starts.
private readonly callGate = new ModelCallGate();
private readonly modelRateLimits = new Map();
- // Keyed by model, not provider, so an all-Google chain doesn't serialize.
+ // Keyed by model.
private readonly tokenMeteredModels = new Map();
private hydrated: Promise | null = null;
diff --git a/packages/models/src/internal/model-review-chain.ts b/packages/models/src/internal/model-review-chain.ts
index cc3d6ee7..fe4d9803 100644
--- a/packages/models/src/internal/model-review-chain.ts
+++ b/packages/models/src/internal/model-review-chain.ts
@@ -15,7 +15,6 @@ import type { ModelChainContext } from './model-chain-runner';
import type { ModelRateLimitBook } from './model-rate-limits';
import type { ModelChainProgressStore } from './model-chain-progress';
-// Past two quota failures per file burns subrequests for nothing.
const MAX_QUOTA_FAILURES_PER_FILE = 2;
export type ModelReviewContext = ModelChainContext & {
@@ -49,8 +48,8 @@ export async function runModelChain(ctx: ModelReviewContext, params: {
});
const wholeChain = [primary, ...fallbacks];
- // Resume index is the min across bin members, clamped so it can't empty the chain.
- const recorded = await Promise.all(progressLabels.map((key) => ctx.chainProgress.startIndexFor(key)));
+// Resume index is min across bin members, clamped to prevent emptying chain.
+const recorded = await Promise.all(progressLabels.map((key) => ctx.chainProgress.startIndexFor(key)));
const startIndex = Math.min(Math.min(...recorded), Math.max(wholeChain.length - 1, 0));
const modelsToTry = wholeChain.slice(startIndex);
if (startIndex > 0) {
@@ -134,8 +133,8 @@ export async function runModelChain(ctx: ModelReviewContext, params: {
continue;
}
- // Floor applies even to the primary model, not just fallbacks.
- if (ctx.tracker && !ctx.tracker.hasRemainingSubrequests(SUBREQUEST_HEADROOM_FOR_MODEL_CALL)) {
+// Floor applies even to primary model, not just fallbacks.
+if (ctx.tracker && !ctx.tracker.hasRemainingSubrequests(SUBREQUEST_HEADROOM_FOR_MODEL_CALL)) {
logger.warn(`Deferring ${label}: not enough subrequest budget left to commit a prompt`, {
subrequests: ctx.tracker.getSubrequestCount(),
needed: SUBREQUEST_HEADROOM_FOR_MODEL_CALL,
@@ -167,8 +166,8 @@ export async function runModelChain(ctx: ModelReviewContext, params: {
ctx.tracker.record(response.modelUsed, response.inputTokens, response.outputTokens);
}
- // isLastModel uses the absolute chain index so resumed jobs don't accept prematurely.
- const parsed = params.parse(response.rawText, {
+// `isLastModel` uses the absolute chain index for resumed jobs.
+const parsed = params.parse(response.rawText, {
isLastModel: startIndex + modelIndex >= wholeChain.length - 1,
});
await ctx.chainProgress.noteSuccess(currentModel);
@@ -177,8 +176,8 @@ export async function runModelChain(ctx: ModelReviewContext, params: {
return { ...response, userPrompt, parsed };
} catch (error) {
const isLastModel = startIndex + modelIndex >= wholeChain.length - 1;
- // Salvage a truncated partial from the final model rather than fail outright.
- const partial = isLastModel ? partialResponseOf(error) : null;
+// Salvage truncated partials from the final model.
+const partial = isLastModel ? partialResponseOf(error) : null;
if (partial) {
try {
const parsed = params.parse(partial.rawText, { isLastModel: true });
@@ -259,8 +258,8 @@ export async function runModelChain(ctx: ModelReviewContext, params: {
retryCause,
);
- // Skipped once at chain's end, so a fresh retry starts clean rather than looping.
- if (attemptedFailedThrough > 0 && attemptedFailedThrough < wholeChain.length) {
+// Skipped at chain end, so a fresh retry starts clean.
+if (attemptedFailedThrough > 0 && attemptedFailedThrough < wholeChain.length) {
await Promise.all(progressLabels.map((key) => ctx.chainProgress.advance(key, attemptedFailedThrough)));
Object.defineProperty(error, 'nextChainIndex', { value: attemptedFailedThrough, configurable: true });
} else {
@@ -270,8 +269,8 @@ export async function runModelChain(ctx: ModelReviewContext, params: {
}
if (!attemptedAnyModel) {
- // Unwrap so a permanent operator error isn't hidden behind a transient wrapper.
- if (lastError !== undefined) {
+// Unwrap permanent operator error.
+if (lastError !== undefined) {
if (isTransientModelFailure(lastError)) {
throw new RetryableModelError(`Every model for ${label} failed to resolve; retrying later.`, lastError);
}
diff --git a/packages/models/src/internal/model-review-file.ts b/packages/models/src/internal/model-review-file.ts
index 78145ec9..decf1e08 100644
--- a/packages/models/src/internal/model-review-file.ts
+++ b/packages/models/src/internal/model-review-file.ts
@@ -195,7 +195,7 @@ export type BatchReviewOutcome = ModelResponse & {
userPrompt: string;
};
-// Caller must not record batch.missing as reviewed when fanning out to file rows.
+// Do not record batch.missing as reviewed.
export async function reviewFiles(ctx: ModelReviewContext, params: {
files: readonly FileDiff[];
prTitle: string | null;
diff --git a/packages/models/src/internal/model-support.ts b/packages/models/src/internal/model-support.ts
index bcb8443e..9117f41a 100644
--- a/packages/models/src/internal/model-support.ts
+++ b/packages/models/src/internal/model-support.ts
@@ -2,7 +2,7 @@ import { normalizeModelId } from '@codraoss/schema';
import { isTimeoutMessage, matchesAnyTransientSubstring } from '@codraoss/schema/transient-errors';
import { UnparseableModelResponseError } from '../types';
-// Hook for future legacy ID rewrites, applied before resolution.
+// Hook for legacy ID rewrites.
const MODEL_ALIASES: Record = {};
export function mergeCounts(sources: Array | undefined>): Record {
@@ -22,14 +22,14 @@ export function estimatePromptTokens(systemPrompt: string, userPrompt: string):
export const PROMPT_FIT_SAFETY_FACTOR = 0.8;
-// Floor to reject misparsed request quotas, not real token buckets.
+// Floor to reject misparsed request quotas.
export const MIN_PLAUSIBLE_TOKEN_BUCKET = 1_000;
export function isPlausibleTokenBucket(limitTokens: number | undefined): boolean {
return typeof limitTokens === 'number' && limitTokens >= MIN_PLAUSIBLE_TOKEN_BUCKET;
}
-// Lives here (not with callers) to avoid vi.mock TypeError in specs.
+// Extracted to avoid vi.mock TypeError in specs.
export function nextChainIndexOf(error: unknown): number | null {
const value = (error as { nextChainIndex?: unknown } | null)?.nextChainIndex;
return typeof value === 'number' && Number.isInteger(value) && value > 0 ? value : null;
@@ -43,7 +43,7 @@ export const MAX_METERED_QUEUE_DEPTH = 2;
const QUOTA_VIOLATION_PATTERN = /metric:\s*(\S+?),\s*limit:\s*(\d[\d_,]*)/gi;
-// Excludes request-count quotas, which would otherwise disable the model.
+// Excludes request-count quotas.
const TOKEN_QUOTA_METRIC = /(?:input_token|output_token|token_count|_tokens)/i;
export function parseRateLimitFromError(error: unknown): { limitTokens?: number; retryAfterMs?: number } {
diff --git a/packages/models/src/providers/cloudflare.ts b/packages/models/src/providers/cloudflare.ts
index 48c191ed..889a06e0 100644
--- a/packages/models/src/providers/cloudflare.ts
+++ b/packages/models/src/providers/cloudflare.ts
@@ -8,11 +8,10 @@ export interface CloudflareAiBinding {
run(model: string, args: unknown, options?: unknown): Promise;
}
-// Reasoning models under strict-JSON can burn the token budget thinking and never emit; fail fast and defer.
+// Reasoning models under strict-JSON can burn the token budget thinking and never emit.
const CLOUDFLARE_TIMEOUT_MS = MODEL_TIMEOUT_MAX_MS;
const CLOUDFLARE_DEFAULT_OUTPUT_TOKENS = OUTPUT_TOKENS_FLOOR;
-// Workers AI context windows vary widely by model, so this stays modest next to Gemini's: an over-large
-// `max_completion_tokens` is refused by the smaller models rather than clamped.
+// Workers AI context windows vary widely, so this stays modest: larger `max_completion_tokens` are clamped.
const CLOUDFLARE_MAX_OUTPUT_TOKENS = 16_384;
type UnknownRecord = Record;
@@ -117,7 +116,7 @@ function extractCloudflareUsage(result: unknown) {
};
}
-// Grammar comes from the CALLER: hardcoding the file-review schema here once forced the verifier to emit a file-review object, silently defaulting `results` to `[]`.
+// Grammar comes from CALLER.
function buildCloudflareInferenceRequest(input: ModelInput) {
const prompts = jsonOnlyPrompts(input);
return {
@@ -237,9 +236,9 @@ export async function reviewWithCloudflare(
providerName = 'Cloudflare',
options?: { timeoutMs?: number },
): Promise {
- // Single attempt: a retry would spend another subrequest on a model that just failed, when the fallback chain is about to try another.
- const timeoutMs = options?.timeoutMs ?? CLOUDFLARE_TIMEOUT_MS;
- let timer: ReturnType | undefined;
+// Single attempt: retries would waste subrequests on a failing model.
+const timeoutMs = options?.timeoutMs ?? CLOUDFLARE_TIMEOUT_MS;
+let timer: ReturnType | undefined;
// Promise.race only stops us awaiting; the binding's abort signal is what actually cancels the still-running subrequest.
const controller = new AbortController();
diff --git a/packages/models/src/providers/google.ts b/packages/models/src/providers/google.ts
index 0c80b877..240b4e2c 100644
--- a/packages/models/src/providers/google.ts
+++ b/packages/models/src/providers/google.ts
@@ -14,12 +14,10 @@ import {
const GEMINI_TIMEOUT_MS = MODEL_TIMEOUT_MAX_MS;
const GEMINI_MAX_RETRIES = 2;
const GEMINI_DEFAULT_OUTPUT_TOKENS = OUTPUT_TOKENS_FLOOR;
-// 65k leaves room for thinking tokens plus dense multi-file output.
const GEMINI_MAX_OUTPUT_TOKENS = 65_536;
const GEMINI_MAX_RETRY_DELAY_MS = 5_000;
const DEFAULT_GEMINI_BASE_URL = 'https://generativelanguage.googleapis.com/v1beta';
-// 429 handled separately; only retryable if a cool-off is stated.
function isRetryableGeminiStatus(status: number) {
return status === 408 || status === 500 || status === 502 || status === 503 || status === 504 || status === 524;
}
@@ -77,8 +75,8 @@ export function classifySchemaRejection(status: number, message: string): 'confi
function isRetryableTransportError(error: unknown) {
if (!(error instanceof Error)) return false;
- // Skip retrying timeouts (caller already grants up to 2m); defer to fallback chain.
- if (error.name === 'TimeoutError' || error.message.toLowerCase().includes('timed out')) return false;
+// Skip retrying timeouts.
+if (error.name === 'TimeoutError' || error.message.toLowerCase().includes('timed out')) return false;
if (error.message.includes('fetch failed')) return true;
return error instanceof TypeError;
}
@@ -110,7 +108,7 @@ export async function reviewWithGoogle(
let currentCeiling = Math.min(GEMINI_MAX_OUTPUT_TOKENS, answerBudget + thinkingBudget);
let ceilingRaised = false;
const fail = (error: unknown): never => {
- // Confident rejections only: a probe that failed anyway proves nothing, and latching would strip the schema from every later call in the job. A successful probe latches via `degraded` instead.
+ // Latch confident rejections only.
if (schemaRejected && schemaRejectionBranch === 'confident' && typeof error === 'object' && error !== null) {
Object.defineProperty(error, 'schemaDropped', { value: true, configurable: true });
}
@@ -205,8 +203,8 @@ export async function reviewWithGoogle(
continue;
}
- // Unexplained invalid-argument 400: strip optional features one at a time -- grammar, then thinking budget -- refunding the attempt each time. The latches bound this ladder to two extra probes.
- if (response.status === 400 && /invalid argument/i.test(message)) {
+// Unexplained invalid-argument 400: strip optional features one at a time (grammar, then thinking budget).
+if (response.status === 400 && /invalid argument/i.test(message)) {
if (responseJsonSchema && !schemaRejected) {
schemaRejected = true;
schemaRejectionBranch = 'catchall';
@@ -233,8 +231,8 @@ export async function reviewWithGoogle(
const requestedDelayMs = response.status === 429
? retryAfterDelayMs(response.headers.get('retry-after')) ?? requestedRetryDelayFromBody(message)
: null;
- // Unstated 429s back off ~60s, making them unretryable here; retry only short, stated cool-offs.
- const isRetryable = response.status === 429
+ // Retry only short, stated cool-offs.
+ const isRetryable = response.status === 429
? requestedDelayMs !== null && requestedDelayMs <= GEMINI_MAX_RETRY_DELAY_MS
: isRetryableGeminiStatus(response.status);
const retryDelayMs = Math.min(
@@ -318,7 +316,7 @@ export async function reviewWithGoogle(
return fail(new Error('Gemini returned an empty response.'));
}
- // Attach partial text so a later fallback model can salvage it.
+ // Attach partial text for fallback models.
if (truncated && input.truncationIntolerant) {
const error = new UnparseableModelResponseError(model, 'finishReason=MAX_TOKENS');
attachPartialResponse(error, {
diff --git a/packages/models/src/providers/openai.ts b/packages/models/src/providers/openai.ts
index c218fa18..1bcf9ea5 100644
--- a/packages/models/src/providers/openai.ts
+++ b/packages/models/src/providers/openai.ts
@@ -4,8 +4,6 @@ import { ProviderRequestError, providerErrorMessage, jsonOnlyPrompts, type Model
import { assertPublicBaseUrl } from '../url-guard';
import { MODEL_TIMEOUT_MAX_MS, resolveOutputTokenCeiling } from '../limits';
-// Fallback when the caller supplies no diff-size-aware budget. Shares the review ceiling so an
-// omitting caller can never outlast the chain budget that governs everything else.
const OPENAI_TIMEOUT_MS = MODEL_TIMEOUT_MAX_MS;
const OPENAI_DEFAULT_OUTPUT_TOKENS = 4096;
const OPENAI_MAX_OUTPUT_TOKENS = 16_384;
diff --git a/packages/models/src/providers/vertex.ts b/packages/models/src/providers/vertex.ts
index 40f1d21c..b732250f 100644
--- a/packages/models/src/providers/vertex.ts
+++ b/packages/models/src/providers/vertex.ts
@@ -10,22 +10,18 @@ import {
resolveOutputTokenCeiling,
} from '../limits';
-// Vertex's REST API rejects plain API keys and requires an OAuth2 token via RFC 7523 JWT-bearer grant, so `apiKey` here holds the full service-account JSON key, not a short API key string.
+// Vertex API requires OAuth2; apiKey holds service-account JSON.
const VERTEX_TIMEOUT_MS = MODEL_TIMEOUT_MAX_MS;
const VERTEX_DEFAULT_OUTPUT_TOKENS = OUTPUT_TOKENS_FLOOR;
-// Same Gemini models as the Google adapter, so the same ceiling and thinkingConfig (unbounded reasoning
-// would otherwise consume the whole ceiling and leave a truncated answer).
+// Same Gemini models as the Google adapter, so same ceiling and thinkingConfig applies.
const VERTEX_MAX_OUTPUT_TOKENS = 65_536;
-// Retries for a 429 only, and only while the caller's own timeout still has room. See the loop below
-// for why resending an unchanged request is the correct response to this particular refusal.
+// Retries for a 429 only, and only while caller's timeout has room.
const VERTEX_QUOTA_RETRIES = 2;
const VERTEX_QUOTA_BACKOFF_MS = 4_000;
-// Room a resend needs to be worth starting at all; a Vertex 429 itself comes back in ~7s.
const VERTEX_MIN_ATTEMPT_MS = 8_000;
const OAUTH_TOKEN_URL = 'https://oauth2.googleapis.com/token';
const OAUTH_SCOPE = 'https://www.googleapis.com/auth/cloud-platform';
const ACCESS_TOKEN_LIFETIME_S = 3600;
-// Refresh before real expiry so an in-flight review never starts a call with a token that expires mid-request.
const TOKEN_REFRESH_MARGIN_MS = 60_000;
interface VertexGenerateResponse {
@@ -47,7 +43,7 @@ interface CachedToken {
expiresAt: number;
}
-// Per-isolate cache, not per-request: saves a token mint (and a subrequest) on every file review after the first to hit a warm isolate.
+// Per-isolate cache.
const tokenCache = new Map();
function parseServiceAccountKey(raw: string): ServiceAccountKey {
@@ -187,7 +183,7 @@ export async function reviewWithVertex(
],
generationConfig: {
responseMimeType: 'application/json',
- // No `responseJsonSchema`: this adapter cannot drop a schema mid-flight, so a rejection would fail the file outright.
+ // No `responseJsonSchema`: this adapter cannot drop schema mid-flight.
maxOutputTokens: ceiling,
...(includeThinking ? { thinkingConfig: { thinkingBudget } } : {}),
// Same models as the Google adapter, so the same value keeps the two paths comparable.
diff --git a/packages/models/src/runner.ts b/packages/models/src/runner.ts
index a20723d3..d48ace7c 100644
--- a/packages/models/src/runner.ts
+++ b/packages/models/src/runner.ts
@@ -20,36 +20,29 @@ import { ModelRateLimitBook } from './internal/model-rate-limits';
import { ModelChainProgressStore } from './internal/model-chain-progress';
import { type ModelChainContext, generateSummary, verifyFindings } from './internal/model-chain-runner';
import { type ModelReviewContext, reviewFile, reviewFiles } from './internal/model-review-file';
-// Re-exported so test doubles can be typed against the real shape.
export type { BatchReviewOutcome } from './internal/model-review-file';
import { pollReviewBatch, submitReviewBatch } from './internal/model-review-batch';
-// Re-exported: core/review.ts and two specs import these.
export { RetryableModelError, isRetryableModelError, nextChainIndexOf } from './internal/model-support';
-
export { PROMPT_FIT_SAFETY_FACTOR, estimatePromptTokens } from './internal/model-support';
-// Re-exported to avoid a sibling import (no-restricted-imports).
export { ModelChainProgressStore } from './internal/model-chain-progress';
export { isPlausibleTokenBucket, parseRateLimitFromError } from './internal/model-support';
const PROVIDER_UNAVAILABLE_TTL_SECONDS = 24 * 60 * 60;
export class ModelRunner {
- // Caches the in-flight promise so concurrent calls for a model share one request.
+ // Caches in-flight config requests.
private readonly resolvedModelCache = new Map>();
- // Keyed by model, not provider; backed by chainProgress so cool-offs persist across invocations.
+ // Backed by chainProgress to persist across invocations.
private readonly rateLimits: ModelRateLimitBook;
- // KV can't flip unavailable to available within one invocation, so cache per instance.
+ // Cached per instance.
private readonly providerUnavailableCache = new Map>();
- // Confirmed unsupported for async batching this invocation; skip re-probing.
private readonly asyncUnsupportedModels = new Set();
-
- // Same, for constrained decoding, keyed by grammar so one refusal doesn't disable others.
private readonly schemaUnsupportedModels = new Set();
- // Per-file progress so a deferral resumes instead of replaying.
+ // Per-file progress to resume defers.
private readonly chainProgress: ModelChainProgressStore;
constructor(
@@ -149,10 +142,10 @@ export class ModelRunner {
const normalized = normalizeModel(model);
let pending = this.resolvedModelCache.get(normalized);
if (!pending) {
- // Cache the null "not configured" result too, so it isn't requeried.
+ // Cache null to prevent requery.
pending = this.deps.getConfig(normalized);
this.resolvedModelCache.set(normalized, pending);
- // Drop cache entry on error so the next call retries.
+ // Drop cache on error so next call retries.
pending.catch(() => this.resolvedModelCache.delete(normalized));
}
const resolved = await pending;
@@ -178,10 +171,10 @@ export class ModelRunner {
config: ResolvedModelConfig,
input: ModelInput,
timeoutMs?: number,
- // Excludes queue wait from the caller's timing budget.
+ // Excludes queue wait from caller's budget.
onGateWait?: (waitedMs: number) => void,
): Promise {
- // Resolve credentials before the gate slot so slow work doesn't hold one.
+ // Resolve credentials before gate so slow work doesn't hold it.
if (config.apiFormat === 'cloudflare-workers-ai') {
if (!this.deps.aiBinding) {
throw new Error(`Provider ${config.providerName} requires a Cloudflare AI binding, but none was provided.`);
@@ -197,7 +190,7 @@ export class ModelRunner {
let response: ModelResponse;
try {
response = await this.rateLimits.runGated(config, onGateWait, () => {
- // Read inside the gate: a hoisted read would race the opening wave.
+ // Read inside gate to prevent race conditions.
const gatedInput = this.schemaUnsupportedModels.has(schemaKey)
? { ...input, responseSchema: undefined }
: input;
@@ -209,7 +202,7 @@ export class ModelRunner {
);
});
} catch (error) {
- // Latch failure too, so a schema-dropped retry doesn't repay the 400 and full prompt.
+ // Latch failure to avoid repeated 400s.
if (isSchemaDroppedError(error)) this.schemaUnsupportedModels.add(schemaKey);
throw error;
}
@@ -277,7 +270,7 @@ export class ModelRunner {
return reviewFile(this.reviewCtx(), params);
}
- // batch.missing files must not be recorded as reviewed.
+ // Do not record batch.missing files.
async reviewFiles(params: Parameters[1]) {
return reviewFiles(this.reviewCtx(), params);
}
diff --git a/packages/models/src/types.ts b/packages/models/src/types.ts
index 646622c9..33258b37 100644
--- a/packages/models/src/types.ts
+++ b/packages/models/src/types.ts
@@ -1,4 +1,4 @@
-// Re-exported from @codraoss/core/ports so existing @codraoss/models/types imports keep working.
+// Re-export for compatibility.
import type { ModelResponse as ModelResponseShape, ModelResponseSchema } from '@codraoss/core/ports';
export type { ModelResponse, ModelResponseSchema } from '@codraoss/core/ports';
diff --git a/packages/models/src/url-guard.ts b/packages/models/src/url-guard.ts
index 29eb29f9..cd02bd92 100644
--- a/packages/models/src/url-guard.ts
+++ b/packages/models/src/url-guard.ts
@@ -1,5 +1,4 @@
-// SSRF guard for operator-supplied provider base URLs: without it, a `baseUrl` from the dashboard could point an adapter at the Worker's own network or a cloud metadata endpoint.
-// Lives in one module because a per-adapter copy-paste version had already failed once (Anthropic fetched `config.baseUrl` unchecked); every adapter must call `assertPublicBaseUrl`.
+// SSRF guard for custom provider base URLs.
import { ProviderRequestError } from './types';
const PRIVATE_HOST_PATTERNS = [
@@ -9,11 +8,11 @@ const PRIVATE_HOST_PATTERNS = [
/^192\.168\./,
/^169\.254\./,
/^localhost$/i,
- // IPv6: URL.hostname returns the literal WITH brackets ("[::1]"), so `isPrivateHost` strips them before testing.
- /^::1?$/, // loopback and unspecified
- /^f[cd][0-9a-f]{2}:/i, // fc00::/7 unique-local
- /^fe[89ab][0-9a-f]:/i, // fe80::/10 link-local
- /^::ffff:/i, // IPv4-mapped, e.g. ::ffff:127.0.0.1
+ // IPv6 loopback, local, IPv4-mapped
+ /^::1?$/,
+ /^f[cd][0-9a-f]{2}:/i,
+ /^fe[89ab][0-9a-f]:/i,
+ /^::ffff:/i,
];
// Cloud instance-metadata endpoints, which are public-looking but reachable only from inside.
@@ -35,7 +34,6 @@ export function isValidPublicUrl(urlString: string) {
}
}
-// Throws the provider-shaped 400 every adapter already raises, so call sites stay one line.
export function assertPublicBaseUrl(baseUrl: string | null | undefined, providerName: string) {
if (baseUrl && !isValidPublicUrl(baseUrl)) {
throw new ProviderRequestError(providerName, 400, 'Invalid provider base URL.');
diff --git a/packages/node-adapters/package.json b/packages/node-adapters/package.json
index 55a02800..74378638 100644
--- a/packages/node-adapters/package.json
+++ b/packages/node-adapters/package.json
@@ -1,6 +1,6 @@
{
"name": "@codraoss/node-adapters",
- "version": "0.9.12",
+ "version": "0.9.13",
"description": "Node.js platform adapters for Codra, including BullMQ, Redis, and Stateless Orchestration.",
"type": "module",
"main": "./src/index.ts",
@@ -43,10 +43,10 @@
"typecheck": "tsc -p tsconfig.json"
},
"dependencies": {
- "@codraoss/api": "*",
- "@codraoss/core": "*",
- "@codraoss/db": "*",
- "@codraoss/schema": "*",
+ "@codraoss/api": "workspace:*",
+ "@codraoss/core": "workspace:*",
+ "@codraoss/db": "workspace:*",
+ "@codraoss/schema": "workspace:*",
"bullmq": "^6.3.8",
"ioredis": "^6.0.0",
"nanoid": "^5.0.9"
diff --git a/packages/node-adapters/src/platform.ts b/packages/node-adapters/src/platform.ts
index da811954..e5bdd696 100644
--- a/packages/node-adapters/src/platform.ts
+++ b/packages/node-adapters/src/platform.ts
@@ -1,10 +1,7 @@
import type { Clock, IdGenerator, KvStore } from '@codraoss/core/ports';
export function makeKvStore(appKv: KvStore): KvStore {
- return {
- get: (key) => appKv.get(key),
- put: (key, value, options) => appKv.put(key, value, options),
- };
+ return appKv;
}
export const systemClock: Clock = { now: () => Date.now() };
diff --git a/packages/provider-github/package.json b/packages/provider-github/package.json
index 7413c9d2..87b204a2 100644
--- a/packages/provider-github/package.json
+++ b/packages/provider-github/package.json
@@ -1,6 +1,6 @@
{
"name": "@codraoss/provider-github",
- "version": "0.9.12",
+ "version": "0.9.13",
"description": "GitHub git-provider adapter for Codra: App auth, webhooks, OAuth, and review posting.",
"author": "Devarshi Shimpi",
"license": "AGPL-3.0-only",
@@ -53,8 +53,8 @@
"postpack": "node ../../scripts/swap-publish-exports.mjs restore"
},
"dependencies": {
- "@codraoss/core": "*",
- "@codraoss/schema": "*"
+ "@codraoss/core": "workspace:*",
+ "@codraoss/schema": "workspace:*"
},
"devDependencies": {
"tsup": "^8.0.2"
diff --git a/packages/schema/package.json b/packages/schema/package.json
index 048e988c..a0408012 100644
--- a/packages/schema/package.json
+++ b/packages/schema/package.json
@@ -1,6 +1,6 @@
{
"name": "@codraoss/schema",
- "version": "0.9.12",
+ "version": "0.9.13",
"description": "Shared types and Zod contracts for Codra, the open-source code review engine.",
"author": "Devarshi Shimpi",
"license": "AGPL-3.0-only",
diff --git a/packages/schema/src/api.ts b/packages/schema/src/api.ts
index 10501047..8a26e71c 100644
--- a/packages/schema/src/api.ts
+++ b/packages/schema/src/api.ts
@@ -43,24 +43,19 @@ export const apiActions = [
export type KnownApiAction = (typeof apiActions)[number];
-// Open union: consumers can add their own action names while the known list keeps autocomplete.
export type ApiAction = KnownApiAction | (string & {});
export type AuthSessionResponse = {
user: AuthSessionUser;
- // Omitted, or a '*' entry, means "allow everything".
permissions?: string[];
};
-// Durable account record persisted in Postgres (account_settings).
export type AccountSettings = {
- // Stable, unique account id (uuid) - distinct from the GitHub user id.
id: string;
githubUserId: number;
githubUsername: string;
accountName: string | null;
accountEmail: string | null;
- // Presentation only (timestamps are always stored UTC); `null` means "follow the viewer's browser timezone".
timezone: string | null;
};
@@ -80,9 +75,6 @@ export type JobDetailResponse = {
job: JobDetail;
};
-/** Per-file reconstructed diff/prompt text, fetched on demand (see GET /api/jobs/:id/diffs) --
- diff_input isn't persisted in Postgres, so this comes from KV or a fresh GitHub fetch. Files
- with no entry are unavailable (e.g. the underlying commits are gone). */
export type JobDiffsResponse = {
diffs: Record;
};
diff --git a/packages/schema/src/hex.ts b/packages/schema/src/hex.ts
index f2de2e1c..e95e017f 100644
--- a/packages/schema/src/hex.ts
+++ b/packages/schema/src/hex.ts
@@ -1,6 +1,3 @@
-// Hex helpers, shared so the webhook verifier, the job store and the token minters agree.
-
-// Trims first: leading/trailing whitespace on a header-supplied value would shift every byte since length drives the slice offsets.
export function hexToBytes(hex: string) {
const clean = hex.trim().toLowerCase();
const bytes = new Uint8Array(clean.length / 2);
@@ -12,7 +9,6 @@ export function hexToBytes(hex: string) {
return bytes;
}
-// Cryptographically random hex, for OAuth state and session tokens.
export function randomHex(size = 32) {
const bytes = crypto.getRandomValues(new Uint8Array(size));
return Array.from(bytes, (byte) => byte.toString(16).padStart(2, '0')).join('');
diff --git a/packages/schema/src/schema-claims.ts b/packages/schema/src/schema-claims.ts
index 8a511ecf..9f74b905 100644
--- a/packages/schema/src/schema-claims.ts
+++ b/packages/schema/src/schema-claims.ts
@@ -1,6 +1,5 @@
import { reviewCategories } from './schema-enums';
-// Enforced, not just labelled; drops whole types and filters candidates.
export const claimTypes = [
'react_hook_missing_deps',
'react_missing_cleanup',
@@ -47,7 +46,6 @@ export function toClaimType(value: unknown): ClaimType {
return (claimTypes as readonly string[]).includes(value as string) ? (value as ClaimType) : 'other';
}
-// Decidable from diff hunk alone? A Record, so new types are COMPILE ERRORS until classified.
export const CLAIM_TYPE_DECIDABILITY: Record = {
sql_injection: 'diff_local',
unsafe_dom_sink: 'diff_local',
@@ -71,12 +69,10 @@ export const CLAIM_TYPE_DECIDABILITY: Record CLAIM_TYPE_DECIDABILITY[type] !== 'diff_local',
);
-// Generate candidates, never post.
export const DEFAULT_SHADOW_RULE_IDS = [
'empty-catch',
'debugger-statement',
@@ -89,7 +85,6 @@ export const DEFAULT_SHADOW_RULE_IDS = [
'insecure-random',
] as const;
-// How finding ended its life; READ-VALIDATING. Retire by marking historical.
export const findingDispositions = [
'posted',
'severity',
diff --git a/packages/schema/src/schema-enums.ts b/packages/schema/src/schema-enums.ts
index 24797c47..bd9694f5 100644
--- a/packages/schema/src/schema-enums.ts
+++ b/packages/schema/src/schema-enums.ts
@@ -1,5 +1,3 @@
-// Leaf module: plain string-literal arrays shared by schema.ts, schema-claims.ts, and
-// schema-repo-config.ts. Kept dependency-free so none of those three risk an import cycle.
export const reviewTriggers = ['auto', 'mention', 'retry'] as const;
export const jobStatuses = ['queued', 'running', 'done', 'failed', 'superseded', 'cancelled', 'stopped'] as const;
export const fileStatuses = ['pending', 'done', 'skipped', 'failed'] as const;
diff --git a/packages/schema/src/schema-repo-config.ts b/packages/schema/src/schema-repo-config.ts
index b8964aee..ccc4c424 100644
--- a/packages/schema/src/schema-repo-config.ts
+++ b/packages/schema/src/schema-repo-config.ts
@@ -31,14 +31,8 @@ export const reviewConfigSchema = z.object({
large_file_threshold_lines: z.number().int().min(1).max(5_000).default(200),
max_diff_lines_per_file: z.number().int().min(1).max(5_000).default(800),
batch_small_files: z.boolean().default(true),
- // Presentation cap: comments actually posted to the PR. Findings past this are still recorded
- // (disposition 'cap') and shown on the dashboard; nothing upstream of posting should read it.
max_comments: z.number().int().min(1).max(150).default(10),
- // How many findings the pipeline works with (generator, verifier, dashboard); independent of
- // max_comments so tightening the posted cap no longer quietly shrinks the review itself.
review_breadth: z.number().int().min(1).max(150).default(25),
- // Off by default: adds a large single file's post-change content as read-only context, costing
- // one extra GitHub subrequest per qualifying file (see FILE_CONTEXT_CHAR_BUDGET).
full_file_context: z.boolean().default(false),
min_severity: z.enum(reviewSeverities).default('P3'),
language_gates: z
@@ -98,7 +92,6 @@ export const repoConfigSchema = z.object({
)
.nullable()
.optional(),
- // Findings are UNIONED with the primary's, never voted on (F1 0.200 vs 0.149 best-single; agreement is not evidence). Never pair across a capability gap: strong + much weaker measured BELOW strong alone.
secondary: z
.object({
model: z.string(),
diff --git a/packages/schema/src/schema.ts b/packages/schema/src/schema.ts
index 4388f9f1..a920905d 100644
--- a/packages/schema/src/schema.ts
+++ b/packages/schema/src/schema.ts
@@ -44,7 +44,6 @@ import {
REPO_CONFIG_CACHE_VERSION,
} from './constants';
-// Re-exported for server use; client imports directly to keep zod out of browser bundle.
export {
reviewSeverities,
reviewConcurrencyLevels,
diff --git a/packages/ui/package.json b/packages/ui/package.json
index 67870ca3..35c3e849 100644
--- a/packages/ui/package.json
+++ b/packages/ui/package.json
@@ -1,6 +1,6 @@
{
"name": "@codraoss/ui",
- "version": "0.9.12",
+ "version": "0.9.13",
"description": "Codra's reusable React design-system primitives and hooks.",
"author": "Devarshi Shimpi",
"license": "AGPL-3.0-only",
@@ -105,7 +105,7 @@
"sonner": ">=2.0.0"
},
"dependencies": {
- "@codraoss/schema": "*",
+ "@codraoss/schema": "workspace:*",
"@base-ui/react": "^1.6.0",
"class-variance-authority": "^0.7.1",
"clsx": "^2.1.1",
diff --git a/packages/ui/src/components/bar-sparkline.tsx b/packages/ui/src/components/bar-sparkline.tsx
index bd705480..add399c1 100644
--- a/packages/ui/src/components/bar-sparkline.tsx
+++ b/packages/ui/src/components/bar-sparkline.tsx
@@ -2,19 +2,13 @@ import { useMemo } from 'react';
import { cn } from '../lib/utils';
interface BarSparklineProps {
- /** Raw daily series; aggregated into `bars` buckets for the mini chart. */
data: number[];
- /** Bar color (hex). A vertical gradient is derived from it. */
color: string;
bars?: number;
className?: string;
}
-/**
- * Resamples `data` to exactly `bars` values (summed down or nearest-neighbour
- * stretched up) so the chart renders a stable bar count even though the trend
- * query omits inactive days and a quiet range can yield far fewer points.
- */
+// Resamples data to exactly bars values (summed down or nearest-neighbour stretched up).
function bucketize(data: number[], bars: number): number[] {
const out = Array(bars).fill(0);
if (data.length === 0) return out;
@@ -34,8 +28,6 @@ function bucketize(data: number[], bars: number): number[] {
return out;
}
-// Lightweight divs rather than a charting lib.
-// Minimum height share so zero/quiet periods still render as a visible bar, not an invisible nub.
const BASELINE_PCT = 32;
export function BarSparkline({ data, color, bars = 8, className }: BarSparklineProps) {
diff --git a/packages/ui/src/components/button.tsx b/packages/ui/src/components/button.tsx
index ee067d6c..8c2ecb23 100644
--- a/packages/ui/src/components/button.tsx
+++ b/packages/ui/src/components/button.tsx
@@ -7,7 +7,6 @@ import { buttonVariants } from '../components/button-variants';
type Shape = 'base' | 'square' | 'circle';
-// Icon-only shapes: collapse padding and match width to the height of each size.
const SQUARE_WIDTH: Record = {
xs: 'w-6 p-0',
sm: 'w-8 p-0',
@@ -27,9 +26,7 @@ export interface ButtonProps
VariantProps {
asChild?: boolean;
shape?: Shape;
- /** Element rendered before children (skipped while `loading`). */
icon?: React.ReactNode;
- /** Shows a spinner and disables the button. */
loading?: boolean;
}
@@ -37,7 +34,6 @@ const Button = React.forwardRef(
({ className, variant, size, shape = 'base', asChild = false, icon, loading, children, ...props }, ref) => {
const classes = cn(buttonVariants({ variant, size }), shapeClass(shape, size), className);
- // `asChild` renders the child itself with props merged onto it (Base UI's equivalent of the former Radix Slot).
return useRender({
render: asChild && React.isValidElement(children) ? children : undefined,
defaultTagName: 'button',
@@ -67,7 +63,6 @@ export interface LinkButtonProps
VariantProps {
shape?: Shape;
icon?: React.ReactNode;
- /** Open in a new tab with safe rel attributes. */
external?: boolean;
}
diff --git a/packages/ui/src/components/chart-primitives.tsx b/packages/ui/src/components/chart-primitives.tsx
index 33a8f60f..3f90841a 100644
--- a/packages/ui/src/components/chart-primitives.tsx
+++ b/packages/ui/src/components/chart-primitives.tsx
@@ -28,8 +28,6 @@ export function GraphShell({
className?: string;
}) {
return (
- // Same chrome as the dashboard stat cards: card face carries the title, the chart itself sits
- // in a recessed inner panel.
- {/* Dot texture lives on the recessed face, where the chart reads against it. */}
{legend && (
@@ -58,18 +55,11 @@ export function GraphShell({
}
export interface SeriesMarkerProps {
- /** Flat CSS colour. Ignored when `hatched` is set, which paints its own fill. */
color?: string;
- /** The cross-hatched fill used for the input-token series. */
hatched?: boolean;
- /** A dashed rule instead of a swatch, for series drawn as a dashed line. */
dashed?: boolean;
}
-/**
- * The swatch that identifies a series. Shared by the legend and the tooltip so a series looks the
- * same in both - a tooltip dot that doesn't match its legend chip reads as a different series.
- */
export function SeriesMarker({ color, hatched, dashed }: SeriesMarkerProps) {
if (dashed) {
return (
diff --git a/packages/ui/src/components/load-error.tsx b/packages/ui/src/components/load-error.tsx
index fa587947..6901ab03 100644
--- a/packages/ui/src/components/load-error.tsx
+++ b/packages/ui/src/components/load-error.tsx
@@ -3,18 +3,14 @@ import { Button } from '../components/button';
import { cn } from '../lib/utils';
interface LoadErrorProps {
- /** Friendly headline, e.g. "Couldn't load dashboard data". */
title?: string;
- /** Raw error detail (e.g. "Failed to fetch"), shown as a mono chip. */
detail?: string | null;
- /** Guidance line under the title; defaults to connection-check copy. */
hint?: string;
onRetry?: () => void;
retrying?: boolean;
className?: string;
}
-/** Friendly copy up front, raw error as a small mono chip - instead of a bare toast echoing "Failed to fetch". */
export function LoadError({
title = "Couldn't load data",
detail,
diff --git a/packages/ui/src/components/motion/smooth-scroll.tsx b/packages/ui/src/components/motion/smooth-scroll.tsx
index 052eda8b..c64fd684 100644
--- a/packages/ui/src/components/motion/smooth-scroll.tsx
+++ b/packages/ui/src/components/motion/smooth-scroll.tsx
@@ -11,7 +11,6 @@ import {
useRef,
} from 'react';
-// Named fn, not a lib/ease token: Lenis needs a (t) => number easing fn, not bezier points.
const EASE_SCROLL = (t: number) => Math.min(1, 1.001 - 2 ** (-10 * t));
export type ScrollTarget = number | string | HTMLElement;
@@ -23,13 +22,10 @@ export type ScrollToOptions = {
};
export type SmoothScrollApi = {
- /** Null on the reduced-motion / native path. */
lenis: Lenis | null;
scrollY: MotionValue
;
progress: MotionValue;
- /** px/frame. */
velocity: MotionValue;
- /** Jumps instantly under reduced motion. */
scrollTo: (target: ScrollTarget, options?: ScrollToOptions) => void;
};
@@ -37,14 +33,11 @@ const SmoothScrollContext = createContext(null);
export interface SmoothScrollProps {
children: ReactNode;
- /** True drives window scroll; false scrolls a contained area. */
root?: boolean;
- /** Lower = smoother, heavier. */
lerp?: number;
duration?: number;
orientation?: 'vertical' | 'horizontal';
wheelMultiplier?: number;
- /** Off by default: native touch momentum is already good on mobile. */
touch?: boolean;
className?: string;
}
@@ -208,7 +201,6 @@ export function SmoothScroll({
smoothWheel: true,
syncTouch: touch,
easing: EASE_SCROLL,
- // Else Lenis preventDefault()s every wheel event, blocking nested scroll areas.
allowNestedScroll: true,
}}
>
diff --git a/packages/ui/src/components/motion/stepped-slider.tsx b/packages/ui/src/components/motion/stepped-slider.tsx
index 739fc57a..9568cf56 100644
--- a/packages/ui/src/components/motion/stepped-slider.tsx
+++ b/packages/ui/src/components/motion/stepped-slider.tsx
@@ -1,5 +1,4 @@
-// Adapted from a min/max/step range slider so labeled steps (e.g. Low/Medium/High/Max) line up on
-// evenly spaced stops; the value readout sits statically above the track (no floating/portal tooltip).
+// Stepped slider with static value readout.
import {
domAnimation,
LazyMotion,
@@ -26,8 +25,6 @@ import { useIsDarkMode } from '../../hooks/use-is-dark-mode';
const SPRING_GLIDE = { stiffness: 700, damping: 50, mass: 0.5 } as const;
const SPRING_BOUNCY = { type: 'spring', stiffness: 500, damping: 14, mass: 0.7 } as const;
-// Deterministic 0..1 seed from the slider's id, so two sliders maxed out at once get slightly
-// different hues/timing instead of pulsing in perfect unison.
function seedFromId(id: string | undefined) {
if (!id) return 0;
let hash = 0;
@@ -50,9 +47,7 @@ export interface SteppedSliderProps {
min?: number;
max?: number;
step?: number;
- /** Tick dots + labels rendered at each defined step. */
steps?: SteppedSliderStep[];
- /** Live value readout shown above the track, and used as the accessible aria-valuetext. Defaults to the raw value. */
formatValue?: (value: number) => string;
disabled?: boolean;
className?: string;
@@ -83,9 +78,6 @@ export function SteppedSlider({
const trackRef = useRef(null);
const [internal, setInternal] = useState(defaultValue);
const [active, setActive] = useState(false);
- // Decoupled from the committed value so onValueChange fires once per gesture (on release),
- // not on every pointer-move tick. Mirrored in a ref so release can read the pending value
- // without doing the commit inside a state updater.
const [dragValue, setDragValue] = useState(null);
const dragValueRef = useRef(null);
const controlled = value !== undefined;
@@ -93,8 +85,6 @@ export function SteppedSlider({
const current = active && dragValue !== null ? clamp(dragValue, min, max) : committedValue;
const percent = ((current - min) / (max - min)) * 100;
const isMaxed = current === max;
-
- // Hue-shifted and timed per instance so simultaneous maxed-out sliders don't pulse in unison.
const hue = 185 + (seed - 0.5) * 16;
const glowColor = isDark ? `oklch(68% 0.14 ${hue})` : `oklch(52% 0.13 ${hue})`;
const fillGradient = isDark
@@ -209,7 +199,6 @@ export function SteppedSlider({
disabled ? 'pointer-events-none opacity-50' : 'cursor-grab active:cursor-grabbing',
)}
>
- {/* Pattern repeats every 10px, shifting by exactly one period, so the loop point is never visible. */}
{isMaxed ? (
- {/* Inset so end dots don't clip; sized up at max so they don't blend into the dot texture. */}
{steps.map((tick) => {
const tp = ((tick.value - min) / (max - min)) * 100;
@@ -248,7 +236,6 @@ export function SteppedSlider({
})}
- {/* Own layer so only opacity animates - Motion's box-shadow interpolator can't parse CSS custom properties in the color stops. */}
{isMaxed && !reduce && (
- {/* layoutRoot: the indicator's layoutId measures in page coordinates, so without this
- it would replay scroll offsets as movement inside fixed/scrolled containers. */}
{children}
@@ -137,7 +132,6 @@ export function TabsTrigger({
);
}
- // Segment uses a neutral raised surface (vs. pill's max-contrast) so it reads as a standard segmented control.
const isSegment = variant === 'segment';
const radius = variant === 'pill' ? 'rounded-full' : 'rounded-[5px]';
const indicatorBg = isSegment ? 'bg-ui-base shadow-sm ring-1 ring-ui-line' : 'bg-primary';
diff --git a/packages/ui/src/components/onboarding-card.tsx b/packages/ui/src/components/onboarding-card.tsx
index 5f722622..ef920e23 100644
--- a/packages/ui/src/components/onboarding-card.tsx
+++ b/packages/ui/src/components/onboarding-card.tsx
@@ -42,7 +42,6 @@ export function OnboardingCard({
- {/* Header */}
{allDone ? completedTitle : title}
@@ -63,7 +62,6 @@ export function OnboardingCard({
)}
- {/* Segmented bar */}
- {/* Check circle */}
-
-
-
-
- {/* Text */}
- {step.label}
-
+ {/* Check circle */}
+
+
+
+
{step.label}
+
);
if (step.onClick) {
diff --git a/packages/ui/src/components/select-panel.tsx b/packages/ui/src/components/select-panel.tsx
index 233dd1ae..296bb04b 100644
--- a/packages/ui/src/components/select-panel.tsx
+++ b/packages/ui/src/components/select-panel.tsx
@@ -109,7 +109,6 @@ export function SelectPanel({
overflow: 'hidden',
pointerEvents: open ? 'auto' : 'none',
}}
- // Flush against the trigger, then separates into its own rounded pill.
className="z-50 border border-ui-line bg-ui-base shadow-lg shadow-black/[0.04] dark:shadow-black/40"
>
onHighlight(index)}
onClick={() => onSelect(option.value)}
- className={cn(
- // `whitespace-nowrap`: on the 72px "rows per page" select, the check icon ate the width and "10" wrapped to stacked digits.
- 'flex w-full items-center justify-between gap-2 whitespace-nowrap rounded-md px-2.5 py-1.5 text-left text-sm outline-none transition-colors',
+ className={cn(
+ 'flex w-full items-center justify-between gap-2 whitespace-nowrap rounded-md px-2.5 py-1.5 text-left text-sm outline-none transition-colors',
selected
? 'bg-ui-brand/10 font-medium text-ui-brand'
: 'text-ui-default hover:bg-ui-fill hover:text-ui-strong focus-visible:bg-ui-fill',
diff --git a/packages/ui/src/components/select-shared.ts b/packages/ui/src/components/select-shared.ts
index daae2415..1479fee8 100644
--- a/packages/ui/src/components/select-shared.ts
+++ b/packages/ui/src/components/select-shared.ts
@@ -7,7 +7,6 @@ export interface SelectOption {
label: string;
}
-/** Trigger box in viewport coordinates; the portaled panel is positioned from it. */
export interface TriggerRect {
left: number;
width: number;
@@ -15,7 +14,7 @@ export interface TriggerRect {
bottom: number;
}
-// Spring with bounce powers the unfold; per-property timings on the panel choreograph it.
+// Spring with bounce powers the unfold.
export const CHEVRON_TRANSITION: Transition = { type: 'spring', duration: 0.4, bounce: 0.3 };
// Compounds per option; 0.035 delayed the last item ~0.9s on long lists, so 0.02 is the compromise.
@@ -28,5 +27,5 @@ export const ITEM_VARIANTS: Variants = {
show: { opacity: 1, y: 0, filter: 'blur(0px)' },
};
-/** Snaps a property to its target: the side not being choreographed, and every reduced-motion path. */
+/** Snaps a property to its target. */
export const INSTANT_TRANSITION: Transition = { duration: 0 };
diff --git a/packages/ui/src/components/select.tsx b/packages/ui/src/components/select.tsx
index c94dd325..03ba5f05 100644
--- a/packages/ui/src/components/select.tsx
+++ b/packages/ui/src/components/select.tsx
@@ -25,7 +25,6 @@ interface SelectProps {
triggerClassName?: string;
triggerStyle?: CSSProperties;
leadingIcon?: ReactNode;
- /** Decides the dropdown's background so it stays distinguishable from where the trigger sits. */
variant?: 'page' | 'card';
}
@@ -56,12 +55,10 @@ export function Select({
const [rect, setRect] = useState(null);
const [highlightedIndex, setHighlightedIndex] = useState(0);
const optionRefs = useRef>([]);
- /** What last moved the highlight - only keyboard moves should auto-scroll. */
const highlightSource = useRef<'keyboard' | 'pointer'>('keyboard');
const selectedOption = options.find((opt) => opt.value === value);
- // Depends on `open` only: keying off `options`/`value` yanked the highlight back when a caller passed a freshly-built array mid-interaction.
useEffect(() => {
if (!open) return;
highlightSource.current = 'keyboard';
@@ -70,7 +67,6 @@ export function Select({
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [open]);
- // Keyboard only: on hover this looped (hover → scrollIntoView → reposition → mouseenter again), causing jitter.
useEffect(() => {
if (!open || highlightSource.current !== 'keyboard') return;
optionRefs.current[highlightedIndex]?.scrollIntoView({ block: 'nearest' });
@@ -83,8 +79,6 @@ export function Select({
const target = e.target as Node;
if (triggerRef.current?.contains(target)) return;
if (panelRef.current?.contains(target)) return;
- // The label forwards its click to the trigger, so treating it as "outside" would close the
- // panel here and let that forwarded click reopen it -- one click, no visible change.
if (labelRef.current?.contains(target)) return;
setOpen(false);
};
@@ -106,7 +100,6 @@ export function Select({
return () => observer.disconnect();
}, []);
- // Flips upward when there's no room below; batched to one animation frame since scroll/resize fire faster than repaints.
useLayoutEffect(() => {
if (!open) return;
const trigger = triggerRef.current;
@@ -122,7 +115,6 @@ export function Select({
setPlacement(below < h + 16 && above > below ? 'top' : 'bottom');
};
const scheduleUpdate = (e?: Event) => {
- // Scrolling the list doesn't move the trigger; recomputing only causes flicker.
if (e && e.target instanceof Node && panelRef.current?.contains(e.target)) return;
if (frame !== null) return;
frame = requestAnimationFrame(update);
@@ -230,7 +222,6 @@ export function Select({
/>
- {/* Portaled to so it can't be clipped by an ancestor's stacking context. */}
{createPortal(
Date: Wed, 23 Sep 2026 02:30:26 +0530
Subject: [PATCH 07/16] chore: update dependencies to specific versions across
all packages
---
apps/node/package.json | 14 ++--
apps/worker/package.json | 12 ++--
package-lock.json | 98 +++++++++++++--------------
package.json | 14 ++--
packages/api/package.json | 10 +--
packages/core/package.json | 2 +-
packages/db/package.json | 4 +-
packages/models/package.json | 4 +-
packages/node-adapters/package.json | 8 +--
packages/provider-github/package.json | 4 +-
packages/ui/package.json | 2 +-
11 files changed, 86 insertions(+), 86 deletions(-)
diff --git a/apps/node/package.json b/apps/node/package.json
index bca66afc..71547e69 100644
--- a/apps/node/package.json
+++ b/apps/node/package.json
@@ -10,13 +10,13 @@
"typecheck": "tsc -p tsconfig.json"
},
"dependencies": {
- "@codraoss/api": "*",
- "@codraoss/core": "*",
- "@codraoss/db": "*",
- "@codraoss/models": "*",
- "@codraoss/node-adapters": "*",
- "@codraoss/provider-github": "*",
- "@codraoss/schema": "*",
+ "@codraoss/api": "^0.9.13",
+ "@codraoss/core": "^0.9.13",
+ "@codraoss/db": "^0.9.13",
+ "@codraoss/models": "^0.9.13",
+ "@codraoss/node-adapters": "^0.9.13",
+ "@codraoss/provider-github": "^0.9.13",
+ "@codraoss/schema": "^0.9.13",
"@hono/node-server": "^1.11.5",
"bullmq": "^6.3.8",
"dotenv": "^16.4.7",
diff --git a/apps/worker/package.json b/apps/worker/package.json
index 7bc6ce5a..887e4e2b 100644
--- a/apps/worker/package.json
+++ b/apps/worker/package.json
@@ -4,12 +4,12 @@
"private": true,
"type": "module",
"dependencies": {
- "@codraoss/api": "*",
- "@codraoss/core": "*",
- "@codraoss/db": "*",
- "@codraoss/models": "*",
- "@codraoss/provider-github": "*",
- "@codraoss/schema": "*",
+ "@codraoss/api": "^0.9.13",
+ "@codraoss/core": "^0.9.13",
+ "@codraoss/db": "^0.9.13",
+ "@codraoss/models": "^0.9.13",
+ "@codraoss/provider-github": "^0.9.13",
+ "@codraoss/schema": "^0.9.13",
"hono": "^4.12.34"
},
"devDependencies": {
diff --git a/package-lock.json b/package-lock.json
index deb8f494..6714ccc2 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -14,13 +14,13 @@
],
"dependencies": {
"@base-ui/react": "^1.6.0",
- "@codraoss/api": "*",
- "@codraoss/core": "*",
- "@codraoss/db": "*",
- "@codraoss/models": "*",
- "@codraoss/provider-github": "*",
- "@codraoss/schema": "*",
- "@codraoss/ui": "*",
+ "@codraoss/api": "^0.9.13",
+ "@codraoss/core": "^0.9.13",
+ "@codraoss/db": "^0.9.13",
+ "@codraoss/models": "^0.9.13",
+ "@codraoss/provider-github": "^0.9.13",
+ "@codraoss/schema": "^0.9.13",
+ "@codraoss/ui": "^0.9.13",
"class-variance-authority": "^0.7.1",
"clsx": "^2.1.1",
"hono": "^4.12.34",
@@ -74,15 +74,15 @@
},
"apps/node": {
"name": "@codraoss/node-server",
- "version": "0.9.12",
- "dependencies": {
- "@codraoss/api": "*",
- "@codraoss/core": "*",
- "@codraoss/db": "*",
- "@codraoss/models": "*",
- "@codraoss/node-adapters": "*",
- "@codraoss/provider-github": "*",
- "@codraoss/schema": "*",
+ "version": "0.9.13",
+ "dependencies": {
+ "@codraoss/api": "^0.9.13",
+ "@codraoss/core": "^0.9.13",
+ "@codraoss/db": "^0.9.13",
+ "@codraoss/models": "^0.9.13",
+ "@codraoss/node-adapters": "^0.9.13",
+ "@codraoss/provider-github": "^0.9.13",
+ "@codraoss/schema": "^0.9.13",
"@hono/node-server": "^1.11.5",
"bullmq": "^6.3.8",
"dotenv": "^16.4.7",
@@ -113,14 +113,14 @@
},
"apps/worker": {
"name": "@codraoss/worker",
- "version": "0.9.12",
- "dependencies": {
- "@codraoss/api": "*",
- "@codraoss/core": "*",
- "@codraoss/db": "*",
- "@codraoss/models": "*",
- "@codraoss/provider-github": "*",
- "@codraoss/schema": "*",
+ "version": "0.9.13",
+ "dependencies": {
+ "@codraoss/api": "^0.9.13",
+ "@codraoss/core": "^0.9.13",
+ "@codraoss/db": "^0.9.13",
+ "@codraoss/models": "^0.9.13",
+ "@codraoss/provider-github": "^0.9.13",
+ "@codraoss/schema": "^0.9.13",
"hono": "^4.12.34"
},
"devDependencies": {
@@ -11490,14 +11490,14 @@
},
"packages/api": {
"name": "@codraoss/api",
- "version": "0.9.12",
+ "version": "0.9.13",
"license": "AGPL-3.0-only",
"dependencies": {
- "@codraoss/core": "*",
- "@codraoss/db": "*",
- "@codraoss/models": "*",
- "@codraoss/provider-github": "*",
- "@codraoss/schema": "*",
+ "@codraoss/core": "^0.9.13",
+ "@codraoss/db": "^0.9.13",
+ "@codraoss/models": "^0.9.13",
+ "@codraoss/provider-github": "^0.9.13",
+ "@codraoss/schema": "^0.9.13",
"hono": "^4.12.34",
"zod": "^4.3.6"
},
@@ -11525,10 +11525,10 @@
},
"packages/core": {
"name": "@codraoss/core",
- "version": "0.9.12",
+ "version": "0.9.13",
"license": "AGPL-3.0-only",
"dependencies": {
- "@codraoss/schema": "*",
+ "@codraoss/schema": "^0.9.13",
"jsonrepair": "^3.15.0",
"picomatch": "^4.0.7",
"zod": "^4.3.6"
@@ -11540,11 +11540,11 @@
},
"packages/db": {
"name": "@codraoss/db",
- "version": "0.9.12",
+ "version": "0.9.13",
"license": "AGPL-3.0-only",
"dependencies": {
- "@codraoss/core": "*",
- "@codraoss/schema": "*",
+ "@codraoss/core": "^0.9.13",
+ "@codraoss/schema": "^0.9.13",
"postgres": "^3.4.9"
},
"devDependencies": {
@@ -11571,11 +11571,11 @@
},
"packages/models": {
"name": "@codraoss/models",
- "version": "0.9.12",
+ "version": "0.9.13",
"license": "AGPL-3.0-only",
"dependencies": {
- "@codraoss/core": "*",
- "@codraoss/schema": "*"
+ "@codraoss/core": "^0.9.13",
+ "@codraoss/schema": "^0.9.13"
},
"devDependencies": {
"tsup": "^8.0.2"
@@ -11583,13 +11583,13 @@
},
"packages/node-adapters": {
"name": "@codraoss/node-adapters",
- "version": "0.9.12",
+ "version": "0.9.13",
"license": "AGPL-3.0-only",
"dependencies": {
- "@codraoss/api": "*",
- "@codraoss/core": "*",
- "@codraoss/db": "*",
- "@codraoss/schema": "*",
+ "@codraoss/api": "^0.9.13",
+ "@codraoss/core": "^0.9.13",
+ "@codraoss/db": "^0.9.13",
+ "@codraoss/schema": "^0.9.13",
"bullmq": "^6.3.8",
"ioredis": "^6.0.0",
"nanoid": "^5.0.9"
@@ -11636,11 +11636,11 @@
},
"packages/provider-github": {
"name": "@codraoss/provider-github",
- "version": "0.9.12",
+ "version": "0.9.13",
"license": "AGPL-3.0-only",
"dependencies": {
- "@codraoss/core": "*",
- "@codraoss/schema": "*"
+ "@codraoss/core": "^0.9.13",
+ "@codraoss/schema": "^0.9.13"
},
"devDependencies": {
"tsup": "^8.0.2"
@@ -11648,7 +11648,7 @@
},
"packages/schema": {
"name": "@codraoss/schema",
- "version": "0.9.12",
+ "version": "0.9.13",
"license": "AGPL-3.0-only",
"dependencies": {
"zod": "^4.3.6"
@@ -11659,11 +11659,11 @@
},
"packages/ui": {
"name": "@codraoss/ui",
- "version": "0.9.12",
+ "version": "0.9.13",
"license": "AGPL-3.0-only",
"dependencies": {
"@base-ui/react": "^1.6.0",
- "@codraoss/schema": "*",
+ "@codraoss/schema": "^0.9.13",
"class-variance-authority": "^0.7.1",
"clsx": "^2.1.1",
"sugar-high": "^2.0.3",
diff --git a/package.json b/package.json
index 1e688991..d3d418b0 100644
--- a/package.json
+++ b/package.json
@@ -71,13 +71,13 @@
},
"dependencies": {
"@base-ui/react": "^1.6.0",
- "@codraoss/api": "*",
- "@codraoss/core": "*",
- "@codraoss/db": "*",
- "@codraoss/models": "*",
- "@codraoss/provider-github": "*",
- "@codraoss/schema": "*",
- "@codraoss/ui": "*",
+ "@codraoss/api": "^0.9.13",
+ "@codraoss/core": "^0.9.13",
+ "@codraoss/db": "^0.9.13",
+ "@codraoss/models": "^0.9.13",
+ "@codraoss/provider-github": "^0.9.13",
+ "@codraoss/schema": "^0.9.13",
+ "@codraoss/ui": "^0.9.13",
"class-variance-authority": "^0.7.1",
"clsx": "^2.1.1",
"hono": "^4.12.34",
diff --git a/packages/api/package.json b/packages/api/package.json
index 1dd148fa..cb01ac9b 100644
--- a/packages/api/package.json
+++ b/packages/api/package.json
@@ -51,11 +51,11 @@
"dependencies": {
"hono": "^4.12.34",
"zod": "^4.3.6",
- "@codraoss/schema": "workspace:*",
- "@codraoss/core": "workspace:*",
- "@codraoss/db": "workspace:*",
- "@codraoss/provider-github": "workspace:*",
- "@codraoss/models": "workspace:*"
+ "@codraoss/schema": "^0.9.13",
+ "@codraoss/core": "^0.9.13",
+ "@codraoss/db": "^0.9.13",
+ "@codraoss/provider-github": "^0.9.13",
+ "@codraoss/models": "^0.9.13"
},
"devDependencies": {
"@types/node": "^22.0.3",
diff --git a/packages/core/package.json b/packages/core/package.json
index 3f872975..435030e0 100644
--- a/packages/core/package.json
+++ b/packages/core/package.json
@@ -123,7 +123,7 @@
"postpack": "node ../../scripts/swap-publish-exports.mjs restore"
},
"dependencies": {
- "@codraoss/schema": "workspace:*",
+ "@codraoss/schema": "^0.9.13",
"jsonrepair": "^3.15.0",
"picomatch": "^4.0.7",
"zod": "^4.3.6"
diff --git a/packages/db/package.json b/packages/db/package.json
index 6e7125db..fabab8b8 100644
--- a/packages/db/package.json
+++ b/packages/db/package.json
@@ -67,8 +67,8 @@
"postpack": "node ../../scripts/swap-publish-exports.mjs restore"
},
"dependencies": {
- "@codraoss/schema": "workspace:*",
- "@codraoss/core": "workspace:*",
+ "@codraoss/schema": "^0.9.13",
+ "@codraoss/core": "^0.9.13",
"postgres": "^3.4.9"
},
"devDependencies": {
diff --git a/packages/models/package.json b/packages/models/package.json
index d3836ded..c1e6e1b2 100644
--- a/packages/models/package.json
+++ b/packages/models/package.json
@@ -78,8 +78,8 @@
"postpack": "node ../../scripts/swap-publish-exports.mjs restore"
},
"dependencies": {
- "@codraoss/schema": "workspace:*",
- "@codraoss/core": "workspace:*"
+ "@codraoss/schema": "^0.9.13",
+ "@codraoss/core": "^0.9.13"
},
"devDependencies": {
"tsup": "^8.0.2"
diff --git a/packages/node-adapters/package.json b/packages/node-adapters/package.json
index 74378638..f4392b14 100644
--- a/packages/node-adapters/package.json
+++ b/packages/node-adapters/package.json
@@ -43,10 +43,10 @@
"typecheck": "tsc -p tsconfig.json"
},
"dependencies": {
- "@codraoss/api": "workspace:*",
- "@codraoss/core": "workspace:*",
- "@codraoss/db": "workspace:*",
- "@codraoss/schema": "workspace:*",
+ "@codraoss/api": "^0.9.13",
+ "@codraoss/core": "^0.9.13",
+ "@codraoss/db": "^0.9.13",
+ "@codraoss/schema": "^0.9.13",
"bullmq": "^6.3.8",
"ioredis": "^6.0.0",
"nanoid": "^5.0.9"
diff --git a/packages/provider-github/package.json b/packages/provider-github/package.json
index 87b204a2..e69d74ac 100644
--- a/packages/provider-github/package.json
+++ b/packages/provider-github/package.json
@@ -53,8 +53,8 @@
"postpack": "node ../../scripts/swap-publish-exports.mjs restore"
},
"dependencies": {
- "@codraoss/core": "workspace:*",
- "@codraoss/schema": "workspace:*"
+ "@codraoss/core": "^0.9.13",
+ "@codraoss/schema": "^0.9.13"
},
"devDependencies": {
"tsup": "^8.0.2"
diff --git a/packages/ui/package.json b/packages/ui/package.json
index 35c3e849..079223fa 100644
--- a/packages/ui/package.json
+++ b/packages/ui/package.json
@@ -105,7 +105,7 @@
"sonner": ">=2.0.0"
},
"dependencies": {
- "@codraoss/schema": "workspace:*",
+ "@codraoss/schema": "^0.9.13",
"@base-ui/react": "^1.6.0",
"class-variance-authority": "^0.7.1",
"clsx": "^2.1.1",
From b3d791a5efeb7e441cea584a162b4d3250ef6a0e Mon Sep 17 00:00:00 2001
From: Devarshi Shimpi
Date: Wed, 23 Sep 2026 02:36:12 +0530
Subject: [PATCH 08/16] fix: reorder export fields in package.json for
consistency
---
packages/api/package.json | 12 ++++++------
packages/node-adapters/package.json | 4 ++--
2 files changed, 8 insertions(+), 8 deletions(-)
diff --git a/packages/api/package.json b/packages/api/package.json
index cb01ac9b..a9aa98ee 100644
--- a/packages/api/package.json
+++ b/packages/api/package.json
@@ -29,16 +29,16 @@
"access": "public",
"exports": {
".": {
- "import": "./dist/index.js",
- "types": "./dist/index.d.ts"
+ "types": "./dist/index.d.ts",
+ "import": "./dist/index.js"
},
"./logger": {
- "import": "./dist/logger.js",
- "types": "./dist/logger.d.ts"
+ "types": "./dist/logger.d.ts",
+ "import": "./dist/logger.js"
},
"./platform": {
- "import": "./dist/platform/index.js",
- "types": "./dist/platform/index.d.ts"
+ "types": "./dist/platform/index.d.ts",
+ "import": "./dist/platform/index.js"
}
}
},
diff --git a/packages/node-adapters/package.json b/packages/node-adapters/package.json
index f4392b14..8276a6a6 100644
--- a/packages/node-adapters/package.json
+++ b/packages/node-adapters/package.json
@@ -15,8 +15,8 @@
"types": "./dist/index.d.ts",
"exports": {
".": {
- "import": "./dist/index.js",
- "types": "./dist/index.d.ts"
+ "types": "./dist/index.d.ts",
+ "import": "./dist/index.js"
}
}
},
From 1b1cdcfdb52115ea7cd0c78afbbf5d6ef2f2acc8 Mon Sep 17 00:00:00 2001
From: Devarshi Shimpi
Date: Wed, 23 Sep 2026 02:50:21 +0530
Subject: [PATCH 09/16] chore: update configuration files for improved build
process and module resolution
---
packages/node-adapters/package.json | 1 +
packages/node-adapters/tsconfig.json | 13 ++++++++-----
packages/node-adapters/tsup.config.json | 7 ++++---
3 files changed, 13 insertions(+), 8 deletions(-)
diff --git a/packages/node-adapters/package.json b/packages/node-adapters/package.json
index 8276a6a6..a5bfcadf 100644
--- a/packages/node-adapters/package.json
+++ b/packages/node-adapters/package.json
@@ -3,6 +3,7 @@
"version": "0.9.13",
"description": "Node.js platform adapters for Codra, including BullMQ, Redis, and Stateless Orchestration.",
"type": "module",
+ "sideEffects": false,
"main": "./src/index.ts",
"types": "./dist/index.d.ts",
"exports": {
diff --git a/packages/node-adapters/tsconfig.json b/packages/node-adapters/tsconfig.json
index 391e21ce..6e673328 100644
--- a/packages/node-adapters/tsconfig.json
+++ b/packages/node-adapters/tsconfig.json
@@ -1,10 +1,13 @@
{
"extends": "../../tsconfig.base.json",
"compilerOptions": {
- "outDir": "dist",
- "rootDir": "src",
- "types": ["node"]
+ "module": "ESNext",
+ "moduleResolution": "Bundler",
+ "types": ["node"],
+ "composite": false,
+ "declaration": false,
+ "emitDeclarationOnly": false,
+ "noEmit": true
},
- "include": ["src/**/*"],
- "exclude": ["node_modules", "dist"]
+ "include": ["src/**/*"]
}
diff --git a/packages/node-adapters/tsup.config.json b/packages/node-adapters/tsup.config.json
index 28a3fea0..369fd559 100644
--- a/packages/node-adapters/tsup.config.json
+++ b/packages/node-adapters/tsup.config.json
@@ -1,10 +1,11 @@
{
"entry": ["src/index.ts"],
"format": ["esm"],
- "outDir": "dist",
- "clean": true,
- "sourcemap": true,
+ "dts": true,
"splitting": false,
+ "sourcemap": true,
+ "clean": true,
"target": "node20",
+ "outDir": "dist",
"noExternal": []
}
From 61fa9049f95abf37b3b7b9c465a50e09cb5fa9e8 Mon Sep 17 00:00:00 2001
From: Devarshi Shimpi
Date: Wed, 23 Sep 2026 03:03:29 +0530
Subject: [PATCH 10/16] chore: add node-adapters to build:packages script for
comprehensive builds
---
package.json | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/package.json b/package.json
index d3d418b0..2673463a 100644
--- a/package.json
+++ b/package.json
@@ -20,7 +20,7 @@
],
"scripts": {
"build": "vite build && npm run cf-typegen",
- "build:packages": "npm run build -w @codraoss/schema && npm run build -w @codraoss/core && npm run build -w @codraoss/provider-github && npm run build -w @codraoss/db && npm run build -w @codraoss/models && npm run build -w @codraoss/api && npm run build -w @codraoss/ui",
+ "build:packages": "npm run build -w @codraoss/schema && npm run build -w @codraoss/core && npm run build -w @codraoss/provider-github && npm run build -w @codraoss/db && npm run build -w @codraoss/models && npm run build -w @codraoss/api && npm run build -w @codraoss/ui && npm run build -w @codraoss/node-adapters",
"build:all": "npm run build --workspaces --if-present",
"cf-typegen": "cd apps/worker && wrangler types ./src/worker-env.d.ts",
"deploy": "npm run build && npm run migrate && cd apps/worker && wrangler deploy",
From f48421157510919a2eb99581520c01ce5d9cfb79 Mon Sep 17 00:00:00 2001
From: Devarshi Shimpi
Date: Wed, 23 Sep 2026 03:13:14 +0530
Subject: [PATCH 11/16] feat: add build coverage check to CI workflow and
scripts
---
.github/workflows/ci.yml | 3 +++
package.json | 3 ++-
scripts/check-package-builds.mjs | 43 ++++++++++++++++++++++++++++++++
3 files changed, 48 insertions(+), 1 deletion(-)
create mode 100644 scripts/check-package-builds.mjs
diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml
index 97818689..6113b5e6 100644
--- a/.github/workflows/ci.yml
+++ b/.github/workflows/ci.yml
@@ -60,6 +60,9 @@ jobs:
- name: Install dependencies
run: npm ci
+ - name: Check build coverage
+ run: npm run check:builds
+
- name: Build packages
run: npm run build:packages
diff --git a/package.json b/package.json
index 2673463a..dd8f7fdd 100644
--- a/package.json
+++ b/package.json
@@ -39,7 +39,8 @@
"typecheck": "tsc --noEmit",
"typecheck:all": "npm run typecheck --workspaces --if-present",
"release": "npm run build:packages",
- "check:exports": "node scripts/check-package-exports.mjs"
+ "check:exports": "node scripts/check-package-exports.mjs",
+ "check:builds": "node scripts/check-package-builds.mjs"
},
"devDependencies": {
"@arethetypeswrong/cli": "^0.18.5",
diff --git a/scripts/check-package-builds.mjs b/scripts/check-package-builds.mjs
new file mode 100644
index 00000000..0a3022f7
--- /dev/null
+++ b/scripts/check-package-builds.mjs
@@ -0,0 +1,43 @@
+import { readFileSync, existsSync, readdirSync } from 'node:fs';
+import { join, dirname, resolve } from 'node:path';
+import { fileURLToPath } from 'node:url';
+
+const root = resolve(dirname(fileURLToPath(import.meta.url)), '..');
+const packagesDir = join(root, 'packages');
+
+const rootPkg = JSON.parse(readFileSync(join(root, 'package.json'), 'utf8'));
+const buildPackages = rootPkg.scripts?.['build:packages'] ?? '';
+
+const errors = [];
+const checked = [];
+
+for (const name of readdirSync(packagesDir)) {
+ const pkgDir = join(packagesDir, name);
+ const pkgJsonPath = join(pkgDir, 'package.json');
+ if (!existsSync(pkgJsonPath)) continue;
+
+ const pkg = JSON.parse(readFileSync(pkgJsonPath, 'utf8'));
+ if (pkg.private) continue;
+ if (!pkg.scripts?.build) continue;
+
+ const id = pkg.name ?? name;
+ checked.push(id);
+
+ // build:packages invokes each workspace via `npm run build -w `
+ if (!buildPackages.includes(`-w ${id}`) && !buildPackages.includes(`-w ${name}`)) {
+ errors.push(
+ `${id}: has a "build" script but is missing from root "build:packages". ` +
+ `CI lints every packages/*/ with publint, so its dist/ is never built on a fresh runner. ` +
+ `Add "npm run build -w ${id}" to "build:packages" in package.json.`,
+ );
+ }
+}
+
+if (errors.length) {
+ console.error('Package build coverage check failed:\n');
+ for (const e of errors) console.error(' - ' + e);
+ console.error('\nChecked: ' + checked.join(', '));
+ process.exit(1);
+}
+
+console.log(`Package build coverage check passed: build:packages covers all publishable packages (${checked.join(', ')}).`);
From 65fec2b1d1b7918adb2a22a8a77e6289ba783f5b Mon Sep 17 00:00:00 2001
From: Devarshi Shimpi
Date: Wed, 23 Sep 2026 10:05:43 +0530
Subject: [PATCH 12/16] fix: enhance Docker support and improve error handling
in services
---
apps/node/Dockerfile | 3 +++
apps/node/src/adapters/services.ts | 6 +++---
apps/node/src/api-deps.ts | 1 +
apps/node/src/index.ts | 4 ++--
docs/deployment/docker.md | 7 +++++--
packages/core/src/ports/git-provider.ts | 4 +++-
packages/db/src/client.ts | 2 +-
packages/node-adapters/src/redis-queue.ts | 2 +-
packages/node-adapters/tsconfig.json | 4 ++--
packages/ui/src/components/onboarding-card.tsx | 2 +-
10 files changed, 22 insertions(+), 13 deletions(-)
diff --git a/apps/node/Dockerfile b/apps/node/Dockerfile
index 537bfc19..420380b8 100644
--- a/apps/node/Dockerfile
+++ b/apps/node/Dockerfile
@@ -24,6 +24,9 @@ COPY packages ./packages
# Build the node server and its dependencies
RUN npm run build --workspace=@codraoss/node-server
+# Prune development dependencies before copying to runner stage
+RUN npm prune --omit=dev
+
# Build runner stage
FROM node:20-alpine AS runner
WORKDIR /app
diff --git a/apps/node/src/adapters/services.ts b/apps/node/src/adapters/services.ts
index 5b36b2ba..6579abd3 100644
--- a/apps/node/src/adapters/services.ts
+++ b/apps/node/src/adapters/services.ts
@@ -14,7 +14,7 @@ export function makeModelFactory(env: NodeAppBindings) {
return (jobId: string, tracker: TokenTracker): ReviewModel => new ModelRunner({
kv: env.APP_KV as any,
secretStore: {
- getSecret: async (key) => env[key as keyof NodeAppBindings] as string || process.env[key] || null,
+ getSecret: async (key) => (env[key as keyof NodeAppBindings] as string | undefined | null) ?? process.env[key] ?? null,
},
getConfig: (modelId) => getResolvedModelConfig({ HYPERDRIVE: env.DATABASE_CONFIG, APP_KV: env.APP_KV }, modelId),
aiBinding: undefined,
@@ -29,8 +29,8 @@ export function makeFormatterFactory(env: NodeAppBindings) {
export function makeGitHubClientFactory(env: NodeAppBindings): GitProviderFactory {
return {
- forInstallation(installationId: string): ReviewGitProvider {
- return new GitHubService(env, installationId);
+ forInstallation(installationId: string, tracker?: TokenTracker): ReviewGitProvider {
+ return new GitHubService(env, installationId, tracker);
},
};
}
diff --git a/apps/node/src/api-deps.ts b/apps/node/src/api-deps.ts
index 6007ca62..10d2c7d7 100644
--- a/apps/node/src/api-deps.ts
+++ b/apps/node/src/api-deps.ts
@@ -20,6 +20,7 @@ export function createNodeApiDeps(env: NodeAppBindings) {
logger.info(`[API Deps] Terminated job workflow for job ${job.id}`);
} catch (error) {
logger.error(`[API Deps] Failed to terminate job workflow for job ${job.id}: ${error}`);
+ throw error;
}
} else {
logger.warn(`[API Deps] QueueAdapter does not support deleteJob. Cannot terminate ${job.id}`);
diff --git a/apps/node/src/index.ts b/apps/node/src/index.ts
index d471cbe7..7eff93bf 100644
--- a/apps/node/src/index.ts
+++ b/apps/node/src/index.ts
@@ -1,4 +1,4 @@
-import * as dotenv from 'dotenv';
+import * as dotenv from 'dotenv';
import * as path from 'node:path';
dotenv.config({ path: path.resolve(process.cwd(), '../../.dev.vars') });
dotenv.config({ path: path.resolve(process.cwd(), '.dev.vars') });
@@ -25,7 +25,7 @@ const __dirname = dirname(__filename);
const redisUrl = process.env.REDIS_URL || 'redis://localhost:6379';
const redisClient = new Redis(redisUrl, {
maxRetriesPerRequest: null,
- tls: redisUrl.startsWith('rediss://') ? { rejectUnauthorized: false } : undefined, // Managed Redis
+ tls: redisUrl.startsWith('rediss://') ? { rejectUnauthorized: process.env.REDIS_INSECURE_TLS !== 'true' } : undefined, // Managed Redis
});
redisClient.on('error', (err) => {
logger.error('[Redis Error]', err);
diff --git a/docs/deployment/docker.md b/docs/deployment/docker.md
index edc0c922..33553a04 100644
--- a/docs/deployment/docker.md
+++ b/docs/deployment/docker.md
@@ -26,7 +26,7 @@ APP_URL=https://codra.yourdomain.com
ENVIRONMENT=production
# Database & Redis (these map to the docker-compose.yml service names)
-DATABASE_URL=postgres://postgres:password@postgres:5432/codra
+DATABASE_URL=postgres://postgres:codra_secure_default_pass@postgres:5432/codra
REDIS_URL=redis://redis:6379
# GitHub App Secrets
@@ -34,7 +34,10 @@ GITHUB_APP_ID=your_app_id
GITHUB_CLIENT_ID=your_client_id
GITHUB_CLIENT_SECRET=your_client_secret
GITHUB_APP_WEBHOOK_SECRET=your_webhook_secret
-APP_PRIVATE_KEY="-----BEGIN RSA PRIVATE KEY-----\n...\n-----END RSA PRIVATE KEY-----"
+# Note: For Docker Compose, you can preserve actual newlines in the private key without \n literals:
+APP_PRIVATE_KEY="-----BEGIN RSA PRIVATE KEY-----
+...
+-----END RSA PRIVATE KEY-----"
# Application Settings
AUTH_CALLBACK_URL=https://codra.yourdomain.com/api/auth/callback
diff --git a/packages/core/src/ports/git-provider.ts b/packages/core/src/ports/git-provider.ts
index 223b49ae..60343772 100644
--- a/packages/core/src/ports/git-provider.ts
+++ b/packages/core/src/ports/git-provider.ts
@@ -46,6 +46,8 @@ export interface ReviewGitProvider {
removeIssueLabelsIfPresent(owner: string, repo: string, prNumber: number, labels: string[]): Promise;
}
+import type { TokenTracker } from '../token-tracker';
+
export interface GitProviderFactory {
- forInstallation(installationId: string): ReviewGitProvider;
+ forInstallation(installationId: string, tracker?: TokenTracker): ReviewGitProvider;
}
diff --git a/packages/db/src/client.ts b/packages/db/src/client.ts
index c038f720..d6d1d697 100644
--- a/packages/db/src/client.ts
+++ b/packages/db/src/client.ts
@@ -92,7 +92,7 @@ async function withStaleConnectionRecovery(env: DbEnv, op: (db: DbClient) =>
try {
return await op(getDb(env));
} catch (error) {
- if (inScope || env.workerMode !== false || !isStaleConnectionError(error)) throw error;
+ if (env.workerMode === false || inScope || !isStaleConnectionError(error)) throw error;
const connectionString = env.HYPERDRIVE.connectionString;
fallbackClients.delete(connectionString);
diff --git a/packages/node-adapters/src/redis-queue.ts b/packages/node-adapters/src/redis-queue.ts
index 704ac38b..f9c8ec8a 100644
--- a/packages/node-adapters/src/redis-queue.ts
+++ b/packages/node-adapters/src/redis-queue.ts
@@ -10,7 +10,7 @@ export class RedisQueueAdapter implements QueueProducer {
jobOptions.delay = options.delaySeconds * 1000;
}
- await this.queue.add('review-job', message, jobOptions);
+ await this.queue.add('codra-reviews', message, jobOptions);
}
async deleteJob(jobId: string): Promise {
diff --git a/packages/node-adapters/tsconfig.json b/packages/node-adapters/tsconfig.json
index 6e673328..b857284e 100644
--- a/packages/node-adapters/tsconfig.json
+++ b/packages/node-adapters/tsconfig.json
@@ -5,9 +5,9 @@
"moduleResolution": "Bundler",
"types": ["node"],
"composite": false,
- "declaration": false,
+ "declaration": true,
"emitDeclarationOnly": false,
- "noEmit": true
+ "noEmit": false
},
"include": ["src/**/*"]
}
diff --git a/packages/ui/src/components/onboarding-card.tsx b/packages/ui/src/components/onboarding-card.tsx
index ef920e23..58f673c5 100644
--- a/packages/ui/src/components/onboarding-card.tsx
+++ b/packages/ui/src/components/onboarding-card.tsx
@@ -103,7 +103,7 @@ export function OnboardingCard({
>
- {step.label}
+ {step.label}
);
From 41ec19fd5fb0591053a2836d1a1e6fe35489a2b4 Mon Sep 17 00:00:00 2001
From: Devarshi Shimpi
Date: Wed, 23 Sep 2026 11:54:53 +0530
Subject: [PATCH 13/16] fix: update Dockerfile and docker-compose for improved
security and consistency
---
apps/node/Dockerfile | 4 ++--
apps/node/src/index.ts | 12 +++++++-----
docker-compose.yml | 4 ++--
packages/core/tsconfig.json | 11 -----------
packages/node-adapters/src/worker.ts | 3 +--
packages/ui/src/components/onboarding-card.tsx | 6 +++---
6 files changed, 15 insertions(+), 25 deletions(-)
diff --git a/apps/node/Dockerfile b/apps/node/Dockerfile
index 420380b8..e038d672 100644
--- a/apps/node/Dockerfile
+++ b/apps/node/Dockerfile
@@ -1,4 +1,4 @@
-FROM node:20-alpine AS builder
+FROM node:20-alpine3.24 AS builder
WORKDIR /app
# Install build dependencies if needed
@@ -28,7 +28,7 @@ RUN npm run build --workspace=@codraoss/node-server
RUN npm prune --omit=dev
# Build runner stage
-FROM node:20-alpine AS runner
+FROM node:20-alpine3.24 AS runner
WORKDIR /app
ENV NODE_ENV=production
diff --git a/apps/node/src/index.ts b/apps/node/src/index.ts
index 7eff93bf..9d6b8078 100644
--- a/apps/node/src/index.ts
+++ b/apps/node/src/index.ts
@@ -85,10 +85,13 @@ if (process.env.START_API !== 'false') {
if (server) {
- const originalClose = server.close;
- server.close = () => originalClose(() => {
- logger.info('HTTP server closed.');
- }) as any;
+ const originalClose = server.close.bind(server);
+ server.close = function(callback?: (err?: Error) => void) {
+ return originalClose((err?: Error) => {
+ logger.info('HTTP server closed.');
+ if (callback) callback(err);
+ });
+ } as typeof server.close;
}
}
@@ -112,7 +115,6 @@ const shutdown = async () => {
// Postgres client manages its own pool.
logger.info('All services stopped. Exiting.');
- process.exit(0);
};
process.on('SIGTERM', shutdown);
diff --git a/docker-compose.yml b/docker-compose.yml
index 27292d61..0a9de3b7 100644
--- a/docker-compose.yml
+++ b/docker-compose.yml
@@ -5,7 +5,7 @@ services:
image: postgres:15-alpine
environment:
POSTGRES_USER: postgres
- POSTGRES_PASSWORD: ${POSTGRES_PASSWORD:-codra_secure_default_pass}
+ POSTGRES_PASSWORD: ${POSTGRES_PASSWORD:-INSECURE_DEFAULT_CHANGE_ME_IN_PROD}
POSTGRES_DB: codra
ports:
- "5432:5432"
@@ -36,7 +36,7 @@ services:
ports:
- "3000:3000"
environment:
- - DATABASE_URL=postgres://postgres:${POSTGRES_PASSWORD:-codra_secure_default_pass}@postgres:5432/codra
+ - DATABASE_URL=postgres://postgres:${POSTGRES_PASSWORD:-INSECURE_DEFAULT_CHANGE_ME_IN_PROD}@postgres:5432/codra
- REDIS_URL=redis://redis:6379
- START_WORKER=true
- PORT=3000
diff --git a/packages/core/tsconfig.json b/packages/core/tsconfig.json
index afff666a..05ae1d08 100644
--- a/packages/core/tsconfig.json
+++ b/packages/core/tsconfig.json
@@ -1,19 +1,8 @@
{
"extends": "../../tsconfig.base.json",
"compilerOptions": {
- // The base sets ES2024 only. The engine reaches for AbortController/AbortSignal (timeout.ts),
- // crypto.subtle + TextEncoder (verify.ts), console (logger.ts) and fetch types -- all of which
- // live in the DOM lib. Deliberately NOT @cloudflare/workers-types: KVNamespace must never
- // resolve inside this package, which is what forces the KvStore port to exist.
"lib": ["ES2024", "DOM"],
"types": ["node"],
-
- // No emit, and therefore no project reference to ../schema. Packages here have no build step:
- // @codraoss/schema is consumed as raw TS source through its `exports` map, exactly as the root
- // program consumes it. Keeping the base's composite/declaration settings would instead demand
- // that schema be built to dist/ first (TS6305) -- a build nothing in this repo performs.
- // This project exists to typecheck the package against a NARROWER lib/types than the root
- // program, which is what catches a stray KVNamespace or hono import.
"composite": false,
"declaration": false,
"emitDeclarationOnly": false,
diff --git a/packages/node-adapters/src/worker.ts b/packages/node-adapters/src/worker.ts
index 6c5789e4..9c55d1c1 100644
--- a/packages/node-adapters/src/worker.ts
+++ b/packages/node-adapters/src/worker.ts
@@ -20,8 +20,7 @@ export function startWorker(
}
const reviewRuntime = createRuntime();
- // Need to cast to any since DbEnv is dynamically merged downstream
- const orchestrator = new NodeOrchestrator(reviewRuntime as any, queue);
+ const orchestrator = new NodeOrchestrator(reviewRuntime, queue);
await orchestrator.startReviewJob(job.id ?? 'unknown', parseResult.data);
},
{ connection: redisConnection }
diff --git a/packages/ui/src/components/onboarding-card.tsx b/packages/ui/src/components/onboarding-card.tsx
index 58f673c5..41d6c1a7 100644
--- a/packages/ui/src/components/onboarding-card.tsx
+++ b/packages/ui/src/components/onboarding-card.tsx
@@ -63,7 +63,7 @@ export function OnboardingCard({
@@ -85,7 +85,7 @@ export function OnboardingCard({
{steps.map((step) => {
const content = (
Date: Wed, 23 Sep 2026 14:43:11 +0530
Subject: [PATCH 14/16] fix: update paths and error handling in node services
for improved stability
---
apps/node/src/index.ts | 4 ++--
packages/db/src/client.ts | 2 +-
packages/node-adapters/src/node-orchestrator.ts | 2 +-
packages/node-adapters/src/redis-queue.ts | 2 +-
scripts/check-package-builds.mjs | 3 ++-
5 files changed, 7 insertions(+), 6 deletions(-)
diff --git a/apps/node/src/index.ts b/apps/node/src/index.ts
index 9d6b8078..b4221ea1 100644
--- a/apps/node/src/index.ts
+++ b/apps/node/src/index.ts
@@ -51,7 +51,7 @@ app.onError((err, c) => {
});
-const distClientPath = path.resolve(__dirname, process.cwd().endsWith('node/dist') ? '../../dist/client' : '../dist/client');
+const distClientPath = path.resolve(__dirname, '../../../dist/client');
app.use('/assets/*', serveStatic({ root: distClientPath }));
app.use('/*.svg', serveStatic({ root: distClientPath }));
app.use('/*.ico', serveStatic({ root: distClientPath }));
@@ -75,7 +75,7 @@ if (process.env.START_API !== 'false') {
deps: createNodeApiDeps(env),
};
- try { return await runWithDb({ ...env, HYPERDRIVE: env.DATABASE_CONFIG }, () => app.fetch(request, apiEnv as any)); } catch (e) { console.error('SERVE ERROR:', e); throw e; }
+ try { return await runWithDb({ ...env, HYPERDRIVE: env.DATABASE_CONFIG }, () => app.fetch(request, apiEnv as any)); } catch (e) { console.error('SERVE ERROR:', e); return new Response('Internal Server Error', { status: 500 }); }
},
port,
hostname: '0.0.0.0',
diff --git a/packages/db/src/client.ts b/packages/db/src/client.ts
index d6d1d697..73fc8172 100644
--- a/packages/db/src/client.ts
+++ b/packages/db/src/client.ts
@@ -99,7 +99,7 @@ async function withStaleConnectionRecovery(env: DbEnv, op: (db: DbClient) =>
const fresh = createDbClient(env);
fallbackClients.set(connectionString, fresh);
- return await op(fresh);
+ return op(fresh);
}
}
diff --git a/packages/node-adapters/src/node-orchestrator.ts b/packages/node-adapters/src/node-orchestrator.ts
index 28c1080a..43529ee7 100644
--- a/packages/node-adapters/src/node-orchestrator.ts
+++ b/packages/node-adapters/src/node-orchestrator.ts
@@ -12,7 +12,7 @@ export class NodeOrchestrator implements JobOrchestrator {
async startReviewJob(id: string, params: ReviewJobMessage): Promise {
return runWithDb(this.env, async () => {
- const currentParams = { ...params };
+ const currentParams = { jobId: id, ...params };
currentParams.phase = currentParams.phase ?? 'prepare';
const result = await runReview(this.env, currentParams);
diff --git a/packages/node-adapters/src/redis-queue.ts b/packages/node-adapters/src/redis-queue.ts
index f9c8ec8a..a711d701 100644
--- a/packages/node-adapters/src/redis-queue.ts
+++ b/packages/node-adapters/src/redis-queue.ts
@@ -10,7 +10,7 @@ export class RedisQueueAdapter implements QueueProducer {
jobOptions.delay = options.delaySeconds * 1000;
}
- await this.queue.add('codra-reviews', message, jobOptions);
+ await this.queue.add(this.queue.name, message, jobOptions);
}
async deleteJob(jobId: string): Promise {
diff --git a/scripts/check-package-builds.mjs b/scripts/check-package-builds.mjs
index 0a3022f7..7f968ef2 100644
--- a/scripts/check-package-builds.mjs
+++ b/scripts/check-package-builds.mjs
@@ -24,7 +24,8 @@ for (const name of readdirSync(packagesDir)) {
checked.push(id);
// build:packages invokes each workspace via `npm run build -w `
- if (!buildPackages.includes(`-w ${id}`) && !buildPackages.includes(`-w ${name}`)) {
+ const isCovered = new RegExp(`-w\\s+${id}(?:\\s|$)`).test(buildPackages) || new RegExp(`-w\\s+${name}(?:\\s|$)`).test(buildPackages);
+ if (!isCovered) {
errors.push(
`${id}: has a "build" script but is missing from root "build:packages". ` +
`CI lints every packages/*/ with publint, so its dist/ is never built on a fresh runner. ` +
From fd7b6317cc7ccc698e4e4d297c6bce6ed8324b3d Mon Sep 17 00:00:00 2001
From: Devarshi Shimpi
Date: Wed, 23 Sep 2026 14:51:07 +0530
Subject: [PATCH 15/16] fix: update createRuntime type to include DbEnv for
improved type safety
---
packages/node-adapters/src/worker.ts | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/packages/node-adapters/src/worker.ts b/packages/node-adapters/src/worker.ts
index 9c55d1c1..8327c9b6 100644
--- a/packages/node-adapters/src/worker.ts
+++ b/packages/node-adapters/src/worker.ts
@@ -2,12 +2,13 @@ import { Worker, type Job } from 'bullmq';
import { reviewJobMessageSchema, type ReviewJobMessage } from '@codraoss/schema';
import { NodeOrchestrator } from './node-orchestrator';
import type { ReviewRuntime, QueueProducer } from '@codraoss/core/ports';
+import type { DbEnv } from '@codraoss/db/env';
import type Redis from 'ioredis';
export function startWorker(
redisConnection: Redis,
queue: QueueProducer,
- createRuntime: () => ReviewRuntime,
+ createRuntime: () => ReviewRuntime & DbEnv,
logger: { info: (msg: string) => void, error: (msg: string, err?: any) => void }
): Worker {
const worker = new Worker(
From 599b87012ba0d32238bf2854949886e2ac9bce38 Mon Sep 17 00:00:00 2001
From: Devarshi Shimpi
Date: Wed, 23 Sep 2026 15:32:42 +0530
Subject: [PATCH 16/16] fix: update tsconfig to ensure correct rootDir and
outDir settings
---
packages/node-adapters/tsconfig.json | 4 +++-
1 file changed, 3 insertions(+), 1 deletion(-)
diff --git a/packages/node-adapters/tsconfig.json b/packages/node-adapters/tsconfig.json
index b857284e..a4131722 100644
--- a/packages/node-adapters/tsconfig.json
+++ b/packages/node-adapters/tsconfig.json
@@ -7,7 +7,9 @@
"composite": false,
"declaration": true,
"emitDeclarationOnly": false,
- "noEmit": false
+ "noEmit": false,
+ "rootDir": "src",
+ "outDir": "dist"
},
"include": ["src/**/*"]
}