convex-devtools 1.1.0 → 1.1.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -154,7 +154,7 @@ The export format is a simple JSON structure:
154
154
 
155
155
  ```json
156
156
  {
157
- "version": "1.1.0",
157
+ "version": "1.1.1",
158
158
  "exportedAt": "2025-01-29T10:00:00.000Z",
159
159
  "collections": [
160
160
  {
@@ -146,10 +146,17 @@ async function createServer(config) {
146
146
  "devtools.ts"
147
147
  );
148
148
  const devtoolsModuleTemplate = `import { v } from "convex/values";
149
- import { query } from "./_generated/server";
149
+ import { mutation, query } from "./_generated/server";
150
+
151
+ const DEVTOOLS_HELPER_VERSION = 2;
150
152
 
151
153
  type FilterOp = "eq" | "neq" | "gt" | "gte" | "lt" | "lte";
152
154
 
155
+ const stripSystemFields = (data: Record<string, unknown>) => {
156
+ const { _id, _creationTime, ...rest } = data;
157
+ return rest;
158
+ };
159
+
153
160
  export const runQuery = query({
154
161
  args: {
155
162
  table: v.string(),
@@ -220,10 +227,61 @@ export const runQuery = query({
220
227
  return await ordered.collect();
221
228
  },
222
229
  });
230
+
231
+ export const runInsert = mutation({
232
+ args: {
233
+ table: v.string(),
234
+ data: v.any(),
235
+ },
236
+ handler: async (ctx, args) => {
237
+ if (!args.data || typeof args.data !== "object" || Array.isArray(args.data)) {
238
+ throw new Error("Insert data must be an object");
239
+ }
240
+ const clean = stripSystemFields(args.data as Record<string, unknown>);
241
+ return await ctx.db.insert(args.table as any, clean as any);
242
+ },
243
+ });
244
+
245
+ export const runUpdate = mutation({
246
+ args: {
247
+ id: v.string(),
248
+ data: v.any(),
249
+ },
250
+ handler: async (ctx, args) => {
251
+ if (!args.data || typeof args.data !== "object" || Array.isArray(args.data)) {
252
+ throw new Error("Update data must be an object");
253
+ }
254
+ const clean = stripSystemFields(args.data as Record<string, unknown>);
255
+ await ctx.db.patch(args.id as any, clean as any);
256
+ return args.id;
257
+ },
258
+ });
223
259
  `;
260
+ const getDevtoolsHelperStatus = () => {
261
+ const installed = fs2.existsSync(devtoolsModulePath);
262
+ if (!installed) {
263
+ return {
264
+ installed: false,
265
+ supportsWrites: false,
266
+ version: null
267
+ };
268
+ }
269
+ try {
270
+ const content = fs2.readFileSync(devtoolsModulePath, "utf-8");
271
+ const supportsWrites = content.includes("runInsert") && content.includes("runUpdate");
272
+ const versionMatch = content.match(
273
+ /DEVTOOLS_HELPER_VERSION\\s*=\\s*(\\d+)/
274
+ );
275
+ const version = versionMatch ? Number(versionMatch[1]) : null;
276
+ return { installed: true, supportsWrites, version };
277
+ } catch {
278
+ return { installed: true, supportsWrites: false, version: null };
279
+ }
280
+ };
224
281
  app.get("/api/devtools/status", (_req, res) => {
282
+ const status = getDevtoolsHelperStatus();
225
283
  res.json({
226
- installed: fs2.existsSync(devtoolsModulePath),
284
+ ...status,
227
285
  path: devtoolsModulePath
228
286
  });
229
287
  });
@@ -242,8 +300,19 @@ export const runQuery = query({
242
300
  });
243
301
  }
244
302
  });
303
+ app.post("/api/devtools/helper/update", (_req, res) => {
304
+ try {
305
+ fs2.writeFileSync(devtoolsModulePath, devtoolsModuleTemplate, "utf-8");
306
+ res.json({ installed: true, updated: true });
307
+ } catch (error) {
308
+ res.status(500).json({
309
+ installed: false,
310
+ error: error?.message || "Failed to write devtools module"
311
+ });
312
+ }
313
+ });
245
314
  app.post("/api/devtools/query", async (req, res) => {
246
- const { table, filters, order, limit, pagination, jwtToken } = req.body || {};
315
+ const { table, filters, order, limit, pagination } = req.body || {};
247
316
  if (!table) {
248
317
  res.status(400).json({
249
318
  error: "Missing table",
@@ -267,18 +336,13 @@ export const runQuery = query({
267
336
  }
268
337
  try {
269
338
  const startTime = Date.now();
270
- const result = await convexClient.invoke(
271
- "devtools:runQuery",
272
- "query",
273
- {
274
- table,
275
- filters,
276
- order,
277
- limit,
278
- pagination
279
- },
280
- { jwtToken }
281
- );
339
+ const result = await convexClient.invoke("devtools:runQuery", "query", {
340
+ table,
341
+ filters,
342
+ order,
343
+ limit,
344
+ pagination
345
+ });
282
346
  const duration = Date.now() - startTime;
283
347
  let payload = result;
284
348
  if (payload && typeof payload === "object" && "status" in payload && payload.status === "success" && "value" in payload) {
@@ -310,6 +374,118 @@ export const runQuery = query({
310
374
  });
311
375
  }
312
376
  });
377
+ app.post("/api/devtools/insert", async (req, res) => {
378
+ const { table, data } = req.body || {};
379
+ if (!table) {
380
+ res.status(400).json({
381
+ error: "Missing table",
382
+ timestamp: (/* @__PURE__ */ new Date()).toISOString()
383
+ });
384
+ return;
385
+ }
386
+ if (!config.deployKey) {
387
+ res.status(403).json({
388
+ error: "CONVEX_DEPLOY_KEY is required to run devtools mutations. Set it in .env.local and restart DevTools.",
389
+ timestamp: (/* @__PURE__ */ new Date()).toISOString()
390
+ });
391
+ return;
392
+ }
393
+ const status = getDevtoolsHelperStatus();
394
+ if (!status.installed) {
395
+ res.status(428).json({
396
+ error: "Devtools write helper is not installed. Install it from the UI first.",
397
+ timestamp: (/* @__PURE__ */ new Date()).toISOString()
398
+ });
399
+ return;
400
+ }
401
+ if (!status.supportsWrites) {
402
+ res.status(428).json({
403
+ error: "Devtools helper needs an update to enable writes. Update it from the UI.",
404
+ timestamp: (/* @__PURE__ */ new Date()).toISOString()
405
+ });
406
+ return;
407
+ }
408
+ try {
409
+ const startTime = Date.now();
410
+ const result = await convexClient.invoke("devtools:runInsert", "mutation", {
411
+ table,
412
+ data
413
+ });
414
+ const duration = Date.now() - startTime;
415
+ res.json({
416
+ success: true,
417
+ result,
418
+ duration,
419
+ timestamp: (/* @__PURE__ */ new Date()).toISOString()
420
+ });
421
+ } catch (error) {
422
+ res.json({
423
+ success: false,
424
+ error: {
425
+ message: error.message,
426
+ code: error.code,
427
+ data: error.data
428
+ },
429
+ timestamp: (/* @__PURE__ */ new Date()).toISOString()
430
+ });
431
+ }
432
+ });
433
+ app.post("/api/devtools/update", async (req, res) => {
434
+ const { id, data } = req.body || {};
435
+ if (!id) {
436
+ res.status(400).json({
437
+ error: "Missing id",
438
+ timestamp: (/* @__PURE__ */ new Date()).toISOString()
439
+ });
440
+ return;
441
+ }
442
+ if (!config.deployKey) {
443
+ res.status(403).json({
444
+ error: "CONVEX_DEPLOY_KEY is required to run devtools mutations. Set it in .env.local and restart DevTools.",
445
+ timestamp: (/* @__PURE__ */ new Date()).toISOString()
446
+ });
447
+ return;
448
+ }
449
+ const status = getDevtoolsHelperStatus();
450
+ if (!status.installed) {
451
+ res.status(428).json({
452
+ error: "Devtools write helper is not installed. Install it from the UI first.",
453
+ timestamp: (/* @__PURE__ */ new Date()).toISOString()
454
+ });
455
+ return;
456
+ }
457
+ if (!status.supportsWrites) {
458
+ res.status(428).json({
459
+ error: "Devtools helper needs an update to enable writes. Update it from the UI.",
460
+ timestamp: (/* @__PURE__ */ new Date()).toISOString()
461
+ });
462
+ return;
463
+ }
464
+ try {
465
+ const startTime = Date.now();
466
+ const result = await convexClient.invoke("devtools:runUpdate", "mutation", {
467
+ id,
468
+ data
469
+ });
470
+ const duration = Date.now() - startTime;
471
+ res.json({
472
+ success: true,
473
+ result,
474
+ duration,
475
+ timestamp: (/* @__PURE__ */ new Date()).toISOString()
476
+ });
477
+ } catch (error) {
478
+ res.json({
479
+ success: false,
480
+ error: {
481
+ message: error.message,
482
+ code: error.code,
483
+ data: error.data
484
+ },
485
+ timestamp: (/* @__PURE__ */ new Date()).toISOString()
486
+ });
487
+ }
488
+ });
313
489
  app.post("/api/invoke", async (req, res) => {
314
490
  const { functionPath, functionType, args, jwtToken } = req.body;
315
491
  if (!functionPath || !functionType) {
@@ -377,4 +553,4 @@ export const runQuery = query({
377
553
  export {
378
554
  createServer
379
555
  };
380
- //# sourceMappingURL=chunk-C34UOOQW.js.map
556
+ //# sourceMappingURL=chunk-V3TQXD75.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../src/server/index.ts","../../src/server/persistence-db.ts"],"sourcesContent":["import cors from 'cors';\nimport express from 'express';\nimport fs from 'fs';\nimport http from 'http';\nimport path from 'path';\nimport { fileURLToPath } from 'url';\nimport { WebSocket, WebSocketServer } from 'ws';\nimport { ConvexClient } from './convex-client.js';\nimport { PersistenceDb } from './persistence-db.js';\nimport { SchemaWatcher } from './schema-watcher.js';\n\nconst __dirname = path.dirname(fileURLToPath(import.meta.url));\n\nexport interface ServerConfig {\n port: number;\n projectDir: string;\n convexUrl: string;\n deployKey: string;\n schemaWatcher: SchemaWatcher;\n persistencePath?: string;\n}\n\nexport async function createServer(config: ServerConfig): Promise<http.Server> {\n const app = express();\n\n app.use(cors());\n app.use(express.json({ limit: '10mb' }));\n\n // Serve static UI files in production\n const uiPath = path.join(__dirname, '..', 'ui');\n app.use(express.static(uiPath));\n\n // Create Convex client\n const convexClient = new ConvexClient(config.convexUrl, config.deployKey);\n\n // Shared persistence database (collections/history)\n const persistenceDb = await PersistenceDb.create(\n config.persistencePath ??\n path.join(config.projectDir, '.convex-devtools', 'devtools.sqlite')\n );\n\n // API Routes\n app.get('/api/schema', (_req, res) => {\n const schema = config.schemaWatcher.getSchema();\n if (!schema) {\n res.status(503).json({ error: 'Schema not yet loaded' });\n return;\n }\n res.json(schema);\n });\n\n app.get('/api/health', (_req, res) => {\n res.json({\n status: 'ok',\n convexUrl: config.convexUrl,\n projectDir: config.projectDir,\n projectName: path.basename(config.projectDir),\n });\n });\n\n app.get('/api/persistence', (_req, res) => {\n res.json(persistenceDb.getData());\n });\n\n app.put('/api/persistence', (req, res) => {\n const { collections, history, dataHistory } = req.body || {};\n persistenceDb.setData({\n collections: Array.isArray(collections) ? collections : [],\n history: Array.isArray(history) ? history : [],\n dataHistory: Array.isArray(dataHistory) ? dataHistory : [],\n });\n res.json({ success: true });\n });\n\n const devtoolsModulePath = path.join(\n config.projectDir,\n 'convex',\n 'devtools.ts'\n );\n\n const devtoolsModuleTemplate = `import { v } from \"convex/values\";\nimport { mutation, query } from \"./_generated/server\";\n\nconst DEVTOOLS_HELPER_VERSION = 2;\n\ntype FilterOp = \"eq\" | \"neq\" | \"gt\" | \"gte\" | \"lt\" | \"lte\";\n\nconst stripSystemFields = (data: Record<string, unknown>) => {\n const { _id, _creationTime, ...rest } = data;\n return rest;\n};\n\nexport const runQuery = query({\n args: {\n table: v.string(),\n filters: v.optional(\n v.array(\n v.object({\n field: v.string(),\n op: v.string(),\n value: v.any(),\n })\n )\n ),\n order: v.optional(v.union(v.literal(\"asc\"), v.literal(\"desc\"))),\n limit: v.optional(v.number()),\n pagination: v.optional(\n v.object({\n cursor: v.union(v.string(), v.null()),\n numItems: v.number(),\n })\n ),\n },\n handler: async (ctx, args) => {\n let q = ctx.db.query(args.table as any);\n\n if (args.filters && args.filters.length > 0) {\n q = q.filter((qb) => {\n const expressions = args.filters!.map((filter) => {\n const field = qb.field(filter.field);\n switch (filter.op as FilterOp) {\n case \"eq\":\n return qb.eq(field, filter.value);\n case \"neq\":\n return qb.neq(field, filter.value);\n case \"gt\":\n return qb.gt(field, filter.value);\n case \"gte\":\n return qb.gte(field, filter.value);\n case \"lt\":\n return qb.lt(field, filter.value);\n case \"lte\":\n return qb.lte(field, filter.value);\n default:\n throw new Error(\\`Unsupported filter op: \\${filter.op}\\`);\n }\n });\n\n if (expressions.length === 1) {\n return expressions[0];\n }\n\n return qb.and(...expressions);\n });\n }\n\n const ordered = args.order ? q.order(args.order) : q;\n\n if (args.pagination) {\n return await ordered.paginate({\n cursor: args.pagination.cursor,\n numItems: args.pagination.numItems,\n });\n }\n\n if (args.limit !== undefined) {\n return await ordered.take(args.limit);\n }\n\n return await ordered.collect();\n },\n});\n\nexport const runInsert = mutation({\n args: {\n table: v.string(),\n data: v.any(),\n },\n handler: async (ctx, args) => {\n if (!args.data || typeof args.data !== \"object\" || Array.isArray(args.data)) {\n throw new Error(\"Insert data must be an object\");\n }\n const clean = stripSystemFields(args.data as Record<string, unknown>);\n return await ctx.db.insert(args.table as any, clean as any);\n },\n});\n\nexport const runUpdate = mutation({\n args: {\n id: v.string(),\n data: v.any(),\n },\n handler: async (ctx, args) => {\n if (!args.data || typeof args.data !== \"object\" || Array.isArray(args.data)) {\n throw new Error(\"Update data must be an object\");\n }\n const clean = stripSystemFields(args.data as Record<string, unknown>);\n await ctx.db.patch(args.id as any, clean as any);\n return args.id;\n },\n});\n`;\n\n const getDevtoolsHelperStatus = () => {\n const installed = fs.existsSync(devtoolsModulePath);\n if (!installed) {\n return {\n installed: false,\n supportsWrites: false,\n version: null as number | null,\n };\n }\n try {\n const content = fs.readFileSync(devtoolsModulePath, 'utf-8');\n const supportsWrites =\n content.includes('runInsert') && content.includes('runUpdate');\n const versionMatch = content.match(\n /DEVTOOLS_HELPER_VERSION\\\\s*=\\\\s*(\\\\d+)/\n );\n const version = versionMatch ? Number(versionMatch[1]) : null;\n return { installed: true, supportsWrites, version };\n } catch {\n return { installed: true, supportsWrites: false, version: null };\n }\n };\n\n app.get('/api/devtools/status', (_req, res) => {\n const status = getDevtoolsHelperStatus();\n res.json({\n ...status,\n path: devtoolsModulePath,\n });\n });\n\n app.post('/api/devtools/install', (_req, res) => {\n if (fs.existsSync(devtoolsModulePath)) {\n res.json({ installed: true, alreadyExisted: true });\n return;\n }\n\n try {\n fs.writeFileSync(devtoolsModulePath, devtoolsModuleTemplate, 'utf-8');\n res.json({ installed: true, created: true });\n } catch (error: any) {\n res.status(500).json({\n installed: false,\n error: error?.message || 'Failed to write devtools module',\n });\n }\n });\n\n app.post('/api/devtools/helper/update', (_req, res) => {\n try {\n fs.writeFileSync(devtoolsModulePath, devtoolsModuleTemplate, 'utf-8');\n res.json({ installed: true, updated: true });\n } catch (error: any) {\n res.status(500).json({\n installed: false,\n error: error?.message || 'Failed to write devtools module',\n });\n }\n });\n\n app.post('/api/devtools/query', async (req, res) => {\n const { table, filters, order, limit, pagination } = req.body || {};\n\n if (!table) {\n res.status(400).json({\n error: 'Missing table',\n timestamp: new Date().toISOString(),\n });\n return;\n }\n\n if (!config.deployKey) {\n res.status(403).json({\n error:\n 'CONVEX_DEPLOY_KEY is required to run devtools queries. Set it in .env.local and restart DevTools.',\n timestamp: new Date().toISOString(),\n });\n return;\n }\n\n if (!fs.existsSync(devtoolsModulePath)) {\n res.status(428).json({\n error:\n 'Devtools query helper is not installed. Install it from the UI first.',\n timestamp: new Date().toISOString(),\n });\n return;\n }\n\n try {\n const startTime = Date.now();\n const result = await convexClient.invoke('devtools:runQuery', 'query', {\n table,\n filters,\n order,\n limit,\n pagination,\n });\n const duration = Date.now() - startTime;\n\n let payload: unknown = result;\n\n if (\n payload &&\n typeof payload === 'object' &&\n 'status' in (payload as Record<string, unknown>) &&\n (payload as { status?: string }).status === 'success' &&\n 'value' in (payload as Record<string, unknown>)\n ) {\n payload = (payload as { value?: unknown }).value;\n }\n\n let pageInfo =\n payload &&\n typeof payload === 'object' &&\n 'pageInfo' in (payload as Record<string, unknown>)\n ? (payload as { pageInfo?: unknown }).pageInfo\n : undefined;\n\n if (\n !pageInfo &&\n payload &&\n typeof payload === 'object' &&\n 'continueCursor' in (payload as Record<string, unknown>)\n ) {\n const cursor = (payload as { continueCursor?: string | null })\n .continueCursor ?? null;\n const isDone = !!(payload as { isDone?: boolean }).isDone;\n pageInfo = { cursor, hasNextPage: !isDone };\n }\n\n const data =\n payload &&\n typeof payload === 'object' &&\n 'page' in (payload as Record<string, unknown>)\n ? (payload as { page?: unknown }).page\n : payload;\n\n res.json({\n success: true,\n result: data,\n pageInfo,\n duration,\n timestamp: new Date().toISOString(),\n });\n } catch (error: any) {\n res.json({\n success: false,\n error: {\n message: error.message,\n code: error.code,\n data: error.data,\n },\n timestamp: new Date().toISOString(),\n });\n }\n });\n\n app.post('/api/devtools/insert', async (req, res) => {\n const { table, data } = req.body || {};\n\n if (!table) {\n res.status(400).json({\n error: 'Missing table',\n timestamp: new Date().toISOString(),\n });\n return;\n }\n\n if (!config.deployKey) {\n res.status(403).json({\n error:\n 'CONVEX_DEPLOY_KEY is required to run devtools mutations. Set it in .env.local and restart DevTools.',\n timestamp: new Date().toISOString(),\n });\n return;\n }\n\n const status = getDevtoolsHelperStatus();\n if (!status.installed) {\n res.status(428).json({\n error:\n 'Devtools write helper is not installed. Install it from the UI first.',\n timestamp: new Date().toISOString(),\n });\n return;\n }\n\n if (!status.supportsWrites) {\n res.status(428).json({\n error:\n 'Devtools helper needs an update to enable writes. Update it from the UI.',\n timestamp: new Date().toISOString(),\n });\n return;\n }\n\n try {\n const startTime = Date.now();\n const result = await convexClient.invoke('devtools:runInsert', 'mutation', {\n table,\n data,\n });\n const duration = Date.now() - startTime;\n res.json({\n success: true,\n result,\n duration,\n timestamp: new Date().toISOString(),\n });\n } catch (error: any) {\n res.json({\n success: false,\n error: {\n message: error.message,\n code: error.code,\n data: error.data,\n },\n timestamp: new Date().toISOString(),\n });\n }\n });\n\n app.post('/api/devtools/update', async (req, res) => {\n const { id, data } = req.body || {};\n\n if (!id) {\n res.status(400).json({\n error: 'Missing id',\n timestamp: new Date().toISOString(),\n });\n return;\n }\n\n if (!config.deployKey) {\n res.status(403).json({\n error:\n 'CONVEX_DEPLOY_KEY is required to run devtools mutations. Set it in .env.local and restart DevTools.',\n timestamp: new Date().toISOString(),\n });\n return;\n }\n\n const status = getDevtoolsHelperStatus();\n if (!status.installed) {\n res.status(428).json({\n error:\n 'Devtools write helper is not installed. Install it from the UI first.',\n timestamp: new Date().toISOString(),\n });\n return;\n }\n\n if (!status.supportsWrites) {\n res.status(428).json({\n error:\n 'Devtools helper needs an update to enable writes. Update it from the UI.',\n timestamp: new Date().toISOString(),\n });\n return;\n }\n\n try {\n const startTime = Date.now();\n const result = await convexClient.invoke('devtools:runUpdate', 'mutation', {\n id,\n data,\n });\n const duration = Date.now() - startTime;\n res.json({\n success: true,\n result,\n duration,\n timestamp: new Date().toISOString(),\n });\n } catch (error: any) {\n res.json({\n success: false,\n error: {\n message: error.message,\n code: error.code,\n data: error.data,\n },\n timestamp: new Date().toISOString(),\n });\n }\n });\n\n // Invoke a function\n app.post('/api/invoke', async (req, res) => {\n const { functionPath, functionType, args, jwtToken } = req.body;\n\n if (!functionPath || !functionType) {\n res.status(400).json({ error: 'Missing functionPath or functionType' });\n return;\n }\n\n try {\n const startTime = Date.now();\n const result = await convexClient.invoke(\n functionPath,\n functionType,\n args || {},\n { jwtToken }\n );\n const duration = Date.now() - startTime;\n\n res.json({\n success: true,\n result,\n duration,\n timestamp: new Date().toISOString(),\n });\n } catch (error: any) {\n res.json({\n success: false,\n error: {\n message: error.message,\n code: error.code,\n data: error.data,\n },\n timestamp: new Date().toISOString(),\n });\n }\n });\n\n // Create HTTP server\n const server = http.createServer(app);\n\n // WebSocket for real-time schema updates\n const wss = new WebSocketServer({ server, path: '/ws' });\n\n const clients = new Set<WebSocket>();\n\n wss.on('connection', (ws) => {\n clients.add(ws);\n\n // Send initial schema\n const schema = config.schemaWatcher.getSchema();\n if (schema) {\n ws.send(JSON.stringify({ type: 'schema', data: schema }));\n }\n\n ws.on('close', () => {\n clients.delete(ws);\n });\n });\n\n // Broadcast schema updates\n config.schemaWatcher.on('schema-updated', (schema) => {\n const message = JSON.stringify({ type: 'schema', data: schema });\n for (const client of clients) {\n if (client.readyState === WebSocket.OPEN) {\n client.send(message);\n }\n }\n });\n\n // SPA fallback - serve index.html for non-API routes\n app.get('*', (_req, res) => {\n res.sendFile(path.join(uiPath, 'index.html'));\n });\n\n return new Promise((resolve) => {\n server.listen(config.port, () => {\n resolve(server);\n });\n });\n}\n","import fs from 'fs';\nimport { createRequire } from 'module';\nimport path from 'path';\nimport initSqlJs, { Database, SqlJsStatic } from 'sql.js';\n\nexport interface PersistenceData {\n collections: unknown[];\n history: unknown[];\n dataHistory: unknown[];\n}\n\nconst DEFAULT_DATA: PersistenceData = {\n collections: [],\n history: [],\n dataHistory: [],\n};\n\nexport class PersistenceDb {\n private db: Database;\n private dbFilePath: string;\n private SQL: SqlJsStatic;\n\n private constructor(db: Database, dbFilePath: string, SQL: SqlJsStatic) {\n this.db = db;\n this.dbFilePath = dbFilePath;\n this.SQL = SQL;\n this.db.exec(\n 'CREATE TABLE IF NOT EXISTS kv (key TEXT PRIMARY KEY, value TEXT NOT NULL, updated_at TEXT NOT NULL)'\n );\n }\n\n static async create(dbFilePath: string): Promise<PersistenceDb> {\n const dir = path.dirname(dbFilePath);\n if (!fs.existsSync(dir)) {\n fs.mkdirSync(dir, { recursive: true });\n }\n\n const require = createRequire(import.meta.url);\n const wasmPath = require.resolve('sql.js/dist/sql-wasm.wasm');\n\n const SQL: SqlJsStatic = await initSqlJs({\n locateFile: () => wasmPath,\n });\n\n let db: Database;\n if (fs.existsSync(dbFilePath)) {\n const fileBuffer = fs.readFileSync(dbFilePath);\n db = new SQL.Database(new Uint8Array(fileBuffer));\n } else {\n db = new SQL.Database();\n }\n\n return new PersistenceDb(db, dbFilePath, SQL);\n }\n\n /** Reload database from disk to pick up changes from other processes */\n private reloadFromDisk(): void {\n if (fs.existsSync(this.dbFilePath)) {\n const fileBuffer = fs.readFileSync(this.dbFilePath);\n this.db = new this.SQL.Database(new Uint8Array(fileBuffer));\n }\n }\n\n getData(): PersistenceData {\n // Reload from disk to get latest data from other server instances\n this.reloadFromDisk();\n\n const result = this.db.exec(\n \"SELECT value FROM kv WHERE key = 'persistence'\"\n );\n\n if (!result.length || !result[0].values.length) {\n return DEFAULT_DATA;\n }\n\n const value = result[0].values[0][0];\n if (typeof value !== 'string') {\n return DEFAULT_DATA;\n }\n\n try {\n const parsed = JSON.parse(value) as PersistenceData;\n return {\n collections: Array.isArray(parsed.collections)\n ? parsed.collections\n : [],\n history: Array.isArray(parsed.history) ? parsed.history : [],\n dataHistory: Array.isArray(parsed.dataHistory) ? parsed.dataHistory : [],\n };\n } catch {\n return DEFAULT_DATA;\n }\n }\n\n setData(data: PersistenceData): void {\n const payload = JSON.stringify({\n collections: Array.isArray(data.collections) ? data.collections : [],\n history: Array.isArray(data.history) ? data.history : [],\n dataHistory: Array.isArray(data.dataHistory) ? data.dataHistory : [],\n });\n\n this.db.run(\n 'INSERT INTO kv (key, value, updated_at) VALUES (?, ?, ?) ON CONFLICT(key) DO UPDATE SET value = excluded.value, updated_at = excluded.updated_at',\n ['persistence', payload, new Date().toISOString()]\n );\n\n this.persistToDisk();\n }\n\n private persistToDisk(): void {\n const data = this.db.export();\n fs.writeFileSync(this.dbFilePath, Buffer.from(data));\n }\n}\n"],"mappings":"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","names":["fs","path","require","path","fs"]}
package/dist/cli/index.js CHANGED
@@ -1,7 +1,7 @@
1
1
  #!/usr/bin/env node
