Skip to content

Commit

Permalink
refactor: improve internal typings
Browse files Browse the repository at this point in the history
  • Loading branch information
harlan-zw committed Mar 30, 2024
1 parent cfd1d60 commit 6d4773a
Show file tree
Hide file tree
Showing 4 changed files with 57 additions and 9 deletions.
23 changes: 23 additions & 0 deletions src/kit.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
import { addTemplate, createResolver, useNuxt } from '@nuxt/kit'
import { relative } from 'pathe'

export function extendTypes(module: string, template: (options: { typesPath: string }) => Promise<string> | string) {
const nuxt = useNuxt()
const { resolve } = createResolver(import.meta.url)
// paths.d.ts
addTemplate({
filename: `module/${module}.d.ts`,
getContents: async () => {
const typesPath = relative(resolve(nuxt!.options.rootDir, nuxt!.options.buildDir, 'module'), resolve('runtime/types'))
const s = await template({ typesPath })
return `// Generated by ${module}
${s}
export {}
`
},
})

nuxt.hooks.hook('prepare:types', ({ references }) => {
references.push({ path: resolve(nuxt.options.buildDir, `module/${module}.d.ts`) })
})
}
16 changes: 14 additions & 2 deletions src/module.ts
Original file line number Diff line number Diff line change
@@ -1,19 +1,21 @@
import { addBuildPlugin, addImports, addImportsDir, addPlugin, addPluginTemplate, addTemplate, createResolver, defineNuxtModule } from '@nuxt/kit'
import { readPackageJSON } from 'pkg-types'
import type { Import } from 'unimport'
import type { Input } from 'valibot'
import type { NuxtUseScriptInput, NuxtUseScriptOptions } from './runtime/types'
import { setupDevToolsUI } from './devtools'
import { NuxtScriptAssetBundlerTransformer } from './plugins/transform'
import { setupPublicAssetStrategy } from './assets'
import { logger } from './logger'
import type { CloudflareWebAnalyticsOptions } from './runtime/registry/cloudflare-web-analytics'
import { extendTypes } from './kit'

export interface ModuleOptions {
/**
* Register scripts globally.
*/
register?: {
cloudflareWebAnalytics?: CloudflareWebAnalyticsOptions
cloudflareWebAnalytics?: Input<typeof CloudflareWebAnalyticsOptions>
// TODO start the rest
}
/**
Expand Down Expand Up @@ -72,7 +74,7 @@ export default defineNuxtModule<ModuleOptions>({
},
async setup(config, nuxt) {
const { resolve } = createResolver(import.meta.url)
const { version } = await readPackageJSON(resolve('../package.json'))
const { version, name } = await readPackageJSON(resolve('../package.json'))
if (!config.enabled) {
// TODO fallback to useHead?
logger.debug('The module is disabled, skipping setup.')
Expand Down Expand Up @@ -186,6 +188,16 @@ ${config.globals?.map(g => !Array.isArray(g)
})
}

extendTypes(name!, async () => {
return `
declare module '#app' {
interface NuxtApp {
${nuxt.options.dev ? `_scripts: (import('#nuxt-scripts').NuxtAppScript)[]` : ''}
}
}
`
})

const scriptMap = new Map<string, string>()
const { normalizeScriptData } = setupPublicAssetStrategy(config.assets)

Expand Down
12 changes: 6 additions & 6 deletions src/runtime/composables/useScript.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,17 +2,17 @@ import { type UseScriptInput, type VueScriptInstance, useScript as _useScript, i
import type { UseScriptOptions } from '@unhead/schema'
import { hashCode } from '@unhead/shared'
import { onNuxtReady, useNuxtApp } from '#imports'
import type { NuxtUseScriptOptions } from '#nuxt-scripts'
import type { NuxtAppScript, NuxtUseScriptOptions } from '#nuxt-scripts'

export function useScript<T>(input: UseScriptInput, options?: NuxtUseScriptOptions) {
input = typeof input === 'string' ? { src: input } : input
options = options || {}
if (options.trigger === 'onNuxtReady')
options.trigger = new Promise(resolve => onNuxtReady(resolve))
const nuxtApp = useNuxtApp()
const id = input.key || hashCode(input.src || (typeof input.innerHTML === 'string' ? input.innerHTML : ''))
const id = input.key || input.src || hashCode((typeof input.innerHTML === 'string' ? input.innerHTML : ''))
// only validate if we're initializing the script
if (import.meta.dev && !nuxtApp.scripts?.[id])
if (!nuxtApp.scripts?.[id]) {
options.beforeInit?.()
if (import.meta.client) {
performance?.mark?.('mark_feature_usage', {
Expand All @@ -26,11 +26,11 @@ export function useScript<T>(input: UseScriptInput, options?: NuxtUseScriptOptio
// used for devtools integration
if (import.meta.dev && import.meta.client) {
// sync scripts to nuxtApp with debug details
const payload = {
key: input.key || input.src,
const payload: NuxtAppScript = {
key: (input.key || input.src) as string,
src: input.src,
$script: null as any as VueScriptInstance<T>,
events: [] as any[],
events: [],
}
nuxtApp._scripts = nuxtApp._scripts! || {}

Expand Down
15 changes: 14 additions & 1 deletion src/runtime/types.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import type { UseScriptOptions } from '@unhead/schema'
import type { UseScriptInput } from '@unhead/vue'
import type { UseScriptInput, VueScriptInstance } from '@unhead/vue'
import type { ComputedRef, Ref } from 'vue'

export type NuxtUseScriptOptions<T = any> = Omit<UseScriptOptions<T>, 'trigger'> & {
Expand Down Expand Up @@ -41,3 +41,16 @@ export interface ConsentPromiseOptions {
*/
loadOnNuxtReady?: boolean
}

export interface NuxtAppScript {
key: string
src: string
$script: VueScriptInstance<any>
events: {
type: string
fn?: string
args?: any
trigger?: string
at: number
}[]
}

0 comments on commit 6d4773a

Please sign in to comment.