From 779ae84b96dbd54338a4a4d406d3496d5df3791e Mon Sep 17 00:00:00 2001 From: Baptiste Leproux Date: Tue, 30 Apr 2024 17:32:14 +0200 Subject: [PATCH] chore(types): add typecheck --- package.json | 1 + src/module.ts | 2 +- src/runtime/components/ContentPreviewMode.vue | 2 +- src/runtime/composables/useStudio.ts | 27 ++++++++++--------- src/runtime/plugins/preview.client.ts | 5 ++-- src/runtime/server/routes/studio.ts | 15 ++++++----- 6 files changed, 28 insertions(+), 24 deletions(-) diff --git a/package.json b/package.json index cb3ae93..5ec6f6c 100644 --- a/package.json +++ b/package.json @@ -39,6 +39,7 @@ "dev:prepare": "nuxt-module-build build --stub && nuxt-module-build prepare && nuxt prepare playground", "dev": "nuxt dev playground --tunnel", "build": "nuxt-module-build build", + "typecheck": "nuxi typecheck", "lint": "eslint .", "lint:fix": "eslint . --fix", "prepack": "pnpm lint && pnpm build", diff --git a/src/module.ts b/src/module.ts index 5b5bd2d..10953db 100644 --- a/src/module.ts +++ b/src/module.ts @@ -81,7 +81,7 @@ export default defineNuxtModule({ const publicToken = process.env.NUXT_PUBLIC_STUDIO_TOKENS const iframeMessagingAllowedOrigins = process.env.IFRAME_MESSAGING_ALLOWED_ORIGINS const gitInfo = await _getLocalGitInfo(nuxt.options.rootDir) || _getGitEnv() || {} - nuxt.options.runtimeConfig.studio = defu(nuxt.options.runtimeConfig.studio, { + nuxt.options.runtimeConfig.studio = defu(nuxt.options.runtimeConfig.studio as Record, { version, publicToken, gitInfo, diff --git a/src/runtime/components/ContentPreviewMode.vue b/src/runtime/components/ContentPreviewMode.vue index 7c80ffa..e26c0c5 100644 --- a/src/runtime/components/ContentPreviewMode.vue +++ b/src/runtime/components/ContentPreviewMode.vue @@ -2,7 +2,6 @@ import { onMounted, ref, onUnmounted } from 'vue' import type { Socket } from 'socket.io-client' import type { PreviewResponse } from '../types' -// @ts-expect-error import does exist import { useCookie, useNuxtApp, useRouter } from '#app' const props = defineProps({ @@ -71,6 +70,7 @@ const sync = async (data: PreviewResponse) => { // Remove query params in url to refresh page (in case of 404 with no SPA fallback) await router.replace({ query: {} }) + // @ts-expect-error custom hook nuxtApp.callHook('nuxt-studio:preview:ready') if (window.parent && window.self !== window.parent) { diff --git a/src/runtime/composables/useStudio.ts b/src/runtime/composables/useStudio.ts index 886cd87..39552c5 100644 --- a/src/runtime/composables/useStudio.ts +++ b/src/runtime/composables/useStudio.ts @@ -7,7 +7,6 @@ import type { AppConfig } from 'nuxt/schema' import ContentPreviewMode from '../components/ContentPreviewMode.vue' import { createSingleton, deepAssign, deepDelete, mergeDraft, StudioConfigFiles } from '../utils' import type { PreviewFile, PreviewResponse, FileChangeMessagePayload } from '../types' -// @ts-expect-error import does exist import { callWithNuxt } from '#app' import { useAppConfig, useNuxtApp, useRuntimeConfig, useState, useContentState, queryContent, ref, toRaw, useRoute, useRouter } from '#imports' @@ -35,6 +34,7 @@ export const useStudio = () => { const storage = useState('studio-client-db', () => null) if (!storage.value) { + // @ts-expect-error custom hook nuxtApp.hook('content:storage', (_storage: Storage) => { storage.value = _storage }) @@ -62,17 +62,17 @@ export const useStudio = () => { ) } - const syncPreviewAppConfig = (appConfig?: AppConfig) => { + const syncPreviewAppConfig = (appConfig?: ParsedContent) => { const _appConfig = callWithNuxt(nuxtApp, useAppConfig) as AppConfig // Set dynamic icons for preview if user is using @nuxt/ui if (_appConfig?.ui) { - (_appConfig.ui as AppConfig).icons = { ...(_appConfig.ui as AppConfig).icons as AppConfig, dynamic: true } + (_appConfig.ui as Record).icons = { ...(_appConfig.ui as Record).icons as AppConfig, dynamic: true } } // Using `defu` to merge with initial config // This is important to revert to default values for missing properties - deepAssign(_appConfig, defu(appConfig as AppConfig, initialAppConfig)) + deepAssign(_appConfig, defu(appConfig as ParsedContent, initialAppConfig)) // Reset app config to initial state if no appConfig is provided // Makes sure that app config does not contain any preview data @@ -81,27 +81,29 @@ export const useStudio = () => { } } - const syncPreviewTokensConfig = (tokensConfig?: AppConfig) => { + const syncPreviewTokensConfig = (tokensConfig?: ParsedContent) => { // Tokens config (optional; depends on the presence of pinceauTheme provide) // TODO: Improve typings // TODO: Use `inject()` but wrong context seem to be resolved; while $pinceauTheme global property is present in `app` context - const themeSheet = nuxtApp?.vueApp?._context?.config?.globalProperties?.$pinceauTheme + const themeSheet = nuxtApp?.vueApp?._context?.config?.globalProperties?.$pinceauTheme as Record // Pinceau might be not present, or not booted yet if (!themeSheet || !themeSheet?.updateTheme) return // Set initial tokens config on first call if (!initialTokensConfig) { - initialTokensConfig = JSON.parse(JSON.stringify(themeSheet?.theme.value || {})) + initialTokensConfig = JSON.parse(JSON.stringify((themeSheet?.theme as Record).value || {})) } // Call updateTheme with new config callWithNuxt( nuxtApp, - themeSheet.updateTheme, [ + // eslint-disable-next-line @typescript-eslint/no-explicit-any + themeSheet.updateTheme as any, + [ // Using `defu` to merge with initial tokens // This is important to revert to default values for missing properties - defu(tokensConfig as AppConfig, initialTokensConfig), + defu(tokensConfig as ParsedContent, initialTokensConfig), ], ) } @@ -125,10 +127,10 @@ export const useStudio = () => { await syncPreviewFiles(storage.value, contentFiles) const appConfig = mergedFiles.find(item => item.path === StudioConfigFiles.appConfig) - syncPreviewAppConfig(appConfig?.parsed) + syncPreviewAppConfig(appConfig?.parsed as ParsedContent) const tokensConfig = mergedFiles.find(item => item.path === StudioConfigFiles.tokensConfig) - syncPreviewTokensConfig(tokensConfig?.parsed) + syncPreviewTokensConfig(tokensConfig?.parsed as ParsedContent) requestRerender() @@ -209,7 +211,7 @@ export const useStudio = () => { const requestRerender = async () => { if (contentConfig?.documentDriven) { - // Update all cached pages + // @ts-expect-error Update all cached pages const { pages } = callWithNuxt(nuxtApp, useContentState) const contents = await Promise.all(Object.keys(pages.value).map(async (key) => { @@ -359,6 +361,7 @@ export const useStudio = () => { route.meta.studio_page_contentId = page?._id }) + // @ts-expect-error custom hook nuxtApp.hook('nuxt-studio:preview:ready', () => { window.parent.postMessage({ type: 'nuxt-studio:preview:ready', diff --git a/src/runtime/plugins/preview.client.ts b/src/runtime/plugins/preview.client.ts index 116fa85..a309f9b 100644 --- a/src/runtime/plugins/preview.client.ts +++ b/src/runtime/plugins/preview.client.ts @@ -1,8 +1,6 @@ import { defineNuxtPlugin, useCookie, useRoute, useRuntimeConfig, useState } from '#imports' -// @ts-expect-error import does exist -import type { NuxtApp } from '#app' -export default defineNuxtPlugin((nuxtApp: NuxtApp) => { +export default defineNuxtPlugin((nuxtApp) => { const runtimeConfig = useRuntimeConfig().public.studio || {} const route = useRoute() const previewToken = useCookie('previewToken', { sameSite: 'none', secure: true }) @@ -35,6 +33,7 @@ export default defineNuxtPlugin((nuxtApp: NuxtApp) => { // Listen to `content:storage` hook to get storage instance // There is some cases that `content:storage` hook is called before initializing preview + // @ts-expect-error custom hook nuxtApp.hook('content:storage', (_storage: Storage) => { storage.value = _storage }) diff --git a/src/runtime/server/routes/studio.ts b/src/runtime/server/routes/studio.ts index 36b4d06..71a2683 100644 --- a/src/runtime/server/routes/studio.ts +++ b/src/runtime/server/routes/studio.ts @@ -30,12 +30,13 @@ export default eventHandler(async () => { const appConfig = useAppConfig() const runtimeConfig = useRuntimeConfig() - const { app, contentSchema, appConfigSchema, studio, content: { sources, ignores, locales, defaultLocale, highlight, navigation, documentDriven, experimental } } = runtimeConfig + const { app, contentSchema, appConfigSchema, studio, content } = runtimeConfig + const { sources, ignores, locales, defaultLocale, highlight, navigation, documentDriven, experimental } = content as Record // Delete GitHub tokens for multiple source to avoid exposing them const safeSources: Record = {} - Object.keys(sources).forEach((name) => { - const { driver, prefix, base, repo, branch, dir } = sources[name] || {} + Object.keys(sources as Record).forEach((name) => { + const { driver, prefix, base, repo, branch, dir } = (sources as Record)[name] as Record || {} safeSources[name] = { driver, prefix, @@ -45,7 +46,7 @@ export default eventHandler(async () => { dir, } }) - const hasPinceau = runtimeConfig?.pinceau?.studio + const hasPinceau = (runtimeConfig?.pinceau as Record)?.studio let tokensConfig let tokensConfigSchema if (hasPinceau) { @@ -57,9 +58,9 @@ export default eventHandler(async () => { return { // Studio version - version: studio.version, - tokens: studio?.publicToken, - gitInfo: studio?.gitInfo || {}, + version: (studio as Record)?.version, + tokens: (studio as Record)?.publicToken, + gitInfo: (studio as Record)?.gitInfo || {}, // nuxt.schema for Nuxt Content frontmatter contentSchema: contentSchema || {}, // app.config