2
2
  import {
3
3
  createServer
4
- } from "./chunk-C34UOOQW.js";
4
+ } from "./chunk-V3TQXD75.js";
5
5
  import {
6
6
  SchemaWatcher
7
7
  } from "./chunk-7LFMAA6L.js";
@@ -16,7 +16,7 @@ import open from "open";
16
16
  import os from "os";
17
17
  import path from "path";
18
18
  var program = new Command();
19
- program.name("convex-devtools").description("A standalone development tool for testing Convex functions").version("1.1.0");
19
+ program.name("convex-devtools").description("A standalone development tool for testing Convex functions").version("1.1.1");
20
20
  program.option("-p, --port <number>", "Port for the devtools server", "5173").option("-d, --dir <path>", "Path to Convex project directory", ".").option(
21
21
  "--storage <mode>",
22
22
  "Storage scope: project (default), global, or path",
@@ -77,7 +77,7 @@ program.option("-p, --port <number>", "Port for the devtools server", "5173").op
77
77
  }
78
78
  console.log(chalk.cyan("\u2554\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2557"));
79
79
  console.log(
80
- chalk.cyan("\u2551") + chalk.white.bold(" Convex DevTools v1.1.0 ") + chalk.cyan("\u2551")
80
+ chalk.cyan("\u2551") + chalk.white.bold(" Convex DevTools v1.1.1 ") + chalk.cyan("\u2551")
81
81
  );
