Skip to content
This repository has been archived by the owner on Apr 6, 2023. It is now read-only.

fix: sanitize import filenames in generated imports #2216

Merged
merged 17 commits into from Feb 7, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
1 change: 1 addition & 0 deletions packages/bridge/package.json
Expand Up @@ -38,6 +38,7 @@
"globby": "^13.1.1",
"h3": "^0.3.9",
"hash-sum": "^2.0.0",
"knitwork": "^0.1.0",
"magic-string": "^0.25.7",
"mlly": "^0.4.1",
"murmurhash-es": "^0.1.1",
Expand Down
13 changes: 5 additions & 8 deletions packages/bridge/src/vite/templates.ts
Expand Up @@ -2,6 +2,7 @@ import hash from 'hash-sum'
import { resolve } from 'pathe'

import type { Nuxt, NuxtApp } from '@nuxt/schema'
import { genImport, genObjectFromRawEntries } from 'knitwork'

type TemplateContext = {
nuxt: Nuxt;
Expand All @@ -24,10 +25,8 @@ export const middlewareTemplate = {
id: m.name || m.src.replace(/[\\/]/g, '/').replace(/\.(js|ts)$/, '')
}
})
return `${_middleware.map(m => `import $${hash(m.id)} from '${m.filePath}'`).join('\n')}
const middleware = {
${_middleware.map(m => ` ['${m.id}']: $${hash(m.id)}`).join(',\n')}
}
return `${_middleware.map(m => genImport(m.filePath, `$${hash(m.id)}`)).join('\n')}
const middleware = ${genObjectFromRawEntries(_middleware.map(m => [m.id, `$${hash(m.id)}`]))}
export default middleware`
}
}
Expand All @@ -49,14 +48,12 @@ export const storeTemplate = {

return `import Vue from 'vue'
import Vuex from 'vuex'
${_storeModules.map(s => `import * as $${hash(s.id)} from '${s.filePath}'`).join('\n')}
${_storeModules.map(s => genImport(s.filePath, { name: '*', as: `$${hash(s.id)}` })).join('\n')}
Vue.use(Vuex)

const VUEX_PROPERTIES = ['state', 'getters', 'actions', 'mutations']

const storeModules = {
${_storeModules.map(m => ` ['${m.id}']: $${hash(m.id)}`).join(',\n')}
}
const storeModules = ${genObjectFromRawEntries(_storeModules.map(m => [m.id, `$${hash(m.id)}`]))}

export function createStore() {
let store = normalizeRoot(storeModules.root || {})
Expand Down
1 change: 1 addition & 0 deletions packages/kit/package.json
Expand Up @@ -20,6 +20,7 @@
"globby": "^13.1.1",
"hash-sum": "^2.0.0",
"jiti": "^1.12.15",
"knitwork": "^0.1.0",
"lodash.template": "^4.5.0",
"mlly": "^0.4.1",
"pathe": "^0.2.0",
Expand Down
5 changes: 3 additions & 2 deletions packages/kit/src/components.ts
@@ -1,5 +1,6 @@
import { pascalCase, kebabCase } from 'scule'
import type { ComponentsDir, Component } from '@nuxt/schema'
import { genDynamicImport } from 'knitwork'
import { useNuxt } from './context'
import { assertNuxtCompatibility } from './compatibility'

Expand Down Expand Up @@ -43,8 +44,8 @@ export async function addComponent (opts: AddComponentOptions) {
shortPath: opts.filePath,
async: false,
level: 0,
asyncImport: `() => import('${opts.filePath}').then(r => r['${opts.export || 'default'}'])`,
import: `require('${opts.filePath}')['${opts.export || 'default'}']`,
asyncImport: `${genDynamicImport(opts.filePath)}.then(r => r['${opts.export || 'default'}'])`,
import: `require(${JSON.stringify(opts.filePath)})['${opts.export || 'default'}']`,

...opts
}
Expand Down
7 changes: 4 additions & 3 deletions packages/kit/src/internal/template.ts
Expand Up @@ -3,6 +3,7 @@ import lodashTemplate from 'lodash.template'
import hash from 'hash-sum'
import { camelCase } from 'scule'
import { basename, extname } from 'pathe'
import { genDynamicImport, genImport } from 'knitwork'

import type { NuxtTemplate } from '@nuxt/schema'

Expand All @@ -23,7 +24,7 @@ export async function compileTemplate (template: NuxtTemplate, ctx: any) {
throw new Error('Invalid template: ' + JSON.stringify(template))
}

const serialize = (data: any) => JSON.stringify(data, null, 2).replace(/"{(.+)}"/g, '$1')
const serialize = (data: any) => JSON.stringify(data, null, 2).replace(/"{(.+)}"(?=,?$)/gm, r => JSON.parse(r).replace(/^{(.*)}$/, '$1'))

const importName = (src: string) => `${camelCase(basename(src, extname(src))).replace(/[^a-zA-Z?\d\s:]/g, '')}_${hash(src)}`

Expand All @@ -33,9 +34,9 @@ const importSources = (sources: string | string[], { lazy = false } = {}) => {
}
return sources.map((src) => {
if (lazy) {
return `const ${importName(src)} = () => import('${src}' /* webpackChunkName: '${src}' */)`
return `const ${importName(src)} = ${genDynamicImport(src, { comment: `webpackChunkName: ${JSON.stringify(src)}` })}`
}
return `import ${importName(src)} from '${src}'`
return genImport(src, importName(src))
}).join('\n')
}

