From 94eb5270ff2cc7f537b91958df2cb44fbbe904a3 Mon Sep 17 00:00:00 2001 From: Daniel Roe Date: Tue, 9 Apr 2024 19:01:20 +0200 Subject: [PATCH] Close storage drivers when nuxt is closing (#65) Co-authored-by: Dave Stewart --- README.md | 17 ----- package.json | 2 +- src/module.ts | 11 ++- src/runtime/assets/public.ts | 18 +++-- src/runtime/content/plugin.ts | 128 ++++++++++++++++++---------------- 5 files changed, 89 insertions(+), 87 deletions(-) diff --git a/README.md b/README.md index 34f0858..1f26a48 100644 --- a/README.md +++ b/README.md @@ -363,23 +363,6 @@ npm run release:dry Make sure to edit changelog and update `package.json` version first! -## Troubleshooting - -### Prepare script hangs - -As of Nuxt `3.7` it seems there might be issues running prepare scripts for some modules: - -- [nuxt/cli / nuxt prepare step hangs](https://github.com/nuxt/cli/issues/169) - -If that's the case with you, fix Nuxt at `3.6.5` (if you can) and you should be fine. - -Failing that, watch that ticket (or these ones): - -- https://github.com/nuxt/cli/issues/185 -- https://github.com/davestewart/nuxt-content-assets/issues/49 - -I'll update when there is more info. - [npm-version-src]: https://img.shields.io/npm/v/nuxt-content-assets/latest.svg?style=flat&colorA=18181B&colorB=28CF8D [npm-version-href]: https://npmjs.com/package/nuxt-content-assets diff --git a/package.json b/package.json index a5c3fa9..151e1d8 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "nuxt-content-assets", - "version": "1.3.4", + "version": "1.3.5", "description": "Enable locally-located assets in Nuxt Content", "repository": "davestewart/nuxt-content-assets", "license": "MIT", diff --git a/src/module.ts b/src/module.ts index f7006b4..86edecf 100644 --- a/src/module.ts +++ b/src/module.ts @@ -101,7 +101,9 @@ export default defineNuxtModule({ /** * Assets manager */ - const assets = makeAssetsManager(publicPath) + const assets = makeAssetsManager(publicPath, nuxt.options.dev) + + nuxt.hooks.hook('close', () => assets.dispose()) /** * Callback for when assets change @@ -185,6 +187,13 @@ export default defineNuxtModule({ managers[key] = makeSourceManager(key, source, publicPath, onAssetChange) } + nuxt.hook('close', async () => { + for (const key in managers) { + await managers[key].storage.unwatch() + await managers[key].storage.dispose() + } + }) + // --------------------------------------------------------------------------------------------------------------------- // build hook // --------------------------------------------------------------------------------------------------------------------- diff --git a/src/runtime/assets/public.ts b/src/runtime/assets/public.ts index 7f7b23a..8946079 100644 --- a/src/runtime/assets/public.ts +++ b/src/runtime/assets/public.ts @@ -9,7 +9,7 @@ import { isImage, warn, log } from '../utils' /** * Manages the public assets */ -export function makeAssetsManager (publicPath: string) { +export function makeAssetsManager (publicPath: string, shouldWatch = true) { // --------------------------------------------------------------------------------------------------------------------- // storage - updates asset index, watches for changes from other processes @@ -20,11 +20,13 @@ export function makeAssetsManager (publicPath: string) { // storage const storage = makeSourceStorage(Path.join(publicPath, '..')) - void storage.watch(async (event: string, key: string) => { - if (event === 'update' && key === indexKey) { - await load() - } - }) + if (shouldWatch) { + void storage.watch(async (event: string, key: string) => { + if (event === 'update' && key === indexKey) { + await load() + } + }) + } // assets const assets: Record = {} @@ -130,6 +132,10 @@ export function makeAssetsManager (publicPath: string) { getAsset, removeAsset, resolveAsset, + dispose: async () => { + await storage.unwatch() + await storage.dispose() + } } } diff --git a/src/runtime/content/plugin.ts b/src/runtime/content/plugin.ts index 15fa016..e7ac8e4 100644 --- a/src/runtime/content/plugin.ts +++ b/src/runtime/content/plugin.ts @@ -5,83 +5,85 @@ import { makeAssetsManager } from '../assets/public' // @ts-ignore – options injected via module.ts import { debug, imageSizes, publicPath } from '#nuxt-content-assets' -/** - * Walk the parsed frontmatter and check properties as paths - */ -function processMeta (content: ParsedContent, imageSizes: ImageSize = [], updated: string[] = []) { - walkMeta(content, (value, parent, key) => { - if (isValidAsset(value)) { - const { srcAttr, width, height } = resolveAsset(content, removeQuery(value), true) - if (srcAttr) { - const query = width && height && (imageSizes.includes('src') || imageSizes.includes('url')) - ? `width=${width}&height=${height}` - : '' - const srcUrl = query - ? buildQuery(srcAttr, parseQuery(value), query) - : srcAttr - parent[key] = srcUrl - updated.push(`meta: ${key} to "${srcUrl}"`) +const plugin: NitroAppPlugin = async (nitro: NitroApp) => { + /** + * Walk the parsed frontmatter and check properties as paths + */ + function processMeta (content: ParsedContent, imageSizes: ImageSize = [], updated: string[] = []) { + walkMeta(content, (value, parent, key) => { + if (isValidAsset(value)) { + const { srcAttr, width, height } = resolveAsset(content, removeQuery(value), true) + if (srcAttr) { + const query = width && height && (imageSizes.includes('src') || imageSizes.includes('url')) + ? `width=${width}&height=${height}` + : '' + const srcUrl = query + ? buildQuery(srcAttr, parseQuery(value), query) + : srcAttr + parent[key] = srcUrl + updated.push(`meta: ${key} to "${srcUrl}"`) + } } - } - }) -} + }) + } -/** - * Walk the parsed content and check potential attributes as paths - */ -function processBody (content: ParsedContent, imageSizes: ImageSize = [], updated: string[] = []) { - walkBody(content, function (node: any) { - const { tag, props } = node - for (const [prop, value] of Object.entries(props)) { - // only process strings - if (typeof value !== 'string') { - return - } + /** + * Walk the parsed content and check potential attributes as paths + */ + function processBody (content: ParsedContent, imageSizes: ImageSize = [], updated: string[] = []) { + walkBody(content, function (node: any) { + const { tag, props } = node + for (const [prop, value] of Object.entries(props)) { + // only process strings + if (typeof value !== 'string') { + return + } - // parse value - const { srcAttr, width, height } = resolveAsset(content, value, true) + // parse value + const { srcAttr, width, height } = resolveAsset(content, value, true) - // if we resolved an asset - if (srcAttr) { - // assign src - node.props[prop] = srcAttr + // if we resolved an asset + if (srcAttr) { + // assign src + node.props[prop] = srcAttr - // assign size - if (node.tag === 'img' || node.tag === 'nuxt-img') { - if (width && height) { - if (imageSizes.includes('attrs')) { - node.props.width = width - node.props.height = height - } - if (imageSizes.includes('style')) { - const ratio = `${width}/${height}` - if (typeof node.props.style === 'string') { - node.props.style = buildStyle(node.props.style, `aspect-ratio: ${ratio}`) + // assign size + if (node.tag === 'img' || node.tag === 'nuxt-img') { + if (width && height) { + if (imageSizes.includes('attrs')) { + node.props.width = width + node.props.height = height } - else { - node.props.style ||= {} - node.props.style.aspectRatio = ratio + if (imageSizes.includes('style')) { + const ratio = `${width}/${height}` + if (typeof node.props.style === 'string') { + node.props.style = buildStyle(node.props.style, `aspect-ratio: ${ratio}`) + } + else { + node.props.style ||= {} + node.props.style.aspectRatio = ratio + } } } } - } - // open links in new window - else if (node.tag === 'a') { - node.props.target ||= '_blank' - } + // open links in new window + else if (node.tag === 'a') { + node.props.target ||= '_blank' + } - // debug - updated.push(`page: ${tag}[${prop}] to "${srcAttr}"`) + // debug + updated.push(`page: ${tag}[${prop}] to "${srcAttr}"`) + } } - } - }) -} + }) + } -const { resolveAsset } = makeAssetsManager(publicPath) + +const { resolveAsset, dispose } = makeAssetsManager(publicPath, import.meta.dev) const plugin: NitroAppPlugin = async (nitro: NitroApp) => { - // @ts-ignore + // @ts-ignore hook name nitro.hooks.hook('content:file:afterParse', function (content: ParsedContent) { if (content._extension === 'md') { const updated: string[] = [] @@ -93,6 +95,8 @@ const plugin: NitroAppPlugin = async (nitro: NitroApp) => { } } }) + + nitro.hooks.hook('close', dispose) } export default plugin