82
82
  console.log(chalk.cyan("\u255A\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u255D"));
83
83
  console.log();
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/cli/index.ts"],"sourcesContent":["#!/usr/bin/env node\n\nimport chalk from 'chalk';\nimport { Command } from 'commander';\nimport dotenv from 'dotenv';\nimport fs from 'fs';\nimport open from 'open';\nimport os from 'os';\nimport path from 'path';\nimport { createServer } from '../server/index.js';\nimport { SchemaWatcher } from '../server/schema-watcher.js';\n\nconst program = new Command();\n\nprogram\n .name('convex-devtools')\n .description('A standalone development tool for testing Convex functions')\n .version('1.1.0');\n\nprogram\n .option('-p, --port <number>', 'Port for the devtools server', '5173')\n .option('-d, --dir <path>', 'Path to Convex project directory', '.')\n .option(\n '--storage <mode>',\n 'Storage scope: project (default), global, or path',\n 'project'\n )\n .option(\n '--storage-path <path>',\n 'Custom storage path when using --storage path'\n )\n .option('--no-open', 'Do not open browser automatically')\n .action(async (options) => {\n const projectDir = path.resolve(options.dir);\n\n // Load .env.local from the project directory\n const envLocalPath = path.join(projectDir, '.env.local');\n const envPath = path.join(projectDir, '.env');\n\n if (fs.existsSync(envLocalPath)) {\n dotenv.config({ path: envLocalPath });\n } else if (fs.existsSync(envPath)) {\n dotenv.config({ path: envPath });\n }\n\n // Check for required environment variables\n if (process.env.CONVEX_DEVTOOLS_ENABLED !== 'true') {\n console.error(\n chalk.red('✗ CONVEX_DEVTOOLS_ENABLED is not set to \"true\"')\n );\n console.error(\n chalk.yellow(\n ' Add CONVEX_DEVTOOLS_ENABLED=true to your .env.local file'\n )\n );\n console.error(\n chalk.yellow(' This tool is intended for local development only.')\n );\n process.exit(1);\n }\n\n const convexUrl = process.env.CONVEX_URL;\n if (!convexUrl) {\n console.error(chalk.red('✗ CONVEX_URL is not set'));\n console.error(\n chalk.yellow(\n ' Make sure you have a valid Convex deployment URL in your .env.local'\n )\n );\n process.exit(1);\n }\n\n // Deploy key is optional for local development\n // Without it, identity mocking won't work but you can still invoke functions\n const deployKey = process.env.CONVEX_DEPLOY_KEY || '';\n if (!deployKey) {\n console.log(chalk.yellow('⚠ CONVEX_DEPLOY_KEY is not set'));\n console.log(chalk.yellow(' Identity mocking will be disabled.'));\n console.log(\n chalk.yellow(\n ' To enable, add to .env.local: CONVEX_DEPLOY_KEY=prod:xxx or dev:xxx'\n )\n );\n console.log();\n }\n\n // Check for convex/_generated directory\n const generatedDir = path.join(projectDir, 'convex', '_generated');\n if (!fs.existsSync(generatedDir)) {\n console.error(chalk.red('✗ Convex generated files not found'));\n console.error(chalk.yellow(` Expected: ${generatedDir}`));\n console.error(chalk.yellow(' Run \"npx convex dev\" to generate them.'));\n process.exit(1);\n }\n\n console.log(chalk.cyan('╔══════════════════════════════════════════╗'));\n console.log(\n chalk.cyan('║') +\n chalk.white.bold(' Convex DevTools v1.1.0 ') +\n chalk.cyan('║')\n );\n console.log(chalk.cyan('╚══════════════════════════════════════════╝'));\n console.log();\n console.log(chalk.green('✓') + ' Environment validated');\n console.log(chalk.green('✓') + ` Convex URL: ${chalk.dim(convexUrl)}`);\n console.log(chalk.green('✓') + ` Project: ${chalk.dim(projectDir)}`);\n console.log();\n\n const storageMode = String(options.storage || 'project');\n let persistencePath: string | undefined;\n\n if (storageMode === 'project') {\n persistencePath = path.join(\n projectDir,\n '.convex-devtools',\n 'devtools.sqlite'\n );\n } else if (storageMode === 'global') {\n persistencePath = path.join(\n os.homedir(),\n '.convex-devtools',\n 'devtools.sqlite'\n );\n } else if (storageMode === 'path') {\n if (!options.storagePath) {\n console.error(\n chalk.red('✗ --storage path requires --storage-path <path>')\n );\n process.exit(1);\n }\n persistencePath = path.resolve(String(options.storagePath));\n } else {\n console.error(\n chalk.red('✗ Invalid --storage value. Use project, global, or path.')\n );\n process.exit(1);\n }\n\n // Start schema watcher\n const schemaWatcher = new SchemaWatcher(projectDir);\n await schemaWatcher.start();\n\n // Start server\n const port = parseInt(options.port, 10);\n const server = await createServer({\n port,\n projectDir,\n convexUrl,\n deployKey,\n schemaWatcher,\n persistencePath,\n });\n\n console.log(\n chalk.green('✓') +\n ` DevTools running at ${chalk.cyan(`http://localhost:${port}`)}`\n );\n console.log();\n console.log(chalk.dim('Press Ctrl+C to stop'));\n\n if (options.open !== false) {\n await open(`http://localhost:${port}`);\n }\n\n // Handle shutdown\n process.on('SIGINT', async () => {\n console.log(chalk.dim('\\nShutting down...'));\n schemaWatcher.stop();\n server.close();\n process.exit(0);\n });\n });\n\nprogram.parse();\n"],"mappings":"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","names":[]}
1
+ {"version":3,"sources":["../../src/cli/index.ts"],"sourcesContent":["#!/usr/bin/env node\n\nimport chalk from 'chalk';\nimport { Command } from 'commander';\nimport dotenv from 'dotenv';\nimport fs from 'fs';\nimport open from 'open';\nimport os from 'os';\nimport path from 'path';\nimport { createServer } from '../server/index.js';\nimport { SchemaWatcher } from '../server/schema-watcher.js';\n\nconst program = new Command();\n\nprogram\n .name('convex-devtools')\n .description('A standalone development tool for testing Convex functions')\n .version('1.1.1');\n\nprogram\n .option('-p, --port <number>', 'Port for the devtools server', '5173')\n .option('-d, --dir <path>', 'Path to Convex project directory', '.')\n .option(\n '--storage <mode>',\n 'Storage scope: project (default), global, or path',\n 'project'\n )\n .option(\n '--storage-path <path>',\n 'Custom storage path when using --storage path'\n )\n .option('--no-open', 'Do not open browser automatically')\n .action(async (options) => {\n const projectDir = path.resolve(options.dir);\n\n // Load .env.local from the project directory\n const envLocalPath = path.join(projectDir, '.env.local');\n const envPath = path.join(projectDir, '.env');\n\n if (fs.existsSync(envLocalPath)) {\n dotenv.config({ path: envLocalPath });\n } else if (fs.existsSync(envPath)) {\n dotenv.config({ path: envPath });\n }\n\n // Check for required environment variables\n if (process.env.CONVEX_DEVTOOLS_ENABLED !== 'true') {\n console.error(\n chalk.red('✗ CONVEX_DEVTOOLS_ENABLED is not set to \"true\"')\n );\n console.error(\n chalk.yellow(\n ' Add CONVEX_DEVTOOLS_ENABLED=true to your .env.local file'\n )\n );\n console.error(\n chalk.yellow(' This tool is intended for local development only.')\n );\n process.exit(1);\n }\n\n const convexUrl = process.env.CONVEX_URL;\n if (!convexUrl) {\n console.error(chalk.red('✗ CONVEX_URL is not set'));\n console.error(\n chalk.yellow(\n ' Make sure you have a valid Convex deployment URL in your .env.local'\n )\n );\n process.exit(1);\n }\n\n // Deploy key is optional for local development\n // Without it, identity mocking won't work but you can still invoke functions\n const deployKey = process.env.CONVEX_DEPLOY_KEY || '';\n if (!deployKey) {\n console.log(chalk.yellow('⚠ CONVEX_DEPLOY_KEY is not set'));\n console.log(chalk.yellow(' Identity mocking will be disabled.'));\n console.log(\n chalk.yellow(\n ' To enable, add to .env.local: CONVEX_DEPLOY_KEY=prod:xxx or dev:xxx'\n )\n );\n console.log();\n }\n\n // Check for convex/_generated directory\n const generatedDir = path.join(projectDir, 'convex', '_generated');\n if (!fs.existsSync(generatedDir)) {\n console.error(chalk.red('✗ Convex generated files not found'));\n console.error(chalk.yellow(` Expected: ${generatedDir}`));\n console.error(chalk.yellow(' Run \"npx convex dev\" to generate them.'));\n process.exit(1);\n }\n\n console.log(chalk.cyan('╔══════════════════════════════════════════╗'));\n console.log(\n chalk.cyan('║') +\n chalk.white.bold(' Convex DevTools v1.1.1 ') +\n chalk.cyan('║')\n );\n console.log(chalk.cyan('╚══════════════════════════════════════════╝'));\n console.log();\n console.log(chalk.green('✓') + ' Environment validated');\n console.log(chalk.green('✓') + ` Convex URL: ${chalk.dim(convexUrl)}`);\n console.log(chalk.green('✓') + ` Project: ${chalk.dim(projectDir)}`);\n console.log();\n\n const storageMode = String(options.storage || 'project');\n let persistencePath: string | undefined;\n\n if (storageMode === 'project') {\n persistencePath = path.join(\n projectDir,\n '.convex-devtools',\n 'devtools.sqlite'\n );\n } else if (storageMode === 'global') {\n persistencePath = path.join(\n os.homedir(),\n '.convex-devtools',\n 'devtools.sqlite'\n );\n } else if (storageMode === 'path') {\n if (!options.storagePath) {\n console.error(\n chalk.red('✗ --storage path requires --storage-path <path>')\n );\n process.exit(1);\n }\n persistencePath = path.resolve(String(options.storagePath));\n } else {\n console.error(\n chalk.red('✗ Invalid --storage value. Use project, global, or path.')\n );\n process.exit(1);\n }\n\n // Start schema watcher\n const schemaWatcher = new SchemaWatcher(projectDir);\n await schemaWatcher.start();\n\n // Start server\n const port = parseInt(options.port, 10);\n const server = await createServer({\n port,\n projectDir,\n convexUrl,\n deployKey,\n schemaWatcher,\n persistencePath,\n });\n\n console.log(\n chalk.green('✓') +\n ` DevTools running at ${chalk.cyan(`http://localhost:${port}`)}`\n );\n console.log();\n console.log(chalk.dim('Press Ctrl+C to stop'));\n\n if (options.open !== false) {\n await open(`http://localhost:${port}`);\n }\n\n // Handle shutdown\n process.on('SIGINT', async () => {\n console.log(chalk.dim('\\nShutting down...'));\n schemaWatcher.stop();\n server.close();\n process.exit(0);\n });\n });\n\nprogram.parse();\n"],"mappings":"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","names":[]}
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  createServer
3
- } from "../chunk-C34UOOQW.js";
3
+ } from "../chunk-V3TQXD75.js";
4
4
  import "../chunk-5B55IAKY.js";