Expand Down
1 change: 1 addition & 0 deletions packages/nitro/package.json
Expand Up @@ -48,6 +48,7 @@
"http-proxy": "^1.18.1",
"is-primitive": "^3.0.1",
"jiti": "^1.12.15",
"knitwork": "^0.1.0",
"listhen": "^0.2.6",
"mime": "^3.0.0",
"mlly": "^0.4.1",
Expand Down
3 changes: 2 additions & 1 deletion packages/nitro/src/build.ts
Expand Up @@ -2,6 +2,7 @@ import { relative, resolve, join } from 'pathe'
import consola from 'consola'
import * as rollup from 'rollup'
import fse from 'fs-extra'
import { genDynamicImport } from 'knitwork'
import { printFSTree } from './utils/tree'
import { getRollupConfig } from './rollup/config'
import { hl, prettyPath, serializeTemplate, writeFile, isDirectory, replaceAll } from './utils'
Expand Down Expand Up @@ -73,7 +74,7 @@ export async function writeTypes (nitroContext: NitroContext) {
if (typeof mw.handle !== 'string') { continue }
const relativePath = relative(nitroContext._nuxt.buildDir, mw.handle).replace(/\.[a-z]+$/, '')
routeTypes[mw.route] = routeTypes[mw.route] || []
routeTypes[mw.route].push(`Awaited<ReturnType<typeof import('${relativePath}').default>>`)
routeTypes[mw.route].push(`Awaited<ReturnType<typeof ${genDynamicImport(relativePath, { wrapper: false })}.default>>`)
}

