Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: debug page of module mutation #770

Draft
wants to merge 6 commits into
base: main
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
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
5 changes: 5 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,12 @@
},
"resolutions": {
"@nuxt/devtools": "workspace:*",
"@nuxt/kit": "file:../nuxt/packages/kit",
"@nuxt/schema": "file:../nuxt/packages/schema",
"@nuxt/vite-builder": "file:../nuxt/packages/vite",
"esbuild": "catalog:",
"jiti": "catalog:",
"nuxt": "file:../nuxt/packages/nuxt",
"typescript": "catalog:",
"vite": "catalog:",
"vue-tsc": "catalog:"
Expand Down
6 changes: 5 additions & 1 deletion packages/devtools-kit/src/_types/client-api.ts
Original file line number Diff line number Diff line change
Expand Up @@ -117,9 +117,13 @@ export interface NuxtDevtoolsHostClient {
syncClient: () => NuxtDevtoolsHostClient
}

export interface CodeHighlightOptions {
grammarContextCode?: string
}

export interface NuxtDevtoolsClient {
rpc: BirpcReturn<ServerFunctions, ClientFunctions>
renderCodeHighlight: (code: string, lang?: BuiltinLanguage) => {
renderCodeHighlight: (code: string, lang?: BuiltinLanguage, options?: CodeHighlightOptions) => {
code: string
supported: boolean
}
Expand Down
3 changes: 2 additions & 1 deletion packages/devtools-kit/src/_types/rpc.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,13 +6,14 @@ import type { AnalyzeBuildsInfo } from './analyze-build'
import type { ModuleCustomTab } from './custom-tabs'
import type { AssetEntry, AssetInfo, AutoImportsWithMetadata, ComponentRelationship, HookInfo, ImageMeta, NpmCommandOptions, NpmCommandType, PackageUpdateInfo, ScannedNitroTasks, ServerRouteInfo } from './integrations'
import type { ModuleOptions, NuxtDevToolsOptions } from './options'
import type { InstallModuleReturn } from './server-ctx'
import type { InstallModuleReturn, ServerDebugContext } from './server-ctx'
import type { TerminalAction, TerminalInfo } from './terminals'
import type { GetWizardArgs, WizardActions } from './wizard'

export interface ServerFunctions {
// Static RPCs (can be provide on production build in the future)
getServerConfig: () => NuxtOptions
getServerDebugContext: () => Promise<ServerDebugContext | undefined>
getServerData: (token: string) => Promise<NuxtServerData>
getServerRuntimeConfig: () => Record<string, any>
getModuleOptions: () => ModuleOptions
Expand Down
8 changes: 7 additions & 1 deletion packages/devtools-kit/src/_types/server-ctx.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import type { BirpcGroup } from 'birpc'
import type { Nuxt } from 'nuxt/schema'
import type { Nuxt, NuxtDebugModuleMutationRecord } from 'nuxt/schema'
import type { ModuleOptions } from './options'
import type { ClientFunctions, ServerFunctions } from './rpc'

Expand Down Expand Up @@ -42,3 +42,9 @@ export interface InstallModuleReturn {
commands: string[]
processId: string
}

export type ServerDebugModuleMutationRecord = (Omit<NuxtDebugModuleMutationRecord, 'module'> & { name: string })

export interface ServerDebugContext {
moduleMutationRecords: ServerDebugModuleMutationRecord[]
}
21 changes: 21 additions & 0 deletions packages/devtools-ui-kit/src/components/NBadgeHashed.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
<script setup lang="ts">
import { computed } from 'vue'
import { getHslColorFromStringHash } from '../composables/color'
import NBadge from './NBadge.vue'

const props = defineProps<{
text: string
}>()

const color = computed(() => {
const foreground = getHslColorFromStringHash(props.text, 50, 60)
const background = getHslColorFromStringHash(props.text, 50, 60, 0.05)
return { color: foreground, background }
})
</script>

<template>
<NBadge :style="color">
{{ text }}<slot />
</NBadge>
</template>
3 changes: 2 additions & 1 deletion packages/devtools-ui-kit/src/components/NCodeBlock.vue
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ const props = withDefaults(
lang?: BuiltinLanguage | 'text'
lines?: boolean
inline?: boolean
grammarContextCode?: string
transformRendered?: (code: string) => string
}>(),
{
Expand All @@ -22,7 +23,7 @@ const emit = defineEmits(['loaded'])
const rendered = computed(() => {
const result = props.lang === 'text'
? { code: props.code, supported: false }
: devToolsClient.value?.devtools.renderCodeHighlight(props.code, props.lang) || { code: props.code, supported: false }
: devToolsClient.value?.devtools.renderCodeHighlight(props.code, props.lang, { grammarContextCode: props.grammarContextCode }) || { code: props.code, supported: false }
if (result.supported && props.transformRendered)
result.code = props.transformRendered(result.code)
if (result.supported)
Expand Down
7 changes: 7 additions & 0 deletions packages/devtools-ui-kit/src/composables/color.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
export function getHslColorFromStringHash(name: string, saturation = 65, lightness = 50, opacity: number | string = 1) {
let hash = 0
for (let i = 0; i < name.length; i++)
hash = name.charCodeAt(i) + ((hash << 5) - hash)
const h = hash % 360
return `hsla(${h}, ${saturation}%, ${lightness}%, ${opacity})`
}
5 changes: 1 addition & 4 deletions packages/devtools-ui-kit/src/module.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ export interface ModuleOptions {

export default defineNuxtModule<ModuleOptions>({
meta: {
name: 'devtools-ui-kit',
name: '@nuxt/devtools-ui-kit',
configKey: 'devtoolsUIKit',
},
defaults: {
Expand All @@ -35,9 +35,6 @@ export default defineNuxtModule<ModuleOptions>({
if (!options.dev)
nuxt.options.unocss = extendUnocssOptions(nuxt.options.unocss)

// eslint-disable-next-line ts/ban-ts-comment
// @ts-ignore - module options
nuxt.options.vueuse = nuxt.options.vueuse || {}
// eslint-disable-next-line ts/ban-ts-comment
// @ts-ignore - module options
nuxt.options.colorMode = defu(nuxt.options.colorMode, { classSuffix: '' })
Expand Down
12 changes: 6 additions & 6 deletions packages/devtools/client/components/BuildAnalyzeDetails.vue
Original file line number Diff line number Diff line change
Expand Up @@ -56,18 +56,18 @@ async function clear(name: string) {
<button
px4 py2 border="r base"
hover="bg-active"
:class="tab.id === selectedTab.id ? '' : 'border-b'"
:class="tab.id === selectedTab?.id ? '' : 'border-b'"
@click="selectedTab = tab"
>
<div :class="tab.id === selectedTab.id ? '' : 'op30' ">
<div :class="tab.id === selectedTab?.id ? '' : 'op30' ">
{{ tab.name }}
</div>
</button>
</template>
<div border="b base" flex-auto />
</div>
<div
v-if="selectedTab.id === 'overview'"
v-if="selectedTab?.id === 'overview'"
flex="~ col gap-4 items-center justify-center" p4
>
<div flex-auto />
Expand Down Expand Up @@ -125,17 +125,17 @@ async function clear(name: string) {
</NButton>
</div>
<iframe
v-lazy-show="selectedTab.id === 'bundle-client'"
v-lazy-show="selectedTab?.id === 'bundle-client'"
:src="`${ROUTE_ANALYZE}${current.slug}/client.html`"
h-full w-full
/>
<iframe
v-lazy-show="selectedTab.id === 'bundle-nitro'"
v-lazy-show="selectedTab?.id === 'bundle-nitro'"
:src="`${ROUTE_ANALYZE}${current.slug}/nitro.html`"
h-full w-full
/>
<iframe
v-lazy-show="selectedTab.id === 'vite-inspect'"
v-lazy-show="selectedTab?.id === 'vite-inspect'"
:src="`${ROUTE_ANALYZE}${current.slug}/.vite-inspect/`"
h-full w-full
/>
Expand Down
133 changes: 133 additions & 0 deletions packages/devtools/client/components/DebugModuleMutationRecords.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,133 @@
<script setup lang="ts">
import type { ServerDebugModuleMutationRecord } from '@nuxt/devtools-kit/types'
import { computed, ref } from 'vue'

const props = defineProps<{
moduleMutationRecords: ServerDebugModuleMutationRecord[]
}>()

function isPath(path: string) {
return path.startsWith('/') || path.match(/^[a-z]:[\\/]/i)
}

// const search = ref('')
const showBuiltin = ref(false)
const showTemplates = ref(false)
const showTranspile = ref(false)
const showPlugins = ref(false)
const showEmptyInitial = ref(false)
const moduleFilter = ref('')

const items = computed(() => {
let arr = props.moduleMutationRecords
if (!showBuiltin.value) {
arr = arr.filter(i => !i.name.startsWith('nuxt:') && i.name !== '@nuxt/devtools')
}
if (!showTemplates.value) {
arr = arr.filter(i => i.keys.join('.') !== 'build.templates')
}
if (!showTranspile.value) {
arr = arr.filter(i => i.keys.join('.') !== 'build.transpile')
}
if (!showPlugins.value) {
arr = arr.filter(i => i.keys.join('.') !== 'plugins')
}
if (!showEmptyInitial.value) {
arr = arr.filter(i => i.method || (i.value !== '[]' && i.value !== '{}'))
}
if (moduleFilter.value) {
arr = arr.filter(i => i.name === moduleFilter.value)
}
return arr
})
</script>

<template>
<div flex="~ gap-2 col" mb4>
<!-- <NTextInput v-model="search" placeholder="Search" w-full /> -->
<div flex="~ gap-3 items-center">
<NCheckbox v-model="showBuiltin" n="primary">
<span ws-nowrap op75>Builtin Modules</span>
</NCheckbox>
<NCheckbox v-model="showTemplates" n="primary">
<span ws-nowrap op75>Templates</span>
</NCheckbox>
<NCheckbox v-model="showTranspile" n="primary">
<span ws-nowrap op75>Transpile</span>
</NCheckbox>
<NCheckbox v-model="showPlugins" n="primary">
<span ws-nowrap op75>Plugins</span>
</NCheckbox>
<NCheckbox v-model="showEmptyInitial" n="primary">
<span ws-nowrap op75>Empty Initial</span>
</NCheckbox>
<div v-if="moduleFilter" flex="~ gap-1" items-center p1 border="~ base rounded">
<NBadgeHashed font-mono :text="moduleFilter" />
<NButton icon="carbon-close" :border="false" @click="moduleFilter = ''" />
</div>
</div>
</div>
<table max-w-full of-auto>
<thead border="b base">
<tr>
<th ws-nowrap p1 text-center font-bold>
Index
</th>
<th ws-nowrap p1 text-center font-bold>
Module
</th>
<th ws-nowrap p1 text-center font-bold>
Key Path
</th>
<th ws-nowrap p1 text-center font-bold>
Method
</th>
<th ws-nowrap p1 text-center font-bold>
Value
</th>
</tr>
</thead>
<tbody>
<tr
v-for="record of items"
:key="moduleMutationRecords.indexOf(record)"
border="b dashed transparent hover:base"
>
<td text-center op50>
<div>{{ moduleMutationRecords.indexOf(record) + 1 }}</div>
</td>
<td>
<FilepathItem v-if="record.name && isPath(record.name)" :filepath="record.name" />
<NBadgeHashed
v-else
role="button" font-mono
:text="record.name"
@click="moduleFilter = record.name"
/>
</td>
<td>
<code flex="~" px4>
<template v-for="key, idy of record.keys" :key="idy">
<span>{{ key }}</span>
<span v-if="idy < record.keys.length - 1" op50>
.
</span>
</template>
</code>
</td>
<td px2 text-center>
<NBadgeHashed font-mono :text="record.method || '='" :class="record.method ? '' : 'saturate-0'" />
</td>
<td of-auto>
<NCodeBlock
:code="String(record.value)"
lang="ts"
grammar-context-code="let a = "
ws-normal break-all py1
:lines="false" :inline="true"
/>
</td>
</tr>
</tbody>
</table>
</template>
2 changes: 1 addition & 1 deletion packages/devtools/client/components/HooksTable.vue
Original file line number Diff line number Diff line change
Expand Up @@ -92,7 +92,7 @@ function toggleSortedBy(by: SortBy) {
<td w-0 ws-nowrap text-center text-sm op25>
{{ startTimes.indexOf(item.start) }}
</td>
<td w-0 ws-nowrap text-right :style="{ color: getHashColorFromString(getNamePrefix(item.name)) }">
<td w-0 ws-nowrap text-right :style="{ color: getHslColorFromStringHash(getNamePrefix(item.name)) }">
<code text-sm>{{ getNamePrefix(item.name) }}</code>
</td>
<td ws-nowrap>
Expand Down
6 changes: 3 additions & 3 deletions packages/devtools/client/components/TimelineItemFunction.vue
Original file line number Diff line number Diff line change
@@ -1,15 +1,15 @@
<script setup lang="ts">
import type { TimelineEventFunction } from '../../types'
import { computed } from 'vue'
import { getHashColorFromString } from '~/composables/utils'
import { getHslColorFromStringHash } from '~/composables/utils'

const props = defineProps<{
item: TimelineEventFunction
}>()

const colorRaw = computed(() => getHashColorFromString(props.item.name, 50, 60, '_op_'))
const colorRaw = computed(() => getHslColorFromStringHash(props.item.name, 50, 60, '_op_'))
const color = computed(() => colorRaw.value.replace(/_op_/, '1'))
const textColor = computed(() => getHashColorFromString(props.item.name, 50, 40))
const textColor = computed(() => getHslColorFromStringHash(props.item.name, 50, 40))
const colorBackground = computed(() => colorRaw.value.replace(/_op_/, '0.2'))
</script>

Expand Down
2 changes: 1 addition & 1 deletion packages/devtools/client/components/TimelineList.vue
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ const emit = defineEmits<{
font-mono
:style="{
color: event.type === 'function'
? getHashColorFromString(event.name, 50, 60)
? getHslColorFromStringHash(event.name, 50, 60)
: '',
}"
>
Expand Down
2 changes: 1 addition & 1 deletion packages/devtools/client/components/TimelineTable.vue
Original file line number Diff line number Diff line change
Expand Up @@ -103,7 +103,7 @@ useEventListener(scroller, 'wheel', (e: WheelEvent) => {
position: 'absolute',
top: `${item.layer * 4}px`,
left: `${item.relativeStart * 100}%`,
backgroundColor: getHashColorFromString(item.event.name, 50, 60),
backgroundColor: getHslColorFromStringHash(item.event.name, 50, 60),
}"
/>
<template v-if="segment.route">
Expand Down
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import type { CodeHighlightOptions } from '@nuxt/devtools-kit/types'
import type { BundledLanguage, BundledTheme, Highlighter } from './shiki.bundle'
import { shallowRef } from 'vue'
import { bundledLanguages, bundledThemes, createHighlighter } from './shiki.bundle'
Expand All @@ -6,7 +7,11 @@ export const shiki = shallowRef<Highlighter>()

let promise: Promise<any> | null = null

export function renderCodeHighlight(code: string, lang: BundledLanguage | 'text' = 'text') {
export function renderCodeHighlight(
code: string,
lang: BundledLanguage | 'text' = 'text',
options?: CodeHighlightOptions,
) {
if (!promise && !shiki.value) {
// Only loading when needed
promise = createHighlighter({
Expand All @@ -27,6 +32,7 @@ export function renderCodeHighlight(code: string, lang: BundledLanguage | 'text'

return {
code: shiki.value!.codeToHtml(code, {
...options,
lang,
themes: {
dark: 'vitesse-dark',
Expand Down
4 changes: 4 additions & 0 deletions packages/devtools/client/composables/state.ts
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,10 @@ export function useServerConfig() {
return useAsyncState('getServerConfig', () => rpc.getServerConfig())
}

export function useServerDebugContext() {
return useAsyncState('getServerDebugContext', () => rpc.getServerDebugContext())
}

export function useServerRuntimeConfig() {
return useAsyncState('getServerRuntimeConfig', () => rpc.getServerRuntimeConfig())
}
Expand Down
Loading
Loading