5
5
  export {
6
6
  createServer
@@ -0,0 +1 @@
1
+ *,:before,:after{--tw-border-spacing-x: 0;--tw-border-spacing-y: 0;--tw-translate-x: 0;--tw-translate-y: 0;--tw-rotate: 0;--tw-skew-x: 0;--tw-skew-y: 0;--tw-scale-x: 1;--tw-scale-y: 1;--tw-pan-x: ;--tw-pan-y: ;--tw-pinch-zoom: ;--tw-scroll-snap-strictness: proximity;--tw-gradient-from-position: ;--tw-gradient-via-position: ;--tw-gradient-to-position: ;--tw-ordinal: ;--tw-slashed-zero: ;--tw-numeric-figure: ;--tw-numeric-spacing: ;--tw-numeric-fraction: ;--tw-ring-inset: ;--tw-ring-offset-width: 0px;--tw-ring-offset-color: #fff;--tw-ring-color: rgb(59 130 246 / .5);--tw-ring-offset-shadow: 0 0 #0000;--tw-ring-shadow: 0 0 #0000;--tw-shadow: 0 0 #0000;--tw-shadow-colored: 0 0 #0000;--tw-blur: ;--tw-brightness: ;--tw-contrast: ;--tw-grayscale: ;--tw-hue-rotate: ;--tw-invert: ;--tw-saturate: ;--tw-sepia: ;--tw-drop-shadow: ;--tw-backdrop-blur: ;--tw-backdrop-brightness: ;--tw-backdrop-contrast: ;--tw-backdrop-grayscale: ;--tw-backdrop-hue-rotate: ;--tw-backdrop-invert: ;--tw-backdrop-opacity: ;--tw-backdrop-saturate: ;--tw-backdrop-sepia: ;--tw-contain-size: ;--tw-contain-layout: ;--tw-contain-paint: ;--tw-contain-style: }::backdrop{--tw-border-spacing-x: 0;--tw-border-spacing-y: 0;--tw-translate-x: 0;--tw-translate-y: 0;--tw-rotate: 0;--tw-skew-x: 0;--tw-skew-y: 0;--tw-scale-x: 1;--tw-scale-y: 1;--tw-pan-x: ;--tw-pan-y: ;--tw-pinch-zoom: ;--tw-scroll-snap-strictness: proximity;--tw-gradient-from-position: ;--tw-gradient-via-position: ;--tw-gradient-to-position: ;--tw-ordinal: ;--tw-slashed-zero: ;--tw-numeric-figure: ;--tw-numeric-spacing: ;--tw-numeric-fraction: ;--tw-ring-inset: ;--tw-ring-offset-width: 0px;--tw-ring-offset-color: #fff;--tw-ring-color: rgb(59 130 246 / .5);--tw-ring-offset-shadow: 0 0 #0000;--tw-ring-shadow: 0 0 #0000;--tw-shadow: 0 0 #0000;--tw-shadow-colored: 0 0 #0000;--tw-blur: ;--tw-brightness: ;--tw-contrast: ;--tw-grayscale: ;--tw-hue-rotate: ;--tw-invert: ;--tw-saturate: ;--tw-sepia: ;--tw-drop-shadow: ;--tw-backdrop-blur: ;--tw-backdrop-brightness: ;--tw-backdrop-contrast: ;--tw-backdrop-grayscale: ;--tw-backdrop-hue-rotate: ;--tw-backdrop-invert: ;--tw-backdrop-opacity: ;--tw-backdrop-saturate: ;--tw-backdrop-sepia: ;--tw-contain-size: ;--tw-contain-layout: ;--tw-contain-paint: ;--tw-contain-style: }*,:before,:after{box-sizing:border-box;border-width:0;border-style:solid;border-color:#e5e7eb}:before,:after{--tw-content: ""}html,:host{line-height:1.5;-webkit-text-size-adjust:100%;-moz-tab-size:4;-o-tab-size:4;tab-size:4;font-family:ui-sans-serif,system-ui,sans-serif,"Apple Color Emoji","Segoe UI Emoji",Segoe UI Symbol,"Noto Color Emoji";font-feature-settings:normal;font-variation-settings:normal;-webkit-tap-highlight-color:transparent}body{margin:0;line-height:inherit}hr{height:0;color:inherit;border-top-width:1px}abbr:where([title]){-webkit-text-decoration:underline dotted;text-decoration:underline dotted}h1,h2,h3,h4,h5,h6{font-size:inherit;font-weight:inherit}a{color:inherit;text-decoration:inherit}b,strong{font-weight:bolder}code,kbd,samp,pre{font-family:ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,Liberation Mono,Courier New,monospace;font-feature-settings:normal;font-variation-settings:normal;font-size:1em}small{font-size:80%}sub,sup{font-size:75%;line-height:0;position:relative;vertical-align:baseline}sub{bottom:-.25em}sup{top:-.5em}table{text-indent:0;border-color:inherit;border-collapse:collapse}button,input,optgroup,select,textarea{font-family:inherit;font-feature-settings:inherit;font-variation-settings:inherit;font-size:100%;font-weight:inherit;line-height:inherit;letter-spacing:inherit;color:inherit;margin:0;padding:0}button,select{text-transform:none}button,input:where([type=button]),input:where([type=reset]),input:where([type=submit]){-webkit-appearance:button;background-color:transparent;background-image:none}:-moz-focusring{outline:auto}:-moz-ui-invalid{box-shadow:none}progress{vertical-align:baseline}::-webkit-inner-spin-button,::-webkit-outer-spin-button{height:auto}[type=search]{-webkit-appearance:textfield;outline-offset:-2px}::-webkit-search-decoration{-webkit-appearance:none}::-webkit-file-upload-button{-webkit-appearance:button;font:inherit}summary{display:list-item}blockquote,dl,dd,h1,h2,h3,h4,h5,h6,hr,figure,p,pre{margin:0}fieldset{margin:0;padding:0}legend{padding:0}ol,ul,menu{list-style:none;margin:0;padding:0}dialog{padding:0}textarea{resize:vertical}input::-moz-placeholder,textarea::-moz-placeholder{opacity:1;color:#9ca3af}input::placeholder,textarea::placeholder{opacity:1;color:#9ca3af}button,[role=button]{cursor:pointer}:disabled{cursor:default}img,svg,video,canvas,audio,iframe,embed,object{display:block;vertical-align:middle}img,video{max-width:100%;height:auto}[hidden]:where(:not([hidden=until-found])){display:none}.pointer-events-none{pointer-events:none}.visible{visibility:visible}.static{position:static}.fixed{position:fixed}.absolute{position:absolute}.relative{position:relative}.sticky{position:sticky}.inset-0{top:0;right:0;bottom:0;left:0}.left-0{left:0}.left-2{left:.5rem}.left-3{left:.75rem}.right-0{right:0}.top-0{top:0}.top-1\/2{top:50%}.z-20{z-index:20}.z-50{z-index:50}.mx-1{margin-left:.25rem;margin-right:.25rem}.mx-auto{margin-left:auto;margin-right:auto}.mb-1{margin-bottom:.25rem}.mb-2{margin-bottom:.5rem}.mb-4{margin-bottom:1rem}.ml-1{margin-left:.25rem}.ml-2{margin-left:.5rem}.ml-5{margin-left:1.25rem}.ml-auto{margin-left:auto}.mt-0\.5{margin-top:.125rem}.mt-1{margin-top:.25rem}.mt-1\.5{margin-top:.375rem}.mt-2{margin-top:.5rem}.mt-6{margin-top:1.5rem}.block{display:block}.inline{display:inline}.flex{display:flex}.inline-flex{display:inline-flex}.\!table{display:table!important}.table{display:table}.grid{display:grid}.hidden{display:none}.h-1\.5{height:.375rem}.h-1\/2{height:50%}.h-12{height:3rem}.h-14{height:3.5rem}.h-16{height:4rem}.h-2{height:.5rem}.h-3{height:.75rem}.h-3\.5{height:.875rem}.h-32{height:8rem}.h-4{height:1rem}.h-40{height:10rem}.h-5{height:1.25rem}.h-6{height:1.5rem}.h-8{height:2rem}.h-9{height:2.25rem}.h-full{height:100%}.h-screen{height:100vh}.max-h-48{max-height:12rem}.max-h-\[calc\(100vh-220px\)\]{max-height:calc(100vh - 220px)}.min-h-0{min-height:0px}.w-1{width:.25rem}.w-16{width:4rem}.w-2{width:.5rem}.w-3{width:.75rem}.w-3\.5{width:.875rem}.w-4{width:1rem}.w-40{width:10rem}.w-5{width:1.25rem}.w-64{width:16rem}.w-72{width:18rem}.w-8{width:2rem}.w-80{width:20rem}.w-9{width:2.25rem}.w-96{width:24rem}.w-full{width:100%}.min-w-0{min-width:0px}.min-w-\[70px\]{min-width:70px}.min-w-full{min-width:100%}.max-w-\[160px\]{max-width:160px}.max-w-\[200px\]{max-width:200px}.max-w-\[240px\]{max-width:240px}.max-w-\[320px\]{max-width:320px}.flex-1{flex:1 1 0%}.flex-shrink-0{flex-shrink:0}.-translate-y-1\/2{--tw-translate-y: -50%;transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skew(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y))}.rotate-90{--tw-rotate: 90deg;transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skew(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y))}.transform{transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skew(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y))}@keyframes pulse{50%{opacity:.5}}.animate-pulse{animation:pulse 2s cubic-bezier(.4,0,.6,1) infinite}@keyframes spin{to{transform:rotate(360deg)}}.animate-spin{animation:spin 1s linear infinite}.cursor-col-resize{cursor:col-resize}.cursor-help{cursor:help}.cursor-not-allowed{cursor:not-allowed}.cursor-pointer{cursor:pointer}.cursor-row-resize{cursor:row-resize}.resize-none{resize:none}.grid-cols-\[minmax\(0\,1\.1fr\)_minmax\(0\,1\.9fr\)\]{grid-template-columns:minmax(0,1.1fr) minmax(0,1.9fr)}.flex-col{flex-direction:column}.flex-wrap{flex-wrap:wrap}.flex-nowrap{flex-wrap:nowrap}.items-start{align-items:flex-start}.items-center{align-items:center}.justify-end{justify-content:flex-end}.justify-center{justify-content:center}.justify-between{justify-content:space-between}.gap-1{gap:.25rem}.gap-1\.5{gap:.375rem}.gap-2{gap:.5rem}.gap-3{gap:.75rem}.gap-4{gap:1rem}.gap-x-3{-moz-column-gap:.75rem;column-gap:.75rem}.gap-y-1{row-gap:.25rem}.space-y-2>:not([hidden])~:not([hidden]){--tw-space-y-reverse: 0;margin-top:calc(.5rem * calc(1 - var(--tw-space-y-reverse)));margin-bottom:calc(.5rem * var(--tw-space-y-reverse))}.space-y-3>:not([hidden])~:not([hidden]){--tw-space-y-reverse: 0;margin-top:calc(.75rem * calc(1 - var(--tw-space-y-reverse)));margin-bottom:calc(.75rem * var(--tw-space-y-reverse))}.space-y-4>:not([hidden])~:not([hidden]){--tw-space-y-reverse: 0;margin-top:calc(1rem * calc(1 - var(--tw-space-y-reverse)));margin-bottom:calc(1rem * var(--tw-space-y-reverse))}.overflow-auto{overflow:auto}.overflow-hidden{overflow:hidden}.overflow-x-auto{overflow-x:auto}.overflow-y-auto{overflow-y:auto}.truncate{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.whitespace-normal{white-space:normal}.whitespace-nowrap{white-space:nowrap}.whitespace-pre-wrap{white-space:pre-wrap}.break-words{overflow-wrap:break-word}.break-all{word-break:break-all}.rounded{border-radius:.25rem}.rounded-full{border-radius:9999px}.rounded-lg{border-radius:.5rem}.rounded-md{border-radius:.375rem}.border{border-width:1px}.border-b{border-bottom-width:1px}.border-l{border-left-width:1px}.border-r{border-right-width:1px}.border-t{border-top-width:1px}.border-amber-800{--tw-border-opacity: 1;border-color:rgb(146 64 14 / var(--tw-border-opacity, 1))}.border-blue-400{--tw-border-opacity: 1;border-color:rgb(96 165 250 / var(--tw-border-opacity, 1))}.border-blue-800{--tw-border-opacity: 1;border-color:rgb(30 64 175 / var(--tw-border-opacity, 1))}.border-convex-accent\/50{border-color:#f9731680}.border-convex-border{--tw-border-opacity: 1;border-color:rgb(42 42 42 / var(--tw-border-opacity, 1))}.border-convex-border\/50{border-color:#2a2a2a80}.border-green-500{--tw-border-opacity: 1;border-color:rgb(34 197 94 / var(--tw-border-opacity, 1))}.border-green-800{--tw-border-opacity: 1;border-color:rgb(22 101 52 / var(--tw-border-opacity, 1))}.border-orange-400{--tw-border-opacity: 1;border-color:rgb(251 146 60 / var(--tw-border-opacity, 1))}.border-purple-400{--tw-border-opacity: 1;border-color:rgb(192 132 252 / var(--tw-border-opacity, 1))}.border-red-800{--tw-border-opacity: 1;border-color:rgb(153 27 27 / var(--tw-border-opacity, 1))}.border-transparent{border-color:transparent}.border-yellow-800{--tw-border-opacity: 1;border-color:rgb(133 77 14 / var(--tw-border-opacity, 1))}.bg-amber-400{--tw-bg-opacity: 1;background-color:rgb(251 191 36 / var(--tw-bg-opacity, 1))}.bg-amber-500{--tw-bg-opacity: 1;background-color:rgb(245 158 11 / var(--tw-bg-opacity, 1))}.bg-amber-900\/20{background-color:#78350f33}.bg-black\/50{background-color:#00000080}.bg-blue-900\/20{background-color:#1e3a8a33}.bg-blue-900\/30{background-color:#1e3a8a4d}.bg-convex-accent{--tw-bg-opacity: 1;background-color:rgb(249 115 22 / var(--tw-bg-opacity, 1))}.bg-convex-accent\/10{background-color:#f973161a}.bg-convex-accent\/20{background-color:#f9731633}.bg-convex-border{--tw-bg-opacity: 1;background-color:rgb(42 42 42 / var(--tw-bg-opacity, 1))}.bg-convex-dark{--tw-bg-opacity: 1;background-color:rgb(15 15 15 / var(--tw-bg-opacity, 1))}.bg-convex-darker{--tw-bg-opacity: 1;background-color:rgb(10 10 10 / var(--tw-bg-opacity, 1))}.bg-convex-darker\/60{background-color:#0a0a0a99}.bg-convex-darker\/90{background-color:#0a0a0ae6}.bg-gray-300{--tw-bg-opacity: 1;background-color:rgb(209 213 219 / var(--tw-bg-opacity, 1))}.bg-gray-500{--tw-bg-opacity: 1;background-color:rgb(107 114 128 / var(--tw-bg-opacity, 1))}.bg-gray-600{--tw-bg-opacity: 1;background-color:rgb(75 85 99 / var(--tw-bg-opacity, 1))}.bg-gray-700{--tw-bg-opacity: 1;background-color:rgb(55 65 81 / var(--tw-bg-opacity, 1))}.bg-gray-800{--tw-bg-opacity: 1;background-color:rgb(31 41 55 / var(--tw-bg-opacity, 1))}.bg-green-400{--tw-bg-opacity: 1;background-color:rgb(74 222 128 / var(--tw-bg-opacity, 1))}.bg-green-500{--tw-bg-opacity: 1;background-color:rgb(34 197 94 / var(--tw-bg-opacity, 1))}.bg-green-600{--tw-bg-opacity: 1;background-color:rgb(22 163 74 / var(--tw-bg-opacity, 1))}.bg-green-900\/20{background-color:#14532d33}.bg-green-900\/30{background-color:#14532d4d}.bg-orange-900\/30{background-color:#7c2d124d}.bg-purple-900\/30{background-color:#581c874d}.bg-red-400{--tw-bg-opacity: 1;background-color:rgb(248 113 113 / var(--tw-bg-opacity, 1))}.bg-red-900\/20{background-color:#7f1d1d33}.bg-transparent{background-color:transparent}.bg-yellow-300{--tw-bg-opacity: 1;background-color:rgb(253 224 71 / var(--tw-bg-opacity, 1))}.bg-yellow-400{--tw-bg-opacity: 1;background-color:rgb(250 204 21 / var(--tw-bg-opacity, 1))}.bg-yellow-900\/20{background-color:#713f1233}.p-0\.5{padding:.125rem}.p-1{padding:.25rem}.p-1\.5{padding:.375rem}.p-2{padding:.5rem}.p-3{padding:.75rem}.p-4{padding:1rem}.p-6{padding:1.5rem}.px-0\.5{padding-left:.125rem;padding-right:.125rem}.px-1{padding-left:.25rem;padding-right:.25rem}.px-1\.5{padding-left:.375rem;padding-right:.375rem}.px-2{padding-left:.5rem;padding-right:.5rem}.px-3{padding-left:.75rem;padding-right:.75rem}.px-4{padding-left:1rem;padding-right:1rem}.py-0\.5{padding-top:.125rem;padding-bottom:.125rem}.py-1{padding-top:.25rem;padding-bottom:.25rem}.py-1\.5{padding-top:.375rem;padding-bottom:.375rem}.py-2{padding-top:.5rem;padding-bottom:.5rem}.py-3{padding-top:.75rem;padding-bottom:.75rem}.py-8{padding-top:2rem;padding-bottom:2rem}.pb-1{padding-bottom:.25rem}.pb-2{padding-bottom:.5rem}.pl-10{padding-left:2.5rem}.pl-3{padding-left:.75rem}.pl-6{padding-left:1.5rem}.pl-8{padding-left:2rem}.pr-1{padding-right:.25rem}.pr-2{padding-right:.5rem}.pr-3{padding-right:.75rem}.pt-0\.5{padding-top:.125rem}.pt-2{padding-top:.5rem}.pt-4{padding-top:1rem}.text-left{text-align:left}.text-center{text-align:center}.text-right{text-align:right}.align-top{vertical-align:top}.font-mono{font-family:ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,Liberation Mono,Courier New,monospace}.text-\[10px\]{font-size:10px}.text-\[11px\]{font-size:11px}.text-lg{font-size:1.125rem;line-height:1.75rem}.text-sm{font-size:.875rem;line-height:1.25rem}.text-xs{font-size:.75rem;line-height:1rem}.font-bold{font-weight:700}.font-medium{font-weight:500}.font-semibold{font-weight:600}.uppercase{text-transform:uppercase}.leading-5{line-height:1.25rem}.leading-none{line-height:1}.tracking-wide{letter-spacing:.025em}.text-amber-300{--tw-text-opacity: 1;color:rgb(252 211 77 / var(--tw-text-opacity, 1))}.text-black{--tw-text-opacity: 1;color:rgb(0 0 0 / var(--tw-text-opacity, 1))}.text-blue-300{--tw-text-opacity: 1;color:rgb(147 197 253 / var(--tw-text-opacity, 1))}.text-blue-400{--tw-text-opacity: 1;color:rgb(96 165 250 / var(--tw-text-opacity, 1))}.text-convex-accent{--tw-text-opacity: 1;color:rgb(249 115 22 / var(--tw-text-opacity, 1))}.text-gray-200{--tw-text-opacity: 1;color:rgb(229 231 235 / var(--tw-text-opacity, 1))}.text-gray-300{--tw-text-opacity: 1;color:rgb(209 213 219 / var(--tw-text-opacity, 1))}.text-gray-400{--tw-text-opacity: 1;color:rgb(156 163 175 / var(--tw-text-opacity, 1))}.text-gray-500{--tw-text-opacity: 1;color:rgb(107 114 128 / var(--tw-text-opacity, 1))}.text-gray-600{--tw-text-opacity: 1;color:rgb(75 85 99 / var(--tw-text-opacity, 1))}.text-gray-900{--tw-text-opacity: 1;color:rgb(17 24 39 / var(--tw-text-opacity, 1))}.text-green-400{--tw-text-opacity: 1;color:rgb(74 222 128 / var(--tw-text-opacity, 1))}.text-green-600{--tw-text-opacity: 1;color:rgb(22 163 74 / var(--tw-text-opacity, 1))}.text-orange-400{--tw-text-opacity: 1;color:rgb(251 146 60 / var(--tw-text-opacity, 1))}.text-purple-400{--tw-text-opacity: 1;color:rgb(192 132 252 / var(--tw-text-opacity, 1))}.text-red-300{--tw-text-opacity: 1;color:rgb(252 165 165 / var(--tw-text-opacity, 1))}.text-red-400{--tw-text-opacity: 1;color:rgb(248 113 113 / var(--tw-text-opacity, 1))}.text-red-600{--tw-text-opacity: 1;color:rgb(220 38 38 / var(--tw-text-opacity, 1))}.text-red-700{--tw-text-opacity: 1;color:rgb(185 28 28 / var(--tw-text-opacity, 1))}.text-white{--tw-text-opacity: 1;color:rgb(255 255 255 / var(--tw-text-opacity, 1))}.text-yellow-400{--tw-text-opacity: 1;color:rgb(250 204 21 / var(--tw-text-opacity, 1))}.text-yellow-500{--tw-text-opacity: 1;color:rgb(234 179 8 / var(--tw-text-opacity, 1))}.opacity-0{opacity:0}.opacity-25{opacity:.25}.opacity-75{opacity:.75}.shadow-lg{--tw-shadow: 0 10px 15px -3px rgb(0 0 0 / .1), 0 4px 6px -4px rgb(0 0 0 / .1);--tw-shadow-colored: 0 10px 15px -3px var(--tw-shadow-color), 0 4px 6px -4px var(--tw-shadow-color);box-shadow:var(--tw-ring-offset-shadow, 0 0 #0000),var(--tw-ring-shadow, 0 0 #0000),var(--tw-shadow)}.filter{filter:var(--tw-blur) var(--tw-brightness) var(--tw-contrast) var(--tw-grayscale) var(--tw-hue-rotate) var(--tw-invert) var(--tw-saturate) var(--tw-sepia) var(--tw-drop-shadow)}.backdrop-blur-sm{--tw-backdrop-blur: blur(4px);-webkit-backdrop-filter:var(--tw-backdrop-blur) var(--tw-backdrop-brightness) var(--tw-backdrop-contrast) var(--tw-backdrop-grayscale) var(--tw-backdrop-hue-rotate) var(--tw-backdrop-invert) var(--tw-backdrop-opacity) var(--tw-backdrop-saturate) var(--tw-backdrop-sepia);backdrop-filter:var(--tw-backdrop-blur) var(--tw-backdrop-brightness) var(--tw-backdrop-contrast) var(--tw-backdrop-grayscale) var(--tw-backdrop-hue-rotate) var(--tw-backdrop-invert) var(--tw-backdrop-opacity) var(--tw-backdrop-saturate) var(--tw-backdrop-sepia)}.transition{transition-property:color,background-color,border-color,text-decoration-color,fill,stroke,opacity,box-shadow,transform,filter,backdrop-filter;transition-timing-function:cubic-bezier(.4,0,.2,1);transition-duration:.15s}.transition-all{transition-property:all;transition-timing-function:cubic-bezier(.4,0,.2,1);transition-duration:.15s}.transition-colors{transition-property:color,background-color,border-color,text-decoration-color,fill,stroke;transition-timing-function:cubic-bezier(.4,0,.2,1);transition-duration:.15s}.transition-transform{transition-property:transform;transition-timing-function:cubic-bezier(.4,0,.2,1);transition-duration:.15s}:root{font-family:Inter,system-ui,-apple-system,sans-serif;line-height:1.5;font-weight:400;font-synthesis:none;text-rendering:optimizeLegibility;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale}body{margin:0;min-width:320px;min-height:100vh}::-webkit-scrollbar{width:8px;height:8px}::-webkit-scrollbar-track{background:#1a1a1a}::-webkit-scrollbar-thumb{background:#3a3a3a;border-radius:4px}::-webkit-scrollbar-thumb:hover{background:#4a4a4a}.scrollbar-hide::-webkit-scrollbar{width:0;height:0}.scrollbar-hide{-ms-overflow-style:none;scrollbar-width:none}.monaco-editor{border-radius:8px}.json-key{color:#9cdcfe}.json-string{color:#ce9178}.json-number{color:#b5cea8}.json-boolean,.json-null{color:#569cd6}.light body{background:#f8fafc;color:#1e293b}.light .bg-convex-dark{background-color:#fff!important}.light .bg-convex-darker{background-color:#f1f5f9!important}.light .border-convex-border{border-color:#cbd5e1!important}.light .text-gray-300{color:#334155!important}.light .text-gray-400{color:#475569!important}.light .text-gray-500{color:#64748b!important}.light .text-gray-600{color:#475569!important}.light .text-white{color:#0f172a!important}.light .bg-convex-accent{background-color:#f97316!important}.light .bg-convex-border,.light .hover\:bg-convex-border:hover{background-color:#e2e8f0!important}.light textarea,.light input,.light select{background-color:#fff!important;border-color:#cbd5e1!important;color:#1e293b!important}.light pre{color:#334155!important}.light .json-key{color:#0369a1!important}.light .json-string{color:#b45309!important}.light .json-number{color:#047857!important}.light .json-boolean{color:#7c3aed!important}.light .json-null{color:#6b7280!important}.light .data-table th{color:#334155!important}.light .data-table td{color:#0f172a!important}.light .data-table tbody tr:hover{background-color:#f1f5f9!important}.light .data-table .bg-convex-darker{background-color:#f8fafc!important}.light .data-table .text-gray-500{color:#64748b!important}.light .data-table .text-gray-200{color:#0f172a!important}.light .data-table .text-gray-300{color:#334155!important}.light .data-table .text-gray-400{color:#475569!important}.light .data-explorer-panel .text-gray-200{color:#0f172a!important}.light .data-explorer-panel .text-gray-400{color:#475569!important}.light .data-explorer-panel .text-gray-500{color:#64748b!important}.light .fields-drawer{background-color:#fff!important;color:#1e293b!important}.light .fields-drawer .text-gray-500{color:#64748b!important}.light .fields-drawer .text-gray-400{color:#475569!important}.light .auth-panel .text-gray-300{color:#334155!important}.light .auth-panel .text-gray-400{color:#475569!important}.light .auth-panel .text-gray-500{color:#64748b!important}.light .auth-panel .text-gray-600{color:#475569!important}.light .auth-panel .bg-gray-800{background-color:#e2e8f0!important}.light .auth-panel .bg-convex-dark{background-color:#fff!important}.panel-tabs{height:3rem;padding-left:.75rem;padding-right:.75rem;display:flex;align-items:center;gap:.25rem}.panel-tab-btn{height:2rem;padding:0 .75rem;border-radius:.5rem;font-size:.875rem;display:inline-flex;align-items:center;justify-content:center;text-align:center}.panel-tabs .panel-tab-btn{line-height:1.25rem}.data-tabs-row{height:3.5rem;min-height:3.5rem;display:flex;align-items:center;gap:.5rem}.btn-compact{height:2.25rem;padding:0 .75rem;border-radius:.5rem;display:inline-flex;align-items:center;justify-content:center}.input-control{border-radius:.25rem;border-width:1px;--tw-border-opacity: 1;border-color:rgb(42 42 42 / var(--tw-border-opacity, 1));--tw-bg-opacity: 1;background-color:rgb(10 10 10 / var(--tw-bg-opacity, 1));padding:.25rem .5rem;font-size:.875rem;line-height:1.25rem}.light .input-control{background-color:#f1f5f9;border-color:#cbd5e1}.light .data-table .input-control{background-color:#f8fafc}.input-control{height:2.25rem;line-height:1.25rem}.json-pill{background-color:#37415199;border-color:#4b5563cc;color:#e5e7eb}.json-pill:hover{background-color:#374151cc}.json-pill-icon{background-color:#4b5563e6;color:#e5e7eb}.json-popover{background-color:#0f172a;border:1px solid #374151;color:#e5e7eb}.light .json-pill{background-color:#f1f5f9;border-color:#cbd5e1;color:#1f2937}.light .json-pill:hover{background-color:#e2e8f0}.light .json-pill-icon{background-color:#e2e8f0;color:#1f2937}.light .json-popover{background-color:#fff;border:1px solid #cbd5e1;color:#1f2937}.input-control:focus{outline:none;border-color:var(--tw-border-opacity)}.light ::-webkit-scrollbar-track{background:#f1f5f9}.light ::-webkit-scrollbar-thumb{background:#cbd5e1}.light ::-webkit-scrollbar-thumb:hover{background:#94a3b8}.light .bg-blue-900\/20{background-color:#dbeafe!important}.light .text-blue-300{color:#1d4ed8!important}.light .bg-gray-800\/50{background-color:#e2e8f0!important}.light .bg-green-900\/20{background-color:#dcfce7!important}.light .text-green-300{color:#15803d!important}.light .text-green-400{color:#16a34a!important}.light .bg-blue-900\/30{background-color:#dbeafe!important}.light .text-blue-400{color:#2563eb!important}.light .bg-orange-900\/30{background-color:#ffedd5!important}.light .text-orange-400{color:#ea580c!important}.light .bg-purple-900\/30{background-color:#f3e8ff!important}.light .text-purple-400{color:#9333ea!important}.light code{background-color:#e2e8f0!important;color:#1e293b!important}.hover\:bg-amber-300:hover{--tw-bg-opacity: 1;background-color:rgb(252 211 77 / var(--tw-bg-opacity, 1))}.hover\:bg-amber-400:hover{--tw-bg-opacity: 1;background-color:rgb(251 191 36 / var(--tw-bg-opacity, 1))}.hover\:bg-convex-accent-hover:hover{--tw-bg-opacity: 1;background-color:rgb(234 88 12 / var(--tw-bg-opacity, 1))}.hover\:bg-convex-accent\/30:hover{background-color:#f973164d}.hover\:bg-convex-border:hover{--tw-bg-opacity: 1;background-color:rgb(42 42 42 / var(--tw-bg-opacity, 1))}.hover\:bg-convex-border\/40:hover{background-color:#2a2a2a66}.hover\:bg-convex-dark:hover{--tw-bg-opacity: 1;background-color:rgb(15 15 15 / var(--tw-bg-opacity, 1))}.hover\:bg-convex-darker\/60:hover{background-color:#0a0a0a99}.hover\:bg-gray-200:hover{--tw-bg-opacity: 1;background-color:rgb(229 231 235 / var(--tw-bg-opacity, 1))}.hover\:bg-gray-600:hover{--tw-bg-opacity: 1;background-color:rgb(75 85 99 / var(--tw-bg-opacity, 1))}.hover\:bg-green-400:hover{--tw-bg-opacity: 1;background-color:rgb(74 222 128 / var(--tw-bg-opacity, 1))}.hover\:bg-green-400\/10:hover{background-color:#4ade801a}.hover\:bg-green-700:hover{--tw-bg-opacity: 1;background-color:rgb(21 128 61 / var(--tw-bg-opacity, 1))}.hover\:bg-red-400\/10:hover{background-color:#f871711a}.hover\:text-blue-500:hover{--tw-text-opacity: 1;color:rgb(59 130 246 / var(--tw-text-opacity, 1))}.hover\:text-gray-200:hover{--tw-text-opacity: 1;color:rgb(229 231 235 / var(--tw-text-opacity, 1))}.hover\:text-gray-900:hover{--tw-text-opacity: 1;color:rgb(17 24 39 / var(--tw-text-opacity, 1))}.hover\:text-green-300:hover{--tw-text-opacity: 1;color:rgb(134 239 172 / var(--tw-text-opacity, 1))}.hover\:text-red-300:hover{--tw-text-opacity: 1;color:rgb(252 165 165 / var(--tw-text-opacity, 1))}.hover\:text-red-400:hover{--tw-text-opacity: 1;color:rgb(248 113 113 / var(--tw-text-opacity, 1))}.hover\:text-red-500:hover{--tw-text-opacity: 1;color:rgb(239 68 68 / var(--tw-text-opacity, 1))}.hover\:text-white:hover{--tw-text-opacity: 1;color:rgb(255 255 255 / var(--tw-text-opacity, 1))}.focus\:border-convex-accent:focus{--tw-border-opacity: 1;border-color:rgb(249 115 22 / var(--tw-border-opacity, 1))}.focus\:outline-none:focus{outline:2px solid transparent;outline-offset:2px}.disabled\:cursor-not-allowed:disabled{cursor:not-allowed}.disabled\:opacity-50:disabled{opacity:.5}.group:hover .group-hover\:pointer-events-auto{pointer-events:auto}.group:hover .group-hover\:opacity-100{opacity:1}@media (prefers-color-scheme: dark){.dark\:bg-convex-border{--tw-bg-opacity: 1;background-color:rgb(42 42 42 / var(--tw-bg-opacity, 1))}.dark\:text-gray-400{--tw-text-opacity: 1;color:rgb(156 163 175 / var(--tw-text-opacity, 1))}.dark\:text-green-400{--tw-text-opacity: 1;color:rgb(74 222 128 / var(--tw-text-opacity, 1))}.dark\:text-red-300{--tw-text-opacity: 1;color:rgb(252 165 165 / var(--tw-text-opacity, 1))}.dark\:text-red-400{--tw-text-opacity: 1;color:rgb(248 113 113 / var(--tw-text-opacity, 1))}.dark\:text-white{--tw-text-opacity: 1;color:rgb(255 255 255 / var(--tw-text-opacity, 1))}.dark\:hover\:bg-convex-border:hover{--tw-bg-opacity: 1;background-color:rgb(42 42 42 / var(--tw-bg-opacity, 1))}.dark\:hover\:bg-convex-border\/50:hover{background-color:#2a2a2a80}.dark\:hover\:text-convex-accent:hover{--tw-text-opacity: 1;color:rgb(249 115 22 / var(--tw-text-opacity, 1))}.dark\:hover\:text-red-400:hover{--tw-text-opacity: 1;color:rgb(248 113 113 / var(--tw-text-opacity, 1))}.dark\:hover\:text-white:hover{--tw-text-opacity: 1;color:rgb(255 255 255 / var(--tw-text-opacity, 1))}}