const lines = [
Expand Down
7 changes: 4 additions & 3 deletions packages/nitro/src/presets/browser.ts
Expand Up @@ -2,6 +2,7 @@ import { existsSync, promises as fsp } from 'fs'
import { resolve } from 'pathe'
import consola from 'consola'
import { joinURL } from 'ufo'
import { genString } from 'knitwork'
import { extendPreset, prettyPath } from '../utils'
import { NitroPreset, NitroContext, NitroInput } from '../context'
import { worker } from './worker'
Expand All @@ -13,7 +14,7 @@ export const browser: NitroPreset = extendPreset(worker, (input: NitroInput) =>
const script = `<script>
if ('serviceWorker' in navigator) {
window.addEventListener('load', function () {
navigator.serviceWorker.register('${joinURL(baseURL, 'sw.js')}');
navigator.serviceWorker.register(${genString(joinURL(baseURL, 'sw.js'))});
});
}
</script>`
Expand All @@ -27,7 +28,7 @@ if ('serviceWorker' in navigator) {
<link rel="prefetch" href="${joinURL(baseURL, '_server/index.mjs')}">
<script>
async function register () {
const registration = await navigator.serviceWorker.register('${joinURL(baseURL, 'sw.js')}')
const registration = await navigator.serviceWorker.register(${genString(joinURL(baseURL, 'sw.js'))})
await navigator.serviceWorker.ready
registration.active.addEventListener('statechange', (event) => {
if (event.target.state === 'activated') {
Expand Down Expand Up @@ -64,7 +65,7 @@ if ('serviceWorker' in navigator) {
tmpl.contents = tmpl.contents.replace('</body>', script + '</body>')
},
async 'nitro:compiled' ({ output }: NitroContext) {
await fsp.writeFile(resolve(output.publicDir, 'sw.js'), `self.importScripts('${joinURL(baseURL, '_server/index.mjs')}');`, 'utf8')
await fsp.writeFile(resolve(output.publicDir, 'sw.js'), `self.importScripts(${genString(joinURL(baseURL, '_server/index.mjs'))});`, 'utf8')

// Temp fix
if (!existsSync(resolve(output.publicDir, 'index.html'))) {
Expand Down
3 changes: 2 additions & 1 deletion packages/nitro/src/rollup/config.ts
Expand Up @@ -18,6 +18,7 @@ import devalue from '@nuxt/devalue'

import type { Preset } from 'unenv'
import { sanitizeFilePath } from 'mlly'
import { genImport } from 'knitwork'
import { NitroContext } from '../context'
import { resolvePath } from '../utils'
import { pkgDir } from '../dirs'
Expand Down Expand Up @@ -215,7 +216,7 @@ export const getRollupConfig = (nitroContext: NitroContext) => {

// Polyfill
rollupConfig.plugins.push(virtual({
'#polyfill': env.polyfill.map(p => `import '${p}';`).join('\n')
'#polyfill': env.polyfill.map(p => genImport(p)).join('\n')
}))

// https://github.com/rollup/plugins/tree/master/packages/alias
Expand Down
10 changes: 7 additions & 3 deletions packages/nitro/src/rollup/plugins/assets.ts
Expand Up @@ -4,6 +4,7 @@ import createEtag from 'etag'
import mime from 'mime'
import { resolve } from 'pathe'
import { globby } from 'globby'
import { genDynamicImport, genObjectFromRawEntries } from 'knitwork'
import virtual from './virtual'

export interface AssetOptions {
Expand Down Expand Up @@ -81,9 +82,12 @@ function normalizeKey (key) {

function getAssetProd (assets: Record<string, Asset>) {
return `
const _assets = {\n${Object.entries(assets).map(([id, asset]) =>
` ['${normalizeKey(id)}']: {\n import: () => import('${asset.fsPath}').then(r => r.default || r),\n meta: ${JSON.stringify(asset.meta)}\n }`
).join(',\n')}\n}
const _assets = ${genObjectFromRawEntries(
Object.entries(assets).map(([id, asset]) => [normalizeKey(id), {
import: genDynamicImport(asset.fsPath, { interopDefault: true }),
meta: asset.meta
}])
)}

${normalizeKey.toString()}

Expand Down
13 changes: 5 additions & 8 deletions packages/nitro/src/rollup/plugins/dynamic-require.ts
Expand Up @@ -2,6 +2,7 @@ import { pathToFileURL } from 'url'
import { resolve } from 'pathe'
import { globby } from 'globby'
import type { Plugin } from 'rollup'
import { genDynamicImport, genObjectFromRawEntries, genImport } from 'knitwork'
import { serializeImportName } from '../../utils'

const PLUGIN_NAME = 'dynamic-require'
Expand Down Expand Up @@ -36,7 +37,7 @@ export function dynamicRequire ({ dir, ignore, inline }: Options): Plugin {
name: PLUGIN_NAME,
transform (code: string, _id: string) {
return {
code: code.replace(DYNAMIC_REQUIRE_RE, `import('${HELPER_DYNAMIC}').then(r => r.default || r).then(dynamicRequire => dynamicRequire($1)).then`),
code: code.replace(DYNAMIC_REQUIRE_RE, `${genDynamicImport(HELPER_DYNAMIC, { wrapper: false, interopDefault: true })}.then(dynamicRequire => dynamicRequire($1)).then`),
map: null
}
},
Expand Down Expand Up @@ -89,10 +90,8 @@ async function getWebpackChunkMeta (src: string) {
}

function TMPL_INLINE ({ chunks }: TemplateContext) {
return `${chunks.map(i => `import * as ${i.name} from '${i.src}'`).join('\n')}
const dynamicChunks = {
${chunks.map(i => ` ['${i.id}']: ${i.name}`).join(',\n')}
};
return `${chunks.map(i => genImport(i.src, { name: '*', as: i.name })).join('\n')}
const dynamicChunks = ${genObjectFromRawEntries(chunks.map(i => [i.id, i.name]))};

export default function dynamicRequire(id) {
return Promise.resolve(dynamicChunks[id]);
Expand All @@ -101,9 +100,7 @@ export default function dynamicRequire(id) {

function TMPL_LAZY ({ chunks }: TemplateContext) {
return `
const dynamicChunks = {
${chunks.map(i => ` ['${i.id}']: () => import('${i.src}')`).join(',\n')}
};
const dynamicChunks = ${genObjectFromRawEntries(chunks.map(i => [i.id, genDynamicImport(i.src)]))};

export default function dynamicRequire(id) {
return dynamicChunks[id]();
Expand Down
16 changes: 10 additions & 6 deletions packages/nitro/src/rollup/plugins/middleware.ts
Expand Up @@ -3,6 +3,7 @@ import { relative } from 'pathe'
import table from 'table'
import isPrimitive from 'is-primitive'
import { isDebug } from 'std-env'
import { genArrayFromRaw, genDynamicImport, genImport } from 'knitwork'
import type { ServerMiddleware } from '../../server/middleware'
import virtual from './virtual'

Expand Down Expand Up @@ -35,15 +36,18 @@ export function middleware (getMiddleware: () => ServerMiddleware[]) {
const lazyImports = unique(middleware.filter(m => m.lazy !== false && !imports.includes(m.handle)).map(m => m.handle))

return `
${imports.map(handle => `import ${getImportId(handle)} from '${handle}';`).join('\n')}
${imports.map(handle => `${genImport(handle, getImportId(handle))};`).join('\n')}

${lazyImports.map(handle => `const ${getImportId(handle)} = () => import('${handle}');`).join('\n')}
${lazyImports.map(handle => `const ${getImportId(handle)} = ${genDynamicImport(handle)};`).join('\n')}

const middleware = [
${middleware.map(m => `{ route: '${m.route}', handle: ${getImportId(m.handle)}, lazy: ${m.lazy || true}, promisify: ${m.promisify !== undefined ? m.promisify : true} }`).join(',\n')}
];
const middleware = ${genArrayFromRaw(middleware.map(m => ({
route: JSON.stringify(m.route),
handle: getImportId(m.handle),
lazy: m.lazy || true,
promisify: m.promisify !== undefined ? m.promisify : true
})))};

export default middleware
export default middleware
`
}
}
Expand Down
5 changes: 3 additions & 2 deletions packages/nitro/src/rollup/plugins/storage.ts
@@ -1,4 +1,5 @@
import virtual from '@rollup/plugin-virtual'
import { genImport, genString } from 'knitwork'
import { serializeImportName } from '../../utils'

export interface StorageOptions {
Expand Down Expand Up @@ -35,13 +36,13 @@ export function storage (opts: StorageOptions) {
import { createStorage } from 'unstorage'
import { assets } from '#assets'

${driverImports.map(i => `import ${serializeImportName(i)} from '${i}'`).join('\n')}
${driverImports.map(i => genImport(i, serializeImportName(i))).join('\n')}

export const storage = createStorage({})

storage.mount('/assets', assets)

${mounts.map(m => `storage.mount('${m.path}', ${serializeImportName(m.driver)}(${JSON.stringify(m.opts)}))`).join('\n')}
${mounts.map(m => `storage.mount(${genString(m.path)}, ${serializeImportName(m.driver)}(${JSON.stringify(m.opts)}))`).join('\n')}
`
})
}
1 change: 1 addition & 0 deletions packages/nuxt3/package.json
Expand Up @@ -39,6 +39,7 @@
"hash-sum": "^2.0.0",
"hookable": "^5.1.1",
"ignore": "^5.2.0",
"knitwork": "^0.1.0",
"mlly": "^0.4.1",
"murmurhash-es": "^0.1.1",
"nuxi": "3.0.0",
Expand Down
3 changes: 2 additions & 1 deletion packages/nuxt3/src/auto-imports/module.ts
@@ -1,6 +1,7 @@
import { addVitePlugin, addWebpackPlugin, defineNuxtModule, addTemplate, resolveAlias, addPluginTemplate, useNuxt } from '@nuxt/kit'
import type { AutoImportsOptions } from '@nuxt/schema'
import { isAbsolute, join, relative, resolve, normalize } from 'pathe'
import { genDynamicImport } from 'knitwork'
import { TransformPlugin } from './transform'
import { Nuxt3AutoImports } from './imports'
import { scanForComposables } from './composables'
Expand Down Expand Up @@ -132,7 +133,7 @@ function generateDts (ctx: AutoImportContext) {
write: true,
getContents: () => `// Generated by auto imports
declare global {
${ctx.autoImports.map(i => ` const ${i.as}: typeof import('${r(i.from)}')['${i.name}']`).join('\n')}
${ctx.autoImports.map(i => ` const ${i.as}: typeof ${genDynamicImport(r(i.from), { wrapper: false })}['${i.name}']`).join('\n')}
}

export {}
Expand Down
7 changes: 4 additions & 3 deletions packages/nuxt3/src/auto-imports/utils.ts
@@ -1,4 +1,5 @@
import type { AutoImport } from '@nuxt/schema'
import { genExport, genImport, genString } from 'knitwork'

export function toImportModuleMap (autoImports: AutoImport[], isCJS = false) {
const aliasKeyword = isCJS ? ' : ' : ' as '
Expand All @@ -20,19 +21,19 @@ export function toImports (autoImports: AutoImport[], isCJS = false) {
const map = toImportModuleMap(autoImports, isCJS)
if (isCJS) {
return Object.entries(map)
.map(([name, imports]) => `const { ${Array.from(imports).join(', ')} } = require('${name}');`)
.map(([name, imports]) => `const { ${Array.from(imports).join(', ')} } = require(${genString(name)});`)
.join('\n')
} else {
return Object.entries(map)
.map(([name, imports]) => `import { ${Array.from(imports).join(', ')} } from '${name}';`)
.map(([name, imports]) => genImport(name, Array.from(imports)))
.join('\n')
}
}

export function toExports (autoImports: AutoImport[]) {
const map = toImportModuleMap(autoImports, false)
return Object.entries(map)
.map(([name, imports]) => `export { ${Array.from(imports).join(', ')} } from '${name}';`)
.map(([name, imports]) => genExport(name, Array.from(imports)))
.join('\n')
}

Expand Down
3 changes: 2 additions & 1 deletion packages/nuxt3/src/components/loader.ts
@@ -1,6 +1,7 @@
import { createUnplugin } from 'unplugin'
import { parseQuery, parseURL } from 'ufo'
import { Component } from '@nuxt/schema'
import { genImport } from 'knitwork'

interface LoaderOptions {
getComponents(): Component[]
Expand Down Expand Up @@ -36,7 +37,7 @@ function transform (content: string, components: Component[]) {
if (component) {
const identifier = map.get(component) || `__nuxt_component_${num++}`
map.set(component, identifier)
imports += `import ${identifier} from "${component.filePath}";`
imports += genImport(component.filePath, identifier)
return ` ${identifier}`
}
// no matched
Expand Down