Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 4 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
"description": "Qwik devtools monorepo",
"scripts": {
"dev": "pnpm --filter plugin build && MODE=dev pnpm --parallel dev",
"playground": "MODE=dev pnpm --filter playground dev",
"playground": "MODE=dev DEBUG=qwik:devtools:* pnpm --filter playground dev",
"build": "tsx scripts/build-devtools.ts",
"change": "changeset",
"release": "changeset publish",
Expand All @@ -17,7 +17,9 @@
"@types/node": "^22.10.5",
"tsdown": "^0.9.6",
"tsx": "^4.19.2",
"vitest": "^3.2.4"
"vitest": "^3.2.4",
"debug": "4.4.3",
"@types/debug": "4.1.12"
},
"private": true,
"keywords": [
Expand Down
1 change: 0 additions & 1 deletion packages/playgrounds/src/root.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@ import {
} from '@qwik.dev/router';
import { RouterHead } from './components/router-head/router-head';
import './global.css';
import '../../devtools/dist/ui/style.css';
export default component$(() => {
/**
* The root of a QwikRouter site always start with the <QwikRouterProvider> component,
Expand Down
7 changes: 4 additions & 3 deletions packages/plugin/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,9 @@ import useCollectHooksSource from './utils/useCollectHooks'
import { parseQwikCode } from './parse/parse';
import { startPreloading } from './npm/index';
import updateConf from './utils/updateConf';
import {debug} from 'debug'


const log = debug('qwik:devtools:plugin');
export function qwikDevtools(): Plugin[] {
let _config: ResolvedConfig;
const qwikData = new Map<string, any>();
Expand Down Expand Up @@ -47,7 +48,7 @@ export function qwikDevtools(): Plugin[] {
if (!preloadStarted) {
preloadStarted = true;
startPreloading({ config: _config }).catch((err) => {
console.error('[Qwik DevTools] Failed to start preloading:', err);
log('[Qwik DevTools] Failed to start preloading:', err);
});
}
},
Expand All @@ -62,7 +63,7 @@ export function qwikDevtools(): Plugin[] {
const importLine = `import { ${INNER_USE_HOOK} } from '${VIRTUAL_QWIK_DEVTOOLS_KEY}';\n`
code = importLine + code
}else {
console.log('importing virtual qwik devtools', VIRTUAL_QWIK_DEVTOOLS_KEY, code);
log('importing virtual qwik devtools', VIRTUAL_QWIK_DEVTOOLS_KEY, code);
}
code = parseQwikCode(code, {path: id})
}
Expand Down
7 changes: 5 additions & 2 deletions packages/plugin/src/inspect/index.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
import fs from 'node:fs/promises'
import { parseQwikCode } from "../parse/parse";
import { ServerContext } from "../types";
import {debug} from 'debug'

const log = debug('qwik:devtools:inspect');
const codeStringCache = new Map<string, ReturnType<typeof parseQwikCode>>()

function parseCodeWithCache(code: string) {
Expand Down Expand Up @@ -41,7 +44,7 @@ export function getModulesContent(ctx: ServerContext) {
modules
};
} catch (error) {
console.log(`Failed to transform request for ${pathId}:`, error);
log(`Failed to transform request for ${pathId}:`, error);
return {
pathId,
modules: null,
Expand Down Expand Up @@ -98,7 +101,7 @@ export function getModulesContent(ctx: ServerContext) {

return []
} catch (error) {
console.error(`Failed to parse qwik code for ${pathId}:`, error);
log(`Failed to parse qwik code for ${pathId}:`, error);
return []
}

Expand Down
28 changes: 15 additions & 13 deletions packages/plugin/src/npm/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,9 @@ import fsp from 'node:fs/promises';
import { NpmInfo } from '@devtools/kit';
import { execSync } from 'child_process';
import path from 'path';
import {debug} from 'debug'

const log = debug('qwik:devtools:npm');
// In-memory cache for npm package information
interface CacheEntry {
data: any;
Expand Down Expand Up @@ -100,17 +102,17 @@ export async function detectPackageManager(
// Preload dependencies function - moved to module scope
const preloadDependencies = async (config: any): Promise<any[]> => {
if (preloadedDependencies) {
console.log('[Qwik DevTools] Dependencies already preloaded');
log('[Qwik DevTools] Dependencies already preloaded');
return preloadedDependencies;
}

if (isPreloading && preloadPromise) {
console.log('[Qwik DevTools] Preloading already in progress...');
log('[Qwik DevTools] Preloading already in progress...');
return preloadPromise;
}

isPreloading = true;
console.log('[Qwik DevTools] Starting to preload dependencies...');
log('[Qwik DevTools] Starting to preload dependencies...');

preloadPromise = (async () => {
const startDir = getProjectStartDirFromConfig(config);
Expand All @@ -119,7 +121,7 @@ const preloadDependencies = async (config: any): Promise<any[]> => {
if (!pathToPackageJson) {
preloadedDependencies = [];
isPreloading = false;
console.log('[Qwik DevTools] No package.json found');
log('[Qwik DevTools] No package.json found');
return [];
}

Expand Down Expand Up @@ -163,7 +165,7 @@ const preloadDependencies = async (config: any): Promise<any[]> => {

const fetchedPackages: any[] = [];

console.log(`[Qwik DevTools] Fetching ${uncachedDependencies.length} packages in parallel...`);
log(`[Qwik DevTools] Fetching ${uncachedDependencies.length} packages in parallel...`);

const allBatchPromises = batches.map(async (batch) => {
const batchPromises = batch.map(async ([name, version]) => {
Expand Down Expand Up @@ -253,11 +255,11 @@ const preloadDependencies = async (config: any): Promise<any[]> => {
preloadedDependencies = allPackages;
isPreloading = false;

console.log(`[Qwik DevTools] ✓ Successfully preloaded ${allPackages.length} dependencies`);
log(`[Qwik DevTools] ✓ Successfully preloaded ${allPackages.length} dependencies`);

return allPackages;
} catch (error) {
console.error('[Qwik DevTools] ✗ Failed to preload dependencies:', error);
log('[Qwik DevTools] ✗ Failed to preload dependencies:', error);
preloadedDependencies = [];
isPreloading = false;
return [];
Expand All @@ -270,14 +272,14 @@ const preloadDependencies = async (config: any): Promise<any[]> => {
// Export function to start preloading from plugin initialization
export async function startPreloading({ config }: { config: any }) {
const startTime = Date.now();
console.log('[Qwik DevTools] 🚀 Initiating dependency preload (background)...');
log('[Qwik DevTools] 🚀 Initiating dependency preload (background)...');

// Start preloading in background, don't wait for it
preloadDependencies(config).then(() => {
const duration = ((Date.now() - startTime) / 1000).toFixed(2);
console.log(`[Qwik DevTools] ⚡ Preload completed in ${duration}s`);
log(`[Qwik DevTools] ⚡ Preload completed in ${duration}s`);
}).catch((err) => {
console.error('[Qwik DevTools] ✗ Preload failed:', err);
log('[Qwik DevTools] ✗ Preload failed:', err);
});

// Return immediately, don't block
Expand Down Expand Up @@ -305,18 +307,18 @@ export function getNpmFunctions({ config }: ServerContext) {
async getAllDependencies(): Promise<any[]> {
// Return preloaded data immediately if available
if (preloadedDependencies) {
console.log('[Qwik DevTools] Returning preloaded dependencies');
log('[Qwik DevTools] Returning preloaded dependencies');
return preloadedDependencies;
}

// If preloading is in progress, wait for it
if (isPreloading && preloadPromise) {
console.log('[Qwik DevTools] Waiting for preload to complete...');
log('[Qwik DevTools] Waiting for preload to complete...');
return preloadPromise;
}

// If preloading hasn't started (shouldn't happen), start it now
console.log('[Qwik DevTools] Warning: Preload not started, starting now...');
log('[Qwik DevTools] Warning: Preload not started, starting now...');
return preloadDependencies(config);
},

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -88,7 +88,7 @@ export const DevtoolsButton = component$(({ state }: DevtoolsButtonProps) => {
<div
ref={elementRef}
class={{
'fixed flex h-9 w-9 origin-center select-none items-center justify-center rounded-lg border border-border bg-background backdrop-blur-md':
'border-border bg-background fixed flex h-9 w-9 origin-center select-none items-center justify-center rounded-lg border backdrop-blur-md':
true,
'border-accent/50 bg-background/95 shadow-accent/35 rotate-90 shadow-lg':
state.isOpen.value && !isDragging.value,
Expand Down
2 changes: 1 addition & 1 deletion packages/ui/src/components/DevtoolsPanel/DevtoolsPanel.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ export const DevtoolsPanel = component$(({ state }: DevtoolsPanelProps) => {
return (
<div
ref={panelRef}
class="fixed bottom-6 right-6 flex h-[calc(100vh-3rem)] w-[calc(100vw-3rem)] translate-y-0 transform overflow-hidden rounded-lg border-2 border-border bg-background text-foreground backdrop-blur-lg transition-transform duration-300 ease-in-out"
class="border-border bg-background text-foreground fixed bottom-6 right-6 flex h-[calc(100vh-3rem)] w-[calc(100vw-3rem)] translate-y-0 transform overflow-hidden rounded-lg border-2 backdrop-blur-lg transition-transform duration-300 ease-in-out"
>
<Slot />
</div>
Expand Down
2 changes: 1 addition & 1 deletion packages/ui/src/components/Tab/Tab.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ export const Tab = component$<TabProps>(({ state, id, title }) => {
class={{
'flex h-10 w-10 items-center justify-center rounded-lg p-2.5 transition-all duration-200':
true,
'bg-transparent hover:bg-foreground/5 text-muted-foreground hover:text-foreground':
'hover:bg-foreground/5 text-muted-foreground hover:text-foreground bg-transparent':
state.activeTab !== id,
'shadow-accent/35 bg-accent text-white shadow-lg':
state.activeTab === id,
Expand Down
2 changes: 1 addition & 1 deletion packages/ui/src/components/TabContent/TabContent.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import { component$, Slot } from '@qwik.dev/core';
export const TabContent = component$(() => {
return (
<div class="flex h-full w-full flex-col space-y-6">
<div class="flex items-center justify-between border-b border-border pb-4">
<div class="border-border flex items-center justify-between border-b pb-4">
<Slot name="title" />
</div>

Expand Down
2 changes: 1 addition & 1 deletion packages/ui/src/components/ThemeToggle/QwikThemeToggle.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ export const QwikThemeToggle = component$(() => {
<>
<button
onClick$={onClick$}
class="group relative flex h-8 w-8 items-center justify-center rounded-md bg-background text-foreground hover:opacity-60"
class="bg-background text-foreground group relative flex h-8 w-8 items-center justify-center rounded-md hover:opacity-60"
>
<div class="absolute inset-0 grid place-items-center transition-transform duration-200 ease-out group-hover:scale-110 group-active:scale-75">
<HiSunOutline class="themeIcon light col-start-1 row-start-1" />
Expand Down
2 changes: 1 addition & 1 deletion packages/ui/src/components/Tree/Tree.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -83,7 +83,7 @@ const TreeNodeComponent = component$(
<div class={`inline-flex items-center rounded-md px-2 py-1`}>
{hasChildren ? (
<HiChevronUpMini
class={`mr-2 h-4 w-4 flex-shrink-0 text-muted-foreground transition-transform duration-200 ${
class={`text-muted-foreground mr-2 h-4 w-4 flex-shrink-0 transition-transform duration-200 ${
isExpanded.value ? 'rotate-90' : 'rotate-180'
}`}
/>
Expand Down
22 changes: 12 additions & 10 deletions packages/ui/src/devtools.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,7 @@ import {
HiPhotoOutline,
HiMegaphoneMini,
HiCubeOutline,

HiCodeBracketSolid
HiCodeBracketSolid,
} from '@qwikest/icons/heroicons';
import { BsDiagram3 } from '@qwikest/icons/bootstrap';
import { LuFolderTree } from '@qwikest/icons/lucide';
Expand Down Expand Up @@ -41,6 +40,9 @@ import { Inspect } from './features/inspect/Inspect';
import { QwikThemeToggle } from './components/ThemeToggle/QwikThemeToggle';
import { ThemeScript as QwikThemeScript } from './components/ThemeToggle/theme-script';
import { CodeBreack } from './features/CodeBreack/CodeBreack';
import { debug } from 'debug';

const log = debug('qwik:devtools:devtools');
function getClientRpcFunctions() {
return {
healthCheck: () => true,
Expand Down Expand Up @@ -81,7 +83,7 @@ export const QwikDevtools = component$(() => {
const assets = await rpc.getAssetsFromPublicDir();
state.assets = assets;
} catch (error) {
console.error('Failed to load assets:', error);
log('Failed to load assets:', error);
}
});

Expand All @@ -93,7 +95,7 @@ export const QwikDevtools = component$(() => {
const components = await rpc.getComponents();
state.components = components;
} catch (error) {
console.error('Failed to load components:', error);
log('Failed to load components:', error);
}
});

Expand Down Expand Up @@ -122,7 +124,7 @@ export const QwikDevtools = component$(() => {

state.routes = noSerialize(values);
} catch (error) {
console.error('Failed to load routes:', error);
log('Failed to load routes:', error);
}
});

Expand All @@ -134,7 +136,7 @@ export const QwikDevtools = component$(() => {
const qwikPackages = await rpc.getQwikPackages();
state.npmPackages = qwikPackages;
} catch (error) {
console.error('Failed to load Qwik packages:', error);
log('Failed to load Qwik packages:', error);
}
});

Expand All @@ -147,7 +149,7 @@ export const QwikDevtools = component$(() => {
const allDeps = await rpc.getAllDependencies();
state.allDependencies = allDeps;
} catch (error) {
console.error('Failed to load all dependencies:', error);
log('Failed to load all dependencies:', error);
} finally {
state.isLoadingDependencies = false;
}
Expand All @@ -161,7 +163,7 @@ export const QwikDevtools = component$(() => {

{state.isOpen.value && (
<DevtoolsPanel state={state}>
<div class="bg-background/95 flex flex-col gap-2 border-r border-border p-3">
<div class="bg-background/95 border-border flex flex-col gap-2 border-r p-3">
<Tab state={state} id="overview" title="Overview">
<HiBoltOutline class="h-5 w-5" />
</Tab>
Expand All @@ -181,7 +183,7 @@ export const QwikDevtools = component$(() => {
<HiMegaphoneMini class="h-5 w-5" />
</Tab>
<Tab state={state} id="codeBreack" title="codeBreack">
< HiCodeBracketSolid class="h-5 w-5" />
<HiCodeBracketSolid class="h-5 w-5" />
</Tab>
<div class="mt-auto">
<QwikThemeToggle />
Expand All @@ -207,7 +209,7 @@ export const QwikDevtools = component$(() => {
{state.activeTab === 'assets' && (
<TabContent>
<TabTitle title="Public Assets" q:slot="title" />
<div class="flex gap-4 text-sm text-muted-foreground">
<div class="text-muted-foreground flex gap-4 text-sm">
<span>
Total Size:{' '}
{(
Expand Down
6 changes: 3 additions & 3 deletions packages/ui/src/features/Assets/Assets.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ export const Assets = component$(({ state }: AssetsProps) => {
return (
<div
key={asset.filePath}
class="overflow-hidden rounded-xl border border-border bg-card-item-bg transition-all duration-200 hover:bg-card-item-hover-bg"
class="border-border bg-card-item-bg hover:bg-card-item-hover-bg overflow-hidden rounded-xl border transition-all duration-200"
>
{isImage ? (
<div class="aspect-square overflow-hidden bg-black/20">
Expand All @@ -29,7 +29,7 @@ export const Assets = component$(({ state }: AssetsProps) => {
</div>
) : (
<div class="flex aspect-square items-center justify-center bg-black/20">
<span class="font-mono text-2xl text-muted-foreground">
<span class="text-muted-foreground font-mono text-2xl">
{fileExt}
</span>
</div>
Expand All @@ -38,7 +38,7 @@ export const Assets = component$(({ state }: AssetsProps) => {
<div class="truncate text-sm" title={asset.path}>
{asset.path.split('/').pop()}
</div>
<div class="flex items-center justify-between text-xs text-muted-foreground">
<div class="text-muted-foreground flex items-center justify-between text-xs">
<span>{(asset.size / 1024).toFixed(2)} KB</span>
<span class="bg-foreground/5 rounded-full px-2 py-1">
{fileExt}
Expand Down
17 changes: 10 additions & 7 deletions packages/ui/src/features/CodeBreack/CodeBreack.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -22,28 +22,31 @@ export const CodeBreack = component$(() => {

const currentTab = useSignal<ParserTab>('state');


return (
<div class="space-y-6 h-full overflow-hidden">
<div class="h-full space-y-6 overflow-hidden">
{/* Segmented Navigation */}
<div class="flex justify-center">
<div class="inline-flex rounded-xl border border-border bg-background p-0.5">
<div class="border-border bg-background inline-flex rounded-xl border p-0.5">
<button
onClick$={() => (currentTab.value = 'state')}
class={{
'px-3 md:px-4 py-2 rounded-lg text-sm font-medium transition-colors': true,
'rounded-lg px-3 py-2 text-sm font-medium transition-colors md:px-4':
true,
'bg-accent text-white shadow': currentTab.value === 'state',
'text-muted-foreground hover:bg-foreground/5': currentTab.value !== 'state',
'text-muted-foreground hover:bg-foreground/5':
currentTab.value !== 'state',
}}
>
State Parser
</button>
<button
onClick$={() => (currentTab.value = 'html')}
class={{
'px-3 md:px-4 py-2 rounded-lg text-sm font-medium transition-colors': true,
'rounded-lg px-3 py-2 text-sm font-medium transition-colors md:px-4':
true,
'bg-accent text-white shadow': currentTab.value === 'html',
'text-muted-foreground hover:bg-foreground/5': currentTab.value !== 'html',
'text-muted-foreground hover:bg-foreground/5':
currentTab.value !== 'html',
}}
>
HTML Parser
Expand Down
Loading
Loading