mirror of
https://github.com/nuxt/nuxt.git
synced 2024-11-21 21:25:11 +00:00
refactor: split schema to @nuxt/schema
and simplify kit (#2059)
This commit is contained in:
parent
07c7a20462
commit
d68318f9d5
@ -12,7 +12,6 @@
|
||||
"@docus/github": "1.0.4",
|
||||
"@docus/social-image": "1.0.3",
|
||||
"@docus/theme": "1.2.2",
|
||||
"@nuxt/kit": "link:../packages/kit",
|
||||
"@nuxt/typescript-build": "^2.1.0",
|
||||
"fs-extra": "^10.0.0",
|
||||
"jiti": "^1.12.9",
|
||||
|
@ -117,7 +117,7 @@ async function generateDocs ({ configFile, configTemplate }) {
|
||||
const start = Date.now()
|
||||
console.log(`Updating docs on ${configFile}`)
|
||||
const template = await readFile(configTemplate, 'utf8')
|
||||
const rootSchema = require('../../packages/kit/schema/config.schema.json') as Schema
|
||||
const rootSchema = require('../../packages/schema/schema/config.schema.json') as Schema
|
||||
const keys = Object.keys(rootSchema.properties).sort()
|
||||
let generatedDocs = ''
|
||||
|
||||
|
@ -4,5 +4,5 @@ set -e
|
||||
cd ..
|
||||
yarn="node `pwd`/.yarn/releases/yarn-*.cjs"
|
||||
$yarn install
|
||||
cd packages/kit
|
||||
cd packages/schema
|
||||
$yarn prepack --stub
|
||||
|
@ -1472,10 +1472,6 @@
|
||||
untyped "^0.2.5"
|
||||
upath "^2.0.1"
|
||||
|
||||
"@nuxt/kit@link:../packages/kit":
|
||||
version "0.0.0"
|
||||
uid ""
|
||||
|
||||
"@nuxt/kit@npm:@nuxt/kit-edge":
|
||||
version "3.0.0-27247485.fb4359e"
|
||||
resolved "https://registry.yarnpkg.com/@nuxt/kit-edge/-/kit-edge-3.0.0-27247485.fb4359e.tgz#efbc5a2289857a698b5d04089ecf5fe9511f4bb2"
|
||||
@ -7328,16 +7324,6 @@ mlly@^0.3.0:
|
||||
resolved "https://registry.yarnpkg.com/mlly/-/mlly-0.3.0.tgz#5705b2a95551d79ad33feedc046daf7c6d079748"
|
||||
integrity sha512-6XphOVPsnIzuqNYlcZPMJhaMDDdrEgbLUlA7BPis8O0kkLPbOVA8GcXGeICGcnDotCtTkxAEWBT+FlhywrXTmg==
|
||||
|
||||
mlly@^0.3.13:
|
||||
version "0.3.13"
|
||||
resolved "https://registry.yarnpkg.com/mlly/-/mlly-0.3.13.tgz#5433261f38ccebba6f72fabda863a4dfc84b16d8"
|
||||
integrity sha512-EXpbSPqSQLR9NEdB25uoyIYLSUvAqDEI7wUeM1HwXHsPF5Gx7cP7kuby5Mz2LfCPxBrgMnbcyPhcTCJRTQ+uvA==
|
||||
|
||||
mlly@^0.3.6:
|
||||
version "0.3.10"
|
||||
resolved "https://registry.yarnpkg.com/mlly/-/mlly-0.3.10.tgz#cf3353565c84e951311c46c8d2c8b320d90f9eb3"
|
||||
integrity sha512-vD3A7naDtIOqHYZhnYUrECRO6UODWNqz6T0TS/pxwolzVoWKX/mXJF1XSM3qxruCDtkzJbzJPgesByihY/r3EA==
|
||||
|
||||
move-concurrently@^1.0.1:
|
||||
version "1.0.1"
|
||||
resolved "https://registry.yarnpkg.com/move-concurrently/-/move-concurrently-1.0.1.tgz#be2c005fda32e0b29af1f05d7c4b33214c701f92"
|
||||
@ -8170,15 +8156,6 @@ pkg-types@^0.2.1:
|
||||
dependencies:
|
||||
jsonc-parser "^3.0.0"
|
||||
|
||||
pkg-types@^0.3.1:
|
||||
version "0.3.1"
|
||||
resolved "https://registry.yarnpkg.com/pkg-types/-/pkg-types-0.3.1.tgz#d7a8b69efb8777a05afc5aabfc259a29a5d6d159"
|
||||
integrity sha512-BjECNgz/tsyqg0/T4Z/U7WbFQXUT24nfkxPbALcrk/uHVeZf9MrGG4tfvYtu+jsrHCFMseLQ6woQddDEBATw3A==
|
||||
dependencies:
|
||||
jsonc-parser "^3.0.0"
|
||||
mlly "^0.3.6"
|
||||
pathe "^0.2.0"
|
||||
|
||||
plausible-tracker@^0.3.4:
|
||||
version "0.3.4"
|
||||
resolved "https://registry.yarnpkg.com/plausible-tracker/-/plausible-tracker-0.3.4.tgz#6c4fb5888f62d0ab9b069fef7e3a06e2e728c65c"
|
||||
@ -10253,11 +10230,6 @@ std-env@^2.2.1, std-env@^2.3.0, std-env@^2.3.1:
|
||||
dependencies:
|
||||
ci-info "^3.1.1"
|
||||
|
||||
std-env@^3.0.1:
|
||||
version "3.0.1"
|
||||
resolved "https://registry.yarnpkg.com/std-env/-/std-env-3.0.1.tgz#bc4cbc0e438610197e34c2d79c3df30b491f5182"
|
||||
integrity sha512-mC1Ps9l77/97qeOZc+HrOL7TIaOboHqMZ24dGVQrlxFcpPpfCHpH+qfUT7Dz+6mlG8+JPA1KfBQo19iC/+Ngcw==
|
||||
|
||||
stream-browserify@^2.0.1:
|
||||
version "2.0.2"
|
||||
resolved "https://registry.yarnpkg.com/stream-browserify/-/stream-browserify-2.0.2.tgz#87521d38a44aa7ee91ce1cd2a47df0cb49dd660b"
|
||||
|
@ -22,6 +22,7 @@
|
||||
"@nuxt/kit": "3.0.0",
|
||||
"@nuxt/nitro": "3.0.0",
|
||||
"@nuxt/postcss8": "^1.1.3",
|
||||
"@nuxt/schema": "3.0.0",
|
||||
"@vitejs/plugin-legacy": "^1.6.2",
|
||||
"@vue/composition-api": "^1.4.0",
|
||||
"@vueuse/head": "^0.7.2",
|
||||
|
@ -3,7 +3,7 @@ import type { CombinedVueInstance } from 'vue/types/vue'
|
||||
import type { MetaInfo } from 'vue-meta'
|
||||
import type VueRouter from 'vue-router'
|
||||
import type { Route } from 'vue-router'
|
||||
import type { RuntimeConfig } from '@nuxt/kit'
|
||||
import type { RuntimeConfig } from '@nuxt/schema'
|
||||
import { useNuxtApp } from './app'
|
||||
|
||||
export { useLazyAsyncData } from './asyncData'
|
||||
|
@ -1,7 +1,7 @@
|
||||
import hash from 'hash-sum'
|
||||
import { resolve } from 'pathe'
|
||||
|
||||
import type { Nuxt, NuxtApp } from '@nuxt/kit'
|
||||
import type { Nuxt, NuxtApp } from '@nuxt/schema'
|
||||
|
||||
type TemplateContext = {
|
||||
nuxt: Nuxt;
|
||||
|
2
packages/bridge/types.d.ts
vendored
2
packages/bridge/types.d.ts
vendored
@ -1,5 +1,5 @@
|
||||
import type {} from '@nuxt/nitro'
|
||||
import type { NuxtConfig as _NuxtConfig } from '@nuxt/kit'
|
||||
import type { NuxtConfig as _NuxtConfig } from '@nuxt/schema'
|
||||
import type { MetaInfo } from 'vue-meta'
|
||||
|
||||
export interface BridgeConfig {
|
||||
|
@ -4,27 +4,11 @@ export default defineBuildConfig({
|
||||
declaration: true,
|
||||
emitCJS: false,
|
||||
entries: [
|
||||
{
|
||||
input: 'src/config/schema/index',
|
||||
outDir: 'schema',
|
||||
name: 'config',
|
||||
builder: 'untyped',
|
||||
defaults: {
|
||||
rootDir: '/project/'
|
||||
}
|
||||
},
|
||||
'src/index'
|
||||
],
|
||||
externals: [
|
||||
'@nuxt/schema',
|
||||
'webpack',
|
||||
'vite',
|
||||
'nuxt',
|
||||
'nuxt3',
|
||||
// type imports
|
||||
'@vue/compiler-core',
|
||||
'vue-meta',
|
||||
'rollup-plugin-visualizer',
|
||||
'webpack-bundle-analyzer',
|
||||
'vue'
|
||||
'vite'
|
||||
]
|
||||
})
|
||||
|
@ -7,25 +7,18 @@
|
||||
"main": "./dist/index.mjs",
|
||||
"types": "./dist/index.d.ts",
|
||||
"files": [
|
||||
"dist",
|
||||
"schema"
|
||||
"dist"
|
||||
],
|
||||
"scripts": {
|
||||
"prepack": "unbuild"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/lodash.template": "^4",
|
||||
"@types/semver": "^7",
|
||||
"unbuild": "latest"
|
||||
},
|
||||
"dependencies": {
|
||||
"@nuxt/schema": "^3.0.0",
|
||||
"consola": "^2.15.3",
|
||||
"create-require": "^1.1.1",
|
||||
"defu": "^5.0.0",
|
||||
"dotenv": "^10.0.0",
|
||||
"globby": "^11.0.4",
|
||||
"hash-sum": "^2.0.0",
|
||||
"hookable": "^5.0.0",
|
||||
"jiti": "^1.12.9",
|
||||
"lodash.template": "^4.5.0",
|
||||
"mlly": "^0.3.13",
|
||||
@ -34,11 +27,14 @@
|
||||
"rc9": "^1.2.0",
|
||||
"scule": "^0.2.1",
|
||||
"semver": "^7.3.5",
|
||||
"std-env": "^3.0.1",
|
||||
"ufo": "^0.7.9",
|
||||
"unctx": "^1.0.2",
|
||||
"untyped": "^0.3.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/lodash.template": "^4",
|
||||
"@types/semver": "^7",
|
||||
"unbuild": "latest"
|
||||
},
|
||||
"engines": {
|
||||
"node": "^14.16.0 || ^16.11.0 || ^17.0.0"
|
||||
}
|
||||
|
123
packages/kit/src/build.ts
Normal file
123
packages/kit/src/build.ts
Normal file
@ -0,0 +1,123 @@
|
||||
import type { WebpackPluginInstance, Configuration as WebpackConfig } from 'webpack'
|
||||
import type { Plugin as VitePlugin, UserConfig as ViteConfig } from 'vite'
|
||||
import { useNuxt } from './context'
|
||||
|
||||
export interface ExtendConfigOptions {
|
||||
/**
|
||||
* Install plugin on dev
|
||||
*
|
||||
* @default true
|
||||
*/
|
||||
dev?: boolean
|
||||
/**
|
||||
* Install plugin on build
|
||||
*
|
||||
* @default true
|
||||
*/
|
||||
build?: boolean
|
||||
}
|
||||
|
||||
export interface ExtendWebpackConfigOptions extends ExtendConfigOptions {
|
||||
/**
|
||||
* Install plugin on server side
|
||||
*
|
||||
* @default true
|
||||
*/
|
||||
server?: boolean
|
||||
/**
|
||||
* Install plugin on client side
|
||||
*
|
||||
* @default true
|
||||
*/
|
||||
client?: boolean
|
||||
/**
|
||||
* Install plugin on modern build
|
||||
*
|
||||
* @default true
|
||||
* @deprecated Nuxt 2 only
|
||||
*/
|
||||
modern?: boolean
|
||||
}
|
||||
|
||||
export interface ExtendViteConfigOptions extends ExtendConfigOptions {}
|
||||
|
||||
/**
|
||||
* Extend Webpack config
|
||||
*
|
||||
* The fallback function might be called multiple times
|
||||
* when applying to both client and server builds.
|
||||
*/
|
||||
export function extendWebpackConfig (
|
||||
fn: ((config: WebpackConfig)=> void),
|
||||
options: ExtendWebpackConfigOptions = {}
|
||||
) {
|
||||
const nuxt = useNuxt()
|
||||
|
||||
if (options.dev === false && nuxt.options.dev) {
|
||||
return
|
||||
}
|
||||
if (options.build === false && nuxt.options.build) {
|
||||
return
|
||||
}
|
||||
|
||||
nuxt.hook('webpack:config', (configs: WebpackConfig[]) => {
|
||||
if (options.server !== false) {
|
||||
const config = configs.find(i => i.name === 'server')
|
||||
if (config) {
|
||||
fn(config)
|
||||
}
|
||||
}
|
||||
if (options.client !== false) {
|
||||
const config = configs.find(i => i.name === 'client')
|
||||
if (config) {
|
||||
fn(config)
|
||||
}
|
||||
}
|
||||
// Nuxt 2 backwards compatibility
|
||||
if (options.modern !== false) {
|
||||
const config = configs.find(i => i.name === 'modern')
|
||||
if (config) {
|
||||
fn(config)
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* Extend Vite config
|
||||
*/
|
||||
export function extendViteConfig (
|
||||
fn: ((config: ViteConfig) => void),
|
||||
options: ExtendViteConfigOptions = {}
|
||||
) {
|
||||
const nuxt = useNuxt()
|
||||
|
||||
if (options.dev === false && nuxt.options.dev) {
|
||||
return
|
||||
}
|
||||
if (options.build === false && nuxt.options.build) {
|
||||
return
|
||||
}
|
||||
|
||||
nuxt.hook('vite:extend', ({ config }) => fn(config))
|
||||
}
|
||||
|
||||
/**
|
||||
* Append Webpack plugin to the config.
|
||||
*/
|
||||
export function addWebpackPlugin (plugin: WebpackPluginInstance, options?: ExtendWebpackConfigOptions) {
|
||||
extendWebpackConfig((config) => {
|
||||
config.plugins = config.plugins || []
|
||||
config.plugins.push(plugin)
|
||||
}, options)
|
||||
}
|
||||
|
||||
/**
|
||||
* Append Vite plugin to the config.
|
||||
*/
|
||||
export function addVitePlugin (plugin: VitePlugin, options?: ExtendViteConfigOptions) {
|
||||
extendViteConfig((config) => {
|
||||
config.plugins = config.plugins || []
|
||||
config.plugins.push(plugin)
|
||||
}, options)
|
||||
}
|
65
packages/kit/src/compatibility.ts
Normal file
65
packages/kit/src/compatibility.ts
Normal file
@ -0,0 +1,65 @@
|
||||
import satisfies from 'semver/functions/satisfies.js' // npm/node-semver#381
|
||||
import type { Nuxt, NuxtCompatibilityConstraints, NuxtCompatibilityIssues } from '@nuxt/schema'
|
||||
import { useNuxt } from './context'
|
||||
|
||||
/**
|
||||
* Check version constraints and return incompatibility issues as an array
|
||||
*/
|
||||
export function checkNuxtCompatibilityIssues (constraints: NuxtCompatibilityConstraints, nuxt: Nuxt = useNuxt()): NuxtCompatibilityIssues {
|
||||
const issues: NuxtCompatibilityIssues = []
|
||||
if (constraints.nuxt) {
|
||||
const nuxtVersion = getNuxtVersion(nuxt)
|
||||
const nuxtSemanticVersion = nuxtVersion.split('-').shift()
|
||||
if (!satisfies(nuxtSemanticVersion, constraints.nuxt)) {
|
||||
issues.push({
|
||||
name: 'nuxt',
|
||||
message: `Nuxt version \`${constraints.nuxt}\` is required but currently using \`${nuxtVersion}\``
|
||||
})
|
||||
}
|
||||
}
|
||||
issues.toString = () => issues.map(issue => ` - [${issue.name}] ${issue.message}`).join('\n')
|
||||
return issues
|
||||
}
|
||||
|
||||
/**
|
||||
* Check version constraints and throw a detailed error if has any, otherwise returns true
|
||||
*/
|
||||
export function ensureNuxtCompatibility (constraints: NuxtCompatibilityConstraints, nuxt: Nuxt = useNuxt()): true {
|
||||
const issues = checkNuxtCompatibilityIssues(constraints, nuxt)
|
||||
if (issues.length) {
|
||||
throw new Error('Nuxt compatibility issues found:\n' + issues.toString())
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
/**
|
||||
* Check version constraints and return true if passed, otherwise returns false
|
||||
*/
|
||||
export function hasNuxtCompatibility (constraints: NuxtCompatibilityConstraints, nuxt: Nuxt = useNuxt()) {
|
||||
return !checkNuxtCompatibilityIssues(constraints, nuxt).length
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if current nuxt instance is version 2 legacy
|
||||
*/
|
||||
export function isNuxt2 (nuxt: Nuxt = useNuxt()) {
|
||||
return getNuxtVersion(nuxt).startsWith('2.')
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if current nuxt instance is version 3
|
||||
*/
|
||||
export function isNuxt3 (nuxt: Nuxt = useNuxt()) {
|
||||
return getNuxtVersion(nuxt).startsWith('3.')
|
||||
}
|
||||
|
||||
/**
|
||||
* Get nuxt version
|
||||
*/
|
||||
export function getNuxtVersion (nuxt: Nuxt | any = useNuxt() /* TODO: LegacyNuxt */) {
|
||||
const version = (nuxt?._version || nuxt?.version || nuxt?.constructor?.version || '').replace(/^v/g, '')
|
||||
if (!version) {
|
||||
throw new Error('Cannot determine nuxt version! Is currect instance passed?')
|
||||
}
|
||||
return version
|
||||
}
|
62
packages/kit/src/components.ts
Normal file
62
packages/kit/src/components.ts
Normal file
@ -0,0 +1,62 @@
|
||||
import { pascalCase, kebabCase } from 'scule'
|
||||
import type { ComponentsDir, Component } from '@nuxt/schema'
|
||||
import { useNuxt } from './context'
|
||||
import { ensureNuxtCompatibility } from './compatibility'
|
||||
|
||||
/**
|
||||
* Register a directory to be scanned for components and imported only when used.
|
||||
*
|
||||
* Requires Nuxt 2.13+
|
||||
*/
|
||||
export function addComponentsDir (dir: ComponentsDir) {
|
||||
const nuxt = useNuxt()
|
||||
ensureNuxtCompatibility({ nuxt: '>=2.13' }, nuxt)
|
||||
nuxt.options.components = nuxt.options.components || []
|
||||
nuxt.hook('components:dirs', (dirs) => { dirs.push(dir) })
|
||||
}
|
||||
|
||||
export type AddComponentOptions = { name: string, filePath: string } & Partial<Exclude<Component,
|
||||
'shortPath' | 'async' | 'level' | 'import' | 'asyncImport'
|
||||
>>
|
||||
|
||||
/**
|
||||
* Register a directory to be scanned for components and imported only when used.
|
||||
*
|
||||
* Requires Nuxt 2.13+
|
||||
*/
|
||||
export function addComponent (opts: AddComponentOptions) {
|
||||
const nuxt = useNuxt()
|
||||
ensureNuxtCompatibility({ nuxt: '>=2.13' }, nuxt)
|
||||
nuxt.options.components = nuxt.options.components || []
|
||||
|
||||
// Apply defaults
|
||||
const component: Component = {
|
||||
export: opts.export || 'default',
|
||||
chunkName: 'components/' + kebabCase(opts.name),
|
||||
global: opts.global ?? false,
|
||||
kebabName: kebabCase(opts.name || ''),
|
||||
pascalName: pascalCase(opts.name || ''),
|
||||
prefetch: false,
|
||||
preload: false,
|
||||
|
||||
// Nuxt 2 support
|
||||
shortPath: opts.filePath,
|
||||
async: false,
|
||||
level: 0,
|
||||
asyncImport: `() => import('${opts.filePath}').then(r => r['${opts.export || 'default'}'])`,
|
||||
import: `require('${opts.filePath}')['${opts.export || 'default'}']`,
|
||||
|
||||
...opts
|
||||
}
|
||||
|
||||
nuxt.hook('components:extend', (components: Component[]) => {
|
||||
const existingComponent = components.find(c => c.pascalName === component.pascalName || c.kebabName === component.kebabName)
|
||||
if (existingComponent) {
|
||||
const name = existingComponent.pascalName || existingComponent.kebabName
|
||||
console.warn(`Overriding ${name} component.`)
|
||||
Object.assign(existingComponent, component)
|
||||
} else {
|
||||
components.push(component)
|
||||
}
|
||||
})
|
||||
}
|
15
packages/kit/src/context.ts
Normal file
15
packages/kit/src/context.ts
Normal file
@ -0,0 +1,15 @@
|
||||
import { getContext } from 'unctx'
|
||||
import type { Nuxt } from '@nuxt/schema'
|
||||
|
||||
/** Direct access to the Nuxt context - see https://github.com/unjs/unctx. */
|
||||
export const nuxtCtx = getContext<Nuxt>('nuxt')
|
||||
|
||||
/**
|
||||
* Get access to Nuxt (if run within the Nuxt context) - see https://github.com/unjs/unctx.
|
||||
*
|
||||
* @example
|
||||
* ```js
|
||||
* const nuxt = useNuxt()
|
||||
* ```
|
||||
*/
|
||||
export const useNuxt = nuxtCtx.use
|
@ -1,28 +1,24 @@
|
||||
// Augmentations
|
||||
import './types/global'
|
||||
|
||||
// Config
|
||||
export * from './config/load'
|
||||
export * from './config/env'
|
||||
|
||||
// Nuxt
|
||||
export * from './nuxt'
|
||||
|
||||
// Module
|
||||
export * from './module/container'
|
||||
export * from './module/define'
|
||||
export * from './module/install'
|
||||
export * from './module/utils'
|
||||
|
||||
// Loader
|
||||
export * from './loader/config'
|
||||
export * from './loader/nuxt'
|
||||
|
||||
// Utils
|
||||
export * from './utils/cjs'
|
||||
export * from './utils/resolve'
|
||||
export * from './build'
|
||||
export * from './compatibility'
|
||||
export * from './components'
|
||||
export * from './context'
|
||||
export * from './pages'
|
||||
export * from './plugin'
|
||||
export * from './resolve'
|
||||
export * from './server'
|
||||
export * from './template'
|
||||
|
||||
// Types
|
||||
export * from './types/config'
|
||||
export * from './types/hooks'
|
||||
export * from './types/module'
|
||||
export * from './types/nuxt'
|
||||
export * from './types/components'
|
||||
export * from './types/imports'
|
||||
export * from './types/runtime-config'
|
||||
// Internal Utils
|
||||
// TODO
|
||||
export * from './internal/cjs'
|
||||
export * from './internal/template'
|
||||
|
@ -15,6 +15,7 @@ export interface RequireModuleOptions extends ResolveModuleOptions {
|
||||
// native?: boolean
|
||||
/** Clear the require cache (force fresh require) but only if not within `node_modules` */
|
||||
clearCache?: boolean
|
||||
|
||||
/** Automatically de-default the result of requiring the module. */
|
||||
interopDefault?: boolean
|
||||
}
|
@ -1,16 +1,17 @@
|
||||
import { promises as fsp, existsSync } from 'fs'
|
||||
import { resolve } from 'pathe'
|
||||
import dotenv from 'dotenv'
|
||||
import { LoadNuxtConfigOptions } from './load'
|
||||
|
||||
export interface LoadDotEnvOptions {
|
||||
export interface DotenvOptions {
|
||||
/** The project root directory (either absolute or relative to the current working directory). */
|
||||
rootDir: string
|
||||
|
||||
/**
|
||||
* What file to look in for environment variables (either absolute or relative
|
||||
* to the current working directory). For example, `.env`.
|
||||
*/
|
||||
dotenvFile: string | false
|
||||
fileName: string
|
||||
|
||||
/**
|
||||
* Whether to interpolate variables within .env.
|
||||
*
|
||||
@ -22,44 +23,44 @@ export interface LoadDotEnvOptions {
|
||||
* ```
|
||||
*/
|
||||
expand: boolean
|
||||
|
||||
/** An object describing environment variables (key, value pairs). */
|
||||
env: NodeJS.ProcessEnv
|
||||
}
|
||||
|
||||
export type Env = typeof process.env
|
||||
|
||||
/**
|
||||
* Load and interpolate environment variables into `process.env`.
|
||||
* If you need more control (or access to the values), consider using `loadDotenv` instead
|
||||
*
|
||||
* @param rootDir - The project root directory (either absolute or relative to the current working directory).
|
||||
*/
|
||||
export async function loadEnv (rootDir: string, options: LoadNuxtConfigOptions['envConfig'] = {}) {
|
||||
export async function setupDotenv (options: DotenvOptions): Promise<Env> {
|
||||
const targetEnv = options.env ?? process.env
|
||||
|
||||
// Load env
|
||||
const env = await loadDotenv({
|
||||
rootDir,
|
||||
dotenvFile: options.dotenv ?? '.env',
|
||||
rootDir: options.rootDir,
|
||||
fileName: options.fileName ?? '.env',
|
||||
env: targetEnv,
|
||||
expand: options.expand ?? true
|
||||
})
|
||||
|
||||
// Fill process.env so it is accessible in nuxt.config
|
||||
// Fill process.env
|
||||
for (const key in env) {
|
||||
if (!key.startsWith('_') && targetEnv[key] === undefined) {
|
||||
targetEnv[key] = env[key]
|
||||
}
|
||||
}
|
||||
|
||||
return env
|
||||
}
|
||||
|
||||
/** Load environment variables into an object. */
|
||||
export async function loadDotenv (opts: LoadDotEnvOptions) {
|
||||
if (!opts.dotenvFile) {
|
||||
return
|
||||
}
|
||||
|
||||
export async function loadDotenv (opts: DotenvOptions): Promise<Env> {
|
||||
const env = Object.create(null)
|
||||
|
||||
const dotenvFile = resolve(opts.rootDir, opts.dotenvFile)
|
||||
const dotenvFile = resolve(opts.rootDir, opts.fileName)
|
||||
|
||||
if (existsSync(dotenvFile)) {
|
||||
const parsed = dotenv.parse(await fsp.readFile(dotenvFile, 'utf-8'))
|
42
packages/kit/src/internal/template.ts
Normal file
42
packages/kit/src/internal/template.ts
Normal file
@ -0,0 +1,42 @@
|
||||
import { promises as fsp } from 'fs'
|
||||
import lodashTemplate from 'lodash.template'
|
||||
import hash from 'hash-sum'
|
||||
import { camelCase } from 'scule'
|
||||
import { basename, extname } from 'pathe'
|
||||
|
||||
import type { NuxtTemplate } from '@nuxt/schema'
|
||||
|
||||
export async function compileTemplate (template: NuxtTemplate, ctx: any) {
|
||||
const data = { ...ctx, options: template.options }
|
||||
if (template.src) {
|
||||
try {
|
||||
const srcContents = await fsp.readFile(template.src, 'utf-8')
|
||||
return lodashTemplate(srcContents, {})(data)
|
||||
} catch (err) {
|
||||
console.error('Error compiling template: ', template)
|
||||
throw err
|
||||
}
|
||||
}
|
||||
if (template.getContents) {
|
||||
return template.getContents(data)
|
||||
}
|
||||
throw new Error('Invalid template: ' + JSON.stringify(template))
|
||||
}
|
||||
|
||||
const serialize = (data: any) => JSON.stringify(data, null, 2).replace(/"{(.+)}"/g, '$1')
|
||||
|
||||
const importName = (src: string) => `${camelCase(basename(src, extname(src))).replace(/[^a-zA-Z?\d\s:]/g, '')}_${hash(src)}`
|
||||
|
||||
const importSources = (sources: string | string[], { lazy = false } = {}) => {
|
||||
if (!Array.isArray(sources)) {
|
||||
sources = [sources]
|
||||
}
|
||||
return sources.map((src) => {
|
||||
if (lazy) {
|
||||
return `const ${importName(src)} = () => import('${src}' /* webpackChunkName: '${src}' */)`
|
||||
}
|
||||
return `import ${importName(src)} from '${src}'`
|
||||
}).join('\n')
|
||||
}
|
||||
|
||||
export const templateUtils = { serialize, importName, importSources }
|
@ -3,29 +3,31 @@ import { resolve } from 'pathe'
|
||||
import defu from 'defu'
|
||||
import { applyDefaults } from 'untyped'
|
||||
import * as rc from 'rc9'
|
||||
import { tryResolveModule, requireModule, scanRequireTree } from '../utils/cjs'
|
||||
import { NuxtOptions } from '../types/config'
|
||||
import nuxtConfigSchema from './schema'
|
||||
import { loadEnv } from './env'
|
||||
import type { NuxtOptions } from '@nuxt/schema'
|
||||
import { NuxtConfigSchema } from '@nuxt/schema'
|
||||
import { tryResolveModule, requireModule, scanRequireTree } from '../internal/cjs'
|
||||
import { setupDotenv, DotenvOptions } from '../internal/dotenv'
|
||||
|
||||
export interface LoadNuxtConfigOptions {
|
||||
/** Your project root directory (either absolute or relative to the current working directory). */
|
||||
rootDir?: string
|
||||
|
||||
/** The path to your `nuxt.config` file (either absolute or relative to your project `rootDir`). */
|
||||
configFile?: string
|
||||
|
||||
/** Any overrides to your Nuxt configuration. */
|
||||
config?: Record<string, any>
|
||||
envConfig?: {
|
||||
dotenv?: string | false
|
||||
env?: Record<string, string | undefined>
|
||||
expand?: boolean
|
||||
}
|
||||
|
||||
/** Configuration for loading dotenv */
|
||||
dotenv?: DotenvOptions | false
|
||||
}
|
||||
|
||||
export async function loadNuxtConfig (opts: LoadNuxtConfigOptions): Promise<NuxtOptions> {
|
||||
const rootDir = resolve(process.cwd(), opts.rootDir || '.')
|
||||
|
||||
await loadEnv(rootDir, opts.envConfig)
|
||||
if (opts.dotenv !== false) {
|
||||
await setupDotenv({ rootDir, ...opts.dotenv })
|
||||
}
|
||||
|
||||
const nuxtConfigFile = tryResolveModule(resolve(rootDir, opts.configFile || 'nuxt.config'))
|
||||
|
||||
@ -58,5 +60,5 @@ export async function loadNuxtConfig (opts: LoadNuxtConfigOptions): Promise<Nuxt
|
||||
}
|
||||
|
||||
// Resolve and apply defaults
|
||||
return applyDefaults(nuxtConfigSchema, nuxtConfig) as NuxtOptions
|
||||
return applyDefaults(NuxtConfigSchema, nuxtConfig) as NuxtOptions
|
||||
}
|
@ -1,22 +1,7 @@
|
||||
import { getContext } from 'unctx'
|
||||
import { readPackageJSON, resolvePackageJSON } from 'pkg-types'
|
||||
import { importModule, tryImportModule, RequireModuleOptions } from './utils/cjs'
|
||||
import type { Nuxt } from './types/nuxt'
|
||||
import type { NuxtConfig } from './types/config'
|
||||
import type { LoadNuxtConfigOptions } from './config/load'
|
||||
|
||||
/** Direct access to the Nuxt context - see https://github.com/unjs/unctx. */
|
||||
export const nuxtCtx = getContext<Nuxt>('nuxt')
|
||||
|
||||
/**
|
||||
* Get access to Nuxt (if run within the Nuxt context) - see https://github.com/unjs/unctx.
|
||||
*
|
||||
* @example
|
||||
* ```js
|
||||
* const nuxt = useNuxt()
|
||||
* ```
|
||||
*/
|
||||
export const useNuxt = nuxtCtx.use
|
||||
import type { Nuxt, NuxtConfig } from '@nuxt/schema'
|
||||
import { importModule, tryImportModule, RequireModuleOptions } from '../internal/cjs'
|
||||
import type { LoadNuxtConfigOptions } from './config'
|
||||
|
||||
export interface LoadNuxtOptions extends LoadNuxtConfigOptions {
|
||||
rootDir: string
|
||||
@ -52,7 +37,7 @@ export async function loadNuxt (opts: LoadNuxtOptions): Promise<Nuxt> {
|
||||
for: opts.dev ? 'dev' : 'build',
|
||||
configOverrides: opts.config,
|
||||
ready: opts.ready,
|
||||
envConfig: opts.envConfig
|
||||
envConfig: opts.dotenv // TODO: Backward format convertion
|
||||
})
|
||||
|
||||
return nuxt as Nuxt
|
@ -1,36 +1,27 @@
|
||||
import { parse, relative } from 'pathe'
|
||||
import consola from 'consola'
|
||||
import type { Nuxt, NuxtPluginTemplate, NuxtTemplate } from '../types/nuxt'
|
||||
import { chainFn } from '../utils/task'
|
||||
import { isNuxt2, addTemplate, addPluginTemplate, addServerMiddleware } from './utils'
|
||||
import type { Nuxt, NuxtPluginTemplate, NuxtTemplate, ModuleContainer } from '@nuxt/schema'
|
||||
import { chainFn } from '../internal/task'
|
||||
import { addTemplate } from '../template'
|
||||
import { addServerMiddleware } from '../server'
|
||||
import { isNuxt2 } from '../compatibility'
|
||||
import { addPluginTemplate } from '../plugin'
|
||||
|
||||
import { installModule } from './install'
|
||||
|
||||
/** Legacy ModuleContainer for backwards compatibility with existing Nuxt 2 modules. */
|
||||
export function createModuleContainer (nuxt: Nuxt) {
|
||||
return {
|
||||
export function createModuleContainer (nuxt: Nuxt): ModuleContainer {
|
||||
return <ModuleContainer>{
|
||||
nuxt,
|
||||
options: nuxt.options,
|
||||
|
||||
/**
|
||||
* Returns a resolved promise immediately.
|
||||
*
|
||||
* @deprecated
|
||||
*/
|
||||
ready () {
|
||||
return Promise.resolve()
|
||||
},
|
||||
ready () { return Promise.resolve() },
|
||||
addVendor () {},
|
||||
|
||||
/** @deprecated */
|
||||
addVendor () {
|
||||
console.warn('addVendor has been deprecated and has no effect.')
|
||||
},
|
||||
requireModule: installModule,
|
||||
addModule: installModule,
|
||||
|
||||
addServerMiddleware,
|
||||
|
||||
/**
|
||||
* Renders given template using lodash template during build into the project buildDir (`.nuxt`).
|
||||
*
|
||||
* If a fileName is not provided or the template is string, target file name defaults to
|
||||
* [dirName].[fileName].[pathHash].[ext].
|
||||
*/
|
||||
addTemplate (template: string | NuxtTemplate) {
|
||||
if (typeof template === 'string') {
|
||||
template = { src: template }
|
||||
@ -41,29 +32,10 @@ export function createModuleContainer (nuxt: Nuxt) {
|
||||
return addTemplate(template)
|
||||
},
|
||||
|
||||
/**
|
||||
* Registers a plugin template and prepends it to the plugins[] array.
|
||||
*
|
||||
* Note: You can use mode or .client and .server modifiers with fileName option
|
||||
* to use plugin only in client or server side.
|
||||
*
|
||||
* If you choose to specify a fileName, you can configure a custom path for the
|
||||
* fileName too, so you can choose the folder structure inside .nuxt folder in
|
||||
* order to prevent name collisioning:
|
||||
*
|
||||
* @example
|
||||
* ```js
|
||||
* this.addPlugin({
|
||||
* src: path.resolve(__dirname, 'templates/foo.js'),
|
||||
* fileName: 'foo.server.js' // [optional] only include in server bundle
|
||||
* })
|
||||
* ```
|
||||
*/
|
||||
addPlugin (pluginTemplate: NuxtPluginTemplate): NuxtPluginTemplate {
|
||||
return addPluginTemplate(pluginTemplate)
|
||||
},
|
||||
|
||||
/** Register a custom layout. If its name is 'error' it will override the default error layout. */
|
||||
addLayout (tmpl: NuxtTemplate, name: string) {
|
||||
const { filename, src } = addTemplate(tmpl)
|
||||
const layoutName = name || parse(src).name
|
||||
@ -72,36 +44,22 @@ export function createModuleContainer (nuxt: Nuxt) {
|
||||
if (layout) {
|
||||
consola.warn(`Duplicate layout registration, "${layoutName}" has been registered as "${layout}"`)
|
||||
}
|
||||
|
||||
// Add to nuxt layouts
|
||||
nuxt.options.layouts[layoutName] = `./${filename}`
|
||||
|
||||
// If error layout, set ErrorPage
|
||||
if (name === 'error') {
|
||||
this.addErrorLayout(filename)
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Set the layout that will render Nuxt errors. It should already have been added via addLayout or addTemplate.
|
||||
*
|
||||
* @param dst - Path to layout file within the buildDir (`.nuxt/<dst>.vue`)
|
||||
*/
|
||||
addErrorLayout (dst: string) {
|
||||
const relativeBuildDir = relative(nuxt.options.rootDir, nuxt.options.buildDir)
|
||||
nuxt.options.ErrorPage = `~/${relativeBuildDir}/${dst}`
|
||||
},
|
||||
|
||||
/** Adds a new server middleware to the end of the server middleware array. */
|
||||
addServerMiddleware,
|
||||
|
||||
/** Allows extending webpack build config by chaining `options.build.extend` function. */
|
||||
extendBuild (fn) {
|
||||
// @ts-ignore
|
||||
nuxt.options.build.extend = chainFn(nuxt.options.build.extend, fn)
|
||||
},
|
||||
|
||||
/** Allows extending routes by chaining `options.build.extendRoutes` function. */
|
||||
extendRoutes (fn) {
|
||||
if (isNuxt2(nuxt)) {
|
||||
nuxt.options.router.extendRoutes = chainFn(nuxt.options.router.extendRoutes, fn)
|
||||
@ -113,14 +71,6 @@ export function createModuleContainer (nuxt: Nuxt) {
|
||||
}
|
||||
})
|
||||
}
|
||||
},
|
||||
|
||||
/** `requireModule` is a shortcut for `addModule` */
|
||||
requireModule: installModule,
|
||||
|
||||
/** Registers a module. moduleOpts can be a string or an array ([src, options]). */
|
||||
addModule: installModule
|
||||
}
|
||||
}
|
||||
|
||||
export type ModuleContainer = ReturnType<typeof createModuleContainer>
|
||||
}
|
||||
|
@ -3,10 +3,10 @@ import defu from 'defu'
|
||||
import { applyDefaults } from 'untyped'
|
||||
import consola from 'consola'
|
||||
import { dirname } from 'pathe'
|
||||
import { useNuxt, nuxtCtx } from '../nuxt'
|
||||
import type { Nuxt, NuxtTemplate } from '../types/nuxt'
|
||||
import type { NuxtModule, LegacyNuxtModule, ModuleOptions } from '../types/module'
|
||||
import { checkNuxtCompatibilityIssues, compileTemplate, isNuxt2, templateUtils } from './utils'
|
||||
import type { Nuxt, NuxtTemplate, NuxtModule, LegacyNuxtModule, ModuleOptions } from '@nuxt/schema'
|
||||
import { useNuxt, nuxtCtx } from '../context'
|
||||
import { isNuxt2, checkNuxtCompatibilityIssues } from '../compatibility'
|
||||
import { templateUtils, compileTemplate } from '../internal/template'
|
||||
|
||||
/**
|
||||
* Define a Nuxt module, automatically merging defaults with user provided options, installing
|
||||
|
@ -1,7 +1,6 @@
|
||||
import { resolveModule, requireModule, importModule } from '../utils/cjs'
|
||||
import { resolveAlias } from '../utils/resolve'
|
||||
import type { LegacyNuxtModule, NuxtModule, ModuleMeta, ModuleInstallOptions, ModuleOptions, ModuleSrc } from '../types/module'
|
||||
import type { Nuxt } from '../types/nuxt'
|
||||
import type { LegacyNuxtModule, NuxtModule, ModuleMeta, ModuleInstallOptions, ModuleOptions, ModuleSrc, Nuxt } from '@nuxt/schema'
|
||||
import { resolveModule, requireModule, importModule } from '../internal/cjs'
|
||||
import { resolveAlias } from '../resolve'
|
||||
import { defineNuxtModule } from './define'
|
||||
import { createModuleContainer } from './container'
|
||||
|
||||
|
@ -1,446 +0,0 @@
|
||||
import { existsSync, promises as fsp } from 'fs'
|
||||
import { basename, extname, normalize, parse, resolve } from 'pathe'
|
||||
import lodashTemplate from 'lodash.template'
|
||||
import hash from 'hash-sum'
|
||||
import { pascalCase, camelCase, kebabCase } from 'scule'
|
||||
import type { WebpackPluginInstance, Configuration as WebpackConfig } from 'webpack'
|
||||
import type { Plugin as VitePlugin, UserConfig as ViteConfig } from 'vite'
|
||||
import satisfies from 'semver/functions/satisfies.js' // npm/node-semver#381
|
||||
import { NuxtCompatibilityConstraints, NuxtCompatibilityIssues } from '../types/module'
|
||||
import { Nuxt } from '../types/nuxt'
|
||||
import { useNuxt } from '../nuxt'
|
||||
import type { NuxtTemplate, NuxtPlugin, NuxtPluginTemplate } from '../types/nuxt'
|
||||
import type { ComponentsDir, Component } from '../types/components'
|
||||
import type { NuxtHooks } from '../types/hooks'
|
||||
|
||||
/**
|
||||
* Renders given template using lodash template during build into the project buildDir
|
||||
*/
|
||||
export function addTemplate (_template: NuxtTemplate | string) {
|
||||
const nuxt = useNuxt()
|
||||
|
||||
// Noprmalize template
|
||||
const template = normalizeTemplate(_template)
|
||||
|
||||
// Remove any existing template with the same filename
|
||||
nuxt.options.build.templates = nuxt.options.build.templates
|
||||
.filter(p => normalizeTemplate(p).filename !== template.filename)
|
||||
|
||||
// Add to templates array
|
||||
nuxt.options.build.templates.push(template)
|
||||
|
||||
return template
|
||||
}
|
||||
|
||||
/**
|
||||
* Normalize a nuxt template object
|
||||
*/
|
||||
export function normalizeTemplate (template: NuxtTemplate | string): NuxtTemplate {
|
||||
if (!template) {
|
||||
throw new Error('Invalid template: ' + JSON.stringify(template))
|
||||
}
|
||||
|
||||
// Normalize
|
||||
if (typeof template === 'string') {
|
||||
template = { src: template }
|
||||
} else {
|
||||
template = { ...template }
|
||||
}
|
||||
|
||||
// Use src if provided
|
||||
if (template.src) {
|
||||
if (!existsSync(template.src)) {
|
||||
throw new Error('Template not found: ' + template.src)
|
||||
}
|
||||
if (!template.filename) {
|
||||
const srcPath = parse(template.src)
|
||||
template.filename = template.fileName ||
|
||||
`${basename(srcPath.dir)}.${srcPath.name}.${hash(template.src)}${srcPath.ext}`
|
||||
}
|
||||
}
|
||||
|
||||
if (!template.src && !template.getContents) {
|
||||
throw new Error('Invalid template. Either getContents or src options should be provided: ' + JSON.stringify(template))
|
||||
}
|
||||
|
||||
if (!template.filename) {
|
||||
throw new Error('Invalid template. Either filename should be provided: ' + JSON.stringify(template))
|
||||
}
|
||||
|
||||
// Resolve dst
|
||||
if (!template.dst) {
|
||||
const nuxt = useNuxt()
|
||||
template.dst = resolve(nuxt.options.buildDir, template.filename)
|
||||
}
|
||||
|
||||
return template
|
||||
}
|
||||
|
||||
/**
|
||||
* Normalize a nuxt plugin object
|
||||
*/
|
||||
export function normalizePlugin (plugin: NuxtPlugin | string): NuxtPlugin {
|
||||
// Normalize src
|
||||
if (typeof plugin === 'string') {
|
||||
plugin = { src: plugin }
|
||||
} else {
|
||||
plugin = { ...plugin }
|
||||
}
|
||||
|
||||
if (!plugin.src) {
|
||||
throw new Error('Invalid plugin. src option is required: ' + JSON.stringify(plugin))
|
||||
}
|
||||
|
||||
// Normalize full path to plugin
|
||||
plugin.src = normalize(plugin.src)
|
||||
|
||||
// Normalize mode
|
||||
if (plugin.ssr) {
|
||||
plugin.mode = 'server'
|
||||
}
|
||||
if (!plugin.mode) {
|
||||
const [, mode = 'all'] = plugin.src.match(/\.(server|client)(\.\w+)*$/) || []
|
||||
plugin.mode = mode as 'all' | 'client' | 'server'
|
||||
}
|
||||
|
||||
return plugin
|
||||
}
|
||||
|
||||
/**
|
||||
* Registers a nuxt plugin and to the plugins array.
|
||||
*
|
||||
* Note: You can use mode or .client and .server modifiers with fileName option
|
||||
* to use plugin only in client or server side.
|
||||
*
|
||||
* Note: By default plugin is prepended to the plugins array. You can use second argument to append (push) instead.
|
||||
*
|
||||
* @example
|
||||
* ```js
|
||||
* addPlugin({
|
||||
* src: path.resolve(__dirname, 'templates/foo.js'),
|
||||
* filename: 'foo.server.js' // [optional] only include in server bundle
|
||||
* })
|
||||
* ```
|
||||
*/
|
||||
export interface AddPluginOptions { append?: Boolean }
|
||||
export function addPlugin (_plugin: NuxtPlugin | string, opts: AddPluginOptions = {}) {
|
||||
const nuxt = useNuxt()
|
||||
|
||||
// Normalize plugin
|
||||
const plugin = normalizePlugin(_plugin)
|
||||
|
||||
// Remove any existing plugin with the same src
|
||||
nuxt.options.plugins = nuxt.options.plugins.filter(p => normalizePlugin(p).src !== plugin.src)
|
||||
|
||||
// Prepend to array by default to be before user provided plugins since is usually used by modules
|
||||
nuxt.options.plugins[opts.append ? 'push' : 'unshift'](plugin)
|
||||
|
||||
return plugin
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a template and registers as a nuxt plugin.
|
||||
*/
|
||||
export function addPluginTemplate (plugin: NuxtPluginTemplate | string, opts: AddPluginOptions = {}): NuxtPluginTemplate {
|
||||
if (typeof plugin === 'string') {
|
||||
plugin = { src: plugin }
|
||||
}
|
||||
|
||||
// Update plugin src to template destination
|
||||
plugin.src = addTemplate(plugin).dst
|
||||
|
||||
return addPlugin(plugin, opts)
|
||||
}
|
||||
|
||||
/** Adds a new server middleware to the end of the server middleware array. */
|
||||
export function addServerMiddleware (middleware) {
|
||||
useNuxt().options.serverMiddleware.push(middleware)
|
||||
}
|
||||
|
||||
export interface ExtendConfigOptions {
|
||||
/**
|
||||
* Install plugin on dev
|
||||
*
|
||||
* @default true
|
||||
*/
|
||||
dev?: boolean
|
||||
/**
|
||||
* Install plugin on build
|
||||
*
|
||||
* @default true
|
||||
*/
|
||||
build?: boolean
|
||||
}
|
||||
|
||||
export interface ExtendWebpackConfigOptions extends ExtendConfigOptions {
|
||||
/**
|
||||
* Install plugin on server side
|
||||
*
|
||||
* @default true
|
||||
*/
|
||||
server?: boolean
|
||||
/**
|
||||
* Install plugin on client side
|
||||
*
|
||||
* @default true
|
||||
*/
|
||||
client?: boolean
|
||||
/**
|
||||
* Install plugin on modern build
|
||||
*
|
||||
* @default true
|
||||
* @deprecated Nuxt 2 only
|
||||
*/
|
||||
modern?: boolean
|
||||
}
|
||||
|
||||
export interface ExtendViteConfigOptions extends ExtendConfigOptions {}
|
||||
|
||||
/**
|
||||
* Extend Webpack config
|
||||
*
|
||||
* The fallback function might be called multiple times
|
||||
* when applying to both client and server builds.
|
||||
*/
|
||||
export function extendWebpackConfig (
|
||||
fn: ((config: WebpackConfig)=> void),
|
||||
options: ExtendWebpackConfigOptions = {}
|
||||
) {
|
||||
const nuxt = useNuxt()
|
||||
|
||||
if (options.dev === false && nuxt.options.dev) {
|
||||
return
|
||||
}
|
||||
if (options.build === false && nuxt.options.build) {
|
||||
return
|
||||
}
|
||||
|
||||
nuxt.hook('webpack:config', (configs: WebpackConfig[]) => {
|
||||
if (options.server !== false) {
|
||||
const config = configs.find(i => i.name === 'server')
|
||||
if (config) {
|
||||
fn(config)
|
||||
}
|
||||
}
|
||||
if (options.client !== false) {
|
||||
const config = configs.find(i => i.name === 'client')
|
||||
if (config) {
|
||||
fn(config)
|
||||
}
|
||||
}
|
||||
// Nuxt 2 backwards compatibility
|
||||
if (options.modern !== false) {
|
||||
const config = configs.find(i => i.name === 'modern')
|
||||
if (config) {
|
||||
fn(config)
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* Extend Vite config
|
||||
*/
|
||||
export function extendViteConfig (
|
||||
fn: ((config: ViteConfig) => void),
|
||||
options: ExtendViteConfigOptions = {}
|
||||
) {
|
||||
const nuxt = useNuxt()
|
||||
|
||||
if (options.dev === false && nuxt.options.dev) {
|
||||
return
|
||||
}
|
||||
if (options.build === false && nuxt.options.build) {
|
||||
return
|
||||
}
|
||||
|
||||
nuxt.hook('vite:extend', ({ config }) => fn(config))
|
||||
}
|
||||
|
||||
/**
|
||||
* Append Webpack plugin to the config.
|
||||
*/
|
||||
export function addWebpackPlugin (plugin: WebpackPluginInstance, options?: ExtendWebpackConfigOptions) {
|
||||
extendWebpackConfig((config) => {
|
||||
config.plugins = config.plugins || []
|
||||
config.plugins.push(plugin)
|
||||
}, options)
|
||||
}
|
||||
|
||||
/**
|
||||
* Append Vite plugin to the config.
|
||||
*/
|
||||
export function addVitePlugin (plugin: VitePlugin, options?: ExtendViteConfigOptions) {
|
||||
extendViteConfig((config) => {
|
||||
config.plugins = config.plugins || []
|
||||
config.plugins.push(plugin)
|
||||
}, options)
|
||||
}
|
||||
|
||||
export async function compileTemplate (template: NuxtTemplate, ctx: any) {
|
||||
const data = { ...ctx, options: template.options }
|
||||
if (template.src) {
|
||||
try {
|
||||
const srcContents = await fsp.readFile(template.src, 'utf-8')
|
||||
return lodashTemplate(srcContents, {})(data)
|
||||
} catch (err) {
|
||||
console.error('Error compiling template: ', template)
|
||||
throw err
|
||||
}
|
||||
}
|
||||
if (template.getContents) {
|
||||
return template.getContents(data)
|
||||
}
|
||||
throw new Error('Invalid template: ' + JSON.stringify(template))
|
||||
}
|
||||
|
||||
/**
|
||||
* Register a directory to be scanned for components and imported only when used.
|
||||
*
|
||||
* Requires Nuxt 2.13+
|
||||
*/
|
||||
export function addComponentsDir (dir: ComponentsDir) {
|
||||
const nuxt = useNuxt()
|
||||
ensureNuxtCompatibility({ nuxt: '>=2.13' }, nuxt)
|
||||
nuxt.options.components = nuxt.options.components || []
|
||||
nuxt.hook('components:dirs', (dirs) => { dirs.push(dir) })
|
||||
}
|
||||
|
||||
export type AddComponentOptions = { name: string, filePath: string } & Partial<Exclude<Component,
|
||||
'shortPath' | 'async' | 'level' | 'import' | 'asyncImport'
|
||||
>>
|
||||
|
||||
/**
|
||||
* Register a directory to be scanned for components and imported only when used.
|
||||
*
|
||||
* Requires Nuxt 2.13+
|
||||
*/
|
||||
export function addComponent (opts: AddComponentOptions) {
|
||||
const nuxt = useNuxt()
|
||||
ensureNuxtCompatibility({ nuxt: '>=2.13' }, nuxt)
|
||||
nuxt.options.components = nuxt.options.components || []
|
||||
|
||||
// Apply defaults
|
||||
const component: Component = {
|
||||
export: opts.export || 'default',
|
||||
chunkName: 'components/' + kebabCase(opts.name),
|
||||
global: opts.global ?? false,
|
||||
kebabName: kebabCase(opts.name || ''),
|
||||
pascalName: pascalCase(opts.name || ''),
|
||||
prefetch: false,
|
||||
preload: false,
|
||||
|
||||
// Nuxt 2 support
|
||||
shortPath: opts.filePath,
|
||||
async: false,
|
||||
level: 0,
|
||||
asyncImport: `() => import('${opts.filePath}').then(r => r['${opts.export || 'default'}'])`,
|
||||
import: `require('${opts.filePath}')['${opts.export || 'default'}']`,
|
||||
|
||||
...opts
|
||||
}
|
||||
|
||||
nuxt.hook('components:extend', (components: Component[]) => {
|
||||
const existingComponent = components.find(c => c.pascalName === component.pascalName || c.kebabName === component.kebabName)
|
||||
if (existingComponent) {
|
||||
const name = existingComponent.pascalName || existingComponent.kebabName
|
||||
console.warn(`Overriding ${name} component.`)
|
||||
Object.assign(existingComponent, component)
|
||||
} else {
|
||||
components.push(component)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
export function extendPages (cb: NuxtHooks['pages:extend']) {
|
||||
const nuxt = useNuxt()
|
||||
if (isNuxt2(nuxt)) {
|
||||
nuxt.hook('build:extendRoutes', cb)
|
||||
} else {
|
||||
nuxt.hook('pages:extend', cb)
|
||||
}
|
||||
}
|
||||
|
||||
const serialize = (data: any) => JSON.stringify(data, null, 2).replace(/"{(.+)}"/g, '$1')
|
||||
|
||||
const importName = (src: string) => `${camelCase(basename(src, extname(src))).replace(/[^a-zA-Z?\d\s:]/g, '')}_${hash(src)}`
|
||||
|
||||
const importSources = (sources: string | string[], { lazy = false } = {}) => {
|
||||
if (!Array.isArray(sources)) {
|
||||
sources = [sources]
|
||||
}
|
||||
return sources.map((src) => {
|
||||
if (lazy) {
|
||||
return `const ${importName(src)} = () => import('${src}' /* webpackChunkName: '${src}' */)`
|
||||
}
|
||||
return `import ${importName(src)} from '${src}'`
|
||||
}).join('\n')
|
||||
}
|
||||
|
||||
export const templateUtils = {
|
||||
serialize,
|
||||
importName,
|
||||
importSources
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if current nuxt instance is version 2 legacy
|
||||
*/
|
||||
export function isNuxt2 (nuxt: Nuxt = useNuxt()) {
|
||||
return getNuxtVersion(nuxt).startsWith('2.')
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if current nuxt instance is version 3
|
||||
*/
|
||||
export function isNuxt3 (nuxt: Nuxt = useNuxt()) {
|
||||
return getNuxtVersion(nuxt).startsWith('3.')
|
||||
}
|
||||
|
||||
/**
|
||||
* Get nuxt version
|
||||
*/
|
||||
export function getNuxtVersion (nuxt: Nuxt | any = useNuxt() /* TODO: LegacyNuxt */) {
|
||||
const version = (nuxt?._version || nuxt?.version || nuxt?.constructor?.version || '').replace(/^v/g, '')
|
||||
if (!version) {
|
||||
throw new Error('Cannot determine nuxt version! Is currect instance passed?')
|
||||
}
|
||||
return version
|
||||
}
|
||||
|
||||
/**
|
||||
* Check version constraints and return incompatibility issues as an array
|
||||
*/
|
||||
export function checkNuxtCompatibilityIssues (constraints: NuxtCompatibilityConstraints, nuxt: Nuxt = useNuxt()): NuxtCompatibilityIssues {
|
||||
const issues: NuxtCompatibilityIssues = []
|
||||
if (constraints.nuxt) {
|
||||
const nuxtVersion = getNuxtVersion(nuxt)
|
||||
const nuxtSemanticVersion = nuxtVersion.split('-').shift()
|
||||
if (!satisfies(nuxtSemanticVersion, constraints.nuxt)) {
|
||||
issues.push({
|
||||
name: 'nuxt',
|
||||
message: `Nuxt version \`${constraints.nuxt}\` is required but currently using \`${nuxtVersion}\``
|
||||
})
|
||||
}
|
||||
}
|
||||
issues.toString = () => issues.map(issue => ` - [${issue.name}] ${issue.message}`).join('\n')
|
||||
return issues
|
||||
}
|
||||
|
||||
/**
|
||||
* Check version constraints and throw a detailed error if has any, otherwise returns true
|
||||
*/
|
||||
export function ensureNuxtCompatibility (constraints: NuxtCompatibilityConstraints, nuxt: Nuxt = useNuxt()): true {
|
||||
const issues = checkNuxtCompatibilityIssues(constraints, nuxt)
|
||||
if (issues.length) {
|
||||
throw new Error('Nuxt compatibility issues found:\n' + issues.toString())
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
/**
|
||||
* Check version constraints and return true if passed, otherwise returns false
|
||||
*/
|
||||
export function hasNuxtCompatibility (constraints: NuxtCompatibilityConstraints, nuxt: Nuxt = useNuxt()) {
|
||||
return !checkNuxtCompatibilityIssues(constraints, nuxt).length
|
||||
}
|
12
packages/kit/src/pages.ts
Normal file
12
packages/kit/src/pages.ts
Normal file
@ -0,0 +1,12 @@
|
||||
import type { NuxtHooks } from '@nuxt/schema'
|
||||
import { useNuxt } from './context'
|
||||
import { isNuxt2 } from './compatibility'
|
||||
|
||||
export function extendPages (cb: NuxtHooks['pages:extend']) {
|
||||
const nuxt = useNuxt()
|
||||
if (isNuxt2(nuxt)) {
|
||||
nuxt.hook('build:extendRoutes', cb)
|
||||
} else {
|
||||
nuxt.hook('pages:extend', cb)
|
||||
}
|
||||
}
|
80
packages/kit/src/plugin.ts
Normal file
80
packages/kit/src/plugin.ts
Normal file
@ -0,0 +1,80 @@
|
||||
import { normalize } from 'pathe'
|
||||
import type { NuxtPlugin, NuxtPluginTemplate } from '@nuxt/schema'
|
||||
import { useNuxt } from './context'
|
||||
import { addTemplate } from './template'
|
||||
|
||||
/**
|
||||
* Normalize a nuxt plugin object
|
||||
*/
|
||||
export function normalizePlugin (plugin: NuxtPlugin | string): NuxtPlugin {
|
||||
// Normalize src
|
||||
if (typeof plugin === 'string') {
|
||||
plugin = { src: plugin }
|
||||
} else {
|
||||
plugin = { ...plugin }
|
||||
}
|
||||
|
||||
if (!plugin.src) {
|
||||
throw new Error('Invalid plugin. src option is required: ' + JSON.stringify(plugin))
|
||||
}
|
||||
|
||||
// Normalize full path to plugin
|
||||
plugin.src = normalize(plugin.src)
|
||||
|
||||
// Normalize mode
|
||||
if (plugin.ssr) {
|
||||
plugin.mode = 'server'
|
||||
}
|
||||
if (!plugin.mode) {
|
||||
const [, mode = 'all'] = plugin.src.match(/\.(server|client)(\.\w+)*$/) || []
|
||||
plugin.mode = mode as 'all' | 'client' | 'server'
|
||||
}
|
||||
|
||||
return plugin
|
||||
}
|
||||
|
||||
/**
|
||||
* Registers a nuxt plugin and to the plugins array.
|
||||
*
|
||||
* Note: You can use mode or .client and .server modifiers with fileName option
|
||||
* to use plugin only in client or server side.
|
||||
*
|
||||
* Note: By default plugin is prepended to the plugins array. You can use second argument to append (push) instead.
|
||||
*
|
||||
* @example
|
||||
* ```js
|
||||
* addPlugin({
|
||||
* src: path.resolve(__dirname, 'templates/foo.js'),
|
||||
* filename: 'foo.server.js' // [optional] only include in server bundle
|
||||
* })
|
||||
* ```
|
||||
*/
|
||||
export interface AddPluginOptions { append?: Boolean }
|
||||
export function addPlugin (_plugin: NuxtPlugin | string, opts: AddPluginOptions = {}) {
|
||||
const nuxt = useNuxt()
|
||||
|
||||
// Normalize plugin
|
||||
const plugin = normalizePlugin(_plugin)
|
||||
|
||||
// Remove any existing plugin with the same src
|
||||
nuxt.options.plugins = nuxt.options.plugins.filter(p => normalizePlugin(p).src !== plugin.src)
|
||||
|
||||
// Prepend to array by default to be before user provided plugins since is usually used by modules
|
||||
nuxt.options.plugins[opts.append ? 'push' : 'unshift'](plugin)
|
||||
|
||||
return plugin
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a template and registers as a nuxt plugin.
|
||||
*/
|
||||
export function addPluginTemplate (plugin: NuxtPluginTemplate | string, opts: AddPluginOptions = {}): NuxtPluginTemplate {
|
||||
if (typeof plugin === 'string') {
|
||||
plugin = { src: plugin }
|
||||
}
|
||||
|
||||
// Update plugin src to template destination
|
||||
plugin.src = addTemplate(plugin).dst
|
||||
|
||||
return addPlugin(plugin, opts)
|
||||
}
|
6
packages/kit/src/server.ts
Normal file
6
packages/kit/src/server.ts
Normal file
@ -0,0 +1,6 @@
|
||||
import { useNuxt } from './context'
|
||||
|
||||
/** Adds a new server middleware to the end of the server middleware array. */
|
||||
export function addServerMiddleware (middleware) {
|
||||
useNuxt().options.serverMiddleware.push(middleware)
|
||||
}
|
68
packages/kit/src/template.ts
Normal file
68
packages/kit/src/template.ts
Normal file
@ -0,0 +1,68 @@
|
||||
import { existsSync } from 'fs'
|
||||
import { basename, parse, resolve } from 'pathe'
|
||||
import hash from 'hash-sum'
|
||||
import type { NuxtTemplate } from '@nuxt/schema'
|
||||
import { useNuxt } from './context'
|
||||
|
||||
/**
|
||||
* Renders given template using lodash template during build into the project buildDir
|
||||
*/
|
||||
export function addTemplate (_template: NuxtTemplate | string) {
|
||||
const nuxt = useNuxt()
|
||||
|
||||
// Noprmalize template
|
||||
const template = normalizeTemplate(_template)
|
||||
|
||||
// Remove any existing template with the same filename
|
||||
nuxt.options.build.templates = nuxt.options.build.templates
|
||||
.filter(p => normalizeTemplate(p).filename !== template.filename)
|
||||
|
||||
// Add to templates array
|
||||
nuxt.options.build.templates.push(template)
|
||||
|
||||
return template
|
||||
}
|
||||
|
||||
/**
|
||||
* Normalize a nuxt template object
|
||||
*/
|
||||
export function normalizeTemplate (template: NuxtTemplate | string): NuxtTemplate {
|
||||
if (!template) {
|
||||
throw new Error('Invalid template: ' + JSON.stringify(template))
|
||||
}
|
||||
|
||||
// Normalize
|
||||
if (typeof template === 'string') {
|
||||
template = { src: template }
|
||||
} else {
|
||||
template = { ...template }
|
||||
}
|
||||
|
||||
// Use src if provided
|
||||
if (template.src) {
|
||||
if (!existsSync(template.src)) {
|
||||
throw new Error('Template not found: ' + template.src)
|
||||
}
|
||||
if (!template.filename) {
|
||||
const srcPath = parse(template.src)
|
||||
template.filename = template.fileName ||
|
||||
`${basename(srcPath.dir)}.${srcPath.name}.${hash(template.src)}${srcPath.ext}`
|
||||
}
|
||||
}
|
||||
|
||||
if (!template.src && !template.getContents) {
|
||||
throw new Error('Invalid template. Either getContents or src options should be provided: ' + JSON.stringify(template))
|
||||
}
|
||||
|
||||
if (!template.filename) {
|
||||
throw new Error('Invalid template. Either filename should be provided: ' + JSON.stringify(template))
|
||||
}
|
||||
|
||||
// Resolve dst
|
||||
if (!template.dst) {
|
||||
const nuxt = useNuxt()
|
||||
template.dst = resolve(nuxt.options.buildDir, template.filename)
|
||||
}
|
||||
|
||||
return template
|
||||
}
|
@ -1,5 +0,0 @@
|
||||
export interface PublicRuntimeConfig extends Record<string, any> { }
|
||||
export interface PrivateRuntimeConfig extends PublicRuntimeConfig { }
|
||||
|
||||
type _RuntimeConfig = PublicRuntimeConfig & Partial<PrivateRuntimeConfig>
|
||||
export interface RuntimeConfig extends _RuntimeConfig { }
|
@ -18,5 +18,8 @@ export default defineBuildConfig({
|
||||
'ora',
|
||||
'vue-bundle-renderer',
|
||||
'vue-server-renderer'
|
||||
],
|
||||
externals: [
|
||||
'@nuxt/schema'
|
||||
]
|
||||
})
|
||||
|
@ -72,6 +72,7 @@
|
||||
"vue-server-renderer": "^2.6.14"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@nuxt/schema": "3.0.0",
|
||||
"@types/fs-extra": "^9.0.13",
|
||||
"@types/http-proxy": "^1.17.7",
|
||||
"@types/node-fetch": "^3.0.2",
|
||||
|
@ -3,7 +3,7 @@ import { resolve } from 'pathe'
|
||||
import defu from 'defu'
|
||||
import { createHooks, Hookable, NestedHooks } from 'hookable'
|
||||
import type { Preset } from 'unenv'
|
||||
import type { NuxtHooks, NuxtOptions } from '@nuxt/kit'
|
||||
import type { NuxtHooks, NuxtOptions } from '@nuxt/schema'
|
||||
import type { PluginVisualizerOptions } from 'rollup-plugin-visualizer'
|
||||
import { tryImport, resolvePath, detectTarget, extendPreset } from './utils'
|
||||
import * as PRESETS from './presets'
|
||||
|
@ -2,7 +2,8 @@ import { resolve, join, extname } from 'pathe'
|
||||
import { joinURL } from 'ufo'
|
||||
import globby from 'globby'
|
||||
import { watch } from 'chokidar'
|
||||
import { tryResolvePath, Nuxt } from '@nuxt/kit'
|
||||
import { tryResolvePath } from '@nuxt/kit'
|
||||
import type { Nuxt } from '@nuxt/schema'
|
||||
import type { Middleware } from 'h3'
|
||||
|
||||
export interface ServerMiddleware {
|
||||
|
2
packages/nitro/types/shims.d.ts
vendored
2
packages/nitro/types/shims.d.ts
vendored
@ -11,7 +11,7 @@ declare module '#assets' {
|
||||
}
|
||||
|
||||
declare module '#config' {
|
||||
import type { PublicRuntimeConfig, PrivateRuntimeConfig } from '@nuxt/kit'
|
||||
import type { PublicRuntimeConfig, PrivateRuntimeConfig } from '@nuxt/schema'
|
||||
export const privateConfig: PrivateRuntimeConfig
|
||||
export const publicConfig: PublicRuntimeConfig
|
||||
const runtimeConfig: PrivateRuntimeConfig & PublicRuntimeConfig
|
||||
|
@ -10,6 +10,14 @@ export default defineBuildConfig({
|
||||
],
|
||||
externals: [
|
||||
'@nuxt/kit',
|
||||
'fsevents'
|
||||
'@nuxt/schema',
|
||||
'fsevents',
|
||||
// TODO: Fix rollup/unbuild issue
|
||||
'node:buffer',
|
||||
'node:path',
|
||||
'node:child_process',
|
||||
'node:process',
|
||||
'node:path',
|
||||
'node:os'
|
||||
]
|
||||
})
|
||||
|
@ -19,6 +19,7 @@
|
||||
"devDependencies": {
|
||||
"@nuxt/design": "0.1.5",
|
||||
"@nuxt/kit": "3.0.0",
|
||||
"@nuxt/schema": "3.0.0",
|
||||
"@types/clear": "^0",
|
||||
"@types/mri": "^1.1.1",
|
||||
"@types/rimraf": "^3",
|
||||
|
@ -1,7 +1,7 @@
|
||||
import { resolve, relative } from 'pathe'
|
||||
import chokidar from 'chokidar'
|
||||
import debounce from 'p-debounce'
|
||||
import type { Nuxt } from '@nuxt/kit'
|
||||
import type { Nuxt } from '@nuxt/schema'
|
||||
import consola from 'consola'
|
||||
import { createServer, createLoadingHandler } from '../utils/server'
|
||||
import { showBanner } from '../utils/banner'
|
||||
|
@ -1,6 +1,6 @@
|
||||
import { promises as fsp } from 'fs'
|
||||
import { join, relative, resolve } from 'pathe'
|
||||
import { Nuxt, TSReference } from '@nuxt/kit'
|
||||
import { Nuxt, TSReference } from '@nuxt/schema'
|
||||
import defu from 'defu'
|
||||
import type { TSConfig } from 'pkg-types'
|
||||
import { getModulePaths, getNearestPackage } from './cjs'
|
||||
|
@ -22,6 +22,7 @@
|
||||
"@nuxt/design": "^0.1.5",
|
||||
"@nuxt/kit": "3.0.0",
|
||||
"@nuxt/nitro": "3.0.0",
|
||||
"@nuxt/schema": "3.0.0",
|
||||
"@nuxt/vite-builder": "3.0.0",
|
||||
"@nuxt/webpack-builder": "3.0.0",
|
||||
"@vue/reactivity": "^3.2.22",
|
||||
|
@ -2,7 +2,7 @@
|
||||
import { getCurrentInstance, reactive } from 'vue'
|
||||
import type { App, VNode } from 'vue'
|
||||
import { createHooks, Hookable } from 'hookable'
|
||||
import type { RuntimeConfig } from '@nuxt/kit'
|
||||
import type { RuntimeConfig } from '@nuxt/schema'
|
||||
import { legacyPlugin, LegacyContext } from './compat/legacy-app'
|
||||
|
||||
type NuxtMeta = {
|
||||
|
@ -3,7 +3,7 @@ import { parse as parsePath, join } from 'pathe'
|
||||
import globby from 'globby'
|
||||
import { findExports } from 'mlly'
|
||||
import { camelCase } from 'scule'
|
||||
import { AutoImport } from '@nuxt/kit'
|
||||
import { AutoImport } from '@nuxt/schema'
|
||||
import { filterInPlace } from './utils'
|
||||
|
||||
export async function scanForComposables (dir: string, autoImports: AutoImport[]) {
|
||||
|
@ -1,4 +1,4 @@
|
||||
import type { AutoImport } from '@nuxt/kit'
|
||||
import type { AutoImport } from '@nuxt/schema'
|
||||
|
||||
export interface AutoImportContext {
|
||||
autoImports: AutoImport[]
|
||||
|
@ -1,4 +1,4 @@
|
||||
import type { AutoImportSource } from '@nuxt/kit'
|
||||
import type { AutoImportSource } from '@nuxt/schema'
|
||||
|
||||
export const Nuxt3AutoImports: AutoImportSource[] = [
|
||||
// #app
|
||||
|
@ -1,5 +1,5 @@
|
||||
import { addVitePlugin, addWebpackPlugin, defineNuxtModule, addTemplate, resolveAlias, addPluginTemplate, useNuxt } from '@nuxt/kit'
|
||||
import type { AutoImportsOptions } from '@nuxt/kit'
|
||||
import type { AutoImportsOptions } from '@nuxt/schema'
|
||||
import { isAbsolute, join, relative, resolve, normalize } from 'pathe'
|
||||
import { TransformPlugin } from './transform'
|
||||
import { Nuxt3AutoImports } from './imports'
|
||||
|
@ -1,4 +1,4 @@
|
||||
import type { AutoImport } from '@nuxt/kit'
|
||||
import type { AutoImport } from '@nuxt/schema'
|
||||
|
||||
export function toImports (autoImports: AutoImport[], isCJS = false) {
|
||||
const aliasKeyword = isCJS ? ' : ' : ' as '
|
||||
|
@ -1,6 +1,6 @@
|
||||
import { createUnplugin } from 'unplugin'
|
||||
import { parseQuery, parseURL } from 'ufo'
|
||||
import { Component } from '@nuxt/kit'
|
||||
import { Component } from '@nuxt/schema'
|
||||
|
||||
interface LoaderOptions {
|
||||
getComponents(): Component[]
|
||||
|
@ -1,7 +1,7 @@
|
||||
import { statSync } from 'fs'
|
||||
import { resolve } from 'pathe'
|
||||
import { defineNuxtModule, resolveAlias, addVitePlugin, addWebpackPlugin } from '@nuxt/kit'
|
||||
import type { Component, ComponentsDir, ComponentsOptions } from '@nuxt/kit'
|
||||
import type { Component, ComponentsDir, ComponentsOptions } from '@nuxt/schema'
|
||||
import { componentsTemplate, componentsTypeTemplate } from './templates'
|
||||
import { scanComponents } from './scan'
|
||||
import { loaderPlugin } from './loader'
|
||||
|
@ -1,7 +1,7 @@
|
||||
import { basename, extname, join, dirname, relative } from 'pathe'
|
||||
import globby from 'globby'
|
||||
import { pascalCase, splitByCase } from 'scule'
|
||||
import type { ScanDir, Component, ComponentsDir } from '@nuxt/kit'
|
||||
import type { ScanDir, Component, ComponentsDir } from '@nuxt/schema'
|
||||
|
||||
export function sortDirsByPathLength ({ path: pathA }: ScanDir, { path: pathB }: ScanDir): number {
|
||||
return pathB.split(/[\\/]/).filter(Boolean).length - pathA.split(/[\\/]/).filter(Boolean).length
|
||||
|
@ -1,6 +1,6 @@
|
||||
|
||||
import { relative } from 'pathe'
|
||||
import type { Component } from '@nuxt/kit'
|
||||
import type { Component } from '@nuxt/schema'
|
||||
|
||||
export type ComponentsTemplateOptions = {
|
||||
buildDir?: string
|
||||
|
@ -1,7 +1,8 @@
|
||||
import { promises as fsp } from 'fs'
|
||||
import { resolve } from 'pathe'
|
||||
import defu from 'defu'
|
||||
import { tryResolvePath, resolveFiles, Nuxt, NuxtApp, normalizePlugin, normalizeTemplate, compileTemplate, templateUtils } from '@nuxt/kit'
|
||||
import type { Nuxt, NuxtApp } from '@nuxt/schema'
|
||||
import { tryResolvePath, resolveFiles, normalizePlugin, normalizeTemplate, compileTemplate, templateUtils } from '@nuxt/kit'
|
||||
|
||||
import * as defaultTemplates from './templates'
|
||||
|
||||
|
@ -1,5 +1,5 @@
|
||||
import chokidar from 'chokidar'
|
||||
import { Nuxt } from '@nuxt/kit'
|
||||
import type { Nuxt } from '@nuxt/schema'
|
||||
import { createApp, generateApp } from './app'
|
||||
|
||||
export async function build (nuxt: Nuxt) {
|
||||
|
@ -1,6 +1,6 @@
|
||||
import { resolve } from 'pathe'
|
||||
import { wpfs, getNitroContext, createDevServer, resolveMiddleware, build, prepare, generate } from '@nuxt/nitro'
|
||||
import type { Nuxt } from '@nuxt/kit'
|
||||
import type { Nuxt } from '@nuxt/schema'
|
||||
|
||||
export function initNitro (nuxt: Nuxt) {
|
||||
// Create contexts
|
||||
|
@ -1,6 +1,7 @@
|
||||
import { resolve } from 'pathe'
|
||||
import { createHooks } from 'hookable'
|
||||
import { loadNuxtConfig, LoadNuxtOptions, Nuxt, NuxtOptions, NuxtConfig, nuxtCtx, installModule, ModuleContainer, NuxtHooks, addComponent } from '@nuxt/kit'
|
||||
import type { Nuxt, NuxtOptions, NuxtConfig, ModuleContainer, NuxtHooks } from '@nuxt/schema'
|
||||
import { loadNuxtConfig, LoadNuxtOptions, nuxtCtx, installModule, addComponent } from '@nuxt/kit'
|
||||
import pagesModule from '../pages/module'
|
||||
import metaModule from '../meta/module'
|
||||
import componentsModule from '../components/module'
|
||||
|
@ -1,5 +1,5 @@
|
||||
import { templateUtils } from '@nuxt/kit'
|
||||
import type { Nuxt, NuxtApp } from '@nuxt/kit'
|
||||
import type { Nuxt, NuxtApp } from '@nuxt/schema'
|
||||
|
||||
import { relative } from 'pathe'
|
||||
|
||||
|
@ -1,7 +1,7 @@
|
||||
import { isFunction } from '@vue/shared'
|
||||
import { computed } from '@vue/reactivity'
|
||||
import type { ComputedGetter } from '@vue/reactivity'
|
||||
import type { MetaObject } from './types'
|
||||
import type { MetaObject } from '../../../../schema/src/types/meta'
|
||||
import { useNuxtApp } from '#app'
|
||||
|
||||
/**
|
||||
|
@ -1,2 +1,2 @@
|
||||
export * from './composables'
|
||||
export * from './types'
|
||||
export * from '../../../../schema/src/types/meta'
|
||||
|
@ -1,6 +1,7 @@
|
||||
import { basename, extname, relative, resolve } from 'pathe'
|
||||
import { encodePath } from 'ufo'
|
||||
import { Nuxt, resolveFiles, NuxtRoute } from '@nuxt/kit'
|
||||
import type { Nuxt, NuxtRoute } from '@nuxt/schema'
|
||||
import { resolveFiles } from '@nuxt/kit'
|
||||
import { kebabCase } from 'scule'
|
||||
|
||||
enum SegmentParserState {
|
||||
|
@ -1,4 +1,4 @@
|
||||
import type { AutoImport } from '@nuxt/kit'
|
||||
import type { AutoImport } from '@nuxt/schema'
|
||||
import { expect } from 'chai'
|
||||
import * as VueFunctions from 'vue'
|
||||
import { AutoImportContext, updateAutoImportContext } from '../src/auto-imports/context'
|
||||
|
@ -1,5 +1,5 @@
|
||||
import { resolve } from 'path'
|
||||
import { ComponentsDir } from '@nuxt/kit'
|
||||
import { ComponentsDir } from '@nuxt/schema'
|
||||
import { expect } from 'chai'
|
||||
import { scanComponents } from '../src/components/scan'
|
||||
|
||||
|
1
packages/schema/.gitignore
vendored
Normal file
1
packages/schema/.gitignore
vendored
Normal file
@ -0,0 +1 @@
|
||||
/schema
|
3
packages/schema/README.md
Normal file
3
packages/schema/README.md
Normal file
@ -0,0 +1,3 @@
|
||||
# Nuxt Schema
|
||||
|
||||
> Cross-version Nuxt typedefs and defaults
|
33
packages/schema/build.config.ts
Normal file
33
packages/schema/build.config.ts
Normal file
@ -0,0 +1,33 @@
|
||||
import { defineBuildConfig } from 'unbuild'
|
||||
|
||||
export default defineBuildConfig({
|
||||
declaration: true,
|
||||
emitCJS: false,
|
||||
entries: [
|
||||
{
|
||||
input: 'src/config/index',
|
||||
outDir: 'schema',
|
||||
name: 'config',
|
||||
builder: 'untyped',
|
||||
defaults: {
|
||||
rootDir: '/project/'
|
||||
}
|
||||
},
|
||||
'src/index'
|
||||
],
|
||||
externals: [
|
||||
// Type imports
|
||||
'nuxt3',
|
||||
'vue-meta',
|
||||
'vue',
|
||||
'hookable',
|
||||
'webpack',
|
||||
'pkg-types',
|
||||
'webpack-bundle-analyzer',
|
||||
'rollup-plugin-visualizer',
|
||||
'vite',
|
||||
// Implicit
|
||||
'@vue/compiler-core',
|
||||
'@vue/shared ',
|
||||
]
|
||||
})
|
33
packages/schema/package.json
Normal file
33
packages/schema/package.json
Normal file
@ -0,0 +1,33 @@
|
||||
{
|
||||
"name": "@nuxt/schema",
|
||||
"version": "3.0.0",
|
||||
"repository": "nuxt/framework",
|
||||
"license": "MIT",
|
||||
"type": "module",
|
||||
"main": "./dist/index.mjs",
|
||||
"types": "./dist/index.d.ts",
|
||||
"files": [
|
||||
"dist",
|
||||
"schema"
|
||||
],
|
||||
"scripts": {
|
||||
"prepack": "unbuild"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/lodash.template": "^4",
|
||||
"@types/semver": "^7",
|
||||
"unbuild": "latest"
|
||||
},
|
||||
"dependencies": {
|
||||
"create-require": "^1.1.1",
|
||||
"defu": "^5.0.0",
|
||||
"jiti": "^1.12.9",
|
||||
"pathe": "^0.2.0",
|
||||
"scule": "^0.2.1",
|
||||
"std-env": "^3.0.1",
|
||||
"ufo": "^0.7.9"
|
||||
},
|
||||
"engines": {
|
||||
"node": "^14.16.0 || ^16.11.0 || ^17.0.0"
|
||||
}
|
||||
}
|
@ -684,7 +684,7 @@ export default {
|
||||
* }
|
||||
* }
|
||||
* ```
|
||||
* @type {typeof import('../src/types/runtime-config').PrivateRuntimeConfig}
|
||||
* @type {typeof import('../src/types/config').PrivateRuntimeConfig}
|
||||
* @version 2
|
||||
* @version 3
|
||||
*/
|
||||
@ -709,7 +709,7 @@ export default {
|
||||
* }
|
||||
* }
|
||||
* ```
|
||||
* @type {typeof import('../src/types/runtime-config').PublicRuntimeConfig}
|
||||
* @type {typeof import('../src/types/config').PublicRuntimeConfig}
|
||||
* @version 2
|
||||
* @version 3
|
||||
*/
|
13
packages/schema/src/index.ts
Normal file
13
packages/schema/src/index.ts
Normal file
@ -0,0 +1,13 @@
|
||||
|
||||
// Types
|
||||
import './types/global'
|
||||
export * from './types/config'
|
||||
export * from './types/hooks'
|
||||
export * from './types/module'
|
||||
export * from './types/nuxt'
|
||||
export * from './types/components'
|
||||
export * from './types/imports'
|
||||
export * from './types/pages'
|
||||
|
||||
// Schema
|
||||
export { default as NuxtConfigSchema } from './config/index'
|
@ -5,3 +5,10 @@ export interface NuxtOptions extends ConfigSchema { }
|
||||
type DeepPartial<T> = T extends Record<string, any> ? { [P in keyof T]?: DeepPartial<T[P]> | T[P] } : T
|
||||
|
||||
export interface NuxtConfig extends DeepPartial<ConfigSchema> { }
|
||||
|
||||
|
||||
export interface PublicRuntimeConfig extends Record<string, any> { }
|
||||
export interface PrivateRuntimeConfig extends PublicRuntimeConfig { }
|
||||
|
||||
type _RuntimeConfig = PublicRuntimeConfig & Partial<PrivateRuntimeConfig>
|
||||
export interface RuntimeConfig extends _RuntimeConfig { }
|
@ -1,9 +1,9 @@
|
||||
import type { IncomingMessage, ServerResponse } from 'http'
|
||||
import type { Compiler, Configuration, Stats } from 'webpack'
|
||||
import type { TSConfig } from 'pkg-types'
|
||||
import type { ModuleContainer } from '../module/container'
|
||||
import type { NuxtTemplate, Nuxt, NuxtApp } from '../types/nuxt'
|
||||
import type { AutoImport, AutoImportSource } from '../types/imports'
|
||||
import type { ModuleContainer } from './module'
|
||||
import type { NuxtTemplate, Nuxt, NuxtApp } from './nuxt'
|
||||
import type { AutoImport, AutoImportSource } from './imports'
|
||||
import type { NuxtConfig, NuxtOptions } from './config'
|
||||
import type { Component, ComponentsDir, ScanDir, ComponentsOptions } from './components'
|
||||
|
@ -1,6 +1,6 @@
|
||||
import type { ModuleContainer } from '../module/container'
|
||||
import { Nuxt } from './nuxt'
|
||||
import { NuxtHooks } from './hooks'
|
||||
import type { Nuxt, NuxtTemplate } from "./nuxt";
|
||||
|
||||
|
||||
export interface NuxtCompatibilityConstraints {
|
||||
/**
|
||||
@ -71,3 +71,41 @@ export type ModuleInstallOptions =
|
||||
ModuleSrc |
|
||||
[ModuleSrc, ModuleOptions?] |
|
||||
Partial<ModuleInstallOptionsObj>
|
||||
|
||||
/**
|
||||
* Legacy ModuleContainer for backwards compatibility with Nuxt 2 module format.
|
||||
*/
|
||||
export interface ModuleContainer {
|
||||
nuxt: Nuxt
|
||||
options: Nuxt['options']
|
||||
|
||||
/** @deprecated */
|
||||
ready(): Promise<any>
|
||||
|
||||
/** @deprecated */
|
||||
addVendor(): void
|
||||
|
||||
/** Renders given template using lodash template during build into the project buildDir (`.nuxt`).*/
|
||||
addTemplate(template: string | NuxtTemplate): NuxtTemplate
|
||||
|
||||
/** Register a custom layout. If its name is 'error' it will override the default error layout. */
|
||||
addLayout(tmpl: NuxtTemplate, name: string): any
|
||||
|
||||
/** Set the layout that will render Nuxt errors. It should already have been added via addLayout or addTemplate. */
|
||||
addErrorLayout(dst: string): void
|
||||
|
||||
/** Adds a new server middleware to the end of the server middleware array. */
|
||||
addServerMiddleware(arg1: any): void
|
||||
|
||||
/** Allows extending webpack build config by chaining `options.build.extend` function. */
|
||||
extendBuild(fn): void
|
||||
|
||||
/** Allows extending routes by chaining `options.build.extendRoutes` function. */
|
||||
extendRoutes(fn): void
|
||||
|
||||
/** Registers a module */
|
||||
requireModule(nuxt: Nuxt, opts: any): Promise<void>
|
||||
|
||||
/** Registers a module */
|
||||
addModule(nuxt: Nuxt, opts: any): Promise<void>
|
||||
}
|
2
packages/schema/src/types/pages.ts
Normal file
2
packages/schema/src/types/pages.ts
Normal file
@ -0,0 +1,2 @@
|
||||
// TODO: Lost!
|
||||
export interface NuxtRoute { }
|
@ -7,7 +7,9 @@ export default defineBuildConfig({
|
||||
'src/index'
|
||||
],
|
||||
dependencies: [
|
||||
'@nuxt/kit',
|
||||
'vue'
|
||||
],
|
||||
externals: [
|
||||
'@nuxt/schema'
|
||||
]
|
||||
})
|
||||
|
@ -13,6 +13,7 @@
|
||||
"prepack": "unbuild"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@nuxt/schema": "3.0.0",
|
||||
"unbuild": "latest",
|
||||
"vue": "3.2.22"
|
||||
},
|
||||
|
@ -1,6 +1,7 @@
|
||||
import createResolver from 'postcss-import-resolver'
|
||||
import defu from 'defu'
|
||||
import { Nuxt, requireModule } from '@nuxt/kit'
|
||||
import { requireModule } from '@nuxt/kit'
|
||||
import type { Nuxt } from '@nuxt/schema'
|
||||
import { ViteOptions } from './vite'
|
||||
import { distDir } from './dirs'
|
||||
|
||||
|
@ -1,7 +1,7 @@
|
||||
import * as vite from 'vite'
|
||||
import { resolve } from 'pathe'
|
||||
import consola from 'consola'
|
||||
import type { Nuxt } from '@nuxt/kit'
|
||||
import type { Nuxt } from '@nuxt/schema'
|
||||
import type { InlineConfig, SSROptions } from 'vite'
|
||||
import type { Options } from '@vitejs/plugin-vue'
|
||||
import { sanitizeFilePath } from 'mlly'
|
||||
|
@ -21,5 +21,8 @@ export default defineBuildConfig({
|
||||
'vue-style-loader',
|
||||
'@babel/core',
|
||||
'vue'
|
||||
],
|
||||
externals: [
|
||||
'@nuxt/schema'
|
||||
]
|
||||
})
|
||||
|
@ -56,6 +56,7 @@
|
||||
"webpackbar": "^5.0.2"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@nuxt/schema": "3.0.0",
|
||||
"@types/pify": "^5.0.1",
|
||||
"@types/terser-webpack-plugin": "^5.0.4",
|
||||
"@types/webpack-bundle-analyzer": "^4.4.1",
|
||||
|
@ -1,7 +1,7 @@
|
||||
import consola from 'consola'
|
||||
import { cloneDeep } from 'lodash-es'
|
||||
import type { Configuration } from 'webpack'
|
||||
import type { Nuxt } from '@nuxt/kit'
|
||||
import type { Nuxt } from '@nuxt/schema'
|
||||
|
||||
export interface WebpackConfigContext extends ReturnType<typeof createWebpackConfigContext>{ }
|
||||
|
||||
|
@ -4,7 +4,8 @@ import consola from 'consola'
|
||||
import { createCommonJS } from 'mlly'
|
||||
import { defaults, merge, cloneDeep } from 'lodash-es'
|
||||
import createResolver from 'postcss-import-resolver'
|
||||
import { Nuxt, requireModule } from '@nuxt/kit'
|
||||
import { requireModule } from '@nuxt/kit'
|
||||
import type { Nuxt } from '@nuxt/schema'
|
||||
|
||||
const isPureObject = obj => obj !== null && !Array.isArray(obj) && typeof obj === 'object'
|
||||
|
||||
|
@ -12,7 +12,7 @@ import type { Compiler, Watching } from 'webpack'
|
||||
import type { Context as WebpackDevMiddlewareContext, Options as WebpackDevMiddlewareOptions } from 'webpack-dev-middleware'
|
||||
import type { MiddlewareOptions as WebpackHotMiddlewareOptions } from 'webpack-hot-middleware'
|
||||
|
||||
import type { Nuxt } from '@nuxt/kit'
|
||||
import type { Nuxt } from '@nuxt/schema'
|
||||
import { createMFS } from './utils/mfs'
|
||||
import { client, server } from './configs'
|
||||
import { createWebpackConfigContext, applyPresets, getWebpackConfig } from './utils/config'
|
||||
|
28
yarn.lock
28
yarn.lock
@ -2425,6 +2425,7 @@ __metadata:
|
||||
"@nuxt/kit": 3.0.0
|
||||
"@nuxt/nitro": 3.0.0
|
||||
"@nuxt/postcss8": ^1.1.3
|
||||
"@nuxt/schema": 3.0.0
|
||||
"@nuxt/types": ^2.15.8
|
||||
"@types/fs-extra": ^9.0.13
|
||||
"@types/hash-sum": ^1.0.0
|
||||
@ -2743,15 +2744,14 @@ __metadata:
|
||||
version: 0.0.0-use.local
|
||||
resolution: "@nuxt/kit@workspace:packages/kit"
|
||||
dependencies:
|
||||
"@nuxt/schema": ^3.0.0
|
||||
"@types/lodash.template": ^4
|
||||
"@types/semver": ^7
|
||||
consola: ^2.15.3
|
||||
create-require: ^1.1.1
|
||||
defu: ^5.0.0
|
||||
dotenv: ^10.0.0
|
||||
globby: ^11.0.4
|
||||
hash-sum: ^2.0.0
|
||||
hookable: ^5.0.0
|
||||
jiti: ^1.12.9
|
||||
lodash.template: ^4.5.0
|
||||
mlly: ^0.3.13
|
||||
@ -2760,8 +2760,6 @@ __metadata:
|
||||
rc9: ^1.2.0
|
||||
scule: ^0.2.1
|
||||
semver: ^7.3.5
|
||||
std-env: ^3.0.1
|
||||
ufo: ^0.7.9
|
||||
unbuild: latest
|
||||
unctx: ^1.0.2
|
||||
untyped: ^0.3.0
|
||||
@ -2790,6 +2788,7 @@ __metadata:
|
||||
"@nuxt/design": 0.1.5
|
||||
"@nuxt/devalue": ^2.0.0
|
||||
"@nuxt/kit": 3.0.0
|
||||
"@nuxt/schema": 3.0.0
|
||||
"@rollup/plugin-alias": ^3.1.8
|
||||
"@rollup/plugin-commonjs": ^21.0.1
|
||||
"@rollup/plugin-inject": ^4.0.3
|
||||
@ -2880,6 +2879,23 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@nuxt/schema@3.0.0, @nuxt/schema@^3.0.0, @nuxt/schema@workspace:packages/schema":
|
||||
version: 0.0.0-use.local
|
||||
resolution: "@nuxt/schema@workspace:packages/schema"
|
||||
dependencies:
|
||||
"@types/lodash.template": ^4
|
||||
"@types/semver": ^7
|
||||
create-require: ^1.1.1
|
||||
defu: ^5.0.0
|
||||
jiti: ^1.12.9
|
||||
pathe: ^0.2.0
|
||||
scule: ^0.2.1
|
||||
std-env: ^3.0.1
|
||||
ufo: ^0.7.9
|
||||
unbuild: latest
|
||||
languageName: unknown
|
||||
linkType: soft
|
||||
|
||||
"@nuxt/server-edge@npm:2.16.0-27282256.ab1c6cb4":
|
||||
version: 2.16.0-27282256.ab1c6cb4
|
||||
resolution: "@nuxt/server-edge@npm:2.16.0-27282256.ab1c6cb4"
|
||||
@ -3030,6 +3046,7 @@ __metadata:
|
||||
resolution: "@nuxt/vite-builder@workspace:packages/vite"
|
||||
dependencies:
|
||||
"@nuxt/kit": 3.0.0
|
||||
"@nuxt/schema": 3.0.0
|
||||
"@vitejs/plugin-vue": ^1.9.4
|
||||
"@vitejs/plugin-vue-jsx": ^1.2.0
|
||||
autoprefixer: ^10.4.0
|
||||
@ -3137,6 +3154,7 @@ __metadata:
|
||||
"@babel/core": ^7.16.0
|
||||
"@nuxt/friendly-errors-webpack-plugin": ^2.5.2
|
||||
"@nuxt/kit": 3.0.0
|
||||
"@nuxt/schema": 3.0.0
|
||||
"@types/pify": ^5.0.1
|
||||
"@types/terser-webpack-plugin": ^5.0.4
|
||||
"@types/webpack-bundle-analyzer": ^4.4.1
|
||||
@ -15142,6 +15160,7 @@ __metadata:
|
||||
dependencies:
|
||||
"@nuxt/design": 0.1.5
|
||||
"@nuxt/kit": 3.0.0
|
||||
"@nuxt/schema": 3.0.0
|
||||
"@types/clear": ^0
|
||||
"@types/mri": ^1.1.1
|
||||
"@types/rimraf": ^3
|
||||
@ -15247,6 +15266,7 @@ __metadata:
|
||||
"@nuxt/design": ^0.1.5
|
||||
"@nuxt/kit": 3.0.0
|
||||
"@nuxt/nitro": 3.0.0
|
||||
"@nuxt/schema": 3.0.0
|
||||
"@nuxt/vite-builder": 3.0.0
|
||||
"@nuxt/webpack-builder": 3.0.0
|
||||
"@types/hash-sum": ^1.0.0
|
||||
|
Loading…
Reference in New Issue
Block a user