@concavejs/devtools 0.0.1-alpha.4

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.

Potentially problematic release.


This version of @concavejs/devtools might be problematic. Click here for more details.

@@ -0,0 +1,544 @@
1
+ import s from "path";
2
+ import { fileURLToPath as m } from "url";
3
+ const g = s.dirname(m(import.meta.url));
4
+ function p(i = {}) {
5
+ const { enabled: a = !0, position: r = "bottom-right" } = i;
6
+ let t = !1;
7
+ return {
8
+ name: "concave-devtools",
9
+ configResolved(e) {
10
+ t = e.mode === "development";
11
+ },
12
+ transformIndexHtml: {
13
+ order: "pre",
14
+ handler(e) {
15
+ if (!t || !a)
16
+ return e;
17
+ const n = `
18
+ <script>
19
+ // Initialize event store immediately
20
+ (function() {
21
+ if (window.__concaveDevTools) return;
22
+
23
+ console.log('[DevTools] Installing WebSocket interceptor...');
24
+
25
+ // Minimal event store for capturing events
26
+ window.__concaveDevToolsEvents = [];
27
+ window.__concaveDevToolsPendingQueries = new Map();
28
+ window.__concaveDevToolsPendingMutations = new Map();
29
+ window.__concaveDevToolsPendingActions = new Map();
30
+ window.__concaveDevToolsPendingAuthTokenType = null;
31
+
32
+ const OriginalWebSocket = window.WebSocket;
33
+
34
+ const emitAuthEvent = (direction, messageType, status, details, error, tokenType) => {
35
+ const now = Date.now();
36
+ window.__concaveDevToolsEvents.push({
37
+ id: 'auth-' + direction + '-' + messageType + '-' + now + '-' + Math.random().toString(36).slice(2, 8),
38
+ timestamp: now,
39
+ type: 'auth',
40
+ direction,
41
+ messageType,
42
+ status,
43
+ tokenType,
44
+ error,
45
+ details,
46
+ });
47
+ };
48
+
49
+ const decodeJwtClaims = (token) => {
50
+ const parts = token.split('.');
51
+ if (parts.length < 2) return null;
52
+ try {
53
+ const normalized = parts[1].replace(/-/g, '+').replace(/_/g, '/');
54
+ const padded = normalized + '='.repeat((4 - (normalized.length % 4)) % 4);
55
+ const payload = JSON.parse(atob(padded));
56
+ const keys = ['iss', 'sub', 'aud', 'exp', 'iat', 'nbf'];
57
+ const claims = {};
58
+ keys.forEach((key) => {
59
+ if (payload[key] !== undefined) claims[key] = payload[key];
60
+ });
61
+ if (typeof claims.exp === 'number') claims.expIso = new Date(claims.exp * 1000).toISOString();
62
+ if (typeof claims.iat === 'number') claims.iatIso = new Date(claims.iat * 1000).toISOString();
63
+ return Object.keys(claims).length > 0 ? claims : null;
64
+ } catch (e) {
65
+ return null;
66
+ }
67
+ };
68
+
69
+ // Create intercepted WebSocket constructor
70
+ window.WebSocket = function(url, protocols) {
71
+ const ws = new OriginalWebSocket(url, protocols);
72
+
73
+ // Intercept send
74
+ const originalSend = ws.send.bind(ws);
75
+ ws.send = function(data) {
76
+ if (typeof data === 'string') {
77
+ try {
78
+ const msg = JSON.parse(data);
79
+ const now = Date.now();
80
+
81
+ if (msg.type === 'Connect') {
82
+ const connectDetails = {};
83
+ if (typeof msg.connectionCount === 'number') connectDetails.connectionCount = msg.connectionCount;
84
+ if (typeof msg.lastCloseReason === 'string') connectDetails.lastCloseReason = msg.lastCloseReason;
85
+ if (typeof msg.clientTs === 'number') connectDetails.clientTs = msg.clientTs;
86
+ if (typeof msg.sessionId === 'string') connectDetails.sessionId = msg.sessionId;
87
+ emitAuthEvent('client', 'Connect', 'success', connectDetails, undefined, undefined);
88
+ }
89
+
90
+ if (msg.type === 'Authenticate') {
91
+ const authDetails = {};
92
+ if (typeof msg.baseVersion === 'number') authDetails.baseVersion = msg.baseVersion;
93
+ if (typeof msg.tokenType === 'string') authDetails.tokenType = msg.tokenType;
94
+ if (typeof msg.value === 'string' && msg.value.length > 0) {
95
+ authDetails.tokenLength = msg.value.length;
96
+ authDetails.tokenPreview = msg.value.length > 24
97
+ ? msg.value.slice(0, 12) + '…' + msg.value.slice(-10)
98
+ : msg.value;
99
+ const claims = decodeJwtClaims(msg.value);
100
+ if (claims) authDetails.jwtClaims = claims;
101
+ }
102
+ window.__concaveDevToolsPendingAuthTokenType = msg.tokenType || 'Unknown';
103
+ emitAuthEvent('client', 'Authenticate', 'success', authDetails, undefined, msg.tokenType);
104
+ }
105
+
106
+ // Track queries
107
+ if (msg.type === 'ModifyQuerySet' && msg.modifications) {
108
+ msg.modifications.forEach(mod => {
109
+ if (mod.type === 'Add') {
110
+ window.__concaveDevToolsPendingQueries.set(mod.queryId, {
111
+ queryId: mod.queryId,
112
+ udfPath: mod.udfPath,
113
+ args: mod.args,
114
+ componentPath: mod.componentPath,
115
+ startTime: now
116
+ });
117
+
118
+ window.__concaveDevToolsEvents.push({
119
+ id: 'sub-' + mod.queryId + '-' + now,
120
+ timestamp: now,
121
+ type: 'subscription',
122
+ queryId: mod.queryId,
123
+ udfPath: mod.udfPath,
124
+ args: mod.args,
125
+ componentPath: mod.componentPath,
126
+ status: 'added'
127
+ });
128
+ } else if (mod.type === 'Remove') {
129
+ const pending = window.__concaveDevToolsPendingQueries.get(mod.queryId);
130
+ window.__concaveDevToolsPendingQueries.delete(mod.queryId);
131
+ // Emit removed subscription if we have context
132
+ window.__concaveDevToolsEvents.push({
133
+ id: 'sub-' + mod.queryId + '-' + now,
134
+ timestamp: now,
135
+ type: 'subscription',
136
+ queryId: mod.queryId,
137
+ udfPath: pending ? pending.udfPath : 'unknown',
138
+ args: pending ? pending.args : [],
139
+ componentPath: pending ? pending.componentPath : undefined,
140
+ status: 'removed'
141
+ });
142
+ }
143
+ });
144
+ }
145
+
146
+ // Track mutations
147
+ if (msg.type === 'Mutation') {
148
+ window.__concaveDevToolsPendingMutations.set(msg.requestId, {
149
+ requestId: msg.requestId,
150
+ udfPath: msg.udfPath,
151
+ args: msg.args,
152
+ componentPath: msg.componentPath,
153
+ startTime: now
154
+ });
155
+ }
156
+
157
+ // Track actions
158
+ if (msg.type === 'Action') {
159
+ window.__concaveDevToolsPendingActions.set(msg.requestId, {
160
+ requestId: msg.requestId,
161
+ udfPath: msg.udfPath,
162
+ args: msg.args,
163
+ componentPath: msg.componentPath,
164
+ startTime: now
165
+ });
166
+ }
167
+ } catch (e) {
168
+ console.warn('[DevTools] Error parsing client message:', e);
169
+ }
170
+ }
171
+ return originalSend(data);
172
+ };
173
+
174
+ // Intercept message handler
175
+ const originalAddEventListener = ws.addEventListener.bind(ws);
176
+ ws.addEventListener = function(type, listener, options) {
177
+ if (type === 'message' && typeof listener === 'function') {
178
+ const wrappedListener = function(event) {
179
+ try {
180
+ const msg = JSON.parse(event.data);
181
+ const now = Date.now();
182
+
183
+ if (msg.type === 'AuthError') {
184
+ const errorDetails = {};
185
+ if (typeof msg.baseVersion === 'number') errorDetails.baseVersion = msg.baseVersion;
186
+ if (typeof msg.authUpdateAttempted === 'boolean') errorDetails.authUpdateAttempted = msg.authUpdateAttempted;
187
+ emitAuthEvent('server', 'AuthError', 'error', errorDetails, msg.error || 'Authentication failed', window.__concaveDevToolsPendingAuthTokenType || undefined);
188
+ window.__concaveDevToolsPendingAuthTokenType = null;
189
+ }
190
+
191
+ // Handle transitions (query updates)
192
+ if (msg.type === 'Transition' && msg.modifications) {
193
+ if (window.__concaveDevToolsPendingAuthTokenType) {
194
+ emitAuthEvent(
195
+ 'server',
196
+ 'Authenticated',
197
+ 'success',
198
+ { modificationCount: msg.modifications.length },
199
+ undefined,
200
+ window.__concaveDevToolsPendingAuthTokenType
201
+ );
202
+ window.__concaveDevToolsPendingAuthTokenType = null;
203
+ }
204
+ msg.modifications.forEach(mod => {
205
+ if (mod.type === 'QueryUpdated' || mod.type === 'QueryFailed') {
206
+ const pending = window.__concaveDevToolsPendingQueries.get(mod.queryId);
207
+ if (pending) {
208
+ const duration = now - pending.startTime;
209
+ window.__concaveDevToolsEvents.push({
210
+ id: 'query-' + mod.queryId + '-' + now,
211
+ timestamp: now,
212
+ type: 'query',
213
+ queryId: mod.queryId,
214
+ udfPath: pending.udfPath,
215
+ args: pending.args,
216
+ componentPath: pending.componentPath,
217
+ status: mod.type === 'QueryUpdated' ? 'success' : 'error',
218
+ result: mod.type === 'QueryUpdated' ? mod.value : undefined,
219
+ error: mod.type === 'QueryFailed' ? mod.errorMessage : undefined,
220
+ logLines: mod.logLines,
221
+ duration: duration
222
+ });
223
+
224
+ // Extract log events
225
+ if (mod.logLines && mod.logLines.length > 0) {
226
+ mod.logLines.forEach(logLine => {
227
+ const match = logLine.match(/^\\[(log|info|warn|error)\\]\\s+(.+)$/i);
228
+ const level = match ? match[1].toLowerCase() : 'log';
229
+ const message = match ? match[2] : logLine;
230
+ window.__concaveDevToolsEvents.push({
231
+ id: 'log-' + now + '-' + Math.random(),
232
+ timestamp: now,
233
+ type: 'log',
234
+ level: level,
235
+ message: message,
236
+ relatedEventId: 'query-' + mod.queryId + '-' + now
237
+ });
238
+ });
239
+ }
240
+ }
241
+ }
242
+ });
243
+ }
244
+
245
+ // Handle mutation responses
246
+ if (msg.type === 'MutationResponse') {
247
+ const pending = window.__concaveDevToolsPendingMutations.get(msg.requestId);
248
+ if (pending) {
249
+ const duration = now - pending.startTime;
250
+ window.__concaveDevToolsEvents.push({
251
+ id: 'mutation-' + msg.requestId + '-' + now,
252
+ timestamp: now,
253
+ type: 'mutation',
254
+ requestId: msg.requestId,
255
+ udfPath: pending.udfPath,
256
+ args: pending.args,
257
+ componentPath: pending.componentPath,
258
+ status: msg.success ? 'success' : 'error',
259
+ result: msg.success ? msg.result : undefined,
260
+ error: !msg.success ? msg.result : undefined,
261
+ logLines: msg.logLines,
262
+ duration: duration
263
+ });
264
+
265
+ // Extract log events
266
+ if (msg.logLines && msg.logLines.length > 0) {
267
+ msg.logLines.forEach(logLine => {
268
+ const match = logLine.match(/^\\[(log|info|warn|error)\\]\\s+(.+)$/i);
269
+ const level = match ? match[1].toLowerCase() : 'log';
270
+ const message = match ? match[2] : logLine;
271
+ window.__concaveDevToolsEvents.push({
272
+ id: 'log-' + now + '-' + Math.random(),
273
+ timestamp: now,
274
+ type: 'log',
275
+ level: level,
276
+ message: message,
277
+ relatedEventId: 'mutation-' + msg.requestId + '-' + now
278
+ });
279
+ });
280
+ }
281
+
282
+ window.__concaveDevToolsPendingMutations.delete(msg.requestId);
283
+ }
284
+ }
285
+
286
+ // Handle action responses
287
+ if (msg.type === 'ActionResponse') {
288
+ const pending = window.__concaveDevToolsPendingActions.get(msg.requestId);
289
+ if (pending) {
290
+ const duration = now - pending.startTime;
291
+ window.__concaveDevToolsEvents.push({
292
+ id: 'action-' + msg.requestId + '-' + now,
293
+ timestamp: now,
294
+ type: 'action',
295
+ requestId: msg.requestId,
296
+ udfPath: pending.udfPath,
297
+ args: pending.args,
298
+ componentPath: pending.componentPath,
299
+ status: msg.success ? 'success' : 'error',
300
+ result: msg.success ? msg.result : undefined,
301
+ error: !msg.success ? msg.result : undefined,
302
+ logLines: msg.logLines,
303
+ duration: duration
304
+ });
305
+
306
+ // Extract log events
307
+ if (msg.logLines && msg.logLines.length > 0) {
308
+ msg.logLines.forEach(logLine => {
309
+ const match = logLine.match(/^\\[(log|info|warn|error)\\]\\s+(.+)$/i);
310
+ const level = match ? match[1].toLowerCase() : 'log';
311
+ const message = match ? match[2] : logLine;
312
+ window.__concaveDevToolsEvents.push({
313
+ id: 'log-' + now + '-' + Math.random(),
314
+ timestamp: now,
315
+ type: 'log',
316
+ level: level,
317
+ message: message,
318
+ relatedEventId: 'action-' + msg.requestId + '-' + now
319
+ });
320
+ });
321
+ }
322
+
323
+ window.__concaveDevToolsPendingActions.delete(msg.requestId);
324
+ }
325
+ }
326
+ } catch (e) {
327
+ console.warn('[DevTools] Error parsing server message:', e);
328
+ }
329
+ return listener(event);
330
+ };
331
+ return originalAddEventListener('message', wrappedListener, options);
332
+ }
333
+ return originalAddEventListener(type, listener, options);
334
+ };
335
+
336
+ // Intercept onmessage assignment as well
337
+ (function(){
338
+ let currentHandler = null;
339
+ Object.defineProperty(ws, 'onmessage', {
340
+ configurable: true,
341
+ enumerable: true,
342
+ get() {
343
+ return currentHandler;
344
+ },
345
+ set(handler) {
346
+ // Remove previous wrapper if present
347
+ if ((ws).__concaveOnMessageWrapper) {
348
+ ws.removeEventListener('message', (ws).__concaveOnMessageWrapper);
349
+ }
350
+ currentHandler = handler;
351
+ if (typeof handler === 'function') {
352
+ const wrapper = function(event) {
353
+ try {
354
+ const msg = JSON.parse(event.data);
355
+ const now = Date.now();
356
+
357
+ if (msg.type === 'AuthError') {
358
+ const errorDetails = {};
359
+ if (typeof msg.baseVersion === 'number') errorDetails.baseVersion = msg.baseVersion;
360
+ if (typeof msg.authUpdateAttempted === 'boolean') errorDetails.authUpdateAttempted = msg.authUpdateAttempted;
361
+ emitAuthEvent('server', 'AuthError', 'error', errorDetails, msg.error || 'Authentication failed', window.__concaveDevToolsPendingAuthTokenType || undefined);
362
+ window.__concaveDevToolsPendingAuthTokenType = null;
363
+ }
364
+
365
+ // Mirror the same processing as in addEventListener wrapper
366
+ if (msg.type === 'Transition' && msg.modifications) {
367
+ if (window.__concaveDevToolsPendingAuthTokenType) {
368
+ emitAuthEvent(
369
+ 'server',
370
+ 'Authenticated',
371
+ 'success',
372
+ { modificationCount: msg.modifications.length },
373
+ undefined,
374
+ window.__concaveDevToolsPendingAuthTokenType
375
+ );
376
+ window.__concaveDevToolsPendingAuthTokenType = null;
377
+ }
378
+ msg.modifications.forEach(mod => {
379
+ if (mod.type === 'QueryUpdated' || mod.type === 'QueryFailed') {
380
+ const pending = window.__concaveDevToolsPendingQueries.get(mod.queryId);
381
+ if (pending) {
382
+ const duration = now - pending.startTime;
383
+ window.__concaveDevToolsEvents.push({
384
+ id: 'query-' + mod.queryId + '-' + now,
385
+ timestamp: now,
386
+ type: 'query',
387
+ queryId: mod.queryId,
388
+ udfPath: pending.udfPath,
389
+ args: pending.args,
390
+ componentPath: pending.componentPath,
391
+ status: mod.type === 'QueryUpdated' ? 'success' : 'error',
392
+ result: mod.type === 'QueryUpdated' ? mod.value : undefined,
393
+ error: mod.type === 'QueryFailed' ? mod.errorMessage : undefined,
394
+ logLines: mod.logLines,
395
+ duration: duration
396
+ });
397
+ if (mod.logLines && mod.logLines.length > 0) {
398
+ mod.logLines.forEach(logLine => {
399
+ const match = logLine.match(/^\\[(log|info|warn|error)\\]\\s+(.+)$/i);
400
+ const level = match ? match[1].toLowerCase() : 'log';
401
+ const message = match ? match[2] : logLine;
402
+ window.__concaveDevToolsEvents.push({
403
+ id: 'log-' + now + '-' + Math.random(),
404
+ timestamp: now,
405
+ type: 'log',
406
+ level: level,
407
+ message: message,
408
+ relatedEventId: 'query-' + mod.queryId + '-' + now
409
+ });
410
+ });
411
+ }
412
+ }
413
+ }
414
+ });
415
+ }
416
+ if (msg.type === 'MutationResponse') {
417
+ const pending = window.__concaveDevToolsPendingMutations.get(msg.requestId);
418
+ if (pending) {
419
+ const duration = now - pending.startTime;
420
+ window.__concaveDevToolsEvents.push({
421
+ id: 'mutation-' + msg.requestId + '-' + now,
422
+ timestamp: now,
423
+ type: 'mutation',
424
+ requestId: msg.requestId,
425
+ udfPath: pending.udfPath,
426
+ args: pending.args,
427
+ componentPath: pending.componentPath,
428
+ status: msg.success ? 'success' : 'error',
429
+ result: msg.success ? msg.result : undefined,
430
+ error: !msg.success ? msg.result : undefined,
431
+ logLines: msg.logLines,
432
+ duration: duration
433
+ });
434
+ if (msg.logLines && msg.logLines.length > 0) {
435
+ msg.logLines.forEach(logLine => {
436
+ const match = logLine.match(/^\\[(log|info|warn|error)\\]\\s+(.+)$/i);
437
+ const level = match ? match[1].toLowerCase() : 'log';
438
+ const message = match ? match[2] : logLine;
439
+ window.__concaveDevToolsEvents.push({
440
+ id: 'log-' + now + '-' + Math.random(),
441
+ timestamp: now,
442
+ type: 'log',
443
+ level: level,
444
+ message: message,
445
+ relatedEventId: 'mutation-' + msg.requestId + '-' + now
446
+ });
447
+ });
448
+ }
449
+ window.__concaveDevToolsPendingMutations.delete(msg.requestId);
450
+ }
451
+ }
452
+ if (msg.type === 'ActionResponse') {
453
+ const pending = window.__concaveDevToolsPendingActions.get(msg.requestId);
454
+ if (pending) {
455
+ const duration = now - pending.startTime;
456
+ window.__concaveDevToolsEvents.push({
457
+ id: 'action-' + msg.requestId + '-' + now,
458
+ timestamp: now,
459
+ type: 'action',
460
+ requestId: msg.requestId,
461
+ udfPath: pending.udfPath,
462
+ args: pending.args,
463
+ componentPath: pending.componentPath,
464
+ status: msg.success ? 'success' : 'error',
465
+ result: msg.success ? msg.result : undefined,
466
+ error: !msg.success ? msg.result : undefined,
467
+ logLines: msg.logLines,
468
+ duration: duration
469
+ });
470
+ if (msg.logLines && msg.logLines.length > 0) {
471
+ msg.logLines.forEach(logLine => {
472
+ const match = logLine.match(/^\\[(log|info|warn|error)\\]\\s+(.+)$/i);
473
+ const level = match ? match[1].toLowerCase() : 'log';
474
+ const message = match ? match[2] : logLine;
475
+ window.__concaveDevToolsEvents.push({
476
+ id: 'log-' + now + '-' + Math.random(),
477
+ timestamp: now,
478
+ type: 'log',
479
+ level: level,
480
+ message: message,
481
+ relatedEventId: 'action-' + msg.requestId + '-' + now
482
+ });
483
+ });
484
+ }
485
+ window.__concaveDevToolsPendingActions.delete(msg.requestId);
486
+ }
487
+ }
488
+ } catch (e) {
489
+ console.warn('[DevTools] Error parsing server message (onmessage):', e);
490
+ }
491
+ if (typeof handler === 'function') {
492
+ handler.call(ws, event);
493
+ }
494
+ };
495
+ (ws).__concaveOnMessageWrapper = wrapper;
496
+ ws.addEventListener('message', wrapper);
497
+ } else {
498
+ (ws).__concaveOnMessageWrapper = null;
499
+ }
500
+ }
501
+ });
502
+ })();
503
+
504
+ return ws;
505
+ };
506
+
507
+ // Preserve prototype chain
508
+ Object.setPrototypeOf(window.WebSocket, OriginalWebSocket);
509
+ Object.defineProperty(window.WebSocket, 'prototype', {
510
+ value: OriginalWebSocket.prototype,
511
+ writable: false,
512
+ configurable: false
513
+ });
514
+
515
+ console.log('[DevTools] WebSocket interceptor installed');
516
+ })();
517
+ <\/script>
518
+ `, d = `
519
+ <script>
520
+ window.__concaveDevToolsConfig = ${JSON.stringify({ position: r, autoInit: !0 })};
521
+ <\/script>
522
+ `, c = `
523
+ <script type="module">
524
+ import { initDevTools } from '/@fs${s.resolve(g, "../client.tsx").replace(/\\/g, "/")}';
525
+ <\/script>
526
+ `, o = n + d + c;
527
+ return e.includes("</head>") ? e.replace("</head>", `${o}</head>`) : e.includes("</body>") ? e.replace("</body>", `${o}</body>`) : e + o;
528
+ }
529
+ },
530
+ // Ensure devtools dependencies are optimized
531
+ config(e) {
532
+ var n;
533
+ return {
534
+ optimizeDeps: {
535
+ include: [...((n = e.optimizeDeps) == null ? void 0 : n.include) || [], "react", "react-dom"]
536
+ }
537
+ };
538
+ }
539
+ };
540
+ }
541
+ export {
542
+ p as concaveDevTools,
543
+ p as default
544
+ };
package/package.json ADDED
@@ -0,0 +1,62 @@
1
+ {
2
+ "name": "@concavejs/devtools",
3
+ "version": "0.0.1-alpha.4",
4
+ "license": "FSL-1.1-Apache-2.0",
5
+ "publishConfig": {
6
+ "access": "public"
7
+ },
8
+ "type": "module",
9
+ "main": "./dist/index.js",
10
+ "types": "./dist/index.d.ts",
11
+ "exports": {
12
+ ".": {
13
+ "types": "./dist/index.d.ts",
14
+ "default": "./dist/index.js"
15
+ },
16
+ "./vite": {
17
+ "types": "./dist/vite-plugin/index.d.ts",
18
+ "default": "./dist/vite-plugin.js"
19
+ },
20
+ "./client": {
21
+ "types": "./dist/client.d.ts",
22
+ "default": "./dist/client.js"
23
+ }
24
+ },
25
+ "files": [
26
+ "dist"
27
+ ],
28
+ "scripts": {
29
+ "sync:version": "node scripts/sync-extension-version.mjs",
30
+ "build": "vite build && tsc --emitDeclarationOnly",
31
+ "build:standalone": "vite build --config vite.config.standalone.ts",
32
+ "build:page-agent": "vite build --config vite.config.page-agent.ts",
33
+ "build:panel": "vite build --config vite.config.panel.ts",
34
+ "build:extension": "bun run sync:version && bun run build:standalone && cp dist-standalone/devtools.js extension/devtools.js && bun run build:panel",
35
+ "build:all": "bun run build && bun run build:extension",
36
+ "sync:icons": "cp ../brand/assets/icon-16.png extension/icons/icon16.png && cp ../brand/assets/icon-48.png extension/icons/icon48.png && cp ../brand/assets/icon-128.png extension/icons/icon128.png",
37
+ "dev": "tsc --watch",
38
+ "type-check": "tsc --noEmit"
39
+ },
40
+ "dependencies": {
41
+ "@concavejs/brand": "0.0.1-alpha.4",
42
+ "@concavejs/core": "0.0.1-alpha.4"
43
+ },
44
+ "peerDependencies": {
45
+ "react": "^18.0.0",
46
+ "react-dom": "^18.0.0",
47
+ "vite": "^5.0.0"
48
+ },
49
+ "devDependencies": {
50
+ "@tailwindcss/vite": "^4.1.18",
51
+ "@types/node": "^20.0.0",
52
+ "@types/react": "^18.2.0",
53
+ "@types/react-dom": "^18.2.0",
54
+ "@vitejs/plugin-react": "^4.2.0",
55
+ "react": "^18.2.0",
56
+ "react-dom": "^18.2.0",
57
+ "tailwindcss": "^4.1.18",
58
+ "terser": "^5.46.0",
59
+ "typescript": "^5.3.0",
60
+ "vite": "^5.0.0"
61
+ }
62
+ }