2021-10-02 16:01:17 +00:00
|
|
|
import { createRequire } from 'module'
|
2021-11-24 15:42:38 +00:00
|
|
|
import { relative, dirname, join, resolve } from 'pathe'
|
2020-11-10 18:19:24 +00:00
|
|
|
import fse from 'fs-extra'
|
2020-11-01 23:17:44 +00:00
|
|
|
import jiti from 'jiti'
|
2020-11-06 09:51:35 +00:00
|
|
|
import defu from 'defu'
|
2021-08-27 12:51:40 +00:00
|
|
|
import { mergeHooks } from 'hookable'
|
2020-11-10 18:19:24 +00:00
|
|
|
import consola from 'consola'
|
2020-11-20 00:16:31 +00:00
|
|
|
import chalk from 'chalk'
|
2021-10-12 18:51:24 +00:00
|
|
|
import dotProp from 'dot-prop'
|
2021-01-22 19:55:59 +00:00
|
|
|
import type { NitroPreset, NitroInput } from '../context'
|
2020-11-01 23:17:44 +00:00
|
|
|
|
2020-11-06 09:51:35 +00:00
|
|
|
export function hl (str: string) {
|
2020-11-20 00:16:31 +00:00
|
|
|
return chalk.cyan(str)
|
2020-11-06 09:51:35 +00:00
|
|
|
}
|
2020-11-01 23:17:44 +00:00
|
|
|
|
2020-11-05 12:26:00 +00:00
|
|
|
export function prettyPath (p: string, highlight = true) {
|
2020-11-06 09:51:35 +00:00
|
|
|
p = relative(process.cwd(), p)
|
2020-11-01 23:17:44 +00:00
|
|
|
return highlight ? hl(p) : p
|
|
|
|
}
|
|
|
|
|
2020-11-06 09:51:35 +00:00
|
|
|
export function compileTemplate (contents: string) {
|
2020-11-20 00:16:31 +00:00
|
|
|
return (params: Record<string, any>) => contents.replace(/{{ ?([\w.]+) ?}}/g, (_, match) => {
|
2021-10-12 18:51:24 +00:00
|
|
|
const val = dotProp.get(params, match)
|
2020-11-20 00:16:31 +00:00
|
|
|
if (!val) {
|
|
|
|
consola.warn(`cannot resolve template param '${match}' in ${contents.substr(0, 20)}`)
|
|
|
|
}
|
|
|
|
return val as string || `${match}`
|
|
|
|
})
|
2020-11-03 22:14:32 +00:00
|
|
|
}
|
|
|
|
|
2020-11-06 09:51:35 +00:00
|
|
|
export function serializeTemplate (contents: string) {
|
2020-11-03 22:14:32 +00:00
|
|
|
// eslint-disable-next-line no-template-curly-in-string
|
2020-11-14 13:05:09 +00:00
|
|
|
return `(params) => \`${contents.replace(/{{ (\w+) }}/g, '${params.$1}')}\``
|
2020-11-05 21:56:40 +00:00
|
|
|
}
|
|
|
|
|
2020-11-06 09:51:35 +00:00
|
|
|
export function jitiImport (dir: string, path: string) {
|
2021-10-02 16:01:17 +00:00
|
|
|
return jiti(dir, { interopDefault: true })(path)
|
2020-11-06 09:51:35 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
export function tryImport (dir: string, path: string) {
|
|
|
|
try {
|
|
|
|
return jitiImport(dir, path)
|
|
|
|
} catch (_err) { }
|
|
|
|
}
|
2020-11-04 13:15:38 +00:00
|
|
|
|
2021-04-04 21:06:56 +00:00
|
|
|
export async function writeFile (file: string, contents: string, log = false) {
|
2020-11-10 18:19:24 +00:00
|
|
|
await fse.mkdirp(dirname(file))
|
|
|
|
await fse.writeFile(file, contents, 'utf-8')
|
2021-01-20 14:37:21 +00:00
|
|
|
if (log) {
|
|
|
|
consola.info('Generated', prettyPath(file))
|
|
|
|
}
|
2020-11-10 18:19:24 +00:00
|
|
|
}
|
|
|
|
|
2021-12-21 11:46:42 +00:00
|
|
|
export function evalTemplate (ctx, input: string | ((ctx) => string)): string {
|
|
|
|
if (typeof input === 'function') {
|
|
|
|
input = input(ctx)
|
2020-11-06 09:51:35 +00:00
|
|
|
}
|
2021-12-21 11:46:42 +00:00
|
|
|
if (typeof input !== 'string') {
|
|
|
|
throw new TypeError('Invalid template: ' + input)
|
2020-11-06 13:46:17 +00:00
|
|
|
}
|
2021-12-21 11:46:42 +00:00
|
|
|
return compileTemplate(input)(ctx)
|
|
|
|
}
|
2020-11-06 13:46:17 +00:00
|
|
|
|
2021-12-21 11:46:42 +00:00
|
|
|
export function resolvePath (nitroContext: NitroInput, input: string | ((nitroContext: NitroInput) => string), resolveBase: string = ''): string {
|
|
|
|
return resolve(resolveBase, evalTemplate(nitroContext, input))
|
|
|
|
}
|
2020-11-06 09:51:35 +00:00
|
|
|
|
2021-12-21 11:46:42 +00:00
|
|
|
export function replaceAll (input: string, from: string, to: string) {
|
|
|
|
return input.replace(new RegExp(from, 'g'), to)
|
2020-11-05 21:23:24 +00:00
|
|
|
}
|
|
|
|
|
2020-11-06 09:12:57 +00:00
|
|
|
export function detectTarget () {
|
2021-07-28 16:42:59 +00:00
|
|
|
if (process.env.NETLIFY || process.env.NETLIFY_LOCAL) {
|
2020-11-06 09:12:57 +00:00
|
|
|
return 'netlify'
|
|
|
|
}
|
|
|
|
|
2020-11-06 14:05:11 +00:00
|
|
|
if (process.env.NOW_BUILDER) {
|
2020-11-06 09:12:57 +00:00
|
|
|
return 'vercel'
|
|
|
|
}
|
2021-02-01 09:24:49 +00:00
|
|
|
|
|
|
|
if (process.env.INPUT_AZURE_STATIC_WEB_APPS_API_TOKEN) {
|
|
|
|
return 'azure'
|
|
|
|
}
|
2020-11-06 09:12:57 +00:00
|
|
|
}
|
|
|
|
|
2020-12-07 12:48:29 +00:00
|
|
|
export async function isDirectory (path: string) {
|
|
|
|
try {
|
|
|
|
return (await fse.stat(path)).isDirectory()
|
|
|
|
} catch (_err) {
|
|
|
|
return false
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-01-22 19:55:59 +00:00
|
|
|
export function extendPreset (base: NitroPreset, preset: NitroPreset): NitroPreset {
|
|
|
|
return (config: NitroInput) => {
|
2020-11-20 00:16:31 +00:00
|
|
|
if (typeof preset === 'function') {
|
|
|
|
preset = preset(config)
|
2020-11-06 12:55:30 +00:00
|
|
|
}
|
|
|
|
if (typeof base === 'function') {
|
2020-11-06 13:46:17 +00:00
|
|
|
base = base(config)
|
2020-11-06 12:55:30 +00:00
|
|
|
}
|
|
|
|
return defu({
|
2021-08-27 12:51:40 +00:00
|
|
|
hooks: mergeHooks(base.hooks, preset.hooks)
|
2020-11-20 00:16:31 +00:00
|
|
|
}, preset, base)
|
2020-11-06 12:55:30 +00:00
|
|
|
}
|
2020-11-06 09:51:35 +00:00
|
|
|
}
|
2020-11-14 13:05:09 +00:00
|
|
|
|
|
|
|
const _getDependenciesMode = {
|
|
|
|
dev: ['devDependencies'],
|
|
|
|
prod: ['dependencies'],
|
|
|
|
all: ['devDependencies', 'dependencies']
|
|
|
|
}
|
2021-10-02 16:01:17 +00:00
|
|
|
const _require = createRequire(import.meta.url)
|
2020-11-14 13:05:09 +00:00
|
|
|
export function getDependencies (dir: string, mode: keyof typeof _getDependenciesMode = 'all') {
|
|
|
|
const fields = _getDependenciesMode[mode]
|
2021-10-02 16:01:17 +00:00
|
|
|
const pkg = _require(resolve(dir, 'package.json'))
|
2020-11-14 13:05:09 +00:00
|
|
|
const dependencies = []
|
|
|
|
for (const field of fields) {
|
|
|
|
if (pkg[field]) {
|
|
|
|
for (const name in pkg[field]) {
|
|
|
|
dependencies.push(name)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return dependencies
|
|
|
|
}
|
2021-09-21 15:05:36 +00:00
|
|
|
|
|
|
|
// TODO: Refactor to scule (https://github.com/unjs/scule/issues/6)
|
|
|
|
export function serializeImportName (id: string) {
|
|
|
|
return '_' + id.replace(/[^a-zA-Z0-9_$]/g, '_')
|
|
|
|
}
|
2021-10-12 17:39:55 +00:00
|
|
|
|
|
|
|
export function readPackageJson (
|
|
|
|
packageName: string,
|
|
|
|
_require: NodeRequire = createRequire(import.meta.url)
|
|
|
|
) {
|
|
|
|
try {
|
|
|
|
return _require(`${packageName}/package.json`)
|
|
|
|
} catch (error) {
|
|
|
|
if (error.code === 'ERR_PACKAGE_PATH_NOT_EXPORTED') {
|
2021-10-18 07:53:50 +00:00
|
|
|
const pkgModulePaths = /^(.*\/node_modules\/).*$/.exec(_require.resolve(packageName))
|
|
|
|
for (const pkgModulePath of pkgModulePaths) {
|
|
|
|
const path = resolve(pkgModulePath, packageName, 'package.json')
|
|
|
|
if (fse.existsSync(path)) {
|
|
|
|
return fse.readJSONSync(path)
|
|
|
|
}
|
|
|
|
continue
|
|
|
|
}
|
|
|
|
|
|
|
|
throw error
|
2021-10-12 17:39:55 +00:00
|
|
|
}
|
|
|
|
throw error
|
|
|
|
}
|
|
|
|
}
|
2021-11-24 15:42:38 +00:00
|
|
|
|
|
|
|
export function readDirRecursively (dir: string) {
|
|
|
|
return fse.readdirSync(dir).reduce((files, file) => {
|
|
|
|
const name = join(dir, file)
|
|
|
|
const isDirectory = fse.statSync(name).isDirectory()
|
|
|
|
return isDirectory ? [...files, ...readDirRecursively(name)] : [...files, name]
|
|
|
|
}, [])
|
|
|
|
}
|